Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-generate OpenAPI documentation from code. #2937

Closed
ShadowJonathan opened this issue Jun 6, 2023 · 34 comments
Closed

Auto-generate OpenAPI documentation from code. #2937

ShadowJonathan opened this issue Jun 6, 2023 · 34 comments
Labels
area: docs Documentation fixes enhancement New feature or request
Milestone

Comments

@ShadowJonathan
Copy link
Contributor

ShadowJonathan commented Jun 6, 2023

Is your proposal related to a problem?

Currently I'm trying to get an overview of the actual REST API of Lemmy, since the WebSocket API was purportedly recently deprecated.

However, the "API" section of the Docs only lists to this URL, https://join-lemmy.org/api, which then links back to a JS library of Lemmy itself.

However, it is unclear if this library even is up-to-date, with this issue showing vague wording.

Looking at the "The current api {version} is here." line, that line refers to a .ts file, which imports all its types from a rust wrapper, which is not really readable.

The page itself talks about using the rust crate that exposes some of the query parameter types and names, but does not provide string constants for the actual URL Endpoints.

Describe the solution you'd like

A document that enumerates all and any API Endpoints that Lemmy exposes, with their request and response formats, and error codes.

I can see this in two ways, one is that the API Docs page will contain all of these endpoints, written in markdown.

Though another one is to write all of the API documentation in OpenAPI, which would be a single or compiled .json/.yaml that's easily able to generate entire libraries/bindings for. It is also machine-readable, and easy to update.

@ShadowJonathan ShadowJonathan added the enhancement New feature or request label Jun 6, 2023
@dessalines
Copy link
Member

dessalines commented Jun 6, 2023

We used to maintain OpenAPI docs (or something similar, I forget it was years ago), but it was a massive amount of work. Others even helped, but then abandoned. Now, we have over 250 type structs, so doing it by hand isn't an option.

Now, we auto-generate all our API docs using ts-rs, into that lemmy-js-client library. Its very much an up-to-date, full description of every struct and API endpoint.

You could also check out that repo by tag, to get older / newer versions.

Though another one is to write all of the API documentation in OpenAPI, which would be a single or compiled .json/.yaml that's easily able to generate entire libraries/bindings for. It is also machine-readable, and easy to update.

We've investigated libraries to do that in rust, but none of them were as good as ts-rs, which is what we're doing now. You could investigate other methods, but I greatly doubt they'd be anywhere as good as ts-rs.

@dessalines dessalines closed this as not planned Won't fix, can't repro, duplicate, stale Jun 6, 2023
@ShadowJonathan
Copy link
Contributor Author

Im not asking for a TS API, I'm asking for a HTTP REST API reference, so that people can write Lemmy clients in other languages, and check their code to the specification.

@dessalines
Copy link
Member

That is a REST API. Every endpoint and type is fully described there.

@ShadowJonathan
Copy link
Contributor Author

In typescript, not in the raw HTTP requests and responses, which is what a HTTP REST API reference is supposed to be.

@dessalines
Copy link
Member

dessalines commented Jun 6, 2023

https://join-lemmy.org/api/classes/LemmyHttp.html#createPostReport

This shows the entire object you need, the endpoint, and the full response, everything well typed. What piece of information is it missing?

Realize also that you are taking away my dev time answering these support questions. You should be using https://lemmy.ml/c/lemmy_support , which you clicked past when creating this issue.

@ShadowJonathan
Copy link
Contributor Author

I wasn't asking for support, I was asking for a developer feature.

And I do not trust that TS documentation to tell me everything there is to the HTTP request or response, I have seen POST requests done with an empty request body and everything inside parameters, and this documentation could easily hide that (as the idiomatic request body is simply given to a translation layer function), and also does not tell me about the HTTP error codes.

This documentation would not help me to write or check a different API client from scratch, to the correctness that every web API is held to nowadays, is what I'm getting at.

@lunaisnotaboy
Copy link

You do realize that you could generate OpenAPI docs, right...? Granted, it would take some work, but it's not infeasible.

@benaryorg
Copy link

benaryorg commented Jun 6, 2023

The original request was in regards to documentation of the HTTP REST API, i.e. the API built on top of HTTP.

The linked API docs are a JavaScript/TypeScript API documentation for an object, i.e. LemmyHttp.
This object under the hood constructs an API call.
This is also pretty obvious in the description of the object documentation which states:

Helps build lemmy HTTP requests.

Either way the provided documentation itself contains merely the application layer input and output data usually encapsulated in "form" request/responses.

Now while this would be enough to build a naïve API client it does not provide any information on HTTP status codes for instance, as was mentioned earlier.
What does an HTTP code 404 mean in response to a changePassword POST-request?
What response codes are used during normal operation?

Digging deeper into the changePassword one, which returns a Promise<LoginResponse>, there are no obvious clues as to what happens if the given password was wrong.
Since the failed request is handled on the Promise level the documentation for LemmyHttp does not need to provide this information.
However for an implementation that is not using LemmyHttp rather than talking directly to the HTTP API this is not sufficient for an implementation as such an implementation would have a very broad failure condition without any further insight into what actually happened.
The difference between an ephemeral server-side error (database offline, out of memory during request processing, etc.) and an actual password mismatch would be hidden, and don't we all love those great applications that give you a little toast or popup saying "An error occured" without any indication as to what error occurred?

In short, an HTTP API documentation should answer questions such as:

  • do I have to report this error to the user or can I retry? (i.e. how to determine if an error is fatal)
  • what should my error message to the user describe? (e.g. "character limit exceeded" or "server temporarily unavailable", aka. "does the user need to change input or try again later")
  • how can I distinguish between the login having expired and the user lacking the permissions to perform an action? (i.e. error handling and distinction)

The 2-3 devs who have built APIs using this library differ with you.

Coming back to the latest response provided here; the devs differ, however it is unclear from your response as to what the differ (or disagree).
Is the response to be taken as a "Lemmy will not provide HTTP API documentation" or is it a disagreement on whether or not the provided documentation constitutes an HTTP API documentation (as this post should've explained; it does not).

What exactly is the disagreement here?


you will be blocked for taking up valuable dev resources answering this.

This also seems slightly unreasonable since the same could be said on both sides of this issue; writing a client which cannot for whatever reason use LemmyHttp (the simplest explanation being that a client may not be written in JavaScript, TypeScript, or a language/application shipping with an appropriate interpreter).
The stance on behalf of Lemmy, i.e. one of not providing an HTTP API documentation takes up valuable development resources for anyone wanting to implement a third-party client.
The handling of this issue makes it look like Lemmy discourages the use of third-party applications to interact with the API, which has a rather odd vibe considering that many people move to fediverse solutions to escape the very same issues with other platforms (Twitter and Reddit being the most prominent and blatant examples of this).


To bring up another question, which may shed more light onto the HTTP API; where could one find automated tests for the API, if such exist?
Considering that OpenAPI intends to document not just ideal conditions but also failures and other issues, OpenAPI is (AFAIK) often also integrated with automated testing.
If a different construct for automated tests exists for Lemmy, that construct would likely also contain information on expected HTTP codes or similar.
Maybe such a form of documentation (in the form of codified tests) could provide a middle-ground between actually documenting the API and not providing documentation for the HTTP level API.
Do such tests exist, and if so, where can they be found?

@dessalines
Copy link
Member

dessalines commented Jun 6, 2023

Errors could be documented better, I agree.

I welcome anyone to maintain openAPI docs if they'd like to. That was tried once before, and the people who did that couldn't keep up with our pace, but if anyone's willing to do that work, feel free.

I don't have time though.

@dessalines
Copy link
Member

dessalines commented Jun 6, 2023

Do such tests exist, and if so, where can they be found?

They do, in the api_tests folder. Unfortunately it uses our official lemmy-js-client that people here are taking issue with.

@dessalines
Copy link
Member

dessalines commented Jun 6, 2023

Those downvotes are very disheartening, yall are putting a huge amount of work on the only 2 devs that maintain this project. We are not a multi-million-dollar corporation with tons of resources to throw at problems like reddit, and we're not going to be able to perfectly solve every problem. Especially something like this that requires a staggering amount of manual work.

I highly recommend reading about how stressful it can be to maintain even small open source projects.

When I get short-tempered, it is because ppl are asking me to do labor for them that they are unwilling to do themselves. At no point did shadowjonathan offer to help.

@ShadowJonathan
Copy link
Contributor Author

ShadowJonathan commented Jun 6, 2023

Lemmy is/was about to become the focal point of a Mastodon for Reddit, with Reddit essentially removing 3rd party API access support, killing off every other app while disregarding their efforts entirely.

I put up this issue to make it a long-term goal for this project, and to kite developers who are inevitably going to find a similar issue, to leave a like a subscribe on this issue, and/or get up to speed with the history of the issue, and get to working.

Instead, you closed the issue without regard for this, pointing to "it is already enough", seemingly misunderstanding my request, and putting down an unreasonable ultimatum when I continued asking for this feature.

I did not ask for any time frame, nor do I expect it to be completed in one.

If anything, hearing about the woes of openapi in the past would've made me want to address it even more, probably by having the rust types generate chunks of OpenAPI response/request data that then just has to be coupled with a request path manually, and adjusted with any path change, which then just would have become part of the flow.

However, with what this issue turned into, that did not happen, and now I'm just simply going to painstakingly copy from the rust types directly, because a typescript library's type/function annotations provides less guarantees than any scrap of HTTP documentation or direct source code ever could.

@dessalines
Copy link
Member

dessalines commented Jun 6, 2023

I will re-open this if anyone wants to work on this issue.

Please understand that our dev time is very limited. We have about 2 years worth of constant work ahead of us.

I'll also add that every app developer so far, has been able to use either these docs we provide, the types from lemmy-js-client (which are automatically generated from the rust ones), or the rust types themselves, to build clients.

I myself auto-generated the kotlin types for jerboa, using these typescript types. Considering the large numbers of types (~250 iirc), Auto-generation should be the main way new clients are developed anyway.

The API is certainly not a closed one, and I'm happy to help any potential app or client developers to use these types.

@buresdv
Copy link

buresdv commented Jun 6, 2023

I think that this was a very poor way of handling this issue. @ShadowJonathan is helping me develop a more robust interface for communicating with Lemmy.

The incomplete documentation of the API has been a long-standing problem for me as well, with users reporting crashes out of the ass because the API often returns unexpected errors that the very type-strict nature of Swift can't handle, and I can't implement error checking for them because:
a) I don't know Rust or JavaScript, so I can't go through the code to see what it's supposed to be doing
b) I can't afford to spend my dev time going over the code even if I understood Rust/JavaScript. I understand that you are under a lot of pressure, but so am I. By not enlisting additional assistance, you're effectively shifting dev time from yourself onto me. I have been tirelessly working on Mlem for the last month, every day, to get it into a usable state for the Reddit blackout, and WAY too much of my time is spent solving undocumented errors that the API gives me (if it even gives me an error instead of just an empty status code 400). I didn't want to mention it because I understood your situation, but now it's become a serious problem with the closure of this issue.

I urge you to reconsider this issue. I believe that @ShadowJonathan could be a valuable asset in the improvements of the API documentation, and if the community reactions to these comments are anything to go by, there is demand for this.

@dessalines
Copy link
Member

Very well. Since @ShadowJonathan has agreed to work on this, I'll reopen and assign them.

@BrooklynMan
Copy link

I’m going to add my voice as a co-developer and designer on Mlem: while I also hope the community reaction to this issue improves, might I also suggest that a post to lemmy calling for some community contributions to updating the documentation be made? It’s clear that you’re overloaded and need more assistance, so why not ask for it in a more open forum?

@lunaisnotaboy
Copy link

@dessalines If you do want to cooperate with @ShadowJonathan, maybe unmarking all of their comments as abuse would be a good start?

@dessalines
Copy link
Member

Sure.

I’m going to add my voice as a co-developer and designer on Mlem: while I also hope the community reaction to this issue improves, might I also suggest that a post to lemmy calling for some community contributions to updating the documentation be made? It’s clear that you’re overloaded and need more assistance, so why not ask for it in a more open forum?

This comment, where I did just that, asking anyone for help, received 11 downvotes, and no offers of help.

@BrooklynMan
Copy link

BrooklynMan commented Jun 6, 2023

I’d also like to point out that that comment has been heavily edited— when i downvoted it, it had no mention of re-opening, for example.

@BrooklynMan
Copy link

This is a very small forum when few people will see this discussion. I will recommend again casting a wider net with a lemmy post requesting help. It would benefit everyone here, and I’m sure that you’d be more familiar with what, exactly, the focus of the assistance you need would be that anyone else.

@eslerm
Copy link

eslerm commented Jun 6, 2023

kindly, https://mikemcquaid.com/entitlement-in-open-source/

@ShadowJonathan
Copy link
Contributor Author

ShadowJonathan commented Jun 7, 2023

In trying to turn this issue towards some more productive things, I was looking for rust openAPI generators, I found this, which is able to add macros of endpoint descriptions to their performing functions.

However, this doesn't seem to mesh well with async_trait, or the error that i'm getting is related to another type problem, but i'll leave it here for today, to show that i do intend to work on this.

However, I need to say that I simply am not able to maintain it indefinitely; I will propose a solution to the devs that'll allow them to maintain good API documentation (by having those lines of documentation inside of their source, so that when editing the endpoints, they could add/edit the corresponding API surface specification), but I'm unable (even if I wanted to) to manually maintain that documentation for them forever more.

Learn a man how to fish, and all that.

(But I'll also document the entire existing codebase when I do find a good approach, to get it started)

@ShadowJonathan
Copy link
Contributor Author

Poking around utoipa a bit more, I realise that the pattern of "utilising a trait to implement route logic" is clashing with an easy implementation of utoipa here, as the macro expands to add extra structures that hold additional information, which cannot be placed inside of traits.

As such, this means that the endpoint functions would probably have to be converted to bare freestanding functions. (The (type) invariants that're encoded into the Perform traits shouldn't be overlooked.)

However, this would allow the endpoint paths to be defined onto the bare function, close to the endpoint definition itself, instead of all in api_routes_https.rs.

These are things up for consideration, and they would be able to hook into maintenance that's planned to happen soon.

@Nutomic
Copy link
Member

Nutomic commented Jun 7, 2023

At the moment we are completely busy to improve the performance of Lemmy, answer questions and review contributions. So we dont have any capacity to make API changes at the same time. If you make small pull requests to fix specific problems we will review and merge them, but otherwise the API is what it is. We will also not be able to work on the API docs anytime soon. For now you are welcome to make improvements to the existing API docs (they are somewhere in joinlemmy-site repo but not sure where). You can also write an OpenAPI spec or alternative API docs by hand and we will happily link it in the readme and docs.

In the future we are definitely planning to improve the API, using utoipa crate to generate an OpenAPI spec sounds like a good idea. However this will require rewriting much of the Lemmy API code, and also rewriting how lemmy-js-client code is generated. We can start thinking about this in a few weeks at the earliest, when all the chaos calms down a bit. Contributions in this area are also not helpful at the moment, because we will publish a new stable version very soon (mainly with the switch from websocket to http).

@ShadowJonathan
Copy link
Contributor Author

However this will require rewriting much of the Lemmy API code, and also rewriting how lemmy-js-client code is generated.

(Clarification from dev chat: js-client is then generated from the OpenAPI docs, instead of importing ts-rs-generated definitions)

This'd be a bit of churn, yeah.

@joelmenezes
Copy link

(Clarification from dev chat: js-client is then generated from the OpenAPI docs, instead of importing ts-rs-generated definitions)

Where are these OpenAPI docs hosted?

@Nutomic
Copy link
Member

Nutomic commented Jun 27, 2023

@ShadowJonathan Have you already started working on this?

@ShadowJonathan
Copy link
Contributor Author

ShadowJonathan commented Jun 27, 2023

Not yet, beyond my initial experiments with utoipa, I haven't had enough time to dedicate to this next to University and work on Mlem.

It is still on my todo list however, and I will come back to this soon, most likely during summer vacation.

@Nutomic
Copy link
Member

Nutomic commented Jun 30, 2023

I tried to use utoipa to generate the docs, but unfortunately there are many problems which make this unfeasible. Mainly it requires that a lot of information be duplicated in two or even more places, which is not an option as we have a huge number of API endpoints.

You can see details in this upstream issue. Maybe some of you could contribute there.

@lionirdeadman lionirdeadman added the area: docs Documentation fixes label Jul 18, 2023
@dessalines
Copy link
Member

Closing as these should be added to the lemmy-docs repo, and there are a few unofficial ones there outside of the official lemmy-js-client docs currently: https://join-lemmy.org/docs/contributors/04-api.html

@dessalines dessalines closed this as not planned Won't fix, can't repro, duplicate, stale Oct 18, 2023
@dessalines dessalines reopened this Jan 16, 2025
@dessalines dessalines changed the title API documentation Auto-generate OpenAPI documentation from code. Jan 16, 2025
@dessalines
Copy link
Member

dessalines commented Jan 16, 2025

Re-opening this as @SleeplessOne1917 , @Nutomic and I found a few more libraries, and many of the older ones might be mature enough now, to auto-generate an OpenAPI spec from our actix code directly. The libraries are linked in the above issue.

@Nutomic Nutomic added this to the 0.20.0 milestone Jan 17, 2025
dessalines added a commit that referenced this issue Jan 22, 2025
@dessalines
Copy link
Member

dessalines commented Jan 22, 2025

I've tried and failed to do this using oasgen, because almost all these need to override / create a wrapper on top of your webserver (actix or axum), and so introduce limitations since they can only support a very limited subset of features, and we are using a lot of custom actix. Of all the ones linked above, it might be possible with utoipa, but also extremely verbose, since it doesn't seem to be able to work with our endpoints.

I'm having better luck doing this with our generated typescript typings on lemmy-js-client, using the following library, so I'll probably go with this:

https://github.com/lukeautry/tsoa

It requires some minimal workarounds, but it seems to be working well. I'll post my results when I finish the rest of the endpoints.

@dessalines
Copy link
Member

Okay this is ready to go: LemmyNet/lemmy-js-client#458 .

@Nutomic
Copy link
Member

Nutomic commented Feb 4, 2025

Working now, see links on https://join-lemmy.org/docs/contributors/04-api.html

@Nutomic Nutomic closed this as completed Feb 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: docs Documentation fixes enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

10 participants