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

Update OpenAPI doc #288

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/python/reference/decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ DBOS.kafka_consumer(
```

Runs a function for each Kafka message received on the specified topic(s).
Uses the Kafka message's topic, partition and offset to create a unique [workflow id](http://localhost:3000/python/reference/contexts#setworkflowid) to ensure once and only once execution.
Uses the Kafka message's topic, partition and offset to create a unique [workflow id](../reference/contexts#setworkflowid) to ensure once and only once execution.
Takes a configuration dictionary and a list of topics to consume.
The decorated function must take a KafkaMessage as its only parameter.

Expand Down
2 changes: 1 addition & 1 deletion docs/typescript/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ If either does not exist, the Postgres role must have the [`CREATEDB`](https://w
This section is used to specify DBOS runtime parameters.

- **start**: The command to run to start your application. For example, if your main function is compiled to `dist/main.js`, your start command would be `node dist/main.js`. Mutually exclusive with entrypoints.
- **entrypoints** (optional): The compiled JavaScript files where DBOS looks for your application's code. Mutually exclusive with a start command, should only be used if you are using the DBOS HTTP decorators. At startup, the DBOS runtime automatically loads all classes exported from these files, serving their endpoints and registering their decorated functions. Defaults to `[dist/operations.js]`.
- **entrypoints** (optional): The compiled JavaScript files where DBOS looks for your application's code. This should only be used if you are using [scheduled workflows](./transactapi/dbos-class.md#scheduled-workflows), [Kafka consumers](../tutorials/requestsandevents/kafka-integration.md), or DBOS HTTP decorators in files that are not referenced by your `start` command. At startup, the DBOS runtime automatically loads all classes exported from these files, serving their endpoints and registering their decorated functions. Defaults to `[dist/operations.js]`.
- **port** (optional): The port from which to serve your functions. Defaults to `3000`. Using [`npx dbos start -p <port>`](./tools/cli#npx-dbos-start) overrides this config parameter. Only used if you are using the DBOS HTTP decorators.
- **setup**: Setup commands to run before your application is built in DBOS Cloud. Used only in DBOS Cloud. Documentation [here](../../cloud-tutorials/application-management.md#customizing-microvm-setup)

Expand Down
11 changes: 11 additions & 0 deletions docs/typescript/reference/tools/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ You must compile your code (`npm run build`) and start the debug proxy before ru
- `-l, --loglevel <log-level>`: The severity of log entries emitted. Can be one of `debug`, `info`, `warn`, `error`, `emerg`, `crit`, `alert`.
- `-d, --appDir <application-directory>`: The path to your application root directory.

---

### `npx dbos-openapi generate`
**Description:**
This command generates an [OpenAPI 3.0.x](https://www.openapis.org/) definition file for a DBOS application.
For more information, please see the [OpenAPI Tutorial](../../tutorials/development/openapi-tutorial.md).
**Arguments:**
- `<entrypoints>`: Path to the application's TypeScript entrypoint files or folders (for example, `src/a.ts src/operations/`)

For a single entrypoint, the generated file is named `openapi.yaml` and is saved to the same directory as the TypeScript entrypoint file. If multiple files are specified, multiple `.yaml` files are generated.

## Workflow Management Commands

### `npx dbos workflow list`
Expand Down
2 changes: 1 addition & 1 deletion docs/typescript/reference/tools/time-travel-debugger.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ The Debug Proxy listens on port 2345 by default. This port can be changed via th

### dbos-ttdbg.debug_pre_launch_task

By default, the [Time Travel Debugging CodeLens](http://localhost:3000/cloud-tutorials/timetravel-debugging#launching-a-debug-session) will use
By default, the [Time Travel Debugging CodeLens](../../../cloud-tutorials/timetravel-debugging#launching-a-debug-session) will use
the settings from the first [VS Code launch configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations)
that includes `dbos-cloud debug` in the command string. If there are no such launch configurations, the extension will create
a launch configuration from scratch. The `dbos-ttdbg.debug_pre_launch_task` configuration setting is used as the
Expand Down
1 change: 1 addition & 0 deletions docs/typescript/reference/transactapi/dbos-class.md
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ This provides the following features over using Koa directly:
* Automatic configuration from `dbos-config.yaml` or the runtime environment
* Automatic network configuration in DBOS Cloud
* Default tracing, parsing, and other middleware, with [additional options](../../tutorials/requestsandevents/http-serving-tutorial.md#body-parser)
* Automatic generation of [OpenAPI](../../tutorials/development/openapi-tutorial.md) clients

The following sections describe the decorators that can be used to register methods for HTTP serving. Note that all decorated methods must be `static`, as there is no mechanism to forward function calls to a specific object instance.

Expand Down
25 changes: 25 additions & 0 deletions docs/typescript/reference/transactapi/oldapi/decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,31 @@ For a scheduled workflow to run at a given time, the time must match the crontab
A time matches the pattern if all fields of the time match the pattern.
Each field matches the pattern if its numerical value is within any of the inclusive ranges provided in the field, and is also divisible by the divisor.

### OpenAPI Decorators

DBOS [can generate](../../../tutorials/development/openapi-tutorial.md) an [OpenAPI 3.0.3](https://spec.openapis.org/oas/v3.0.3) interface description for an application. While most information needed to generate the API is picked up from decorators such as [`@GetApi`](#getapi) or [`@ArgSource`](#argsource), some decorators provide specific details only needed by OpenAPI.

#### `@OpenApiSecurityScheme`
This decorator is used to declare an [OpenAPI security scheme](https://spec.openapis.org/oas/v3.0.3#security-scheme-object) for the handler functions in a class.
This decorator takes a single parameter defining the security scheme as per the OpenAPI specification.
This decorator is purely declarative for the purpose of inclusion in the generated interface description.
You still need to implement authentication as per the [Authentication and Authorization tutorial](../../../tutorials/authentication-authorization).

::::info
DBOS does not support the `oauth2` OpenAPI security scheme at this time.
::::

```typescript
@OpenApiSecurityScheme({ type: 'http', scheme: 'bearer' })
@Authentication(authMiddleware)
export class Operations {
@DBOS.getApi("/post/:id")
static async getPost(id: string) {
...
}
}
```

### Other Decorators

#### TypeORM Decorators
Expand Down
153 changes: 153 additions & 0 deletions docs/typescript/tutorials/development/openapi-tutorial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
---
sidebar_position: 70
title: OpenAPI Support
description: Learn how to automatically generate clients for DBOS applications.
---

[DBOS CLI](../../reference/tools/cli.md) v0.6 adds the `dbos-openapi generate` command that generates an [OpenAPI 3.0.x](https://www.openapis.org/) definition file for a DBOS application.
This definition file can be used to automatically generate strongly typed client code to invoke DBOS application endpoints.

### Generate OpenAPI Definition File

First, install `@dbos-inc/dbos-openapi` as a development dependency in your project:
```shell
npm install --save-dev @dbos-inc/dbos-openapi
```

To generate a OpenAPI definition file for a DBOS application, run the following `dbos-openapi` cli command:

```shell
npx dbos-openapi generate src/operations.ts
```

::::info
It is best to check that your code compiles before running `dbos-openapi generate`.
::::

This command takes a single required argument - the path to the DBOS application's TypeScript entrypoint files. Lists of files and folders are also supported.
For DBOS applications generated by [`npx @dbos-inc/create`](../../reference/tools/cli.md#npx-dbos-inccreate), the entrypoint will be `src/operations.ts`.

The `dbos-openapi generate` command generates an OpenAPI definition file `.yaml` in the same folder as the entrypoint files. If multiple entrypoints are specified, multiple files will be created.

::::info
This `entrypoints` argument is slightly different from the [`runtimeConfig.entrypoints`](../../reference/configuration.md#runtime) config setting.
The `dbos-openapi generate` argument references the TypeScript entrypoint files.
The `runtimeConfig.entrypoints` setting references the JavaScript file generated from the TypeScript entrypoint files.
::::

### Generate Client Code From OpenAPI Definition

Multiple vendors provide OpenAPI client generators that will work with a generated OpenAPI declaration file.
Each of these vendors have tools and documentation for generating client code for a variety of languages and runtimes.
Some of these tools include:

* [Microsoft Kiota](https://learn.microsoft.com/en-us/openapi/kiota/overview)
* [OpenAPI Generator](https://openapi-generator.tech/)
* [Swagger CodeGen](https://swagger.io/tools/swagger-codegen/) and [Online Editor](https://editor.swagger.io/)
* [openapi-typescript](https://openapi-ts.pages.dev/)
* [oazapfts](https://github.com/oazapfts/oazapfts)
* [OpenAPI TypeScript Codegen](https://github.com/ferdikoomen/openapi-typescript-codegen)

We can't provide tutorials for all of these OpenAPI generator tools, but the Swagger Editor runs in the browser so is straightforward to use for a simple tutorial

First, you need to run `npx dbos-openapi generate` against your DBOS application entrypoints as described above.

::::info
Note, the shop and payment backend applications from the [E-Commerce demo app](https://github.com/dbos-inc/dbos-demo-apps/tree/main/typescript/e-commerce)
include generated OpenApi definition files if you want to try this without creating your own application.
::::

Then, copy and paste the contents of the generated `openapi.yaml` file into [Swagger Editor](https://editor.swagger.io/).
Swagger Editor will validate the OpenAPI definitions and render a documentation page for the api.

::::info
Note, the Swagger Editor generated documentation includes tooling to trigger OpenAPI endpoints from directly in the web page.
This tooling will not work as the OpenAPI definition generated by `dbos-openapi generate` does not include server URL information.
::::

At the top of the Swagger Editor, there is a "Generate Client" dropdown menu. Select typescript-axios from the menu.
This will download a zip file containing a TypeScript package with the code generated from the OpenAPI definition.

The `typescript-axios` Swagger generator generates a full TypeScript package that supports `npm install` and `npm run build`.
Typically, you would incorporate the generated code into an existing client projects that needs to call into the DBOS project.

Here is some example code using the `typescript-axios` Swagger generator and the OpenAPI definition for the [E-Commerce Demo Shop DBOS application](https://github.com/dbos-inc/dbos-demo-apps/tree/main/typescript/e-commerce/shop-backend).


```ts
import { Configuration, DefaultApi } from "./index";

const config = new Configuration({
basePath: "http://localhost:8082"
});

const api = new DefaultApi(config);

async function main() {
const response = await api.getProducts();
for (const product of response.data) {
console.log(product.description);
}
}

main();
```

::::info
As mentioned earlier, the OpenAPI definition file generated for an application does not include server URL information.
The server `basePath` must be included programmatically as in the code snippet above, regardless of the OpenAPI generator you choose to use.
::::

### Specify OpenAPI Security Scheme and Requirements

DBOS [handlers](../requestsandevents/http-serving-tutorial#handlers) (i.e. methods with `@DBOS.getApi` or `@DBOS.postApi`)
are mapped to OpenAPI [path items](https://spec.openapis.org/oas/v3.0.3#path-item-object).
Path item operations optionally include security requirements, which map to security schemes defined in the
`components.securitySchemes` section of the OpenAPI definition file.
Some OpenAPI generators use this information to automatically manage user credentials in the generated client code.

[Authentication](../authentication-authorization.md) in DBOS is done via the middleware function passed to `@Authentication`.
Parsing the authentication logic to determine the OpenAPI security scheme information is not feasible.
To include authentication information in the OpenAPI file, declare the security scheme via the `@OpenApiSecurityScheme` class decorator.

```typescript
@Authentication(authMiddleware)
@OpenApiSecurityScheme({ type: 'http', scheme: 'bearer' })
export class Operations {
@DBOS.getApi("/post/:id")
@DBOS.requiredRoles(['user'])
static async getPost(@ArgSource(ArgSources.URL) id: string) {
...
}
}
```

The `@OpenApiSecurityScheme` decorator takes a single parameter, matching a supported security scheme
[from the OpenAPI spec](https://spec.openapis.org/oas/v3.0.3#security-scheme-object).

::::info
`dbos-openapi generate` does not support the `oauth2` OpenAPI security scheme at this time.
::::

All handler methods on a class use the same `@OpenApiSecurityScheme` in the generated OpenAPI definition,
except for methods that have no specified [`@DBOS.requiredRoles`](../authentication-authorization#authorization-decorators).
DBOS does not check authentication or authorization info for methods without any required roles.
Methods without any required roles do not emit security requirements in the generated OpenAPI definition file.


```typescript
@Authentication(authMiddleware)
@DBOS.defaultRequiredRoles(['user'])
@OpenApiSecurityScheme({ type: 'http', scheme: 'bearer' })
export class Operations {
@DBOS.postApi('/api/login')
@DBOS.requiredRoles([])
static async login(ctx: HandlerContext, username: string, password: string) {
...
}
}
```

This allows a developer to have authenticated and non authenticated methods within a single class.
If you need to support different security schemes for different methods, those need to be divided into separate classes.

Loading