@acrool/rtk-query-codegen-openapi 0.0.1

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.
package/README.md ADDED
@@ -0,0 +1,20 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/rtk-incubator/rtk-query/main/logo.png" width="400" />
3
+ </p>
4
+ <h2 align="center">
5
+ Code Generator
6
+ </h2>
7
+
8
+ <p align="center">
9
+ <a href="https://discord.gg/0ZcbPKXt5bZ6au5t" target="_blank">
10
+ <img src="https://img.shields.io/badge/chat-online-green" alt="Discord server" />
11
+ </a>
12
+ </p>
13
+
14
+ ### Introduction
15
+
16
+ This is a utility library meant to be used with [RTK Query](https://redux-toolkit.js.org/rtk-query/overview) that will generate a typed API client from an OpenAPI schema.
17
+
18
+ ### Documentation
19
+
20
+ [View the RTK Query Code Generation docs](https://redux-toolkit.js.org/rtk-query/usage/code-generation)
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import{fileURLToPath as l}from"node:url";var p=()=>l(import.meta.url);var c=p();import{generateEndpoints as m,parseConfig as f}from"@acrool/rtk-query-codegen-openapi";import r from"commander";import{createRequire as u}from"node:module";import{dirname as g,resolve as d}from"node:path";var e=u(c),o=!1;try{e.resolve("esbuild")&&e.resolve("esbuild-runner")&&e("esbuild-runner/register"),o=!0}catch{}try{o||(e.resolve("typescript")&&e.resolve("ts-node")&&e("ts-node").register({transpileOnly:!0,compilerOptions:{target:"es6",module:"commonjs"}}),o=!0)}catch{}var h=e("../../package.json");r.version(h.version).usage("</path/to/config.js>").parse(process.argv);var t=r.args[0];r.args.length===0||!/\.([mc]?(jsx?|tsx?)|jsonc?)?$/.test(t)?r.help():(/\.[mc]?tsx?$/.test(t)&&!o&&(console.error("Encountered a TypeScript configfile, but neither esbuild-runner nor ts-node are installed."),process.exit(1)),v(d(process.cwd(),t)));async function v(s){process.chdir(g(s));let n=e(s);for(let i of f(n.default??n))try{console.log(`Generating ${i.outputFile}`),await m(i),console.log("Done")}catch(a){console.error(a),process.exit(1)}}
3
+ //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../node_modules/tsup/assets/esm_shims.js","../../src/bin/cli.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","#!/usr/bin/env node\n\nimport { generateEndpoints, parseConfig } from '@acrool/rtk-query-codegen-openapi';\nimport program from 'commander';\nimport { createRequire } from 'node:module';\nimport { dirname, resolve } from 'node:path';\n\nconst require = createRequire(__filename);\n\nlet ts = false;\ntry {\n if (require.resolve('esbuild') && require.resolve('esbuild-runner')) {\n require('esbuild-runner/register');\n }\n ts = true;\n} catch {}\n\ntry {\n if (!ts) {\n if (require.resolve('typescript') && require.resolve('ts-node')) {\n (require('ts-node') as typeof import('ts-node')).register({\n transpileOnly: true,\n compilerOptions: {\n target: 'es6',\n module: 'commonjs',\n },\n });\n }\n\n ts = true;\n }\n} catch {}\n\n// tslint:disable-next-line\nconst meta = require('../../package.json');\n\nprogram.version(meta.version).usage('</path/to/config.js>').parse(process.argv);\n\nconst configFile = program.args[0];\n\nif (program.args.length === 0 || !/\\.([mc]?(jsx?|tsx?)|jsonc?)?$/.test(configFile)) {\n program.help();\n} else {\n if (/\\.[mc]?tsx?$/.test(configFile) && !ts) {\n console.error('Encountered a TypeScript configfile, but neither esbuild-runner nor ts-node are installed.');\n process.exit(1);\n }\n run(resolve(process.cwd(), configFile));\n}\n\nasync function run(configFile: string) {\n process.chdir(dirname(configFile));\n\n const unparsedConfig = require(configFile);\n\n for (const config of parseConfig(unparsedConfig.default ?? unparsedConfig)) {\n try {\n console.log(`Generating ${config.outputFile}`);\n await generateEndpoints(config);\n console.log(`Done`);\n } catch (err) {\n console.error(err);\n process.exit(1);\n }\n }\n}\n"],"mappings":";AAEA,OAAS,iBAAAA,MAAqB,WAE9B,IAAMC,EAAc,IAAMD,EAAc,YAAY,GAAG,EAIhD,IAAME,EAA6BC,EAAY,ECNtD,OAAS,qBAAAC,EAAmB,eAAAC,MAAmB,oCAC/C,OAAOC,MAAa,YACpB,OAAS,iBAAAC,MAAqB,cAC9B,OAAS,WAAAC,EAAS,WAAAC,MAAe,YAEjC,IAAMC,EAAUH,EAAcI,CAAU,EAEpCC,EAAK,GACT,GAAI,CACEF,EAAQ,QAAQ,SAAS,GAAKA,EAAQ,QAAQ,gBAAgB,GAChEA,EAAQ,yBAAyB,EAEnCE,EAAK,EACP,MAAQ,CAAC,CAET,GAAI,CACGA,IACCF,EAAQ,QAAQ,YAAY,GAAKA,EAAQ,QAAQ,SAAS,GAC3DA,EAAQ,SAAS,EAA+B,SAAS,CACxD,cAAe,GACf,gBAAiB,CACf,OAAQ,MACR,OAAQ,UACV,CACF,CAAC,EAGHE,EAAK,GAET,MAAQ,CAAC,CAGT,IAAMC,EAAOH,EAAQ,oBAAoB,EAEzCJ,EAAQ,QAAQO,EAAK,OAAO,EAAE,MAAM,sBAAsB,EAAE,MAAM,QAAQ,IAAI,EAE9E,IAAMC,EAAaR,EAAQ,KAAK,CAAC,EAE7BA,EAAQ,KAAK,SAAW,GAAK,CAAC,gCAAgC,KAAKQ,CAAU,EAC/ER,EAAQ,KAAK,GAET,eAAe,KAAKQ,CAAU,GAAK,CAACF,IACtC,QAAQ,MAAM,4FAA4F,EAC1G,QAAQ,KAAK,CAAC,GAEhBG,EAAIN,EAAQ,QAAQ,IAAI,EAAGK,CAAU,CAAC,GAGxC,eAAeC,EAAID,EAAoB,CACrC,QAAQ,MAAMN,EAAQM,CAAU,CAAC,EAEjC,IAAME,EAAiBN,EAAQI,CAAU,EAEzC,QAAWG,KAAUZ,EAAYW,EAAe,SAAWA,CAAc,EACvE,GAAI,CACF,QAAQ,IAAI,cAAcC,EAAO,UAAU,EAAE,EAC7C,MAAMb,EAAkBa,CAAM,EAC9B,QAAQ,IAAI,MAAM,CACpB,OAASC,EAAK,CACZ,QAAQ,MAAMA,CAAG,EACjB,QAAQ,KAAK,CAAC,CAChB,CAEJ","names":["fileURLToPath","getFilename","__filename","getFilename","generateEndpoints","parseConfig","program","createRequire","dirname","resolve","require","__filename","ts","meta","configFile","run","unparsedConfig","config","err"]}
@@ -0,0 +1,141 @@
1
+ import SwaggerParser from '@apidevtools/swagger-parser';
2
+ import { OpenAPIV3 } from 'openapi-types';
3
+
4
+ type OperationDefinition = {
5
+ path: string;
6
+ verb: (typeof operationKeys)[number];
7
+ pathItem: OpenAPIV3.PathItemObject;
8
+ operation: OpenAPIV3.OperationObject;
9
+ };
10
+ type ParameterDefinition = OpenAPIV3.ParameterObject;
11
+ type Require<T, K extends keyof T> = {
12
+ [k in K]-?: NonNullable<T[k]>;
13
+ } & Omit<T, K>;
14
+ type Optional<T, K extends keyof T> = {
15
+ [k in K]?: NonNullable<T[k]>;
16
+ } & Omit<T, K>;
17
+ type Id<T> = {
18
+ [K in keyof T]: T[K];
19
+ } & {};
20
+ type AtLeastOneKey<T> = {
21
+ [K in keyof T]-?: Pick<T, K> & Partial<T>;
22
+ }[keyof T];
23
+ declare const operationKeys: readonly ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
24
+ type GenerationOptions = Id<CommonOptions & Optional<OutputFileOptions, 'outputFile'> & {
25
+ isDataResponse?(code: string, includeDefault: boolean, response: OpenAPIV3.ResponseObject, allResponses: OpenAPIV3.ResponsesObject): boolean;
26
+ }>;
27
+ interface CommonOptions {
28
+ apiFile: string;
29
+ /**
30
+ * filename or url
31
+ */
32
+ schemaFile: string;
33
+ /**
34
+ * defaults to "api"
35
+ */
36
+ apiImport?: string;
37
+ /**
38
+ * defaults to "enhancedApi"
39
+ */
40
+ exportName?: string;
41
+ /**
42
+ * defaults to "ApiArg"
43
+ */
44
+ argSuffix?: string;
45
+ /**
46
+ * defaults to "ApiResponse"
47
+ */
48
+ responseSuffix?: string;
49
+ /**
50
+ * defaults to empty
51
+ */
52
+ operationNameSuffix?: string;
53
+ /**
54
+ * defaults to `false`
55
+ * `true` will generate hooks for queries and mutations, but no lazyQueries
56
+ */
57
+ hooks?: boolean | {
58
+ queries: boolean;
59
+ lazyQueries: boolean;
60
+ mutations: boolean;
61
+ };
62
+ /**
63
+ * defaults to false
64
+ * `true` will generate a union type for `undefined` properties like: `{ id?: string | undefined }` instead of `{ id?: string }`
65
+ */
66
+ unionUndefined?: boolean;
67
+ /**
68
+ * defaults to false
69
+ * `true` will result in all generated endpoints having `providesTags`/`invalidatesTags` declarations for the `tags` of their respective operation definition
70
+ * @see https://redux-toolkit.js.org/rtk-query/usage/code-generation for more information
71
+ */
72
+ tag?: boolean;
73
+ /**
74
+ * defaults to false
75
+ * `true` will add `encodeURIComponent` to the generated path parameters
76
+ */
77
+ encodePathParams?: boolean;
78
+ /**
79
+ * defaults to false
80
+ * `true` will add `encodeURIComponent` to the generated query parameters
81
+ */
82
+ encodeQueryParams?: boolean;
83
+ /**
84
+ * defaults to false
85
+ * `true` will "flatten" the arg so that you can do things like `useGetEntityById(1)` instead of `useGetEntityById({ entityId: 1 })`
86
+ */
87
+ flattenArg?: boolean;
88
+ /**
89
+ * default to false
90
+ * If set to `true`, the default response type will be included in the generated code for all endpoints.
91
+ * @see https://swagger.io/docs/specification/describing-responses/#default
92
+ */
93
+ includeDefault?: boolean;
94
+ /**
95
+ * default to false
96
+ * `true` will not generate separate types for read-only and write-only properties.
97
+ */
98
+ mergeReadWriteOnly?: boolean;
99
+ /**
100
+ *
101
+ * HTTPResolverOptions object that is passed to the SwaggerParser bundle function.
102
+ */
103
+ httpResolverOptions?: SwaggerParser.HTTPResolverOptions;
104
+ /**
105
+ * defaults to undefined
106
+ * If present the given file will be used as prettier config when formatting the generated code. If undefined the default prettier config
107
+ * resolution mechanism will be used.
108
+ */
109
+ prettierConfigFile?: string;
110
+ }
111
+ type TextMatcher = string | RegExp | (string | RegExp)[];
112
+ type EndpointMatcherFunction = (operationName: string, operationDefinition: OperationDefinition) => boolean;
113
+ type EndpointMatcher = TextMatcher | EndpointMatcherFunction;
114
+ type ParameterMatcherFunction = (parameterName: string, parameterDefinition: ParameterDefinition) => boolean;
115
+ type ParameterMatcher = TextMatcher | ParameterMatcherFunction;
116
+ interface OutputFileOptions extends Partial<CommonOptions> {
117
+ outputFile: string;
118
+ filterEndpoints?: EndpointMatcher;
119
+ endpointOverrides?: EndpointOverrides[];
120
+ /**
121
+ * defaults to false
122
+ * If passed as true it will generate TS enums instead of union of strings
123
+ */
124
+ useEnumType?: boolean;
125
+ }
126
+ type EndpointOverrides = {
127
+ pattern: EndpointMatcher;
128
+ } & AtLeastOneKey<{
129
+ type: 'mutation' | 'query';
130
+ parameterFilter: ParameterMatcher;
131
+ }>;
132
+ type ConfigFile = Id<Require<CommonOptions & OutputFileOptions, 'outputFile'>> | Id<Omit<CommonOptions, 'outputFile'> & {
133
+ outputFiles: {
134
+ [outputFile: string]: Omit<OutputFileOptions, 'outputFile'>;
135
+ };
136
+ }>;
137
+
138
+ declare function generateEndpoints(options: GenerationOptions): Promise<string | void>;
139
+ declare function parseConfig(fullConfig: ConfigFile): (CommonOptions & OutputFileOptions)[];
140
+
141
+ export { type ConfigFile, generateEndpoints, parseConfig };
package/lib/index.d.ts ADDED
@@ -0,0 +1,141 @@
1
+ import SwaggerParser from '@apidevtools/swagger-parser';
2
+ import { OpenAPIV3 } from 'openapi-types';
3
+
4
+ type OperationDefinition = {
5
+ path: string;
6
+ verb: (typeof operationKeys)[number];
7
+ pathItem: OpenAPIV3.PathItemObject;
8
+ operation: OpenAPIV3.OperationObject;
9
+ };
10
+ type ParameterDefinition = OpenAPIV3.ParameterObject;
11
+ type Require<T, K extends keyof T> = {
12
+ [k in K]-?: NonNullable<T[k]>;
13
+ } & Omit<T, K>;
14
+ type Optional<T, K extends keyof T> = {
15
+ [k in K]?: NonNullable<T[k]>;
16
+ } & Omit<T, K>;
17
+ type Id<T> = {
18
+ [K in keyof T]: T[K];
19
+ } & {};
20
+ type AtLeastOneKey<T> = {
21
+ [K in keyof T]-?: Pick<T, K> & Partial<T>;
22
+ }[keyof T];
23
+ declare const operationKeys: readonly ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
24
+ type GenerationOptions = Id<CommonOptions & Optional<OutputFileOptions, 'outputFile'> & {
25
+ isDataResponse?(code: string, includeDefault: boolean, response: OpenAPIV3.ResponseObject, allResponses: OpenAPIV3.ResponsesObject): boolean;
26
+ }>;
27
+ interface CommonOptions {
28
+ apiFile: string;
29
+ /**
30
+ * filename or url
31
+ */
32
+ schemaFile: string;
33
+ /**
34
+ * defaults to "api"
35
+ */
36
+ apiImport?: string;
37
+ /**
38
+ * defaults to "enhancedApi"
39
+ */
40
+ exportName?: string;
41
+ /**
42
+ * defaults to "ApiArg"
43
+ */
44
+ argSuffix?: string;
45
+ /**
46
+ * defaults to "ApiResponse"
47
+ */
48
+ responseSuffix?: string;
49
+ /**
50
+ * defaults to empty
51
+ */
52
+ operationNameSuffix?: string;
53
+ /**
54
+ * defaults to `false`
55
+ * `true` will generate hooks for queries and mutations, but no lazyQueries
56
+ */
57
+ hooks?: boolean | {
58
+ queries: boolean;
59
+ lazyQueries: boolean;
60
+ mutations: boolean;
61
+ };
62
+ /**
63
+ * defaults to false
64
+ * `true` will generate a union type for `undefined` properties like: `{ id?: string | undefined }` instead of `{ id?: string }`
65
+ */
66
+ unionUndefined?: boolean;
67
+ /**
68
+ * defaults to false
69
+ * `true` will result in all generated endpoints having `providesTags`/`invalidatesTags` declarations for the `tags` of their respective operation definition
70
+ * @see https://redux-toolkit.js.org/rtk-query/usage/code-generation for more information
71
+ */
72
+ tag?: boolean;
73
+ /**
74
+ * defaults to false
75
+ * `true` will add `encodeURIComponent` to the generated path parameters
76
+ */
77
+ encodePathParams?: boolean;
78
+ /**
79
+ * defaults to false
80
+ * `true` will add `encodeURIComponent` to the generated query parameters
81
+ */
82
+ encodeQueryParams?: boolean;
83
+ /**
84
+ * defaults to false
85
+ * `true` will "flatten" the arg so that you can do things like `useGetEntityById(1)` instead of `useGetEntityById({ entityId: 1 })`
86
+ */
87
+ flattenArg?: boolean;
88
+ /**
89
+ * default to false
90
+ * If set to `true`, the default response type will be included in the generated code for all endpoints.
91
+ * @see https://swagger.io/docs/specification/describing-responses/#default
92
+ */
93
+ includeDefault?: boolean;
94
+ /**
95
+ * default to false
96
+ * `true` will not generate separate types for read-only and write-only properties.
97
+ */
98
+ mergeReadWriteOnly?: boolean;
99
+ /**
100
+ *
101
+ * HTTPResolverOptions object that is passed to the SwaggerParser bundle function.
102
+ */
103
+ httpResolverOptions?: SwaggerParser.HTTPResolverOptions;
104
+ /**
105
+ * defaults to undefined
106
+ * If present the given file will be used as prettier config when formatting the generated code. If undefined the default prettier config
107
+ * resolution mechanism will be used.
108
+ */
109
+ prettierConfigFile?: string;
110
+ }
111
+ type TextMatcher = string | RegExp | (string | RegExp)[];
112
+ type EndpointMatcherFunction = (operationName: string, operationDefinition: OperationDefinition) => boolean;
113
+ type EndpointMatcher = TextMatcher | EndpointMatcherFunction;
114
+ type ParameterMatcherFunction = (parameterName: string, parameterDefinition: ParameterDefinition) => boolean;
115
+ type ParameterMatcher = TextMatcher | ParameterMatcherFunction;
116
+ interface OutputFileOptions extends Partial<CommonOptions> {
117
+ outputFile: string;
118
+ filterEndpoints?: EndpointMatcher;
119
+ endpointOverrides?: EndpointOverrides[];
120
+ /**
121
+ * defaults to false
122
+ * If passed as true it will generate TS enums instead of union of strings
123
+ */
124
+ useEnumType?: boolean;
125
+ }
126
+ type EndpointOverrides = {
127
+ pattern: EndpointMatcher;
128
+ } & AtLeastOneKey<{
129
+ type: 'mutation' | 'query';
130
+ parameterFilter: ParameterMatcher;
131
+ }>;
132
+ type ConfigFile = Id<Require<CommonOptions & OutputFileOptions, 'outputFile'>> | Id<Omit<CommonOptions, 'outputFile'> & {
133
+ outputFiles: {
134
+ [outputFile: string]: Omit<OutputFileOptions, 'outputFile'>;
135
+ };
136
+ }>;
137
+
138
+ declare function generateEndpoints(options: GenerationOptions): Promise<string | void>;
139
+ declare function parseConfig(fullConfig: ConfigFile): (CommonOptions & OutputFileOptions)[];
140
+
141
+ export { type ConfigFile, generateEndpoints, parseConfig };