@acrool/rtk-query-codegen-openapi 1.3.0-alpha.1 → 1.4.0-alpha.0

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
@@ -108,7 +108,7 @@ init_cjs_shims();
108
108
  // src/services/unified-code-generator.ts
109
109
  init_cjs_shims();
110
110
  var import_node_path4 = __toESM(require("node:path"));
111
- var import_typescript3 = __toESM(require("typescript"));
111
+ var import_typescript4 = __toESM(require("typescript"));
112
112
 
113
113
  // src/services/openapi-service.ts
114
114
  init_cjs_shims();
@@ -514,7 +514,7 @@ function renameIdentifier(node, oldName, newName) {
514
514
  })
515
515
  ]).transformed[0];
516
516
  }
517
- function generateComponentSchemaFile(interfaces) {
517
+ function generateComponentSchemaFile(interfaces, includeOnly) {
518
518
  const printer = import_typescript.default.createPrinter({ newLine: import_typescript.default.NewLineKind.LineFeed });
519
519
  const resultFile = import_typescript.default.createSourceFile(
520
520
  "component-schema.ts",
@@ -528,6 +528,9 @@ function generateComponentSchemaFile(interfaces) {
528
528
  Object.entries(interfaces).forEach(([originalName, node]) => {
529
529
  const pascalCaseName = toPascalCase(originalName);
530
530
  typeNameMapping[originalName] = pascalCaseName;
531
+ if (includeOnly && !includeOnly.has(originalName)) {
532
+ return;
533
+ }
531
534
  const renamedNode = renameIdentifier(node, originalName, pascalCaseName);
532
535
  const printed = printer.printNode(import_typescript.default.EmitHint.Unspecified, renamedNode, resultFile);
533
536
  renamedInterfaces.push(printed);
@@ -566,7 +569,7 @@ function generateDoNotModifyFile() {
566
569
 
567
570
  // src/services/api-code-generator.ts
568
571
  init_cjs_shims();
569
- var import_typescript2 = __toESM(require("typescript"));
572
+ var import_typescript3 = __toESM(require("typescript"));
570
573
 
571
574
  // src/services/endpoint-info-extractor.ts
572
575
  init_cjs_shims();
@@ -668,10 +671,46 @@ var EndpointInfoExtractor = class {
668
671
 
669
672
  // src/generators/types-generator.ts
670
673
  init_cjs_shims();
674
+ var import_typescript2 = __toESM(require("typescript"));
671
675
  var toPascalCase2 = (name) => {
672
676
  return name.charAt(0).toUpperCase() + name.slice(1);
673
677
  };
674
- function generateTypesFile(endpointInfos, _options, schemaInterfaces, operationDefinitions) {
678
+ function renameIdentifier2(node, oldName, newName) {
679
+ return import_typescript2.default.transform(node, [
680
+ (context) => (rootNode) => import_typescript2.default.visitNode(rootNode, function visit(node2) {
681
+ if (import_typescript2.default.isIdentifier(node2) && node2.text === oldName) {
682
+ return import_typescript2.default.factory.createIdentifier(newName);
683
+ }
684
+ return import_typescript2.default.visitEachChild(node2, visit, context);
685
+ })
686
+ ]).transformed[0];
687
+ }
688
+ function prefixSharedSchemaRefs(node, allSchemaNames, localSchemaNames, declarationName) {
689
+ const sharedNames = /* @__PURE__ */ new Set();
690
+ for (const name of allSchemaNames) {
691
+ if (!localSchemaNames.has(name)) {
692
+ sharedNames.add(toPascalCase2(name));
693
+ }
694
+ }
695
+ return import_typescript2.default.transform(node, [
696
+ (context) => (rootNode) => import_typescript2.default.visitNode(rootNode, function visit(node2) {
697
+ if (import_typescript2.default.isTypeReferenceNode(node2) && import_typescript2.default.isIdentifier(node2.typeName)) {
698
+ const name = node2.typeName.text;
699
+ if (sharedNames.has(name) && name !== declarationName) {
700
+ const qualifiedName = import_typescript2.default.factory.createQualifiedName(
701
+ import_typescript2.default.factory.createIdentifier("Schema"),
702
+ import_typescript2.default.factory.createIdentifier(name)
703
+ );
704
+ return import_typescript2.default.factory.createTypeReferenceNode(qualifiedName, node2.typeArguments);
705
+ }
706
+ }
707
+ return import_typescript2.default.visitEachChild(node2, visit, context);
708
+ })
709
+ ]).transformed[0];
710
+ }
711
+ function generateTypesFile(endpointInfos, _options, schemaInterfaces, operationDefinitions, localSchemaOptions) {
712
+ const localSchemaNames = localSchemaOptions?.localSchemaNames ?? /* @__PURE__ */ new Set();
713
+ const localSchemaInterfaces = localSchemaOptions?.localSchemaInterfaces ?? {};
675
714
  const schemaTypeMap = {};
676
715
  if (schemaInterfaces) {
677
716
  Object.keys(schemaInterfaces).forEach((actualTypeName) => {
@@ -686,23 +725,41 @@ function generateTypesFile(endpointInfos, _options, schemaInterfaces, operationD
686
725
  }
687
726
  });
688
727
  }
728
+ const hasSharedSchemaTypes = schemaInterfaces && Object.keys(schemaInterfaces).some(
729
+ (name) => !localSchemaNames.has(name)
730
+ );
689
731
  let importStatement = `/* eslint-disable */
690
- // [Warning] Generated automatically - do not edit manually
691
-
732
+ // [Warning] Generated automatically - do not edit manually
733
+
692
734
  `;
693
- const hasSchemaTypes = schemaInterfaces && Object.keys(schemaInterfaces).length > 0;
694
- if (hasSchemaTypes) {
735
+ if (hasSharedSchemaTypes) {
695
736
  importStatement += `import * as Schema from "../schema";
696
737
  `;
697
738
  }
698
739
  importStatement += "\n";
699
740
  const typeDefinitions = [];
741
+ if (Object.keys(localSchemaInterfaces).length > 0) {
742
+ const printer = import_typescript2.default.createPrinter({ newLine: import_typescript2.default.NewLineKind.LineFeed });
743
+ const resultFile = import_typescript2.default.createSourceFile("types.ts", "", import_typescript2.default.ScriptTarget.Latest, false, import_typescript2.default.ScriptKind.TS);
744
+ const localTypeDefs = [];
745
+ const allSchemaNameSet = new Set(schemaInterfaces ? Object.keys(schemaInterfaces) : []);
746
+ for (const [originalName, node] of Object.entries(localSchemaInterfaces)) {
747
+ const pascalCaseName = toPascalCase2(originalName);
748
+ let transformedNode = renameIdentifier2(node, originalName, pascalCaseName);
749
+ transformedNode = prefixSharedSchemaRefs(transformedNode, allSchemaNameSet, localSchemaNames, pascalCaseName);
750
+ const printed = printer.printNode(import_typescript2.default.EmitHint.Unspecified, transformedNode, resultFile);
751
+ localTypeDefs.push(printed);
752
+ }
753
+ if (localTypeDefs.length > 0) {
754
+ typeDefinitions.push(localTypeDefs.join("\n"));
755
+ }
756
+ }
700
757
  const endpointTypes = [];
701
758
  endpointInfos.forEach((endpoint) => {
702
759
  const reqTypeName = endpoint.argTypeName;
703
760
  const resTypeName = endpoint.responseTypeName;
704
761
  if (reqTypeName) {
705
- const requestTypeContent = generateRequestTypeContent(endpoint, operationDefinitions, schemaTypeMap);
762
+ const requestTypeContent = generateRequestTypeContent(endpoint, operationDefinitions, schemaTypeMap, localSchemaNames);
706
763
  if (requestTypeContent.trim() === "") {
707
764
  endpointTypes.push(
708
765
  `export type ${reqTypeName} = void;`,
@@ -718,7 +775,7 @@ function generateTypesFile(endpointInfos, _options, schemaInterfaces, operationD
718
775
  }
719
776
  }
720
777
  if (resTypeName) {
721
- const responseTypeResult = generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeMap);
778
+ const responseTypeResult = generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeMap, localSchemaNames);
722
779
  if (responseTypeResult.content.trim() === "") {
723
780
  endpointTypes.push(
724
781
  `export type ${resTypeName} = void;`,
@@ -751,19 +808,19 @@ function generateTypesFile(endpointInfos, _options, schemaInterfaces, operationD
751
808
  }
752
809
  return importStatement + typeDefinitions.join("\n\n");
753
810
  }
754
- function generateRequestTypeContent(endpoint, operationDefinitions, schemaTypeMap = {}) {
811
+ function generateRequestTypeContent(endpoint, operationDefinitions, schemaTypeMap = {}, localSchemaNames = /* @__PURE__ */ new Set()) {
755
812
  const properties = [];
756
813
  if (endpoint.queryParams && endpoint.queryParams.length > 0) {
757
814
  endpoint.queryParams.forEach((param) => {
758
815
  const optional = param.required ? "" : "?";
759
- const paramType = getTypeFromParameter(param, schemaTypeMap);
816
+ const paramType = getTypeFromParameter(param, schemaTypeMap, localSchemaNames);
760
817
  properties.push(` ${param.name}${optional}: ${paramType};`);
761
818
  });
762
819
  }
763
820
  if (endpoint.pathParams && endpoint.pathParams.length > 0) {
764
821
  endpoint.pathParams.forEach((param) => {
765
822
  const optional = param.required ? "" : "?";
766
- const paramType = getTypeFromParameter(param, schemaTypeMap);
823
+ const paramType = getTypeFromParameter(param, schemaTypeMap, localSchemaNames);
767
824
  properties.push(` ${param.name}${optional}: ${paramType};`);
768
825
  });
769
826
  }
@@ -777,15 +834,15 @@ function generateRequestTypeContent(endpoint, operationDefinitions, schemaTypeMa
777
834
  const jsonContent = content["application/json"] || content["*/*"];
778
835
  const formContent = content["multipart/form-data"] || content["application/x-www-form-urlencoded"];
779
836
  if (jsonContent?.schema) {
780
- const bodyType = getTypeFromSchema(jsonContent.schema, schemaTypeMap, 1);
837
+ const bodyType = getTypeFromSchema(jsonContent.schema, schemaTypeMap, 1, localSchemaNames);
781
838
  properties.push(` body: ${bodyType};`);
782
839
  } else if (formContent?.schema) {
783
- const bodyType = getTypeFromSchema(formContent.schema, schemaTypeMap, 1);
840
+ const bodyType = getTypeFromSchema(formContent.schema, schemaTypeMap, 1, localSchemaNames);
784
841
  properties.push(` body: ${bodyType};`);
785
842
  } else {
786
843
  const firstContent = Object.values(content)[0];
787
844
  if (firstContent?.schema) {
788
- const bodyType = getTypeFromSchema(firstContent.schema, schemaTypeMap, 1);
845
+ const bodyType = getTypeFromSchema(firstContent.schema, schemaTypeMap, 1, localSchemaNames);
789
846
  properties.push(` body: ${bodyType};`);
790
847
  } else {
791
848
  properties.push(` body?: any; // Request body from OpenAPI`);
@@ -797,7 +854,7 @@ function generateRequestTypeContent(endpoint, operationDefinitions, schemaTypeMa
797
854
  }
798
855
  return properties.join("\n");
799
856
  }
800
- function generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeMap = {}) {
857
+ function generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeMap = {}, localSchemaNames = /* @__PURE__ */ new Set()) {
801
858
  const operationDef = operationDefinitions?.find((op) => {
802
859
  return op.operation?.operationId === endpoint.operationName || op.operation?.operationId === endpoint.operationName.toLowerCase() || // 也嘗試匹配 verb + path 組合
803
860
  op.verb === endpoint.verb.toLowerCase() && op.path === endpoint.path;
@@ -809,12 +866,12 @@ function generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeM
809
866
  if (jsonContent?.schema) {
810
867
  const schema = jsonContent.schema;
811
868
  if (schema.$ref || schema.type !== "object" || !schema.properties) {
812
- const directType = getTypeFromSchema(schema, schemaTypeMap, 0);
869
+ const directType = getTypeFromSchema(schema, schemaTypeMap, 0, localSchemaNames);
813
870
  if (directType && directType !== "any") {
814
871
  return { content: directType, isDirectType: true };
815
872
  }
816
873
  }
817
- const responseProps = parseSchemaProperties(schema, schemaTypeMap);
874
+ const responseProps = parseSchemaProperties(schema, schemaTypeMap, localSchemaNames);
818
875
  if (responseProps.length > 0) {
819
876
  return { content: responseProps.join("\n"), isDirectType: false };
820
877
  }
@@ -823,14 +880,14 @@ function generateResponseTypeContent(endpoint, operationDefinitions, schemaTypeM
823
880
  }
824
881
  return { content: "", isDirectType: false };
825
882
  }
826
- function parseSchemaProperties(schema, schemaTypeMap = {}) {
883
+ function parseSchemaProperties(schema, schemaTypeMap = {}, localSchemaNames = /* @__PURE__ */ new Set()) {
827
884
  const properties = [];
828
885
  if (schema.type === "object" && schema.properties) {
829
886
  const required = schema.required || [];
830
887
  Object.entries(schema.properties).forEach(([propName, propSchema]) => {
831
888
  const isRequired = required.includes(propName);
832
889
  const optional = isRequired ? "" : "?";
833
- const propType = getTypeFromSchema(propSchema, schemaTypeMap, 1);
890
+ const propType = getTypeFromSchema(propSchema, schemaTypeMap, 1, localSchemaNames);
834
891
  const needsQuotes = /[^a-zA-Z0-9_$]/.test(propName);
835
892
  const quotedPropName = needsQuotes ? `"${propName}"` : propName;
836
893
  if (propSchema.description) {
@@ -841,7 +898,7 @@ function parseSchemaProperties(schema, schemaTypeMap = {}) {
841
898
  }
842
899
  return properties;
843
900
  }
844
- function getTypeFromSchema(schema, schemaTypeMap = {}, indentLevel = 0) {
901
+ function getTypeFromSchema(schema, schemaTypeMap = {}, indentLevel = 0, localSchemaNames = /* @__PURE__ */ new Set()) {
845
902
  if (!schema) return "any";
846
903
  if (schema.$ref) {
847
904
  const refPath = schema.$ref;
@@ -849,7 +906,7 @@ function getTypeFromSchema(schema, schemaTypeMap = {}, indentLevel = 0) {
849
906
  const originalTypeName = refPath.replace("#/components/schemas/", "");
850
907
  const actualTypeName = schemaTypeMap[originalTypeName] || originalTypeName;
851
908
  const pascalCaseTypeName = toPascalCase2(actualTypeName);
852
- const baseType2 = `Schema.${pascalCaseTypeName}`;
909
+ const baseType2 = localSchemaNames.has(originalTypeName) ? pascalCaseTypeName : `Schema.${pascalCaseTypeName}`;
853
910
  return schema.nullable ? `${baseType2} | null` : baseType2;
854
911
  }
855
912
  }
@@ -872,7 +929,7 @@ function getTypeFromSchema(schema, schemaTypeMap = {}, indentLevel = 0) {
872
929
  baseType = "boolean";
873
930
  break;
874
931
  case "array":
875
- const itemType = schema.items ? getTypeFromSchema(schema.items, schemaTypeMap, indentLevel) : "any";
932
+ const itemType = schema.items ? getTypeFromSchema(schema.items, schemaTypeMap, indentLevel, localSchemaNames) : "any";
876
933
  const needsParentheses = itemType.includes("|");
877
934
  baseType = needsParentheses ? `(${itemType})[]` : `${itemType}[]`;
878
935
  break;
@@ -881,7 +938,7 @@ function getTypeFromSchema(schema, schemaTypeMap = {}, indentLevel = 0) {
881
938
  const entries = Object.entries(schema.properties);
882
939
  if (entries.length === 0) {
883
940
  if (schema.additionalProperties) {
884
- const valueType = schema.additionalProperties === true ? "any" : getTypeFromSchema(schema.additionalProperties, schemaTypeMap, indentLevel);
941
+ const valueType = schema.additionalProperties === true ? "any" : getTypeFromSchema(schema.additionalProperties, schemaTypeMap, indentLevel, localSchemaNames);
885
942
  baseType = `Record<string, ${valueType}>`;
886
943
  } else {
887
944
  baseType = "{}";
@@ -893,7 +950,7 @@ function getTypeFromSchema(schema, schemaTypeMap = {}, indentLevel = 0) {
893
950
  entries.forEach(([key, propSchema]) => {
894
951
  const required = schema.required || [];
895
952
  const optional = required.includes(key) ? "" : "?";
896
- const type = getTypeFromSchema(propSchema, schemaTypeMap, indentLevel + 1);
953
+ const type = getTypeFromSchema(propSchema, schemaTypeMap, indentLevel + 1, localSchemaNames);
897
954
  const needsQuotes = /[^a-zA-Z0-9_$]/.test(key);
898
955
  const quotedKey = needsQuotes ? `"${key}"` : key;
899
956
  if (propSchema.description) {
@@ -906,7 +963,7 @@ ${props.join("\n")}
906
963
  ${currentIndent}}`;
907
964
  }
908
965
  } else if (schema.additionalProperties) {
909
- const valueType = schema.additionalProperties === true ? "any" : getTypeFromSchema(schema.additionalProperties, schemaTypeMap, indentLevel);
966
+ const valueType = schema.additionalProperties === true ? "any" : getTypeFromSchema(schema.additionalProperties, schemaTypeMap, indentLevel, localSchemaNames);
910
967
  baseType = `Record<string, ${valueType}>`;
911
968
  } else {
912
969
  baseType = "any";
@@ -918,9 +975,9 @@ ${currentIndent}}`;
918
975
  }
919
976
  return schema.nullable ? `${baseType} | null` : baseType;
920
977
  }
921
- function getTypeFromParameter(param, schemaTypeMap = {}) {
978
+ function getTypeFromParameter(param, schemaTypeMap = {}, localSchemaNames = /* @__PURE__ */ new Set()) {
922
979
  if (!param.schema) return "any";
923
- return getTypeFromSchema(param.schema, schemaTypeMap);
980
+ return getTypeFromSchema(param.schema, schemaTypeMap, 0, localSchemaNames);
924
981
  }
925
982
 
926
983
  // src/generators/rtk-query-generator.ts
@@ -1117,7 +1174,7 @@ var ApiCodeGenerator = class {
1117
1174
  };
1118
1175
  const apiGen = this.parserService.getApiGenerator();
1119
1176
  const schemaInterfaces = apiGen.aliases.reduce((curr, alias) => {
1120
- if (import_typescript2.default.isInterfaceDeclaration(alias) || import_typescript2.default.isTypeAliasDeclaration(alias)) {
1177
+ if (import_typescript3.default.isInterfaceDeclaration(alias) || import_typescript3.default.isTypeAliasDeclaration(alias)) {
1121
1178
  const name = alias.name.text;
1122
1179
  return {
1123
1180
  ...curr,
@@ -1201,6 +1258,150 @@ ${enumEntries}
1201
1258
  `;
1202
1259
  }
1203
1260
 
1261
+ // src/utils/schema-ref-analyzer.ts
1262
+ init_cjs_shims();
1263
+ function collectRefsFromSchema(schema, refs) {
1264
+ if (!schema || typeof schema !== "object") return;
1265
+ if (schema.$ref && typeof schema.$ref === "string") {
1266
+ const match = schema.$ref.match(/^#\/components\/schemas\/(.+)$/);
1267
+ if (match) {
1268
+ refs.add(match[1]);
1269
+ }
1270
+ }
1271
+ if (schema.properties) {
1272
+ for (const prop of Object.values(schema.properties)) {
1273
+ collectRefsFromSchema(prop, refs);
1274
+ }
1275
+ }
1276
+ if (schema.items) {
1277
+ collectRefsFromSchema(schema.items, refs);
1278
+ }
1279
+ if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
1280
+ collectRefsFromSchema(schema.additionalProperties, refs);
1281
+ }
1282
+ for (const key of ["allOf", "oneOf", "anyOf"]) {
1283
+ if (Array.isArray(schema[key])) {
1284
+ for (const item of schema[key]) {
1285
+ collectRefsFromSchema(item, refs);
1286
+ }
1287
+ }
1288
+ }
1289
+ }
1290
+ function collectDirectRefs(operationDefs) {
1291
+ const refs = /* @__PURE__ */ new Set();
1292
+ for (const opDef of operationDefs) {
1293
+ const op = opDef.operation;
1294
+ if (op.parameters) {
1295
+ for (const param of op.parameters) {
1296
+ const p = param;
1297
+ if (p.schema) {
1298
+ collectRefsFromSchema(p.schema, refs);
1299
+ }
1300
+ }
1301
+ }
1302
+ if (op.requestBody) {
1303
+ const rb = op.requestBody;
1304
+ if (rb.content) {
1305
+ for (const ct of Object.values(rb.content)) {
1306
+ if (ct.schema) {
1307
+ collectRefsFromSchema(ct.schema, refs);
1308
+ }
1309
+ }
1310
+ }
1311
+ }
1312
+ if (op.responses) {
1313
+ for (const resp of Object.values(op.responses)) {
1314
+ const r = resp;
1315
+ if (r.content) {
1316
+ for (const ct of Object.values(r.content)) {
1317
+ if (ct.schema) {
1318
+ collectRefsFromSchema(ct.schema, refs);
1319
+ }
1320
+ }
1321
+ }
1322
+ }
1323
+ }
1324
+ }
1325
+ return refs;
1326
+ }
1327
+ function resolveTransitiveDeps(directRefs, allSchemas) {
1328
+ const resolved = /* @__PURE__ */ new Set();
1329
+ const queue = [...directRefs];
1330
+ while (queue.length > 0) {
1331
+ const name = queue.pop();
1332
+ if (resolved.has(name)) continue;
1333
+ resolved.add(name);
1334
+ const schema = allSchemas[name];
1335
+ if (!schema) continue;
1336
+ const nestedRefs = /* @__PURE__ */ new Set();
1337
+ collectRefsFromSchema(schema, nestedRefs);
1338
+ for (const ref of nestedRefs) {
1339
+ if (!resolved.has(ref)) {
1340
+ queue.push(ref);
1341
+ }
1342
+ }
1343
+ }
1344
+ return resolved;
1345
+ }
1346
+ function analyzeSchemaRefs(groupOperations, allSchemas, allSchemaNames) {
1347
+ const groupRefs = /* @__PURE__ */ new Map();
1348
+ for (const [groupKey, opDefs] of groupOperations) {
1349
+ const directRefs = collectDirectRefs(opDefs);
1350
+ const fullRefs = resolveTransitiveDeps(directRefs, allSchemas);
1351
+ groupRefs.set(groupKey, fullRefs);
1352
+ }
1353
+ const refCountMap = /* @__PURE__ */ new Map();
1354
+ for (const [groupKey, refs] of groupRefs) {
1355
+ for (const schemaName of refs) {
1356
+ if (!refCountMap.has(schemaName)) {
1357
+ refCountMap.set(schemaName, /* @__PURE__ */ new Set());
1358
+ }
1359
+ refCountMap.get(schemaName).add(groupKey);
1360
+ }
1361
+ }
1362
+ const sharedSchemas = /* @__PURE__ */ new Set();
1363
+ const groupLocalSchemas = /* @__PURE__ */ new Map();
1364
+ const unusedSchemas = /* @__PURE__ */ new Set();
1365
+ for (const schemaName of allSchemaNames) {
1366
+ const groups = refCountMap.get(schemaName);
1367
+ if (!groups || groups.size === 0) {
1368
+ unusedSchemas.add(schemaName);
1369
+ } else if (groups.size === 1) {
1370
+ const groupKey = [...groups][0];
1371
+ if (!groupLocalSchemas.has(groupKey)) {
1372
+ groupLocalSchemas.set(groupKey, /* @__PURE__ */ new Set());
1373
+ }
1374
+ groupLocalSchemas.get(groupKey).add(schemaName);
1375
+ } else {
1376
+ sharedSchemas.add(schemaName);
1377
+ }
1378
+ }
1379
+ let changed = true;
1380
+ while (changed) {
1381
+ changed = false;
1382
+ for (const [groupKey, localSchemas] of groupLocalSchemas) {
1383
+ for (const schemaName of [...localSchemas]) {
1384
+ const schema = allSchemas[schemaName];
1385
+ if (!schema) continue;
1386
+ const deps = /* @__PURE__ */ new Set();
1387
+ collectRefsFromSchema(schema, deps);
1388
+ for (const dep of deps) {
1389
+ for (const [otherGroup, otherLocals] of groupLocalSchemas) {
1390
+ if (otherGroup !== groupKey && otherLocals.has(dep)) {
1391
+ sharedSchemas.add(dep);
1392
+ sharedSchemas.add(schemaName);
1393
+ otherLocals.delete(dep);
1394
+ localSchemas.delete(schemaName);
1395
+ changed = true;
1396
+ }
1397
+ }
1398
+ }
1399
+ }
1400
+ }
1401
+ }
1402
+ return { sharedSchemas, groupLocalSchemas, unusedSchemas };
1403
+ }
1404
+
1204
1405
  // src/services/unified-code-generator.ts
1205
1406
  var UnifiedCodeGenerator = class {
1206
1407
  _options;
@@ -1223,6 +1424,10 @@ var UnifiedCodeGenerator = class {
1223
1424
  };
1224
1425
  // 收集所有 tags
1225
1426
  allTags = /* @__PURE__ */ new Set();
1427
+ // 收集每個 group 的 operation definitions(用於 schema 引用分析)
1428
+ groupOperationDefs = /* @__PURE__ */ new Map();
1429
+ // 收集每個 group 的生成選項(用於重新生成 types)
1430
+ groupGenerationOptions = /* @__PURE__ */ new Map();
1226
1431
  constructor(options) {
1227
1432
  this._options = options;
1228
1433
  }
@@ -1232,6 +1437,7 @@ var UnifiedCodeGenerator = class {
1232
1437
  async generateAll() {
1233
1438
  await this.prepare();
1234
1439
  await this.generateApi();
1440
+ this.splitSchemaByUsage();
1235
1441
  this.generateCommonTypesContent();
1236
1442
  this.generateSchemaContent();
1237
1443
  this.generateUtilsContent();
@@ -1258,7 +1464,7 @@ var UnifiedCodeGenerator = class {
1258
1464
  this.parserService.initialize();
1259
1465
  const apiGen = this.parserService.getApiGenerator();
1260
1466
  this.schemaInterfaces = apiGen.aliases.reduce((curr, alias) => {
1261
- if (import_typescript3.default.isInterfaceDeclaration(alias) || import_typescript3.default.isTypeAliasDeclaration(alias)) {
1467
+ if (import_typescript4.default.isInterfaceDeclaration(alias) || import_typescript4.default.isTypeAliasDeclaration(alias)) {
1262
1468
  const name = alias.name.text;
1263
1469
  return {
1264
1470
  ...curr,
@@ -1298,6 +1504,55 @@ var UnifiedCodeGenerator = class {
1298
1504
  }
1299
1505
  }
1300
1506
  }
1507
+ /**
1508
+ * 分析 schema 引用,將只被單一 group 使用的 schema 移到該 group 的 types.ts
1509
+ */
1510
+ splitSchemaByUsage() {
1511
+ if (!this.openApiDoc || this.groupOperationDefs.size === 0) return;
1512
+ const rawSchemas = this.openApiDoc.components?.schemas ?? {};
1513
+ const allSchemaNames = Object.keys(this.schemaInterfaces);
1514
+ const analysis = analyzeSchemaRefs(
1515
+ this.groupOperationDefs,
1516
+ rawSchemas,
1517
+ allSchemaNames
1518
+ );
1519
+ this.sharedSchemaNames = analysis.sharedSchemas;
1520
+ for (const group of this.generatedContent.groups) {
1521
+ const localNames = analysis.groupLocalSchemas.get(group.groupKey);
1522
+ if (!localNames || localNames.size === 0) continue;
1523
+ const groupOptions = this.groupGenerationOptions.get(group.groupKey);
1524
+ if (!groupOptions || !this.parserService) continue;
1525
+ const localSchemaInterfaces = {};
1526
+ for (const name of localNames) {
1527
+ if (this.schemaInterfaces[name]) {
1528
+ localSchemaInterfaces[name] = this.schemaInterfaces[name];
1529
+ }
1530
+ }
1531
+ const infoExtractor = new EndpointInfoExtractor(groupOptions);
1532
+ const operationDefs = this.groupOperationDefs.get(group.groupKey) ?? [];
1533
+ const endpointInfos = infoExtractor.extractEndpointInfos(operationDefs);
1534
+ const generatorOptions = {
1535
+ ...groupOptions,
1536
+ apiConfiguration: groupOptions.apiConfiguration || {
1537
+ file: "@/store/webapi",
1538
+ importName: "WebApiConfiguration"
1539
+ }
1540
+ };
1541
+ const newTypesContent = generateTypesFile(
1542
+ endpointInfos,
1543
+ generatorOptions,
1544
+ this.schemaInterfaces,
1545
+ operationDefs,
1546
+ {
1547
+ localSchemaInterfaces,
1548
+ localSchemaNames: localNames
1549
+ }
1550
+ );
1551
+ group.content.files.types = newTypesContent;
1552
+ }
1553
+ }
1554
+ // 儲存 shared schema 名稱(只有這些會寫入 schema.ts)
1555
+ sharedSchemaNames = null;
1301
1556
  /**
1302
1557
  * 生成 common types
1303
1558
  */
@@ -1305,10 +1560,13 @@ var UnifiedCodeGenerator = class {
1305
1560
  this.generatedContent.commonTypes = generateCommonTypesFile();
1306
1561
  }
1307
1562
  /**
1308
- * 生成Schema
1563
+ * 生成Schema(只包含 shared types,排除 group-local 和未使用的 types)
1309
1564
  */
1310
1565
  async generateSchemaContent() {
1311
- this.generatedContent.componentSchema = generateComponentSchemaFile(this.schemaInterfaces);
1566
+ this.generatedContent.componentSchema = generateComponentSchemaFile(
1567
+ this.schemaInterfaces,
1568
+ this.sharedSchemaNames ?? void 0
1569
+ );
1312
1570
  }
1313
1571
  /**
1314
1572
  * 生成 DO_NOT_MODIFY.md
@@ -1416,6 +1674,9 @@ var UnifiedCodeGenerator = class {
1416
1674
  if (!this.openApiDoc || !this.parserService) {
1417
1675
  throw new Error("OpenAPI \u6587\u6A94\u672A\u521D\u59CB\u5316\uFF0C\u8ACB\u5148\u8ABF\u7528 prepare()");
1418
1676
  }
1677
+ const groupOpDefs = this.parserService.getOperationDefinitions(groupOptions.filterEndpoints);
1678
+ this.groupOperationDefs.set(groupInfo.groupKey, groupOpDefs);
1679
+ this.groupGenerationOptions.set(groupInfo.groupKey, groupOptions);
1419
1680
  const apiGenerator = new ApiCodeGenerator(this.parserService, groupOptions);
1420
1681
  const result = await apiGenerator.generate();
1421
1682
  return result;
@@ -1424,11 +1685,12 @@ var UnifiedCodeGenerator = class {
1424
1685
  * 生成主 index.ts 檔案
1425
1686
  */
1426
1687
  generateMainIndex(generatedGroups) {
1427
- const exports2 = generatedGroups.map((groupKey) => `export * from "./${groupKey}";`).join("\n");
1688
+ const groupExports = generatedGroups.map((groupKey) => `export * from "./${groupKey}";`).join("\n");
1428
1689
  return `/* eslint-disable */
1429
1690
  // [Warning] Generated automatically - do not edit manually
1430
1691
 
1431
- ${exports2}
1692
+ export * from "./schema";
1693
+ ${groupExports}
1432
1694
  `;
1433
1695
  }
1434
1696
  };