@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/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 fs from "node:fs";
7
+ import fs2 from "node:fs";
8
8
  import { createRequire } from "node:module";
9
- import path3 from "node:path";
9
+ import path4 from "node:path";
10
10
 
11
11
  // src/generate.ts
12
12
  import camelCase from "lodash.camelcase";
13
- import path2 from "node:path";
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
- ([path4, pathItem]) => !pathItem ? [] : Object.entries(pathItem).filter(
249
+ ([path5, pathItem]) => !pathItem ? [] : Object.entries(pathItem).filter(
212
250
  (arg) => operationKeys.includes(arg[0])
213
251
  ).map(([verb, operation]) => ({
214
- path: path4,
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 path from "node:path";
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 = path.extname(filePath).slice(1);
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: path4 },
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, path4, void 0))}${isQuery(verb, overrides) ? "Query" : "Mutation"}`
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: path4 }) {
370
- return _getOperationName(verb, path4, void 0);
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
- const componentDefinitions = Object.entries(components).map(([componentType, componentDefs]) => {
465
- const typeEntries = Object.entries(componentDefs).map(([name, def]) => {
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
- return factory.createModuleDeclaration(
478
- [factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
479
- factory.createIdentifier("Scheme"),
480
- factory.createModuleBlock(typeEntries),
481
- ts4.NodeFlags.Namespace
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 fs2 = await import("node:fs/promises");
578
- const path4 = await import("node:path");
579
- const sharedTypesDir = path4.dirname(sharedTypesFile);
580
- await fs2.mkdir(sharedTypesDir, { recursive: true });
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 fs2.writeFile(sharedTypesFile, output, "utf-8");
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 = path2.resolve(process.cwd(), outputFile);
652
+ outputFile = path3.resolve(process.cwd(), outputFile);
616
653
  if (apiFile.startsWith(".")) {
617
- apiFile = path2.relative(path2.dirname(outputFile), 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 = path2.relative(path2.dirname(outputFile), sharedTypesFile).replace(/\\/g, "/").replace(/\.[jt]sx?$/, "");
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
- return printer.printNode(
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("@acrool/react-fetcher", { IRestFulEndpointsQueryReturn: "IRestFulEndpointsQueryReturn" }),
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) => generateEndpoint({
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: path4,
742
+ path: path5,
693
743
  pathItem,
694
744
  operation,
695
745
  operation: { responses, requestBody }
696
746
  } = operationDefinition;
697
- const operationName = getOperationName2({ verb, path: path4 });
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(apiGen.getTypeFromSchema(isReference(param) ? param : param.schema, void 0, "writeOnly")),
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: path4, verb } = operationDefinition;
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(path4, pickParams("path"), variablesObject, isFlatArg, encodePathParams2)
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(variablesObject, factory.createIdentifier(bodyParameter.name))
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(path4, pathParameters, rootObject, isFlatArg, encodePathParams) {
1078
+ function generatePathExpression(path5, pathParameters, rootObject, isFlatArg, encodePathParams) {
1020
1079
  const expressions = [];
1021
- const head = path4.replace(/\{(.*?)}(.*?)(?=\{|$)/g, (_, expression, literal) => {
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 '${path4}'!`);
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 = path3.dirname(filePath);
1049
- if (!fs.existsSync(dirname)) {
1050
- await fs.promises.mkdir(dirname, { recursive: true });
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 fs.statSync(filePath).isFile();
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 = path3.basename(dirPath);
1120
+ const dirName = path4.basename(dirPath);
1062
1121
  return `${dirName}Api`;
1063
1122
  }
1064
- async function ensureBaseFilesExist(outputDir) {
1065
- const enhanceEndpointsPath = path3.join(outputDir, "enhanceEndpoints.ts");
1066
- const indexPath = path3.join(outputDir, "index.ts");
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 fs.promises.writeFile(enhanceEndpointsPath, enhanceEndpointsContent, "utf-8");
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 fs.promises.writeFile(indexPath, indexContent, "utf-8");
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
- const schemaLocation = options.schemaFile;
1096
- const schemaAbsPath = isValidUrl(options.schemaFile) ? options.schemaFile : path3.resolve(process.cwd(), schemaLocation);
1097
- if (isValidUrl(options.schemaFile) && "outputFiles" in options) {
1098
- const { outputFiles, ...commonConfig } = options;
1099
- const openApiDoc = await getV3Doc(options.schemaFile, options.httpResolverOptions);
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 outputFilesEntries = Object.entries(outputFiles);
1102
- const [outputPath, config] = outputFilesEntries[0];
1103
- const patterns = config.groupMatch;
1104
- const filterEndpoint = config.filterEndpoint;
1105
- const pattern = patterns;
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[groupName].push(path4);
1169
+ acc[groupKey].push(path5);
1112
1170
  return acc;
1113
1171
  }, {});
1114
- for (const [groupName, paths2] of Object.entries(groupedPaths)) {
1115
- const finalOutputPath = outputPath.replace("$1", groupName);
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 path4 = operationDefinition.path;
1119
- const pathGroupName = getGroupNameFromPath(path4, pattern);
1120
- if (pathGroupName !== groupName) {
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(groupName);
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
- filterEndpoints: pathBasedFilter
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 path4 = operationDefinition.path;
1138
- const pathGroupName = getGroupNameFromPath(path4, pattern);
1139
- return pathGroupName === groupName;
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
- filterEndpoints: pathBasedFilter
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(options);
1213
+ await generateSingleEndpoint(updatedOptions);
1152
1214
  }
1153
1215
  async function generateSingleEndpoint(options) {
1154
1216
  const schemaLocation = options.schemaFile;
1155
- const schemaAbsPath = isValidUrl(options.schemaFile) ? options.schemaFile : path3.resolve(process.cwd(), schemaLocation);
1156
- const sourceCode = await enforceOazapftsTsVersion(async () => {
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 = path3.resolve(process.cwd(), outputFile);
1223
+ const outputPath = path4.resolve(process.cwd(), outputFile);
1162
1224
  await ensureDirectoryExists(outputPath);
1163
- const outputDir = path3.dirname(outputPath);
1164
- await ensureBaseFilesExist(outputDir);
1165
- fs.writeFileSync(
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 (isValidUrl(fullConfig.schemaFile)) {
1240
+ if (fullConfig.remoteFile) {
1179
1241
  outFiles.push(fullConfig);
1180
1242
  return outFiles;
1181
1243
  } else {
1182
- openApiDoc = JSON.parse(fs.readFileSync(fullConfig.schemaFile, "utf-8"));
1244
+ openApiDoc = JSON.parse(fs2.readFileSync(fullConfig.schemaFile, "utf-8"));
1183
1245
  }
1184
1246
  const paths = Object.keys(openApiDoc.paths);
1185
- const outputFilesEntries = Object.entries(outputFiles);
1186
- const [outputPath, config] = outputFilesEntries[0];
1187
- const patterns = config.groupMatch;
1188
- const filterEndpoint = config.filterEndpoint;
1189
- const pattern = patterns;
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[groupName].push(path4);
1253
+ acc[groupKey].push(path5);
1196
1254
  return acc;
1197
1255
  }, {});
1198
- Object.entries(groupedPaths).forEach(([groupName, paths2]) => {
1199
- const finalOutputPath = outputPath.replace("$1", groupName);
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 path4 = operationDefinition.path;
1203
- const pathGroupName = getGroupNameFromPath(path4, pattern);
1204
- if (pathGroupName !== groupName) {
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(groupName);
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
- filterEndpoints: pathBasedFilter
1274
+ sharedTypesFile: `${outputDir}/shared-types.ts`,
1275
+ filterEndpoints: pathBasedFilter,
1276
+ queryMatch
1217
1277
  });
1218
1278
  } else {
1219
1279
  const pathBasedFilter = (operationName, operationDefinition) => {
1220
- const path4 = operationDefinition.path;
1221
- const pathGroupName = getGroupNameFromPath(path4, pattern);
1222
- return pathGroupName === groupName;
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
- filterEndpoints: pathBasedFilter
1287
+ sharedTypesFile: `${outputDir}/shared-types.ts`,
1288
+ filterEndpoints: pathBasedFilter,
1289
+ queryMatch
1228
1290
  });
1229
1291
  }
1230
1292
  });