@acrool/rtk-query-codegen-openapi 0.0.2-test.0 → 0.0.2-test.2

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
@@ -9,11 +9,17 @@ import { createRequire } from "node:module";
9
9
  import path3 from "node:path";
10
10
 
11
11
  // src/generate.ts
12
+ import camelCase from "lodash.camelcase";
12
13
  import path2 from "node:path";
13
14
  import ApiGenerator, {
14
15
  getOperationName as _getOperationName,
16
+ getReferenceName,
15
17
  isReference,
16
- isValidIdentifier
18
+ supportDeepObjects,
19
+ createPropertyAssignment,
20
+ createQuestionToken,
21
+ isValidIdentifier,
22
+ keywordType
17
23
  } from "oazapfts/generate";
18
24
  import ts4 from "typescript";
19
25
 
@@ -151,10 +157,7 @@ function generateEndpointDefinition({
151
157
  objectProperties.push(
152
158
  factory.createPropertyAssignment(
153
159
  factory.createIdentifier(type === "query" ? "providesTags" : "invalidatesTags"),
154
- factory.createArrayLiteralExpression(
155
- tags.map((tag) => factory.createStringLiteral(tag)),
156
- false
157
- )
160
+ factory.createArrayLiteralExpression(tags.map((tag) => factory.createStringLiteral(tag), false))
158
161
  )
159
162
  );
160
163
  }
@@ -356,10 +359,7 @@ var generateReactHooks = ({
356
359
  // src/generate.ts
357
360
  var generatedApiName = "injectedRtkApi";
358
361
  var v3DocCache = {};
359
- var useFetcherImport = generateImportNode("@acrool/react-fetcher", {
360
- IUseFetcherArgs: "IUseFetcherArgs"
361
- });
362
- function defaultIsDataResponse(code, includeDefault, response, allResponses) {
362
+ function defaultIsDataResponse(code, includeDefault) {
363
363
  if (includeDefault && code === "default") {
364
364
  return true;
365
365
  }
@@ -370,8 +370,7 @@ function getOperationName2({ verb, path: path4, operation }) {
370
370
  return _getOperationName(verb, path4, operation.operationId);
371
371
  }
372
372
  function getTags({ verb, pathItem }) {
373
- const tags = verb && pathItem[verb]?.tags ? pathItem[verb].tags : [];
374
- return tags.map((tag) => tag.toString());
373
+ return verb ? pathItem[verb]?.tags || [] : [];
375
374
  }
376
375
  function patternMatches(pattern) {
377
376
  const filters = Array.isArray(pattern) ? pattern : [pattern];
@@ -390,6 +389,26 @@ function operationMatches(pattern) {
390
389
  return checkMatch(operationName, operationDefinition);
391
390
  };
392
391
  }
392
+ function argumentMatches(pattern) {
393
+ const checkMatch = typeof pattern === "function" ? pattern : patternMatches(pattern);
394
+ return function matcher(argumentDefinition) {
395
+ if (!pattern || argumentDefinition.in === "path") return true;
396
+ const argumentName = argumentDefinition.name;
397
+ return checkMatch(argumentName, argumentDefinition);
398
+ };
399
+ }
400
+ function withQueryComment(node, def, hasTrailingNewLine) {
401
+ const comment = def.origin === "param" ? def.param.description : def.body.description;
402
+ if (comment) {
403
+ return ts4.addSyntheticLeadingComment(
404
+ node,
405
+ ts4.SyntaxKind.MultiLineCommentTrivia,
406
+ `* ${comment} `,
407
+ hasTrailingNewLine
408
+ );
409
+ }
410
+ return node;
411
+ }
393
412
  function getOverrides(operation, endpointOverrides) {
394
413
  return endpointOverrides?.find((override) => operationMatches(override.pattern)(operation));
395
414
  }
@@ -508,109 +527,6 @@ async function generateApi(spec, {
508
527
  }
509
528
  return [...allTagTypes];
510
529
  }
511
- function generateQueryArgType(operationDefinition) {
512
- const {
513
- operation: { parameters = [], requestBody }
514
- } = operationDefinition;
515
- const properties = [];
516
- if (requestBody && !isReference(requestBody)) {
517
- const bodySchema = requestBody.content?.["application/json"]?.schema;
518
- if (bodySchema) {
519
- properties.push(
520
- factory.createPropertySignature(
521
- void 0,
522
- factory.createIdentifier("body"),
523
- void 0,
524
- factory.createTypeReferenceNode(factory.createIdentifier("any"), void 0)
525
- )
526
- );
527
- }
528
- }
529
- const queryParams = parameters.filter((p) => !isReference(p) && p.in === "query");
530
- if (queryParams.length > 0) {
531
- properties.push(
532
- factory.createPropertySignature(
533
- void 0,
534
- factory.createIdentifier("params"),
535
- void 0,
536
- factory.createTypeLiteralNode(
537
- queryParams.map(
538
- (param) => factory.createPropertySignature(
539
- void 0,
540
- factory.createIdentifier(param.name),
541
- factory.createToken(ts4.SyntaxKind.QuestionToken),
542
- factory.createKeywordTypeNode(ts4.SyntaxKind.StringKeyword)
543
- )
544
- )
545
- )
546
- )
547
- );
548
- }
549
- const headerParams = parameters.filter((p) => !isReference(p) && p.in === "header");
550
- if (headerParams.length > 0) {
551
- properties.push(
552
- factory.createPropertySignature(
553
- void 0,
554
- factory.createIdentifier("headers"),
555
- void 0,
556
- factory.createTypeLiteralNode(
557
- headerParams.map(
558
- (param) => factory.createPropertySignature(
559
- void 0,
560
- factory.createIdentifier(param.name),
561
- factory.createToken(ts4.SyntaxKind.QuestionToken),
562
- factory.createKeywordTypeNode(ts4.SyntaxKind.StringKeyword)
563
- )
564
- )
565
- )
566
- )
567
- );
568
- }
569
- return factory.createTypeLiteralNode([
570
- factory.createPropertySignature(
571
- void 0,
572
- factory.createIdentifier("variables"),
573
- void 0,
574
- factory.createTypeLiteralNode(properties)
575
- ),
576
- factory.createPropertySignature(
577
- void 0,
578
- factory.createIdentifier("fetchOptions"),
579
- factory.createToken(ts4.SyntaxKind.QuestionToken),
580
- factory.createTypeReferenceNode(factory.createIdentifier("any"), void 0)
581
- )
582
- ]);
583
- }
584
- function generateQueryArgDefinitions(operationDefinition) {
585
- const {
586
- operation: { parameters = [], requestBody }
587
- } = operationDefinition;
588
- const queryArg = {};
589
- if (requestBody && !isReference(requestBody)) {
590
- const bodySchema = requestBody.content?.["application/json"]?.schema;
591
- if (bodySchema) {
592
- queryArg["body"] = {
593
- name: "body",
594
- originalName: "body",
595
- type: factory.createKeywordTypeNode(ts4.SyntaxKind.AnyKeyword),
596
- required: true,
597
- origin: "body",
598
- body: requestBody
599
- };
600
- }
601
- }
602
- parameters.filter((p) => !isReference(p)).forEach((param) => {
603
- queryArg[param.name] = {
604
- name: param.name,
605
- originalName: param.name,
606
- type: factory.createKeywordTypeNode(ts4.SyntaxKind.StringKeyword),
607
- required: param.required || false,
608
- origin: "param",
609
- param
610
- };
611
- });
612
- return queryArg;
613
- }
614
530
  function generateEndpoint({
615
531
  operationDefinition,
616
532
  overrides
@@ -629,39 +545,138 @@ async function generateApi(spec, {
629
545
  let ResponseType = factory.createKeywordTypeNode(ts4.SyntaxKind.UnknownKeyword);
630
546
  if (returnsJson) {
631
547
  const returnTypes = Object.entries(responses || {}).map(
632
- ([code, response]) => isDataResponse(code, includeDefault, response, responses) && response ? apiGen.getTypeFromResponse(response) : void 0
633
- ).filter(removeUndefined);
634
- if (returnTypes.length === 1) {
635
- ResponseType = returnTypes[0];
636
- } else if (returnTypes.length > 1) {
548
+ ([code, response]) => [
549
+ code,
550
+ apiGen.resolve(response),
551
+ apiGen.getTypeFromResponse(response, "readOnly") || factory.createKeywordTypeNode(ts4.SyntaxKind.UndefinedKeyword)
552
+ ]
553
+ ).filter(
554
+ ([status, response]) => isDataResponse(status, includeDefault, apiGen.resolve(response), responses || {})
555
+ ).filter(([_1, _2, type]) => type !== keywordType.void).map(
556
+ ([code, response, type]) => ts4.addSyntheticLeadingComment(
557
+ { ...type },
558
+ ts4.SyntaxKind.MultiLineCommentTrivia,
559
+ `* status ${code} ${response.description} `,
560
+ false
561
+ )
562
+ );
563
+ if (returnTypes.length > 0) {
637
564
  ResponseType = factory.createUnionTypeNode(returnTypes);
638
565
  }
639
566
  }
640
- const QueryArg = generateQueryArgType(operationDefinition);
641
- const wrappedQueryArg = factory.createTypeReferenceNode(factory.createIdentifier("IUseFetcherArgs"), [QueryArg]);
642
- const endpointBuilder = factory.createIdentifier("build");
643
- const Response = factory.createTypeReferenceNode(
644
- factory.createIdentifier(`${capitalize(operationName)}${responseSuffix}`),
645
- void 0
567
+ const ResponseTypeName = factory.createTypeReferenceNode(
568
+ registerInterface(
569
+ factory.createTypeAliasDeclaration(
570
+ [factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
571
+ capitalize(operationName + operationNameSuffix + responseSuffix),
572
+ void 0,
573
+ ResponseType
574
+ )
575
+ ).name
576
+ );
577
+ const operationParameters = apiGen.resolveArray(operation.parameters);
578
+ const pathItemParameters = apiGen.resolveArray(pathItem.parameters).filter((pp) => !operationParameters.some((op) => op.name === pp.name && op.in === pp.in));
579
+ const parameters = supportDeepObjects([...pathItemParameters, ...operationParameters]).filter(
580
+ argumentMatches(overrides?.parameterFilter)
581
+ );
582
+ const allNames = parameters.map((p) => p.name);
583
+ const queryArg = {};
584
+ function generateName(name, potentialPrefix) {
585
+ const isPureSnakeCase = /^[a-zA-Z][a-zA-Z0-9_]*$/.test(name);
586
+ const hasNamingConflict = allNames.filter((n) => n === name).length > 1;
587
+ if (hasNamingConflict) {
588
+ name = `${potentialPrefix}_${name}`;
589
+ }
590
+ const camelCaseName = camelCase(name);
591
+ if (isPureSnakeCase && !allNames.includes(camelCaseName)) {
592
+ name = camelCaseName;
593
+ }
594
+ while (name in queryArg) {
595
+ name = `_${name}`;
596
+ }
597
+ return name;
598
+ }
599
+ for (const param of parameters) {
600
+ const name = generateName(param.name, param.in);
601
+ queryArg[name] = {
602
+ origin: "param",
603
+ name,
604
+ originalName: param.name,
605
+ type: apiGen.getTypeFromSchema(isReference(param) ? param : param.schema, void 0, "writeOnly"),
606
+ required: param.required,
607
+ param
608
+ };
609
+ }
610
+ if (requestBody) {
611
+ const body = apiGen.resolve(requestBody);
612
+ const schema = apiGen.getSchemaFromContent(body.content);
613
+ const type = apiGen.getTypeFromSchema(schema);
614
+ const schemaName = camelCase(
615
+ type.name || getReferenceName(schema) || typeof schema === "object" && "title" in schema && schema.title || "body"
616
+ );
617
+ const name = generateName(schemaName in queryArg ? "body" : schemaName, "body");
618
+ queryArg[name] = {
619
+ origin: "body",
620
+ name,
621
+ originalName: schemaName,
622
+ type: apiGen.getTypeFromSchema(schema, void 0, "writeOnly"),
623
+ required: true,
624
+ body
625
+ };
626
+ }
627
+ const propertyName = (name) => {
628
+ if (typeof name === "string") {
629
+ return isValidIdentifier(name) ? factory.createIdentifier(name) : factory.createStringLiteral(name);
630
+ }
631
+ return name;
632
+ };
633
+ const queryArgValues = Object.values(queryArg);
634
+ const isFlatArg = flattenArg && queryArgValues.length === 1;
635
+ const QueryArg = factory.createTypeReferenceNode(
636
+ registerInterface(
637
+ factory.createTypeAliasDeclaration(
638
+ [factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
639
+ capitalize(operationName + operationNameSuffix + argSuffix),
640
+ void 0,
641
+ queryArgValues.length > 0 ? isFlatArg ? withQueryComment(
642
+ factory.createUnionTypeNode([
643
+ queryArgValues[0].type,
644
+ ...!queryArgValues[0].required ? [factory.createKeywordTypeNode(ts4.SyntaxKind.UndefinedKeyword)] : []
645
+ ]),
646
+ queryArgValues[0],
647
+ false
648
+ ) : factory.createTypeLiteralNode(
649
+ queryArgValues.map(
650
+ (def) => withQueryComment(
651
+ factory.createPropertySignature(
652
+ void 0,
653
+ propertyName(def.name),
654
+ createQuestionToken(!def.required),
655
+ def.type
656
+ ),
657
+ def,
658
+ true
659
+ )
660
+ )
661
+ ) : factory.createKeywordTypeNode(ts4.SyntaxKind.VoidKeyword)
662
+ )
663
+ ).name
646
664
  );
647
- const queryArgDefinitions = generateQueryArgDefinitions(operationDefinition);
648
- const extraEndpointsProps = isQuery2 ? generateQueryEndpointProps({ operationDefinition }) : generateMutationEndpointProps({ operationDefinition });
649
665
  return generateEndpointDefinition({
650
- operationName,
666
+ operationName: operationNameSuffix ? capitalize(operationName + operationNameSuffix) : operationName,
651
667
  type: isQuery2 ? "query" : "mutation",
652
- Response,
653
- QueryArg: wrappedQueryArg,
668
+ Response: ResponseTypeName,
669
+ QueryArg,
654
670
  queryFn: generateQueryFn({
655
671
  operationDefinition,
656
- queryArg: queryArgDefinitions,
657
- isFlatArg: flattenArg,
672
+ queryArg,
658
673
  isQuery: isQuery2,
674
+ isFlatArg,
659
675
  encodePathParams,
660
676
  encodeQueryParams
661
677
  }),
662
- extraEndpointsProps,
663
- tags,
664
- endpointBuilder
678
+ extraEndpointsProps: isQuery2 ? generateQueryEndpointProps({ operationDefinition }) : generateMutationEndpointProps({ operationDefinition }),
679
+ tags
665
680
  });
666
681
  }
667
682
  function generateQueryFn({
@@ -672,91 +687,60 @@ async function generateApi(spec, {
672
687
  encodePathParams: encodePathParams2,
673
688
  encodeQueryParams: encodeQueryParams2
674
689
  }) {
675
- const {
676
- operation: { parameters = [], requestBody },
677
- path: path4,
678
- verb
679
- } = operationDefinition;
680
- const bodyParameter = requestBody && !isReference(requestBody) ? requestBody.content?.["application/json"]?.schema : void 0;
681
- const bodyArg = bodyParameter ? queryArg["body"] : void 0;
682
- const pathParameters = parameters.filter((p) => !isReference(p) && p.in === "path").map((param) => ({
683
- name: param.name,
684
- originalName: param.name,
685
- type: factory.createKeywordTypeNode(ts4.SyntaxKind.StringKeyword),
686
- required: param.required,
687
- param,
688
- origin: "param"
689
- }));
690
- const queryParameters = parameters.filter((p) => !isReference(p) && p.in === "query").map((param) => ({
691
- name: param.name,
692
- originalName: param.name,
693
- type: factory.createKeywordTypeNode(ts4.SyntaxKind.StringKeyword),
694
- required: param.required,
695
- param,
696
- origin: "param"
697
- }));
698
- const headerParameters = parameters.filter((p) => !isReference(p) && p.in === "header").map((param) => ({
699
- name: param.name.includes("-") ? `'${param.name}'` : param.name,
700
- originalName: param.name,
701
- type: factory.createKeywordTypeNode(ts4.SyntaxKind.StringKeyword),
702
- required: param.required,
703
- param,
704
- origin: "param"
705
- }));
690
+ const { path: path4, verb } = operationDefinition;
691
+ const bodyParameter = Object.values(queryArg).find((def) => def.origin === "body");
706
692
  const rootObject = factory.createIdentifier("queryArg");
707
- const objectProperties = [
708
- factory.createPropertyAssignment(
709
- "url",
710
- generatePathExpression(path4, pathParameters, rootObject, isFlatArg, encodePathParams2)
711
- ),
712
- factory.createPropertyAssignment("method", factory.createStringLiteral(verb.toUpperCase()))
713
- ];
714
- if (bodyArg) {
715
- objectProperties.push(
716
- factory.createPropertyAssignment(
717
- "body",
718
- factory.createPropertyAccessExpression(
719
- factory.createPropertyAccessExpression(rootObject, factory.createIdentifier("variables")),
720
- factory.createIdentifier("body")
721
- )
722
- )
723
- );
693
+ function pickParams(paramIn) {
694
+ return Object.values(queryArg).filter((def) => def.origin === "param" && def.param.in === paramIn);
724
695
  }
725
- if (queryParameters.length) {
726
- objectProperties.push(
727
- factory.createPropertyAssignment(
728
- "params",
729
- factory.createPropertyAccessExpression(
730
- factory.createPropertyAccessExpression(rootObject, factory.createIdentifier("variables")),
731
- factory.createIdentifier("params")
732
- )
733
- )
734
- );
735
- }
736
- if (headerParameters.length) {
737
- objectProperties.push(
738
- factory.createPropertyAssignment(
739
- "headers",
740
- factory.createPropertyAccessExpression(
741
- factory.createPropertyAccessExpression(rootObject, factory.createIdentifier("variables")),
742
- factory.createIdentifier("headers")
743
- )
744
- )
696
+ function createObjectLiteralProperty(parameters, propertyName) {
697
+ if (parameters.length === 0) return void 0;
698
+ const properties = parameters.map((param) => {
699
+ const value = isFlatArg ? rootObject : accessProperty(rootObject, param.name);
700
+ const encodedValue = encodeQueryParams2 && param.param?.in === "query" ? factory.createConditionalExpression(
701
+ value,
702
+ void 0,
703
+ factory.createCallExpression(factory.createIdentifier("encodeURIComponent"), void 0, [
704
+ factory.createCallExpression(factory.createIdentifier("String"), void 0, [value])
705
+ ]),
706
+ void 0,
707
+ factory.createIdentifier("undefined")
708
+ ) : value;
709
+ return createPropertyAssignment(param.originalName, encodedValue);
710
+ });
711
+ return factory.createPropertyAssignment(
712
+ factory.createIdentifier(propertyName),
713
+ factory.createObjectLiteralExpression(properties, true)
745
714
  );
746
715
  }
747
- objectProperties.push(
748
- factory.createPropertyAssignment(
749
- "fetchOptions",
750
- factory.createPropertyAccessExpression(rootObject, factory.createIdentifier("fetchOptions"))
751
- )
752
- );
753
716
  return factory.createArrowFunction(
754
717
  void 0,
755
718
  void 0,
756
- [factory.createParameterDeclaration(void 0, void 0, rootObject)],
719
+ Object.keys(queryArg).length ? [factory.createParameterDeclaration(void 0, void 0, rootObject, void 0, void 0, void 0)] : [],
757
720
  void 0,
758
721
  factory.createToken(ts4.SyntaxKind.EqualsGreaterThanToken),
759
- factory.createParenthesizedExpression(factory.createObjectLiteralExpression(objectProperties, true))
722
+ factory.createParenthesizedExpression(
723
+ factory.createObjectLiteralExpression(
724
+ [
725
+ factory.createPropertyAssignment(
726
+ factory.createIdentifier("url"),
727
+ generatePathExpression(path4, pickParams("path"), rootObject, isFlatArg, encodePathParams2)
728
+ ),
729
+ isQuery2 && verb.toUpperCase() === "GET" ? void 0 : factory.createPropertyAssignment(
730
+ factory.createIdentifier("method"),
731
+ factory.createStringLiteral(verb.toUpperCase())
732
+ ),
733
+ bodyParameter === void 0 ? void 0 : factory.createPropertyAssignment(
734
+ factory.createIdentifier("body"),
735
+ isFlatArg ? rootObject : factory.createPropertyAccessExpression(rootObject, factory.createIdentifier(bodyParameter.name))
736
+ ),
737
+ createObjectLiteralProperty(pickParams("cookie"), "cookies"),
738
+ createObjectLiteralProperty(pickParams("header"), "headers"),
739
+ createObjectLiteralProperty(pickParams("query"), "params")
740
+ ].filter(removeUndefined),
741
+ false
742
+ )
743
+ )
760
744
  );
761
745
  }
762
746
  function generateQueryEndpointProps({}) {
@@ -766,6 +750,9 @@ async function generateApi(spec, {
766
750
  return {};
767
751
  }
768
752
  }
753
+ function accessProperty(rootObject, propertyName) {
754
+ return isValidIdentifier(propertyName) ? factory.createPropertyAccessExpression(rootObject, factory.createIdentifier(propertyName)) : factory.createElementAccessExpression(rootObject, factory.createStringLiteral(propertyName));
755
+ }
769
756
  function generatePathExpression(path4, pathParameters, rootObject, isFlatArg, encodePathParams) {
770
757
  const expressions = [];
771
758
  const head = path4.replace(/\{(.*?)}(.*?)(?=\{|$)/g, (_, expression, literal) => {
@@ -777,21 +764,18 @@ function generatePathExpression(path4, pathParameters, rootObject, isFlatArg, en
777
764
  return "";
778
765
  });
779
766
  return expressions.length ? factory.createTemplateExpression(
780
- factory.createTemplateHead(head, head),
767
+ factory.createTemplateHead(head),
781
768
  expressions.map(([prop, literal], index) => {
782
- const value = factory.createPropertyAccessExpression(
783
- factory.createPropertyAccessExpression(rootObject, factory.createIdentifier("variables")),
784
- factory.createIdentifier(prop)
785
- );
769
+ const value = isFlatArg ? rootObject : accessProperty(rootObject, prop);
786
770
  const encodedValue = encodePathParams ? factory.createCallExpression(factory.createIdentifier("encodeURIComponent"), void 0, [
787
771
  factory.createCallExpression(factory.createIdentifier("String"), void 0, [value])
788
772
  ]) : value;
789
773
  return factory.createTemplateSpan(
790
774
  encodedValue,
791
- index === expressions.length - 1 ? factory.createTemplateTail(literal, literal) : factory.createTemplateMiddle(literal, literal)
775
+ index === expressions.length - 1 ? factory.createTemplateTail(literal) : factory.createTemplateMiddle(literal)
792
776
  );
793
777
  })
794
- ) : factory.createStringLiteral(head);
778
+ ) : factory.createNoSubstitutionTemplateLiteral(head);
795
779
  }
796
780
 
797
781
  // src/index.ts