ts-openapi-codegen 2.1.0-beta.8 → 2.1.0-beta.9

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.
Files changed (133) hide show
  1. package/README.md +4 -0
  2. package/README.rus.md +4 -0
  3. package/dist/cli/analyzeDiff/__tests__/analyzeDiff.cli.test.js +31 -24
  4. package/dist/cli/analyzeDiff/__tests__/analyzeDiffLomMiracles.test.d.ts +2 -0
  5. package/dist/cli/analyzeDiff/__tests__/analyzeDiffLomMiracles.test.d.ts.map +1 -0
  6. package/dist/cli/analyzeDiff/__tests__/analyzeDiffLomMiracles.test.js +47 -0
  7. package/dist/cli/analyzeDiff/__tests__/analyzeDiffRenameAndInvalidRegex.test.js +8 -7
  8. package/dist/cli/analyzeDiff/__tests__/analyzeDiffTypeCoercion.test.js +8 -7
  9. package/dist/cli/analyzeDiff/analyzeDiff.d.ts +14 -2
  10. package/dist/cli/analyzeDiff/analyzeDiff.d.ts.map +1 -1
  11. package/dist/cli/analyzeDiff/analyzeDiff.js +56 -13
  12. package/dist/cli/analyzeDiff/ciSummary.d.ts +6 -3
  13. package/dist/cli/analyzeDiff/ciSummary.d.ts.map +1 -1
  14. package/dist/cli/analyzeDiff/ciSummary.js +10 -6
  15. package/dist/cli/analyzeDiff/report.d.ts +0 -1
  16. package/dist/cli/analyzeDiff/report.d.ts.map +1 -1
  17. package/dist/cli/analyzeDiff/report.js +1 -3
  18. package/dist/cli/analyzeDiff/writeLegacyReport.d.ts +2 -0
  19. package/dist/cli/analyzeDiff/writeLegacyReport.d.ts.map +1 -1
  20. package/dist/cli/analyzeDiff/writeLegacyReport.js +2 -0
  21. package/dist/cli/analyzeUsage/core/Scanner.d.ts +8 -0
  22. package/dist/cli/analyzeUsage/core/Scanner.d.ts.map +1 -1
  23. package/dist/cli/analyzeUsage/core/Scanner.js +10 -0
  24. package/dist/cli/analyzeUsage/rules/ClientRule.d.ts +8 -0
  25. package/dist/cli/analyzeUsage/rules/ClientRule.d.ts.map +1 -1
  26. package/dist/cli/analyzeUsage/rules/ClientRule.js +10 -0
  27. package/dist/cli/analyzeUsage/rules/ServiceRule.d.ts +8 -0
  28. package/dist/cli/analyzeUsage/rules/ServiceRule.d.ts.map +1 -1
  29. package/dist/cli/analyzeUsage/rules/ServiceRule.js +10 -0
  30. package/dist/common/LoggerMessages.d.ts +5 -0
  31. package/dist/common/LoggerMessages.d.ts.map +1 -1
  32. package/dist/common/LoggerMessages.js +4 -0
  33. package/dist/core/OpenApiClient.d.ts +8 -0
  34. package/dist/core/OpenApiClient.d.ts.map +1 -1
  35. package/dist/core/OpenApiClient.js +16 -2
  36. package/dist/core/WriteClient.d.ts +52 -15
  37. package/dist/core/WriteClient.d.ts.map +1 -1
  38. package/dist/core/WriteClient.js +36 -4
  39. package/dist/core/semanticDiff/__tests__/analyzeOpenApiDiff.test.js +72 -0
  40. package/dist/core/semanticDiff/__tests__/semanticDiffReportSchema.test.js +20 -1
  41. package/dist/core/semanticDiff/analyzeOpenApiDiff.d.ts +58 -6
  42. package/dist/core/semanticDiff/analyzeOpenApiDiff.d.ts.map +1 -1
  43. package/dist/core/semanticDiff/analyzeOpenApiDiff.js +47 -19
  44. package/dist/core/semanticDiff/semanticDiffReportSchema.d.ts +11 -1
  45. package/dist/core/semanticDiff/semanticDiffReportSchema.d.ts.map +1 -1
  46. package/dist/core/semanticDiff/semanticDiffReportSchema.js +140 -50
  47. package/dist/core/types/DiffReport.model.d.ts +101 -0
  48. package/dist/core/types/DiffReport.model.d.ts.map +1 -0
  49. package/dist/core/types/DiffReport.model.js +5 -0
  50. package/dist/core/types/shared/Model.model.d.ts +36 -0
  51. package/dist/core/types/shared/Model.model.d.ts.map +1 -1
  52. package/dist/core/utils/__tests__/applyDiffReportToClient.test.js +182 -0
  53. package/dist/core/utils/__tests__/buildMiraclesFromSemanticChanges.test.d.ts +2 -0
  54. package/dist/core/utils/__tests__/buildMiraclesFromSemanticChanges.test.d.ts.map +1 -0
  55. package/dist/core/utils/__tests__/buildMiraclesFromSemanticChanges.test.js +77 -0
  56. package/dist/core/utils/__tests__/expandOpenApiRefsForSemanticDiff.test.d.ts +2 -0
  57. package/dist/core/utils/__tests__/expandOpenApiRefsForSemanticDiff.test.d.ts.map +1 -0
  58. package/dist/core/utils/__tests__/expandOpenApiRefsForSemanticDiff.test.js +159 -0
  59. package/dist/core/utils/__tests__/loadDiffReport.test.js +131 -0
  60. package/dist/core/utils/__tests__/modelHelpers.test.js +27 -9
  61. package/dist/core/utils/__tests__/prepareDtoModels.test.js +74 -2
  62. package/dist/core/utils/__tests__/resolveClassesModeTypes.test.d.ts +2 -0
  63. package/dist/core/utils/__tests__/resolveClassesModeTypes.test.d.ts.map +1 -0
  64. package/dist/core/utils/__tests__/resolveClassesModeTypes.test.js +111 -0
  65. package/dist/core/utils/__tests__/semanticChangesToDiffEntries.test.d.ts +2 -0
  66. package/dist/core/utils/__tests__/semanticChangesToDiffEntries.test.d.ts.map +1 -0
  67. package/dist/core/utils/__tests__/semanticChangesToDiffEntries.test.js +68 -0
  68. package/dist/core/utils/__tests__/serviceHelpers.test.js +10 -11
  69. package/dist/core/utils/__tests__/templateRendering.test.js +71 -0
  70. package/dist/core/utils/adapters/__tests__/semanticToStructural.test.d.ts +2 -0
  71. package/dist/core/utils/adapters/__tests__/semanticToStructural.test.d.ts.map +1 -0
  72. package/dist/core/utils/adapters/__tests__/semanticToStructural.test.js +63 -0
  73. package/dist/core/utils/adapters/extractMiraclesFromSemantic.d.ts +10 -0
  74. package/dist/core/utils/adapters/extractMiraclesFromSemantic.d.ts.map +1 -0
  75. package/dist/core/utils/adapters/extractMiraclesFromSemantic.js +13 -0
  76. package/dist/core/utils/adapters/index.d.ts +4 -0
  77. package/dist/core/utils/adapters/index.d.ts.map +1 -0
  78. package/dist/core/utils/adapters/index.js +8 -0
  79. package/dist/core/utils/adapters/semanticToStructural.d.ts +12 -0
  80. package/dist/core/utils/adapters/semanticToStructural.d.ts.map +1 -0
  81. package/dist/core/utils/adapters/semanticToStructural.js +36 -0
  82. package/dist/core/utils/applyDiffReportToClient.d.ts +13 -1
  83. package/dist/core/utils/applyDiffReportToClient.d.ts.map +1 -1
  84. package/dist/core/utils/applyDiffReportToClient.js +187 -107
  85. package/dist/core/utils/buildMiraclesFromSemanticChanges.d.ts +25 -0
  86. package/dist/core/utils/buildMiraclesFromSemanticChanges.d.ts.map +1 -0
  87. package/dist/core/utils/buildMiraclesFromSemanticChanges.js +146 -0
  88. package/dist/core/utils/expandOpenApiRefsForSemanticDiff.d.ts +23 -0
  89. package/dist/core/utils/expandOpenApiRefsForSemanticDiff.d.ts.map +1 -0
  90. package/dist/core/utils/expandOpenApiRefsForSemanticDiff.js +163 -0
  91. package/dist/core/utils/getOpenApiSpec.d.ts +18 -0
  92. package/dist/core/utils/getOpenApiSpec.d.ts.map +1 -1
  93. package/dist/core/utils/getOpenApiSpec.js +35 -0
  94. package/dist/core/utils/loadDiffReport.d.ts +11 -30
  95. package/dist/core/utils/loadDiffReport.d.ts.map +1 -1
  96. package/dist/core/utils/loadDiffReport.js +69 -3
  97. package/dist/core/utils/loadSemanticOpenApiSpec.d.ts +15 -0
  98. package/dist/core/utils/loadSemanticOpenApiSpec.d.ts.map +1 -0
  99. package/dist/core/utils/loadSemanticOpenApiSpec.js +61 -0
  100. package/dist/core/utils/modelHelpers.d.ts +13 -5
  101. package/dist/core/utils/modelHelpers.d.ts.map +1 -1
  102. package/dist/core/utils/modelHelpers.js +28 -23
  103. package/dist/core/utils/prepareDtoModels.d.ts +5 -0
  104. package/dist/core/utils/prepareDtoModels.d.ts.map +1 -1
  105. package/dist/core/utils/prepareDtoModels.js +55 -12
  106. package/dist/core/utils/resolveClassesModeTypes.d.ts +8 -0
  107. package/dist/core/utils/resolveClassesModeTypes.d.ts.map +1 -0
  108. package/dist/core/utils/resolveClassesModeTypes.js +77 -0
  109. package/dist/core/utils/semanticChangesToDiffEntries.d.ts +37 -0
  110. package/dist/core/utils/semanticChangesToDiffEntries.d.ts.map +1 -0
  111. package/dist/core/utils/semanticChangesToDiffEntries.js +99 -0
  112. package/dist/core/utils/semanticPointerToJsonPath.d.ts +7 -0
  113. package/dist/core/utils/semanticPointerToJsonPath.d.ts.map +1 -0
  114. package/dist/core/utils/semanticPointerToJsonPath.js +67 -0
  115. package/dist/core/utils/serviceHelpers.d.ts +6 -7
  116. package/dist/core/utils/serviceHelpers.d.ts.map +1 -1
  117. package/dist/core/utils/serviceHelpers.js +8 -25
  118. package/dist/core/utils/writeClientServices.d.ts +14 -14
  119. package/dist/core/utils/writeClientServices.d.ts.map +1 -1
  120. package/dist/core/utils/writeClientServices.js +4 -8
  121. package/dist/templatesCompiled/client/exportModels.d.ts +17 -11
  122. package/dist/templatesCompiled/client/exportModels.d.ts.map +1 -1
  123. package/dist/templatesCompiled/client/exportModels.js +96 -49
  124. package/dist/templatesCompiled/client/exportService.d.ts +13 -10
  125. package/dist/templatesCompiled/client/exportService.d.ts.map +1 -1
  126. package/dist/templatesCompiled/client/exportService.js +95 -67
  127. package/package.json +1 -3
  128. package/dist/cli/analyzeDiff/buildLegacyReport.d.ts +0 -17
  129. package/dist/cli/analyzeDiff/buildLegacyReport.d.ts.map +0 -1
  130. package/dist/cli/analyzeDiff/buildLegacyReport.js +0 -54
  131. package/dist/cli/analyzeDiff/diffEngine.d.ts +0 -54
  132. package/dist/cli/analyzeDiff/diffEngine.d.ts.map +0 -1
  133. package/dist/cli/analyzeDiff/diffEngine.js +0 -209
@@ -1,11 +1,18 @@
1
1
  import type { Model } from '../types/shared/Model.model';
2
+ type AliasAssignable = {
3
+ name: string;
4
+ alias: string;
5
+ };
6
+ /**
7
+ * Назначает различающие алиасы, когда несколько элементов имеют одно имя.
8
+ * Первое вхождение сохраняет имя без алиаса; следующие получают $2, $3 и т.д.
9
+ * @param items массив элементов с полями name и alias
10
+ * @returns тот же массив с обновлёнными алиасами
11
+ */
12
+ export declare const assignDuplicateAliases: <T extends AliasAssignable>(items: T[]) => T[];
2
13
  /**
3
14
  * Assigns alias to models with the same name.
4
- * Modifies objects of in-place models and returns an array.
5
- *
6
- * Example: if there are two models with name="Pet", the following will be assigned:
7
- * - first: alias="Pet$1"
8
- * - second: alias="Pet$2"
15
+ * Modifies objects in-place and returns the same array.
9
16
  *
10
17
  * @param models - an array of models sorted by name
11
18
  * @returns the same array of models (modified)
@@ -25,4 +32,5 @@ export declare function setDuplicateModelAliases(models: Model[]): Model[];
25
32
  * @returns the same array of models (modified)
26
33
  */
27
34
  export declare function resolveModelImports(models: Model[], outputModelsDir: string): Model[];
35
+ export {};
28
36
  //# sourceMappingURL=modelHelpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"modelHelpers.d.ts","sourceRoot":"","sources":["../../../src/core/utils/modelHelpers.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAEzD;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAkBjE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,eAAe,EAAE,MAAM,GAAG,KAAK,EAAE,CAyErF"}
1
+ {"version":3,"file":"modelHelpers.d.ts","sourceRoot":"","sources":["../../../src/core/utils/modelHelpers.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAEzD,KAAK,eAAe,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GAAI,CAAC,SAAS,eAAe,EAAE,OAAO,CAAC,EAAE,KAAG,CAAC,EAoB/E,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAEjE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,eAAe,EAAE,MAAM,GAAG,KAAK,EAAE,CAyErF"}
@@ -3,40 +3,45 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.assignDuplicateAliases = void 0;
6
7
  exports.setDuplicateModelAliases = setDuplicateModelAliases;
7
8
  exports.resolveModelImports = resolveModelImports;
8
9
  const path_1 = __importDefault(require("path"));
9
10
  const pathHelpers_1 = require("../../common/utils/pathHelpers");
11
+ /**
12
+ * Назначает различающие алиасы, когда несколько элементов имеют одно имя.
13
+ * Первое вхождение сохраняет имя без алиаса; следующие получают $2, $3 и т.д.
14
+ * @param items массив элементов с полями name и alias
15
+ * @returns тот же массив с обновлёнными алиасами
16
+ */
17
+ const assignDuplicateAliases = (items) => {
18
+ const nameCounts = new Map();
19
+ items.forEach(item => {
20
+ nameCounts.set(item.name, (nameCounts.get(item.name) ?? 0) + 1);
21
+ });
22
+ const nameIndex = new Map();
23
+ items.forEach(item => {
24
+ const count = nameCounts.get(item.name) ?? 1;
25
+ if (count <= 1) {
26
+ item.alias = '';
27
+ return;
28
+ }
29
+ const index = (nameIndex.get(item.name) ?? 0) + 1;
30
+ nameIndex.set(item.name, index);
31
+ item.alias = index === 1 ? '' : `${item.name}$${index}`;
32
+ });
33
+ return items;
34
+ };
35
+ exports.assignDuplicateAliases = assignDuplicateAliases;
10
36
  /**
11
37
  * Assigns alias to models with the same name.
12
- * Modifies objects of in-place models and returns an array.
13
- *
14
- * Example: if there are two models with name="Pet", the following will be assigned:
15
- * - first: alias="Pet$1"
16
- * - second: alias="Pet$2"
38
+ * Modifies objects in-place and returns the same array.
17
39
  *
18
40
  * @param models - an array of models sorted by name
19
41
  * @returns the same array of models (modified)
20
42
  */
21
43
  function setDuplicateModelAliases(models) {
22
- let previous;
23
- let index = 1;
24
- models.forEach(model => {
25
- if (previous && previous.name === model.name) {
26
- if (index === 1) {
27
- previous.alias = `${model.name}$${index}`;
28
- index++;
29
- }
30
- model.alias = `${model.name}$${index}`;
31
- index++;
32
- }
33
- else {
34
- model.alias = '';
35
- index = 1;
36
- }
37
- previous = model;
38
- });
39
- return models;
44
+ return (0, exports.assignDuplicateAliases)(models);
40
45
  }
41
46
  /**
42
47
  * Adjusts the imports fields of the models to relative paths and correct aliases,
@@ -1,3 +1,8 @@
1
1
  import type { Client } from '../types/shared/Client.model';
2
+ /**
3
+ * Подготавливает raw/DTO-модели и геттеры для режима classes.
4
+ * @param client сгенерированный клиент
5
+ * @returns клиент с заполненными DTO-полями моделей
6
+ */
2
7
  export declare const prepareDtoModels: (client: Client) => Client;
3
8
  //# sourceMappingURL=prepareDtoModels.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prepareDtoModels.d.ts","sourceRoot":"","sources":["../../../src/core/utils/prepareDtoModels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAuL3D,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,MAqCjD,CAAC"}
1
+ {"version":3,"file":"prepareDtoModels.d.ts","sourceRoot":"","sources":["../../../src/core/utils/prepareDtoModels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAgO3D;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,KAAG,MAuCjD,CAAC"}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.prepareDtoModels = void 0;
4
4
  const escapeName_1 = require("./escapeName");
5
5
  const unique_1 = require("./unique");
6
+ const getBaseName = (model) => model.alias || model.name;
6
7
  const buildPropertyTarget = (name, prefix) => {
7
8
  if (name.startsWith("'") && name.endsWith("'")) {
8
9
  return `${prefix}[${name}]`;
@@ -61,16 +62,49 @@ const resolveTypeFactory = (nameMap, kind) => {
61
62
  };
62
63
  return resolveType;
63
64
  };
65
+ const finalizeDtoType = (property, dtoType) => {
66
+ if (!property.isRequired && !property.default && !property.isNullable) {
67
+ return `${dtoType} | undefined`;
68
+ }
69
+ return dtoType;
70
+ };
71
+ const applyCoercion = (expr, property, accessor) => {
72
+ if (!property.needsCoercion || !property.coercionTo) {
73
+ return expr;
74
+ }
75
+ switch (property.coercionTo) {
76
+ case 'number':
77
+ return `typeof ${accessor} === 'string' ? Number(${accessor}) : (${expr})`;
78
+ case 'boolean':
79
+ return `typeof ${accessor} === 'string' ? ${accessor} === 'true' : (${expr})`;
80
+ default:
81
+ return expr;
82
+ }
83
+ };
84
+ const buildOptionalSuffix = (property) => {
85
+ if (property.default) {
86
+ return '';
87
+ }
88
+ if (!property.isRequired) {
89
+ return property.isNullable ? ' ?? null' : ' ?? undefined';
90
+ }
91
+ if (property.isNullable) {
92
+ return ' ?? null';
93
+ }
94
+ return '';
95
+ };
64
96
  const buildDtoInit = (property, nameMap) => {
65
97
  const accessor = buildPropertyTarget(property.name, 'data');
66
- const defaultSuffix = property.default ? ` ?? ${property.default}` : '';
98
+ const optionalSuffix = buildOptionalSuffix(property);
99
+ const defaultSuffix = property.default ? ` ?? ${property.default}` : optionalSuffix;
67
100
  const isReference = property.export === 'reference' && nameMap.has(property.type);
68
101
  if (isReference) {
69
102
  const dtoName = nameMap.get(property.type).dtoName;
70
103
  if (property.isRequired) {
71
- return `new ${dtoName}(${accessor})`;
104
+ return applyCoercion(`new ${dtoName}(${accessor})`, property, accessor);
72
105
  }
73
- return `${accessor} ? new ${dtoName}(${accessor}) : undefined`;
106
+ const expr = `${accessor} ? new ${dtoName}(${accessor}) : undefined`;
107
+ return applyCoercion(expr, property, accessor);
74
108
  }
75
109
  if (property.export === 'array') {
76
110
  const itemModel = property.link ?? { ...property, export: 'reference', link: null };
@@ -78,13 +112,14 @@ const buildDtoInit = (property, nameMap) => {
78
112
  if (itemIsRef) {
79
113
  const dtoName = nameMap.get(itemModel.type).dtoName;
80
114
  if (property.isRequired) {
81
- return `fromArray(${dtoName}, ${accessor})`;
115
+ return applyCoercion(`fromArray(${dtoName}, ${accessor})`, property, accessor);
82
116
  }
83
- return `${accessor} ? fromArray(${dtoName}, ${accessor}) : undefined`;
117
+ const expr = `${accessor} ? fromArray(${dtoName}, ${accessor}) : undefined`;
118
+ return applyCoercion(expr, property, accessor);
84
119
  }
85
- return `${accessor}${defaultSuffix}`;
120
+ return applyCoercion(`${accessor}${defaultSuffix}`, property, accessor);
86
121
  }
87
- return `${accessor}${defaultSuffix}`;
122
+ return applyCoercion(`${accessor}${defaultSuffix}`, property, accessor);
88
123
  };
89
124
  const buildDtoToJson = (property, nameMap) => {
90
125
  const accessor = buildPropertyTarget(property.name, 'this');
@@ -122,7 +157,8 @@ const attachDtoGetters = (client) => {
122
157
  client.models.forEach(model => {
123
158
  if (!model.isDefinition || model.export !== 'interface')
124
159
  return;
125
- const entries = miraclesByModel.get(model.name);
160
+ const modelKey = getBaseName(model);
161
+ const entries = miraclesByModel.get(modelKey) ?? miraclesByModel.get(model.name);
126
162
  if (!entries || entries.length === 0)
127
163
  return;
128
164
  const getters = entries
@@ -148,15 +184,22 @@ const attachDtoGetters = (client) => {
148
184
  }
149
185
  });
150
186
  };
187
+ /**
188
+ * Подготавливает raw/DTO-модели и геттеры для режима classes.
189
+ * @param client сгенерированный клиент
190
+ * @returns клиент с заполненными DTO-полями моделей
191
+ */
151
192
  const prepareDtoModels = (client) => {
152
193
  const nameMap = new Map();
153
194
  client.models.forEach(model => {
154
- const rawName = `${model.name}Raw`;
155
- const dtoName = `${model.name}Dto`;
195
+ const baseName = getBaseName(model);
196
+ const rawName = `${baseName}Raw`;
197
+ const dtoName = `${baseName}Dto`;
156
198
  model.rawName = rawName;
157
199
  model.dtoName = dtoName;
200
+ model.exportName = baseName;
158
201
  model.dtoKind = model.export === 'interface' ? 'class' : 'alias';
159
- nameMap.set(model.name, { rawName, dtoName });
202
+ nameMap.set(baseName, { rawName, dtoName });
160
203
  });
161
204
  const resolveRaw = resolveTypeFactory(nameMap, 'raw');
162
205
  const resolveDto = resolveTypeFactory(nameMap, 'dto');
@@ -171,7 +214,7 @@ const prepareDtoModels = (client) => {
171
214
  }
172
215
  model.properties.forEach(property => {
173
216
  property.rawType = resolveRaw(property);
174
- property.dtoType = resolveDto(property);
217
+ property.dtoType = finalizeDtoType(property, resolveDto(property));
175
218
  property.dtoInit = buildDtoInit(property, nameMap);
176
219
  property.dtoToJSON = buildDtoToJson(property, nameMap);
177
220
  property.dtoTarget = buildPropertyTarget(property.name, '');
@@ -0,0 +1,8 @@
1
+ import type { Client } from '../types/shared/Client.model';
2
+ /**
3
+ * Заменяет импорты и типы моделей на exportName в режиме classes.
4
+ * @param client сгенерированный клиент
5
+ * @returns клиент с обновлёнными импортами и типами
6
+ */
7
+ export declare const resolveClassesModeTypes: (client: Client) => Client;
8
+ //# sourceMappingURL=resolveClassesModeTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveClassesModeTypes.d.ts","sourceRoot":"","sources":["../../../src/core/utils/resolveClassesModeTypes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAsD3D;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAAI,QAAQ,MAAM,KAAG,MA8BxD,CAAC"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveClassesModeTypes = void 0;
4
+ const normalizeImportPath = (value) => (value.startsWith('./') ? value.slice(2) : value);
5
+ const resolveExportName = (model, pathToExportName) => {
6
+ const modelPath = normalizeImportPath(model.path);
7
+ if (modelPath) {
8
+ const exportName = pathToExportName.get(modelPath);
9
+ if (exportName) {
10
+ return exportName;
11
+ }
12
+ }
13
+ for (const imprt of model.imports ?? []) {
14
+ const importPath = normalizeImportPath(imprt.path);
15
+ const exportName = pathToExportName.get(importPath);
16
+ if (exportName && (imprt.name === model.base || imprt.name === model.type)) {
17
+ return exportName;
18
+ }
19
+ }
20
+ return undefined;
21
+ };
22
+ const applyExportNameToModel = (model, pathToExportName) => {
23
+ const exportName = resolveExportName(model, pathToExportName);
24
+ if (exportName) {
25
+ model.base = exportName;
26
+ model.type = exportName;
27
+ }
28
+ if (model.link) {
29
+ applyExportNameToModel(model.link, pathToExportName);
30
+ }
31
+ model.properties?.forEach(child => applyExportNameToModel(child, pathToExportName));
32
+ };
33
+ const resolveImportForClassesMode = (imprt, pathToExportName) => {
34
+ const importPath = normalizeImportPath(imprt.path);
35
+ const exportName = pathToExportName.get(importPath);
36
+ if (!exportName || exportName === imprt.name) {
37
+ return imprt;
38
+ }
39
+ return {
40
+ ...imprt,
41
+ name: exportName,
42
+ alias: '',
43
+ };
44
+ };
45
+ /**
46
+ * Заменяет импорты и типы моделей на exportName в режиме classes.
47
+ * @param client сгенерированный клиент
48
+ * @returns клиент с обновлёнными импортами и типами
49
+ */
50
+ const resolveClassesModeTypes = (client) => {
51
+ const pathToExportName = new Map();
52
+ client.models.forEach(model => {
53
+ if (!model.isDefinition) {
54
+ return;
55
+ }
56
+ const exportName = model.exportName || model.alias || model.name;
57
+ pathToExportName.set(normalizeImportPath(model.path), exportName);
58
+ });
59
+ client.services.forEach(service => {
60
+ service.imports = service.imports.map(imprt => resolveImportForClassesMode(imprt, pathToExportName));
61
+ service.operations.forEach(operation => {
62
+ operation.imports = operation.imports.map(imprt => resolveImportForClassesMode(imprt, pathToExportName));
63
+ operation.results.forEach(result => applyExportNameToModel(result, pathToExportName));
64
+ operation.parameters.forEach(parameter => applyExportNameToModel(parameter, pathToExportName));
65
+ operation.parametersPath.forEach(parameter => applyExportNameToModel(parameter, pathToExportName));
66
+ operation.parametersQuery.forEach(parameter => applyExportNameToModel(parameter, pathToExportName));
67
+ operation.parametersForm.forEach(parameter => applyExportNameToModel(parameter, pathToExportName));
68
+ operation.parametersHeader.forEach(parameter => applyExportNameToModel(parameter, pathToExportName));
69
+ operation.parametersCookie.forEach(parameter => applyExportNameToModel(parameter, pathToExportName));
70
+ if (operation.parametersBody) {
71
+ applyExportNameToModel(operation.parametersBody, pathToExportName);
72
+ }
73
+ });
74
+ });
75
+ return client;
76
+ };
77
+ exports.resolveClassesModeTypes = resolveClassesModeTypes;
@@ -0,0 +1,37 @@
1
+ import type { SemanticDiffChange } from '../semanticDiff/analyzeOpenApiDiff';
2
+ import type { DiffReportEntry } from '../types/DiffReport.model';
3
+ import type { DiffAction, DiffSeverity } from '../types/shared/DiffInfo.model';
4
+ /**
5
+ * Преобразует тип семантического изменения в legacy diff action.
6
+ * @param changeType тип семантического изменения
7
+ * @returns действие legacy diff
8
+ */
9
+ export declare function semanticChangeTypeToAction(changeType: string): DiffAction;
10
+ /**
11
+ * Преобразует серьёзность семантического изменения в legacy diff severity.
12
+ * @param severity серьёзность семантического изменения
13
+ * @returns уровень серьёзности legacy diff
14
+ */
15
+ export declare function semanticSeverityToDiffSeverity(severity: SemanticDiffChange['severity']): DiffSeverity;
16
+ /**
17
+ * Строит legacy JSONPath для семантического изменения, включая суффикс `.type`.
18
+ * @param change семантическое изменение
19
+ * @returns JSONPath для legacy diff
20
+ */
21
+ export declare function semanticChangeToJsonPath(change: SemanticDiffChange): string;
22
+ /**
23
+ * Извлекает значения from/to для legacy diff-записи.
24
+ * @param change семантическое изменение
25
+ * @returns значения до и после изменения
26
+ */
27
+ export declare function resolveSemanticChangeValues(change: SemanticDiffChange): {
28
+ from?: unknown;
29
+ to?: unknown;
30
+ };
31
+ /**
32
+ * Преобразует семантические изменения в legacy DiffReportEntry.
33
+ * @param changes список семантических изменений
34
+ * @returns список legacy diff-записей
35
+ */
36
+ export declare function semanticChangesToDiffEntries(changes: SemanticDiffChange[]): DiffReportEntry[];
37
+ //# sourceMappingURL=semanticChangesToDiffEntries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semanticChangesToDiffEntries.d.ts","sourceRoot":"","sources":["../../../src/core/utils/semanticChangesToDiffEntries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAgB/E;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAczE;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,kBAAkB,CAAC,UAAU,CAAC,GAAG,YAAY,CAUrG;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAQ3E;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,kBAAkB,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAE,CAgBxG;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,eAAe,EAAE,CAa7F"}
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.semanticChangeTypeToAction = semanticChangeTypeToAction;
4
+ exports.semanticSeverityToDiffSeverity = semanticSeverityToDiffSeverity;
5
+ exports.semanticChangeToJsonPath = semanticChangeToJsonPath;
6
+ exports.resolveSemanticChangeValues = resolveSemanticChangeValues;
7
+ exports.semanticChangesToDiffEntries = semanticChangesToDiffEntries;
8
+ const semanticPointerToJsonPath_1 = require("./semanticPointerToJsonPath");
9
+ const REMOVED_CHANGE_TYPES = new Set(['model.removed', 'model.property.removed', 'model.enum.value.removed', 'operation.removed', 'operation.parameter.removed', 'operation.response.success.removed']);
10
+ const ADDED_CHANGE_TYPES = new Set(['model.added', 'model.property.added', 'model.enum.value.added', 'operation.added', 'operation.parameter.added', 'operation.response.success.added']);
11
+ const CHANGED_CHANGE_TYPES = new Set([
12
+ 'model.property.type.changed',
13
+ 'model.property.required.changed',
14
+ 'operation.parameter.required.changed',
15
+ 'operation.parameter.type.changed',
16
+ 'operation.requestBody.required.changed',
17
+ 'operation.response.success.type.changed',
18
+ ]);
19
+ /**
20
+ * Преобразует тип семантического изменения в legacy diff action.
21
+ * @param changeType тип семантического изменения
22
+ * @returns действие legacy diff
23
+ */
24
+ function semanticChangeTypeToAction(changeType) {
25
+ if (REMOVED_CHANGE_TYPES.has(changeType) || changeType.endsWith('.removed')) {
26
+ return 'removed';
27
+ }
28
+ if (ADDED_CHANGE_TYPES.has(changeType) || changeType.endsWith('.added')) {
29
+ return 'added';
30
+ }
31
+ if (CHANGED_CHANGE_TYPES.has(changeType) || changeType.endsWith('.changed')) {
32
+ return 'changed';
33
+ }
34
+ return 'changed';
35
+ }
36
+ /**
37
+ * Преобразует серьёзность семантического изменения в legacy diff severity.
38
+ * @param severity серьёзность семантического изменения
39
+ * @returns уровень серьёзности legacy diff
40
+ */
41
+ function semanticSeverityToDiffSeverity(severity) {
42
+ if (severity === 'breaking') {
43
+ return 'breaking';
44
+ }
45
+ if (severity === 'non-breaking') {
46
+ return 'warning';
47
+ }
48
+ return 'info';
49
+ }
50
+ /**
51
+ * Строит legacy JSONPath для семантического изменения, включая суффикс `.type`.
52
+ * @param change семантическое изменение
53
+ * @returns JSONPath для legacy diff
54
+ */
55
+ function semanticChangeToJsonPath(change) {
56
+ const basePath = (0, semanticPointerToJsonPath_1.semanticPointerToJsonPath)(change.path);
57
+ if (change.type === 'model.property.type.changed' || change.type === 'operation.parameter.type.changed') {
58
+ return `${basePath}.type`;
59
+ }
60
+ return basePath;
61
+ }
62
+ /**
63
+ * Извлекает значения from/to для legacy diff-записи.
64
+ * @param change семантическое изменение
65
+ * @returns значения до и после изменения
66
+ */
67
+ function resolveSemanticChangeValues(change) {
68
+ if (change.type === 'model.property.required.changed' || change.type === 'operation.parameter.required.changed') {
69
+ return {
70
+ from: change.fromRequired,
71
+ to: change.toRequired,
72
+ };
73
+ }
74
+ if (change.from !== undefined || change.to !== undefined) {
75
+ return {
76
+ from: change.from,
77
+ to: change.to,
78
+ };
79
+ }
80
+ return {};
81
+ }
82
+ /**
83
+ * Преобразует семантические изменения в legacy DiffReportEntry.
84
+ * @param changes список семантических изменений
85
+ * @returns список legacy diff-записей
86
+ */
87
+ function semanticChangesToDiffEntries(changes) {
88
+ return changes.map(change => {
89
+ const { from, to } = resolveSemanticChangeValues(change);
90
+ return {
91
+ action: semanticChangeTypeToAction(change.type),
92
+ path: semanticChangeToJsonPath(change),
93
+ severity: semanticSeverityToDiffSeverity(change.severity),
94
+ from,
95
+ to,
96
+ note: change.message,
97
+ };
98
+ });
99
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Преобразует семантический JSON Pointer в legacy JSONPath, используемый генератором.
3
+ * @param pointer JSON Pointer или уже готовый JSONPath
4
+ * @returns legacy JSONPath
5
+ */
6
+ export declare function semanticPointerToJsonPath(pointer: string): string;
7
+ //# sourceMappingURL=semanticPointerToJsonPath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semanticPointerToJsonPath.d.ts","sourceRoot":"","sources":["../../../src/core/utils/semanticPointerToJsonPath.ts"],"names":[],"mappings":"AAgDA;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAuBjE"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.semanticPointerToJsonPath = semanticPointerToJsonPath;
4
+ const jsonPath_1 = require("../../common/utils/jsonPath");
5
+ const HTTP_METHODS = new Set(['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS', 'HEAD', 'PATCH', 'TRACE']);
6
+ const OPERATION_SUFFIX_MARKERS = ['parameters', 'requestBody', 'responses'];
7
+ /**
8
+ * Splits semantic operation pointer tail into operation key and nested suffix segments.
9
+ */
10
+ function splitOperationPointerTail(tail) {
11
+ for (const marker of OPERATION_SUFFIX_MARKERS) {
12
+ const markerIndex = tail.indexOf(`/${marker}`);
13
+ if (markerIndex > 0) {
14
+ return {
15
+ operationKey: tail.slice(0, markerIndex),
16
+ suffix: [
17
+ marker,
18
+ ...tail
19
+ .slice(markerIndex + marker.length + 1)
20
+ .split('/')
21
+ .filter(Boolean),
22
+ ],
23
+ };
24
+ }
25
+ }
26
+ return { operationKey: tail, suffix: [] };
27
+ }
28
+ /**
29
+ * Parses semantic operation key "GET /pets" into HTTP method and route path.
30
+ */
31
+ function parseOperationKey(operationKey) {
32
+ const match = operationKey.match(/^(GET|PUT|POST|DELETE|OPTIONS|HEAD|PATCH|TRACE)\s+(\S+)$/i);
33
+ if (!match) {
34
+ return null;
35
+ }
36
+ const method = match[1].toLowerCase();
37
+ const routePath = match[2];
38
+ if (!HTTP_METHODS.has(match[1].toUpperCase())) {
39
+ return null;
40
+ }
41
+ return { method, routePath };
42
+ }
43
+ const decodePointerSegment = (segment) => segment.replace(/~1/g, '/').replace(/~0/g, '~');
44
+ /**
45
+ * Преобразует семантический JSON Pointer в legacy JSONPath, используемый генератором.
46
+ * @param pointer JSON Pointer или уже готовый JSONPath
47
+ * @returns legacy JSONPath
48
+ */
49
+ function semanticPointerToJsonPath(pointer) {
50
+ if (pointer.startsWith('$')) {
51
+ return pointer;
52
+ }
53
+ if (!pointer.startsWith('#/')) {
54
+ return pointer;
55
+ }
56
+ const body = pointer.slice(2);
57
+ if (body.startsWith('paths/')) {
58
+ const tail = body.slice('paths/'.length);
59
+ const { operationKey, suffix } = splitOperationPointerTail(tail);
60
+ const parsedOperation = parseOperationKey(operationKey);
61
+ if (parsedOperation) {
62
+ return (0, jsonPath_1.toJsonPath)(['paths', parsedOperation.routePath, parsedOperation.method, ...suffix]);
63
+ }
64
+ }
65
+ const rawSegments = body.split('/').map(decodePointerSegment);
66
+ return (0, jsonPath_1.toJsonPath)(rawSegments);
67
+ }
@@ -7,12 +7,11 @@ import type { Service } from '../types/shared/Service.model';
7
7
  */
8
8
  export declare function forEachOperationInPath(pathObj: Record<string, any>, cb: (method: string, op: any) => void): void;
9
9
  /**
10
- * Ensure service exists in the services map or create a new one.
11
- *
12
- * @param services - Map of services
13
- * @param name - service name
14
- * @param originName - originName (optional) used when creating a new service
15
- * @returns existing or newly created Service
10
+ * Возвращает существующий сервис из map или создаёт новый.
11
+ * @param services map сервисов
12
+ * @param name имя сервиса
13
+ * @param [originName] исходное имя сервиса при создании
14
+ * @returns существующий или новый сервис
16
15
  */
17
16
  export declare function ensureService(services: Map<string, Service>, name: string, originName?: string): Service;
18
17
  /**
@@ -29,7 +28,7 @@ export declare function mergeOperationImportsIntoService(service: Service, opera
29
28
  /**
30
29
  * Finalize imports for a service:
31
30
  * - Deduplicate and sort imports
32
- * - Assign aliases for duplicate import names (name, name$1, name$2, ...)
31
+ * - Assign aliases for duplicate import names (first keeps plain name, then name$2, name$3, ...)
33
32
  * - Propagate assigned aliases to models referenced in operations (results, parameters)
34
33
  *
35
34
  * Modifies service in-place and returns it.
@@ -1 +1 @@
1
- {"version":3,"file":"serviceHelpers.d.ts","sourceRoot":"","sources":["../../../src/core/utils/serviceHelpers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAK7D;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAOhH;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAWxG;AAED;;;;;;;;;GASG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,GAAG,IAAI,CAMvF;AA+CD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAiChE"}
1
+ {"version":3,"file":"serviceHelpers.d.ts","sourceRoot":"","sources":["../../../src/core/utils/serviceHelpers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAM7D;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI,CAOhH;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAWxG;AAED;;;;;;;;;GASG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,GAAG,IAAI,CAMvF;AA+CD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAiBhE"}
@@ -5,6 +5,7 @@ exports.ensureService = ensureService;
5
5
  exports.mergeOperationImportsIntoService = mergeOperationImportsIntoService;
6
6
  exports.finalizeServiceImports = finalizeServiceImports;
7
7
  const safeHasOwn_1 = require("../../common/utils/safeHasOwn");
8
+ const modelHelpers_1 = require("./modelHelpers");
8
9
  const unique_1 = require("./unique");
9
10
  const SUPPORTED_METHODS = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch'];
10
11
  /**
@@ -23,12 +24,11 @@ function forEachOperationInPath(pathObj, cb) {
23
24
  }
24
25
  }
25
26
  /**
26
- * Ensure service exists in the services map or create a new one.
27
- *
28
- * @param services - Map of services
29
- * @param name - service name
30
- * @param originName - originName (optional) used when creating a new service
31
- * @returns existing or newly created Service
27
+ * Возвращает существующий сервис из map или создаёт новый.
28
+ * @param services map сервисов
29
+ * @param name имя сервиса
30
+ * @param [originName] исходное имя сервиса при создании
31
+ * @returns существующий или новый сервис
32
32
  */
33
33
  function ensureService(services, name, originName) {
34
34
  const existing = services.get(name);
@@ -100,7 +100,7 @@ function fillModelsByAlias(items = [], value) {
100
100
  /**
101
101
  * Finalize imports for a service:
102
102
  * - Deduplicate and sort imports
103
- * - Assign aliases for duplicate import names (name, name$1, name$2, ...)
103
+ * - Assign aliases for duplicate import names (first keeps plain name, then name$2, name$3, ...)
104
104
  * - Propagate assigned aliases to models referenced in operations (results, parameters)
105
105
  *
106
106
  * Modifies service in-place and returns it.
@@ -114,24 +114,7 @@ function finalizeServiceImports(service) {
114
114
  const nameB = b.name.toLowerCase();
115
115
  return nameA.localeCompare(nameB, 'en');
116
116
  });
117
- let previous;
118
- let index = 1;
119
- service.imports = service.imports.map(value => {
120
- if (previous && previous.name === value.name) {
121
- if (index === 1) {
122
- previous.alias = `${value.name}$${index}`;
123
- index++;
124
- }
125
- value.alias = `${value.name}$${index}`;
126
- index++;
127
- }
128
- else {
129
- value.alias = '';
130
- index = 1;
131
- }
132
- previous = value;
133
- return value;
134
- });
117
+ (0, modelHelpers_1.assignDuplicateAliases)(service.imports);
135
118
  for (const item of service.imports) {
136
119
  for (const operation of service.operations) {
137
120
  fillModelsByAlias(operation.results, item);