@acrool/rtk-query-codegen-openapi 0.0.7 → 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 +185 -129
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +185 -129
- package/lib/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/generate.ts +33 -8
- 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, {
|
|
@@ -575,10 +611,10 @@ async function generateApi(spec, {
|
|
|
575
611
|
}
|
|
576
612
|
}
|
|
577
613
|
}
|
|
578
|
-
const
|
|
579
|
-
const
|
|
580
|
-
const sharedTypesDir =
|
|
581
|
-
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 });
|
|
582
618
|
const output = printer2.printNode(
|
|
583
619
|
ts4.EmitHint.Unspecified,
|
|
584
620
|
factory.createSourceFile(
|
|
@@ -588,7 +624,7 @@ async function generateApi(spec, {
|
|
|
588
624
|
),
|
|
589
625
|
resultFile2
|
|
590
626
|
);
|
|
591
|
-
await
|
|
627
|
+
await fs3.writeFile(sharedTypesFile, output, "utf-8");
|
|
592
628
|
}
|
|
593
629
|
if (apiGen.spec.components?.schemas) {
|
|
594
630
|
apiGen.preprocessComponents(apiGen.spec.components.schemas);
|
|
@@ -613,25 +649,32 @@ async function generateApi(spec, {
|
|
|
613
649
|
return declaration;
|
|
614
650
|
}
|
|
615
651
|
if (outputFile) {
|
|
616
|
-
outputFile =
|
|
652
|
+
outputFile = path3.resolve(process.cwd(), outputFile);
|
|
617
653
|
if (apiFile.startsWith(".")) {
|
|
618
|
-
apiFile =
|
|
654
|
+
apiFile = path3.relative(path3.dirname(outputFile), apiFile);
|
|
619
655
|
apiFile = apiFile.replace(/\\/g, "/");
|
|
620
656
|
if (!apiFile.startsWith(".")) apiFile = `./${apiFile}`;
|
|
621
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
|
+
}
|
|
622
663
|
}
|
|
623
664
|
apiFile = apiFile.replace(/\.[jt]sx?$/, "");
|
|
665
|
+
endpointsQueryReturnTypeFile = endpointsQueryReturnTypeFile.replace(/\.[jt]sx?$/, "");
|
|
624
666
|
const sharedTypesImportPath = sharedTypesFile && outputFile ? (() => {
|
|
625
|
-
let rel =
|
|
667
|
+
let rel = path3.relative(path3.dirname(outputFile), sharedTypesFile).replace(/\\/g, "/").replace(/\.[jt]sx?$/, "");
|
|
626
668
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
627
669
|
return rel;
|
|
628
670
|
})() : "./shared-types";
|
|
629
|
-
|
|
671
|
+
const operationNames = [];
|
|
672
|
+
const sourceCode = printer.printNode(
|
|
630
673
|
ts4.EmitHint.Unspecified,
|
|
631
674
|
factory.createSourceFile(
|
|
632
675
|
[
|
|
633
676
|
generateImportNode(apiFile, { [apiImport]: "api" }),
|
|
634
|
-
generateImportNode(
|
|
677
|
+
generateImportNode(endpointsQueryReturnTypeFile, { IRestFulEndpointsQueryReturn: "IRestFulEndpointsQueryReturn" }),
|
|
635
678
|
...sharedTypesFile ? [
|
|
636
679
|
generateImportNode(sharedTypesImportPath, {
|
|
637
680
|
Scheme: "Scheme",
|
|
@@ -642,13 +685,17 @@ async function generateApi(spec, {
|
|
|
642
685
|
generateCreateApiCall({
|
|
643
686
|
tag,
|
|
644
687
|
endpointDefinitions: factory.createObjectLiteralExpression(
|
|
645
|
-
operationDefinitions.map(
|
|
646
|
-
(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({
|
|
647
693
|
operationDefinition,
|
|
648
694
|
overrides: getOverrides(operationDefinition, endpointOverrides),
|
|
649
|
-
sharedTypesFile: !!sharedTypesFile
|
|
650
|
-
|
|
651
|
-
|
|
695
|
+
sharedTypesFile: !!sharedTypesFile,
|
|
696
|
+
queryMatch
|
|
697
|
+
});
|
|
698
|
+
}),
|
|
652
699
|
true
|
|
653
700
|
)
|
|
654
701
|
}),
|
|
@@ -660,7 +707,8 @@ async function generateApi(spec, {
|
|
|
660
707
|
exportName: generatedApiName,
|
|
661
708
|
operationDefinitions,
|
|
662
709
|
endpointOverrides,
|
|
663
|
-
config: hooks
|
|
710
|
+
config: hooks,
|
|
711
|
+
queryMatch
|
|
664
712
|
})
|
|
665
713
|
] : []
|
|
666
714
|
],
|
|
@@ -669,6 +717,10 @@ async function generateApi(spec, {
|
|
|
669
717
|
),
|
|
670
718
|
resultFile
|
|
671
719
|
);
|
|
720
|
+
return {
|
|
721
|
+
sourceCode,
|
|
722
|
+
operationNames
|
|
723
|
+
};
|
|
672
724
|
function extractAllTagTypes({ operationDefinitions: operationDefinitions2 }) {
|
|
673
725
|
const allTagTypes = /* @__PURE__ */ new Set();
|
|
674
726
|
for (const operationDefinition of operationDefinitions2) {
|
|
@@ -682,18 +734,19 @@ async function generateApi(spec, {
|
|
|
682
734
|
function generateEndpoint({
|
|
683
735
|
operationDefinition,
|
|
684
736
|
overrides,
|
|
685
|
-
sharedTypesFile: sharedTypesFile2
|
|
737
|
+
sharedTypesFile: sharedTypesFile2,
|
|
738
|
+
queryMatch: queryMatch2
|
|
686
739
|
}) {
|
|
687
740
|
const {
|
|
688
741
|
verb,
|
|
689
|
-
path:
|
|
742
|
+
path: path5,
|
|
690
743
|
pathItem,
|
|
691
744
|
operation,
|
|
692
745
|
operation: { responses, requestBody }
|
|
693
746
|
} = operationDefinition;
|
|
694
|
-
const operationName = getOperationName2({ verb, path:
|
|
747
|
+
const operationName = getOperationName2({ verb, path: path5 });
|
|
695
748
|
const tags = tag ? getTags({ verb, pathItem }) : [];
|
|
696
|
-
const isQuery2 = isQuery(verb, overrides);
|
|
749
|
+
const isQuery2 = isQuery(verb, path5, overrides, queryMatch2);
|
|
697
750
|
const returnsJson = apiGen.getResponseType(responses) === "json";
|
|
698
751
|
let ResponseType = factory.createKeywordTypeNode(ts4.SyntaxKind.UnknownKeyword);
|
|
699
752
|
if (returnsJson) {
|
|
@@ -842,7 +895,7 @@ async function generateApi(spec, {
|
|
|
842
895
|
encodePathParams: encodePathParams2,
|
|
843
896
|
encodeQueryParams: encodeQueryParams2
|
|
844
897
|
}) {
|
|
845
|
-
const { path:
|
|
898
|
+
const { path: path5, verb, operation } = operationDefinition;
|
|
846
899
|
const bodyParameter = Object.values(queryArg).find((def) => def.origin === "body");
|
|
847
900
|
const rootObject = factory.createIdentifier("queryArg");
|
|
848
901
|
const variablesObject = factory.createPropertyAccessExpression(rootObject, factory.createIdentifier("variables"));
|
|
@@ -889,7 +942,7 @@ async function generateApi(spec, {
|
|
|
889
942
|
[
|
|
890
943
|
factory.createPropertyAssignment(
|
|
891
944
|
factory.createIdentifier("url"),
|
|
892
|
-
generatePathExpression(
|
|
945
|
+
generatePathExpression(path5, pickParams("path"), variablesObject, isFlatArg, encodePathParams2)
|
|
893
946
|
),
|
|
894
947
|
isQuery2 && verb.toUpperCase() === "GET" ? void 0 : factory.createPropertyAssignment(
|
|
895
948
|
factory.createIdentifier("method"),
|
|
@@ -1022,12 +1075,12 @@ async function generateApi(spec, {
|
|
|
1022
1075
|
return typeNode;
|
|
1023
1076
|
}
|
|
1024
1077
|
}
|
|
1025
|
-
function generatePathExpression(
|
|
1078
|
+
function generatePathExpression(path5, pathParameters, rootObject, isFlatArg, encodePathParams) {
|
|
1026
1079
|
const expressions = [];
|
|
1027
|
-
const head =
|
|
1080
|
+
const head = path5.replace(/\{(.*?)}(.*?)(?=\{|$)/g, (_, expression, literal) => {
|
|
1028
1081
|
const param = pathParameters.find((p) => p.originalName === expression);
|
|
1029
1082
|
if (!param) {
|
|
1030
|
-
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}'!`);
|
|
1031
1084
|
}
|
|
1032
1085
|
expressions.push([param.name, literal]);
|
|
1033
1086
|
return "";
|
|
@@ -1051,82 +1104,81 @@ function generatePathExpression(path4, pathParameters, rootObject, isFlatArg, en
|
|
|
1051
1104
|
import camelCase2 from "lodash.camelcase";
|
|
1052
1105
|
var require2 = createRequire(__filename);
|
|
1053
1106
|
async function ensureDirectoryExists(filePath) {
|
|
1054
|
-
const dirname =
|
|
1055
|
-
if (!
|
|
1056
|
-
await
|
|
1107
|
+
const dirname = path4.dirname(filePath);
|
|
1108
|
+
if (!fs2.existsSync(dirname)) {
|
|
1109
|
+
await fs2.promises.mkdir(dirname, { recursive: true });
|
|
1057
1110
|
}
|
|
1058
1111
|
}
|
|
1059
1112
|
function fileExists(filePath) {
|
|
1060
1113
|
try {
|
|
1061
|
-
return
|
|
1114
|
+
return fs2.statSync(filePath).isFile();
|
|
1062
1115
|
} catch {
|
|
1063
1116
|
return false;
|
|
1064
1117
|
}
|
|
1065
1118
|
}
|
|
1066
1119
|
function getApiNameFromDir(dirPath) {
|
|
1067
|
-
const dirName =
|
|
1120
|
+
const dirName = path4.basename(dirPath);
|
|
1068
1121
|
return `${dirName}Api`;
|
|
1069
1122
|
}
|
|
1070
|
-
async function ensureBaseFilesExist(outputDir) {
|
|
1071
|
-
const enhanceEndpointsPath =
|
|
1072
|
-
const indexPath =
|
|
1123
|
+
async function ensureBaseFilesExist(outputDir, operationNames) {
|
|
1124
|
+
const enhanceEndpointsPath = path4.join(outputDir, "enhanceEndpoints.ts");
|
|
1125
|
+
const indexPath = path4.join(outputDir, "index.ts");
|
|
1073
1126
|
const apiName = getApiNameFromDir(outputDir);
|
|
1074
1127
|
if (!fileExists(enhanceEndpointsPath)) {
|
|
1128
|
+
const operationNamesString = operationNames.map((name) => ` ${name}: {},`).join("\n");
|
|
1075
1129
|
const enhanceEndpointsContent = `import api from './query.generated';
|
|
1076
1130
|
|
|
1077
1131
|
const enhancedApi = api.enhanceEndpoints({
|
|
1078
1132
|
endpoints: {
|
|
1133
|
+
${operationNamesString}
|
|
1079
1134
|
},
|
|
1080
1135
|
});
|
|
1081
1136
|
|
|
1082
1137
|
export default enhancedApi;
|
|
1083
1138
|
`;
|
|
1084
|
-
await
|
|
1139
|
+
await fs2.promises.writeFile(enhanceEndpointsPath, enhanceEndpointsContent, "utf-8");
|
|
1085
1140
|
}
|
|
1086
1141
|
if (!fileExists(indexPath)) {
|
|
1087
1142
|
const indexContent = `export * from './query.generated';
|
|
1088
1143
|
export {default as ${apiName}} from './enhanceEndpoints';
|
|
1089
1144
|
`;
|
|
1090
|
-
await
|
|
1145
|
+
await fs2.promises.writeFile(indexPath, indexContent, "utf-8");
|
|
1091
1146
|
}
|
|
1092
1147
|
}
|
|
1093
|
-
function getGroupNameFromPath(path4, pattern) {
|
|
1094
|
-
const match = path4.match(pattern);
|
|
1095
|
-
if (match && match[1]) {
|
|
1096
|
-
return camelCase2(match[1]);
|
|
1097
|
-
}
|
|
1098
|
-
return "common";
|
|
1099
|
-
}
|
|
1100
1148
|
async function generateEndpoints(options) {
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
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);
|
|
1106
1162
|
const paths = Object.keys(openApiDoc.paths);
|
|
1107
|
-
const
|
|
1108
|
-
const
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
const groupedPaths = paths.reduce((acc, path4) => {
|
|
1113
|
-
const groupName = getGroupNameFromPath(path4, pattern);
|
|
1114
|
-
if (!acc[groupName]) {
|
|
1115
|
-
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] = [];
|
|
1116
1168
|
}
|
|
1117
|
-
acc[
|
|
1169
|
+
acc[groupKey].push(path5);
|
|
1118
1170
|
return acc;
|
|
1119
1171
|
}, {});
|
|
1120
|
-
for (const [
|
|
1121
|
-
const finalOutputPath =
|
|
1172
|
+
for (const [groupKey, paths2] of Object.entries(groupedPaths)) {
|
|
1173
|
+
const finalOutputPath = `${outputDir}/${groupKey}/query.generated.ts`;
|
|
1122
1174
|
if (filterEndpoint) {
|
|
1123
1175
|
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1124
|
-
const
|
|
1125
|
-
const
|
|
1126
|
-
if (
|
|
1176
|
+
const path5 = operationDefinition.path;
|
|
1177
|
+
const pathGroupKey = camelCase2(groupKeyMatch(path5));
|
|
1178
|
+
if (pathGroupKey !== groupKey) {
|
|
1127
1179
|
return false;
|
|
1128
1180
|
}
|
|
1129
|
-
const endpointFilter = filterEndpoint(
|
|
1181
|
+
const endpointFilter = filterEndpoint(groupKey);
|
|
1130
1182
|
if (endpointFilter instanceof RegExp) {
|
|
1131
1183
|
return endpointFilter.test(operationName);
|
|
1132
1184
|
}
|
|
@@ -1135,45 +1187,49 @@ async function generateEndpoints(options) {
|
|
|
1135
1187
|
const groupOptions = {
|
|
1136
1188
|
...commonConfig,
|
|
1137
1189
|
outputFile: finalOutputPath,
|
|
1138
|
-
|
|
1190
|
+
sharedTypesFile: `${outputDir}/shared-types.ts`,
|
|
1191
|
+
filterEndpoints: pathBasedFilter,
|
|
1192
|
+
queryMatch
|
|
1139
1193
|
};
|
|
1140
1194
|
await generateSingleEndpoint(groupOptions);
|
|
1141
1195
|
} else {
|
|
1142
1196
|
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1143
|
-
const
|
|
1144
|
-
const
|
|
1145
|
-
return
|
|
1197
|
+
const path5 = operationDefinition.path;
|
|
1198
|
+
const pathGroupKey = camelCase2(groupKeyMatch(path5));
|
|
1199
|
+
return pathGroupKey === groupKey;
|
|
1146
1200
|
};
|
|
1147
1201
|
const groupOptions = {
|
|
1148
1202
|
...commonConfig,
|
|
1149
1203
|
outputFile: finalOutputPath,
|
|
1150
|
-
|
|
1204
|
+
sharedTypesFile: `${outputDir}/shared-types.ts`,
|
|
1205
|
+
filterEndpoints: pathBasedFilter,
|
|
1206
|
+
queryMatch
|
|
1151
1207
|
};
|
|
1152
1208
|
await generateSingleEndpoint(groupOptions);
|
|
1153
1209
|
}
|
|
1154
1210
|
}
|
|
1155
1211
|
return;
|
|
1156
1212
|
}
|
|
1157
|
-
await generateSingleEndpoint(
|
|
1213
|
+
await generateSingleEndpoint(updatedOptions);
|
|
1158
1214
|
}
|
|
1159
1215
|
async function generateSingleEndpoint(options) {
|
|
1160
1216
|
const schemaLocation = options.schemaFile;
|
|
1161
|
-
const schemaAbsPath =
|
|
1162
|
-
const
|
|
1217
|
+
const schemaAbsPath = path4.resolve(process.cwd(), schemaLocation);
|
|
1218
|
+
const result = await enforceOazapftsTsVersion(async () => {
|
|
1163
1219
|
return generateApi(schemaAbsPath, options);
|
|
1164
1220
|
});
|
|
1165
1221
|
const { outputFile, prettierConfigFile } = options;
|
|
1166
1222
|
if (outputFile) {
|
|
1167
|
-
const outputPath =
|
|
1223
|
+
const outputPath = path4.resolve(process.cwd(), outputFile);
|
|
1168
1224
|
await ensureDirectoryExists(outputPath);
|
|
1169
|
-
const outputDir =
|
|
1170
|
-
await ensureBaseFilesExist(outputDir);
|
|
1171
|
-
|
|
1225
|
+
const outputDir = path4.dirname(outputPath);
|
|
1226
|
+
await ensureBaseFilesExist(outputDir, result.operationNames);
|
|
1227
|
+
fs2.writeFileSync(
|
|
1172
1228
|
outputPath,
|
|
1173
|
-
await prettify(outputFile, sourceCode, prettierConfigFile)
|
|
1229
|
+
await prettify(outputFile, result.sourceCode, prettierConfigFile)
|
|
1174
1230
|
);
|
|
1175
1231
|
} else {
|
|
1176
|
-
return await prettify(null, sourceCode, prettierConfigFile);
|
|
1232
|
+
return await prettify(null, result.sourceCode, prettierConfigFile);
|
|
1177
1233
|
}
|
|
1178
1234
|
}
|
|
1179
1235
|
function parseConfig(fullConfig) {
|
|
@@ -1181,36 +1237,32 @@ function parseConfig(fullConfig) {
|
|
|
1181
1237
|
if ("outputFiles" in fullConfig) {
|
|
1182
1238
|
const { outputFiles, ...commonConfig } = fullConfig;
|
|
1183
1239
|
let openApiDoc;
|
|
1184
|
-
if (
|
|
1240
|
+
if (fullConfig.remoteFile) {
|
|
1185
1241
|
outFiles.push(fullConfig);
|
|
1186
1242
|
return outFiles;
|
|
1187
1243
|
} else {
|
|
1188
|
-
openApiDoc = JSON.parse(
|
|
1244
|
+
openApiDoc = JSON.parse(fs2.readFileSync(fullConfig.schemaFile, "utf-8"));
|
|
1189
1245
|
}
|
|
1190
1246
|
const paths = Object.keys(openApiDoc.paths);
|
|
1191
|
-
const
|
|
1192
|
-
const
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
const groupedPaths = paths.reduce((acc, path4) => {
|
|
1197
|
-
const groupName = getGroupNameFromPath(path4, pattern);
|
|
1198
|
-
if (!acc[groupName]) {
|
|
1199
|
-
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] = [];
|
|
1200
1252
|
}
|
|
1201
|
-
acc[
|
|
1253
|
+
acc[groupKey].push(path5);
|
|
1202
1254
|
return acc;
|
|
1203
1255
|
}, {});
|
|
1204
|
-
Object.entries(groupedPaths).forEach(([
|
|
1205
|
-
const finalOutputPath =
|
|
1256
|
+
Object.entries(groupedPaths).forEach(([groupKey, paths2]) => {
|
|
1257
|
+
const finalOutputPath = `${outputDir}/${groupKey}/query.generated.ts`;
|
|
1206
1258
|
if (filterEndpoint) {
|
|
1207
1259
|
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1208
|
-
const
|
|
1209
|
-
const
|
|
1210
|
-
if (
|
|
1260
|
+
const path5 = operationDefinition.path;
|
|
1261
|
+
const pathGroupKey = camelCase2(groupKeyMatch(path5));
|
|
1262
|
+
if (pathGroupKey !== groupKey) {
|
|
1211
1263
|
return false;
|
|
1212
1264
|
}
|
|
1213
|
-
const endpointFilter = filterEndpoint(
|
|
1265
|
+
const endpointFilter = filterEndpoint(groupKey);
|
|
1214
1266
|
if (endpointFilter instanceof RegExp) {
|
|
1215
1267
|
return endpointFilter.test(operationName);
|
|
1216
1268
|
}
|
|
@@ -1219,18 +1271,22 @@ function parseConfig(fullConfig) {
|
|
|
1219
1271
|
outFiles.push({
|
|
1220
1272
|
...commonConfig,
|
|
1221
1273
|
outputFile: finalOutputPath,
|
|
1222
|
-
|
|
1274
|
+
sharedTypesFile: `${outputDir}/shared-types.ts`,
|
|
1275
|
+
filterEndpoints: pathBasedFilter,
|
|
1276
|
+
queryMatch
|
|
1223
1277
|
});
|
|
1224
1278
|
} else {
|
|
1225
1279
|
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1226
|
-
const
|
|
1227
|
-
const
|
|
1228
|
-
return
|
|
1280
|
+
const path5 = operationDefinition.path;
|
|
1281
|
+
const pathGroupKey = camelCase2(groupKeyMatch(path5));
|
|
1282
|
+
return pathGroupKey === groupKey;
|
|
1229
1283
|
};
|
|
1230
1284
|
outFiles.push({
|
|
1231
1285
|
...commonConfig,
|
|
1232
1286
|
outputFile: finalOutputPath,
|
|
1233
|
-
|
|
1287
|
+
sharedTypesFile: `${outputDir}/shared-types.ts`,
|
|
1288
|
+
filterEndpoints: pathBasedFilter,
|
|
1289
|
+
queryMatch
|
|
1234
1290
|
});
|
|
1235
1291
|
}
|
|
1236
1292
|
});
|