@acrool/rtk-query-codegen-openapi 0.0.6 → 0.0.9
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 +33 -0
- package/lib/index.d.mts +15 -5
- package/lib/index.d.ts +15 -5
- package/lib/index.js +219 -157
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +219 -157
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/generate.ts +180 -132
- package/src/generators/react-hooks.ts +10 -4
- package/src/index.ts +76 -77
- package/src/types.ts +20 -5
- package/src/utils/downloadSchema.ts +33 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/isQuery.ts +9 -1
package/lib/index.mjs
CHANGED
|
@@ -4,13 +4,13 @@ var getFilename = () => fileURLToPath(import.meta.url);
|
|
|
4
4
|
var __filename = /* @__PURE__ */ getFilename();
|
|
5
5
|
|
|
6
6
|
// src/index.ts
|
|
7
|
-
import
|
|
7
|
+
import fs2 from "node:fs";
|
|
8
8
|
import { createRequire } from "node:module";
|
|
9
|
-
import
|
|
9
|
+
import path4 from "node:path";
|
|
10
10
|
|
|
11
11
|
// src/generate.ts
|
|
12
12
|
import camelCase from "lodash.camelcase";
|
|
13
|
-
import
|
|
13
|
+
import path3 from "node:path";
|
|
14
14
|
import ApiGenerator, {
|
|
15
15
|
getOperationName as _getOperationName,
|
|
16
16
|
getReferenceName,
|
|
@@ -202,16 +202,54 @@ function capitalize(str) {
|
|
|
202
202
|
return str.replace(str[0], str[0].toUpperCase());
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
// src/utils/downloadSchema.ts
|
|
206
|
+
import fs from "node:fs";
|
|
207
|
+
import path from "node:path";
|
|
208
|
+
|
|
209
|
+
// src/utils/isValidUrl.ts
|
|
210
|
+
function isValidUrl(string) {
|
|
211
|
+
try {
|
|
212
|
+
new URL(string);
|
|
213
|
+
} catch (_) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// src/utils/downloadSchema.ts
|
|
220
|
+
async function downloadSchemaFile(remoteFile, targetPath) {
|
|
221
|
+
if (!isValidUrl(remoteFile)) {
|
|
222
|
+
throw new Error(`remoteFile must be a valid URL: ${remoteFile}`);
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
const dir = path.dirname(targetPath);
|
|
226
|
+
if (!fs.existsSync(dir)) {
|
|
227
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
228
|
+
}
|
|
229
|
+
const response = await fetch(remoteFile);
|
|
230
|
+
if (!response.ok) {
|
|
231
|
+
throw new Error(`Failed to download schema from ${remoteFile}: ${response.statusText}`);
|
|
232
|
+
}
|
|
233
|
+
const content = await response.text();
|
|
234
|
+
await fs.promises.writeFile(targetPath, content, "utf-8");
|
|
235
|
+
console.log(`Schema downloaded from ${remoteFile} to ${targetPath}`);
|
|
236
|
+
return targetPath;
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.error(`Error downloading schema from ${remoteFile}:`, error);
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
205
243
|
// src/types.ts
|
|
206
244
|
var operationKeys = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
|
|
207
245
|
|
|
208
246
|
// src/utils/getOperationDefinitions.ts
|
|
209
247
|
function getOperationDefinitions(v3Doc) {
|
|
210
248
|
return Object.entries(v3Doc.paths).flatMap(
|
|
211
|
-
([
|
|
249
|
+
([path5, pathItem]) => !pathItem ? [] : Object.entries(pathItem).filter(
|
|
212
250
|
(arg) => operationKeys.includes(arg[0])
|
|
213
251
|
).map(([verb, operation]) => ({
|
|
214
|
-
path:
|
|
252
|
+
path: path5,
|
|
215
253
|
verb,
|
|
216
254
|
pathItem,
|
|
217
255
|
operation
|
|
@@ -238,25 +276,18 @@ async function getV3Doc(spec, httpResolverOptions) {
|
|
|
238
276
|
}
|
|
239
277
|
|
|
240
278
|
// src/utils/isQuery.ts
|
|
241
|
-
function isQuery(verb, overrides) {
|
|
279
|
+
function isQuery(verb, path5, overrides, queryMatch) {
|
|
280
|
+
if (queryMatch) {
|
|
281
|
+
return queryMatch(verb, path5);
|
|
282
|
+
}
|
|
242
283
|
if (overrides?.type) {
|
|
243
284
|
return overrides.type === "query";
|
|
244
285
|
}
|
|
245
286
|
return verb === "get";
|
|
246
287
|
}
|
|
247
288
|
|
|
248
|
-
// src/utils/isValidUrl.ts
|
|
249
|
-
function isValidUrl(string) {
|
|
250
|
-
try {
|
|
251
|
-
new URL(string);
|
|
252
|
-
} catch (_) {
|
|
253
|
-
return false;
|
|
254
|
-
}
|
|
255
|
-
return true;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
289
|
// src/utils/prettier.ts
|
|
259
|
-
import
|
|
290
|
+
import path2 from "node:path";
|
|
260
291
|
import prettier from "prettier";
|
|
261
292
|
var EXTENSION_TO_PARSER = {
|
|
262
293
|
ts: "typescript",
|
|
@@ -279,7 +310,7 @@ async function prettify(filePath, content, prettierConfigFile) {
|
|
|
279
310
|
let config = null;
|
|
280
311
|
let parser = "typescript";
|
|
281
312
|
if (filePath) {
|
|
282
|
-
const fileExtension =
|
|
313
|
+
const fileExtension = path2.extname(filePath).slice(1);
|
|
283
314
|
parser = EXTENSION_TO_PARSER[fileExtension];
|
|
284
315
|
config = await prettier.resolveConfig(process.cwd(), {
|
|
285
316
|
useCache: true,
|
|
@@ -305,24 +336,26 @@ function removeUndefined(t) {
|
|
|
305
336
|
|
|
306
337
|
// src/generators/react-hooks.ts
|
|
307
338
|
var createBinding = ({
|
|
308
|
-
operationDefinition: { verb, path:
|
|
339
|
+
operationDefinition: { verb, path: path5 },
|
|
309
340
|
overrides,
|
|
310
|
-
isLazy = false
|
|
341
|
+
isLazy = false,
|
|
342
|
+
queryMatch
|
|
311
343
|
}) => factory.createBindingElement(
|
|
312
344
|
void 0,
|
|
313
345
|
void 0,
|
|
314
346
|
factory.createIdentifier(
|
|
315
|
-
`use${isLazy ? "Lazy" : ""}${capitalize(getOperationName(verb,
|
|
347
|
+
`use${isLazy ? "Lazy" : ""}${capitalize(getOperationName(verb, path5, void 0))}${isQuery(verb, path5, overrides, queryMatch) ? "Query" : "Mutation"}`
|
|
316
348
|
),
|
|
317
349
|
void 0
|
|
318
350
|
);
|
|
319
|
-
var getReactHookName = ({ operationDefinition, endpointOverrides, config }) => {
|
|
351
|
+
var getReactHookName = ({ operationDefinition, endpointOverrides, config, queryMatch }) => {
|
|
320
352
|
const overrides = getOverrides(operationDefinition, endpointOverrides);
|
|
321
353
|
const baseParams = {
|
|
322
354
|
operationDefinition,
|
|
323
|
-
overrides
|
|
355
|
+
overrides,
|
|
356
|
+
queryMatch
|
|
324
357
|
};
|
|
325
|
-
const _isQuery = isQuery(operationDefinition.verb, overrides);
|
|
358
|
+
const _isQuery = isQuery(operationDefinition.verb, operationDefinition.path, overrides, queryMatch);
|
|
326
359
|
if (typeof config === "boolean") {
|
|
327
360
|
return createBinding(baseParams);
|
|
328
361
|
}
|
|
@@ -338,14 +371,15 @@ var generateReactHooks = ({
|
|
|
338
371
|
exportName,
|
|
339
372
|
operationDefinitions,
|
|
340
373
|
endpointOverrides,
|
|
341
|
-
config
|
|
374
|
+
config,
|
|
375
|
+
queryMatch
|
|
342
376
|
}) => factory.createVariableStatement(
|
|
343
377
|
[factory.createModifier(ts3.SyntaxKind.ExportKeyword)],
|
|
344
378
|
factory.createVariableDeclarationList(
|
|
345
379
|
[
|
|
346
380
|
factory.createVariableDeclaration(
|
|
347
381
|
factory.createObjectBindingPattern(
|
|
348
|
-
operationDefinitions.map((operationDefinition) => getReactHookName({ operationDefinition, endpointOverrides, config })).flat()
|
|
382
|
+
operationDefinitions.map((operationDefinition) => getReactHookName({ operationDefinition, endpointOverrides, config, queryMatch })).flat()
|
|
349
383
|
),
|
|
350
384
|
void 0,
|
|
351
385
|
void 0,
|
|
@@ -366,8 +400,8 @@ function defaultIsDataResponse(code, includeDefault) {
|
|
|
366
400
|
const parsedCode = Number(code);
|
|
367
401
|
return !Number.isNaN(parsedCode) && parsedCode >= 200 && parsedCode < 300;
|
|
368
402
|
}
|
|
369
|
-
function getOperationName2({ verb, path:
|
|
370
|
-
return _getOperationName(verb,
|
|
403
|
+
function getOperationName2({ verb, path: path5 }) {
|
|
404
|
+
return _getOperationName(verb, path5, void 0);
|
|
371
405
|
}
|
|
372
406
|
function getTags({ verb, pathItem }) {
|
|
373
407
|
return verb ? pathItem[verb]?.tags || [] : [];
|
|
@@ -433,7 +467,9 @@ async function generateApi(spec, {
|
|
|
433
467
|
useEnumType = false,
|
|
434
468
|
mergeReadWriteOnly = false,
|
|
435
469
|
httpResolverOptions,
|
|
436
|
-
sharedTypesFile
|
|
470
|
+
sharedTypesFile,
|
|
471
|
+
queryMatch,
|
|
472
|
+
endpointsQueryReturnTypeFile = "./endpointsQueryReturnType"
|
|
437
473
|
}) {
|
|
438
474
|
const v3Doc = v3DocCache[spec] ??= await getV3Doc(spec, httpResolverOptions);
|
|
439
475
|
const apiGen = new ApiGenerator(v3Doc, {
|
|
@@ -461,8 +497,8 @@ async function generateApi(spec, {
|
|
|
461
497
|
const definedTypeNames = /* @__PURE__ */ new Set();
|
|
462
498
|
const components = v3Doc.components;
|
|
463
499
|
if (components) {
|
|
464
|
-
|
|
465
|
-
const typeEntries = Object.entries(
|
|
500
|
+
if (components.schemas) {
|
|
501
|
+
const typeEntries = Object.entries(components.schemas).map(([name, def]) => {
|
|
466
502
|
addSchemeTypeName(name);
|
|
467
503
|
const typeName = capitalize(camelCase(name));
|
|
468
504
|
definedTypeNames.add(typeName);
|
|
@@ -474,14 +510,15 @@ async function generateApi(spec, {
|
|
|
474
510
|
typeNode
|
|
475
511
|
);
|
|
476
512
|
});
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
513
|
+
allTypeDefinitions.push(
|
|
514
|
+
factory.createModuleDeclaration(
|
|
515
|
+
[factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
|
|
516
|
+
factory.createIdentifier("Scheme"),
|
|
517
|
+
factory.createModuleBlock(typeEntries),
|
|
518
|
+
ts4.NodeFlags.Namespace
|
|
519
|
+
)
|
|
482
520
|
);
|
|
483
|
-
}
|
|
484
|
-
allTypeDefinitions.push(...componentDefinitions);
|
|
521
|
+
}
|
|
485
522
|
}
|
|
486
523
|
const enumEntries = [
|
|
487
524
|
...apiGen.enumAliases.filter((e) => ts4.isEnumDeclaration(e)),
|
|
@@ -574,10 +611,10 @@ async function generateApi(spec, {
|
|
|
574
611
|
}
|
|
575
612
|
}
|
|
576
613
|
}
|
|
577
|
-
const
|
|
578
|
-
const
|
|
579
|
-
const sharedTypesDir =
|
|
580
|
-
await
|
|
614
|
+
const fs3 = await import("node:fs/promises");
|
|
615
|
+
const path5 = await import("node:path");
|
|
616
|
+
const sharedTypesDir = path5.dirname(sharedTypesFile);
|
|
617
|
+
await fs3.mkdir(sharedTypesDir, { recursive: true });
|
|
581
618
|
const output = printer2.printNode(
|
|
582
619
|
ts4.EmitHint.Unspecified,
|
|
583
620
|
factory.createSourceFile(
|
|
@@ -587,7 +624,7 @@ async function generateApi(spec, {
|
|
|
587
624
|
),
|
|
588
625
|
resultFile2
|
|
589
626
|
);
|
|
590
|
-
await
|
|
627
|
+
await fs3.writeFile(sharedTypesFile, output, "utf-8");
|
|
591
628
|
}
|
|
592
629
|
if (apiGen.spec.components?.schemas) {
|
|
593
630
|
apiGen.preprocessComponents(apiGen.spec.components.schemas);
|
|
@@ -612,25 +649,32 @@ async function generateApi(spec, {
|
|
|
612
649
|
return declaration;
|
|
613
650
|
}
|
|
614
651
|
if (outputFile) {
|
|
615
|
-
outputFile =
|
|
652
|
+
outputFile = path3.resolve(process.cwd(), outputFile);
|
|
616
653
|
if (apiFile.startsWith(".")) {
|
|
617
|
-
apiFile =
|
|
654
|
+
apiFile = path3.relative(path3.dirname(outputFile), apiFile);
|
|
618
655
|
apiFile = apiFile.replace(/\\/g, "/");
|
|
619
656
|
if (!apiFile.startsWith(".")) apiFile = `./${apiFile}`;
|
|
620
657
|
}
|
|
658
|
+
if (endpointsQueryReturnTypeFile.startsWith(".")) {
|
|
659
|
+
endpointsQueryReturnTypeFile = path3.relative(path3.dirname(outputFile), endpointsQueryReturnTypeFile);
|
|
660
|
+
endpointsQueryReturnTypeFile = endpointsQueryReturnTypeFile.replace(/\\/g, "/");
|
|
661
|
+
if (!endpointsQueryReturnTypeFile.startsWith(".")) endpointsQueryReturnTypeFile = `./${endpointsQueryReturnTypeFile}`;
|
|
662
|
+
}
|
|
621
663
|
}
|
|
622
664
|
apiFile = apiFile.replace(/\.[jt]sx?$/, "");
|
|
665
|
+
endpointsQueryReturnTypeFile = endpointsQueryReturnTypeFile.replace(/\.[jt]sx?$/, "");
|
|
623
666
|
const sharedTypesImportPath = sharedTypesFile && outputFile ? (() => {
|
|
624
|
-
let rel =
|
|
667
|
+
let rel = path3.relative(path3.dirname(outputFile), sharedTypesFile).replace(/\\/g, "/").replace(/\.[jt]sx?$/, "");
|
|
625
668
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
626
669
|
return rel;
|
|
627
670
|
})() : "./shared-types";
|
|
628
|
-
|
|
671
|
+
const operationNames = [];
|
|
672
|
+
const sourceCode = printer.printNode(
|
|
629
673
|
ts4.EmitHint.Unspecified,
|
|
630
674
|
factory.createSourceFile(
|
|
631
675
|
[
|
|
632
676
|
generateImportNode(apiFile, { [apiImport]: "api" }),
|
|
633
|
-
generateImportNode(
|
|
677
|
+
generateImportNode(endpointsQueryReturnTypeFile, { IRestFulEndpointsQueryReturn: "IRestFulEndpointsQueryReturn" }),
|
|
634
678
|
...sharedTypesFile ? [
|
|
635
679
|
generateImportNode(sharedTypesImportPath, {
|
|
636
680
|
Scheme: "Scheme",
|
|
@@ -641,21 +685,21 @@ async function generateApi(spec, {
|
|
|
641
685
|
generateCreateApiCall({
|
|
642
686
|
tag,
|
|
643
687
|
endpointDefinitions: factory.createObjectLiteralExpression(
|
|
644
|
-
operationDefinitions.map(
|
|
645
|
-
(operationDefinition
|
|
688
|
+
operationDefinitions.map((operationDefinition) => {
|
|
689
|
+
const operationName = getOperationName2({ verb: operationDefinition.verb, path: operationDefinition.path });
|
|
690
|
+
const finalOperationName = operationNameSuffix ? capitalize(operationName + operationNameSuffix) : operationName;
|
|
691
|
+
operationNames.push(finalOperationName);
|
|
692
|
+
return generateEndpoint({
|
|
646
693
|
operationDefinition,
|
|
647
694
|
overrides: getOverrides(operationDefinition, endpointOverrides),
|
|
648
|
-
sharedTypesFile: !!sharedTypesFile
|
|
649
|
-
|
|
650
|
-
|
|
695
|
+
sharedTypesFile: !!sharedTypesFile,
|
|
696
|
+
queryMatch
|
|
697
|
+
});
|
|
698
|
+
}),
|
|
651
699
|
true
|
|
652
700
|
)
|
|
653
701
|
}),
|
|
654
|
-
factory.createExportAssignment(
|
|
655
|
-
void 0,
|
|
656
|
-
void 0,
|
|
657
|
-
factory.createIdentifier(generatedApiName)
|
|
658
|
-
),
|
|
702
|
+
factory.createExportAssignment(void 0, void 0, factory.createIdentifier(generatedApiName)),
|
|
659
703
|
...Object.values(interfaces),
|
|
660
704
|
...sharedTypesFile ? [] : [...apiGen.aliases, ...apiGen.enumAliases],
|
|
661
705
|
...hooks ? [
|
|
@@ -663,7 +707,8 @@ async function generateApi(spec, {
|
|
|
663
707
|
exportName: generatedApiName,
|
|
664
708
|
operationDefinitions,
|
|
665
709
|
endpointOverrides,
|
|
666
|
-
config: hooks
|
|
710
|
+
config: hooks,
|
|
711
|
+
queryMatch
|
|
667
712
|
})
|
|
668
713
|
] : []
|
|
669
714
|
],
|
|
@@ -672,6 +717,10 @@ async function generateApi(spec, {
|
|
|
672
717
|
),
|
|
673
718
|
resultFile
|
|
674
719
|
);
|
|
720
|
+
return {
|
|
721
|
+
sourceCode,
|
|
722
|
+
operationNames
|
|
723
|
+
};
|
|
675
724
|
function extractAllTagTypes({ operationDefinitions: operationDefinitions2 }) {
|
|
676
725
|
const allTagTypes = /* @__PURE__ */ new Set();
|
|
677
726
|
for (const operationDefinition of operationDefinitions2) {
|
|
@@ -685,18 +734,19 @@ async function generateApi(spec, {
|
|
|
685
734
|
function generateEndpoint({
|
|
686
735
|
operationDefinition,
|
|
687
736
|
overrides,
|
|
688
|
-
sharedTypesFile: sharedTypesFile2
|
|
737
|
+
sharedTypesFile: sharedTypesFile2,
|
|
738
|
+
queryMatch: queryMatch2
|
|
689
739
|
}) {
|
|
690
740
|
const {
|
|
691
741
|
verb,
|
|
692
|
-
path:
|
|
742
|
+
path: path5,
|
|
693
743
|
pathItem,
|
|
694
744
|
operation,
|
|
695
745
|
operation: { responses, requestBody }
|
|
696
746
|
} = operationDefinition;
|
|
697
|
-
const operationName = getOperationName2({ verb, path:
|
|
747
|
+
const operationName = getOperationName2({ verb, path: path5 });
|
|
698
748
|
const tags = tag ? getTags({ verb, pathItem }) : [];
|
|
699
|
-
const isQuery2 = isQuery(verb, overrides);
|
|
749
|
+
const isQuery2 = isQuery(verb, path5, overrides, queryMatch2);
|
|
700
750
|
const returnsJson = apiGen.getResponseType(responses) === "json";
|
|
701
751
|
let ResponseType = factory.createKeywordTypeNode(ts4.SyntaxKind.UnknownKeyword);
|
|
702
752
|
if (returnsJson) {
|
|
@@ -758,7 +808,9 @@ async function generateApi(spec, {
|
|
|
758
808
|
origin: "param",
|
|
759
809
|
name,
|
|
760
810
|
originalName: param.name,
|
|
761
|
-
type: wrapWithSchemeIfComponent(
|
|
811
|
+
type: wrapWithSchemeIfComponent(
|
|
812
|
+
apiGen.getTypeFromSchema(isReference(param) ? param : param.schema, void 0, "writeOnly")
|
|
813
|
+
),
|
|
762
814
|
required: param.required,
|
|
763
815
|
param
|
|
764
816
|
};
|
|
@@ -822,10 +874,7 @@ async function generateApi(spec, {
|
|
|
822
874
|
operationName: operationNameSuffix ? capitalize(operationName + operationNameSuffix) : operationName,
|
|
823
875
|
type: isQuery2 ? "query" : "mutation",
|
|
824
876
|
Response: ResponseTypeName,
|
|
825
|
-
QueryArg: factory.createTypeReferenceNode(
|
|
826
|
-
factory.createIdentifier("IRestFulEndpointsQueryReturn"),
|
|
827
|
-
[QueryArg]
|
|
828
|
-
),
|
|
877
|
+
QueryArg: factory.createTypeReferenceNode(factory.createIdentifier("IRestFulEndpointsQueryReturn"), [QueryArg]),
|
|
829
878
|
queryFn: generateQueryFn({
|
|
830
879
|
operationDefinition,
|
|
831
880
|
queryArg,
|
|
@@ -846,10 +895,18 @@ async function generateApi(spec, {
|
|
|
846
895
|
encodePathParams: encodePathParams2,
|
|
847
896
|
encodeQueryParams: encodeQueryParams2
|
|
848
897
|
}) {
|
|
849
|
-
const { path:
|
|
898
|
+
const { path: path5, verb, operation } = operationDefinition;
|
|
850
899
|
const bodyParameter = Object.values(queryArg).find((def) => def.origin === "body");
|
|
851
900
|
const rootObject = factory.createIdentifier("queryArg");
|
|
852
901
|
const variablesObject = factory.createPropertyAccessExpression(rootObject, factory.createIdentifier("variables"));
|
|
902
|
+
function getContentType() {
|
|
903
|
+
if (operation.requestBody) {
|
|
904
|
+
const requestBody = apiGen.resolve(operation.requestBody);
|
|
905
|
+
const contentTypes = Object.keys(requestBody.content || {});
|
|
906
|
+
return contentTypes[0];
|
|
907
|
+
}
|
|
908
|
+
return void 0;
|
|
909
|
+
}
|
|
853
910
|
function pickParams(paramIn) {
|
|
854
911
|
return Object.values(queryArg).filter((def) => def.origin === "param" && def.param.in === paramIn);
|
|
855
912
|
}
|
|
@@ -873,6 +930,7 @@ async function generateApi(spec, {
|
|
|
873
930
|
factory.createObjectLiteralExpression(properties, true)
|
|
874
931
|
);
|
|
875
932
|
}
|
|
933
|
+
const contentType = getContentType();
|
|
876
934
|
return factory.createArrowFunction(
|
|
877
935
|
void 0,
|
|
878
936
|
void 0,
|
|
@@ -884,15 +942,22 @@ async function generateApi(spec, {
|
|
|
884
942
|
[
|
|
885
943
|
factory.createPropertyAssignment(
|
|
886
944
|
factory.createIdentifier("url"),
|
|
887
|
-
generatePathExpression(
|
|
945
|
+
generatePathExpression(path5, pickParams("path"), variablesObject, isFlatArg, encodePathParams2)
|
|
888
946
|
),
|
|
889
947
|
isQuery2 && verb.toUpperCase() === "GET" ? void 0 : factory.createPropertyAssignment(
|
|
890
948
|
factory.createIdentifier("method"),
|
|
891
949
|
factory.createStringLiteral(verb.toUpperCase())
|
|
892
950
|
),
|
|
951
|
+
contentType ? factory.createPropertyAssignment(
|
|
952
|
+
factory.createIdentifier("contentType"),
|
|
953
|
+
factory.createStringLiteral(contentType)
|
|
954
|
+
) : void 0,
|
|
893
955
|
bodyParameter === void 0 ? void 0 : factory.createPropertyAssignment(
|
|
894
956
|
factory.createIdentifier("body"),
|
|
895
|
-
isFlatArg ? variablesObject : factory.createPropertyAccessExpression(
|
|
957
|
+
isFlatArg ? variablesObject : factory.createPropertyAccessExpression(
|
|
958
|
+
variablesObject,
|
|
959
|
+
factory.createIdentifier(bodyParameter.name)
|
|
960
|
+
)
|
|
896
961
|
),
|
|
897
962
|
createObjectLiteralProperty(pickParams("cookie"), "cookies"),
|
|
898
963
|
createObjectLiteralProperty(pickParams("query"), "params"),
|
|
@@ -934,19 +999,13 @@ async function generateApi(spec, {
|
|
|
934
999
|
}));
|
|
935
1000
|
if (isEnumType) {
|
|
936
1001
|
return factory.createTypeReferenceNode(
|
|
937
|
-
factory.createQualifiedName(
|
|
938
|
-
factory.createIdentifier("Enum"),
|
|
939
|
-
typeNode.typeName
|
|
940
|
-
),
|
|
1002
|
+
factory.createQualifiedName(factory.createIdentifier("Enum"), typeNode.typeName),
|
|
941
1003
|
typeNode.typeArguments?.map(wrapWithSchemeIfComponent)
|
|
942
1004
|
);
|
|
943
1005
|
}
|
|
944
1006
|
if (schemeTypeNames.has(typeName)) {
|
|
945
1007
|
return factory.createTypeReferenceNode(
|
|
946
|
-
factory.createQualifiedName(
|
|
947
|
-
factory.createIdentifier("Scheme"),
|
|
948
|
-
typeNode.typeName
|
|
949
|
-
),
|
|
1008
|
+
factory.createQualifiedName(factory.createIdentifier("Scheme"), typeNode.typeName),
|
|
950
1009
|
typeNode.typeArguments?.map(wrapWithSchemeIfComponent)
|
|
951
1010
|
);
|
|
952
1011
|
}
|
|
@@ -1016,12 +1075,12 @@ async function generateApi(spec, {
|
|
|
1016
1075
|
return typeNode;
|
|
1017
1076
|
}
|
|
1018
1077
|
}
|
|
1019
|
-
function generatePathExpression(
|
|
1078
|
+
function generatePathExpression(path5, pathParameters, rootObject, isFlatArg, encodePathParams) {
|
|
1020
1079
|
const expressions = [];
|
|
1021
|
-
const head =
|
|
1080
|
+
const head = path5.replace(/\{(.*?)}(.*?)(?=\{|$)/g, (_, expression, literal) => {
|
|
1022
1081
|
const param = pathParameters.find((p) => p.originalName === expression);
|
|
1023
1082
|
if (!param) {
|
|
1024
|
-
throw new Error(`path parameter ${expression} does not seem to be defined in '${
|
|
1083
|
+
throw new Error(`path parameter ${expression} does not seem to be defined in '${path5}'!`);
|
|
1025
1084
|
}
|
|
1026
1085
|
expressions.push([param.name, literal]);
|
|
1027
1086
|
return "";
|
|
@@ -1045,82 +1104,81 @@ function generatePathExpression(path4, pathParameters, rootObject, isFlatArg, en
|
|
|
1045
1104
|
import camelCase2 from "lodash.camelcase";
|
|
1046
1105
|
var require2 = createRequire(__filename);
|
|
1047
1106
|
async function ensureDirectoryExists(filePath) {
|
|
1048
|
-
const dirname =
|
|
1049
|
-
if (!
|
|
1050
|
-
await
|
|
1107
|
+
const dirname = path4.dirname(filePath);
|
|
1108
|
+
if (!fs2.existsSync(dirname)) {
|
|
1109
|
+
await fs2.promises.mkdir(dirname, { recursive: true });
|
|
1051
1110
|
}
|
|
1052
1111
|
}
|
|
1053
1112
|
function fileExists(filePath) {
|
|
1054
1113
|
try {
|
|
1055
|
-
return
|
|
1114
|
+
return fs2.statSync(filePath).isFile();
|
|
1056
1115
|
} catch {
|
|
1057
1116
|
return false;
|
|
1058
1117
|
}
|
|
1059
1118
|
}
|
|
1060
1119
|
function getApiNameFromDir(dirPath) {
|
|
1061
|
-
const dirName =
|
|
1120
|
+
const dirName = path4.basename(dirPath);
|
|
1062
1121
|
return `${dirName}Api`;
|
|
1063
1122
|
}
|
|
1064
|
-
async function ensureBaseFilesExist(outputDir) {
|
|
1065
|
-
const enhanceEndpointsPath =
|
|
1066
|
-
const indexPath =
|
|
1123
|
+
async function ensureBaseFilesExist(outputDir, operationNames) {
|
|
1124
|
+
const enhanceEndpointsPath = path4.join(outputDir, "enhanceEndpoints.ts");
|
|
1125
|
+
const indexPath = path4.join(outputDir, "index.ts");
|
|
1067
1126
|
const apiName = getApiNameFromDir(outputDir);
|
|
1068
1127
|
if (!fileExists(enhanceEndpointsPath)) {
|
|
1128
|
+
const operationNamesString = operationNames.map((name) => ` ${name}: {},`).join("\n");
|
|
1069
1129
|
const enhanceEndpointsContent = `import api from './query.generated';
|
|
1070
1130
|
|
|
1071
1131
|
const enhancedApi = api.enhanceEndpoints({
|
|
1072
1132
|
endpoints: {
|
|
1133
|
+
${operationNamesString}
|
|
1073
1134
|
},
|
|
1074
1135
|
});
|
|
1075
1136
|
|
|
1076
1137
|
export default enhancedApi;
|
|
1077
1138
|
`;
|
|
1078
|
-
await
|
|
1139
|
+
await fs2.promises.writeFile(enhanceEndpointsPath, enhanceEndpointsContent, "utf-8");
|
|
1079
1140
|
}
|
|
1080
1141
|
if (!fileExists(indexPath)) {
|
|
1081
1142
|
const indexContent = `export * from './query.generated';
|
|
1082
1143
|
export {default as ${apiName}} from './enhanceEndpoints';
|
|
1083
1144
|
`;
|
|
1084
|
-
await
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
function getGroupNameFromPath(path4, pattern) {
|
|
1088
|
-
const match = path4.match(pattern);
|
|
1089
|
-
if (match && match[1]) {
|
|
1090
|
-
return camelCase2(match[1]);
|
|
1145
|
+
await fs2.promises.writeFile(indexPath, indexContent, "utf-8");
|
|
1091
1146
|
}
|
|
1092
|
-
return "common";
|
|
1093
1147
|
}
|
|
1094
1148
|
async function generateEndpoints(options) {
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1149
|
+
let actualSchemaFile = options.schemaFile;
|
|
1150
|
+
if (options.remoteFile) {
|
|
1151
|
+
actualSchemaFile = await downloadSchemaFile(options.remoteFile, options.schemaFile);
|
|
1152
|
+
}
|
|
1153
|
+
const updatedOptions = {
|
|
1154
|
+
...options,
|
|
1155
|
+
schemaFile: actualSchemaFile
|
|
1156
|
+
};
|
|
1157
|
+
const schemaLocation = updatedOptions.schemaFile;
|
|
1158
|
+
const schemaAbsPath = path4.resolve(process.cwd(), schemaLocation);
|
|
1159
|
+
if ("outputFiles" in options) {
|
|
1160
|
+
const { outputFiles, ...commonConfig } = updatedOptions;
|
|
1161
|
+
const openApiDoc = await getV3Doc(actualSchemaFile, updatedOptions.httpResolverOptions);
|
|
1100
1162
|
const paths = Object.keys(openApiDoc.paths);
|
|
1101
|
-
const
|
|
1102
|
-
const
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
const groupedPaths = paths.reduce((acc, path4) => {
|
|
1107
|
-
const groupName = getGroupNameFromPath(path4, pattern);
|
|
1108
|
-
if (!acc[groupName]) {
|
|
1109
|
-
acc[groupName] = [];
|
|
1163
|
+
const { groupKeyMatch, outputDir, filterEndpoint, queryMatch } = outputFiles;
|
|
1164
|
+
const groupedPaths = paths.reduce((acc, path5) => {
|
|
1165
|
+
const groupKey = camelCase2(groupKeyMatch(path5));
|
|
1166
|
+
if (!acc[groupKey]) {
|
|
1167
|
+
acc[groupKey] = [];
|
|
1110
1168
|
}
|
|
1111
|
-
acc[
|
|
1169
|
+
acc[groupKey].push(path5);
|
|
1112
1170
|
return acc;
|
|
1113
1171
|
}, {});
|
|
1114
|
-
for (const [
|
|
1115
|
-
const finalOutputPath =
|
|
1172
|
+
for (const [groupKey, paths2] of Object.entries(groupedPaths)) {
|
|
1173
|
+
const finalOutputPath = `${outputDir}/${groupKey}/query.generated.ts`;
|
|
1116
1174
|
if (filterEndpoint) {
|
|
1117
1175
|
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1118
|
-
const
|
|
1119
|
-
const
|
|
1120
|
-
if (
|
|
1176
|
+
const path5 = operationDefinition.path;
|
|
1177
|
+
const pathGroupKey = camelCase2(groupKeyMatch(path5));
|
|
1178
|
+
if (pathGroupKey !== groupKey) {
|
|
1121
1179
|
return false;
|
|
1122
1180
|
}
|
|
1123
|
-
const endpointFilter = filterEndpoint(
|
|
1181
|
+
const endpointFilter = filterEndpoint(groupKey);
|
|
1124
1182
|
if (endpointFilter instanceof RegExp) {
|
|
1125
1183
|
return endpointFilter.test(operationName);
|
|
1126
1184
|
}
|
|
@@ -1129,45 +1187,49 @@ async function generateEndpoints(options) {
|
|
|
1129
1187
|
const groupOptions = {
|
|
1130
1188
|
...commonConfig,
|
|
1131
1189
|
outputFile: finalOutputPath,
|
|
1132
|
-
|
|
1190
|
+
sharedTypesFile: `${outputDir}/shared-types.ts`,
|
|
1191
|
+
filterEndpoints: pathBasedFilter,
|
|
1192
|
+
queryMatch
|
|
1133
1193
|
};
|
|
1134
1194
|
await generateSingleEndpoint(groupOptions);
|
|
1135
1195
|
} else {
|
|
1136
1196
|
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1137
|
-
const
|
|
1138
|
-
const
|
|
1139
|
-
return
|
|
1197
|
+
const path5 = operationDefinition.path;
|
|
1198
|
+
const pathGroupKey = camelCase2(groupKeyMatch(path5));
|
|
1199
|
+
return pathGroupKey === groupKey;
|
|
1140
1200
|
};
|
|
1141
1201
|
const groupOptions = {
|
|
1142
1202
|
...commonConfig,
|
|
1143
1203
|
outputFile: finalOutputPath,
|
|
1144
|
-
|
|
1204
|
+
sharedTypesFile: `${outputDir}/shared-types.ts`,
|
|
1205
|
+
filterEndpoints: pathBasedFilter,
|
|
1206
|
+
queryMatch
|
|
1145
1207
|
};
|
|
1146
1208
|
await generateSingleEndpoint(groupOptions);
|
|
1147
1209
|
}
|
|
1148
1210
|
}
|
|
1149
1211
|
return;
|
|
1150
1212
|
}
|
|
1151
|
-
await generateSingleEndpoint(
|
|
1213
|
+
await generateSingleEndpoint(updatedOptions);
|
|
1152
1214
|
}
|
|
1153
1215
|
async function generateSingleEndpoint(options) {
|
|
1154
1216
|
const schemaLocation = options.schemaFile;
|
|
1155
|
-
const schemaAbsPath =
|
|
1156
|
-
const
|
|
1217
|
+
const schemaAbsPath = path4.resolve(process.cwd(), schemaLocation);
|
|
1218
|
+
const result = await enforceOazapftsTsVersion(async () => {
|
|
1157
1219
|
return generateApi(schemaAbsPath, options);
|
|
1158
1220
|
});
|
|
1159
1221
|
const { outputFile, prettierConfigFile } = options;
|
|
1160
1222
|
if (outputFile) {
|
|
1161
|
-
const outputPath =
|
|
1223
|
+
const outputPath = path4.resolve(process.cwd(), outputFile);
|
|
1162
1224
|
await ensureDirectoryExists(outputPath);
|
|
1163
|
-
const outputDir =
|
|
1164
|
-
await ensureBaseFilesExist(outputDir);
|
|
1165
|
-
|
|
1225
|
+
const outputDir = path4.dirname(outputPath);
|
|
1226
|
+
await ensureBaseFilesExist(outputDir, result.operationNames);
|
|
1227
|
+
fs2.writeFileSync(
|
|
1166
1228
|
outputPath,
|
|
1167
|
-
await prettify(outputFile, sourceCode, prettierConfigFile)
|
|
1229
|
+
await prettify(outputFile, result.sourceCode, prettierConfigFile)
|
|
1168
1230
|
);
|
|
1169
1231
|
} else {
|
|
1170
|
-
return await prettify(null, sourceCode, prettierConfigFile);
|
|
1232
|
+
return await prettify(null, result.sourceCode, prettierConfigFile);
|
|
1171
1233
|
}
|
|
1172
1234
|
}
|
|
1173
1235
|
function parseConfig(fullConfig) {
|
|
@@ -1175,36 +1237,32 @@ function parseConfig(fullConfig) {
|
|
|
1175
1237
|
if ("outputFiles" in fullConfig) {
|
|
1176
1238
|
const { outputFiles, ...commonConfig } = fullConfig;
|
|
1177
1239
|
let openApiDoc;
|
|
1178
|
-
if (
|
|
1240
|
+
if (fullConfig.remoteFile) {
|
|
1179
1241
|
outFiles.push(fullConfig);
|
|
1180
1242
|
return outFiles;
|
|
1181
1243
|
} else {
|
|
1182
|
-
openApiDoc = JSON.parse(
|
|
1244
|
+
openApiDoc = JSON.parse(fs2.readFileSync(fullConfig.schemaFile, "utf-8"));
|
|
1183
1245
|
}
|
|
1184
1246
|
const paths = Object.keys(openApiDoc.paths);
|
|
1185
|
-
const
|
|
1186
|
-
const
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
const groupedPaths = paths.reduce((acc, path4) => {
|
|
1191
|
-
const groupName = getGroupNameFromPath(path4, pattern);
|
|
1192
|
-
if (!acc[groupName]) {
|
|
1193
|
-
acc[groupName] = [];
|
|
1247
|
+
const { groupKeyMatch, outputDir, filterEndpoint, queryMatch } = outputFiles;
|
|
1248
|
+
const groupedPaths = paths.reduce((acc, path5) => {
|
|
1249
|
+
const groupKey = camelCase2(groupKeyMatch(path5));
|
|
1250
|
+
if (!acc[groupKey]) {
|
|
1251
|
+
acc[groupKey] = [];
|
|
1194
1252
|
}
|
|
1195
|
-
acc[
|
|
1253
|
+
acc[groupKey].push(path5);
|
|
1196
1254
|
return acc;
|
|
1197
1255
|
}, {});
|
|
1198
|
-
Object.entries(groupedPaths).forEach(([
|
|
1199
|
-
const finalOutputPath =
|
|
1256
|
+
Object.entries(groupedPaths).forEach(([groupKey, paths2]) => {
|
|
1257
|
+
const finalOutputPath = `${outputDir}/${groupKey}/query.generated.ts`;
|
|
1200
1258
|
if (filterEndpoint) {
|
|
1201
1259
|
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1202
|
-
const
|
|
1203
|
-
const
|
|
1204
|
-
if (
|
|
1260
|
+
const path5 = operationDefinition.path;
|
|
1261
|
+
const pathGroupKey = camelCase2(groupKeyMatch(path5));
|
|
1262
|
+
if (pathGroupKey !== groupKey) {
|
|
1205
1263
|
return false;
|
|
1206
1264
|
}
|
|
1207
|
-
const endpointFilter = filterEndpoint(
|
|
1265
|
+
const endpointFilter = filterEndpoint(groupKey);
|
|
1208
1266
|
if (endpointFilter instanceof RegExp) {
|
|
1209
1267
|
return endpointFilter.test(operationName);
|
|
1210
1268
|
}
|
|
@@ -1213,18 +1271,22 @@ function parseConfig(fullConfig) {
|
|
|
1213
1271
|
outFiles.push({
|
|
1214
1272
|
...commonConfig,
|
|
1215
1273
|
outputFile: finalOutputPath,
|
|
1216
|
-
|
|
1274
|
+
sharedTypesFile: `${outputDir}/shared-types.ts`,
|
|
1275
|
+
filterEndpoints: pathBasedFilter,
|
|
1276
|
+
queryMatch
|
|
1217
1277
|
});
|
|
1218
1278
|
} else {
|
|
1219
1279
|
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1220
|
-
const
|
|
1221
|
-
const
|
|
1222
|
-
return
|
|
1280
|
+
const path5 = operationDefinition.path;
|
|
1281
|
+
const pathGroupKey = camelCase2(groupKeyMatch(path5));
|
|
1282
|
+
return pathGroupKey === groupKey;
|
|
1223
1283
|
};
|
|
1224
1284
|
outFiles.push({
|
|
1225
1285
|
...commonConfig,
|
|
1226
1286
|
outputFile: finalOutputPath,
|
|
1227
|
-
|
|
1287
|
+
sharedTypesFile: `${outputDir}/shared-types.ts`,
|
|
1288
|
+
filterEndpoints: pathBasedFilter,
|
|
1289
|
+
queryMatch
|
|
1228
1290
|
});
|
|
1229
1291
|
}
|
|
1230
1292
|
});
|