@acrool/rtk-query-codegen-openapi 0.0.2-test.5 → 0.0.2-test.7

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
@@ -305,14 +305,14 @@ function removeUndefined(t) {
305
305
 
306
306
  // src/generators/react-hooks.ts
307
307
  var createBinding = ({
308
- operationDefinition: { verb, path: path4, operation },
308
+ operationDefinition: { verb, path: path4 },
309
309
  overrides,
310
310
  isLazy = false
311
311
  }) => factory.createBindingElement(
312
312
  void 0,
313
313
  void 0,
314
314
  factory.createIdentifier(
315
- `use${isLazy ? "Lazy" : ""}${capitalize(getOperationName(verb, path4, operation.operationId))}${isQuery(verb, overrides) ? "Query" : "Mutation"}`
315
+ `use${isLazy ? "Lazy" : ""}${capitalize(getOperationName(verb, path4, void 0))}${isQuery(verb, overrides) ? "Query" : "Mutation"}`
316
316
  ),
317
317
  void 0
318
318
  );
@@ -366,8 +366,8 @@ function defaultIsDataResponse(code, includeDefault) {
366
366
  const parsedCode = Number(code);
367
367
  return !Number.isNaN(parsedCode) && parsedCode >= 200 && parsedCode < 300;
368
368
  }
369
- function getOperationName2({ verb, path: path4, operation }) {
370
- return _getOperationName(verb, path4, operation.operationId);
369
+ function getOperationName2({ verb, path: path4 }) {
370
+ return _getOperationName(verb, path4, void 0);
371
371
  }
372
372
  function getTags({ verb, pathItem }) {
373
373
  return verb ? pathItem[verb]?.tags || [] : [];
@@ -432,7 +432,8 @@ async function generateApi(spec, {
432
432
  includeDefault = false,
433
433
  useEnumType = false,
434
434
  mergeReadWriteOnly = false,
435
- httpResolverOptions
435
+ httpResolverOptions,
436
+ sharedTypesFile
436
437
  }) {
437
438
  const v3Doc = v3DocCache[spec] ??= await getV3Doc(spec, httpResolverOptions);
438
439
  const apiGen = new ApiGenerator(v3Doc, {
@@ -440,6 +441,62 @@ async function generateApi(spec, {
440
441
  useEnumType,
441
442
  mergeReadWriteOnly
442
443
  });
444
+ const schemeTypeNames = /* @__PURE__ */ new Set();
445
+ function addSchemeTypeName(name) {
446
+ schemeTypeNames.add(name);
447
+ schemeTypeNames.add(camelCase(name));
448
+ schemeTypeNames.add(capitalize(camelCase(name)));
449
+ }
450
+ if (sharedTypesFile) {
451
+ const resultFile2 = ts4.createSourceFile(
452
+ "sharedTypes.ts",
453
+ "",
454
+ ts4.ScriptTarget.Latest,
455
+ /*setParentNodes*/
456
+ false,
457
+ ts4.ScriptKind.TS
458
+ );
459
+ const printer2 = ts4.createPrinter({ newLine: ts4.NewLineKind.LineFeed });
460
+ const allTypeDefinitions = [];
461
+ const components = v3Doc.components;
462
+ if (components) {
463
+ const componentDefinitions = Object.entries(components).map(([componentType, componentDefs]) => {
464
+ const typeEntries = Object.entries(componentDefs).map(([name, def]) => {
465
+ addSchemeTypeName(name);
466
+ const typeName = capitalize(camelCase(name));
467
+ const typeNode = wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(def));
468
+ return factory.createTypeAliasDeclaration(
469
+ [factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
470
+ factory.createIdentifier(typeName),
471
+ void 0,
472
+ typeNode
473
+ );
474
+ });
475
+ return factory.createModuleDeclaration(
476
+ [factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
477
+ factory.createIdentifier("Scheme"),
478
+ factory.createModuleBlock(typeEntries),
479
+ ts4.NodeFlags.Namespace
480
+ );
481
+ });
482
+ allTypeDefinitions.push(...componentDefinitions);
483
+ }
484
+ if (useEnumType) {
485
+ allTypeDefinitions.push(...apiGen.enumAliases);
486
+ }
487
+ allTypeDefinitions.push(...apiGen.aliases);
488
+ const output = printer2.printNode(
489
+ ts4.EmitHint.Unspecified,
490
+ factory.createSourceFile(
491
+ allTypeDefinitions,
492
+ factory.createToken(ts4.SyntaxKind.EndOfFileToken),
493
+ ts4.NodeFlags.None
494
+ ),
495
+ resultFile2
496
+ );
497
+ const fs2 = await import("node:fs/promises");
498
+ await fs2.writeFile(sharedTypesFile, output, "utf-8");
499
+ }
443
500
  if (apiGen.spec.components?.schemas) {
444
501
  apiGen.preprocessComponents(apiGen.spec.components.schemas);
445
502
  }
@@ -471,12 +528,18 @@ async function generateApi(spec, {
471
528
  }
472
529
  }
473
530
  apiFile = apiFile.replace(/\.[jt]sx?$/, "");
531
+ const sharedTypesImportPath = sharedTypesFile && outputFile ? (() => {
532
+ let rel = path2.relative(path2.dirname(outputFile), sharedTypesFile).replace(/\\/g, "/").replace(/\.[jt]sx?$/, "");
533
+ if (!rel.startsWith(".")) rel = "./" + rel;
534
+ return rel;
535
+ })() : "./shared-types";
474
536
  return printer.printNode(
475
537
  ts4.EmitHint.Unspecified,
476
538
  factory.createSourceFile(
477
539
  [
478
540
  generateImportNode(apiFile, { [apiImport]: "api" }),
479
541
  generateImportNode("@acrool/react-fetcher", { IRestFulEndpointsQueryReturn: "IRestFulEndpointsQueryReturn" }),
542
+ ...sharedTypesFile ? [generateImportNode(sharedTypesImportPath, { Scheme: "Scheme" })] : [],
480
543
  ...tag ? [generateTagTypes({ addTagTypes: extractAllTagTypes({ operationDefinitions }) })] : [],
481
544
  generateCreateApiCall({
482
545
  tag,
@@ -484,7 +547,8 @@ async function generateApi(spec, {
484
547
  operationDefinitions.map(
485
548
  (operationDefinition) => generateEndpoint({
486
549
  operationDefinition,
487
- overrides: getOverrides(operationDefinition, endpointOverrides)
550
+ overrides: getOverrides(operationDefinition, endpointOverrides),
551
+ sharedTypesFile: !!sharedTypesFile
488
552
  })
489
553
  ),
490
554
  true
@@ -496,8 +560,7 @@ async function generateApi(spec, {
496
560
  factory.createIdentifier(generatedApiName)
497
561
  ),
498
562
  ...Object.values(interfaces),
499
- ...apiGen.aliases,
500
- ...apiGen.enumAliases,
563
+ ...sharedTypesFile ? [] : [...apiGen.aliases, ...apiGen.enumAliases],
501
564
  ...hooks ? [
502
565
  generateReactHooks({
503
566
  exportName: generatedApiName,
@@ -524,7 +587,8 @@ async function generateApi(spec, {
524
587
  }
525
588
  function generateEndpoint({
526
589
  operationDefinition,
527
- overrides
590
+ overrides,
591
+ sharedTypesFile: sharedTypesFile2
528
592
  }) {
529
593
  const {
530
594
  verb,
@@ -533,7 +597,7 @@ async function generateApi(spec, {
533
597
  operation,
534
598
  operation: { responses, requestBody }
535
599
  } = operationDefinition;
536
- const operationName = getOperationName2({ verb, path: path4, operation });
600
+ const operationName = getOperationName2({ verb, path: path4 });
537
601
  const tags = tag ? getTags({ verb, pathItem }) : [];
538
602
  const isQuery2 = isQuery(verb, overrides);
539
603
  const returnsJson = apiGen.getResponseType(responses) === "json";
@@ -543,18 +607,39 @@ async function generateApi(spec, {
543
607
  ([code, response]) => [
544
608
  code,
545
609
  apiGen.resolve(response),
546
- apiGen.getTypeFromResponse(response, "readOnly") || factory.createKeywordTypeNode(ts4.SyntaxKind.UndefinedKeyword)
610
+ wrapWithSchemeIfComponent(
611
+ apiGen.getTypeFromResponse(response, "readOnly") || factory.createKeywordTypeNode(ts4.SyntaxKind.UndefinedKeyword)
612
+ )
547
613
  ]
548
614
  ).filter(
549
615
  ([status, response]) => isDataResponse(status, includeDefault, apiGen.resolve(response), responses || {})
550
- ).filter(([_1, _2, type]) => type !== keywordType.void).map(
551
- ([code, response, type]) => ts4.addSyntheticLeadingComment(
552
- { ...type },
616
+ ).filter(([_1, _2, type]) => type !== keywordType.void).map(([code, response, type]) => {
617
+ if (sharedTypesFile2 && ts4.isTypeReferenceNode(type) && type.typeName) {
618
+ if (ts4.isIdentifier(type.typeName)) {
619
+ const typeName = type.typeName.text;
620
+ if (typeName in apiGen.aliases || typeName in apiGen.enumAliases) {
621
+ return ts4.addSyntheticLeadingComment(
622
+ factory.createTypeReferenceNode(
623
+ factory.createQualifiedName(
624
+ factory.createIdentifier("sharedTypes"),
625
+ factory.createIdentifier(camelCase(typeName))
626
+ ),
627
+ type.typeArguments
628
+ ),
629
+ ts4.SyntaxKind.MultiLineCommentTrivia,
630
+ `* status ${code} ${response.description} `,
631
+ false
632
+ );
633
+ }
634
+ }
635
+ }
636
+ return ts4.addSyntheticLeadingComment(
637
+ type,
553
638
  ts4.SyntaxKind.MultiLineCommentTrivia,
554
639
  `* status ${code} ${response.description} `,
555
640
  false
556
- )
557
- );
641
+ );
642
+ });
558
643
  if (returnTypes.length > 0) {
559
644
  ResponseType = factory.createUnionTypeNode(returnTypes);
560
645
  }
@@ -595,7 +680,7 @@ async function generateApi(spec, {
595
680
  origin: "param",
596
681
  name,
597
682
  originalName: param.name,
598
- type: apiGen.getTypeFromSchema(isReference(param) ? param : param.schema, void 0, "writeOnly"),
683
+ type: wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(isReference(param) ? param : param.schema, void 0, "writeOnly")),
599
684
  required: param.required,
600
685
  param
601
686
  };
@@ -603,7 +688,7 @@ async function generateApi(spec, {
603
688
  if (requestBody) {
604
689
  const body = apiGen.resolve(requestBody);
605
690
  const schema = apiGen.getSchemaFromContent(body.content);
606
- const type = apiGen.getTypeFromSchema(schema);
691
+ const type = wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(schema));
607
692
  const schemaName = camelCase(
608
693
  type.name || getReferenceName(schema) || typeof schema === "object" && "title" in schema && schema.title || "body"
609
694
  );
@@ -612,7 +697,7 @@ async function generateApi(spec, {
612
697
  origin: "body",
613
698
  name,
614
699
  originalName: schemaName,
615
- type: apiGen.getTypeFromSchema(schema, void 0, "writeOnly"),
700
+ type: wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(schema, void 0, "writeOnly")),
616
701
  required: true,
617
702
  body
618
703
  };
@@ -753,6 +838,49 @@ async function generateApi(spec, {
753
838
  function generateMutationEndpointProps({}) {
754
839
  return {};
755
840
  }
841
+ function wrapWithSchemeIfComponent(typeNode) {
842
+ if (ts4.isTypeReferenceNode(typeNode) && ts4.isIdentifier(typeNode.typeName)) {
843
+ const typeName = typeNode.typeName.text;
844
+ if (schemeTypeNames.has(typeName)) {
845
+ return factory.createTypeReferenceNode(
846
+ factory.createQualifiedName(
847
+ factory.createIdentifier("Scheme"),
848
+ typeNode.typeName
849
+ ),
850
+ typeNode.typeArguments?.map(wrapWithSchemeIfComponent)
851
+ );
852
+ }
853
+ if (typeNode.typeArguments) {
854
+ return factory.createTypeReferenceNode(
855
+ typeNode.typeName,
856
+ typeNode.typeArguments.map(wrapWithSchemeIfComponent)
857
+ );
858
+ }
859
+ }
860
+ if (ts4.isArrayTypeNode(typeNode)) {
861
+ return factory.createArrayTypeNode(wrapWithSchemeIfComponent(typeNode.elementType));
862
+ }
863
+ if (ts4.isUnionTypeNode(typeNode)) {
864
+ return factory.createUnionTypeNode(typeNode.types.map(wrapWithSchemeIfComponent));
865
+ }
866
+ if (ts4.isTypeLiteralNode(typeNode)) {
867
+ return factory.createTypeLiteralNode(
868
+ typeNode.members.map((member) => {
869
+ if (ts4.isPropertySignature(member) && member.type) {
870
+ return factory.updatePropertySignature(
871
+ member,
872
+ member.modifiers,
873
+ member.name,
874
+ member.questionToken,
875
+ wrapWithSchemeIfComponent(member.type)
876
+ );
877
+ }
878
+ return member;
879
+ })
880
+ );
881
+ }
882
+ return typeNode;
883
+ }
756
884
  }
757
885
  function generatePathExpression(path4, pathParameters, rootObject, isFlatArg, encodePathParams) {
758
886
  const expressions = [];
@@ -780,7 +908,55 @@ function generatePathExpression(path4, pathParameters, rootObject, isFlatArg, en
780
908
  }
781
909
 
782
910
  // src/index.ts
911
+ import camelCase2 from "lodash.camelcase";
783
912
  var require2 = createRequire(__filename);
913
+ async function ensureDirectoryExists(filePath) {
914
+ const dirname = path3.dirname(filePath);
915
+ if (!fs.existsSync(dirname)) {
916
+ await fs.promises.mkdir(dirname, { recursive: true });
917
+ }
918
+ }
919
+ function fileExists(filePath) {
920
+ try {
921
+ return fs.statSync(filePath).isFile();
922
+ } catch {
923
+ return false;
924
+ }
925
+ }
926
+ function getApiNameFromDir(dirPath) {
927
+ const dirName = path3.basename(dirPath);
928
+ return `${dirName}Api`;
929
+ }
930
+ async function ensureBaseFilesExist(outputDir) {
931
+ const enhanceEndpointsPath = path3.join(outputDir, "enhanceEndpoints.ts");
932
+ const indexPath = path3.join(outputDir, "index.ts");
933
+ const apiName = getApiNameFromDir(outputDir);
934
+ if (!fileExists(enhanceEndpointsPath)) {
935
+ const enhanceEndpointsContent = `import api from './query.generated';
936
+
937
+ const enhancedApi = api.enhanceEndpoints({
938
+ endpoints: {
939
+ },
940
+ });
941
+
942
+ export default enhancedApi;
943
+ `;
944
+ await fs.promises.writeFile(enhanceEndpointsPath, enhanceEndpointsContent, "utf-8");
945
+ }
946
+ if (!fileExists(indexPath)) {
947
+ const indexContent = `export * from './query.generated';
948
+ export {default as ${apiName}} from './enhanceEndpoints';
949
+ `;
950
+ await fs.promises.writeFile(indexPath, indexContent, "utf-8");
951
+ }
952
+ }
953
+ function getGroupNameFromPath(path4, pattern) {
954
+ const match = path4.match(pattern);
955
+ if (match && match[1]) {
956
+ return camelCase2(match[1]);
957
+ }
958
+ return "common";
959
+ }
784
960
  async function generateEndpoints(options) {
785
961
  const schemaLocation = options.schemaFile;
786
962
  const schemaAbsPath = isValidUrl(options.schemaFile) ? options.schemaFile : path3.resolve(process.cwd(), schemaLocation);
@@ -789,8 +965,12 @@ async function generateEndpoints(options) {
789
965
  });
790
966
  const { outputFile, prettierConfigFile } = options;
791
967
  if (outputFile) {
968
+ const outputPath = path3.resolve(process.cwd(), outputFile);
969
+ await ensureDirectoryExists(outputPath);
970
+ const outputDir = path3.dirname(outputPath);
971
+ await ensureBaseFilesExist(outputDir);
792
972
  fs.writeFileSync(
793
- path3.resolve(process.cwd(), outputFile),
973
+ outputPath,
794
974
  await prettify(outputFile, sourceCode, prettierConfigFile)
795
975
  );
796
976
  } else {
@@ -801,13 +981,29 @@ function parseConfig(fullConfig) {
801
981
  const outFiles = [];
802
982
  if ("outputFiles" in fullConfig) {
803
983
  const { outputFiles, ...commonConfig } = fullConfig;
804
- for (const [outputFile, specificConfig] of Object.entries(outputFiles)) {
984
+ const openApiDoc = JSON.parse(fs.readFileSync(fullConfig.schemaFile, "utf-8"));
985
+ const paths = Object.keys(openApiDoc.paths);
986
+ const [outputPath, config] = Object.entries(outputFiles)[0];
987
+ const patterns = config.groupMatch;
988
+ const filterEndpoint = config.filterEndpoint;
989
+ const pattern = patterns;
990
+ const groupedPaths = paths.reduce((acc, path4) => {
991
+ const groupName = getGroupNameFromPath(path4, pattern);
992
+ if (!acc[groupName]) {
993
+ acc[groupName] = [];
994
+ }
995
+ acc[groupName].push(path4);
996
+ return acc;
997
+ }, {});
998
+ Object.entries(groupedPaths).forEach(([groupName, paths2]) => {
999
+ const finalOutputPath = outputPath.replace("$1", groupName);
1000
+ const filterEndpoints = filterEndpoint(groupName);
805
1001
  outFiles.push({
806
1002
  ...commonConfig,
807
- ...specificConfig,
808
- outputFile
1003
+ outputFile: finalOutputPath,
1004
+ filterEndpoints: [filterEndpoints]
809
1005
  });
810
- }
1006
+ });
811
1007
  } else {
812
1008
  outFiles.push(fullConfig);
813
1009
  }