Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
f7129d2
Add initial 1.0.0 datatypes
MV-GH May 3, 2025
9406c77
Add Initial new uni types changes
MV-GH May 25, 2025
7ad6160
Make all impl specific typealias internal
MV-GH May 25, 2025
2e5c63b
Fix some TODOs
MV-GH May 25, 2025
b760249
Fix dynamic types with Kotlinx.serialization polymorphic
MV-GH May 25, 2025
b4ce05a
Fix GetModLogs transformation
MV-GH May 25, 2025
2b38d80
Wip comment changes v2
MV-GH Jun 30, 2025
5f0f1b4
WIP: Sync uni types with 1.0.0 types
MV-GH Sep 15, 2025
8ca9726
Some more fields
MV-GH Sep 15, 2025
8f9b8a9
Fix LocalUserVoteDisplayMode
MV-GH Sep 15, 2025
f49a6bd
Remove SiteAggregates
MV-GH Sep 16, 2025
f9d68fa
Fix taglines
MV-GH Sep 16, 2025
c9bffe1
Fix Search mappings
MV-GH Sep 17, 2025
15835f0
Fix ListReports
MV-GH Sep 23, 2025
ae6ce2c
Count fixes
MV-GH Sep 23, 2025
53758cf
Remove ModlogListParams
MV-GH Sep 23, 2025
ce0abe2
Fix inbox endpoints
MV-GH Sep 29, 2025
549e2f4
Remove wrong deps
MV-GH Sep 30, 2025
9009c3d
Fix nullable API fields and backup mapping
MV-GH Sep 30, 2025
122cc3a
Fix LinkMetadata.kt
MV-GH Oct 1, 2025
9a65e44
Fix Comment.kt
MV-GH Oct 1, 2025
718be00
Fix PersonView.kt LocalUserView.kt
MV-GH Oct 2, 2025
6ab41df
Fix site, post and comment view mappings
MV-GH Oct 6, 2025
c25274e
Fix ModLog renaming
MV-GH Oct 7, 2025
dca12d2
Fix remaining mapping todos
MV-GH Oct 7, 2025
c09d3cb
Fix listCustomEmojis
MV-GH Oct 9, 2025
fc9278f
Fix myUserInfo
MV-GH Oct 9, 2025
b51698c
Fix CommentResponse.kt
MV-GH Oct 10, 2025
519a8cf
Apply MarkManyPostsAsRead changes
MV-GH Feb 22, 2026
609cbaf
Wip progress 1.0.0 types mapping
MV-GH Mar 3, 2026
ca1815a
Refactor enums infra
MV-GH Mar 3, 2026
eed8a5d
Remove obsolete Lemmy 1.0 mapping remnants
MV-GH Mar 3, 2026
22057d6
Finish enum migration and clean up imports
MV-GH Mar 7, 2026
fc1e94e
Fix listPostLikes and listCommentLikes
MV-GH Mar 8, 2026
1f0c450
Small tweaks
MV-GH Mar 8, 2026
3d845ed
SearchCombinedView changes
MV-GH Mar 8, 2026
1adf64f
Remove ResolveObjectResponse
MV-GH Mar 8, 2026
fb12af0
Fix NotificationData
MV-GH Mar 8, 2026
1ff9382
Remove remnants
MV-GH Mar 8, 2026
32ad910
Fix ReportCombinedView
MV-GH Mar 8, 2026
c3fb48f
Fix PostOrCommentOrPrivateMessage interface
MV-GH Mar 8, 2026
eabe62d
Fix community and combined view models
MV-GH Mar 9, 2026
2437641
Add ListPersonContent
MV-GH Mar 9, 2026
4ee0487
Fix GetPersonDetails endpoint
MV-GH Mar 9, 2026
0e8bf76
Add init version of LemmyApiController LemmyApiRouter
MV-GH May 23, 2026
a463a2e
Tweak Lemmy 1.0 endpoints
MV-GH May 23, 2026
7c93959
Pictrs changes
MV-GH May 23, 2026
ec6e9ea
Implement Lemmy 1.0 image and unsupported endpoints
MV-GH May 23, 2026
035f933
Fix ListLogins
MV-GH May 23, 2026
3001fca
Fix hidePost
MV-GH May 23, 2026
05823dc
Fix transferCommunity
MV-GH May 23, 2026
399dc05
Remove todo
MV-GH May 23, 2026
65a692c
Apply linter + Mapper
MV-GH May 24, 2026
3a85a7a
Add uniWrapper for V1
MV-GH May 24, 2026
9b2f445
Bump deps
MV-GH May 24, 2026
26a058d
Update Android tooling and generated enum naming
MV-GH May 24, 2026
7e36f3f
Update Lemmy 1.0 API types
MV-GH May 24, 2026
b50e8e9
Update the genTypes script
MV-GH May 24, 2026
09af822
Add ListPersons endpoint and update generated types
MV-GH May 24, 2026
523095f
Update site types
MV-GH May 24, 2026
ae75728
Update GenTypes.kt
MV-GH May 24, 2026
638009b
Update Search and SearchResponse types
MV-GH May 24, 2026
aac429a
Fix lint
MV-GH May 24, 2026
f6236a5
Replace legacy image update APIs with removal endpoints
MV-GH May 24, 2026
c882aa5
Rename apiV18 to api
MV-GH May 24, 2026
ac8e388
Remove InstanceWithFederationState remnants
MV-GH May 24, 2026
fbc8acb
Fix couple types
MV-GH May 24, 2026
7aac5c3
Update Site types
MV-GH May 24, 2026
7750d04
Update todos
MV-GH May 24, 2026
060a2ce
Update some descriptions
MV-GH May 24, 2026
d7ae395
Documentation changes
MV-GH May 24, 2026
e036a72
Bump Kotlin tooling and publish plugin
MV-GH May 24, 2026
0fd741b
Fix Gradle deployment resource handling
MV-GH May 24, 2026
8e06e91
Tweak Gradle download timeout and memory settings
MV-GH May 24, 2026
bc141b2
Try fix duplicate deployment
MV-GH May 25, 2026
f3adb3d
Bump semver
MV-GH May 25, 2026
1ed328f
Fix Maven deployment workflow
MV-GH May 25, 2026
63de6f0
Fix default_comment_sort_type
MV-GH Jun 21, 2026
ee03c9a
Update image APIs for Lemmy 1.0 beta.1
MV-GH Jul 8, 2026
4378779
Add new Invitation endpoints
MV-GH Jul 8, 2026
2488af4
Ignore DeleteUserForm
MV-GH Jul 10, 2026
9a16d72
Remove unused LikeType enum
MV-GH Jul 11, 2026
dc5f4bb
Apply Lemmy 1.0 vote changes
MV-GH Jul 11, 2026
fcf766f
Refactor LemmyApi into LemmyApiFactory for cleaner API creation and c…
MV-GH Jul 17, 2026
21adf27
Refactor NodeInfo API into a dedicated `NodeInfoClient` for improved …
MV-GH Jul 17, 2026
ea0b726
Refactor clients and controllers to support proper resource cleanup a…
MV-GH Jul 17, 2026
64b2539
Refactor authentication, routing and cancellation handling
MV-GH Jul 17, 2026
3629813
Refactor authentication and client handling with `LemmyRequestClient`…
MV-GH Jul 17, 2026
de81e31
Consolidate unified routes and remove obsolete API base code
MV-GH Jul 17, 2026
d3b7da1
Improve incremental tasks executions (much faster)
MV-GH Jul 17, 2026
3514cb1
Bump publishing and Kotlin lint plugins
MV-GH Jul 17, 2026
d8e6e17
Add FeatureFlags coverage
MV-GH Jul 18, 2026
dade479
Make DEFAULT_TIMEOUT_MS internal
MV-GH Jul 18, 2026
23dd08d
Rename LemmyApiFactory to LemmyApiClient
MV-GH Jul 18, 2026
fb393a3
Test timeout cancellation propagation
MV-GH Jul 19, 2026
9704e31
Tweak build & bump gradle
MV-GH Aug 15, 2026
6c0bbe5
Add LemmyAuth.fromToken factory method
MV-GH Aug 15, 2026
621d470
Swap parameter order for connectForVersion
MV-GH Aug 16, 2026
597724e
Expose nodeInfoClient
MV-GH Aug 16, 2026
ab80042
Fix flaky CancellationPropagationTest
MV-GH Aug 16, 2026
56962bc
Improve NodeInfo client support
MV-GH Aug 16, 2026
a2399fe
Align types to 1.0.0-beta.2
MV-GH Oct 17, 2026
3b92819
Bump version to 0.7.0-beta.0
MV-GH Oct 17, 2026
50e2b91
Bump gradle to 9.8.1
MV-GH Oct 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 0 additions & 2 deletions .github/gradle.properties

This file was deleted.

26 changes: 10 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,15 @@ jobs:
os: [ macos-latest, ubuntu-latest, windows-latest ]

steps:
- uses: actions/checkout@v4
- uses: SimonMarquis/ci-gradle-properties-action@v1
with:
path: .github/gradle.properties
- uses: actions/setup-java@v4
- uses: actions/checkout@v6
- uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
uses: gradle/actions/setup-gradle@v5
- name: Cache Konan dependencies
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ~/.konan
key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle.kts') }}
Expand All @@ -40,10 +37,10 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
- uses: actions/setup-java@v4
uses: gradle/actions/setup-gradle@v5
- uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '17'
Expand All @@ -52,13 +49,10 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: SimonMarquis/ci-gradle-properties-action@v1
with:
path: .github/gradle.properties
- uses: actions/checkout@v6
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
- uses: actions/setup-java@v4
uses: gradle/actions/setup-gradle@v5
- uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '17'
Expand Down
22 changes: 11 additions & 11 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ name: Deployment
on:
push:
tags: [ '[0-9]+.[0-9]+.[0-9]+*' ]
workflow_dispatch:

jobs:
publish:
if: github.repository == 'mv-gh/lemmybackwardscompatibleapi' && startsWith(github.ref, 'refs/tags')
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ macos-latest, ubuntu-latest, windows-latest ]
if: >
github.repository == 'mv-gh/lemmybackwardscompatibleapi' &&
(
startsWith(github.ref, 'refs/tags/') ||
(github.event_name == 'workflow_dispatch' && github.actor == 'mv-gh')
)
runs-on: macos-latest
environment: publish
env:
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKey }}
Expand All @@ -19,13 +22,10 @@ jobs:
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.ORG_GRADLE_PROJECT_mavenCentralPassword }}
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKeyId }}
steps:
- uses: actions/checkout@v4
- uses: SimonMarquis/ci-gradle-properties-action@v1
with:
path: .github/gradle.properties
- uses: actions/checkout@v6
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
- uses: actions/setup-java@v4
uses: gradle/actions/setup-gradle@v5
- uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '17'
Expand Down
32 changes: 31 additions & 1 deletion ACTIVE_CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,37 @@
This document lists the changes that you will need to actively handle, through feature flags.


## V1

### Sort types split + `time_range_seconds`

The many `Top*` `SortType` variants (`TopDay`, `TopWeek`, `TopMonth`, `TopYear`, `TopAll`, `TopHour`, `TopSixHour`, `TopTwelveHour`, `TopThreeMonths`, `TopSixMonths`, `TopNineMonths`) have been collapsed into a single `Top` value in v1. Time range is now expressed via `time_range_seconds: Long?` on the query (`GetPosts`, `GetComments`, `ListCommunities`, `ListMultiCommunities`, `Search`).

- On v1, set `sort = SortType.Top` and pass `time_range_seconds` (e.g. `86400` for top day).
- On pre-v1, the old `Top*` variants are still used; `time_range_seconds` is ignored. The wrapper translates automatically.

### Image upload / delete compatibility

- Consumers should use `LemmyApiBaseController.uploadImage()` and `LemmyApiBaseController.deleteMedia()`.
- Pre-1.0 Lemmy instances are now wired internally to legacy pictrs endpoints; callers should not use pictrs APIs directly anymore.
- `UploadImageResponse` now includes `delete_filename`.
- Always pass `uploadImage(...).delete_filename` into `deleteMedia(DeleteImageParams(...))`.
- On Lemmy `1.x`, `delete_filename == filename`.
- On pre-`1.0`, `delete_filename` contains the full legacy pictrs delete path, like `/pictrs/image/delete/{delete_token}/{file}`.

### Avatar/Icon/Banner

Should now use the dedicated avatar/icon/banner upload/delete endpoints.

### Pagination: `page` replaced by `page_cursor`

`page: Long?` has been removed from all list/query types in v1 (`GetPosts`, `GetComments`, `GetModlog`, `Search`, `ListCommunities`, `ListReports`, `ListNotifications`, `ListMedia`, `ListPersonContent`, `ListPostLikes`, `ListCommentLikes`, `ListRegistrationApplications`).

- On v1, use `page_cursor` for cursor-based pagination.
- To support pre-v1 instances, populate **both** `page` (for older versions, handled internally) and `page_cursor` (for v1). The wrapper will pass the appropriate one.



## 0.19.11

- Added `last_donation_notification` field to LocalUser
Expand All @@ -29,4 +60,3 @@ But each has different behaviour. The old behaviour is to hide all voting types
- Log out support (invalidates the current JWT)
- Instance block support
- 2FA rework, one must now provide a valid 2FA code to enable 2FA. Added routes to support this.

65 changes: 65 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Contributing to this project


## Architecture

```
LemmyApiClient (options, optional caller-owned HttpClient)
└─ connect / connectForVersion (typed instance, auth, version) → LemmyApiBaseController
│
└─ version-specific LemmyApiUniWrapper (implements LemmyApiBaseController)
├─ LemmyApiController (raw Ktor HTTP calls, version-specific datatypes)
├─ Transformer (maps version-specific ↔ unified datatypes)
└─ MapperGenerator (interface) (declares all toUni/fromUni signatures)
```

### Per-version module structure

Each `vX/xN/xM/` folder contains exactly these files:

| File | Purpose |
|---|---|
| `datatypes/` | Auto-generated version-specific Kotlin datatypes. **Do not edit by hand.** |
| `MapperGenerator.kt` | Interface declaring all `toUni` / `fromUni` signatures, used to drive Konvert code generation. Annotations are commented out in committed code; uncomment + build to regenerate. |
| `Transformer.kt` | Implements `MapperGenerator`. Contains all field-level mapping logic. Generated initially by Konvert, then hand-maintained for non-trivial differences. |
| `LemmyApiUniWrapper.kt` | Implements `LemmyApiBaseController`. Delegates HTTP calls to `LemmyApiController` and transforms results. Unsupported endpoints call `notSupported()`. |
| `LemmyApiController.kt` | Raw Ktor HTTP calls returning version-specific datatypes. |
| `LemmyApiRouter.kt` | Route path definitions for this version. |

### Unified datatypes (1.0.0 baseline)

The `it.vercruysse.lemmyapi.datatypes` package represents the **1.0.0 Lemmy API** and is the single source of truth for all API consumers. Older version wrappers transform their version-specific types into these unified types. See `ACTIVE_CHANGES.md` for the key API differences consumers need to handle.


## Backwards Compatibility Strategy

- **API route added**: add a function to `FeatureFlags` that returns whether this feature is supported. Older versions implement this route by throwing `notSupported()`.
- **API route removed**: newer versions implement the old route by throwing `notSupported()`. Add to the `oldRoutes` interface if needed.
- **Request/response changes**: transform using `Transformer`. The unified type (usually the latest datatype shape) is returned regardless of version. Example: [moving admin flag from person to local_user](https://github.com/LemmyNet/lemmy/pull/3403) — pre-0.19 APIs map their type to the latest shape.
- **Enum entries**: each entry tracks `minimumVersion`/`maximumVersion`. Use `getSupportedEntries<Type>()` to retrieve the valid entries for the connected instance (e.g. sort options).


## Compatibility Rules

When adding or updating an older-version implementation:

1. **Reference `v0.x19.x11`** — it is kept up-to-date with the unified interface. Copy its `LemmyApiUniWrapper.kt` pattern.
2. `MapperGenerator.kt` return types must use **unified** types only.
3. `Transformer.kt` must not import deleted unified types.
4. `LemmyApiUniWrapper.kt` must implement **every** abstract method from `LemmyApiBaseController`. Missing features use `notSupported()`.
5. Import aliases are required in `Transformer.kt`:
- Unified types: `import it.vercruysse.lemmyapi.datatypes.Foo as LemmyapiDatatypesFoo`
- Local version types: `import it.vercruysse.lemmyapi.vX.xN.xM.datatypes.Foo as XMDatatypesFoo`
- Unused aliases cause compilation errors — remove them when the corresponding method is deleted.


## AutoGenerated Code

To minimize the maintenance burden, many aspects have been automated via Kotlin scripts in the `GeneratorScripts` submodule:

- **`GenTypes`**: Downloads TS types from [lemmy-js-client](https://github.com/LemmyNet/lemmy-js-client) and generates `datatypes/` for a target version. Requires [dukat](https://github.com/Kotlin/dukat).
- **`GenRoutes`**: Generates route/controller templates from [lemmy_openapi_spec](https://github.com/MV-GH/lemmy_openapi_spec). Output goes to `temp/`.
- **`GenMapperRoutes`**: Generates `MapperGenerator.kt` by diffing two version datatypes. Uncomment the Konvert annotations and build to generate `Transformer.kt` base, then copy from the build output. Output goes to `temp/`.

See `STEPS_TO_SUPPORT_MORE_VERSION.md` for the full checklist when adding a new Lemmy version.

18 changes: 9 additions & 9 deletions GeneratorScripts/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
kotlin("jvm")
kotlin("plugin.serialization") version "2.1.10"
id("com.google.devtools.ksp").version("2.1.10-1.0.30")
kotlin("plugin.serialization") version "2.3.21"
id("com.google.devtools.ksp").version("2.3.8")
}

repositories {
Expand All @@ -11,19 +11,18 @@ repositories {
dependencies {
testImplementation("org.jetbrains.kotlin:kotlin-test")
implementation("com.charleskorn.kaml:kaml:0.55.0")
val ktorVersion = "3.1.2"
val konvertVersion = "3.2.1"
val ktorVersion = "3.5.0"
val konvertVersion = "4.5.0"
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
implementation("io.ktor:ktor-client-logging:$ktorVersion")

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.11.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.11.0")

implementation("com.squareup.okio:okio:3.10.2")
implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.6.0")
implementation("io.mcarle:konvert:$konvertVersion")
implementation("com.squareup.okio:okio:3.17.0")
implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.9.0")
implementation("io.mcarle:konvert-api:$konvertVersion")
implementation(project(":app"))

Expand All @@ -37,3 +36,4 @@ tasks.test {
kotlin {
jvmToolchain(17)
}

Loading
Loading