@openapi-qraft/cli
Version:
CLI for generating typed TanStack Query React Hooks and services from OpenAPI Document, improving type safety in React apps
261 lines (215 loc) • 19.8 kB
Markdown
`@openapi-qraft/cli` is a powerful command-line utility designed to streamline the development process by generating
service declarations and typed React Query interfaces directly from an OpenAPI Schema. With `@openapi-qraft/cli`,
frontend developers can easily generate typed API clients, ensuring type safety and improving development efficiency
within React applications.
- **Typed React Query Interfaces:** Create typed React Query hooks for seamless and type-safe API requests.
- **Generate Typed Services:** Automatically generate service declarations from an OpenAPI Schema.
```bash
npm install -g @openapi-qraft/cli
```
```
Usage: openapi-qraft --plugin tanstack-query-react --plugin openapi-typescript [input] [options]
Generate a type-safe TanStack Query client for React from an OpenAPI Document.
Arguments:
input Input OpenAPI Document file path, URL (json, yml) (default: null)
Options:
-o, --output-dir <path> Output directory for generated services
-rm, --clean Clean output directory before generating services
--filter-services <glob-patterns...> Filter services to be generated using glob patterns. Example: "/user/**,/post/**". For more details, see the NPM `micromatch` package documentation.
--operation-predefined-parameters <patterns...> Predefined parameters for services. The specified service parameters will be optional. Example: "/**:header.x-monite-version,query.x-api-key" or
"get /**:header.x-monite-entity-id"
--operation-name-modifier <patterns...> Modifies operation names using a pattern. Use the `==>` operator to separate the regular expression (left) and the substitution string (right). For
example: "post /**:[A-Za-z]+Id ==> createOne"
--postfix-services <string> Postfix to be added to the generated service name (eg: Service)
--service-name-base <endpoint[<index>] | tags> Use OpenAPI Operation `endpoint[<index>]` path part (e.g.: "/0/1/2") or `tags` as the base name of the service. (default: "endpoint[0]")
--file-header <string> Header to be added to the generated file (eg: /* eslint-disable */)
--redocly [config] Use the Redocly configuration to generate multiple API clients
If the [config] parameter is not specified, the default Redocly configuration will be used: [redocly.yaml | redocly.yml | .redocly.yaml |
.redocly.yml].
For more information about this option, use the command: --redocly-help
Examples:
$ bin --redocly
$ bin my-api --redocly
$ bin my-api@v1 my-api@v2 --redocly
$ bin --redocly ./my-redocly-config.yaml
--openapi-types-import-path <path> Path to schema types file (.d.ts), e.g.: "../schema.d.ts"
--explicit-import-extensions [extension] All import statements will contain an explicit file extension. Ideal for projects using ECMAScript modules. (choices: ".js", ".ts", preset: ".js")
--export-openapi-types [bool] Add an export statement of the generated OpenAPI document types from the `./index.ts' file. Useful for sharing types within your project. Default:
true when --plugin openapi-typescript is used. (default: true)
--queryable-write-operations [bool] Enable generation of query hooks (useQuery, useSuspenseQuery, etc.) for writable HTTP methods like POST, PUT, PATCH. By default, only mutation hooks
are generated for writable operations.
--create-api-client-fn <functionName> [options...] Configure API client creation function. Allows specifying the function name, included services, and callbacks. Can be specified multiple times to
generate several different API client functions from a single OpenAPI document. (default: null)
--override-import-type <pathname overrides...> Override import paths for specific types in generated files. This allows using custom type implementations instead of the default ones. Expected
format: filepath originalModule:importTypeName:customImportPath
--openapi-types-file-name <path> OpenAPI Schema types file name, e.g.: "schema.d.ts" (default: "schema.ts")
--enum Export true TS enums instead of unions
--enum-values Export enum values as arrays.
--dedupe-enums Dedupe enum types when `--enum` is set
-t, --export-type Export top-level `type` instead of `interface`
--immutable Generate readonly types
--additional-properties Treat schema objects as if `additionalProperties: true` is set
--empty-objects-unknown Generate `unknown` instead of `Record<string, never>` for empty objects
--default-non-nullable Set to `false` to ignore default values when generating non-nullable types
--properties-required-by-default Treat schema objects as if `required` is set to all properties by default
--array-length Generate tuples using array minItems / maxItems
--path-params-as-types Convert paths to template literal types
--alphabetize Sort object keys alphabetically
--exclude-deprecated Exclude deprecated types
--no-blob-from-binary If this option is enabled, binary format fields will not be converted to Blob types, preserving the native representation
--explicit-component-exports Enabling this option will export API components as separate type aliases, alongside `components` interface
-h, --help display help for command
```
## Usage example
The command below generates Qraft API services for the OpenAPI schema and places them in the `src/api` directory:
```bash npm2yarn
npx openapi-qraft --plugin tanstack-query-react --plugin openapi-typescript https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml \
--output-dir src/api
```
## Options
### Required
- **`-o <path>, --output-dir <path>`:** Specify where to output the generated services.
- Example: `--output-dir src/api`
### Edge-case Options
- **`-rm, --clean`:** Clean the specified output directory services before generating to remove stale files _(optional)_.
- **`--filter-services <glob-patterns...>`:** Filter services to be generated by glob pattern _(optional)_.
- **Pattern syntax:**
- `<glob-pattern>,<glob-pattern>,...` - comma-separated list of glob patterns. See [`micromatch`](https://github.com/micromatch/micromatch)
package for more details. More than one pattern can be specified.
- Examples:
- `--filter-services '/user/**,/post/**'` - include only API endpoints that start with `/user/` or `/post/`
- `--filter-services '**,!/internal/**'` - include _all_ API endpoints _except_ those that start with `/internal/`
- **`--operation-predefined-parameters <patterns...> `:** Predefined parameters for services. The specified services parameters will be optional. _(optional)_
- **Pattern syntax:**
- `<path glob>:<operation parameter>,...`
- `<method> <path glob>:<operation parameter>,...`
- Each modifier consists of an _optional_ **method**, a **path glob** pattern,
a colon, and a comma-separated list of **operation parameters** to be set as optional.
More than one predefined parameter option can be specified.
This option 💎 is arguably one of the most awesome features, allowing you to **set default parameters** across multiple endpoints.
However, if an endpoint doesn't contain a parameter specified in this option, an error will be displayed. For example:
```text
⚠ Missing predefined parameter 'header' 'x-monite-version' in 'post /files' in '/**'
```
To resolve such errors, you can exclude specific endpoints from the predefined parameters using the negation syntax in the glob pattern, like:
```
--operation-predefined-parameters '/**,!/files:header.x-monite-version'
```
- Examples:
- `--operation-predefined-parameters '/**:header.x-monite-version'` - set `header.x-monite-version`
as optional parameters for all services.
- `--operation-predefined-parameters '/**,!/auth/token:header.x-entity-id'` - set `header.x-entity-id` as optional parameters for all services except `/auth/token`.
- `--operation-predefined-parameters 'post,put /**:header.x-entity-id'` - set the `Header` record `x-entity-id` as an optional parameter for the `POST` and `PUT` methods.
- **`--operation-name-modifier <patterns...>`:** Modifies operation names using a pattern.
- **Pattern syntax:**
- `<path glob>:<regular expression> ==> <new operation name>`
- `<method> <path glob>:<regular expression> ==> <new operation name>`
- Each modifier consists of an _optional_ **method**, a **path glob** pattern,
a colon, and a **regular expression** that matches the operation name. The part after `==>` is the new operation name.
More than one modifier option can be specified.
- Examples:
- `--operation-name-modifier 'get /**:[A-Za-z]+Id ==> findOne'` - will change all `GET` operations with `Id` suffix to `findOne`.
- `--operation-name-modifier 'get /**:get(.*) ==> find-$1'` - will change all `GET` operations with `get` prefix to `findById | findAll | ...`.
- The pattern is a regular expression that matches the operation name.
- The operation name is converted to Camel Case. Spaces, hyphens, and underscores are removed.
- `--operation-name-modifier 'put,patch /**:[A-Za-z]+Id ==> updateOne'` - will change all `PUT` and `PATCH` operations with `Id` suffix to `updateOne`.
- `--operation-name-modifier '/posts,/files:create[a-zA-Z]+ ==> createOne'` - will change all operations under `/posts` and `/files` to `createOne` if the operation name starts with `create`.
- `--operation-name-modifier 'post /files ==> createOne' 'put /posts ==> updateOne'` - will change all `POST` operations under `/files` to `createOne` and all `PUT` operations under `/posts` to `updateOne`.
- **`--explicit-component-exports`:** Enabling this option will export API components as separate type aliases, alongside `components` interface.
- **`--redocly [config]`:** Use the Redocly configuration to generate multiple API clients. If the `[config]` parameter is not specified, the default Redocly configuration will be used: `[redocly.yaml | redocly.yml | .redocly.yaml | .redocly.yml]`. _(optional)_
- Examples:
- `--redocly` - use the default Redocly configuration file
- `--redocly ./my-redocly-config.yaml` - use a custom Redocly configuration file
- `openapi-qraft my-api@v1 external-api --redocly` - generate clients for multiple APIs defined in the Redocly configuration
- For more information about this option, use the command: `--redocly-help`
- **`--service-name-base <endpoint[<index>] | tags>`:** Use OpenAPI Operation `endpoint[<index>]` path part (e.g.: `/0/1/2`) or `tags` as the base name of the service. _(optional, default: `endpoint[0]`)_.
- **`endpoint[<index>]`** - Use the path segment (e.g., `/0/1/2`) as the base name for the service.
- Examples:
- `--service-name-base endpoint[0]` generates `services/FooService.ts` for the endpoint `/foo/bar/baz`
- `--service-name-base endpoint[1]` generates `services/BarService.ts` for the endpoint `/foo/bar/baz`
- `--service-name-base endpoint[3]` generates `services/BazService.ts` for the endpoint `/foo/bar/baz` _(if the endpoint is shorter than the index, the last part is used)_
- If used `endpoint[<index>]` as the base name, operation names will be generated according to the specified index.
- For example:
- `--service-name-base endpoint[1]` for the endpoint `/api/bar` generates `get` operation name.
- `--service-name-base endpoint[1]` for the endpoint `/api/foo/bar` generates `getBar` operation name.
- **`tags`** - Use the OpenAPI Operation `tags` as the base name of the service.
- Examples:
- `--service-name-base tags` will generate services based on the OpenAPI Operation tags instead of the endpoint.
- If multiple tags are present for the operation, similar services will be created for each tag. Operation with `tags: [Foo, Bar]` will generate `services/FooService.ts` and `services/BarService.ts`.
- If there are no tags for the operation, the services will be created under the `default` tag. Operation with empty `tags: []` will generate `services/DefaultService.ts`.
- If `tags` are used as the base name, operation names will be generated based on the `operationId` from the
OpenAPI Operation, or from the path if `operationId` is not provided.
You can use `--operation-name-modifier` to customize the operation names.
- **`--explicit-import-extensions [extension]`**: All import statements will contain an explicit file extension. Ideal for projects using ECMAScript modules
when TypeScript's _--moduleResolution_ is `node16` or `nodenext`. Choices: `.js`, `.ts`, preset: `.js`. _(optional)_
- **`--file-header <string>`:** Add a custom header to each generated file, useful for disabling linting rules or adding file
comments _(optional)_.
- Example: `--file-header '/* eslint-disable */'`
- **`--postfix-services <string>`:** Customize the generated service names with a specific postfix _(optional, default: `Service`)_.
- Example: `--postfix-services Endpoint` will generate `services/UserEndpoint.ts` instead of `services/UserService.ts`.
- **`--plugin <name_1> --plugin <name_2>`**: Generator plugins to be used. (choices: `tanstack-query-react`, `openapi-typescript`)
- Examples:
- `--plugin tanstack-query-react --plugin openapi-typescript` generates Qraft Services and `openapi-typescript` types file.
- `--plugin tanstack-query-react` generates Qraft Services only.
- `--plugin openapi-typescript` generates [`openapi-typescript`](https://github.com/drwpow/openapi-typescript) types file only.
- **`-h, --help`:** Display help for the command (optional).
## Plugin System
The following plugins are currently supported:
- `openapi-typescript` - Generates TypeScript types from an OpenAPI Document. The main difference from the original [`openapi-typescript`](https://www.npmjs.com/package/openapi-typescript) package is that `format: binary` fields default to `Blob` types instead of remaining as `string`. This behavior can be altered using the `--no-blob-from-binary` option.
- `tanstack-query-react` - Generates Qraft API services for React.
> Plugin must be provided with the `--plugin <name>` option. By default, the `tanstack-query-react` plugin is used.
> It is possible to use multiple plugins at the same time. For example, `--plugin tanstack-query-react --plugin openapi-typescript` generates Qraft API services & schema types file.
### `--plugin tanstack-query-react` options
- **`--openapi-types-import-path <path>`:** Set the path to the schema types definition file to ensure consistent type
usage (assumed, you already have `schema.d.ts` as a result of the [`openapi-typescript`](https://github.com/drwpow/openapi-typescript) utility). You also probably
don't need the ~~`--plugin openapi-typescript`~~ option in this case.
- The path is the exact import specifier used in the _generated services_. It should be _relative_ to the service
output directory. _Optional_, if the `--plugin openapi-typescript` is used. _Required_ otherwise.
- Examples:
- `--openapi-types-import-path ../openapi.d.ts`
- `--openapi-types-import-path '@/api/openapi.d.ts'`
- `--openapi-types-import-path '@external-package-types'`
- **`--operation-generics-import-path <path>`:** Define the path to the operation generics file, allowing for custom
operation handling _(optional, default: `@openapi-qraft/react`)_.
- **`--export-openapi-types [bool]`:** Add an export statement of the generated OpenAPI document types from the `./index.ts` file. Useful for sharing types within your project. _(optional, default: `true`, if `--plugin openapi-typescript` is used)_
### `--plugin openapi-typescript` options
- **`--queryable-write-operations [bool]`**: Enable generation of query hooks (`useQuery`, `useSuspenseQuery`, etc.) for
writable HTTP methods like _POST_, _PUT_, _PATCH_. By default, only mutation hooks are generated for writable operations.
- **`--openapi-types-file-name <path>`**: OpenAPI Schema types file name, e.g., `schema.d.ts` (default: `schema.ts`).
- **`--enum`**: Export true TypeScript enums instead of unions.
- **`--enum-values`**: Export enum values as arrays.
- **`--dedupe-enums`**: Dedupe enum types when `--enum` is set.
- **`-t, --export-type`**: Export top-level `type` instead of `interface`.
- **`--immutable`**: Generate readonly types.
- **`--additional-properties`**: Treat schema objects as if `additionalProperties: true` is set.
- **`--empty-objects-unknown`**: Generate `unknown` instead of `Record<string, never>` for empty objects.
- **`--default-non-nullable`**: Set to `false` to ignore default values when generating non-nullable types.
- **`--properties-required-by-default`**: Treat schema objects as if `required` is set to all properties by default.
- **`--array-length`**: Generate tuples using array `minItems` / `maxItems`.
- **`--path-params-as-types`**: Convert paths to template literal types.
- **`--alphabetize`**: Sort object keys alphabetically.
- **`--exclude-deprecated`**: Exclude deprecated types.
- **`--no-blob-from-binary`**: If this option is enabled, `format: binary` fields will not be converted to `Blob` types, preserving the native type. Could be used with `--plugin openapi-typescript` option.
- **`--explicit-component-exports`**: Enabling this option will export API components as separate type aliases, alongside `components` interface.
## In-project Setup
Add the following `"scripts"` to your `package.json` file:
```json5 title="package.json"
{
devDependencies: {
'@openapi-qraft/cli': 'latest',
},
scripts: {
'generate-client': 'openapi-qraft --plugin tanstack-query-react --plugin openapi-typescript https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml --output-dir src/api',
// ...other scripts
},
}
```
Contributions to `@openapi-qraft/cli` are welcome! Please feel free to submit issues, pull requests, or suggest features
to help improve the utility.
This project is licensed under the [MIT License](https://opensource.org/license/mit/).