@acrool/rtk-query-codegen-openapi 0.0.2-test.6 → 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 || [] : [];
@@ -441,41 +441,61 @@ async function generateApi(spec, {
441
441
  useEnumType,
442
442
  mergeReadWriteOnly
443
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
+ }
444
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 = [];
445
461
  const components = v3Doc.components;
446
462
  if (components) {
447
- const resultFile2 = ts4.createSourceFile(
448
- "sharedTypes.ts",
449
- "",
450
- ts4.ScriptTarget.Latest,
451
- /*setParentNodes*/
452
- false,
453
- ts4.ScriptKind.TS
454
- );
455
- const printer2 = ts4.createPrinter({ newLine: ts4.NewLineKind.LineFeed });
456
- const typeDefinitions = Object.entries(components).flatMap(([_, componentDefs]) => {
457
- return Object.entries(componentDefs).map(([name, def]) => {
458
- const typeNode = apiGen.getTypeFromSchema(def);
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));
459
468
  return factory.createTypeAliasDeclaration(
460
469
  [factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
461
- factory.createIdentifier(name),
470
+ factory.createIdentifier(typeName),
462
471
  void 0,
463
472
  typeNode
464
473
  );
465
474
  });
475
+ return factory.createModuleDeclaration(
476
+ [factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
477
+ factory.createIdentifier("Scheme"),
478
+ factory.createModuleBlock(typeEntries),
479
+ ts4.NodeFlags.Namespace
480
+ );
466
481
  });
467
- const output = printer2.printNode(
468
- ts4.EmitHint.Unspecified,
469
- factory.createSourceFile(
470
- typeDefinitions,
471
- factory.createToken(ts4.SyntaxKind.EndOfFileToken),
472
- ts4.NodeFlags.None
473
- ),
474
- resultFile2
475
- );
476
- const fs2 = await import("node:fs/promises");
477
- await fs2.writeFile(sharedTypesFile, output, "utf-8");
482
+ allTypeDefinitions.push(...componentDefinitions);
483
+ }
484
+ if (useEnumType) {
485
+ allTypeDefinitions.push(...apiGen.enumAliases);
478
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");
479
499
  }
480
500
  if (apiGen.spec.components?.schemas) {
481
501
  apiGen.preprocessComponents(apiGen.spec.components.schemas);
@@ -506,34 +526,20 @@ async function generateApi(spec, {
506
526
  apiFile = apiFile.replace(/\\/g, "/");
507
527
  if (!apiFile.startsWith(".")) apiFile = `./${apiFile}`;
508
528
  }
509
- if (sharedTypesFile && sharedTypesFile.startsWith(".")) {
510
- sharedTypesFile = path2.relative(path2.dirname(outputFile), sharedTypesFile);
511
- sharedTypesFile = sharedTypesFile.replace(/\\/g, "/");
512
- if (!sharedTypesFile.startsWith(".")) sharedTypesFile = `./${sharedTypesFile}`;
513
- }
514
529
  }
515
530
  apiFile = apiFile.replace(/\.[jt]sx?$/, "");
516
- if (sharedTypesFile) {
517
- sharedTypesFile = sharedTypesFile.replace(/\.[jt]sx?$/, "");
518
- }
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";
519
536
  return printer.printNode(
520
537
  ts4.EmitHint.Unspecified,
521
538
  factory.createSourceFile(
522
539
  [
523
540
  generateImportNode(apiFile, { [apiImport]: "api" }),
524
541
  generateImportNode("@acrool/react-fetcher", { IRestFulEndpointsQueryReturn: "IRestFulEndpointsQueryReturn" }),
525
- ...sharedTypesFile ? [
526
- factory.createImportDeclaration(
527
- void 0,
528
- factory.createImportClause(
529
- false,
530
- void 0,
531
- factory.createNamespaceImport(factory.createIdentifier("SharedTypes"))
532
- ),
533
- factory.createStringLiteral(sharedTypesFile),
534
- void 0
535
- )
536
- ] : [],
542
+ ...sharedTypesFile ? [generateImportNode(sharedTypesImportPath, { Scheme: "Scheme" })] : [],
537
543
  ...tag ? [generateTagTypes({ addTagTypes: extractAllTagTypes({ operationDefinitions }) })] : [],
538
544
  generateCreateApiCall({
539
545
  tag,
@@ -541,7 +547,8 @@ async function generateApi(spec, {
541
547
  operationDefinitions.map(
542
548
  (operationDefinition) => generateEndpoint({
543
549
  operationDefinition,
544
- overrides: getOverrides(operationDefinition, endpointOverrides)
550
+ overrides: getOverrides(operationDefinition, endpointOverrides),
551
+ sharedTypesFile: !!sharedTypesFile
545
552
  })
546
553
  ),
547
554
  true
@@ -580,7 +587,8 @@ async function generateApi(spec, {
580
587
  }
581
588
  function generateEndpoint({
582
589
  operationDefinition,
583
- overrides
590
+ overrides,
591
+ sharedTypesFile: sharedTypesFile2
584
592
  }) {
585
593
  const {
586
594
  verb,
@@ -589,60 +597,49 @@ async function generateApi(spec, {
589
597
  operation,
590
598
  operation: { responses, requestBody }
591
599
  } = operationDefinition;
592
- const operationName = getOperationName2({ verb, path: path4, operation });
600
+ const operationName = getOperationName2({ verb, path: path4 });
593
601
  const tags = tag ? getTags({ verb, pathItem }) : [];
594
602
  const isQuery2 = isQuery(verb, overrides);
595
603
  const returnsJson = apiGen.getResponseType(responses) === "json";
596
604
  let ResponseType = factory.createKeywordTypeNode(ts4.SyntaxKind.UnknownKeyword);
597
- function replaceReferences(schema) {
598
- if (!schema) return factory.createKeywordTypeNode(ts4.SyntaxKind.UnknownKeyword);
599
- const refName = getReferenceName(schema);
600
- if (refName && sharedTypesFile) {
601
- return factory.createTypeReferenceNode(
602
- factory.createQualifiedName(
603
- factory.createIdentifier("SharedTypes"),
604
- factory.createIdentifier(refName)
605
- ),
606
- void 0
607
- );
608
- }
609
- if (schema.type === "object" && schema.properties) {
610
- const members = Object.entries(schema.properties).map(([key, value]) => {
611
- return factory.createPropertySignature(
612
- void 0,
613
- factory.createIdentifier(key),
614
- schema.required?.includes(key) ? void 0 : factory.createToken(ts4.SyntaxKind.QuestionToken),
615
- replaceReferences(value)
616
- );
617
- });
618
- return factory.createTypeLiteralNode(members);
619
- }
620
- if (schema.type === "array" && schema.items) {
621
- return factory.createArrayTypeNode(replaceReferences(schema.items));
622
- }
623
- return apiGen.getTypeFromSchema(schema);
624
- }
625
605
  if (returnsJson) {
626
606
  const returnTypes = Object.entries(responses || {}).map(
627
- ([code, response]) => {
628
- const resolvedResponse = apiGen.resolve(response);
629
- if (!resolvedResponse.content?.["application/json"]?.schema) {
630
- return [code, resolvedResponse, factory.createKeywordTypeNode(ts4.SyntaxKind.UndefinedKeyword)];
631
- }
632
- const schema = resolvedResponse.content["application/json"].schema;
633
- const type = replaceReferences(schema);
634
- return [code, resolvedResponse, type];
635
- }
607
+ ([code, response]) => [
608
+ code,
609
+ apiGen.resolve(response),
610
+ wrapWithSchemeIfComponent(
611
+ apiGen.getTypeFromResponse(response, "readOnly") || factory.createKeywordTypeNode(ts4.SyntaxKind.UndefinedKeyword)
612
+ )
613
+ ]
636
614
  ).filter(
637
615
  ([status, response]) => isDataResponse(status, includeDefault, apiGen.resolve(response), responses || {})
638
- ).filter(([_1, _2, type]) => type !== keywordType.void).map(
639
- ([code, response, type]) => ts4.addSyntheticLeadingComment(
640
- { ...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,
641
638
  ts4.SyntaxKind.MultiLineCommentTrivia,
642
639
  `* status ${code} ${response.description} `,
643
640
  false
644
- )
645
- );
641
+ );
642
+ });
646
643
  if (returnTypes.length > 0) {
647
644
  ResponseType = factory.createUnionTypeNode(returnTypes);
648
645
  }
@@ -677,10 +674,21 @@ async function generateApi(spec, {
677
674
  }
678
675
  return name;
679
676
  }
677
+ for (const param of parameters) {
678
+ const name = generateName(param.name, param.in);
679
+ queryArg[name] = {
680
+ origin: "param",
681
+ name,
682
+ originalName: param.name,
683
+ type: wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(isReference(param) ? param : param.schema, void 0, "writeOnly")),
684
+ required: param.required,
685
+ param
686
+ };
687
+ }
680
688
  if (requestBody) {
681
689
  const body = apiGen.resolve(requestBody);
682
690
  const schema = apiGen.getSchemaFromContent(body.content);
683
- const type = replaceReferences(schema);
691
+ const type = wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(schema));
684
692
  const schemaName = camelCase(
685
693
  type.name || getReferenceName(schema) || typeof schema === "object" && "title" in schema && schema.title || "body"
686
694
  );
@@ -689,24 +697,11 @@ async function generateApi(spec, {
689
697
  origin: "body",
690
698
  name,
691
699
  originalName: schemaName,
692
- type,
700
+ type: wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(schema, void 0, "writeOnly")),
693
701
  required: true,
694
702
  body
695
703
  };
696
704
  }
697
- for (const param of parameters) {
698
- const name = generateName(param.name, param.in);
699
- const paramSchema = isReference(param) ? param : param.schema;
700
- const type = replaceReferences(paramSchema);
701
- queryArg[name] = {
702
- origin: "param",
703
- name,
704
- originalName: param.name,
705
- type,
706
- required: param.required,
707
- param
708
- };
709
- }
710
705
  const propertyName = (name) => {
711
706
  if (typeof name === "string") {
712
707
  return isValidIdentifier(name) ? factory.createIdentifier(name) : factory.createStringLiteral(name);
@@ -843,6 +838,49 @@ async function generateApi(spec, {
843
838
  function generateMutationEndpointProps({}) {
844
839
  return {};
845
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
+ }
846
884
  }
847
885
  function generatePathExpression(path4, pathParameters, rootObject, isFlatArg, encodePathParams) {
848
886
  const expressions = [];
@@ -870,7 +908,55 @@ function generatePathExpression(path4, pathParameters, rootObject, isFlatArg, en
870
908
  }
871
909
 
872
910
  // src/index.ts
911
+ import camelCase2 from "lodash.camelcase";
873
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
+ }
874
960
  async function generateEndpoints(options) {
875
961
  const schemaLocation = options.schemaFile;
876
962
  const schemaAbsPath = isValidUrl(options.schemaFile) ? options.schemaFile : path3.resolve(process.cwd(), schemaLocation);
@@ -879,8 +965,12 @@ async function generateEndpoints(options) {
879
965
  });
880
966
  const { outputFile, prettierConfigFile } = options;
881
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);
882
972
  fs.writeFileSync(
883
- path3.resolve(process.cwd(), outputFile),
973
+ outputPath,
884
974
  await prettify(outputFile, sourceCode, prettierConfigFile)
885
975
  );
886
976
  } else {
@@ -891,13 +981,29 @@ function parseConfig(fullConfig) {
891
981
  const outFiles = [];
892
982
  if ("outputFiles" in fullConfig) {
893
983
  const { outputFiles, ...commonConfig } = fullConfig;
894
- 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);
895
1001
  outFiles.push({
896
1002
  ...commonConfig,
897
- ...specificConfig,
898
- outputFile
1003
+ outputFile: finalOutputPath,
1004
+ filterEndpoints: [filterEndpoints]
899
1005
  });
900
- }
1006
+ });
901
1007
  } else {
902
1008
  outFiles.push(fullConfig);
903
1009
  }