memos/docs/documenting-the-api.md
boojack 35f2d399e2
chore: update api v1 docs (#2117)
* chore: update apiv1 docs

* chore: update
2023-08-09 22:30:27 +08:00

5.2 KiB

Documenting the API

Principles

  • The documentation is generated by swaggo/swag from comments in the API code.

  • Documentation is written using Declarative Comments Format.

  • The documentation is generated in the ./api folder as docs.go.

  • echo-swagger is used to integrate with Echo framework and serve the documentation with Swagger-UI at http://memos.host:5230/api/index.html

Updating the documentation

  1. Update or add API-related comments in the code. Make sure to follow the Declarative Comments Format:

    // signIn godoc
    //
    //  @Summary    Sign-in to memos.
    //  @Tags       auth
    //  @Accept     json
    //  @Produce    json
    //  @Param      body    body        SignIn      true    "Sign-in object"
    //  @Success    200     {object}    store.User  "User information"
    //  @Failure    400     {object}    nil         "Malformatted signin request"
    //  @Failure    401     {object}    nil         "Password login is deactivated | Incorrect login credentials, please try again"
    //  @Failure    403     {object}    nil         "User has been archived with username {username}"
    //  @Failure    500     {object}    nil         "Failed to find system setting | Failed to unmarshal system setting | Incorrect login credentials, please try again | Failed to generate tokens | Failed to create activity"
    //  @Router     /api/v1/auth/signin [POST]
    func (s *APIV1Service) signIn(c echo.Context) error {
    ...
    

    Sample from api/v1/auth.go You can check existing comments at api/v1

  2. Run one of the following provided scripts:

    • Linux: ./scripts/gen-api-v1-docs.sh (remember to chmod +x the script first)
    • Windows: ./scripts/gen-api-v1-docs.ps1

    The scripts will install swag if needed (via go install), then run swag fmt and swag init commands.

  3. That's it! The documentation is updated. You can check it at http://memos.host:5230/api/index.html

Extra tips

  • If you reference a custom Go struct from outside the API file, use a relative definition, like store.IdentityProvider. This works because ./ is passed to swag at --dir argument. If swag can't resolve the reference, it will fail.

  • If the API grows or you need to reference some type from another location, remember to update ./scripts/gen-api-v1-docs.cfg file with the new paths.

  • It's possible to list multiple errors for the same code using enum-like structs, that will show a proper, spec-conformant model with all entries at Swagger-UI. The drawback is that this approach requires a major refactoring and will add a lot of boilerplate code, as there are inconsistencies between API methods error responses.

    type signInInternalServerError string
    
    const signInErrorFailedToFindSystemSetting signInInternalServerError = "Failed to find system setting"
    const signInErrorFailedToUnmarshalSystemSetting signInInternalServerError = "Failed to unmarshal system setting"
    const signInErrorIncorrectLoginCredentials signInInternalServerError = "Incorrect login credentials, please try again"
    const signInErrorFailedToGenerateTokens signInInternalServerError = "Failed to generate tokens"
    const signInErrorFailedToCreateActivity signInInternalServerError = "Failed to create activity"
    
    type signInUnauthorized string
    
    const signInErrorPasswordLoginDeactivated signInUnauthorized = "Password login is deactivated"
    const signInErrorIncorrectCredentials signInUnauthorized = "Incorrect login credentials, please try again"
    
    // signIn godoc
    //
    //  @Summary    Sign-in to memos.
    //  @Tags       auth
    //  @Accept     json
    //  @Produce    json
    //  @Param      body    body        SignIn      true    "Sign-in object"
    //  @Success    200     {object}    store.User  "User information"
    //  @Failure    400     {object}    nil         "Malformatted signin request"
    //  @Failure    401     {object}    signInUnauthorized
    //  @Failure    403     {object}    nil "User has been archived with username {username}"
    //  @Failure    500     {object}    signInInternalServerError
    //  @Router     /api/v1/auth/signin [POST]
    func (s *APIV1Service) signIn(c echo.Context) error {
        ...
    

Step-by-step (no scripts)

Required tools

# Swag v1.8.12 or newer
# Also updates swag if needed
$ go install github.com/swaggo/swag/cmd/swag@latest

If $HOME/go/bin is not in your PATH, you can call swag directly at $HOME/go/bin/swag.

Generate the documentation

  1. Run swag fmt to format the comments

    swag fmt --dir ./api/v1 && go fmt
    
  2. Run swag init to generate the documentation

    cd <project-root>
    swag init --output api --generalInfo ./server/server.go --dir ./,./api/v1
    

If the API gets a new version, you'll need to add the file system path to swag's --dir parameter.