@bitstack/ng-query-codegen-openapi 0.0.30 → 0.0.31-alpha.1

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.js CHANGED
@@ -326,6 +326,13 @@ var FileWriterService = class {
326
326
  async writeFile(filePath, content) {
327
327
  try {
328
328
  const resolvedPath = import_node_path3.default.resolve(process.cwd(), filePath);
329
+ const fileName = import_node_path3.default.basename(resolvedPath);
330
+ if (fileName === "enhanceEndpoints.ts" && import_node_fs3.default.existsSync(resolvedPath)) {
331
+ return {
332
+ path: resolvedPath,
333
+ success: true
334
+ };
335
+ }
329
336
  await ensureDirectoryExists(resolvedPath);
330
337
  import_node_fs3.default.writeFileSync(resolvedPath, content);
331
338
  return {
@@ -353,7 +360,7 @@ var FileWriterService = class {
353
360
  return results;
354
361
  }
355
362
  /**
356
- * 為群組寫入標準檔案結構
363
+ * 為群組寫入 RTK Query 檔案結構
357
364
  * @param groupOutputDir - 群組輸出目錄
358
365
  * @param files - 檔案內容
359
366
  */
@@ -362,11 +369,11 @@ var FileWriterService = class {
362
369
  if (files.types) {
363
370
  filesToWrite[import_node_path3.default.join(groupOutputDir, "types.ts")] = files.types;
364
371
  }
365
- if (files.apiService) {
366
- filesToWrite[import_node_path3.default.join(groupOutputDir, "api.service.ts")] = files.apiService;
367
- }
368
372
  if (files.queryService) {
369
- filesToWrite[import_node_path3.default.join(groupOutputDir, "query.service.ts")] = files.queryService;
373
+ filesToWrite[import_node_path3.default.join(groupOutputDir, "query.generated.ts")] = files.queryService;
374
+ }
375
+ if (files.enhanceEndpoints) {
376
+ filesToWrite[import_node_path3.default.join(groupOutputDir, "enhanceEndpoints.ts")] = files.enhanceEndpoints;
370
377
  }
371
378
  if (files.index) {
372
379
  filesToWrite[import_node_path3.default.join(groupOutputDir, "index.ts")] = files.index;
@@ -383,9 +390,6 @@ var FileWriterService = class {
383
390
  if (sharedFiles.commonTypes) {
384
391
  filesToWrite[import_node_path3.default.join(outputDir, "common-types.ts")] = sharedFiles.commonTypes;
385
392
  }
386
- if (sharedFiles.cacheKeys) {
387
- filesToWrite[import_node_path3.default.join(outputDir, "cache-keys.ts")] = sharedFiles.cacheKeys;
388
- }
389
393
  if (sharedFiles.doNotModify) {
390
394
  filesToWrite[import_node_path3.default.join(outputDir, "DO_NOT_MODIFY.md")] = sharedFiles.doNotModify;
391
395
  }
@@ -414,7 +418,6 @@ var OpenApiParserService = class {
414
418
  this.v3Doc = v3Doc;
415
419
  this.apiGen = new import_generate2.default(v3Doc, {
416
420
  unionUndefined: options.unionUndefined,
417
- useEnumType: options.useEnumType,
418
421
  mergeReadWriteOnly: options.mergeReadWriteOnly
419
422
  });
420
423
  }
@@ -424,6 +427,12 @@ var OpenApiParserService = class {
424
427
  */
425
428
  initialize() {
426
429
  if (this.apiGen.spec.components?.schemas) {
430
+ Object.keys(this.apiGen.spec.components.schemas).forEach((schemaName) => {
431
+ const schema = this.apiGen.spec.components.schemas[schemaName];
432
+ if (schema && typeof schema === "object" && "title" in schema) {
433
+ delete schema.title;
434
+ }
435
+ });
427
436
  this.apiGen.preprocessComponents(this.apiGen.spec.components.schemas);
428
437
  Object.keys(this.apiGen.spec.components.schemas).forEach((schemaName) => {
429
438
  try {
@@ -462,64 +471,6 @@ var OpenApiParserService = class {
462
471
  }
463
472
  };
464
473
 
465
- // src/generators/cache-keys-generator.ts
466
- init_cjs_shims();
467
-
468
- // src/generators/utils-generator.ts
469
- init_cjs_shims();
470
- function generateUtilsFile() {
471
- return `/* eslint-disable */
472
- // [Warning] Generated automatically - do not edit manually
473
-
474
- /**
475
- * Clear undefined in object
476
- */
477
- export function withoutUndefined(obj?: Record<string, any>) {
478
- if(typeof obj === 'undefined') return;
479
- return Object.fromEntries(
480
- Object.entries(obj).filter(([_, v]) => v !== undefined && v !== null)
481
- );
482
- }
483
-
484
- `;
485
- }
486
- function toCamelCase(str) {
487
- return str.toLowerCase().replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
488
- }
489
-
490
- // src/generators/cache-keys-generator.ts
491
- function generateCacheKeysFile(allEndpointInfos) {
492
- const groupedKeys = allEndpointInfos.reduce((acc, info) => {
493
- if (!acc[info.groupKey]) {
494
- acc[info.groupKey] = [];
495
- }
496
- acc[info.groupKey].push({
497
- operationName: info.operationName,
498
- queryKeyName: info.queryKeyName
499
- });
500
- return acc;
501
- }, {});
502
- const enumEntries = Object.entries(groupedKeys).map(([groupKey, keys]) => {
503
- const groupComment = ` // ${groupKey.charAt(0).toUpperCase() + groupKey.slice(1)} related cache keys`;
504
- const keyEntries = keys.map(
505
- (key) => ` ${key.queryKeyName} = '${toCamelCase(key.queryKeyName)}',`
506
- ).join("\n");
507
- return `${groupComment}
508
- ${keyEntries}`;
509
- }).join("\n\n");
510
- return `// [Warning] Generated automatically - do not edit manually
511
-
512
- /**
513
- * Cache keys enum for all API queries
514
- */
515
- export enum ECacheKeys {
516
- ${enumEntries}
517
- }
518
-
519
- export default ECacheKeys;
520
- `;
521
- }
522
-
523
474
  // src/generators/common-types-generator.ts
524
475
  init_cjs_shims();
525
476
  function generateCommonTypesFile() {
@@ -540,11 +491,15 @@ export interface QueryConfig {
540
491
  keepUnusedDataFor?: number,
541
492
  }
542
493
 
494
+ export interface IRequestConfig extends RequestOptions {
495
+ timeout?: number;
496
+ }
497
+
543
498
  export type IRestFulEndpointsQueryReturn<TVariables> = TVariables extends void ?
544
- void | {fetchOptions?: RequestOptions;config?: QueryConfig;}:
499
+ (void | {fetchOptions?: IRequestConfig;}):
545
500
  {
546
501
  variables: TVariables;
547
- fetchOptions?: RequestOptions;
502
+ fetchOptions?: IRequestConfig;
548
503
  config?: QueryConfig;
549
504
  };
550
505
  `;
@@ -553,6 +508,19 @@ export type IRestFulEndpointsQueryReturn<TVariables> = TVariables extends void ?
553
508
  // src/generators/component-schema-generator.ts
554
509
  init_cjs_shims();
555
510
  var import_typescript = __toESM(require("typescript"));
511
+ function toPascalCase(name) {
512
+ return name.charAt(0).toUpperCase() + name.slice(1);
513
+ }
514
+ function renameIdentifier(node, oldName, newName) {
515
+ return import_typescript.default.transform(node, [
516
+ (context) => (rootNode) => import_typescript.default.visitNode(rootNode, function visit(node2) {
517
+ if (import_typescript.default.isIdentifier(node2) && node2.text === oldName) {
518
+ return import_typescript.default.factory.createIdentifier(newName);
519
+ }
520
+ return import_typescript.default.visitEachChild(node2, visit, context);
521
+ })
522
+ ]).transformed[0];
523
+ }
556
524
  function generateComponentSchemaFile(interfaces) {
557
525
  const printer = import_typescript.default.createPrinter({ newLine: import_typescript.default.NewLineKind.LineFeed });
558
526
  const resultFile = import_typescript.default.createSourceFile(
@@ -562,10 +530,19 @@ function generateComponentSchemaFile(interfaces) {
562
530
  false,
563
531
  import_typescript.default.ScriptKind.TS
564
532
  );
533
+ const renamedInterfaces = [];
534
+ const typeNameMapping = {};
535
+ Object.entries(interfaces).forEach(([originalName, node]) => {
536
+ const pascalCaseName = toPascalCase(originalName);
537
+ typeNameMapping[originalName] = pascalCaseName;
538
+ const renamedNode = renameIdentifier(node, originalName, pascalCaseName);
539
+ const printed = printer.printNode(import_typescript.default.EmitHint.Unspecified, renamedNode, resultFile);
540
+ renamedInterfaces.push(printed);
541
+ });
565
542
  return `/* eslint-disable */
566
- // [Warning] Generated automatically - do not edit manually
567
-
568
- ${Object.values(interfaces).map((i) => printer.printNode(import_typescript.default.EmitHint.Unspecified, i, resultFile)).join("\n")}
543
+ // [Warning] Generated automatically - do not edit manually
544
+
545
+ ${renamedInterfaces.join("\n")}
569
546
  `;
570
547
  }
571
548
 
@@ -621,7 +598,13 @@ var EndpointInfoExtractor = class {
621
598
  */
622
599
  extractSingleEndpointInfo(operationDefinition) {
623
600
  const { verb, path: path5, operation } = operationDefinition;
624
- const { operationNameSuffix = "", argSuffix = "Req", responseSuffix = "Res", queryMatch, endpointOverrides } = this.options;
601
+ const {
602
+ operationNameSuffix = "",
603
+ argSuffix = "Req",
604
+ responseSuffix = "Res",
605
+ queryMatch,
606
+ endpointOverrides
607
+ } = this.options;
625
608
  const operationName = getOperationName({ verb, path: path5 });
626
609
  const finalOperationName = operationNameSuffix ? capitalize(operationName + operationNameSuffix) : operationName;
627
610
  const argTypeName = capitalize(operationName + operationNameSuffix + argSuffix);
@@ -629,7 +612,9 @@ var EndpointInfoExtractor = class {
629
612
  const isQuery2 = isQuery(verb, path5, getOverrides(operationDefinition, endpointOverrides), queryMatch);
630
613
  const queryKeyName = `${operationName.replace(/([A-Z])/g, "_$1").toUpperCase()}`;
631
614
  const summary = operation.summary || `${verb.toUpperCase()} ${path5}`;
632
- const { queryParams, pathParams, isVoidArg } = this.extractParameters(operationDefinition);
615
+ const { queryParams, pathParams, isVoidArg, hasRequestBody } = this.extractParameters(operationDefinition);
616
+ const contentType = this.extractContentType(operation);
617
+ const tags = Array.isArray(operation.tags) ? operation.tags : [];
633
618
  return {
634
619
  operationName: finalOperationName,
635
620
  argTypeName,
@@ -641,7 +626,10 @@ var EndpointInfoExtractor = class {
641
626
  queryParams,
642
627
  pathParams,
643
628
  isVoidArg,
644
- summary
629
+ summary,
630
+ contentType,
631
+ hasRequestBody,
632
+ tags
645
633
  };
646
634
  }
647
635
  /**
@@ -651,15 +639,21 @@ var EndpointInfoExtractor = class {
651
639
  extractParameters(operationDefinition) {
652
640
  const { operation, pathItem } = operationDefinition;
653
641
  const operationParameters = this.resolveArray(operation.parameters);
654
- const pathItemParameters = this.resolveArray(pathItem.parameters).filter((pp) => !operationParameters.some((op) => op.name === pp.name && op.in === pp.in));
655
- const allParameters = (0, import_generate3.supportDeepObjects)([...pathItemParameters, ...operationParameters]).filter((param) => param.in !== "header");
642
+ const pathItemParameters = this.resolveArray(pathItem.parameters).filter(
643
+ (pp) => !operationParameters.some((op) => op.name === pp.name && op.in === pp.in)
644
+ );
645
+ const allParameters = (0, import_generate3.supportDeepObjects)([...pathItemParameters, ...operationParameters]).filter(
646
+ (param) => param.in !== "header"
647
+ );
656
648
  const queryParams = allParameters.filter((param) => param.in === "query");
657
649
  const pathParams = allParameters.filter((param) => param.in === "path");
650
+ const hasRequestBody = !!operation.requestBody;
658
651
  const isVoidArg = queryParams.length === 0 && pathParams.length === 0 && !operation.requestBody;
659
652
  return {
660
653
  queryParams,
661
654
  pathParams,
662
- isVoidArg
655
+ isVoidArg,
656
+ hasRequestBody
663
657
  };
664
658
  }
665
659
  /**
@@ -669,11 +663,46 @@ var EndpointInfoExtractor = class {
669
663
  if (!parameters) return [];
670
664
  return Array.isArray(parameters) ? parameters : [parameters];
671
665
  }
666
+ /**
667
+ * 提取操作的 content type
668
+ * @param operation - 操作對象
669
+ */
670
+ extractContentType(operation) {
671
+ if (!operation.requestBody) {
672
+ return "application/json";
673
+ }
674
+ const content = operation.requestBody.content;
675
+ if (!content || typeof content !== "object") {
676
+ return "application/json";
677
+ }
678
+ const contentTypes = Object.keys(content);
679
+ if (contentTypes.length === 0) {
680
+ return "application/json";
681
+ }
682
+ return contentTypes[0];
683
+ }
672
684
  };
673
685
 
674
686
  // src/generators/types-generator.ts
675
687
  init_cjs_shims();
688
+ var toPascalCase2 = (name) => {
689
+ return name.charAt(0).toUpperCase() + name.slice(1);
690
+ };
676
691
  function generateTypesFile(endpointInfos, _options, schemaInterfaces, operationDefinitions) {
692
+ const schemaTypeMap = {};
693
+ if (schemaInterfaces) {
694
+ Object.keys(schemaInterfaces).forEach((actualTypeName) => {
695
+ schemaTypeMap[actualTypeName] = actualTypeName;
696
+ if (actualTypeName.endsWith("Vo")) {
697
+ const openApiName = actualTypeName.slice(0, -2) + "VO";
698
+ schemaTypeMap[openApiName] = actualTypeName;
699
+ }
700
+ if (actualTypeName.endsWith("Dto")) {
701
+ const openApiName = actualTypeName.slice(0, -3) + "DTO";
702
+ schemaTypeMap[openApiName] = actualTypeName;
703
+ }
704
+ });
705
+ }
677
706
  let importStatement = `/* eslint-disable */
678
707
  // [Warning] Generated automatically - do not edit manually
679
708
 
@@ -690,35 +719,19 @@ function generateTypesFile(endpointInfos, _options, schemaInterfaces, operationD
690
719
  const reqTypeName = endpoint.argTypeName;
691
720
  const resTypeName = endpoint.responseTypeName;
692
721
  if (reqTypeName) {
693
- const requestTypeContent = generateRequestTypeContent(endpoint, operationDefinitions);
694
- if (requestTypeContent.trim() === "" || requestTypeContent.includes("TODO") || requestTypeContent.includes("[key: string]: any")) {
695
- endpointTypes.push(
696
- `export type ${reqTypeName} = void;`,
697
- ``
698
- );
722
+ const requestTypeContent = generateRequestTypeContent(endpoint, operationDefinitions, schemaTypeMap);
723
+ if (requestTypeContent.trim() === "") {
724
+ endpointTypes.push(`export type ${reqTypeName} = void;`, ``);
699
725
  } else {
700
- endpointTypes.push(
701
- `export type ${reqTypeName} = {`,
702
- requestTypeContent,
703
- `};`,
704
- ``
705
- );
726
+ endpointTypes.push(`export type ${reqTypeName} = {`, requestTypeContent, `};`, ``);
706
727
  }
707
728
  }
708
729
  if (resTypeName) {
709
- const responseTypeContent = generateResponseTypeContent(endpoint, operationDefinitions);
710
- if (responseTypeContent.trim() === "" || responseTypeContent.includes("TODO") || responseTypeContent.includes("[key: string]: any")) {
711
- endpointTypes.push(
712
- `export type ${resTypeName} = void;`,
713
- ``
714
- );
730
+ const responseTypeContent = generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeMap);
731
+ if (responseTypeContent.trim() === "") {
732
+ endpointTypes.push(`export type ${resTypeName} = void;`, ``);
715
733
  } else {
716
- endpointTypes.push(
717
- `export type ${resTypeName} = {`,
718
- responseTypeContent,
719
- `};`,
720
- ``
721
- );
734
+ endpointTypes.push(`export type ${resTypeName} = {`, responseTypeContent, `};`, ``);
722
735
  }
723
736
  }
724
737
  });
@@ -726,27 +739,23 @@ function generateTypesFile(endpointInfos, _options, schemaInterfaces, operationD
726
739
  typeDefinitions.push(endpointTypes.join("\n"));
727
740
  }
728
741
  if (typeDefinitions.length === 0) {
729
- typeDefinitions.push(
730
- `// \u6B64\u6A94\u6848\u7528\u65BC\u5B9A\u7FA9 API \u76F8\u95DC\u7684\u985E\u578B`,
731
- `// \u985E\u578B\u5B9A\u7FA9\u6703\u6839\u64DA OpenAPI Schema \u81EA\u52D5\u751F\u6210`,
732
- ``
733
- );
742
+ typeDefinitions.push(`// \u6B64\u6A94\u6848\u7528\u65BC\u5B9A\u7FA9 API \u76F8\u95DC\u7684\u985E\u578B`, `// \u985E\u578B\u5B9A\u7FA9\u6703\u6839\u64DA OpenAPI Schema \u81EA\u52D5\u751F\u6210`, ``);
734
743
  }
735
744
  return importStatement + typeDefinitions.join("\n\n");
736
745
  }
737
- function generateRequestTypeContent(endpoint, operationDefinitions) {
746
+ function generateRequestTypeContent(endpoint, operationDefinitions, schemaTypeMap = {}) {
738
747
  const properties = [];
739
748
  if (endpoint.queryParams && endpoint.queryParams.length > 0) {
740
749
  endpoint.queryParams.forEach((param) => {
741
750
  const optional = param.required ? "" : "?";
742
- const paramType = getTypeFromParameter(param);
751
+ const paramType = getTypeFromParameter(param, schemaTypeMap);
743
752
  properties.push(` ${param.name}${optional}: ${paramType};`);
744
753
  });
745
754
  }
746
755
  if (endpoint.pathParams && endpoint.pathParams.length > 0) {
747
756
  endpoint.pathParams.forEach((param) => {
748
757
  const optional = param.required ? "" : "?";
749
- const paramType = getTypeFromParameter(param);
758
+ const paramType = getTypeFromParameter(param, schemaTypeMap);
750
759
  properties.push(` ${param.name}${optional}: ${paramType};`);
751
760
  });
752
761
  }
@@ -757,16 +766,22 @@ function generateRequestTypeContent(endpoint, operationDefinitions) {
757
766
  if (operationDef?.operation?.requestBody) {
758
767
  const requestBody = operationDef.operation.requestBody;
759
768
  const content = requestBody.content;
760
- const jsonContent = content["application/json"];
769
+ const jsonContent = content["application/json"] || content["*/*"];
761
770
  const formContent = content["multipart/form-data"] || content["application/x-www-form-urlencoded"];
762
771
  if (jsonContent?.schema) {
763
- const bodyType = getTypeFromSchema(jsonContent.schema);
772
+ const bodyType = getTypeFromSchema(jsonContent.schema, schemaTypeMap, 1);
764
773
  properties.push(` body: ${bodyType};`);
765
774
  } else if (formContent?.schema) {
766
- const bodyType = getTypeFromSchema(formContent.schema);
775
+ const bodyType = getTypeFromSchema(formContent.schema, schemaTypeMap, 1);
767
776
  properties.push(` body: ${bodyType};`);
768
777
  } else {
769
- properties.push(` body?: any; // Request body from OpenAPI`);
778
+ const firstContent = Object.values(content)[0];
779
+ if (firstContent?.schema) {
780
+ const bodyType = getTypeFromSchema(firstContent.schema, schemaTypeMap, 1);
781
+ properties.push(` body: ${bodyType};`);
782
+ } else {
783
+ properties.push(` body?: any; // Request body from OpenAPI`);
784
+ }
770
785
  }
771
786
  }
772
787
  if (properties.length === 0) {
@@ -774,7 +789,7 @@ function generateRequestTypeContent(endpoint, operationDefinitions) {
774
789
  }
775
790
  return properties.join("\n");
776
791
  }
777
- function generateResponseTypeContent(endpoint, operationDefinitions) {
792
+ function generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeMap = {}) {
778
793
  const properties = [];
779
794
  const operationDef = operationDefinitions?.find((op) => {
780
795
  return op.operation?.operationId === endpoint.operationName || op.operation?.operationId === endpoint.operationName.toLowerCase() || // 也嘗試匹配 verb + path 組合
@@ -783,9 +798,9 @@ function generateResponseTypeContent(endpoint, operationDefinitions) {
783
798
  if (operationDef?.operation?.responses) {
784
799
  const successResponse = operationDef.operation.responses["200"] || operationDef.operation.responses["201"];
785
800
  if (successResponse?.content) {
786
- const jsonContent = successResponse.content["application/json"];
801
+ const jsonContent = successResponse.content["application/json"] || successResponse.content["*/*"] || Object.values(successResponse.content)[0];
787
802
  if (jsonContent?.schema) {
788
- const responseProps = parseSchemaProperties(jsonContent.schema);
803
+ const responseProps = parseSchemaProperties(jsonContent.schema, schemaTypeMap);
789
804
  properties.push(...responseProps);
790
805
  } else {
791
806
  properties.push(` // Success response from OpenAPI`);
@@ -798,83 +813,114 @@ function generateResponseTypeContent(endpoint, operationDefinitions) {
798
813
  }
799
814
  return properties.join("\n");
800
815
  }
801
- function parseSchemaProperties(schema) {
816
+ function parseSchemaProperties(schema, schemaTypeMap = {}) {
802
817
  const properties = [];
803
818
  if (schema.type === "object" && schema.properties) {
804
819
  const required = schema.required || [];
805
820
  Object.entries(schema.properties).forEach(([propName, propSchema]) => {
806
821
  const isRequired = required.includes(propName);
807
822
  const optional = isRequired ? "" : "?";
808
- const propType = getTypeFromSchema(propSchema);
809
- const description = propSchema.description ? ` // ${propSchema.description}` : "";
810
- properties.push(` ${propName}${optional}: ${propType};${description}`);
823
+ const propType = getTypeFromSchema(propSchema, schemaTypeMap, 1);
824
+ const needsQuotes = /[^a-zA-Z0-9_$]/.test(propName);
825
+ const quotedPropName = needsQuotes ? `"${propName}"` : propName;
826
+ if (propSchema.description) {
827
+ properties.push(` /** ${propSchema.description} */`);
828
+ }
829
+ properties.push(` ${quotedPropName}${optional}: ${propType};`);
811
830
  });
812
831
  }
813
832
  return properties;
814
833
  }
815
- function getTypeFromSchema(schema) {
834
+ function getTypeFromSchema(schema, schemaTypeMap = {}, indentLevel = 0) {
816
835
  if (!schema) return "any";
817
836
  if (schema.$ref) {
818
837
  const refPath = schema.$ref;
819
838
  if (refPath.startsWith("#/components/schemas/")) {
820
- const typeName = refPath.replace("#/components/schemas/", "");
821
- return `Schema.${typeName}`;
839
+ const originalTypeName = refPath.replace("#/components/schemas/", "");
840
+ const actualTypeName = schemaTypeMap[originalTypeName] || originalTypeName;
841
+ const pascalCaseTypeName = toPascalCase2(actualTypeName);
842
+ const baseType2 = `Schema.${pascalCaseTypeName}`;
843
+ return schema.nullable ? `${baseType2} | null` : baseType2;
822
844
  }
823
845
  }
846
+ let baseType;
824
847
  switch (schema.type) {
825
848
  case "string":
826
849
  if (schema.enum) {
827
- return schema.enum.map((val) => `"${val}"`).join(" | ");
850
+ baseType = schema.enum.map((val) => `"${val}"`).join(" | ");
851
+ } else if (schema.format === "binary") {
852
+ baseType = "Blob";
853
+ } else {
854
+ baseType = "string";
828
855
  }
829
- return "string";
856
+ break;
830
857
  case "number":
831
858
  case "integer":
832
- return "number";
859
+ baseType = "number";
860
+ break;
833
861
  case "boolean":
834
- return "boolean";
862
+ baseType = "boolean";
863
+ break;
835
864
  case "array":
836
- const itemType = schema.items ? getTypeFromSchema(schema.items) : "any";
837
- return `${itemType}[]`;
865
+ const itemType = schema.items ? getTypeFromSchema(schema.items, schemaTypeMap, indentLevel) : "any";
866
+ const needsParentheses = itemType.includes("|");
867
+ baseType = needsParentheses ? `(${itemType})[]` : `${itemType}[]`;
868
+ break;
838
869
  case "object":
839
870
  if (schema.properties) {
840
- const props = Object.entries(schema.properties).map(([key, propSchema]) => {
841
- const required = schema.required || [];
842
- const optional = required.includes(key) ? "" : "?";
843
- const type = getTypeFromSchema(propSchema);
844
- return `${key}${optional}: ${type}`;
845
- }).join("; ");
846
- return `{ ${props} }`;
871
+ const entries = Object.entries(schema.properties);
872
+ if (entries.length === 0) {
873
+ if (schema.additionalProperties) {
874
+ const valueType = schema.additionalProperties === true ? "any" : getTypeFromSchema(schema.additionalProperties, schemaTypeMap, indentLevel);
875
+ baseType = `Record<string, ${valueType}>`;
876
+ } else {
877
+ baseType = "{}";
878
+ }
879
+ } else {
880
+ const nextIndent = " ".repeat(indentLevel + 1);
881
+ const currentIndent = " ".repeat(indentLevel);
882
+ const props = [];
883
+ entries.forEach(([key, propSchema]) => {
884
+ const required = schema.required || [];
885
+ const optional = required.includes(key) ? "" : "?";
886
+ const type = getTypeFromSchema(propSchema, schemaTypeMap, indentLevel + 1);
887
+ const needsQuotes = /[^a-zA-Z0-9_$]/.test(key);
888
+ const quotedKey = needsQuotes ? `"${key}"` : key;
889
+ if (propSchema.description) {
890
+ props.push(`${nextIndent}/** ${propSchema.description} */`);
891
+ }
892
+ props.push(`${nextIndent}${quotedKey}${optional}: ${type};`);
893
+ });
894
+ baseType = `{
895
+ ${props.join("\n")}
896
+ ${currentIndent}}`;
897
+ }
898
+ } else if (schema.additionalProperties) {
899
+ const valueType = schema.additionalProperties === true ? "any" : getTypeFromSchema(schema.additionalProperties, schemaTypeMap, indentLevel);
900
+ baseType = `Record<string, ${valueType}>`;
901
+ } else {
902
+ baseType = "any";
847
903
  }
848
- return "any";
904
+ break;
849
905
  default:
850
- return "any";
906
+ baseType = "any";
907
+ break;
851
908
  }
909
+ return schema.nullable ? `${baseType} | null` : baseType;
852
910
  }
853
- function getTypeFromParameter(param) {
911
+ function getTypeFromParameter(param, schemaTypeMap = {}) {
854
912
  if (!param.schema) return "any";
855
- return getTypeFromSchema(param.schema);
856
- }
857
-
858
- // src/generators/index-generator.ts
859
- init_cjs_shims();
860
- function generateIndexFile(groupKey, options) {
861
- const { groupKey: optionsGroupKey } = options;
862
- return `export * from './types';
863
- export * from './api.service';
864
- export * from './query.service';
865
- `;
913
+ return getTypeFromSchema(param.schema, schemaTypeMap);
866
914
  }
867
915
 
868
- // src/services/query-code-generator.ts
916
+ // src/generators/rtk-query-generator.ts
869
917
  init_cjs_shims();
870
-
871
- // src/generators/query-service-generator.ts
872
- init_cjs_shims();
873
- function generateQueryServiceFile(endpointInfos, options) {
918
+ function generateRtkQueryFile(endpointInfos, options) {
874
919
  const { groupKey, refetchOnMountOrArgChange = 60 } = options;
875
920
  const queryServiceName = groupKey ? `${groupKey.charAt(0).toUpperCase() + groupKey.slice(1)}QueryService` : "QueryService";
876
921
  const apiServiceName = groupKey ? `${groupKey.charAt(0).toUpperCase() + groupKey.slice(1)}ApiService` : "ApiService";
877
- const queryMethods = endpointInfos.filter((info) => info.isQuery).map((info) => `
922
+ const queryMethods = endpointInfos.filter((info) => info.isQuery).map(
923
+ (info) => `
878
924
  /**
879
925
  * ${info.summary}
880
926
  */
@@ -887,8 +933,10 @@ function generateQueryServiceFile(endpointInfos, options) {
887
933
  fetchOptions: args?.fetchOptions,
888
934
  config: args?.config,
889
935
  })${info.argTypeName !== "VoidApiArg" ? "(args)" : "()"};
890
- }`).join("");
891
- const mutationMethods = endpointInfos.filter((info) => !info.isQuery).map((info) => `
936
+ }`
937
+ ).join("");
938
+ const mutationMethods = endpointInfos.filter((info) => !info.isQuery).map(
939
+ (info) => `
892
940
  /**
893
941
  * ${info.summary}
894
942
  */
@@ -902,8 +950,10 @@ function generateQueryServiceFile(endpointInfos, options) {
902
950
  return this.apiService.${info.operationName}(${info.argTypeName !== "VoidApiArg" ? "args" : ""});
903
951
  },
904
952
  });
905
- }`).join("");
906
- const lazyQueryMethods = endpointInfos.filter((info) => info.isQuery).map((info) => `
953
+ }`
954
+ ).join("");
955
+ const lazyQueryMethods = endpointInfos.filter((info) => info.isQuery).map(
956
+ (info) => `
907
957
  /**
908
958
  * ${info.summary}
909
959
  */
@@ -922,7 +972,8 @@ function generateQueryServiceFile(endpointInfos, options) {
922
972
  return this.apiService.${info.operationName}(${info.argTypeName !== "VoidApiArg" ? "args" : ""});
923
973
  }
924
974
  };
925
- }`).join("");
975
+ }`
976
+ ).join("");
926
977
  return `/* eslint-disable */
927
978
  // [Warning] Generated automatically - do not edit manually
928
979
 
@@ -946,38 +997,15 @@ ${queryMethods}${mutationMethods}${lazyQueryMethods}
946
997
  `;
947
998
  }
948
999
 
949
- // src/services/query-code-generator.ts
950
- var QueryCodeGenerator = class {
951
- constructor(options) {
952
- this.options = options;
953
- }
954
- /**
955
- * 生成 Query Service 檔案內容
956
- */
957
- generateQueryService(endpointInfos) {
958
- const generatorOptions = {
959
- ...this.options,
960
- apiConfiguration: this.options.apiConfiguration || {
961
- file: "@/store/webapi",
962
- importName: "WebApiConfiguration"
963
- }
964
- };
965
- return generateQueryServiceFile(endpointInfos, generatorOptions);
966
- }
967
- };
968
-
969
- // src/services/api-service-generator.ts
970
- init_cjs_shims();
971
-
972
- // src/generators/api-service-generator.ts
1000
+ // src/generators/rtk-enhance-endpoints-generator.ts
973
1001
  init_cjs_shims();
974
- function generateApiServiceFile(endpointInfos, options) {
1002
+ function generateRtkEnhanceEndpointsFile(endpointInfos, options) {
975
1003
  const { apiConfiguration, httpClient, groupKey } = options;
976
1004
  const apiServiceClassName = groupKey ? `${groupKey.charAt(0).toUpperCase() + groupKey.slice(1)}ApiService` : "ApiService";
977
1005
  return `/* eslint-disable */
978
1006
  // [Warning] Generated automatically - do not edit manually
979
1007
 
980
- import { ${httpClient.importName} } from '${httpClient.file}';
1008
+ import { ${httpClient.importReturnTypeName} } from '${httpClient.file}';
981
1009
  import { Injectable, inject } from '@angular/core';
982
1010
  import { Observable } from 'rxjs';
983
1011
  import { ${apiConfiguration.importName} } from '${apiConfiguration.file}';
@@ -990,11 +1018,12 @@ import {${endpointInfos.map((info) => ` ${info.argTypeName}, ${info.responseType
990
1018
  })
991
1019
  export class ${apiServiceClassName} {
992
1020
  private config = inject(${apiConfiguration.importName});
993
- private http = inject(${httpClient.importName});
1021
+ private http = inject(${httpClient.importReturnTypeName});
994
1022
 
995
1023
  ${endpointInfos.map((info) => {
996
1024
  const isGet = info.verb.toUpperCase() === "GET";
997
1025
  const hasArgs = info.argTypeName !== "VoidApiArg";
1026
+ const hasRequestBody = info.hasRequestBody;
998
1027
  const generateUrlTemplate = (path5) => {
999
1028
  const hasPathParams = path5.includes("{");
1000
1029
  if (hasPathParams && hasArgs) {
@@ -1005,21 +1034,18 @@ ${endpointInfos.map((info) => {
1005
1034
  }
1006
1035
  };
1007
1036
  const hasQueryParams = info.queryParams.length > 0;
1008
- const hasBody = !isGet && hasArgs && !info.isVoidArg;
1037
+ const hasBody = !isGet && hasArgs;
1009
1038
  const generateRequestOptions = () => {
1010
- const options2 = [
1011
- "...args.fetchOptions"
1012
- ];
1013
- if (hasBody || !isGet) {
1014
- options2.push(`headers: { 'Content-Type': 'application/json', ...args.fetchOptions?.headers }`);
1015
- }
1016
- if (hasQueryParams && hasArgs) {
1017
- options2.push(generateQueryParams(info.queryParams));
1039
+ let paramsSection = "";
1040
+ if (info.queryParams && info.queryParams.length > 0) {
1041
+ const paramsLines = info.queryParams.map((param) => `${param.name}: args.variables.${param.name},`).join("\n");
1042
+ paramsSection = `params: {${paramsLines}},`;
1018
1043
  }
1019
- if (hasBody) {
1020
- options2.push("body: args.variables.body");
1021
- }
1022
- return options2.length > 0 ? `{ ${options2.join(", ")} }` : "{}";
1044
+ return `{
1045
+ ...args.fetchOptions,
1046
+ headers: { 'Content-Type': '${info.contentType}', ...args.fetchOptions?.headers },
1047
+ ${paramsSection}${info.hasRequestBody ? `body: args.variables.body,` : ""}
1048
+ }`;
1023
1049
  };
1024
1050
  return `
1025
1051
  /**
@@ -1035,32 +1061,6 @@ ${endpointInfos.map((info) => {
1035
1061
  }
1036
1062
  `;
1037
1063
  }
1038
- function generateQueryParams(queryParams) {
1039
- const paramEntries = queryParams.map(
1040
- (param) => `${param.name}: args.variables.${param.name}`
1041
- ).join(", ");
1042
- return `params: withoutUndefined({ ${paramEntries} })`;
1043
- }
1044
-
1045
- // src/services/api-service-generator.ts
1046
- var ApiServiceGenerator = class {
1047
- constructor(options) {
1048
- this.options = options;
1049
- }
1050
- /**
1051
- * 生成 API Service 檔案內容
1052
- */
1053
- generateApiService(endpointInfos) {
1054
- const generatorOptions = {
1055
- ...this.options,
1056
- apiConfiguration: this.options.apiConfiguration || {
1057
- file: "@/store/webapi",
1058
- importName: "WebApiConfiguration"
1059
- }
1060
- };
1061
- return generateApiServiceFile(endpointInfos, generatorOptions);
1062
- }
1063
- };
1064
1064
 
1065
1065
  // src/services/api-code-generator.ts
1066
1066
  var ApiCodeGenerator = class {
@@ -1068,36 +1068,41 @@ var ApiCodeGenerator = class {
1068
1068
  this.parserService = parserService;
1069
1069
  this.options = options;
1070
1070
  this.infoExtractor = new EndpointInfoExtractor(options);
1071
- this.queryGenerator = new QueryCodeGenerator(options);
1072
- this.apiServiceGenerator = new ApiServiceGenerator(options);
1073
1071
  }
1074
1072
  infoExtractor;
1075
- queryGenerator;
1076
- apiServiceGenerator;
1077
1073
  /**
1078
- * 生成完整的 API 程式碼
1074
+ * 生成完整的 RTK Query 程式碼
1079
1075
  */
1080
1076
  async generate() {
1081
1077
  const operationDefinitions = this.parserService.getOperationDefinitions(this.options.filterEndpoints);
1082
1078
  const endpointInfos = this.infoExtractor.extractEndpointInfos(operationDefinitions);
1079
+ return this.generateRtkQueryCode(endpointInfos);
1080
+ }
1081
+ /**
1082
+ * 生成 RTK Query 代碼
1083
+ */
1084
+ generateRtkQueryCode(endpointInfos) {
1083
1085
  const typesContent = this.generateTypes(endpointInfos);
1084
- const apiServiceContent = this.generateApiService(endpointInfos);
1085
- const queryServiceContent = this.generateQueryService(endpointInfos);
1086
+ const rtkQueryContent = generateRtkQueryFile(endpointInfos, this.options);
1087
+ const enhanceEndpointsContent = generateRtkEnhanceEndpointsFile(endpointInfos, this.options);
1086
1088
  const indexContent = this.generateIndex();
1087
- const allEndpointCacheKeys = endpointInfos.filter((info) => info.isQuery).map((info) => ({
1088
- operationName: info.operationName,
1089
- queryKeyName: info.queryKeyName,
1090
- groupKey: this.options.groupKey || "_common"
1091
- }));
1092
1089
  const operationNames = endpointInfos.map((info) => info.operationName);
1090
+ const allTags = /* @__PURE__ */ new Set();
1091
+ endpointInfos.forEach((info) => {
1092
+ if (info.tags && Array.isArray(info.tags)) {
1093
+ info.tags.forEach((tag) => allTags.add(tag));
1094
+ }
1095
+ });
1093
1096
  return {
1094
1097
  operationNames,
1098
+ tags: Array.from(allTags),
1095
1099
  files: {
1096
1100
  types: typesContent,
1097
- apiService: apiServiceContent,
1098
- queryService: queryServiceContent,
1101
+ queryService: rtkQueryContent,
1102
+ // RTK Query 檔案
1099
1103
  index: indexContent,
1100
- allEndpointCacheKeys
1104
+ enhanceEndpoints: enhanceEndpointsContent
1105
+ // 新增的 enhance endpoints 檔案
1101
1106
  }
1102
1107
  };
1103
1108
  }
@@ -1113,43 +1118,35 @@ var ApiCodeGenerator = class {
1113
1118
  }
1114
1119
  };
1115
1120
  const apiGen = this.parserService.getApiGenerator();
1116
- const schemaInterfaces = apiGen.aliases.reduce((curr, alias) => {
1117
- if (import_typescript2.default.isInterfaceDeclaration(alias) || import_typescript2.default.isTypeAliasDeclaration(alias)) {
1118
- const name = alias.name.text;
1119
- return {
1120
- ...curr,
1121
- [name]: alias
1122
- };
1123
- }
1124
- return curr;
1125
- }, {});
1121
+ const schemaInterfaces = apiGen.aliases.reduce(
1122
+ (curr, alias) => {
1123
+ if (import_typescript2.default.isInterfaceDeclaration(alias) || import_typescript2.default.isTypeAliasDeclaration(alias)) {
1124
+ const name = alias.name.text;
1125
+ return {
1126
+ ...curr,
1127
+ [name]: alias
1128
+ };
1129
+ }
1130
+ return curr;
1131
+ },
1132
+ {}
1133
+ );
1126
1134
  const operationDefinitions = this.parserService.getOperationDefinitions(this.options.filterEndpoints);
1127
1135
  return generateTypesFile(endpointInfos, generatorOptions, schemaInterfaces, operationDefinitions);
1128
1136
  }
1129
- /**
1130
- * 生成 API Service 檔案內容
1131
- */
1132
- generateApiService(endpointInfos) {
1133
- return this.apiServiceGenerator.generateApiService(endpointInfos);
1134
- }
1135
- /**
1136
- * 生成 Query Service 檔案內容
1137
- */
1138
- generateQueryService(endpointInfos) {
1139
- return this.queryGenerator.generateQueryService(endpointInfos);
1140
- }
1141
1137
  /**
1142
1138
  * 生成 Index 檔案內容
1143
1139
  */
1144
1140
  generateIndex() {
1145
- const generatorOptions = {
1146
- ...this.options,
1147
- apiConfiguration: this.options.apiConfiguration || {
1148
- file: "@/store/webapi",
1149
- importName: "WebApiConfiguration"
1150
- }
1151
- };
1152
- return generateIndexFile(this.options.groupKey || "", generatorOptions);
1141
+ const groupKey = this.options.groupKey || "";
1142
+ const exportName = groupKey ? `${groupKey.charAt(0).toLowerCase() + groupKey.slice(1)}Api` : "api";
1143
+ return `/* eslint-disable */
1144
+ // [Warning] Generated automatically - do not edit manually
1145
+
1146
+ export { default as ${exportName} } from "./enhanceEndpoints";
1147
+ export * from "./query.generated";
1148
+ export * from "./types";
1149
+ `;
1153
1150
  }
1154
1151
  // /**
1155
1152
  // * 獲取已解析的 parser service(供外部使用)
@@ -1166,6 +1163,46 @@ var ApiCodeGenerator = class {
1166
1163
  // }
1167
1164
  };
1168
1165
 
1166
+ // src/generators/utils-generator.ts
1167
+ init_cjs_shims();
1168
+ function generateUtilsFile() {
1169
+ return `/* eslint-disable */
1170
+ // [Warning] Generated automatically - do not edit manually
1171
+
1172
+ /**
1173
+ * Clear undefined in object
1174
+ */
1175
+ export function withoutUndefined(obj?: Record<string, any>) {
1176
+ if(typeof obj === 'undefined') return;
1177
+ return Object.fromEntries(
1178
+ Object.entries(obj).filter(([_, v]) => v !== undefined && v !== null)
1179
+ );
1180
+ }
1181
+
1182
+ `;
1183
+ }
1184
+
1185
+ // src/generators/tag-types-generator.ts
1186
+ init_cjs_shims();
1187
+ function generateTagTypesFile(tags) {
1188
+ if (tags.length === 0) {
1189
+ return `/* eslint-disable */
1190
+ // [Warning] Generated automatically - do not edit manually
1191
+
1192
+ export enum ECacheTagTypes {
1193
+ }
1194
+ `;
1195
+ }
1196
+ const enumEntries = tags.sort().map((tag) => ` ${tag} = '${tag}',`).join("\n");
1197
+ return `/* eslint-disable */
1198
+ // [Warning] Generated automatically - do not edit manually
1199
+
1200
+ export enum ECacheTagTypes {
1201
+ ${enumEntries}
1202
+ }
1203
+ `;
1204
+ }
1205
+
1169
1206
  // src/services/unified-code-generator.ts
1170
1207
  var UnifiedCodeGenerator = class {
1171
1208
  _options;
@@ -1176,17 +1213,18 @@ var UnifiedCodeGenerator = class {
1176
1213
  openApiDoc = null;
1177
1214
  parserService = null;
1178
1215
  schemaInterfaces = {};
1179
- allEndpointCacheKeys = [];
1180
1216
  actualSchemaFile = "";
1181
1217
  // 生成內容存儲
1182
1218
  generatedContent = {
1183
1219
  groups: [],
1184
- cacheKeys: null,
1185
1220
  commonTypes: "",
1186
1221
  componentSchema: "",
1187
1222
  doNotModify: "",
1188
- utils: ""
1223
+ utils: "",
1224
+ tagTypes: ""
1189
1225
  };
1226
+ // 收集所有 tags
1227
+ allTags = /* @__PURE__ */ new Set();
1190
1228
  constructor(options) {
1191
1229
  this._options = options;
1192
1230
  }
@@ -1196,11 +1234,11 @@ var UnifiedCodeGenerator = class {
1196
1234
  async generateAll() {
1197
1235
  await this.prepare();
1198
1236
  await this.generateApi();
1199
- this.generateCacheKeysContent();
1200
1237
  this.generateCommonTypesContent();
1201
1238
  this.generateSchemaContent();
1202
1239
  this.generateUtilsContent();
1203
1240
  this.generateDoNotModifyContent();
1241
+ this.generateTagTypesContent();
1204
1242
  return await this.release();
1205
1243
  }
1206
1244
  /**
@@ -1253,18 +1291,15 @@ var UnifiedCodeGenerator = class {
1253
1291
  outputPath: groupInfo.outputPath,
1254
1292
  content: groupContent
1255
1293
  });
1294
+ if (groupContent.tags && Array.isArray(groupContent.tags)) {
1295
+ groupContent.tags.forEach((tag) => this.allTags.add(tag));
1296
+ }
1256
1297
  }
1257
1298
  } catch (error) {
1258
1299
  throw new Error(`\u7FA4\u7D44 ${groupInfo.groupKey} \u751F\u6210\u5931\u6557: ${error}`);
1259
1300
  }
1260
1301
  }
1261
1302
  }
1262
- /**
1263
- * 生成 cache keys
1264
- */
1265
- async generateCacheKeysContent() {
1266
- this.generatedContent.cacheKeys = generateCacheKeysFile(this.allEndpointCacheKeys);
1267
- }
1268
1303
  /**
1269
1304
  * 生成 common types
1270
1305
  */
@@ -1289,6 +1324,13 @@ var UnifiedCodeGenerator = class {
1289
1324
  async generateUtilsContent() {
1290
1325
  this.generatedContent.utils = generateUtilsFile();
1291
1326
  }
1327
+ /**
1328
+ * 生成 Tag Types
1329
+ */
1330
+ async generateTagTypesContent() {
1331
+ const tagsArray = Array.from(this.allTags);
1332
+ this.generatedContent.tagTypes = generateTagTypesFile(tagsArray);
1333
+ }
1292
1334
  /**
1293
1335
  * 發佈階段:統一寫入所有檔案
1294
1336
  */
@@ -1305,8 +1347,8 @@ var UnifiedCodeGenerator = class {
1305
1347
  groupOutputDir,
1306
1348
  {
1307
1349
  types: group.content.files.types,
1308
- apiService: group.content.files.apiService,
1309
1350
  queryService: group.content.files.queryService,
1351
+ enhanceEndpoints: group.content.files.enhanceEndpoints,
1310
1352
  index: group.content.files.index
1311
1353
  }
1312
1354
  );
@@ -1318,11 +1360,10 @@ var UnifiedCodeGenerator = class {
1318
1360
  }
1319
1361
  }
1320
1362
  const outputDir = this.generatedContent.groups[0] ? import_node_path4.default.dirname(import_node_path4.default.dirname(this.generatedContent.groups[0].outputPath)) : "./generated";
1321
- if (this.generatedContent.cacheKeys || this.generatedContent.commonTypes || this.generatedContent.doNotModify || this.generatedContent.utils) {
1363
+ if (this.generatedContent.commonTypes || this.generatedContent.doNotModify || this.generatedContent.utils) {
1322
1364
  const sharedResults = await this.fileWriterService.writeSharedFiles(
1323
1365
  outputDir,
1324
1366
  {
1325
- cacheKeys: this.generatedContent.cacheKeys || void 0,
1326
1367
  commonTypes: this.generatedContent.commonTypes || void 0,
1327
1368
  doNotModify: this.generatedContent.doNotModify || void 0,
1328
1369
  utils: this.generatedContent.utils || void 0
@@ -1330,6 +1371,13 @@ var UnifiedCodeGenerator = class {
1330
1371
  );
1331
1372
  results.push(...sharedResults);
1332
1373
  }
1374
+ if (this.generatedContent.tagTypes) {
1375
+ const tagTypesResult = await this.fileWriterService.writeFile(
1376
+ import_node_path4.default.join(outputDir, "tagTypes.ts"),
1377
+ this.generatedContent.tagTypes
1378
+ );
1379
+ results.push(tagTypesResult);
1380
+ }
1333
1381
  if (this.generatedContent.componentSchema) {
1334
1382
  const schemaResults = await this.fileWriterService.writeSchemaFile(
1335
1383
  outputDir,
@@ -1337,6 +1385,12 @@ var UnifiedCodeGenerator = class {
1337
1385
  );
1338
1386
  results.push(...schemaResults);
1339
1387
  }
1388
+ const mainIndexContent = this.generateMainIndex(generatedGroups);
1389
+ const mainIndexResult = await this.fileWriterService.writeFile(
1390
+ import_node_path4.default.join(outputDir, "index.ts"),
1391
+ mainIndexContent
1392
+ );
1393
+ results.push(mainIndexResult);
1340
1394
  } catch (error) {
1341
1395
  errors.push(error);
1342
1396
  }
@@ -1366,12 +1420,19 @@ var UnifiedCodeGenerator = class {
1366
1420
  }
1367
1421
  const apiGenerator = new ApiCodeGenerator(this.parserService, groupOptions);
1368
1422
  const result = await apiGenerator.generate();
1369
- if (result.files && "allEndpointCacheKeys" in result.files) {
1370
- const cacheKeys = result.files.allEndpointCacheKeys;
1371
- this.allEndpointCacheKeys.push(...cacheKeys);
1372
- }
1373
1423
  return result;
1374
1424
  }
1425
+ /**
1426
+ * 生成主 index.ts 檔案
1427
+ */
1428
+ generateMainIndex(generatedGroups) {
1429
+ const exports2 = generatedGroups.map((groupKey) => `export * from "./${groupKey}";`).join("\n");
1430
+ return `/* eslint-disable */
1431
+ // [Warning] Generated automatically - do not edit manually
1432
+
1433
+ ${exports2}
1434
+ `;
1435
+ }
1375
1436
  };
1376
1437
 
1377
1438
  // src/index.ts