Skip to content

Commit 38d578b

Browse files
authored
Merge pull request #334 from OpenAPI-Qraft/feat/custom-imports
feat: add support custom type imports with `--override-import-type`
2 parents 7cb9f44 + c990dc0 commit 38d578b

File tree

60 files changed

+1936
-412
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1936
-412
lines changed

.changeset/gentle-sites-pump.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@openapi-qraft/tanstack-query-react-plugin': minor
3+
---
4+
5+
New `--override-import-type` option for the CLI that has been implemented to allow overriding import paths for specific
6+
types in generated files
7+
8+
This feature has been designed to enable using custom type implementations instead of the default ones
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@openapi-qraft/cli': minor
3+
---
4+
5+
Global x-openapi-qraft configuration has been added to the Redocly config support.
6+
7+
This feature has been implemented to allow specifying x-openapi-qraft options at the global level in the Redocly
8+
configuration, rather than repeating the same options for each API client.

.changeset/orange-foxes-shave.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@openapi-qraft/tanstack-query-react-plugin': minor
3+
'@openapi-qraft/react': minor
4+
---
5+
6+
Updated the generated services to always import types from `@tanstack/react-query` instead of `@tanstack/query-core`.
7+
This simplifies the generated code and makes it easier to override types if needed.

.github/actions/spelling/allow.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ https
33
ssh
44
ubuntu
55
workarounds
6+
createapiclient

packages/cli/README.md

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,43 +24,55 @@ Usage: openapi-qraft --plugin tanstack-query-react --plugin openapi-typescript [
2424
Generate a type-safe TanStack Query client for React from an OpenAPI Document.
2525
2626
Arguments:
27-
input Input OpenAPI Document file path, URL (json, yml) (default: null)
27+
input Input OpenAPI Document file path, URL (json, yml) (default: null)
2828
2929
Options:
30-
-o, --output-dir <path> Output directory for generated services
31-
-rm, --clean Clean output directory before generating services
32-
--filter-services <glob-patterns...> Filter services to be generated using glob patterns. Example: "/user/**,/post/**". For more details, see the NPM `micromatch` package documentation.
33-
--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"
34-
--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"
35-
--postfix-services <string> Postfix to be added to the generated service name (eg: Service)
36-
--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]")
37-
--file-header <string> Header to be added to the generated file (eg: /* eslint-disable */)
38-
--redocly [config] Use the Redocly configuration to generate multiple API clients
39-
If the [config] parameter is not specified, the default Redocly configuration will be used: [redocly.yaml | redocly.yml | .redocly.yaml | .redocly.yml].
40-
For more information about this option, use the command: --redocly-help
41-
Examples: "openapi-qraft --redocly", "openapi-qraft my-api@v1 external-api --redocly", "openapi-qraft --redocly
42-
./my-redocly-config.yaml"
43-
--openapi-types-import-path <path> Path to schema types file (.d.ts), e.g.: "../schema.d.ts"
44-
--explicit-import-extensions [extension] All import statements will contain an explicit file extension. Ideal for projects using ECMAScript modules. (choices: ".js", ".ts", preset: ".js")
45-
--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)
46-
--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.
47-
--openapi-types-file-name <path> OpenAPI Schema types file name, e.g.: "schema.d.ts" (default: "schema.ts")
48-
--enum Export true TS enums instead of unions
49-
--enum-values Export enum values as arrays.
50-
--dedupe-enums Dedupe enum types when `--enum` is set
51-
-t, --export-type Export top-level `type` instead of `interface`
52-
--immutable Generate readonly types
53-
--additional-properties Treat schema objects as if `additionalProperties: true` is set
54-
--empty-objects-unknown Generate `unknown` instead of `Record<string, never>` for empty objects
55-
--default-non-nullable Set to `false` to ignore default values when generating non-nullable types
56-
--properties-required-by-default Treat schema objects as if `required` is set to all properties by default
57-
--array-length Generate tuples using array minItems / maxItems
58-
--path-params-as-types Convert paths to template literal types
59-
--alphabetize Sort object keys alphabetically
60-
--exclude-deprecated Exclude deprecated types
61-
--no-blob-from-binary If this option is enabled, binary format fields will not be converted to Blob types, preserving the native representation
62-
--explicit-component-exports Enabling this option will export API components as separate type aliases, alongside `components` interface
63-
-h, --help display help for command
30+
-o, --output-dir <path> Output directory for generated services
31+
-rm, --clean Clean output directory before generating services
32+
--filter-services <glob-patterns...> Filter services to be generated using glob patterns. Example: "/user/**,/post/**". For more details, see the NPM `micromatch` package documentation.
33+
--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
34+
"get /**:header.x-monite-entity-id"
35+
--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
36+
example: "post /**:[A-Za-z]+Id ==> createOne"
37+
--postfix-services <string> Postfix to be added to the generated service name (eg: Service)
38+
--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]")
39+
--file-header <string> Header to be added to the generated file (eg: /* eslint-disable */)
40+
--redocly [config] Use the Redocly configuration to generate multiple API clients
41+
If the [config] parameter is not specified, the default Redocly configuration will be used: [redocly.yaml | redocly.yml | .redocly.yaml |
42+
.redocly.yml].
43+
For more information about this option, use the command: --redocly-help
44+
Examples:
45+
$ bin --redocly
46+
$ bin my-api --redocly
47+
$ bin my-api@v1 my-api@v2 --redocly
48+
$ bin --redocly ./my-redocly-config.yaml
49+
--openapi-types-import-path <path> Path to schema types file (.d.ts), e.g.: "../schema.d.ts"
50+
--explicit-import-extensions [extension] All import statements will contain an explicit file extension. Ideal for projects using ECMAScript modules. (choices: ".js", ".ts", preset: ".js")
51+
--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:
52+
true when --plugin openapi-typescript is used. (default: true)
53+
--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
54+
are generated for writable operations.
55+
--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
56+
generate several different API client functions from a single OpenAPI document. (default: null)
57+
--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
58+
format: filepath originalModule:importTypeName:customImportPath
59+
--openapi-types-file-name <path> OpenAPI Schema types file name, e.g.: "schema.d.ts" (default: "schema.ts")
60+
--enum Export true TS enums instead of unions
61+
--enum-values Export enum values as arrays.
62+
--dedupe-enums Dedupe enum types when `--enum` is set
63+
-t, --export-type Export top-level `type` instead of `interface`
64+
--immutable Generate readonly types
65+
--additional-properties Treat schema objects as if `additionalProperties: true` is set
66+
--empty-objects-unknown Generate `unknown` instead of `Record<string, never>` for empty objects
67+
--default-non-nullable Set to `false` to ignore default values when generating non-nullable types
68+
--properties-required-by-default Treat schema objects as if `required` is set to all properties by default
69+
--array-length Generate tuples using array minItems / maxItems
70+
--path-params-as-types Convert paths to template literal types
71+
--alphabetize Sort object keys alphabetically
72+
--exclude-deprecated Exclude deprecated types
73+
--no-blob-from-binary If this option is enabled, binary format fields will not be converted to Blob types, preserving the native representation
74+
--explicit-component-exports Enabling this option will export API components as separate type aliases, alongside `components` interface
75+
-h, --help display help for command
6476
```
6577

6678
## Usage example

packages/plugin/src/lib/RedoclyConfigCommand.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,16 @@ export class RedoclyConfigCommand extends Command {
104104
}
105105

106106
redocAPIsToQraftEntries.forEach(([apiName, api]) => {
107+
const globalQraftConfig =
108+
'x-openapi-qraft' in redoc.rawConfig
109+
? redoc.rawConfig['x-openapi-qraft']
110+
: undefined;
111+
107112
const {
108-
['x-openapi-qraft']: { ['output-dir']: outputDir, ...qraftConfig },
113+
['x-openapi-qraft']: {
114+
['output-dir']: outputDir,
115+
...apiQraftConfig
116+
},
109117
} = api;
110118

111119
const cwd = fileURLToPath(this.cwd);
@@ -115,7 +123,10 @@ export class RedoclyConfigCommand extends Command {
115123
...parseConfigToArgs({
116124
redocly: relative(cwd, redocConfigFile),
117125
'output-dir': relative(cwd, outputDir),
118-
...qraftConfig,
126+
...(globalQraftConfig && typeof globalQraftConfig === 'object'
127+
? globalQraftConfig
128+
: undefined),
129+
...apiQraftConfig,
119130
}),
120131
];
121132
});
@@ -155,7 +166,7 @@ export class RedoclyConfigCommand extends Command {
155166
spinner.info(
156167
`Generating API client for ${c.magenta(apiName)} with the following parameters:\n` +
157168
c.gray.italic('bin ') +
158-
`${c.green.italic(openAPIDocument)}` +
169+
`${c.green.italic(openAPIDocument)} ` +
159170
apiProcessArgv
160171
.map((arg) =>
161172
arg.startsWith('--')

packages/plugin/src/lib/parseConfigToArgs.spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,36 @@ describe('configParser', () => {
130130
'callbacks:setQueryData,getQueryData,fetchQuery',
131131
]);
132132
});
133+
134+
it('should parse complex nested mappings', () => {
135+
expect(
136+
parseConfigToArgs({
137+
'override-import-type': {
138+
services: {
139+
'@openapi-qraft/tanstack-query-react-types': {
140+
ResultError: '../ResponseError',
141+
ResultSuccess: '../ResultSuccess',
142+
},
143+
'@openapi-qraft/react': {
144+
UseQueryOperation: '../UseQueryOperation',
145+
},
146+
},
147+
'create-client': {
148+
'@openapi-qraft/react': {
149+
UseQueryOperation: '../UseQueryOperation',
150+
},
151+
},
152+
},
153+
})
154+
).toEqual([
155+
'--override-import-type',
156+
'services',
157+
'@openapi-qraft/tanstack-query-react-types:ResultError:../ResponseError',
158+
'@openapi-qraft/tanstack-query-react-types:ResultSuccess:../ResultSuccess',
159+
'@openapi-qraft/react:UseQueryOperation:../UseQueryOperation',
160+
'--override-import-type',
161+
'create-client',
162+
'@openapi-qraft/react:UseQueryOperation:../UseQueryOperation',
163+
]);
164+
});
133165
});

packages/react-client/redocly.yaml

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
x-openapi-qraft:
2+
plugin:
3+
tanstack-query-react: true
4+
openapi-typescript: true
5+
16
rules:
27
operation-operationId-unique:
38
severity: 'error'
@@ -6,9 +11,6 @@ apis:
611
main:
712
root: ../test-fixtures/openapi.json
813
x-openapi-qraft:
9-
plugin:
10-
tanstack-query-react: true
11-
openapi-typescript: true
1214
output-dir: src/tests/fixtures/api
1315
clean: true
1416
enum-values: true
@@ -37,12 +39,27 @@ apis:
3739
filter-services:
3840
- '/approval_policies/**'
3941
- '/files/**'
42+
operation-predefined-parameters:
43+
'/approval_policies/**': 'header.x-monite-entity-id'
44+
override-import-type:
45+
services:
46+
'@openapi-qraft/tanstack-query-react-types':
47+
OperationError: '../../type-overrides/operation-error.js'
48+
'@tanstack/react-query':
49+
UseSuspenseQueryOptions: '../../type-overrides/suspense-query.js'
50+
UseSuspenseQueryResult: '../../type-overrides/suspense-query.js'
51+
UseInfiniteQueryResult: '../../type-overrides/use-infinite-query-result.js'
52+
create-api-client:
53+
'@openapi-qraft/react':
54+
CreateAPIQueryClientOptions: '../type-overrides/create-query-client-options.js'
55+
create-predefined-parameters-request-fn:
56+
'@openapi-qraft/react':
57+
RequestFn: '../type-overrides/qraft-predefined-parameters.js'
58+
'@openapi-qraft/react/qraftPredefinedParametersRequestFn':
59+
QraftPredefinedParameterValue: '../type-overrides/qraft-predefined-parameters.js'
4060
files:
4161
root: ../test-fixtures/openapi.json
4262
x-openapi-qraft:
43-
plugin:
44-
tanstack-query-react: true
45-
openapi-typescript: true
4663
output-dir: src/tests/fixtures/files-api
4764
clean: true
4865
openapi-types-file-name: internal-openapi.ts
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type { CreateAPIQueryClientOptions } from '@openapi-qraft/react';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type { OperationError } from '@openapi-qraft/tanstack-query-react-types';

0 commit comments

Comments
 (0)