@openapi-qraft/cli 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +109 -43
  3. package/bin.mjs +3 -1
  4. package/dist/bin.d.ts +13 -1
  5. package/dist/bin.d.ts.map +1 -0
  6. package/dist/bin.js +71 -59
  7. package/dist/bin.js.map +1 -1
  8. package/dist/builtInPlugins.d.ts +5 -0
  9. package/dist/builtInPlugins.d.ts.map +1 -0
  10. package/dist/builtInPlugins.js +5 -0
  11. package/dist/builtInPlugins.js.map +1 -0
  12. package/package.json +16 -12
  13. package/src/bin.ts +99 -0
  14. package/src/builtInPlugins.ts +6 -0
  15. package/dist/lib/fileHeader.d.ts +0 -1
  16. package/dist/lib/fileHeader.js +0 -5
  17. package/dist/lib/fileHeader.js.map +0 -1
  18. package/dist/lib/open-api/OpenAPISchemaType.d.ts +0 -31
  19. package/dist/lib/open-api/OpenAPISchemaType.js +0 -2
  20. package/dist/lib/open-api/OpenAPISchemaType.js.map +0 -1
  21. package/dist/lib/open-api/getContent.d.ts +0 -5
  22. package/dist/lib/open-api/getContent.js +0 -23
  23. package/dist/lib/open-api/getContent.js.map +0 -1
  24. package/dist/lib/open-api/getOperationName.d.ts +0 -6
  25. package/dist/lib/open-api/getOperationName.js +0 -20
  26. package/dist/lib/open-api/getOperationName.js.map +0 -1
  27. package/dist/lib/open-api/getServiceName.d.ts +0 -5
  28. package/dist/lib/open-api/getServiceName.js +0 -13
  29. package/dist/lib/open-api/getServiceName.js.map +0 -1
  30. package/dist/lib/open-api/getServiceNamesByOperationEndpoint.d.ts +0 -4
  31. package/dist/lib/open-api/getServiceNamesByOperationEndpoint.js +0 -30
  32. package/dist/lib/open-api/getServiceNamesByOperationEndpoint.js.map +0 -1
  33. package/dist/lib/open-api/getServiceNamesByOperationTags.d.ts +0 -1
  34. package/dist/lib/open-api/getServiceNamesByOperationTags.js +0 -11
  35. package/dist/lib/open-api/getServiceNamesByOperationTags.js.map +0 -1
  36. package/dist/lib/open-api/getServices.d.ts +0 -32
  37. package/dist/lib/open-api/getServices.js +0 -112
  38. package/dist/lib/open-api/getServices.js.map +0 -1
  39. package/dist/lib/open-api/readSchema.d.ts +0 -7
  40. package/dist/lib/open-api/readSchema.js +0 -15
  41. package/dist/lib/open-api/readSchema.js.map +0 -1
  42. package/dist/lib/ts-factory/astToString.d.ts +0 -8
  43. package/dist/lib/ts-factory/astToString.js +0 -14
  44. package/dist/lib/ts-factory/astToString.js.map +0 -1
  45. package/dist/lib/ts-factory/getClientFactory.d.ts +0 -7
  46. package/dist/lib/ts-factory/getClientFactory.js +0 -82
  47. package/dist/lib/ts-factory/getClientFactory.js.map +0 -1
  48. package/dist/lib/ts-factory/getIndexFactory.d.ts +0 -5
  49. package/dist/lib/ts-factory/getIndexFactory.js +0 -17
  50. package/dist/lib/ts-factory/getIndexFactory.js.map +0 -1
  51. package/dist/lib/ts-factory/getServiceFactory.d.ts +0 -10
  52. package/dist/lib/ts-factory/getServiceFactory.js +0 -120
  53. package/dist/lib/ts-factory/getServiceFactory.js.map +0 -1
  54. package/dist/lib/ts-factory/getServiceIndexFactory.d.ts +0 -7
  55. package/dist/lib/ts-factory/getServiceIndexFactory.js +0 -26
  56. package/dist/lib/ts-factory/getServiceIndexFactory.js.map +0 -1
  57. package/dist/writeOpenAPIServices.d.ts +0 -23
  58. package/dist/writeOpenAPIServices.js +0 -97
  59. package/dist/writeOpenAPIServices.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @openapi-qraft/cli
2
2
 
3
+ ## 1.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 3a75364: **Plugin Support in CLI**: Introduced the `--plugin <name>` option in the OpenAPI Qraft CLI to allow users to specify
8
+ plugins such as `tanstack-query-react` for React service generation and `openapi-typescript` for TypeScript type
9
+ generation. This enhancement provides greater flexibility and customization options in the API generation process. The
10
+ CLI now supports using multiple plugins simultaneously, enhancing the tool's versatility for developers.
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies [943a9d3]
15
+ - Updated dependencies [3a75364]
16
+ - @openapi-qraft/plugin@1.9.0
17
+ - @openapi-qraft/openapi-typescript-plugin@1.0.1
18
+ - @openapi-qraft/tanstack-query-react-plugin@1.9.0
19
+
20
+ ## 1.8.0
21
+
22
+ ### Patch Changes
23
+
24
+ - 878c002: Replaced string-based path handling with URL objects to ensure path normalization and enhance security.
25
+ - Updated dependencies [27d501a]
26
+ - @openapi-qraft/tanstack-query-react-plugin@1.8.0
27
+
3
28
  ## 1.7.0
4
29
 
5
30
  ## 1.6.0
package/README.md CHANGED
@@ -19,49 +19,59 @@ npm install -g @openapi-qraft/cli
19
19
  ## Usage
20
20
 
21
21
  ```
22
- Usage: openapi-qraft [options] [input]
22
+ Usage: openapi-qraft --plugin tanstack-query-react --plugin openapi-typescript [input] [options]
23
+
24
+ Generate TypeScript types from OpenAPI 3.x Document. Based on "openapi-typescript" (https://github.com/drwpow/openapi-typescript/)
23
25
 
24
26
  Arguments:
25
- input Input OpenAPI Schema file path, URL (json, yml) (default: null)
27
+ input Input OpenAPI Document file path, URL (json, yml) (default: null)
26
28
 
27
29
  Options:
28
- -o, --output-dir <path> Output directory for generated services
29
- --openapi-types-import-path <path> Path to schema types file (.d.ts), eg: "../openapi.d.ts"
30
- -rm, --clean Clean output directory before generating services
31
- --filter-services <glob-pattern> Filter services to be generated by glob pattern. Eg: "/user/**,/post/**". See NPM `micromatch` package for more details.
32
- --operation-generics-import-path <path> Path to operation generics file (default: "@openapi-qraft/react")
33
- --file-header <string> Header to be added to the generated file (eg: /* eslint-disable */)
34
- --postfix-services <string> Postfix to be added to the generated service name (eg: Service)
35
- --explicit-import-extensions All import statements will include explicit `.js` extensions. Ideal for projects using ECMAScript modules.
36
- --service-name-base <endpoint | tags> Use OpenAPI Operation `endpoint` or `tags` as service names (default: "endpoint")
37
- -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-pattern> Filter services to be generated by glob pattern. Eg: "/user/**,/post/**". See NPM `micromatch` package for more
33
+ details.
34
+ --postfix-services <string> Postfix to be added to the generated service name (eg: Service)
35
+ --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.
36
+ (default: "endpoint[0]")
37
+ --file-header <string> Header to be added to the generated file (eg: /* eslint-disable */)
38
+ --openapi-types-import-path <path> Path to schema types file (.d.ts), eg: "../schema.d.ts"
39
+ --explicit-import-extensions All import statements will include explicit `.js` extensions. Ideal for projects using ECMAScript modules.
40
+ --export-openapi-types [bool] Export the OpenAPI schema types from the generated `./index.ts` file (default: true)
41
+ --operation-generics-import-path <path> Path to operation generics file (default: "@openapi-qraft/react")
42
+ --openapi-types-file-name <path> OpenAPI Schema types file name, eg: "schema.d.ts" (default: "schema.ts")
43
+ --enum Export true TS enums instead of unions
44
+ -t, --export-type Export top-level `type` instead of `interface`
45
+ --immutable Generate readonly types
46
+ --additional-properties Treat schema objects as if `additionalProperties: true` is set
47
+ --empty-objects-unknown Generate `unknown` instead of `Record<string, never>` for empty objects
48
+ --default-non-nullable Set to `false` to ignore default values when generating non-nullable types
49
+ --properties-required-by-default Treat schema objects as if `required` is set to all properties by default
50
+ --array-length Generate tuples using array minItems / maxItems
51
+ --path-params-as-types Convert paths to template literal types
52
+ --alphabetize Sort object keys alphabetically
53
+ --exclude-deprecated Exclude deprecated types
54
+ --no-blob-from-binary If this option is enabled, binary format fields will not be converted to Blob types, preserving the native
55
+ representation
56
+ -h, --help display help for command
57
+
38
58
  ```
39
59
 
40
- ### Example
60
+ ## Usage example
41
61
 
42
- To generate services from an OpenAPI schema file:
62
+ The command below generates Qraft API services for the OpenAPI schema and places them in the `src/api` directory:
43
63
 
44
- ```bash
45
- openapi-qraft https://example.com/openapi.json --output-dir src/api --openapi-types-import-path ../openapi.d.ts
64
+ ```bash npm2yarn
65
+ npx openapi-qraft --plugin tanstack-query-react --plugin openapi-typescript https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml \
66
+ --output-dir src/api
46
67
  ```
47
68
 
48
- This command generates service declarations and React Query hooks types in the `src/api` directory based on
49
- the `schema.json` file.
50
-
51
- #### Required Options
69
+ ### Required
52
70
 
53
71
  - **`-o <path>, --output-dir <path>`:** Specify where to output the generated services.
54
72
  - Example: `--output-dir src/api`
55
- - **`--openapi-types-import-path <path>`:** Set the path to the schema types definition file to ensure consistent type
56
- usage (assumed, you already have `openapi.d.ts` as a result of the [`openapi-typescript`](https://github.com/drwpow/openapi-typescript) utility).
57
- - The path is the exact import specifier used in the _generated services_. It should be \_relative to the service
58
- output directory.
59
- - Examples:
60
- - `--openapi-types-import-path ../openapi.d.ts`
61
- - `--openapi-types-import-path '@/api/openapi.d.ts'`
62
- - `--openapi-types-import-path '@external-package-types'`
63
73
 
64
- #### Useful Options
74
+ ### Edge-case Options
65
75
 
66
76
  - **`-rm, --clean`:** Clean the specified output directory services before generating to remove stale files _(optional)_.
67
77
  - **`--filter-services`:** Filter services to be generated by glob pattern _(optional)_. See [`micromatch`](https://github.com/micromatch/micromatch)
@@ -69,28 +79,84 @@ the `schema.json` file.
69
79
  - Examples:
70
80
  - `--filter-services '/user/**,/post/**'` - include only API endpoints that start with `/user/` or `/post/`
71
81
  - `--filter-services '**,!/internal/**'` - include _all_ API endpoints _except_ those that start with `/internal/`
72
-
73
- #### Edge-case Options
74
-
75
- - **`--operation-generics-import-path <path>`:** Define the path to the operation generics file, allowing for custom
76
- operation handling _(optional, default: `@openapi-qraft/react`)_.
82
+ - **`--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]`)_.
83
+ - Examples:
84
+ - `--service-name-base endpoint[0]` generates `services/FooService.ts` for the endpoint `/foo/bar/baz`
85
+ - `--service-name-base endpoint[1]` generates `services/BarService.ts` for the endpoint `/foo/bar/baz`
86
+ - `--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)_
87
+ - `--service-name-base tags` will generate services based on the OpenAPI Operation tags instead of the endpoint.
88
+ - 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`.
89
+ - 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`.
90
+ - **`--explicit-import-extensions`:** Include explicit `.js` extensions in all import statements. Ideal for projects using ECMAScript modules when TypeScript's _--moduleResolution_ is `node16` or `nodenext` _(optional)_.
77
91
  - **`--file-header <string>`:** Add a custom header to each generated file, useful for disabling linting rules or adding file
78
92
  comments _(optional)_.
79
93
  - Example: `--file-header '/* eslint-disable */'`
80
94
  - **`--postfix-services <string>`:** Customize the generated service names with a specific postfix _(optional, default: `Service`)_.
81
95
  - Example: `--postfix-services Endpoint` will generate `services/UserEndpoint.ts` instead of `services/UserService.ts`.
82
- - **`--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]`)_.
96
+ - **`--plugin <name_1> --plugin <name_2>`**: Generator plugins to be used. (choices: `tanstack-query-react`, `openapi-typescript`)
83
97
  - Examples:
84
- - `--service-name-base endpoint[0]` generates `services/FooService.ts`. from endpoint `/foo/bar/baz`
85
- - `--service-name-base endpoint[1]` generates `services/BarService.ts`. from endpoint `/foo/bar/baz`
86
- - `--service-name-base endpoint[2]` generates `services/BarService.ts`. from endpoint `/foo/bar` _(if the endpoint is shorter than the index, the last part is used)_
87
- - `--service-name-base tags` will generate services based on the OpenAPI Operation tags instead of the endpoint.
88
- - 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`.
89
- - 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`.
90
- - **`--explicit-import-extensions`:** Include explicit `.js` extensions in all import statements. Ideal for projects
91
- using ECMAScript modules when TypeScript's _--moduleResolution_ is `node16` or `nodenext` _(optional)_.
98
+ - `--plugin tanstack-query-react --plugin openapi-typescript` generates Qraft Services and `openapi-typescript` types file.
99
+ - `--plugin tanstack-query-react` generates Qraft Services only.
100
+ - `--plugin openapi-typescript` generates [`openapi-typescript`](https://github.com/drwpow/openapi-typescript) types file only.
92
101
  - **`-h, --help`:** Display help for the command (optional).
93
102
 
103
+ ## Plugin System
104
+
105
+ The following plugins are currently supported:
106
+
107
+ - `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.
108
+ - `tanstack-query-react` - Generates Qraft API services for React.
109
+
110
+ > Plugin must be provided with the `--plugin <name>` option. By default, the `tanstack-query-react` plugin is used.
111
+ > 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.
112
+
113
+ ### `--plugin tanstack-query-react` options
114
+
115
+ - **`--openapi-types-import-path <path>`:** Set the path to the schema types definition file to ensure consistent type
116
+ 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
117
+ don't need the ~~`--plugin openapi-typescript`~~ option in this case.
118
+ - The path is the exact import specifier used in the _generated services_. It should be _relative_ to the service
119
+ output directory. _Optional_, if the `--plugin openapi-typescript` is used. _Required_ otherwise.
120
+ - Examples:
121
+ - `--openapi-types-import-path ../openapi.d.ts`
122
+ - `--openapi-types-import-path '@/api/openapi.d.ts'`
123
+ - `--openapi-types-import-path '@external-package-types'`
124
+ - **`--operation-generics-import-path <path>`:** Define the path to the operation generics file, allowing for custom
125
+ operation handling _(optional, default: `@openapi-qraft/react`)_.
126
+ - **`--export-openapi-types [bool]`:** Export the OpenAPI schema types from the generated `./index.ts` file. _(optional, default: `true`, if `--plugin openapi-typescript` is used)_
127
+
128
+ ### `--plugin openapi-typescript` options
129
+
130
+ - **`--openapi-types-file-name <path>`**: OpenAPI Schema types file name, e.g., `schema.d.ts` (default: `schema.ts`).
131
+ - **`--enum`**: Export true TypeScript enums instead of unions.
132
+ - **`-t, --export-type`**: Export top-level `type` instead of `interface`.
133
+ - **`--immutable`**: Generate readonly types.
134
+ - **`--additional-properties`**: Treat schema objects as if `additionalProperties: true` is set.
135
+ - **`--empty-objects-unknown`**: Generate `unknown` instead of `Record<string, never>` for empty objects.
136
+ - **`--default-non-nullable`**: Set to `false` to ignore default values when generating non-nullable types.
137
+ - **`--properties-required-by-default`**: Treat schema objects as if `required` is set to all properties by default.
138
+ - **`--array-length`**: Generate tuples using array `minItems` / `maxItems`.
139
+ - **`--path-params-as-types`**: Convert paths to template literal types.
140
+ - **`--alphabetize`**: Sort object keys alphabetically.
141
+ - **`--exclude-deprecated`**: Exclude deprecated types.
142
+ - **`--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.
143
+
144
+ ## In-project Setup
145
+
146
+ Add the following `"scripts"` to your `package.json` file:
147
+
148
+ ```json lines title="package.json"
149
+ {
150
+ "devDependencies": {
151
+ "@openapi-qraft/cli": "latest"
152
+ },
153
+ "scripts": {
154
+ "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"
155
+ // ...other scripts
156
+ }
157
+ }
158
+ ```
159
+
94
160
  ## Contributing
95
161
 
96
162
  Contributions to `@openapi-qraft/cli` are welcome! Please feel free to submit issues, pull requests, or suggest features
package/bin.mjs CHANGED
@@ -5,4 +5,6 @@
5
5
  * Workaround to allow `rimraf dist/` on rebuilds and keep `bin` executable
6
6
  * without a need `yarn install`
7
7
  */
8
- import './dist/bin.js';
8
+ import { main } from './dist/bin.js';
9
+
10
+ main();
package/dist/bin.d.ts CHANGED
@@ -1,2 +1,14 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ export declare function main(): Promise<undefined>;
3
+ /**
4
+ * Extracts multiple `--plugin <name>` options from the `argv`
5
+ * and returns the filtered `argv` and the list of plugins.
6
+ */
7
+ export declare function extractArgvPluginOptions(argv: string[]): {
8
+ argv: string[];
9
+ plugins?: undefined;
10
+ } | {
11
+ argv: string[];
12
+ plugins: string[];
13
+ };
14
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AASA,wBAAsB,IAAI,uBA8BzB;AA+BD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE;;;;;;EAwBtD"}
package/dist/bin.js CHANGED
@@ -1,63 +1,75 @@
1
1
  #!/usr/bin/env node
2
- import c from 'ansi-colors';
3
- import { program } from 'commander';
4
- import fs from 'node:fs';
5
- import { fileHeader } from './lib/fileHeader.js';
6
- import { writeOpenAPIServices } from './writeOpenAPIServices.js';
7
- program
8
- .description('Generate services declarations and Typed React Query Interfaces from OpenAPI Schema')
9
- .argument('[input]', 'Input OpenAPI Schema file path, URL (json, yml)', null)
10
- .requiredOption('-o, --output-dir <path>', 'Output directory for generated services')
11
- .requiredOption('--openapi-types-import-path <path>', // todo::specify better param name to avoid confusion with real path
12
- 'Path to schema types file (.d.ts), eg: "../openapi.d.ts"')
13
- .option('-rm, --clean', 'Clean output directory before generating services')
14
- .option('--filter-services <glob-pattern>', 'Filter services to be generated by glob pattern. Eg: "/user/**,/post/**". See NPM `micromatch` package for more details.')
15
- .option('--operation-generics-import-path <path>', 'Path to operation generics file', '@openapi-qraft/react')
16
- .option('--file-header <string>', 'Header to be added to the generated file (eg: /* eslint-disable */)')
17
- .option('--postfix-services <string>', 'Postfix to be added to the generated service name (eg: Service)')
18
- .option('--explicit-import-extensions', 'All import statements will include explicit `.js` extensions. Ideal for projects using ECMAScript modules.')
19
- .option('--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.', 'endpoint[0]')
20
- .action(async (input, args) => {
21
- const { version: packageVersion, name: packageName } = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
22
- if (args.version) {
23
- console.info(`v${packageVersion}`);
24
- process.exit(0);
2
+ import { QraftCommand } from '@openapi-qraft/plugin/lib/QraftCommand';
3
+ import { Option } from 'commander';
4
+ import process from 'node:process';
5
+ import { builtInPlugins } from './builtInPlugins.js';
6
+ export async function main() {
7
+ const command = new QraftCommand();
8
+ const { argv, plugins } = extractArgvPluginOptions(process.argv);
9
+ if (plugins) {
10
+ await setupPlugins(command, plugins);
25
11
  }
26
- console.info(`✨ ${c.bold(`${packageName} ${packageVersion}`)}`);
27
- const source = input
28
- ? new URL(input, new URL(`file://${process.cwd()}/`))
29
- : process.stdin;
30
- if (source === process.stdin && source.isTTY) {
31
- console.error(c.red('Input file not found or stdin is empty. Please specify `--input` option or pipe OpenAPI Schema to stdin.'));
32
- process.exit(1);
12
+ else {
13
+ // default - setup tanstack-query-react plugin
14
+ await setupPlugins(command, [
15
+ 'tanstack-query-react',
16
+ ]);
17
+ // option to display help with all available plugins
18
+ command.addOption(new Option('--plugin <name_1> --plugin <name_2>', `Generator plugins to be used.`)
19
+ .choices(Object.keys(builtInPlugins))
20
+ .argParser(() => {
21
+ // Fallback, if plugins parsing went wrong
22
+ throw new Error('Plugin option must be handled before parsing the command and should not be passed to the commander');
23
+ }));
33
24
  }
34
- const servicesGlob = args.filterServices
35
- ? args.filterServices
36
- .split(',')
37
- .filter((item) => typeof item === 'string' && item.trim())
38
- : undefined;
39
- await writeOpenAPIServices({
40
- source,
41
- serviceImports: {
42
- operationGenericsImportPath: args.operationGenericsImportPath,
43
- openapiTypesImportPath: args.openapiTypesImportPath,
44
- },
45
- servicesGlob,
46
- output: {
47
- dir: args.outputDir,
48
- clean: args.clean,
49
- fileHeader: args.fileHeader ?? fileHeader,
50
- postfixServices: args.postfixServices,
51
- explicitImportExtensions: args.explicitImportExtensions,
52
- servicesDirName: 'services',
53
- serviceNameBase: args.serviceNameBase,
54
- },
55
- }).catch((error) => {
56
- if (error instanceof Error)
57
- console.error(c.red(error.message), c.red(error.stack ?? ''));
58
- console.error(error);
59
- process.exit(1);
60
- });
61
- });
62
- program.parse(process.argv);
25
+ return void (await command.parseAsync(argv));
26
+ }
27
+ async function setupPlugins(command, plugins) {
28
+ const pluginList = [];
29
+ for (const pluginName of plugins) {
30
+ if (!(pluginName in builtInPlugins))
31
+ throw new Error(`Unknown plugin: '${pluginName}'`);
32
+ pluginList.push((await builtInPlugins[pluginName]())
33
+ .default);
34
+ addCommandUsageWithPlugins(command, plugins);
35
+ }
36
+ await Promise.all(pluginList.map((plugin) => plugin.setupCommand(command)));
37
+ await Promise.all(pluginList.map((plugin) => plugin.postSetupCommand?.(command, plugins)));
38
+ }
39
+ /**
40
+ * Add plugin's usage instructions calling `command.usage(...)`
41
+ */
42
+ function addCommandUsageWithPlugins(command, plugins) {
43
+ const pluginUsage = plugins.map((plugin) => `--plugin ${plugin}`).join(' ');
44
+ command.usage(`${pluginUsage} [input] [options]`);
45
+ }
46
+ /**
47
+ * Extracts multiple `--plugin <name>` options from the `argv`
48
+ * and returns the filtered `argv` and the list of plugins.
49
+ */
50
+ export function extractArgvPluginOptions(argv) {
51
+ const pluginIndex = argv.indexOf('--plugin');
52
+ if (pluginIndex === -1)
53
+ return { argv };
54
+ const filteredArgv = argv.slice(0, pluginIndex);
55
+ const plugins = [];
56
+ for (let i = pluginIndex; i < argv.length; i++) {
57
+ if (argv[i] === '--plugin') {
58
+ const pluginName = argv.at(i + 1);
59
+ if (!pluginName)
60
+ throw new Error(`Missing plugin name after '--plugin'`);
61
+ if (pluginName?.startsWith('--'))
62
+ throw new Error(`Invalid plugin name: '${pluginName}'`);
63
+ plugins.push(pluginName);
64
+ i++; // Skip next item
65
+ }
66
+ else {
67
+ filteredArgv.push(argv[i]);
68
+ }
69
+ }
70
+ return {
71
+ argv: filteredArgv,
72
+ plugins,
73
+ };
74
+ }
63
75
  //# sourceMappingURL=bin.js.map
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare const builtInPlugins: {
2
+ readonly 'tanstack-query-react': () => Promise<typeof import("@openapi-qraft/tanstack-query-react-plugin")>;
3
+ readonly 'openapi-typescript': () => Promise<typeof import("@openapi-qraft/openapi-typescript-plugin")>;
4
+ };
5
+ //# sourceMappingURL=builtInPlugins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtInPlugins.d.ts","sourceRoot":"","sources":["../src/builtInPlugins.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc;;;CAKjB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export const builtInPlugins = {
2
+ 'tanstack-query-react': () => import('@openapi-qraft/tanstack-query-react-plugin'),
3
+ 'openapi-typescript': () => import('@openapi-qraft/openapi-typescript-plugin'),
4
+ };
5
+ //# sourceMappingURL=builtInPlugins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtInPlugins.js","sourceRoot":"","sources":["../src/builtInPlugins.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,sBAAsB,EAAE,GAAG,EAAE,CAC3B,MAAM,CAAC,4CAA4C,CAAC;IACtD,oBAAoB,EAAE,GAAG,EAAE,CACzB,MAAM,CAAC,0CAA0C,CAAC;CAC5C,CAAC"}
package/package.json CHANGED
@@ -1,36 +1,40 @@
1
1
  {
2
2
  "name": "@openapi-qraft/cli",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "description": "CLI for generating typed Tanstack Query React Hooks and services from OpenAPI Schemas, improving type safety in React apps",
5
5
  "scripts": {
6
6
  "build": "rimraf dist/ && tsc --project tsconfig.build.json",
7
7
  "dev": "yarn build --watch",
8
8
  "test": "vitest run",
9
- "typecheck": "tsc --noEmit"
9
+ "typecheck": "tsc --noEmit",
10
+ "lint": "eslint"
10
11
  },
11
12
  "type": "module",
12
13
  "bin": {
13
14
  "openapi-qraft": "./bin.mjs"
14
15
  },
15
16
  "dependencies": {
16
- "ansi-colors": "^4.1.3",
17
- "camelcase": "^8.0.0",
18
- "commander": "^11.1.0",
19
- "micromatch": "^4.0.5",
20
- "openapi-typescript": "7.0.0-next.7",
21
- "ora": "^8.0.1",
22
- "typescript": "^5.3.3",
23
- "yaml": "^2.3.4"
17
+ "@openapi-qraft/openapi-typescript-plugin": "~1.0.1",
18
+ "@openapi-qraft/plugin": "~1.9.0",
19
+ "@openapi-qraft/tanstack-query-react-plugin": "~1.9.0",
20
+ "commander": "^11.1.0"
24
21
  },
25
22
  "devDependencies": {
26
- "@types/micromatch": "^4",
23
+ "@openapi-qraft/eslint-config": "~1.0.0",
27
24
  "@types/node": "^18.19.4",
25
+ "eslint": "^9.0.0",
26
+ "globals": "^15.0.0",
28
27
  "rimraf": "^5.0.5",
28
+ "typescript": "^5.3.3",
29
29
  "vitest": "^1.4.0"
30
30
  },
31
31
  "files": [
32
32
  "dist",
33
- "bin.mjs"
33
+ "src",
34
+ "!dist/**/*.test.*",
35
+ "!dist/**/*.spec.*",
36
+ "!src/**/*.test.*",
37
+ "!src/**/*.spec.*"
34
38
  ],
35
39
  "exports": {
36
40
  "./package.json": "./package.json",
package/src/bin.ts ADDED
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env node
2
+ import { QraftCommand } from '@openapi-qraft/plugin/lib/QraftCommand';
3
+ import type { QraftCommandPlugin } from '@openapi-qraft/plugin/lib/QraftCommandPlugin';
4
+
5
+ import { Option } from 'commander';
6
+ import process from 'node:process';
7
+
8
+ import { builtInPlugins } from './builtInPlugins.js';
9
+
10
+ export async function main() {
11
+ const command = new QraftCommand();
12
+
13
+ const { argv, plugins } = extractArgvPluginOptions(process.argv);
14
+
15
+ if (plugins) {
16
+ await setupPlugins(command, plugins);
17
+ } else {
18
+ // default - setup tanstack-query-react plugin
19
+ await setupPlugins(command, [
20
+ 'tanstack-query-react',
21
+ ] satisfies (keyof typeof builtInPlugins)[]);
22
+
23
+ // option to display help with all available plugins
24
+ command.addOption(
25
+ new Option(
26
+ '--plugin <name_1> --plugin <name_2>',
27
+ `Generator plugins to be used.`
28
+ )
29
+ .choices(Object.keys(builtInPlugins))
30
+ .argParser(() => {
31
+ // Fallback, if plugins parsing went wrong
32
+ throw new Error(
33
+ 'Plugin option must be handled before parsing the command and should not be passed to the commander'
34
+ );
35
+ })
36
+ );
37
+ }
38
+
39
+ return void (await command.parseAsync(argv));
40
+ }
41
+
42
+ async function setupPlugins(command: QraftCommand, plugins: string[]) {
43
+ const pluginList: QraftCommandPlugin[] = [];
44
+
45
+ for (const pluginName of plugins) {
46
+ if (!(pluginName in builtInPlugins))
47
+ throw new Error(`Unknown plugin: '${pluginName}'`);
48
+
49
+ pluginList.push(
50
+ (await builtInPlugins[pluginName as keyof typeof builtInPlugins]())
51
+ .default
52
+ );
53
+
54
+ addCommandUsageWithPlugins(command, plugins);
55
+ }
56
+
57
+ await Promise.all(pluginList.map((plugin) => plugin.setupCommand(command)));
58
+ await Promise.all(
59
+ pluginList.map((plugin) => plugin.postSetupCommand?.(command, plugins))
60
+ );
61
+ }
62
+
63
+ /**
64
+ * Add plugin's usage instructions calling `command.usage(...)`
65
+ */
66
+ function addCommandUsageWithPlugins(command: QraftCommand, plugins: string[]) {
67
+ const pluginUsage = plugins.map((plugin) => `--plugin ${plugin}`).join(' ');
68
+ command.usage(`${pluginUsage} [input] [options]`);
69
+ }
70
+
71
+ /**
72
+ * Extracts multiple `--plugin <name>` options from the `argv`
73
+ * and returns the filtered `argv` and the list of plugins.
74
+ */
75
+ export function extractArgvPluginOptions(argv: string[]) {
76
+ const pluginIndex = argv.indexOf('--plugin');
77
+ if (pluginIndex === -1) return { argv };
78
+
79
+ const filteredArgv: string[] = argv.slice(0, pluginIndex);
80
+ const plugins: string[] = [];
81
+
82
+ for (let i = pluginIndex; i < argv.length; i++) {
83
+ if (argv[i] === '--plugin') {
84
+ const pluginName = argv.at(i + 1);
85
+ if (!pluginName) throw new Error(`Missing plugin name after '--plugin'`);
86
+ if (pluginName?.startsWith('--'))
87
+ throw new Error(`Invalid plugin name: '${pluginName}'`);
88
+ plugins.push(pluginName);
89
+ i++; // Skip next item
90
+ } else {
91
+ filteredArgv.push(argv[i]);
92
+ }
93
+ }
94
+
95
+ return {
96
+ argv: filteredArgv,
97
+ plugins,
98
+ };
99
+ }
@@ -0,0 +1,6 @@
1
+ export const builtInPlugins = {
2
+ 'tanstack-query-react': () =>
3
+ import('@openapi-qraft/tanstack-query-react-plugin'),
4
+ 'openapi-typescript': () =>
5
+ import('@openapi-qraft/openapi-typescript-plugin'),
6
+ } as const;
@@ -1 +0,0 @@
1
- export declare const fileHeader = "/* generated using @openapi-qraft/cli -- do no edit */\n/* istanbul ignore file */\n/* tslint:disable */\n/* eslint-disable */";
@@ -1,5 +0,0 @@
1
- export const fileHeader = `/* generated using @openapi-qraft/cli -- do no edit */
2
- /* istanbul ignore file */
3
- /* tslint:disable */
4
- /* eslint-disable */`;
5
- //# sourceMappingURL=fileHeader.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fileHeader.js","sourceRoot":"","sources":["../../src/lib/fileHeader.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;;;qBAGL,CAAC"}