UNPKG

@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
# @openapi-qraft/cli `@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. ## Features - **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. ## Installation ```bash npm install -g @openapi-qraft/cli ``` ## Usage ``` 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 }, } ``` ## Contributing Contributions to `@openapi-qraft/cli` are welcome! Please feel free to submit issues, pull requests, or suggest features to help improve the utility. ## License This project is licensed under the [MIT License](https://opensource.org/license/mit/).