Giter VIP home page Giter VIP logo

lemmybackwardscompatibleapi's Introduction

Sonatype Nexus (Snapshots) badge badge badge badge badge badge badge badge badge example workflow License: AGPL v3 GitHub stars

LemmyBackwardsCompatibleAPI

A backwards compatible API for Lemmy made with Kotlin Multiplatform. Supports Lemmy 0.18+

Usage

val api =  LemmyApi.getLemmyApi("voyager.lemmy.ml", auth)

api.getSite()

// Some features are version dependent, so we can check if they are supported
if(api.FF.instanceBlock()) {
    api.instanceBlock()
}

// These enums can be different depending on the version of the API
api.getSupportedEntries<SortType>()

Installation

implementation("it.vercruysse.lemmyapi:lemmy-api:VERSION")

It is currently in beta, so only snapshots are available.

Add the following repository

maven { url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots") }

Goals

The intention is to provide an easy-to-use API that supports a wide range of Lemmy instances. The backwards compatibility is achieved by transforming the requests and responses to a "universal" type. And by allowing you to check if a feature is supported by the instance. That way you can change the behavior of your app depending on the instance's version.

It is a non-goal to provide a stable API. The API can change with every iteration without warning nor deprecation.

Backwards Compatibility Strategy

The API is backwards compatible by using the following strategy:

  • API route gets added. Add a function that returns if this feature is supported. Older versions implement this route by throwing an error (nonSupported).
  • API route gets removed. newer versions implement this route by throwing an error (nonSupported). Is added to the oldRoutes interface
  • API routes its request/response changes. For this, we transform response/requests to a "universal" type. Concrete this means, it will usually be the modified latest datatypes. So that the response will be the same regardless of which version. Here are some examples from how this will look concrete:
  • Enum entries keep an added/removed version. Using get getSupportedEntries<Type> we can retrieve the supported entries for a given enum. This is useful, for example, for sorting, where the sorting options can change between versions.

AutoGenerated Code

To minimize the maintenance burden, many aspects have been automated.

This is done through kotlinscripts which are located in the GeneratorScripts submodule

There is 3 main scripts:

  • GenTypes: This script updates the datatypes for the set package version (ex: v0x19). It does this by downloading the TS types from lemmy-js-client. And applying the transformations (see here) to the types. This script does require that you have downloaded dukat
  • GenRoutes: This script generates templates for the routes, LemmyApiService and its implementation. It will output it to temp/ and you can copy what you need. It does this by extracting the routes from lemmy_openapi_spec
  • GenMapperRoutes: This script is a bit more complex. To prevent having to manually write all the basic transformations between datatypes of different versions. We can automatically generate them with Konvert. This is done by having a definition file, in this case it is just a Interface MapperGenerator. Uncomment the annotations and build the project. The mappings will be generated in the build folder. Then you can copy them to the appropriate Transformer class. Now to prevent having to manually write the definition file, we can generate it with GenMapperRoutes. This will output them to the temp/ folder. And these are generated by comparing the datatypes from the given source package version and the given target package version. Datatypes, which exist in both, will have a mapping generated.

Extra features

  • JVM datatypes implement Serializable
  • Android datatypes implement Parcelable and Serializable

lemmybackwardscompatibleapi's People

Contributors

mv-gh avatar

Stargazers

 avatar mittwerk avatar Diego Beraldin avatar Dessalines avatar

Watchers

Dessalines avatar  avatar

Forkers

dessalines

lemmybackwardscompatibleapi's Issues

Expose httpClient configuration

Not sure yet how to best achieve this, but i want the consumer be able to fully modify httpClient but it should still have the current config defaults

Look into using Rust Codebase to generate the DTOs

Possible avenues:

  • Something crude that goes over the AST and generates KT DTOs
  • Find a tool to convert rust DTOs to OpenAPI, then another tool to convert OpenAPI to KT DTOs
  • Make ts_rs equivalent for KT

Find a tool to convert rust DTOs to OpenAPI is also needed for lemmy_openapi_spec

Add Java serializable support for JVM

With K2 this is possible again.

Common

expect interface JavaSerializable

data class Post(val name: String) : JavaSerializable

JVM

actual interface JavaSerializable: java.io.Serializable

fun main() {
    val post = Post("Hello")
    println(post)
    println(post is java.io.Serializable) // True
}

How to properly auto-generate routes?

I'd like to add the ListPostLikes and ListCommentLikes routes in order to add the Admin View Votes functionality to jerboa, but I'm not seeing any instructions for how to do that in the README, or any scripts, like we used to with jerboa copy_generated_types.sh.

Should I do a PR to add them manually for now?

Use `Result` do not throw exceptions

From experience, even as the author I have missed handling some explicit exceptions that were thrown. Instead I will now opt use Result so that these exceptions must be explicitly handled.

Discuss: versioning

Currently I don't follow semver but I do use its notation. because with each Lemmy API change, I would have to increase my major.

Maybe I should go with a Lemmy Semver prefix notation. like 0.19.5-1.0.0. The prefix will denote the newest supported Lemmy version. And the version will denote changes to the API other than Lemmy API routes and datapoints

Structural changes

Originally I had planned to do only concrete implementations of the API every minor version, and update the existing implementation with every patch. But with release of Lemmy 0.19.4 I realize this approach is no longer feasible. Too easy to make non backwards compatible changes, DTOs are mess no longer easily visible which fields exists in which minor patch.

So instead every patch will needs it own implementation that will be an exact match for that version. Meaning it will no longer hold properties that don't exist in the current patch but in previous patch that must still be kept for compatibility.

Each patch will need its own mapper to the "universal" types. Each patch will only have the endpoints that it supports. So each patch will need to implement a wrapper for its universal endpoint.

The only drawback is that this will be significantly more work. Especially since I haven't made the universal types / API yet.

Newer versions should still fallback to an older implementation if a implementation for that version doesn't exist yet.

Add EndToEnd tests for all endpoints

EndToEndTest success is defined as simply having a 2XX returned for a endpoint. We test serialization.

The only way we can reliably do this is by having a local docker instance running of a LemmyServer using TestContainers. The db should be preseeded with some data.

Then add a test for each endpoint

These tests should only be required to executed before the publishing. On demand otherwise.

Have demo app?

Hi.

Thank you for this project work!

I want create an app for both ios and android platform.

Has a demo application?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.