@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/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, {
@@ -575,10 +611,10 @@ async function generateApi(spec, {
575
611
  }
576
612
  }
577
613
  }
578
- const fs2 = await import("node:fs/promises");
579
- const path4 = await import("node:path");
580
- const sharedTypesDir = path4.dirname(sharedTypesFile);
581
- 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 });
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 fs2.writeFile(sharedTypesFile, output, "utf-8");
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 = path2.resolve(process.cwd(), outputFile);
652
+ outputFile = path3.resolve(process.cwd(), outputFile);
617
653
  if (apiFile.startsWith(".")) {
618
- apiFile = path2.relative(path2.dirname(outputFile), 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 = 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?$/, "");
626
668
  if (!rel.startsWith(".")) rel = "./" + rel;
627
669
  return rel;
628
670
  })() : "./shared-types";
629
- return printer.printNode(
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("@acrool/react-fetcher", { IRestFulEndpointsQueryReturn: "IRestFulEndpointsQueryReturn" }),
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) => 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({
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: path4,
742
+ path: path5,
690
743
  pathItem,
691
744
  operation,
692
745
  operation: { responses, requestBody }
693
746
  } = operationDefinition;
694
- const operationName = getOperationName2({ verb, path: path4 });
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: path4, verb, operation } = operationDefinition;
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(path4, pickParams("path"), variablesObject, isFlatArg, encodePathParams2)
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(path4, pathParameters, rootObject, isFlatArg, encodePathParams) {
1078
+ function generatePathExpression(path5, pathParameters, rootObject, isFlatArg, encodePathParams) {
1026
1079
  const expressions = [];
1027
- const head = path4.replace(/\{(.*?)}(.*?)(?=\{|$)/g, (_, expression, literal) => {
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 '${path4}'!`);
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 = path3.dirname(filePath);
1055
- if (!fs.existsSync(dirname)) {
1056
- 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 });
1057
1110
  }
1058
1111
  }
1059
1112
  function fileExists(filePath) {
1060
1113
  try {
1061
- return fs.statSync(filePath).isFile();
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 = path3.basename(dirPath);
1120
+ const dirName = path4.basename(dirPath);
1068
1121
  return `${dirName}Api`;
1069
1122
  }
1070
- async function ensureBaseFilesExist(outputDir) {
1071
- const enhanceEndpointsPath = path3.join(outputDir, "enhanceEndpoints.ts");
1072
- 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");
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 fs.promises.writeFile(enhanceEndpointsPath, enhanceEndpointsContent, "utf-8");
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 fs.promises.writeFile(indexPath, indexContent, "utf-8");
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
- const schemaLocation = options.schemaFile;
1102
- const schemaAbsPath = isValidUrl(options.schemaFile) ? options.schemaFile : path3.resolve(process.cwd(), schemaLocation);
1103
- if (isValidUrl(options.schemaFile) && "outputFiles" in options) {
1104
- const { outputFiles, ...commonConfig } = options;
1105
- 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);
1106
1162
  const paths = Object.keys(openApiDoc.paths);
1107
- const outputFilesEntries = Object.entries(outputFiles);
1108
- const [outputPath, config] = outputFilesEntries[0];
1109
- const patterns = config.groupMatch;
1110
- const filterEndpoint = config.filterEndpoint;
1111
- const pattern = patterns;
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[groupName].push(path4);
1169
+ acc[groupKey].push(path5);
1118
1170
  return acc;
1119
1171
  }, {});
1120
- for (const [groupName, paths2] of Object.entries(groupedPaths)) {
1121
- const finalOutputPath = outputPath.replace("$1", groupName);
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 path4 = operationDefinition.path;
1125
- const pathGroupName = getGroupNameFromPath(path4, pattern);
1126
- if (pathGroupName !== groupName) {
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(groupName);
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
- filterEndpoints: pathBasedFilter
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 path4 = operationDefinition.path;
1144
- const pathGroupName = getGroupNameFromPath(path4, pattern);
1145
- return pathGroupName === groupName;
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
- filterEndpoints: pathBasedFilter
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(options);
1213
+ await generateSingleEndpoint(updatedOptions);
1158
1214
  }
1159
1215
  async function generateSingleEndpoint(options) {
1160
1216
  const schemaLocation = options.schemaFile;
1161
- const schemaAbsPath = isValidUrl(options.schemaFile) ? options.schemaFile : path3.resolve(process.cwd(), schemaLocation);
1162
- const sourceCode = await enforceOazapftsTsVersion(async () => {
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 = path3.resolve(process.cwd(), outputFile);
1223
+ const outputPath = path4.resolve(process.cwd(), outputFile);
1168
1224
  await ensureDirectoryExists(outputPath);
1169
- const outputDir = path3.dirname(outputPath);
1170
- await ensureBaseFilesExist(outputDir);
1171
- fs.writeFileSync(
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 (isValidUrl(fullConfig.schemaFile)) {
1240
+ if (fullConfig.remoteFile) {
1185
1241
  outFiles.push(fullConfig);
1186
1242
  return outFiles;
1187
1243
  } else {
1188
- openApiDoc = JSON.parse(fs.readFileSync(fullConfig.schemaFile, "utf-8"));
1244
+ openApiDoc = JSON.parse(fs2.readFileSync(fullConfig.schemaFile, "utf-8"));
1189
1245
  }
1190
1246
  const paths = Object.keys(openApiDoc.paths);
1191
- const outputFilesEntries = Object.entries(outputFiles);
1192
- const [outputPath, config] = outputFilesEntries[0];
1193
- const patterns = config.groupMatch;
1194
- const filterEndpoint = config.filterEndpoint;
1195
- const pattern = patterns;
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[groupName].push(path4);
1253
+ acc[groupKey].push(path5);
1202
1254
  return acc;
1203
1255
  }, {});
1204
- Object.entries(groupedPaths).forEach(([groupName, paths2]) => {
1205
- const finalOutputPath = outputPath.replace("$1", groupName);
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 path4 = operationDefinition.path;
1209
- const pathGroupName = getGroupNameFromPath(path4, pattern);
1210
- if (pathGroupName !== groupName) {
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(groupName);
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
- filterEndpoints: pathBasedFilter
1274
+ sharedTypesFile: `${outputDir}/shared-types.ts`,
1275
+ filterEndpoints: pathBasedFilter,
1276
+ queryMatch
1223
1277
  });
1224
1278
  } else {
1225
1279
  const pathBasedFilter = (operationName, operationDefinition) => {
1226
- const path4 = operationDefinition.path;
1227
- const pathGroupName = getGroupNameFromPath(path4, pattern);
1228
- return pathGroupName === groupName;
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
- filterEndpoints: pathBasedFilter
1287
+ sharedTypesFile: `${outputDir}/shared-types.ts`,
1288
+ filterEndpoints: pathBasedFilter,
1289
+ queryMatch
1234
1290
  });
1235
1291
  }
1236
1292
  });