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
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_assert_1 = __importDefault(require("node:assert"));
7
+ const node_test_1 = require("node:test");
8
+ const semanticToStructural_1 = require("../semanticToStructural");
9
+ (0, node_test_1.describe)('@unit: semanticToStructural adapter', () => {
10
+ (0, node_test_1.test)('groups semantic changes by legacy severity and calculates stats', () => {
11
+ const changes = [
12
+ {
13
+ type: 'model.property.removed',
14
+ severity: 'breaking',
15
+ path: '#/components/schemas/User/properties/oldName',
16
+ message: 'removed',
17
+ from: { type: 'string' },
18
+ },
19
+ {
20
+ type: 'model.property.added',
21
+ severity: 'non-breaking',
22
+ path: '#/components/schemas/User/properties/newName',
23
+ message: 'added',
24
+ to: { type: 'string' },
25
+ },
26
+ {
27
+ type: 'model.property.type.changed',
28
+ severity: 'informational',
29
+ path: '#/components/schemas/User/properties/age',
30
+ message: 'type changed',
31
+ from: 'integer',
32
+ to: 'integer:int64',
33
+ },
34
+ ];
35
+ const structural = (0, semanticToStructural_1.adaptSemanticToStructural)({ changes }, 2);
36
+ node_assert_1.default.strictEqual(structural.diff.all.length, 3);
37
+ node_assert_1.default.strictEqual(structural.diff.breaking.length, 1);
38
+ node_assert_1.default.strictEqual(structural.diff.warnings.length, 1);
39
+ node_assert_1.default.strictEqual(structural.diff.info.length, 1);
40
+ node_assert_1.default.strictEqual(structural.stats.totalChanges, 3);
41
+ node_assert_1.default.strictEqual(structural.stats.added, 1);
42
+ node_assert_1.default.strictEqual(structural.stats.removed, 1);
43
+ node_assert_1.default.strictEqual(structural.stats.changed, 1);
44
+ node_assert_1.default.strictEqual(structural.stats.ignored, 2);
45
+ node_assert_1.default.strictEqual(structural.stats.stabilityScore, 67);
46
+ });
47
+ (0, node_test_1.test)('uses provided miracles instead of rebuilding them', () => {
48
+ const structural = (0, semanticToStructural_1.adaptSemanticToStructural)({
49
+ changes: [],
50
+ miracles: [
51
+ {
52
+ oldPath: '$.old',
53
+ newPath: '$.new',
54
+ type: 'RENAME',
55
+ confidence: 1,
56
+ status: 'confirmed',
57
+ },
58
+ ],
59
+ });
60
+ node_assert_1.default.strictEqual(structural.miracles.length, 1);
61
+ node_assert_1.default.strictEqual(structural.miracles[0].status, 'confirmed');
62
+ });
63
+ });
@@ -0,0 +1,10 @@
1
+ import type { SemanticDiffChange } from '../../semanticDiff/analyzeOpenApiDiff';
2
+ import type { MiracleEntry } from '../../types/shared/Miracle.model';
3
+ /**
4
+ * Возвращает miracles из отчёта или строит их из семантических изменений.
5
+ * @param changes список семантических изменений
6
+ * @param [miracles] готовый список miracles из отчёта
7
+ * @returns список miracles для структурного diff
8
+ */
9
+ export declare function extractMiraclesFromSemantic(changes: SemanticDiffChange[], miracles?: MiracleEntry[]): MiracleEntry[];
10
+ //# sourceMappingURL=extractMiraclesFromSemantic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractMiraclesFromSemantic.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/adapters/extractMiraclesFromSemantic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAGrE;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,kBAAkB,EAAE,EAAE,QAAQ,CAAC,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAEpH"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractMiraclesFromSemantic = extractMiraclesFromSemantic;
4
+ const buildMiraclesFromSemanticChanges_1 = require("../buildMiraclesFromSemanticChanges");
5
+ /**
6
+ * Возвращает miracles из отчёта или строит их из семантических изменений.
7
+ * @param changes список семантических изменений
8
+ * @param [miracles] готовый список miracles из отчёта
9
+ * @returns список miracles для структурного diff
10
+ */
11
+ function extractMiraclesFromSemantic(changes, miracles) {
12
+ return miracles?.length ? miracles : (0, buildMiraclesFromSemanticChanges_1.buildMiraclesFromSemanticChanges)(changes);
13
+ }
@@ -0,0 +1,4 @@
1
+ /** Реэкспорт адаптеров семантического diff в структурный формат. */
2
+ export { extractMiraclesFromSemantic } from './extractMiraclesFromSemantic';
3
+ export { adaptSemanticToStructural, type SemanticDiffLike } from './semanticToStructural';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/adapters/index.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,yBAAyB,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.adaptSemanticToStructural = exports.extractMiraclesFromSemantic = void 0;
4
+ /** Реэкспорт адаптеров семантического diff в структурный формат. */
5
+ var extractMiraclesFromSemantic_1 = require("./extractMiraclesFromSemantic");
6
+ Object.defineProperty(exports, "extractMiraclesFromSemantic", { enumerable: true, get: function () { return extractMiraclesFromSemantic_1.extractMiraclesFromSemantic; } });
7
+ var semanticToStructural_1 = require("./semanticToStructural");
8
+ Object.defineProperty(exports, "adaptSemanticToStructural", { enumerable: true, get: function () { return semanticToStructural_1.adaptSemanticToStructural; } });
@@ -0,0 +1,12 @@
1
+ import type { SemanticDiffReport } from '../../semanticDiff/analyzeOpenApiDiff';
2
+ import type { StructuralDiffPart } from '../../types/DiffReport.model';
3
+ /** Минимальный набор полей семантического diff для адаптации в структурный формат. */
4
+ export type SemanticDiffLike = Pick<SemanticDiffReport, 'changes' | 'miracles'>;
5
+ /**
6
+ * Преобразует семантический diff в структурную часть legacy-отчёта.
7
+ * @param semantic семантический diff или его подмножество
8
+ * @param [ignored] количество проигнорированных изменений
9
+ * @returns структурная часть diff-отчёта
10
+ */
11
+ export declare function adaptSemanticToStructural(semantic: SemanticDiffLike, ignored?: number): StructuralDiffPart;
12
+ //# sourceMappingURL=semanticToStructural.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semanticToStructural.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/adapters/semanticToStructural.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAChF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAIvE,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,UAAU,CAAC,CAAC;AAgBhF;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAa1G"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.adaptSemanticToStructural = adaptSemanticToStructural;
4
+ const semanticChangesToDiffEntries_1 = require("../semanticChangesToDiffEntries");
5
+ const extractMiraclesFromSemantic_1 = require("./extractMiraclesFromSemantic");
6
+ function calculateStats(all, ignored) {
7
+ const breakingCount = all.filter(entry => entry.severity === 'breaking').length;
8
+ const stabilityScore = all.length === 0 ? 100 : Math.round(((all.length - breakingCount) / all.length) * 100);
9
+ return {
10
+ totalChanges: all.length,
11
+ added: all.filter(entry => entry.action === 'added').length,
12
+ removed: all.filter(entry => entry.action === 'removed').length,
13
+ changed: all.filter(entry => entry.action === 'changed').length,
14
+ ignored: ignored || undefined,
15
+ stabilityScore,
16
+ };
17
+ }
18
+ /**
19
+ * Преобразует семантический diff в структурную часть legacy-отчёта.
20
+ * @param semantic семантический diff или его подмножество
21
+ * @param [ignored] количество проигнорированных изменений
22
+ * @returns структурная часть diff-отчёта
23
+ */
24
+ function adaptSemanticToStructural(semantic, ignored) {
25
+ const all = (0, semanticChangesToDiffEntries_1.semanticChangesToDiffEntries)(semantic.changes);
26
+ return {
27
+ diff: {
28
+ breaking: all.filter(entry => entry.severity === 'breaking'),
29
+ warnings: all.filter(entry => entry.severity === 'warning'),
30
+ info: all.filter(entry => entry.severity === 'info'),
31
+ all,
32
+ },
33
+ miracles: (0, extractMiraclesFromSemantic_1.extractMiraclesFromSemantic)(semantic.changes, semantic.miracles),
34
+ stats: calculateStats(all, ignored),
35
+ };
36
+ }
@@ -1,3 +1,4 @@
1
+ import type { Context } from '../Context';
1
2
  import type { PrefixArtifacts } from '../types/base/PrefixArtifacts.model';
2
3
  import type { Client } from '../types/shared/Client.model';
3
4
  import { OpenApiVersion } from './getOpenApiVersion';
@@ -8,7 +9,18 @@ type ApplyDiffParams = {
8
9
  openApiVersion: OpenApiVersion;
9
10
  diffReport: DiffReport | null;
10
11
  prefix: PrefixArtifacts;
12
+ context?: Context;
11
13
  };
12
- export declare const applyDiffReportToClient: ({ client, openApi, openApiVersion, diffReport, prefix }: ApplyDiffParams) => Client;
14
+ /**
15
+ * Применяет структурный diff-отчёт к сгенерированному клиенту: помечает изменения, miracles и ghost-свойства.
16
+ * @param client сгенерированный клиент
17
+ * @param openApi исходная OpenAPI-спецификация
18
+ * @param openApiVersion версия OpenAPI
19
+ * @param diffReport загруженный diff-отчёт или null
20
+ * @param prefix артефакты префиксов имён
21
+ * @param [context] контекст генерации для разрешения имён схем
22
+ * @returns клиент с аннотациями diff
23
+ */
24
+ export declare const applyDiffReportToClient: ({ client, openApi, openApiVersion, diffReport, prefix, context }: ApplyDiffParams) => Client;
13
25
  export {};
14
26
  //# sourceMappingURL=applyDiffReportToClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"applyDiffReportToClient.d.ts","sourceRoot":"","sources":["../../../src/core/utils/applyDiffReportToClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAW3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,kBAAkB,CAAC;AAGpE,KAAK,eAAe,GAAG;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,eAAe,CAAC;CAC3B,CAAC;AAuWF,eAAO,MAAM,uBAAuB,GAAI,yDAAyD,eAAe,KAAG,MAwClH,CAAC"}
1
+ {"version":3,"file":"applyDiffReportToClient.d.ts","sourceRoot":"","sources":["../../../src/core/utils/applyDiffReportToClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAY3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAKrD,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,kBAAkB,CAAC;AAGpE,KAAK,eAAe,GAAG;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAsbF;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,GAAI,kEAAkE,eAAe,KAAG,MAwC3H,CAAC"}
@@ -9,6 +9,7 @@ const getComment_1 = require("./getComment");
9
9
  const getModelNameWithPrefix_1 = require("./getModelNameWithPrefix");
10
10
  const getOpenApiVersion_1 = require("./getOpenApiVersion");
11
11
  const getOperationName_1 = require("./getOperationName");
12
+ const getOperationParameterName_1 = require("./getOperationParameterName");
12
13
  const getOperationPath_1 = require("./getOperationPath");
13
14
  const getServiceClassName_1 = require("./getServiceClassName");
14
15
  const serviceHelpers_1 = require("./serviceHelpers");
@@ -21,12 +22,28 @@ const getSchemaDefinitions = (openApi, version) => {
21
22
  const definitions = openApi?.definitions;
22
23
  return definitions ?? {};
23
24
  };
24
- const buildSchemaNameMap = (openApi, version, prefix) => {
25
+ const buildLocalSchemaRef = (schemaName, version) => (version === getOpenApiVersion_1.OpenApiVersion.V3 ? `#/components/schemas/${schemaName}` : `#/definitions/${schemaName}`);
26
+ const resolveSchemaDefinition = (schemaName, schemaDef, version, context) => {
27
+ if (context) {
28
+ try {
29
+ const resolved = context.get(buildLocalSchemaRef(schemaName, version));
30
+ if (resolved && typeof resolved === 'object') {
31
+ return resolved;
32
+ }
33
+ }
34
+ catch {
35
+ // fallback to raw schemaDef
36
+ }
37
+ }
38
+ return schemaDef;
39
+ };
40
+ const buildSchemaNameMap = (openApi, version, prefix, context) => {
25
41
  const definitions = getSchemaDefinitions(openApi, version);
26
42
  const map = new Map();
27
43
  Object.entries(definitions).forEach(([schemaName, schemaDef]) => {
44
+ const resolvedDef = resolveSchemaDefinition(schemaName, schemaDef, version, context);
28
45
  const encodedName = (0, encode_1.encode)(schemaName);
29
- const modelName = (0, getModelNameWithPrefix_1.getModelNameWithPrefix)(encodedName, schemaDef, prefix);
46
+ const modelName = (0, getModelNameWithPrefix_1.getModelNameWithPrefix)(encodedName, resolvedDef, prefix);
30
47
  map.set(schemaName, modelName);
31
48
  });
32
49
  return map;
@@ -96,7 +113,43 @@ const mergeOperationDiff = (existing, entry) => {
96
113
  severity,
97
114
  };
98
115
  };
99
- const buildOperationKey = (method, path) => `${method.toUpperCase()} ${(0, getOperationPath_1.getOperationPath)(path)}`;
116
+ const normalizeOperationPathForKey = (path) => path.replace(/\$\{([^}]+)\}/g, '{$1}').replace(/\{([^}]+)\}/g, (substring, name) => (substring === '{api-version}' ? substring : `{${name}}`));
117
+ const buildOperationKey = (method, path) => `${method.toUpperCase()} ${normalizeOperationPathForKey(path)}`;
118
+ const createGhostPathParameters = (path) => {
119
+ const parameters = [];
120
+ const pattern = /\{([^}]+)\}/g;
121
+ let match;
122
+ while ((match = pattern.exec(path)) !== null) {
123
+ const prop = match[1];
124
+ if (prop === 'api-version') {
125
+ continue;
126
+ }
127
+ const name = (0, getOperationParameterName_1.getOperationParameterName)(prop);
128
+ parameters.push({
129
+ in: 'path',
130
+ prop,
131
+ name,
132
+ alias: '',
133
+ path: '',
134
+ export: 'generic',
135
+ type: 'string',
136
+ base: 'string',
137
+ template: null,
138
+ link: null,
139
+ description: null,
140
+ isDefinition: false,
141
+ isReadOnly: false,
142
+ isRequired: true,
143
+ isNullable: false,
144
+ imports: [],
145
+ enum: [],
146
+ enums: [],
147
+ properties: [],
148
+ mediaType: null,
149
+ });
150
+ }
151
+ return parameters;
152
+ };
100
153
  const findOperationMatches = (entries) => {
101
154
  const operationDiffs = new Map();
102
155
  const removedOperations = [];
@@ -128,6 +181,7 @@ const createGhostOperation = (match, serviceName) => {
128
181
  const description = typeof from.description === 'string' ? from.description : '';
129
182
  const operationNameFallback = `${match.method}${serviceName}`;
130
183
  const operationName = (0, getOperationName_1.getOperationName)(operationId || operationNameFallback);
184
+ const pathParameters = createGhostPathParameters(match.path);
131
185
  return {
132
186
  service: serviceName,
133
187
  name: operationName,
@@ -136,8 +190,8 @@ const createGhostOperation = (match, serviceName) => {
136
190
  deprecated: true,
137
191
  method: match.method.toUpperCase(),
138
192
  path: (0, getOperationPath_1.getOperationPath)(match.path),
139
- parameters: [],
140
- parametersPath: [],
193
+ parameters: pathParameters,
194
+ parametersPath: pathParameters,
141
195
  parametersQuery: [],
142
196
  parametersForm: [],
143
197
  parametersHeader: [],
@@ -196,20 +250,32 @@ const applyOperationDiffs = (client, entries) => {
196
250
  }
197
251
  client.services = Array.from(servicesMap.values());
198
252
  };
199
- const applyModelDiffs = (client, entries, openApi, openApiVersion, prefix) => {
200
- const schemaNameMap = buildSchemaNameMap(openApi, openApiVersion, prefix);
201
- const modelsByName = new Map(client.models.map(model => [model.name, model]));
253
+ const buildModelsByName = (models) => {
254
+ const modelsByName = new Map();
255
+ models.forEach(model => {
256
+ const list = modelsByName.get(model.name) ?? [];
257
+ list.push(model);
258
+ modelsByName.set(model.name, list);
259
+ });
260
+ return modelsByName;
261
+ };
262
+ const getModelsForSchema = (schemaName, schemaNameMap, modelsByName) => {
263
+ const modelName = schemaNameMap.get(schemaName);
264
+ if (!modelName)
265
+ return [];
266
+ return modelsByName.get(modelName) ?? [];
267
+ };
268
+ const applyModelDiffs = (client, entries, openApi, openApiVersion, prefix, context) => {
269
+ const schemaNameMap = buildSchemaNameMap(openApi, openApiVersion, prefix, context);
270
+ const modelsByName = buildModelsByName(client.models);
202
271
  const ghostPropertyKeys = new Set();
203
272
  entries.forEach(entry => {
204
273
  const segments = (0, jsonPath_1.parseJsonPath)(entry.path);
205
274
  const schemaName = getSchemaNameFromSegments(segments, openApiVersion);
206
275
  if (!schemaName)
207
276
  return;
208
- const modelName = schemaNameMap.get(schemaName);
209
- if (!modelName)
210
- return;
211
- const model = modelsByName.get(modelName);
212
- if (!model)
277
+ const models = getModelsForSchema(schemaName, schemaNameMap, modelsByName);
278
+ if (models.length === 0)
213
279
  return;
214
280
  const propertiesIndex = segments.indexOf('properties');
215
281
  if (propertiesIndex === -1 || propertiesIndex + 1 >= segments.length) {
@@ -217,68 +283,70 @@ const applyModelDiffs = (client, entries, openApi, openApiVersion, prefix) => {
217
283
  }
218
284
  const rawPropertyName = segments[propertiesIndex + 1];
219
285
  const propertyName = (0, escapeName_1.escapeName)(rawPropertyName);
220
- if (entry.action === 'removed' && propertiesIndex + 1 === segments.length - 1) {
221
- const key = `${modelName}:${propertyName}`;
222
- if (ghostPropertyKeys.has(key))
223
- return;
224
- const exists = model.properties.some(prop => prop.name === propertyName);
225
- if (!exists) {
226
- const ghost = {
227
- name: propertyName,
228
- alias: '',
229
- path: model.path,
230
- export: 'generic',
231
- type: 'unknown',
232
- base: 'unknown',
233
- template: null,
234
- link: null,
235
- description: null,
236
- isDefinition: false,
237
- isReadOnly: false,
238
- isRequired: false,
239
- isNullable: false,
240
- imports: [],
241
- enum: [],
242
- enums: [],
243
- properties: [],
244
- diff: {
245
- action: 'removed',
246
- path: entry.path,
247
- severity: entry.severity,
248
- from: entry.from,
249
- to: entry.to,
250
- },
251
- isGhost: true,
252
- };
253
- if (!model.ghostProperties) {
254
- model.ghostProperties = [];
286
+ for (const model of models) {
287
+ if (entry.action === 'removed' && propertiesIndex + 1 === segments.length - 1) {
288
+ const key = `${model.name}:${model.alias}:${propertyName}`;
289
+ if (ghostPropertyKeys.has(key))
290
+ continue;
291
+ const exists = model.properties.some(prop => prop.name === propertyName);
292
+ if (!exists) {
293
+ const ghost = {
294
+ name: propertyName,
295
+ alias: '',
296
+ path: model.path,
297
+ export: 'generic',
298
+ type: 'unknown',
299
+ base: 'unknown',
300
+ template: null,
301
+ link: null,
302
+ description: null,
303
+ isDefinition: false,
304
+ isReadOnly: false,
305
+ isRequired: false,
306
+ isNullable: false,
307
+ imports: [],
308
+ enum: [],
309
+ enums: [],
310
+ properties: [],
311
+ diff: {
312
+ action: 'removed',
313
+ path: entry.path,
314
+ severity: entry.severity,
315
+ from: entry.from,
316
+ to: entry.to,
317
+ },
318
+ isGhost: true,
319
+ };
320
+ if (!model.ghostProperties) {
321
+ model.ghostProperties = [];
322
+ }
323
+ model.ghostProperties.push(ghost);
324
+ ghostPropertyKeys.add(key);
255
325
  }
256
- model.ghostProperties.push(ghost);
257
- ghostPropertyKeys.add(key);
326
+ continue;
258
327
  }
259
- return;
260
- }
261
- if (entry.action === 'changed' && segments[segments.length - 1] === 'type') {
262
- const property = model.properties.find(prop => prop.name === propertyName);
263
- if (!property)
264
- return;
265
- const previousType = describeSchemaType(entry.from);
266
- const currentTypeRaw = typeof entry.to === 'string' ? entry.to : describeSchemaType(entry.to);
267
- const currentType = normalizeScalarType(currentTypeRaw);
268
- const previousScalar = normalizeScalarType(previousType);
269
- property.diff = {
270
- action: entry.action,
271
- path: entry.path,
272
- severity: entry.severity,
273
- from: entry.from,
274
- to: entry.to,
275
- previousType,
276
- };
277
- if (previousScalar && currentType && previousScalar !== currentType) {
278
- property.needsCoercion = true;
279
- property.coercionFrom = previousScalar;
280
- property.coercionTo = currentType;
281
- model.hasCoercion = true;
328
+ if (entry.action === 'changed' && segments[segments.length - 1] === 'type') {
329
+ const property = model.properties.find(prop => prop.name === propertyName);
330
+ if (!property)
331
+ continue;
332
+ const previousType = describeSchemaType(entry.from);
333
+ const currentTypeRaw = typeof entry.to === 'string' ? entry.to : describeSchemaType(entry.to);
334
+ const currentType = normalizeScalarType(currentTypeRaw);
335
+ const previousScalar = normalizeScalarType(previousType);
336
+ property.diff = {
337
+ action: entry.action,
338
+ path: entry.path,
339
+ severity: entry.severity,
340
+ from: entry.from,
341
+ to: entry.to,
342
+ previousType,
343
+ };
344
+ if (previousScalar && currentType && previousScalar !== currentType) {
345
+ property.needsCoercion = true;
346
+ property.coercionFrom = previousScalar;
347
+ property.coercionTo = currentType;
348
+ model.hasCoercion = true;
349
+ }
282
350
  }
283
351
  }
284
352
  });
@@ -286,53 +354,65 @@ const applyModelDiffs = (client, entries, openApi, openApiVersion, prefix) => {
286
354
  const applyMiracleTypeCoercions = (client, confirmedMiracles, entries) => {
287
355
  if (!confirmedMiracles.length)
288
356
  return;
289
- const modelsByName = new Map(client.models.map(model => [model.name, model]));
357
+ const modelsByName = buildModelsByName(client.models);
290
358
  for (const miracle of confirmedMiracles) {
291
359
  if (miracle.type !== 'TYPE_COERCION')
292
360
  continue;
293
361
  if (!miracle.modelName)
294
362
  continue;
295
- const model = modelsByName.get(miracle.modelName);
296
- if (!model)
363
+ const models = modelsByName.get(miracle.modelName) ?? [];
364
+ if (models.length === 0)
297
365
  continue;
298
366
  const rawProperty = miracle.newProperty ?? miracle.oldProperty;
299
367
  if (!rawProperty)
300
368
  continue;
301
369
  const propertyName = (0, escapeName_1.escapeName)(rawProperty);
302
- const property = model.properties.find(prop => prop.name === propertyName);
303
- if (!property)
304
- continue;
305
- property.needsCoercion = true;
306
- model.hasCoercion = true;
307
- if (!miracle.newPath)
308
- continue;
309
- const typePath = `${miracle.newPath}.type`;
310
- const typeEntry = entries.find(entry => entry.action === 'changed' && entry.path === typePath);
311
- if (!typeEntry)
312
- continue;
313
- const previousType = describeSchemaType(typeEntry.from);
314
- const currentTypeRaw = typeof typeEntry.to === 'string' ? typeEntry.to : describeSchemaType(typeEntry.to);
315
- const currentType = normalizeScalarType(currentTypeRaw);
316
- const previousScalar = normalizeScalarType(previousType);
317
- if (previousScalar && currentType && previousScalar !== currentType) {
318
- property.coercionFrom = previousScalar;
319
- property.coercionTo = currentType;
320
- if (!property.diff) {
321
- property.diff = {
322
- action: typeEntry.action,
323
- path: typeEntry.path,
324
- severity: typeEntry.severity,
325
- from: typeEntry.from,
326
- to: typeEntry.to,
327
- previousType,
328
- };
370
+ for (const model of models) {
371
+ const property = model.properties.find(prop => prop.name === propertyName);
372
+ if (!property)
373
+ continue;
374
+ property.needsCoercion = true;
375
+ model.hasCoercion = true;
376
+ if (!miracle.newPath)
377
+ continue;
378
+ const typePath = `${miracle.newPath}.type`;
379
+ const typeEntry = entries.find(entry => entry.action === 'changed' && entry.path === typePath);
380
+ if (!typeEntry)
381
+ continue;
382
+ const previousType = describeSchemaType(typeEntry.from);
383
+ const currentTypeRaw = typeof typeEntry.to === 'string' ? typeEntry.to : describeSchemaType(typeEntry.to);
384
+ const currentType = normalizeScalarType(currentTypeRaw);
385
+ const previousScalar = normalizeScalarType(previousType);
386
+ if (previousScalar && currentType && previousScalar !== currentType) {
387
+ property.coercionFrom = previousScalar;
388
+ property.coercionTo = currentType;
389
+ if (!property.diff) {
390
+ property.diff = {
391
+ action: typeEntry.action,
392
+ path: typeEntry.path,
393
+ severity: typeEntry.severity,
394
+ from: typeEntry.from,
395
+ to: typeEntry.to,
396
+ previousType,
397
+ };
398
+ }
329
399
  }
330
400
  }
331
401
  }
332
402
  };
333
- const applyDiffReportToClient = ({ client, openApi, openApiVersion, diffReport, prefix }) => {
403
+ /**
404
+ * Применяет структурный diff-отчёт к сгенерированному клиенту: помечает изменения, miracles и ghost-свойства.
405
+ * @param client сгенерированный клиент
406
+ * @param openApi исходная OpenAPI-спецификация
407
+ * @param openApiVersion версия OpenAPI
408
+ * @param diffReport загруженный diff-отчёт или null
409
+ * @param prefix артефакты префиксов имён
410
+ * @param [context] контекст генерации для разрешения имён схем
411
+ * @returns клиент с аннотациями diff
412
+ */
413
+ const applyDiffReportToClient = ({ client, openApi, openApiVersion, diffReport, prefix, context }) => {
334
414
  const entries = diffReport?.diff?.all ?? [];
335
- const schemaNameMap = buildSchemaNameMap(openApi, openApiVersion, prefix);
415
+ const schemaNameMap = buildSchemaNameMap(openApi, openApiVersion, prefix, context);
336
416
  const confirmedMiracles = (diffReport?.miracles ?? [])
337
417
  .filter(miracle => miracle.status === 'confirmed' || miracle.confidence === 1)
338
418
  .map(miracle => {
@@ -341,7 +421,7 @@ const applyDiffReportToClient = ({ client, openApi, openApiVersion, diffReport,
341
421
  const oldSchema = getSchemaNameFromSegments(oldSegments, openApiVersion);
342
422
  const newSchema = getSchemaNameFromSegments(newSegments, openApiVersion);
343
423
  const schemaName = oldSchema || newSchema;
344
- const modelName = schemaName ? schemaNameMap.get(schemaName) : undefined;
424
+ const modelName = (schemaName ? schemaNameMap.get(schemaName) : undefined) ?? miracle.modelName;
345
425
  const oldPropIndex = oldSegments.indexOf('properties');
346
426
  const newPropIndex = newSegments.indexOf('properties');
347
427
  const oldProperty = oldPropIndex !== -1 ? oldSegments[oldPropIndex + 1] : undefined;
@@ -360,7 +440,7 @@ const applyDiffReportToClient = ({ client, openApi, openApiVersion, diffReport,
360
440
  if (entries.length === 0) {
361
441
  return client;
362
442
  }
363
- applyModelDiffs(client, entries, openApi, openApiVersion, prefix);
443
+ applyModelDiffs(client, entries, openApi, openApiVersion, prefix, context);
364
444
  applyOperationDiffs(client, entries);
365
445
  return client;
366
446
  };
@@ -0,0 +1,25 @@
1
+ import type { SemanticDiffChange } from '../semanticDiff/analyzeOpenApiDiff';
2
+ import type { MiracleEntry } from '../types/shared/Miracle.model';
3
+ type SemanticPropertyChange = {
4
+ schemaPath: string;
5
+ schemaName: string;
6
+ propertyName: string;
7
+ jsonPath: string;
8
+ payload: Record<string, unknown>;
9
+ typeSignature?: string;
10
+ description?: string;
11
+ };
12
+ /**
13
+ * Разбирает JSON Pointer свойства схемы в метаданные изменения.
14
+ * @param path JSON Pointer путь к свойству
15
+ * @returns метаданные изменения или null, если путь не относится к свойству схемы
16
+ */
17
+ export declare function parseSchemaPropertyPointer(path: string): Omit<SemanticPropertyChange, 'payload' | 'typeSignature' | 'description'> | null;
18
+ /**
19
+ * Строит miracles типов RENAME и TYPE_COERCION из семантических изменений.
20
+ * @param changes список семантических изменений
21
+ * @returns список miracles
22
+ */
23
+ export declare function buildMiraclesFromSemanticChanges(changes: SemanticDiffChange[]): MiracleEntry[];
24
+ export {};
25
+ //# sourceMappingURL=buildMiraclesFromSemanticChanges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildMiraclesFromSemanticChanges.d.ts","sourceRoot":"","sources":["../../../src/core/utils/buildMiraclesFromSemanticChanges.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,KAAK,sBAAsB,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAIF;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,sBAAsB,EAAE,SAAS,GAAG,eAAe,GAAG,aAAa,CAAC,GAAG,IAAI,CAezI;AA0CD;;;;GAIG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,YAAY,EAAE,CA6F9F"}