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.
- package/README.md +4 -0
- package/README.rus.md +4 -0
- package/dist/cli/analyzeDiff/__tests__/analyzeDiff.cli.test.js +31 -24
- package/dist/cli/analyzeDiff/__tests__/analyzeDiffLomMiracles.test.d.ts +2 -0
- package/dist/cli/analyzeDiff/__tests__/analyzeDiffLomMiracles.test.d.ts.map +1 -0
- package/dist/cli/analyzeDiff/__tests__/analyzeDiffLomMiracles.test.js +47 -0
- package/dist/cli/analyzeDiff/__tests__/analyzeDiffRenameAndInvalidRegex.test.js +8 -7
- package/dist/cli/analyzeDiff/__tests__/analyzeDiffTypeCoercion.test.js +8 -7
- package/dist/cli/analyzeDiff/analyzeDiff.d.ts +14 -2
- package/dist/cli/analyzeDiff/analyzeDiff.d.ts.map +1 -1
- package/dist/cli/analyzeDiff/analyzeDiff.js +56 -13
- package/dist/cli/analyzeDiff/ciSummary.d.ts +6 -3
- package/dist/cli/analyzeDiff/ciSummary.d.ts.map +1 -1
- package/dist/cli/analyzeDiff/ciSummary.js +10 -6
- package/dist/cli/analyzeDiff/report.d.ts +0 -1
- package/dist/cli/analyzeDiff/report.d.ts.map +1 -1
- package/dist/cli/analyzeDiff/report.js +1 -3
- package/dist/cli/analyzeDiff/writeLegacyReport.d.ts +2 -0
- package/dist/cli/analyzeDiff/writeLegacyReport.d.ts.map +1 -1
- package/dist/cli/analyzeDiff/writeLegacyReport.js +2 -0
- package/dist/cli/analyzeUsage/core/Scanner.d.ts +8 -0
- package/dist/cli/analyzeUsage/core/Scanner.d.ts.map +1 -1
- package/dist/cli/analyzeUsage/core/Scanner.js +10 -0
- package/dist/cli/analyzeUsage/rules/ClientRule.d.ts +8 -0
- package/dist/cli/analyzeUsage/rules/ClientRule.d.ts.map +1 -1
- package/dist/cli/analyzeUsage/rules/ClientRule.js +10 -0
- package/dist/cli/analyzeUsage/rules/ServiceRule.d.ts +8 -0
- package/dist/cli/analyzeUsage/rules/ServiceRule.d.ts.map +1 -1
- package/dist/cli/analyzeUsage/rules/ServiceRule.js +10 -0
- package/dist/common/LoggerMessages.d.ts +5 -0
- package/dist/common/LoggerMessages.d.ts.map +1 -1
- package/dist/common/LoggerMessages.js +4 -0
- package/dist/core/OpenApiClient.d.ts +8 -0
- package/dist/core/OpenApiClient.d.ts.map +1 -1
- package/dist/core/OpenApiClient.js +16 -2
- package/dist/core/WriteClient.d.ts +52 -15
- package/dist/core/WriteClient.d.ts.map +1 -1
- package/dist/core/WriteClient.js +36 -4
- package/dist/core/semanticDiff/__tests__/analyzeOpenApiDiff.test.js +72 -0
- package/dist/core/semanticDiff/__tests__/semanticDiffReportSchema.test.js +20 -1
- package/dist/core/semanticDiff/analyzeOpenApiDiff.d.ts +58 -6
- package/dist/core/semanticDiff/analyzeOpenApiDiff.d.ts.map +1 -1
- package/dist/core/semanticDiff/analyzeOpenApiDiff.js +47 -19
- package/dist/core/semanticDiff/semanticDiffReportSchema.d.ts +11 -1
- package/dist/core/semanticDiff/semanticDiffReportSchema.d.ts.map +1 -1
- package/dist/core/semanticDiff/semanticDiffReportSchema.js +140 -50
- package/dist/core/types/DiffReport.model.d.ts +101 -0
- package/dist/core/types/DiffReport.model.d.ts.map +1 -0
- package/dist/core/types/DiffReport.model.js +5 -0
- package/dist/core/types/shared/Model.model.d.ts +36 -0
- package/dist/core/types/shared/Model.model.d.ts.map +1 -1
- package/dist/core/utils/__tests__/applyDiffReportToClient.test.js +182 -0
- package/dist/core/utils/__tests__/buildMiraclesFromSemanticChanges.test.d.ts +2 -0
- package/dist/core/utils/__tests__/buildMiraclesFromSemanticChanges.test.d.ts.map +1 -0
- package/dist/core/utils/__tests__/buildMiraclesFromSemanticChanges.test.js +77 -0
- package/dist/core/utils/__tests__/expandOpenApiRefsForSemanticDiff.test.d.ts +2 -0
- package/dist/core/utils/__tests__/expandOpenApiRefsForSemanticDiff.test.d.ts.map +1 -0
- package/dist/core/utils/__tests__/expandOpenApiRefsForSemanticDiff.test.js +159 -0
- package/dist/core/utils/__tests__/loadDiffReport.test.js +131 -0
- package/dist/core/utils/__tests__/modelHelpers.test.js +27 -9
- package/dist/core/utils/__tests__/prepareDtoModels.test.js +74 -2
- package/dist/core/utils/__tests__/resolveClassesModeTypes.test.d.ts +2 -0
- package/dist/core/utils/__tests__/resolveClassesModeTypes.test.d.ts.map +1 -0
- package/dist/core/utils/__tests__/resolveClassesModeTypes.test.js +111 -0
- package/dist/core/utils/__tests__/semanticChangesToDiffEntries.test.d.ts +2 -0
- package/dist/core/utils/__tests__/semanticChangesToDiffEntries.test.d.ts.map +1 -0
- package/dist/core/utils/__tests__/semanticChangesToDiffEntries.test.js +68 -0
- package/dist/core/utils/__tests__/serviceHelpers.test.js +10 -11
- package/dist/core/utils/__tests__/templateRendering.test.js +71 -0
- package/dist/core/utils/adapters/__tests__/semanticToStructural.test.d.ts +2 -0
- package/dist/core/utils/adapters/__tests__/semanticToStructural.test.d.ts.map +1 -0
- package/dist/core/utils/adapters/__tests__/semanticToStructural.test.js +63 -0
- package/dist/core/utils/adapters/extractMiraclesFromSemantic.d.ts +10 -0
- package/dist/core/utils/adapters/extractMiraclesFromSemantic.d.ts.map +1 -0
- package/dist/core/utils/adapters/extractMiraclesFromSemantic.js +13 -0
- package/dist/core/utils/adapters/index.d.ts +4 -0
- package/dist/core/utils/adapters/index.d.ts.map +1 -0
- package/dist/core/utils/adapters/index.js +8 -0
- package/dist/core/utils/adapters/semanticToStructural.d.ts +12 -0
- package/dist/core/utils/adapters/semanticToStructural.d.ts.map +1 -0
- package/dist/core/utils/adapters/semanticToStructural.js +36 -0
- package/dist/core/utils/applyDiffReportToClient.d.ts +13 -1
- package/dist/core/utils/applyDiffReportToClient.d.ts.map +1 -1
- package/dist/core/utils/applyDiffReportToClient.js +187 -107
- package/dist/core/utils/buildMiraclesFromSemanticChanges.d.ts +25 -0
- package/dist/core/utils/buildMiraclesFromSemanticChanges.d.ts.map +1 -0
- package/dist/core/utils/buildMiraclesFromSemanticChanges.js +146 -0
- package/dist/core/utils/expandOpenApiRefsForSemanticDiff.d.ts +23 -0
- package/dist/core/utils/expandOpenApiRefsForSemanticDiff.d.ts.map +1 -0
- package/dist/core/utils/expandOpenApiRefsForSemanticDiff.js +163 -0
- package/dist/core/utils/getOpenApiSpec.d.ts +18 -0
- package/dist/core/utils/getOpenApiSpec.d.ts.map +1 -1
- package/dist/core/utils/getOpenApiSpec.js +35 -0
- package/dist/core/utils/loadDiffReport.d.ts +11 -30
- package/dist/core/utils/loadDiffReport.d.ts.map +1 -1
- package/dist/core/utils/loadDiffReport.js +69 -3
- package/dist/core/utils/loadSemanticOpenApiSpec.d.ts +15 -0
- package/dist/core/utils/loadSemanticOpenApiSpec.d.ts.map +1 -0
- package/dist/core/utils/loadSemanticOpenApiSpec.js +61 -0
- package/dist/core/utils/modelHelpers.d.ts +13 -5
- package/dist/core/utils/modelHelpers.d.ts.map +1 -1
- package/dist/core/utils/modelHelpers.js +28 -23
- package/dist/core/utils/prepareDtoModels.d.ts +5 -0
- package/dist/core/utils/prepareDtoModels.d.ts.map +1 -1
- package/dist/core/utils/prepareDtoModels.js +55 -12
- package/dist/core/utils/resolveClassesModeTypes.d.ts +8 -0
- package/dist/core/utils/resolveClassesModeTypes.d.ts.map +1 -0
- package/dist/core/utils/resolveClassesModeTypes.js +77 -0
- package/dist/core/utils/semanticChangesToDiffEntries.d.ts +37 -0
- package/dist/core/utils/semanticChangesToDiffEntries.d.ts.map +1 -0
- package/dist/core/utils/semanticChangesToDiffEntries.js +99 -0
- package/dist/core/utils/semanticPointerToJsonPath.d.ts +7 -0
- package/dist/core/utils/semanticPointerToJsonPath.d.ts.map +1 -0
- package/dist/core/utils/semanticPointerToJsonPath.js +67 -0
- package/dist/core/utils/serviceHelpers.d.ts +6 -7
- package/dist/core/utils/serviceHelpers.d.ts.map +1 -1
- package/dist/core/utils/serviceHelpers.js +8 -25
- package/dist/core/utils/writeClientServices.d.ts +14 -14
- package/dist/core/utils/writeClientServices.d.ts.map +1 -1
- package/dist/core/utils/writeClientServices.js +4 -8
- package/dist/templatesCompiled/client/exportModels.d.ts +17 -11
- package/dist/templatesCompiled/client/exportModels.d.ts.map +1 -1
- package/dist/templatesCompiled/client/exportModels.js +96 -49
- package/dist/templatesCompiled/client/exportService.d.ts +13 -10
- package/dist/templatesCompiled/client/exportService.d.ts.map +1 -1
- package/dist/templatesCompiled/client/exportService.js +95 -67
- package/package.json +1 -3
- package/dist/cli/analyzeDiff/buildLegacyReport.d.ts +0 -17
- package/dist/cli/analyzeDiff/buildLegacyReport.d.ts.map +0 -1
- package/dist/cli/analyzeDiff/buildLegacyReport.js +0 -54
- package/dist/cli/analyzeDiff/diffEngine.d.ts +0 -54
- package/dist/cli/analyzeDiff/diffEngine.d.ts.map +0 -1
- package/dist/cli/analyzeDiff/diffEngine.js +0 -209
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { GovernanceReport } from '../governance/evaluateGovernanceRules';
|
|
2
|
+
import type { SemanticDiffChange, SemanticDiffRecommendation, SemanticDiffSummary } from '../semanticDiff/analyzeOpenApiDiff';
|
|
3
|
+
import type { DiffInfo } from './shared/DiffInfo.model';
|
|
4
|
+
import type { MiracleEntry } from './shared/Miracle.model';
|
|
5
|
+
/** Версия схемы унифицированного diff-отчёта. */
|
|
6
|
+
export declare const UNIFIED_DIFF_REPORT_SCHEMA_VERSION = "2.0.0";
|
|
7
|
+
/** Запись структурного diff с обязательным действием изменения. */
|
|
8
|
+
export interface DiffReportEntry extends DiffInfo {
|
|
9
|
+
action: DiffInfo['action'];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Метаданные diff-отчёта.
|
|
13
|
+
* @property [base] источник базовой спецификации
|
|
14
|
+
* @property [target] источник целевой спецификации
|
|
15
|
+
* @property [baseHash] хеш базовой спецификации
|
|
16
|
+
* @property [targetHash] хеш целевой спецификации
|
|
17
|
+
*/
|
|
18
|
+
export interface DiffReportMetadata {
|
|
19
|
+
base?: string;
|
|
20
|
+
target?: string;
|
|
21
|
+
baseHash?: string;
|
|
22
|
+
targetHash?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Статистика изменений в diff-отчёте.
|
|
26
|
+
* @property [totalChanges] общее количество изменений
|
|
27
|
+
* @property [added] количество добавлений
|
|
28
|
+
* @property [removed] количество удалений
|
|
29
|
+
* @property [changed] количество изменений
|
|
30
|
+
* @property [ignored] количество проигнорированных изменений
|
|
31
|
+
* @property [stabilityScore] оценка стабильности API в процентах
|
|
32
|
+
*/
|
|
33
|
+
export interface DiffReportStats {
|
|
34
|
+
totalChanges?: number;
|
|
35
|
+
added?: number;
|
|
36
|
+
removed?: number;
|
|
37
|
+
changed?: number;
|
|
38
|
+
ignored?: number;
|
|
39
|
+
stabilityScore?: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Структурная часть diff-отчёта для генерации клиента.
|
|
43
|
+
* @property diff группы изменений по уровню серьёзности
|
|
44
|
+
* @property miracles кандидаты на переименование и приведение типов
|
|
45
|
+
* @property stats агрегированная статистика изменений
|
|
46
|
+
*/
|
|
47
|
+
export interface StructuralDiffPart {
|
|
48
|
+
diff: {
|
|
49
|
+
breaking: DiffReportEntry[];
|
|
50
|
+
warnings: DiffReportEntry[];
|
|
51
|
+
info: DiffReportEntry[];
|
|
52
|
+
all: DiffReportEntry[];
|
|
53
|
+
};
|
|
54
|
+
miracles: MiracleEntry[];
|
|
55
|
+
stats: DiffReportStats;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Legacy diff-отчёт для обратной совместимости.
|
|
59
|
+
* @property [version] версия схемы отчёта
|
|
60
|
+
* @property [timestamp] время формирования отчёта
|
|
61
|
+
* @property [metadata] метаданные сравниваемых спецификаций
|
|
62
|
+
* @property [stats] статистика изменений
|
|
63
|
+
* @property [diff] группы изменений по уровню серьёзности
|
|
64
|
+
* @property [miracles] кандидаты на переименование и приведение типов
|
|
65
|
+
*/
|
|
66
|
+
export interface DiffReport {
|
|
67
|
+
version?: string;
|
|
68
|
+
timestamp?: string;
|
|
69
|
+
metadata?: DiffReportMetadata;
|
|
70
|
+
stats?: DiffReportStats;
|
|
71
|
+
diff?: {
|
|
72
|
+
breaking?: DiffReportEntry[];
|
|
73
|
+
warnings?: DiffReportEntry[];
|
|
74
|
+
info?: DiffReportEntry[];
|
|
75
|
+
all?: DiffReportEntry[];
|
|
76
|
+
};
|
|
77
|
+
miracles?: MiracleEntry[];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Унифицированный diff-отчёт с семантической и структурной частями.
|
|
81
|
+
* @property schemaVersion версия схемы отчёта
|
|
82
|
+
* @property timestamp время формирования отчёта
|
|
83
|
+
* @property metadata метаданные сравниваемых спецификаций
|
|
84
|
+
* @property semantic семантический анализ изменений
|
|
85
|
+
* @property structural структурная часть для генерации клиента
|
|
86
|
+
*/
|
|
87
|
+
export interface UnifiedDiffReport {
|
|
88
|
+
schemaVersion: typeof UNIFIED_DIFF_REPORT_SCHEMA_VERSION;
|
|
89
|
+
timestamp: string;
|
|
90
|
+
metadata: DiffReportMetadata;
|
|
91
|
+
semantic: {
|
|
92
|
+
changes: SemanticDiffChange[];
|
|
93
|
+
governance: GovernanceReport;
|
|
94
|
+
recommendation: SemanticDiffRecommendation;
|
|
95
|
+
summary: SemanticDiffSummary;
|
|
96
|
+
};
|
|
97
|
+
structural: StructuralDiffPart;
|
|
98
|
+
}
|
|
99
|
+
/** Реэкспорт типов структурного diff и miracles. */
|
|
100
|
+
export type { DiffInfo, MiracleEntry };
|
|
101
|
+
//# sourceMappingURL=DiffReport.model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiffReport.model.d.ts","sourceRoot":"","sources":["../../../src/core/types/DiffReport.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC9H,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,iDAAiD;AACjD,eAAO,MAAM,kCAAkC,UAAU,CAAC;AAE1D,mEAAmE;AACnE,MAAM,WAAW,eAAgB,SAAQ,QAAQ;IAC7C,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE;QACF,QAAQ,EAAE,eAAe,EAAE,CAAC;QAC5B,QAAQ,EAAE,eAAe,EAAE,CAAC;QAC5B,IAAI,EAAE,eAAe,EAAE,CAAC;QACxB,GAAG,EAAE,eAAe,EAAE,CAAC;KAC1B,CAAC;IACF,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,KAAK,EAAE,eAAe,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,IAAI,CAAC,EAAE;QACH,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;QAC7B,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;QAC7B,IAAI,CAAC,EAAE,eAAe,EAAE,CAAC;QACzB,GAAG,CAAC,EAAE,eAAe,EAAE,CAAC;KAC3B,CAAC;IACF,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAC9B,aAAa,EAAE,OAAO,kCAAkC,CAAC;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,QAAQ,EAAE;QACN,OAAO,EAAE,kBAAkB,EAAE,CAAC;QAC9B,UAAU,EAAE,gBAAgB,CAAC;QAC7B,cAAc,EAAE,0BAA0B,CAAC;QAC3C,OAAO,EAAE,mBAAmB,CAAC;KAChC,CAAC;IACF,UAAU,EAAE,kBAAkB,CAAC;CAClC;AAED,oDAAoD;AACpD,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -2,6 +2,41 @@ import type { DiffInfo } from './DiffInfo.model';
|
|
|
2
2
|
import type { Enum } from './Enum.model';
|
|
3
3
|
import { Import } from './Import.model';
|
|
4
4
|
import type { Schema } from './Schema.model';
|
|
5
|
+
/**
|
|
6
|
+
* Модель OpenAPI-схемы для генерации TypeScript-типов и DTO.
|
|
7
|
+
* @property name имя модели
|
|
8
|
+
* @property alias алиас для экспорта
|
|
9
|
+
* @property path путь к схеме в спецификации
|
|
10
|
+
* @property export способ экспорта модели
|
|
11
|
+
* @property type строковое представление типа
|
|
12
|
+
* @property base базовый тип
|
|
13
|
+
* @property template шаблон generic-типа
|
|
14
|
+
* @property link связанная модель
|
|
15
|
+
* @property description описание схемы
|
|
16
|
+
* @property [default] значение по умолчанию
|
|
17
|
+
* @property imports импорты модели
|
|
18
|
+
* @property enum значения enum
|
|
19
|
+
* @property enums вложенные enum-модели
|
|
20
|
+
* @property properties свойства модели
|
|
21
|
+
* @property [ghostProperties] свойства, удалённые в новой версии API
|
|
22
|
+
* @property [diff] основное diff-изменение свойства
|
|
23
|
+
* @property [structuralDiff] список структурных diff-изменений
|
|
24
|
+
* @property [isGhost] признак ghost-свойства
|
|
25
|
+
* @property [rawName] имя raw-типа в режиме classes
|
|
26
|
+
* @property [dtoName] имя DTO-типа в режиме classes
|
|
27
|
+
* @property [exportName] имя для экспорта в режиме classes
|
|
28
|
+
* @property [rawType] строковое представление raw-типа
|
|
29
|
+
* @property [dtoType] строковое представление DTO-типа
|
|
30
|
+
* @property [dtoInit] инициализатор DTO
|
|
31
|
+
* @property [dtoToJSON] метод сериализации DTO
|
|
32
|
+
* @property [dtoTarget] целевой тип DTO
|
|
33
|
+
* @property [dtoKind] вид DTO: class или alias
|
|
34
|
+
* @property [dtoGetters] геттеры для переименованных свойств
|
|
35
|
+
* @property [needsCoercion] требуется приведение типа
|
|
36
|
+
* @property [coercionFrom] исходный тип приведения
|
|
37
|
+
* @property [coercionTo] целевой тип приведения
|
|
38
|
+
* @property [hasCoercion] признак наличия приведения типа
|
|
39
|
+
*/
|
|
5
40
|
export interface Model extends Schema {
|
|
6
41
|
name: string;
|
|
7
42
|
alias: string;
|
|
@@ -23,6 +58,7 @@ export interface Model extends Schema {
|
|
|
23
58
|
isGhost?: boolean;
|
|
24
59
|
rawName?: string;
|
|
25
60
|
dtoName?: string;
|
|
61
|
+
exportName?: string;
|
|
26
62
|
rawType?: string;
|
|
27
63
|
dtoType?: string;
|
|
28
64
|
dtoInit?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Model.model.d.ts","sourceRoot":"","sources":["../../../../src/core/types/shared/Model.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,WAAW,KAAM,SAAQ,MAAM;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACjH,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,IAAI,EAAE,CAAC;IACb,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,UAAU,EAAE,KAAK,EAAE,CAAC;IACpB,eAAe,CAAC,EAAE,KAAK,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B,UAAU,CAAC,EAAE;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;KACvB,EAAE,CAAC;IACJ,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB"}
|
|
1
|
+
{"version":3,"file":"Model.model.d.ts","sourceRoot":"","sources":["../../../../src/core/types/shared/Model.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,WAAW,KAAM,SAAQ,MAAM;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACjH,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,IAAI,EAAE,CAAC;IACb,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,UAAU,EAAE,KAAK,EAAE,CAAC;IACpB,eAAe,CAAC,EAAE,KAAK,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,cAAc,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B,UAAU,CAAC,EAAE;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;KACvB,EAAE,CAAC;IACJ,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB"}
|
|
@@ -105,4 +105,186 @@ const createObjectModel = (name, properties) => ({
|
|
|
105
105
|
node_assert_1.default.strictEqual(property?.coercionTo, 'number');
|
|
106
106
|
node_assert_1.default.ok(updatedModel.hasCoercion, 'Expected model.hasCoercion to be true');
|
|
107
107
|
});
|
|
108
|
+
(0, node_test_1.test)('marks needsCoercion for $ref alias schema via Context resolver', () => {
|
|
109
|
+
const userBodyDef = {
|
|
110
|
+
type: 'object',
|
|
111
|
+
properties: {
|
|
112
|
+
age: { type: 'number' },
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
const mockContext = {
|
|
116
|
+
get: (ref) => {
|
|
117
|
+
if (ref === '#/components/schemas/User') {
|
|
118
|
+
return userBodyDef;
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
const userModel = createObjectModel('IUser', [createPropertyModel('age', 'number')]);
|
|
124
|
+
const client = {
|
|
125
|
+
version: '1.0.0',
|
|
126
|
+
server: 'http://localhost',
|
|
127
|
+
models: [userModel],
|
|
128
|
+
services: [],
|
|
129
|
+
};
|
|
130
|
+
const openApi = {
|
|
131
|
+
openapi: '3.0.0',
|
|
132
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
133
|
+
paths: {},
|
|
134
|
+
components: {
|
|
135
|
+
schemas: {
|
|
136
|
+
User: { $ref: '#/components/schemas/UserBody' },
|
|
137
|
+
UserBody: userBodyDef,
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
const report = {
|
|
142
|
+
diff: {
|
|
143
|
+
all: [
|
|
144
|
+
{
|
|
145
|
+
action: 'changed',
|
|
146
|
+
path: '$.components.schemas.User.properties.age.type',
|
|
147
|
+
severity: 'warning',
|
|
148
|
+
from: 'string',
|
|
149
|
+
to: 'number',
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
miracles: [
|
|
154
|
+
{
|
|
155
|
+
oldPath: '$.components.schemas.User.properties.age',
|
|
156
|
+
newPath: '$.components.schemas.User.properties.age',
|
|
157
|
+
type: 'TYPE_COERCION',
|
|
158
|
+
confidence: 1,
|
|
159
|
+
status: 'auto-generated',
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
};
|
|
163
|
+
const result = (0, applyDiffReportToClient_1.applyDiffReportToClient)({
|
|
164
|
+
client,
|
|
165
|
+
openApi,
|
|
166
|
+
openApiVersion: getOpenApiVersion_1.OpenApiVersion.V3,
|
|
167
|
+
diffReport: report,
|
|
168
|
+
prefix: { interface: 'I', enum: 'E', type: 'T' },
|
|
169
|
+
context: mockContext,
|
|
170
|
+
});
|
|
171
|
+
const updatedModel = result.models[0];
|
|
172
|
+
const property = updatedModel.properties.find(prop => prop.name === 'age');
|
|
173
|
+
node_assert_1.default.ok(property?.needsCoercion, 'Expected needsCoercion to be true for $ref schema');
|
|
174
|
+
node_assert_1.default.strictEqual(property?.coercionFrom, 'string');
|
|
175
|
+
node_assert_1.default.strictEqual(property?.coercionTo, 'number');
|
|
176
|
+
node_assert_1.default.ok(updatedModel.hasCoercion, 'Expected model.hasCoercion to be true');
|
|
177
|
+
});
|
|
178
|
+
(0, node_test_1.test)('marks needsCoercion on property via applyModelDiffs with $ref schema', () => {
|
|
179
|
+
const userBodyDef = {
|
|
180
|
+
type: 'object',
|
|
181
|
+
properties: {
|
|
182
|
+
age: { type: 'number' },
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
const mockContext = {
|
|
186
|
+
get: (ref) => {
|
|
187
|
+
if (ref === '#/components/schemas/User') {
|
|
188
|
+
return userBodyDef;
|
|
189
|
+
}
|
|
190
|
+
return undefined;
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
const userModel = createObjectModel('IUser', [createPropertyModel('age', 'number')]);
|
|
194
|
+
const client = {
|
|
195
|
+
version: '1.0.0',
|
|
196
|
+
server: 'http://localhost',
|
|
197
|
+
models: [userModel],
|
|
198
|
+
services: [],
|
|
199
|
+
};
|
|
200
|
+
const openApi = {
|
|
201
|
+
openapi: '3.0.0',
|
|
202
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
203
|
+
paths: {},
|
|
204
|
+
components: {
|
|
205
|
+
schemas: {
|
|
206
|
+
User: { $ref: '#/components/schemas/UserBody' },
|
|
207
|
+
UserBody: userBodyDef,
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
const report = {
|
|
212
|
+
diff: {
|
|
213
|
+
all: [
|
|
214
|
+
{
|
|
215
|
+
action: 'changed',
|
|
216
|
+
path: '$.components.schemas.User.properties.age.type',
|
|
217
|
+
severity: 'warning',
|
|
218
|
+
from: 'string',
|
|
219
|
+
to: 'number',
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
const result = (0, applyDiffReportToClient_1.applyDiffReportToClient)({
|
|
225
|
+
client,
|
|
226
|
+
openApi,
|
|
227
|
+
openApiVersion: getOpenApiVersion_1.OpenApiVersion.V3,
|
|
228
|
+
diffReport: report,
|
|
229
|
+
prefix: { interface: 'I', enum: 'E', type: 'T' },
|
|
230
|
+
context: mockContext,
|
|
231
|
+
});
|
|
232
|
+
const updatedModel = result.models[0];
|
|
233
|
+
const property = updatedModel.properties.find(prop => prop.name === 'age');
|
|
234
|
+
node_assert_1.default.ok(property?.needsCoercion, 'Expected needsCoercion from applyModelDiffs');
|
|
235
|
+
node_assert_1.default.strictEqual(property?.coercionFrom, 'string');
|
|
236
|
+
node_assert_1.default.strictEqual(property?.coercionTo, 'number');
|
|
237
|
+
node_assert_1.default.ok(updatedModel.hasCoercion, 'Expected model.hasCoercion to be true');
|
|
238
|
+
});
|
|
239
|
+
(0, node_test_1.test)('applies model diffs to all models with the same schema name', () => {
|
|
240
|
+
const sequence1 = createObjectModel('ISequence', [createPropertyModel('pathway_id', 'string')]);
|
|
241
|
+
const sequence2 = createObjectModel('ISequence', [createPropertyModel('pathwayId', 'string')]);
|
|
242
|
+
sequence2.alias = 'ISequence$2';
|
|
243
|
+
const client = {
|
|
244
|
+
version: '1.0.0',
|
|
245
|
+
server: 'http://localhost',
|
|
246
|
+
models: [sequence1, sequence2],
|
|
247
|
+
services: [],
|
|
248
|
+
};
|
|
249
|
+
const openApi = {
|
|
250
|
+
openapi: '3.0.0',
|
|
251
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
252
|
+
paths: {},
|
|
253
|
+
components: {
|
|
254
|
+
schemas: {
|
|
255
|
+
Sequence: {
|
|
256
|
+
type: 'object',
|
|
257
|
+
properties: {
|
|
258
|
+
pathway_id: { type: 'string' },
|
|
259
|
+
pathwayId: { type: 'string' },
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
const report = {
|
|
266
|
+
diff: {
|
|
267
|
+
all: [
|
|
268
|
+
{
|
|
269
|
+
action: 'removed',
|
|
270
|
+
path: '$.components.schemas.Sequence.properties.legacyField',
|
|
271
|
+
severity: 'warning',
|
|
272
|
+
},
|
|
273
|
+
],
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
const result = (0, applyDiffReportToClient_1.applyDiffReportToClient)({
|
|
277
|
+
client,
|
|
278
|
+
openApi,
|
|
279
|
+
openApiVersion: getOpenApiVersion_1.OpenApiVersion.V3,
|
|
280
|
+
diffReport: report,
|
|
281
|
+
prefix: { interface: 'I', enum: 'E', type: 'T' },
|
|
282
|
+
});
|
|
283
|
+
const updated1 = result.models.find(model => model.name === 'ISequence' && !model.alias);
|
|
284
|
+
const updated2 = result.models.find(model => model.alias === 'ISequence$2');
|
|
285
|
+
node_assert_1.default.strictEqual(updated1?.ghostProperties?.length, 1);
|
|
286
|
+
node_assert_1.default.strictEqual(updated1?.ghostProperties?.[0].name, 'legacyField');
|
|
287
|
+
node_assert_1.default.strictEqual(updated2?.ghostProperties?.length, 1);
|
|
288
|
+
node_assert_1.default.strictEqual(updated2?.ghostProperties?.[0].name, 'legacyField');
|
|
289
|
+
});
|
|
108
290
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildMiraclesFromSemanticChanges.test.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/__tests__/buildMiraclesFromSemanticChanges.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,77 @@
|
|
|
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 buildMiraclesFromSemanticChanges_1 = require("../buildMiraclesFromSemanticChanges");
|
|
9
|
+
(0, node_test_1.describe)('@unit: buildMiraclesFromSemanticChanges', () => {
|
|
10
|
+
(0, node_test_1.test)('parses schema property pointer', () => {
|
|
11
|
+
const parsed = (0, buildMiraclesFromSemanticChanges_1.parseSchemaPropertyPointer)('#/components/schemas/User/properties/first_name');
|
|
12
|
+
node_assert_1.default.ok(parsed);
|
|
13
|
+
node_assert_1.default.strictEqual(parsed.schemaName, 'User');
|
|
14
|
+
node_assert_1.default.strictEqual(parsed.propertyName, 'first_name');
|
|
15
|
+
node_assert_1.default.strictEqual(parsed.jsonPath, '$.components.schemas.User.properties.first_name');
|
|
16
|
+
});
|
|
17
|
+
(0, node_test_1.test)('creates RENAME miracle between removed and added property', () => {
|
|
18
|
+
const changes = [
|
|
19
|
+
{
|
|
20
|
+
type: 'model.property.removed',
|
|
21
|
+
severity: 'breaking',
|
|
22
|
+
path: '#/components/schemas/User/properties/first_name',
|
|
23
|
+
message: 'removed',
|
|
24
|
+
from: { type: 'string' },
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
type: 'model.property.added',
|
|
28
|
+
severity: 'non-breaking',
|
|
29
|
+
path: '#/components/schemas/User/properties/firstName',
|
|
30
|
+
message: 'added',
|
|
31
|
+
to: { type: 'string' },
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
const miracles = (0, buildMiraclesFromSemanticChanges_1.buildMiraclesFromSemanticChanges)(changes);
|
|
35
|
+
node_assert_1.default.strictEqual(miracles.length, 1);
|
|
36
|
+
node_assert_1.default.strictEqual(miracles[0].type, 'RENAME');
|
|
37
|
+
node_assert_1.default.strictEqual(miracles[0].oldPath, '$.components.schemas.User.properties.first_name');
|
|
38
|
+
node_assert_1.default.strictEqual(miracles[0].newPath, '$.components.schemas.User.properties.firstName');
|
|
39
|
+
node_assert_1.default.ok(miracles[0].confidence >= 0.8);
|
|
40
|
+
});
|
|
41
|
+
(0, node_test_1.test)('creates TYPE_COERCION miracle for scalar type changes', () => {
|
|
42
|
+
const changes = [
|
|
43
|
+
{
|
|
44
|
+
type: 'model.property.type.changed',
|
|
45
|
+
severity: 'breaking',
|
|
46
|
+
path: '#/components/schemas/User/properties/age',
|
|
47
|
+
message: 'type changed',
|
|
48
|
+
from: 'string',
|
|
49
|
+
to: 'integer',
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
const miracles = (0, buildMiraclesFromSemanticChanges_1.buildMiraclesFromSemanticChanges)(changes);
|
|
53
|
+
node_assert_1.default.strictEqual(miracles.length, 1);
|
|
54
|
+
node_assert_1.default.strictEqual(miracles[0].type, 'TYPE_COERCION');
|
|
55
|
+
node_assert_1.default.strictEqual(miracles[0].oldPath, '$.components.schemas.User.properties.age');
|
|
56
|
+
});
|
|
57
|
+
(0, node_test_1.test)('returns empty list when rename candidates do not match', () => {
|
|
58
|
+
const changes = [
|
|
59
|
+
{
|
|
60
|
+
type: 'model.property.removed',
|
|
61
|
+
severity: 'breaking',
|
|
62
|
+
path: '#/components/schemas/User/properties/id',
|
|
63
|
+
message: 'removed',
|
|
64
|
+
from: { type: 'string' },
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: 'model.property.added',
|
|
68
|
+
severity: 'non-breaking',
|
|
69
|
+
path: '#/components/schemas/Account/properties/accountId',
|
|
70
|
+
message: 'added',
|
|
71
|
+
to: { type: 'string' },
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
const miracles = (0, buildMiraclesFromSemanticChanges_1.buildMiraclesFromSemanticChanges)(changes);
|
|
75
|
+
node_assert_1.default.deepStrictEqual(miracles, []);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expandOpenApiRefsForSemanticDiff.test.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/__tests__/expandOpenApiRefsForSemanticDiff.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,159 @@
|
|
|
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 expandOpenApiRefsForSemanticDiff_1 = require("../expandOpenApiRefsForSemanticDiff");
|
|
9
|
+
const sourceFile = '/tmp/openapi/api.yaml';
|
|
10
|
+
function createResolver(entries) {
|
|
11
|
+
return {
|
|
12
|
+
exists: ref => Object.prototype.hasOwnProperty.call(entries, ref),
|
|
13
|
+
get: ref => entries[ref],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
(0, node_test_1.describe)('@unit: expandOpenApiRefsForSemanticDiff', () => {
|
|
17
|
+
(0, node_test_1.test)('expands local refs without mutating the original document', () => {
|
|
18
|
+
const spec = {
|
|
19
|
+
openapi: '3.0.0',
|
|
20
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
21
|
+
paths: {},
|
|
22
|
+
components: {
|
|
23
|
+
schemas: {
|
|
24
|
+
User: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
id: { $ref: '#/components/schemas/UserId' },
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
UserId: { type: 'string', format: 'uuid' },
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
const expanded = (0, expandOpenApiRefsForSemanticDiff_1.expandOpenApiRefsForSemanticDiff)(spec, { sourceFile });
|
|
35
|
+
node_assert_1.default.deepStrictEqual(expanded.components.schemas.User.properties.id, { type: 'string', format: 'uuid' });
|
|
36
|
+
node_assert_1.default.deepStrictEqual(spec.components.schemas.User.properties.id, { $ref: '#/components/schemas/UserId' });
|
|
37
|
+
});
|
|
38
|
+
(0, node_test_1.test)('expands external file refs through the resolver', () => {
|
|
39
|
+
const spec = {
|
|
40
|
+
openapi: '3.0.0',
|
|
41
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
42
|
+
paths: {},
|
|
43
|
+
components: {
|
|
44
|
+
schemas: {
|
|
45
|
+
User: { $ref: './schemas/User.yaml' },
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
const resolver = createResolver({
|
|
50
|
+
'/tmp/openapi/schemas/User.yaml': {
|
|
51
|
+
type: 'object',
|
|
52
|
+
properties: {
|
|
53
|
+
name: { type: 'string' },
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
const expanded = (0, expandOpenApiRefsForSemanticDiff_1.expandOpenApiRefsForSemanticDiff)(spec, { refs: resolver, sourceFile });
|
|
58
|
+
node_assert_1.default.deepStrictEqual(expanded.components.schemas.User, {
|
|
59
|
+
type: 'object',
|
|
60
|
+
properties: {
|
|
61
|
+
name: { type: 'string' },
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
(0, node_test_1.test)('expands external file fragment refs through the resolver', () => {
|
|
66
|
+
const spec = {
|
|
67
|
+
openapi: '3.0.0',
|
|
68
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
69
|
+
paths: {},
|
|
70
|
+
components: {
|
|
71
|
+
schemas: {
|
|
72
|
+
User: { $ref: './schemas/common.yaml#/components/schemas/User' },
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
const resolver = createResolver({
|
|
77
|
+
'/tmp/openapi/schemas/common.yaml#/components/schemas/User': {
|
|
78
|
+
type: 'object',
|
|
79
|
+
required: ['id'],
|
|
80
|
+
properties: {
|
|
81
|
+
id: { type: 'string' },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
const expanded = (0, expandOpenApiRefsForSemanticDiff_1.expandOpenApiRefsForSemanticDiff)(spec, { refs: resolver, sourceFile });
|
|
86
|
+
node_assert_1.default.deepStrictEqual(expanded.components.schemas.User, {
|
|
87
|
+
type: 'object',
|
|
88
|
+
required: ['id'],
|
|
89
|
+
properties: {
|
|
90
|
+
id: { type: 'string' },
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
(0, node_test_1.test)('expands path item refs', () => {
|
|
95
|
+
const spec = {
|
|
96
|
+
openapi: '3.0.0',
|
|
97
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
98
|
+
paths: {
|
|
99
|
+
'/users': { $ref: '#/components/pathItems/Users' },
|
|
100
|
+
},
|
|
101
|
+
components: {
|
|
102
|
+
pathItems: {
|
|
103
|
+
Users: {
|
|
104
|
+
get: {
|
|
105
|
+
operationId: 'listUsers',
|
|
106
|
+
responses: {
|
|
107
|
+
'200': { description: 'ok' },
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
const expanded = (0, expandOpenApiRefsForSemanticDiff_1.expandOpenApiRefsForSemanticDiff)(spec, { sourceFile });
|
|
115
|
+
node_assert_1.default.deepStrictEqual(expanded.paths['/users'], {
|
|
116
|
+
get: {
|
|
117
|
+
operationId: 'listUsers',
|
|
118
|
+
responses: {
|
|
119
|
+
'200': { description: 'ok' },
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
(0, node_test_1.test)('keeps unresolved refs stable', () => {
|
|
125
|
+
const spec = {
|
|
126
|
+
openapi: '3.0.0',
|
|
127
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
128
|
+
paths: {},
|
|
129
|
+
components: {
|
|
130
|
+
schemas: {
|
|
131
|
+
Missing: { $ref: './missing.yaml#/Missing' },
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
const expanded = (0, expandOpenApiRefsForSemanticDiff_1.expandOpenApiRefsForSemanticDiff)(spec, { sourceFile });
|
|
136
|
+
node_assert_1.default.deepStrictEqual(expanded.components.schemas.Missing, { $ref: './missing.yaml#/Missing' });
|
|
137
|
+
});
|
|
138
|
+
(0, node_test_1.test)('keeps circular refs stringify-safe', () => {
|
|
139
|
+
const spec = {
|
|
140
|
+
openapi: '3.0.0',
|
|
141
|
+
info: { title: 'Test', version: '1.0.0' },
|
|
142
|
+
paths: {},
|
|
143
|
+
components: {
|
|
144
|
+
schemas: {
|
|
145
|
+
Node: {
|
|
146
|
+
type: 'object',
|
|
147
|
+
properties: {
|
|
148
|
+
child: { $ref: '#/components/schemas/Node' },
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
const expanded = (0, expandOpenApiRefsForSemanticDiff_1.expandOpenApiRefsForSemanticDiff)(spec, { sourceFile });
|
|
155
|
+
const child = expanded.components.schemas.Node.properties.child;
|
|
156
|
+
node_assert_1.default.deepStrictEqual(child.properties.child, { $ref: '#/components/schemas/Node' });
|
|
157
|
+
node_assert_1.default.doesNotThrow(() => JSON.stringify(expanded));
|
|
158
|
+
});
|
|
159
|
+
});
|