@acrool/rtk-query-codegen-openapi 0.0.2 → 0.0.6
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.d.mts +8 -4
- package/lib/index.d.ts +8 -4
- package/lib/index.js +442 -112
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +442 -112
- package/lib/index.mjs.map +1 -1
- package/package.json +11 -2
- package/src/generate.ts +327 -127
- package/src/generators/react-hooks.ts +2 -2
- package/src/index.ts +250 -9
- package/src/types.ts +9 -1
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
|
|
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,
|
|
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
|
|
370
|
-
return _getOperationName(verb, path4,
|
|
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,153 @@ 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 = [];
|
|
461
|
+
const definedTypeNames = /* @__PURE__ */ new Set();
|
|
445
462
|
const components = v3Doc.components;
|
|
446
463
|
if (components) {
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
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);
|
|
464
|
+
const componentDefinitions = Object.entries(components).map(([componentType, componentDefs]) => {
|
|
465
|
+
const typeEntries = Object.entries(componentDefs).map(([name, def]) => {
|
|
466
|
+
addSchemeTypeName(name);
|
|
467
|
+
const typeName = capitalize(camelCase(name));
|
|
468
|
+
definedTypeNames.add(typeName);
|
|
469
|
+
const typeNode = wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(def));
|
|
459
470
|
return factory.createTypeAliasDeclaration(
|
|
460
471
|
[factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
|
|
461
|
-
factory.createIdentifier(
|
|
472
|
+
factory.createIdentifier(typeName),
|
|
462
473
|
void 0,
|
|
463
474
|
typeNode
|
|
464
475
|
);
|
|
465
476
|
});
|
|
477
|
+
return factory.createModuleDeclaration(
|
|
478
|
+
[factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
|
|
479
|
+
factory.createIdentifier("Scheme"),
|
|
480
|
+
factory.createModuleBlock(typeEntries),
|
|
481
|
+
ts4.NodeFlags.Namespace
|
|
482
|
+
);
|
|
466
483
|
});
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
484
|
+
allTypeDefinitions.push(...componentDefinitions);
|
|
485
|
+
}
|
|
486
|
+
const enumEntries = [
|
|
487
|
+
...apiGen.enumAliases.filter((e) => ts4.isEnumDeclaration(e)),
|
|
488
|
+
...apiGen.enumAliases.filter((e) => ts4.isTypeAliasDeclaration(e))
|
|
489
|
+
].map((enumDecl) => {
|
|
490
|
+
if (ts4.isEnumDeclaration(enumDecl)) {
|
|
491
|
+
return factory.createEnumDeclaration(
|
|
492
|
+
[factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
|
|
493
|
+
enumDecl.name,
|
|
494
|
+
enumDecl.members
|
|
495
|
+
);
|
|
496
|
+
} else if (ts4.isTypeAliasDeclaration(enumDecl)) {
|
|
497
|
+
return factory.createTypeAliasDeclaration(
|
|
498
|
+
[factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
|
|
499
|
+
enumDecl.name,
|
|
500
|
+
enumDecl.typeParameters,
|
|
501
|
+
enumDecl.type
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
return enumDecl;
|
|
505
|
+
});
|
|
506
|
+
const unionTypeEnums = apiGen.aliases.filter((alias) => {
|
|
507
|
+
if (ts4.isTypeAliasDeclaration(alias) && alias.type) {
|
|
508
|
+
return ts4.isUnionTypeNode(alias.type);
|
|
509
|
+
}
|
|
510
|
+
return false;
|
|
511
|
+
}).map((alias) => {
|
|
512
|
+
if (ts4.isTypeAliasDeclaration(alias)) {
|
|
513
|
+
return factory.createTypeAliasDeclaration(
|
|
514
|
+
[factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
|
|
515
|
+
alias.name,
|
|
516
|
+
alias.typeParameters,
|
|
517
|
+
alias.type
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
return alias;
|
|
521
|
+
});
|
|
522
|
+
const allEnumEntries = [...enumEntries, ...unionTypeEnums];
|
|
523
|
+
if (allEnumEntries.length > 0) {
|
|
524
|
+
allTypeDefinitions.push(
|
|
525
|
+
factory.createModuleDeclaration(
|
|
526
|
+
[factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
|
|
527
|
+
factory.createIdentifier("Enum"),
|
|
528
|
+
factory.createModuleBlock(allEnumEntries),
|
|
529
|
+
ts4.NodeFlags.Namespace
|
|
530
|
+
)
|
|
475
531
|
);
|
|
476
|
-
const fs2 = await import("node:fs/promises");
|
|
477
|
-
await fs2.writeFile(sharedTypesFile, output, "utf-8");
|
|
478
532
|
}
|
|
533
|
+
if (apiGen.aliases.length > 0) {
|
|
534
|
+
const aliasEntries = apiGen.aliases.filter((alias) => {
|
|
535
|
+
if (ts4.isTypeAliasDeclaration(alias)) {
|
|
536
|
+
const isDefinedInComponents = definedTypeNames.has(alias.name.text);
|
|
537
|
+
const isUnionTypeEnum = ts4.isUnionTypeNode(alias.type);
|
|
538
|
+
return !isDefinedInComponents && !isUnionTypeEnum;
|
|
539
|
+
}
|
|
540
|
+
return false;
|
|
541
|
+
}).map((alias) => {
|
|
542
|
+
if (ts4.isTypeAliasDeclaration(alias)) {
|
|
543
|
+
return factory.createTypeAliasDeclaration(
|
|
544
|
+
[factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
|
|
545
|
+
alias.name,
|
|
546
|
+
alias.typeParameters,
|
|
547
|
+
alias.type
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
return alias;
|
|
551
|
+
});
|
|
552
|
+
if (aliasEntries.length > 0) {
|
|
553
|
+
const existingSchemeIndex = allTypeDefinitions.findIndex(
|
|
554
|
+
(def) => ts4.isModuleDeclaration(def) && ts4.isIdentifier(def.name) && def.name.text === "Scheme"
|
|
555
|
+
);
|
|
556
|
+
if (existingSchemeIndex >= 0) {
|
|
557
|
+
const existingScheme = allTypeDefinitions[existingSchemeIndex];
|
|
558
|
+
const mergedMembers = [...existingScheme.body.statements, ...aliasEntries];
|
|
559
|
+
allTypeDefinitions[existingSchemeIndex] = factory.createModuleDeclaration(
|
|
560
|
+
[factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
|
|
561
|
+
factory.createIdentifier("Scheme"),
|
|
562
|
+
factory.createModuleBlock(mergedMembers),
|
|
563
|
+
ts4.NodeFlags.Namespace
|
|
564
|
+
);
|
|
565
|
+
} else {
|
|
566
|
+
allTypeDefinitions.push(
|
|
567
|
+
factory.createModuleDeclaration(
|
|
568
|
+
[factory.createModifier(ts4.SyntaxKind.ExportKeyword)],
|
|
569
|
+
factory.createIdentifier("Scheme"),
|
|
570
|
+
factory.createModuleBlock(aliasEntries),
|
|
571
|
+
ts4.NodeFlags.Namespace
|
|
572
|
+
)
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
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 });
|
|
581
|
+
const output = printer2.printNode(
|
|
582
|
+
ts4.EmitHint.Unspecified,
|
|
583
|
+
factory.createSourceFile(
|
|
584
|
+
allTypeDefinitions,
|
|
585
|
+
factory.createToken(ts4.SyntaxKind.EndOfFileToken),
|
|
586
|
+
ts4.NodeFlags.None
|
|
587
|
+
),
|
|
588
|
+
resultFile2
|
|
589
|
+
);
|
|
590
|
+
await fs2.writeFile(sharedTypesFile, output, "utf-8");
|
|
479
591
|
}
|
|
480
592
|
if (apiGen.spec.components?.schemas) {
|
|
481
593
|
apiGen.preprocessComponents(apiGen.spec.components.schemas);
|
|
@@ -506,16 +618,13 @@ async function generateApi(spec, {
|
|
|
506
618
|
apiFile = apiFile.replace(/\\/g, "/");
|
|
507
619
|
if (!apiFile.startsWith(".")) apiFile = `./${apiFile}`;
|
|
508
620
|
}
|
|
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
621
|
}
|
|
515
622
|
apiFile = apiFile.replace(/\.[jt]sx?$/, "");
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
623
|
+
const sharedTypesImportPath = sharedTypesFile && outputFile ? (() => {
|
|
624
|
+
let rel = path2.relative(path2.dirname(outputFile), sharedTypesFile).replace(/\\/g, "/").replace(/\.[jt]sx?$/, "");
|
|
625
|
+
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
626
|
+
return rel;
|
|
627
|
+
})() : "./shared-types";
|
|
519
628
|
return printer.printNode(
|
|
520
629
|
ts4.EmitHint.Unspecified,
|
|
521
630
|
factory.createSourceFile(
|
|
@@ -523,16 +632,10 @@ async function generateApi(spec, {
|
|
|
523
632
|
generateImportNode(apiFile, { [apiImport]: "api" }),
|
|
524
633
|
generateImportNode("@acrool/react-fetcher", { IRestFulEndpointsQueryReturn: "IRestFulEndpointsQueryReturn" }),
|
|
525
634
|
...sharedTypesFile ? [
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
void 0,
|
|
531
|
-
factory.createNamespaceImport(factory.createIdentifier("SharedTypes"))
|
|
532
|
-
),
|
|
533
|
-
factory.createStringLiteral(sharedTypesFile),
|
|
534
|
-
void 0
|
|
535
|
-
)
|
|
635
|
+
generateImportNode(sharedTypesImportPath, {
|
|
636
|
+
Scheme: "Scheme",
|
|
637
|
+
...useEnumType ? { Enum: "Enum" } : {}
|
|
638
|
+
})
|
|
536
639
|
] : [],
|
|
537
640
|
...tag ? [generateTagTypes({ addTagTypes: extractAllTagTypes({ operationDefinitions }) })] : [],
|
|
538
641
|
generateCreateApiCall({
|
|
@@ -541,7 +644,8 @@ async function generateApi(spec, {
|
|
|
541
644
|
operationDefinitions.map(
|
|
542
645
|
(operationDefinition) => generateEndpoint({
|
|
543
646
|
operationDefinition,
|
|
544
|
-
overrides: getOverrides(operationDefinition, endpointOverrides)
|
|
647
|
+
overrides: getOverrides(operationDefinition, endpointOverrides),
|
|
648
|
+
sharedTypesFile: !!sharedTypesFile
|
|
545
649
|
})
|
|
546
650
|
),
|
|
547
651
|
true
|
|
@@ -580,7 +684,8 @@ async function generateApi(spec, {
|
|
|
580
684
|
}
|
|
581
685
|
function generateEndpoint({
|
|
582
686
|
operationDefinition,
|
|
583
|
-
overrides
|
|
687
|
+
overrides,
|
|
688
|
+
sharedTypesFile: sharedTypesFile2
|
|
584
689
|
}) {
|
|
585
690
|
const {
|
|
586
691
|
verb,
|
|
@@ -589,60 +694,30 @@ async function generateApi(spec, {
|
|
|
589
694
|
operation,
|
|
590
695
|
operation: { responses, requestBody }
|
|
591
696
|
} = operationDefinition;
|
|
592
|
-
const operationName = getOperationName2({ verb, path: path4
|
|
697
|
+
const operationName = getOperationName2({ verb, path: path4 });
|
|
593
698
|
const tags = tag ? getTags({ verb, pathItem }) : [];
|
|
594
699
|
const isQuery2 = isQuery(verb, overrides);
|
|
595
700
|
const returnsJson = apiGen.getResponseType(responses) === "json";
|
|
596
701
|
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
702
|
if (returnsJson) {
|
|
626
703
|
const returnTypes = Object.entries(responses || {}).map(
|
|
627
|
-
([code, response]) =>
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
return [code, resolvedResponse, type];
|
|
635
|
-
}
|
|
704
|
+
([code, response]) => [
|
|
705
|
+
code,
|
|
706
|
+
apiGen.resolve(response),
|
|
707
|
+
wrapWithSchemeIfComponent(
|
|
708
|
+
apiGen.getTypeFromResponse(response, "readOnly") || factory.createKeywordTypeNode(ts4.SyntaxKind.UndefinedKeyword)
|
|
709
|
+
)
|
|
710
|
+
]
|
|
636
711
|
).filter(
|
|
637
712
|
([status, response]) => isDataResponse(status, includeDefault, apiGen.resolve(response), responses || {})
|
|
638
|
-
).filter(([_1, _2, type]) => type !== keywordType.void).map(
|
|
639
|
-
|
|
640
|
-
|
|
713
|
+
).filter(([_1, _2, type]) => type !== keywordType.void).map(([code, response, type]) => {
|
|
714
|
+
return ts4.addSyntheticLeadingComment(
|
|
715
|
+
type,
|
|
641
716
|
ts4.SyntaxKind.MultiLineCommentTrivia,
|
|
642
717
|
`* status ${code} ${response.description} `,
|
|
643
718
|
false
|
|
644
|
-
)
|
|
645
|
-
);
|
|
719
|
+
);
|
|
720
|
+
});
|
|
646
721
|
if (returnTypes.length > 0) {
|
|
647
722
|
ResponseType = factory.createUnionTypeNode(returnTypes);
|
|
648
723
|
}
|
|
@@ -677,10 +752,21 @@ async function generateApi(spec, {
|
|
|
677
752
|
}
|
|
678
753
|
return name;
|
|
679
754
|
}
|
|
755
|
+
for (const param of parameters) {
|
|
756
|
+
const name = generateName(param.name, param.in);
|
|
757
|
+
queryArg[name] = {
|
|
758
|
+
origin: "param",
|
|
759
|
+
name,
|
|
760
|
+
originalName: param.name,
|
|
761
|
+
type: wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(isReference(param) ? param : param.schema, void 0, "writeOnly")),
|
|
762
|
+
required: param.required,
|
|
763
|
+
param
|
|
764
|
+
};
|
|
765
|
+
}
|
|
680
766
|
if (requestBody) {
|
|
681
767
|
const body = apiGen.resolve(requestBody);
|
|
682
768
|
const schema = apiGen.getSchemaFromContent(body.content);
|
|
683
|
-
const type =
|
|
769
|
+
const type = wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(schema));
|
|
684
770
|
const schemaName = camelCase(
|
|
685
771
|
type.name || getReferenceName(schema) || typeof schema === "object" && "title" in schema && schema.title || "body"
|
|
686
772
|
);
|
|
@@ -689,24 +775,11 @@ async function generateApi(spec, {
|
|
|
689
775
|
origin: "body",
|
|
690
776
|
name,
|
|
691
777
|
originalName: schemaName,
|
|
692
|
-
type,
|
|
778
|
+
type: wrapWithSchemeIfComponent(apiGen.getTypeFromSchema(schema, void 0, "writeOnly")),
|
|
693
779
|
required: true,
|
|
694
780
|
body
|
|
695
781
|
};
|
|
696
782
|
}
|
|
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
783
|
const propertyName = (name) => {
|
|
711
784
|
if (typeof name === "string") {
|
|
712
785
|
return isValidIdentifier(name) ? factory.createIdentifier(name) : factory.createStringLiteral(name);
|
|
@@ -843,6 +916,105 @@ async function generateApi(spec, {
|
|
|
843
916
|
function generateMutationEndpointProps({}) {
|
|
844
917
|
return {};
|
|
845
918
|
}
|
|
919
|
+
function wrapWithSchemeIfComponent(typeNode) {
|
|
920
|
+
if (ts4.isTypeReferenceNode(typeNode) && ts4.isIdentifier(typeNode.typeName)) {
|
|
921
|
+
const typeName = typeNode.typeName.text;
|
|
922
|
+
const isEnumType = useEnumType && (apiGen.enumAliases.some((enumDecl) => {
|
|
923
|
+
if (ts4.isEnumDeclaration(enumDecl) || ts4.isTypeAliasDeclaration(enumDecl)) {
|
|
924
|
+
return enumDecl.name.text === typeName;
|
|
925
|
+
}
|
|
926
|
+
return false;
|
|
927
|
+
}) || apiGen.aliases.some((alias) => {
|
|
928
|
+
if (ts4.isTypeAliasDeclaration(alias) && alias.type) {
|
|
929
|
+
if (ts4.isUnionTypeNode(alias.type)) {
|
|
930
|
+
return alias.name.text === typeName;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
return false;
|
|
934
|
+
}));
|
|
935
|
+
if (isEnumType) {
|
|
936
|
+
return factory.createTypeReferenceNode(
|
|
937
|
+
factory.createQualifiedName(
|
|
938
|
+
factory.createIdentifier("Enum"),
|
|
939
|
+
typeNode.typeName
|
|
940
|
+
),
|
|
941
|
+
typeNode.typeArguments?.map(wrapWithSchemeIfComponent)
|
|
942
|
+
);
|
|
943
|
+
}
|
|
944
|
+
if (schemeTypeNames.has(typeName)) {
|
|
945
|
+
return factory.createTypeReferenceNode(
|
|
946
|
+
factory.createQualifiedName(
|
|
947
|
+
factory.createIdentifier("Scheme"),
|
|
948
|
+
typeNode.typeName
|
|
949
|
+
),
|
|
950
|
+
typeNode.typeArguments?.map(wrapWithSchemeIfComponent)
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
if (typeNode.typeArguments) {
|
|
954
|
+
return factory.createTypeReferenceNode(
|
|
955
|
+
typeNode.typeName,
|
|
956
|
+
typeNode.typeArguments.map(wrapWithSchemeIfComponent)
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
if (ts4.isArrayTypeNode(typeNode)) {
|
|
961
|
+
return factory.createArrayTypeNode(wrapWithSchemeIfComponent(typeNode.elementType));
|
|
962
|
+
}
|
|
963
|
+
if (ts4.isUnionTypeNode(typeNode)) {
|
|
964
|
+
const unionTypes = typeNode.types;
|
|
965
|
+
if (unionTypes.length > 0 && unionTypes.every(
|
|
966
|
+
(type) => ts4.isLiteralTypeNode(type) && (ts4.isStringLiteral(type.literal) || ts4.isNumericLiteral(type.literal))
|
|
967
|
+
)) {
|
|
968
|
+
const enumValues = unionTypes.map((type) => {
|
|
969
|
+
if (ts4.isLiteralTypeNode(type)) {
|
|
970
|
+
if (ts4.isStringLiteral(type.literal)) {
|
|
971
|
+
return type.literal.text;
|
|
972
|
+
} else if (ts4.isNumericLiteral(type.literal)) {
|
|
973
|
+
return type.literal.text;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
return null;
|
|
977
|
+
}).filter(Boolean);
|
|
978
|
+
const matchingEnum = apiGen.aliases.find((alias) => {
|
|
979
|
+
if (ts4.isTypeAliasDeclaration(alias) && ts4.isUnionTypeNode(alias.type)) {
|
|
980
|
+
const aliasValues = alias.type.types.map((type) => {
|
|
981
|
+
if (ts4.isLiteralTypeNode(type)) {
|
|
982
|
+
if (ts4.isStringLiteral(type.literal)) {
|
|
983
|
+
return type.literal.text;
|
|
984
|
+
} else if (ts4.isNumericLiteral(type.literal)) {
|
|
985
|
+
return type.literal.text;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
return null;
|
|
989
|
+
}).filter(Boolean);
|
|
990
|
+
return aliasValues.length === enumValues.length && aliasValues.every((val) => enumValues.includes(val));
|
|
991
|
+
}
|
|
992
|
+
return false;
|
|
993
|
+
});
|
|
994
|
+
if (matchingEnum && ts4.isTypeAliasDeclaration(matchingEnum)) {
|
|
995
|
+
return typeNode;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
return factory.createUnionTypeNode(typeNode.types.map(wrapWithSchemeIfComponent));
|
|
999
|
+
}
|
|
1000
|
+
if (ts4.isTypeLiteralNode(typeNode)) {
|
|
1001
|
+
return factory.createTypeLiteralNode(
|
|
1002
|
+
typeNode.members.map((member) => {
|
|
1003
|
+
if (ts4.isPropertySignature(member) && member.type) {
|
|
1004
|
+
return factory.updatePropertySignature(
|
|
1005
|
+
member,
|
|
1006
|
+
member.modifiers,
|
|
1007
|
+
member.name,
|
|
1008
|
+
member.questionToken,
|
|
1009
|
+
wrapWithSchemeIfComponent(member.type)
|
|
1010
|
+
);
|
|
1011
|
+
}
|
|
1012
|
+
return member;
|
|
1013
|
+
})
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
return typeNode;
|
|
1017
|
+
}
|
|
846
1018
|
}
|
|
847
1019
|
function generatePathExpression(path4, pathParameters, rootObject, isFlatArg, encodePathParams) {
|
|
848
1020
|
const expressions = [];
|
|
@@ -870,8 +1042,115 @@ function generatePathExpression(path4, pathParameters, rootObject, isFlatArg, en
|
|
|
870
1042
|
}
|
|
871
1043
|
|
|
872
1044
|
// src/index.ts
|
|
1045
|
+
import camelCase2 from "lodash.camelcase";
|
|
873
1046
|
var require2 = createRequire(__filename);
|
|
1047
|
+
async function ensureDirectoryExists(filePath) {
|
|
1048
|
+
const dirname = path3.dirname(filePath);
|
|
1049
|
+
if (!fs.existsSync(dirname)) {
|
|
1050
|
+
await fs.promises.mkdir(dirname, { recursive: true });
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
function fileExists(filePath) {
|
|
1054
|
+
try {
|
|
1055
|
+
return fs.statSync(filePath).isFile();
|
|
1056
|
+
} catch {
|
|
1057
|
+
return false;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
function getApiNameFromDir(dirPath) {
|
|
1061
|
+
const dirName = path3.basename(dirPath);
|
|
1062
|
+
return `${dirName}Api`;
|
|
1063
|
+
}
|
|
1064
|
+
async function ensureBaseFilesExist(outputDir) {
|
|
1065
|
+
const enhanceEndpointsPath = path3.join(outputDir, "enhanceEndpoints.ts");
|
|
1066
|
+
const indexPath = path3.join(outputDir, "index.ts");
|
|
1067
|
+
const apiName = getApiNameFromDir(outputDir);
|
|
1068
|
+
if (!fileExists(enhanceEndpointsPath)) {
|
|
1069
|
+
const enhanceEndpointsContent = `import api from './query.generated';
|
|
1070
|
+
|
|
1071
|
+
const enhancedApi = api.enhanceEndpoints({
|
|
1072
|
+
endpoints: {
|
|
1073
|
+
},
|
|
1074
|
+
});
|
|
1075
|
+
|
|
1076
|
+
export default enhancedApi;
|
|
1077
|
+
`;
|
|
1078
|
+
await fs.promises.writeFile(enhanceEndpointsPath, enhanceEndpointsContent, "utf-8");
|
|
1079
|
+
}
|
|
1080
|
+
if (!fileExists(indexPath)) {
|
|
1081
|
+
const indexContent = `export * from './query.generated';
|
|
1082
|
+
export {default as ${apiName}} from './enhanceEndpoints';
|
|
1083
|
+
`;
|
|
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]);
|
|
1091
|
+
}
|
|
1092
|
+
return "common";
|
|
1093
|
+
}
|
|
874
1094
|
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);
|
|
1100
|
+
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] = [];
|
|
1110
|
+
}
|
|
1111
|
+
acc[groupName].push(path4);
|
|
1112
|
+
return acc;
|
|
1113
|
+
}, {});
|
|
1114
|
+
for (const [groupName, paths2] of Object.entries(groupedPaths)) {
|
|
1115
|
+
const finalOutputPath = outputPath.replace("$1", groupName);
|
|
1116
|
+
if (filterEndpoint) {
|
|
1117
|
+
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1118
|
+
const path4 = operationDefinition.path;
|
|
1119
|
+
const pathGroupName = getGroupNameFromPath(path4, pattern);
|
|
1120
|
+
if (pathGroupName !== groupName) {
|
|
1121
|
+
return false;
|
|
1122
|
+
}
|
|
1123
|
+
const endpointFilter = filterEndpoint(groupName);
|
|
1124
|
+
if (endpointFilter instanceof RegExp) {
|
|
1125
|
+
return endpointFilter.test(operationName);
|
|
1126
|
+
}
|
|
1127
|
+
return true;
|
|
1128
|
+
};
|
|
1129
|
+
const groupOptions = {
|
|
1130
|
+
...commonConfig,
|
|
1131
|
+
outputFile: finalOutputPath,
|
|
1132
|
+
filterEndpoints: pathBasedFilter
|
|
1133
|
+
};
|
|
1134
|
+
await generateSingleEndpoint(groupOptions);
|
|
1135
|
+
} else {
|
|
1136
|
+
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1137
|
+
const path4 = operationDefinition.path;
|
|
1138
|
+
const pathGroupName = getGroupNameFromPath(path4, pattern);
|
|
1139
|
+
return pathGroupName === groupName;
|
|
1140
|
+
};
|
|
1141
|
+
const groupOptions = {
|
|
1142
|
+
...commonConfig,
|
|
1143
|
+
outputFile: finalOutputPath,
|
|
1144
|
+
filterEndpoints: pathBasedFilter
|
|
1145
|
+
};
|
|
1146
|
+
await generateSingleEndpoint(groupOptions);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
await generateSingleEndpoint(options);
|
|
1152
|
+
}
|
|
1153
|
+
async function generateSingleEndpoint(options) {
|
|
875
1154
|
const schemaLocation = options.schemaFile;
|
|
876
1155
|
const schemaAbsPath = isValidUrl(options.schemaFile) ? options.schemaFile : path3.resolve(process.cwd(), schemaLocation);
|
|
877
1156
|
const sourceCode = await enforceOazapftsTsVersion(async () => {
|
|
@@ -879,8 +1158,12 @@ async function generateEndpoints(options) {
|
|
|
879
1158
|
});
|
|
880
1159
|
const { outputFile, prettierConfigFile } = options;
|
|
881
1160
|
if (outputFile) {
|
|
1161
|
+
const outputPath = path3.resolve(process.cwd(), outputFile);
|
|
1162
|
+
await ensureDirectoryExists(outputPath);
|
|
1163
|
+
const outputDir = path3.dirname(outputPath);
|
|
1164
|
+
await ensureBaseFilesExist(outputDir);
|
|
882
1165
|
fs.writeFileSync(
|
|
883
|
-
|
|
1166
|
+
outputPath,
|
|
884
1167
|
await prettify(outputFile, sourceCode, prettierConfigFile)
|
|
885
1168
|
);
|
|
886
1169
|
} else {
|
|
@@ -891,13 +1174,60 @@ function parseConfig(fullConfig) {
|
|
|
891
1174
|
const outFiles = [];
|
|
892
1175
|
if ("outputFiles" in fullConfig) {
|
|
893
1176
|
const { outputFiles, ...commonConfig } = fullConfig;
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1177
|
+
let openApiDoc;
|
|
1178
|
+
if (isValidUrl(fullConfig.schemaFile)) {
|
|
1179
|
+
outFiles.push(fullConfig);
|
|
1180
|
+
return outFiles;
|
|
1181
|
+
} else {
|
|
1182
|
+
openApiDoc = JSON.parse(fs.readFileSync(fullConfig.schemaFile, "utf-8"));
|
|
900
1183
|
}
|
|
1184
|
+
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] = [];
|
|
1194
|
+
}
|
|
1195
|
+
acc[groupName].push(path4);
|
|
1196
|
+
return acc;
|
|
1197
|
+
}, {});
|
|
1198
|
+
Object.entries(groupedPaths).forEach(([groupName, paths2]) => {
|
|
1199
|
+
const finalOutputPath = outputPath.replace("$1", groupName);
|
|
1200
|
+
if (filterEndpoint) {
|
|
1201
|
+
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1202
|
+
const path4 = operationDefinition.path;
|
|
1203
|
+
const pathGroupName = getGroupNameFromPath(path4, pattern);
|
|
1204
|
+
if (pathGroupName !== groupName) {
|
|
1205
|
+
return false;
|
|
1206
|
+
}
|
|
1207
|
+
const endpointFilter = filterEndpoint(groupName);
|
|
1208
|
+
if (endpointFilter instanceof RegExp) {
|
|
1209
|
+
return endpointFilter.test(operationName);
|
|
1210
|
+
}
|
|
1211
|
+
return true;
|
|
1212
|
+
};
|
|
1213
|
+
outFiles.push({
|
|
1214
|
+
...commonConfig,
|
|
1215
|
+
outputFile: finalOutputPath,
|
|
1216
|
+
filterEndpoints: pathBasedFilter
|
|
1217
|
+
});
|
|
1218
|
+
} else {
|
|
1219
|
+
const pathBasedFilter = (operationName, operationDefinition) => {
|
|
1220
|
+
const path4 = operationDefinition.path;
|
|
1221
|
+
const pathGroupName = getGroupNameFromPath(path4, pattern);
|
|
1222
|
+
return pathGroupName === groupName;
|
|
1223
|
+
};
|
|
1224
|
+
outFiles.push({
|
|
1225
|
+
...commonConfig,
|
|
1226
|
+
outputFile: finalOutputPath,
|
|
1227
|
+
filterEndpoints: pathBasedFilter
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
901
1231
|
} else {
|
|
902
1232
|
outFiles.push(fullConfig);
|
|
903
1233
|
}
|