ts-openapi-codegen 2.1.0-beta.6 → 2.1.0-beta.7

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 (212) hide show
  1. package/dist/cli/analyzeDiff/__tests__/analyzeDiff.cli.test.js +9 -0
  2. package/dist/cli/analyzeDiff/__tests__/analyzeDiffRenameAndInvalidRegex.test.js +9 -0
  3. package/dist/cli/analyzeDiff/__tests__/analyzeDiffTypeCoercion.test.js +9 -0
  4. package/dist/cli/analyzeUsage/analyzeUsage.d.ts +4 -0
  5. package/dist/cli/analyzeUsage/analyzeUsage.d.ts.map +1 -0
  6. package/dist/cli/analyzeUsage/analyzeUsage.js +62 -0
  7. package/dist/cli/analyzeUsage/core/Analyzer.d.ts +9 -0
  8. package/dist/cli/analyzeUsage/core/Analyzer.d.ts.map +1 -0
  9. package/dist/cli/analyzeUsage/core/Analyzer.js +29 -0
  10. package/dist/cli/analyzeUsage/core/ProjectContext.d.ts +10 -0
  11. package/dist/cli/analyzeUsage/core/ProjectContext.d.ts.map +1 -0
  12. package/dist/cli/analyzeUsage/core/ProjectContext.js +63 -0
  13. package/dist/cli/analyzeUsage/core/Scanner.d.ts +15 -0
  14. package/dist/cli/analyzeUsage/core/Scanner.d.ts.map +1 -0
  15. package/dist/cli/analyzeUsage/core/Scanner.js +115 -0
  16. package/dist/cli/analyzeUsage/rules/ClientRule.d.ts +6 -0
  17. package/dist/cli/analyzeUsage/rules/ClientRule.d.ts.map +1 -0
  18. package/dist/cli/analyzeUsage/rules/ClientRule.js +78 -0
  19. package/dist/cli/analyzeUsage/rules/CoverageRule.d.ts +7 -0
  20. package/dist/cli/analyzeUsage/rules/CoverageRule.d.ts.map +1 -0
  21. package/dist/cli/analyzeUsage/rules/CoverageRule.js +63 -0
  22. package/dist/cli/analyzeUsage/rules/DiagnosticsRule.d.ts +6 -0
  23. package/dist/cli/analyzeUsage/rules/DiagnosticsRule.d.ts.map +1 -0
  24. package/dist/cli/analyzeUsage/rules/DiagnosticsRule.js +60 -0
  25. package/dist/cli/analyzeUsage/rules/ImportRule.d.ts +6 -0
  26. package/dist/cli/analyzeUsage/rules/ImportRule.d.ts.map +1 -0
  27. package/dist/cli/analyzeUsage/rules/ImportRule.js +52 -0
  28. package/dist/cli/analyzeUsage/rules/ModelRule.d.ts +6 -0
  29. package/dist/cli/analyzeUsage/rules/ModelRule.d.ts.map +1 -0
  30. package/dist/cli/analyzeUsage/rules/ModelRule.js +38 -0
  31. package/dist/cli/analyzeUsage/rules/SchemaRule.d.ts +6 -0
  32. package/dist/cli/analyzeUsage/rules/SchemaRule.d.ts.map +1 -0
  33. package/dist/cli/analyzeUsage/rules/SchemaRule.js +48 -0
  34. package/dist/cli/analyzeUsage/rules/ServiceRule.d.ts +7 -0
  35. package/dist/cli/analyzeUsage/rules/ServiceRule.d.ts.map +1 -0
  36. package/dist/cli/analyzeUsage/rules/ServiceRule.js +92 -0
  37. package/dist/cli/analyzeUsage/types.d.ts +52 -0
  38. package/dist/cli/analyzeUsage/types.d.ts.map +1 -0
  39. package/dist/cli/analyzeUsage/types.js +2 -0
  40. package/dist/cli/analyzeUsage/utils/fuzzy.d.ts +5 -0
  41. package/dist/cli/analyzeUsage/utils/fuzzy.d.ts.map +1 -0
  42. package/dist/cli/analyzeUsage/utils/fuzzy.js +38 -0
  43. package/dist/cli/analyzeUsage/utils/report.d.ts +16 -0
  44. package/dist/cli/analyzeUsage/utils/report.d.ts.map +1 -0
  45. package/dist/cli/analyzeUsage/utils/report.js +85 -0
  46. package/dist/cli/checkAndUpdateConfig/__tests__/checkConfig.test.js +10 -20
  47. package/dist/cli/checkAndUpdateConfig/__tests__/updateConfig.test.js +10 -20
  48. package/dist/cli/checkAndUpdateConfig/checkConfig.d.ts +2 -1
  49. package/dist/cli/checkAndUpdateConfig/checkConfig.d.ts.map +1 -1
  50. package/dist/cli/checkAndUpdateConfig/checkConfig.js +8 -4
  51. package/dist/cli/checkAndUpdateConfig/updateConfig.d.ts +2 -1
  52. package/dist/cli/checkAndUpdateConfig/updateConfig.d.ts.map +1 -1
  53. package/dist/cli/checkAndUpdateConfig/updateConfig.js +6 -3
  54. package/dist/cli/checkAndUpdateConfig/utils/validateAndMigrateConfigData.d.ts.map +1 -1
  55. package/dist/cli/checkAndUpdateConfig/utils/validateAndMigrateConfigData.js +19 -1
  56. package/dist/cli/generateOpenApiClient/__tests__/generateOpenApiClient.strict.test.js +18 -9
  57. package/dist/cli/generateOpenApiClient/generateOpenApiClient.d.ts +2 -5
  58. package/dist/cli/generateOpenApiClient/generateOpenApiClient.d.ts.map +1 -1
  59. package/dist/cli/generateOpenApiClient/generateOpenApiClient.js +12 -16
  60. package/dist/cli/index.js +41 -9
  61. package/dist/cli/initOpenApiConfig/__tests__/init.test.js +4 -14
  62. package/dist/cli/initOpenApiConfig/__tests__/initConfig.test.js +3 -1
  63. package/dist/cli/initOpenApiConfig/init.d.ts +2 -1
  64. package/dist/cli/initOpenApiConfig/init.d.ts.map +1 -1
  65. package/dist/cli/initOpenApiConfig/init.js +3 -3
  66. package/dist/cli/initOpenApiConfig/initCustomRequest.d.ts +0 -1
  67. package/dist/cli/initOpenApiConfig/initCustomRequest.d.ts.map +1 -1
  68. package/dist/cli/initOpenApiConfig/initCustomRequest.js +1 -2
  69. package/dist/cli/initOpenApiConfig/utils/__tests__/validateSpecFiles.test.js +9 -0
  70. package/dist/cli/initOpenApiConfig/utils/buildConfig.d.ts.map +1 -1
  71. package/dist/cli/initOpenApiConfig/utils/buildConfig.js +0 -4
  72. package/dist/cli/previewChanges/previewChanges.d.ts +2 -1
  73. package/dist/cli/previewChanges/previewChanges.d.ts.map +1 -1
  74. package/dist/cli/previewChanges/previewChanges.js +6 -6
  75. package/dist/cli/schemas/analyzeUsage.d.ts +13 -0
  76. package/dist/cli/schemas/analyzeUsage.d.ts.map +1 -0
  77. package/dist/cli/schemas/analyzeUsage.js +38 -0
  78. package/dist/cli/schemas/generate.d.ts +7 -0
  79. package/dist/cli/schemas/generate.d.ts.map +1 -1
  80. package/dist/cli/schemas/generate.js +4 -0
  81. package/dist/cli/schemas/index.d.ts +2 -2
  82. package/dist/cli/schemas/index.d.ts.map +1 -1
  83. package/dist/cli/schemas/index.js +1 -1
  84. package/dist/cli/schemas/init.d.ts +0 -1
  85. package/dist/cli/schemas/init.d.ts.map +1 -1
  86. package/dist/cli/schemas/init.js +0 -1
  87. package/dist/cli/types.d.ts +6 -0
  88. package/dist/cli/types.d.ts.map +1 -0
  89. package/dist/cli/types.js +2 -0
  90. package/dist/common/Consts.d.ts +1 -0
  91. package/dist/common/Consts.d.ts.map +1 -1
  92. package/dist/common/Consts.js +6 -2
  93. package/dist/common/Logger.js +2 -2
  94. package/dist/common/LoggerMessages.d.ts +59 -12
  95. package/dist/common/LoggerMessages.d.ts.map +1 -1
  96. package/dist/common/LoggerMessages.js +62 -15
  97. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedBase.d.ts +0 -1
  98. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedBase.d.ts.map +1 -1
  99. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedOptionsSchemaV1.d.ts +0 -2
  100. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedOptionsSchemaV1.d.ts.map +1 -1
  101. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedOptionsSchemaV2.d.ts +0 -2
  102. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedOptionsSchemaV2.d.ts.map +1 -1
  103. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedOptionsSchemaV3.d.ts +0 -2
  104. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedOptionsSchemaV3.d.ts.map +1 -1
  105. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedOptionsSchemaV4.d.ts +0 -2
  106. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedOptionsSchemaV4.d.ts.map +1 -1
  107. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedOptionsSchemaV5.d.ts +7 -2
  108. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedOptionsSchemaV5.d.ts.map +1 -1
  109. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedOptionsSchemaV5.js +5 -1
  110. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedVersionedSchemas.d.ts +14 -11
  111. package/dist/common/VersionedSchema/AllVersionedSchemas/UnifiedVersionedSchemas.d.ts.map +1 -1
  112. package/dist/common/VersionedSchema/CommonSchemas.d.ts +0 -2
  113. package/dist/common/VersionedSchema/CommonSchemas.d.ts.map +1 -1
  114. package/dist/common/VersionedSchema/CommonSchemas.js +0 -1
  115. package/dist/common/VersionedSchema/MultiOptionsVersioned/MultiOptionsMigrationPlan.d.ts.map +1 -1
  116. package/dist/common/VersionedSchema/MultiOptionsVersioned/MultiOptionsMigrationPlan.js +0 -1
  117. package/dist/common/VersionedSchema/MultiOptionsVersioned/MultiOptionsSchemaV3.d.ts +0 -1
  118. package/dist/common/VersionedSchema/MultiOptionsVersioned/MultiOptionsSchemaV3.d.ts.map +1 -1
  119. package/dist/common/VersionedSchema/MultiOptionsVersioned/MultiOptionsSchemaV4.d.ts +0 -1
  120. package/dist/common/VersionedSchema/MultiOptionsVersioned/MultiOptionsSchemaV4.d.ts.map +1 -1
  121. package/dist/common/VersionedSchema/MultiOptionsVersioned/MultiOptionsSchemaV5.d.ts +0 -1
  122. package/dist/common/VersionedSchema/MultiOptionsVersioned/MultiOptionsSchemaV5.d.ts.map +1 -1
  123. package/dist/common/VersionedSchema/OptionsVersioned/OptionsMigrationPlans.d.ts.map +1 -1
  124. package/dist/common/VersionedSchema/OptionsVersioned/OptionsMigrationPlans.js +0 -1
  125. package/dist/common/VersionedSchema/OptionsVersioned/OptionsSchemaV3.d.ts +0 -1
  126. package/dist/common/VersionedSchema/OptionsVersioned/OptionsSchemaV3.d.ts.map +1 -1
  127. package/dist/common/VersionedSchema/OptionsVersioned/OptionsSchemaV4.d.ts +0 -1
  128. package/dist/common/VersionedSchema/OptionsVersioned/OptionsSchemaV4.d.ts.map +1 -1
  129. package/dist/common/VersionedSchema/Utils/__mocks__/compatibilityCases.d.ts.map +1 -1
  130. package/dist/common/VersionedSchema/Utils/__mocks__/compatibilityCases.js +8 -9
  131. package/dist/common/VersionedSchema/Utils/migrateDataToLatestSchemaVersion.d.ts.map +1 -1
  132. package/dist/common/VersionedSchema/Utils/migrateDataToLatestSchemaVersion.js +1 -1
  133. package/dist/common/utils/__tests__/convertArrayToObject.test.js +0 -3
  134. package/dist/common/utils/convertArrayToObject.d.ts.map +1 -1
  135. package/dist/common/utils/convertArrayToObject.js +0 -2
  136. package/dist/core/OpenApiClient.d.ts +12 -1
  137. package/dist/core/OpenApiClient.d.ts.map +1 -1
  138. package/dist/core/OpenApiClient.js +193 -16
  139. package/dist/core/WriteClient.d.ts +12 -3
  140. package/dist/core/WriteClient.d.ts.map +1 -1
  141. package/dist/core/WriteClient.js +25 -5
  142. package/dist/core/plugins/getBuiltinPlugins.d.ts.map +1 -1
  143. package/dist/core/plugins/loadGeneratorPlugins.d.ts.map +1 -1
  144. package/dist/core/plugins/loadGeneratorPlugins.js +1 -1
  145. package/dist/core/types/shared/Client.model.d.ts +1 -1
  146. package/dist/core/types/shared/Client.model.d.ts.map +1 -1
  147. package/dist/core/types/shared/Model.model.d.ts +1 -1
  148. package/dist/core/types/shared/Model.model.d.ts.map +1 -1
  149. package/dist/core/utils/__tests__/prepareDtoModels.test.js +95 -0
  150. package/dist/core/utils/__tests__/writeClientServices.test.js +0 -1
  151. package/dist/core/utils/loadDiffReport.d.ts.map +1 -1
  152. package/dist/core/utils/loadDiffReport.js +5 -4
  153. package/dist/core/utils/precompileTemplates.js +3 -2
  154. package/dist/core/utils/prepareDtoModels.d.ts.map +1 -1
  155. package/dist/core/utils/prepareDtoModels.js +1 -7
  156. package/dist/core/utils/writeClientCore.d.ts +0 -2
  157. package/dist/core/utils/writeClientCore.d.ts.map +1 -1
  158. package/dist/core/utils/writeClientCore.js +19 -18
  159. package/dist/core/utils/writeClientCoreIndex.d.ts.map +1 -1
  160. package/dist/core/utils/writeClientCoreIndex.js +14 -4
  161. package/dist/core/utils/writeClientExecutor.d.ts.map +1 -1
  162. package/dist/core/utils/writeClientExecutor.js +4 -4
  163. package/dist/core/utils/writeClientFullIndex.js +4 -4
  164. package/dist/core/utils/writeClientModels.d.ts.map +1 -1
  165. package/dist/core/utils/writeClientModels.js +10 -10
  166. package/dist/core/utils/writeClientModelsIndex.d.ts +1 -1
  167. package/dist/core/utils/writeClientModelsIndex.d.ts.map +1 -1
  168. package/dist/core/utils/writeClientModelsIndex.js +14 -4
  169. package/dist/core/utils/writeClientSchemas.d.ts.map +1 -1
  170. package/dist/core/utils/writeClientSchemas.js +7 -7
  171. package/dist/core/utils/writeClientSchemasIndex.d.ts.map +1 -1
  172. package/dist/core/utils/writeClientSchemasIndex.js +14 -4
  173. package/dist/core/utils/writeClientServices.d.ts +0 -2
  174. package/dist/core/utils/writeClientServices.d.ts.map +1 -1
  175. package/dist/core/utils/writeClientServices.js +7 -8
  176. package/dist/core/utils/writeClientServicesIndex.d.ts.map +1 -1
  177. package/dist/core/utils/writeClientServicesIndex.js +14 -4
  178. package/dist/core/utils/writeClientSimpleIndex.js +4 -4
  179. package/dist/templatesCompiled/cli/customRequest.d.ts +2 -6
  180. package/dist/templatesCompiled/cli/customRequest.d.ts.map +1 -1
  181. package/dist/templatesCompiled/cli/customRequest.js +8 -28
  182. package/dist/templatesCompiled/cli/customRequestExecutor.d.ts +0 -3
  183. package/dist/templatesCompiled/cli/customRequestExecutor.d.ts.map +1 -1
  184. package/dist/templatesCompiled/cli/customRequestExecutor.js +5 -28
  185. package/dist/templatesCompiled/client/core/axios/request.d.ts +2 -6
  186. package/dist/templatesCompiled/client/core/axios/request.d.ts.map +1 -1
  187. package/dist/templatesCompiled/client/core/axios/request.js +2 -22
  188. package/dist/templatesCompiled/client/core/executor/createExecutorAdapter.d.ts +2 -5
  189. package/dist/templatesCompiled/client/core/executor/createExecutorAdapter.d.ts.map +1 -1
  190. package/dist/templatesCompiled/client/core/executor/createExecutorAdapter.js +12 -42
  191. package/dist/templatesCompiled/client/core/executor/requestExecutor.d.ts +0 -2
  192. package/dist/templatesCompiled/client/core/executor/requestExecutor.d.ts.map +1 -1
  193. package/dist/templatesCompiled/client/core/executor/requestExecutor.js +3 -11
  194. package/dist/templatesCompiled/client/core/fetch/request.d.ts +2 -6
  195. package/dist/templatesCompiled/client/core/fetch/request.d.ts.map +1 -1
  196. package/dist/templatesCompiled/client/core/fetch/request.js +2 -22
  197. package/dist/templatesCompiled/client/core/interceptors/withInterceptors.d.ts +0 -2
  198. package/dist/templatesCompiled/client/core/interceptors/withInterceptors.d.ts.map +1 -1
  199. package/dist/templatesCompiled/client/core/interceptors/withInterceptors.js +3 -11
  200. package/dist/templatesCompiled/client/core/node/request.d.ts +2 -6
  201. package/dist/templatesCompiled/client/core/node/request.d.ts.map +1 -1
  202. package/dist/templatesCompiled/client/core/node/request.js +2 -22
  203. package/dist/templatesCompiled/client/core/xhr/request.d.ts +2 -6
  204. package/dist/templatesCompiled/client/core/xhr/request.d.ts.map +1 -1
  205. package/dist/templatesCompiled/client/core/xhr/request.js +2 -22
  206. package/dist/templatesCompiled/client/exportService.d.ts +9 -11
  207. package/dist/templatesCompiled/client/exportService.d.ts.map +1 -1
  208. package/dist/templatesCompiled/client/exportService.js +64 -82
  209. package/dist/test/helpers/silenceLoggers.d.ts +11 -0
  210. package/dist/test/helpers/silenceLoggers.d.ts.map +1 -0
  211. package/dist/test/helpers/silenceLoggers.js +88 -0
  212. package/package.json +4 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImportRule.d.ts","sourceRoot":"","sources":["../../../../src/cli/analyzeUsage/rules/ImportRule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAG/D,qBAAa,UAAW,YAAW,IAAI;IAC/B,KAAK,CACT,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,QAAQ,EAElB,MAAM,EAAE,KAAK,GACZ,OAAO,CAAC,OAAO,EAAE,CAAC;CAiDtB"}
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ImportRule = void 0;
4
+ const fuzzy_1 = require("../utils/fuzzy");
5
+ class ImportRule {
6
+ async check(context, contract,
7
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
8
+ _stats) {
9
+ const findings = [];
10
+ const rootExports = new Set(contract.sourceFile.getExportedDeclarations().keys());
11
+ for (const file of context.getConsumerSourceFiles()) {
12
+ for (const imp of file.getImportDeclarations()) {
13
+ const moduleName = imp.getModuleSpecifierValue();
14
+ if (moduleName !== "@lom-api" && !moduleName.startsWith("@lom-api/")) {
15
+ continue;
16
+ }
17
+ const importedSource = imp.getModuleSpecifierSourceFile();
18
+ if (!importedSource) {
19
+ findings.push({
20
+ id: "INVALID_IMPORT_PATH",
21
+ category: "INVALID_IMPORT",
22
+ severity: "ERROR",
23
+ message: `Import "${moduleName}" could not be resolved.`,
24
+ file: file.getFilePath(),
25
+ line: imp.getStartLineNumber(),
26
+ });
27
+ continue;
28
+ }
29
+ const allowedExports = moduleName === "@lom-api"
30
+ ? rootExports
31
+ : new Set(importedSource.getExportedDeclarations().keys());
32
+ for (const namedImport of imp.getNamedImports()) {
33
+ const importedName = namedImport.getName();
34
+ if (allowedExports.has(importedName))
35
+ continue;
36
+ const suggestion = (0, fuzzy_1.findBestMatch)(importedName, [...allowedExports]);
37
+ findings.push({
38
+ id: "INVALID_IMPORT_NAME",
39
+ category: suggestion ? "RENAMED_SYMBOL" : "MISSING_EXPORT",
40
+ severity: "ERROR",
41
+ message: `Import "${importedName}" is not exported by "${moduleName}".${suggestion ? ` Did you mean "${suggestion}"?` : ""}`,
42
+ file: file.getFilePath(),
43
+ line: namedImport.getStartLineNumber(),
44
+ context: { suggestion },
45
+ });
46
+ }
47
+ }
48
+ }
49
+ return findings;
50
+ }
51
+ }
52
+ exports.ImportRule = ImportRule;
@@ -0,0 +1,6 @@
1
+ import type { ProjectContext } from "../core/ProjectContext";
2
+ import type { Contract, Finding, Rule, Stats } from "../types";
3
+ export declare class ModelRule implements Rule {
4
+ check(context: ProjectContext, contract: Contract, stats: Stats): Promise<Finding[]>;
5
+ }
6
+ //# sourceMappingURL=ModelRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModelRule.d.ts","sourceRoot":"","sources":["../../../../src/cli/analyzeUsage/rules/ModelRule.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAE/D,qBAAa,SAAU,YAAW,IAAI;IAC9B,KAAK,CACT,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,OAAO,EAAE,CAAC;CAuCtB"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModelRule = void 0;
4
+ const ts_morph_1 = require("ts-morph");
5
+ class ModelRule {
6
+ async check(context, contract, stats) {
7
+ const findings = [];
8
+ const knownModels = new Set(contract.models);
9
+ for (const file of context.getConsumerSourceFiles()) {
10
+ for (const imp of file.getImportDeclarations()) {
11
+ const moduleName = imp.getModuleSpecifierValue();
12
+ if (moduleName !== "@lom-api" && !moduleName.startsWith("@lom-api/")) {
13
+ continue;
14
+ }
15
+ for (const namedImport of imp.getNamedImports()) {
16
+ const importedName = namedImport.getName();
17
+ if (importedName.endsWith("Schema") ||
18
+ importedName.endsWith("Service") ||
19
+ importedName === "createClient") {
20
+ continue;
21
+ }
22
+ const localName = namedImport.getAliasNode()?.getText() || importedName;
23
+ if (!knownModels.has(importedName))
24
+ continue;
25
+ const identifiers = file
26
+ .getDescendantsOfKind(ts_morph_1.SyntaxKind.Identifier)
27
+ .filter((id) => id.getText() === localName);
28
+ const usedOutsideImport = identifiers.some((id) => id.getFirstAncestorByKind(ts_morph_1.SyntaxKind.ImportDeclaration) == null);
29
+ if (usedOutsideImport) {
30
+ stats.usedModels.add(importedName);
31
+ }
32
+ }
33
+ }
34
+ }
35
+ return findings;
36
+ }
37
+ }
38
+ exports.ModelRule = ModelRule;
@@ -0,0 +1,6 @@
1
+ import type { ProjectContext } from "../core/ProjectContext";
2
+ import type { Contract, Finding, Rule, Stats } from "../types";
3
+ export declare class SchemaRule implements Rule {
4
+ check(context: ProjectContext, contract: Contract, stats: Stats): Promise<Finding[]>;
5
+ }
6
+ //# sourceMappingURL=SchemaRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaRule.d.ts","sourceRoot":"","sources":["../../../../src/cli/analyzeUsage/rules/SchemaRule.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAG/D,qBAAa,UAAW,YAAW,IAAI;IAC/B,KAAK,CACT,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,OAAO,EAAE,CAAC;CAgDtB"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SchemaRule = void 0;
4
+ const ts_morph_1 = require("ts-morph");
5
+ const fuzzy_1 = require("../utils/fuzzy");
6
+ class SchemaRule {
7
+ async check(context, contract, stats) {
8
+ const findings = [];
9
+ const knownSchemas = new Set(contract.schemas);
10
+ for (const file of context.getConsumerSourceFiles()) {
11
+ const imports = file.getImportDeclarations();
12
+ for (const imp of imports) {
13
+ const moduleName = imp.getModuleSpecifierValue();
14
+ if (moduleName !== "@lom-api" && !moduleName.startsWith("@lom-api/")) {
15
+ continue;
16
+ }
17
+ for (const namedImport of imp.getNamedImports()) {
18
+ const importedName = namedImport.getName();
19
+ if (!importedName.endsWith("Schema"))
20
+ continue;
21
+ const localName = namedImport.getAliasNode()?.getText() || importedName;
22
+ if (!knownSchemas.has(importedName)) {
23
+ const suggestion = (0, fuzzy_1.findBestMatch)(importedName, contract.schemas);
24
+ findings.push({
25
+ id: "SCHEMA_NOT_FOUND",
26
+ category: suggestion ? "RENAMED_SYMBOL" : "MISSING_EXPORT",
27
+ severity: "ERROR",
28
+ message: `Schema "${importedName}" was not found in the API.${suggestion ? ` Did you mean "${suggestion}"?` : ""}`,
29
+ file: file.getFilePath(),
30
+ line: namedImport.getStartLineNumber(),
31
+ context: { suggestion },
32
+ });
33
+ continue;
34
+ }
35
+ const identifiers = file
36
+ .getDescendantsOfKind(ts_morph_1.SyntaxKind.Identifier)
37
+ .filter((id) => id.getText() === localName);
38
+ const usedOutsideImport = identifiers.some((id) => id.getFirstAncestorByKind(ts_morph_1.SyntaxKind.ImportDeclaration) == null);
39
+ if (usedOutsideImport) {
40
+ stats.usedSchemas.add(importedName);
41
+ }
42
+ }
43
+ }
44
+ }
45
+ return findings;
46
+ }
47
+ }
48
+ exports.SchemaRule = SchemaRule;
@@ -0,0 +1,7 @@
1
+ import type { ProjectContext } from "../core/ProjectContext";
2
+ import type { Contract, Finding, Rule, Stats } from "../types";
3
+ export declare class ServiceRule implements Rule {
4
+ check(context: ProjectContext, contract: Contract, stats: Stats): Promise<Finding[]>;
5
+ private getExpectedParameterType;
6
+ }
7
+ //# sourceMappingURL=ServiceRule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ServiceRule.d.ts","sourceRoot":"","sources":["../../../../src/cli/analyzeUsage/rules/ServiceRule.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAG/D,qBAAa,WAAY,YAAW,IAAI;IAChC,KAAK,CACT,OAAO,EAAE,cAAc,EACvB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,OAAO,EAAE,CAAC;IA0FrB,OAAO,CAAC,wBAAwB;CAiBjC"}
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ServiceRule = void 0;
4
+ const ts_morph_1 = require("ts-morph");
5
+ const fuzzy_1 = require("../utils/fuzzy");
6
+ class ServiceRule {
7
+ async check(context, contract, stats) {
8
+ const findings = [];
9
+ const checker = context.getTypeChecker();
10
+ for (const file of context.getConsumerSourceFiles()) {
11
+ const calls = file.getDescendantsOfKind(ts_morph_1.SyntaxKind.CallExpression);
12
+ for (const call of calls) {
13
+ const expression = call.getExpression();
14
+ if (!ts_morph_1.Node.isPropertyAccessExpression(expression))
15
+ continue;
16
+ const serviceAccess = expression.getExpression();
17
+ if (!ts_morph_1.Node.isPropertyAccessExpression(serviceAccess))
18
+ continue;
19
+ const serviceName = serviceAccess.getName();
20
+ const methodName = expression.getName();
21
+ if (!contract.services[serviceName])
22
+ continue;
23
+ stats.usedMethods.add(`${serviceName}.${methodName}`);
24
+ const methodContract = contract.services[serviceName].find((m) => m.name === methodName);
25
+ if (!methodContract) {
26
+ const suggestion = (0, fuzzy_1.findBestMatch)(methodName, contract.services[serviceName].map((m) => m.name));
27
+ findings.push({
28
+ id: "SERVICE_METHOD_NOT_FOUND",
29
+ category: suggestion ? "RENAMED_SYMBOL" : "MISSING_EXPORT",
30
+ severity: "ERROR",
31
+ message: `Method "${serviceName}.${methodName}" was not found in the generated API.${suggestion ? ` Did you mean "${serviceName}.${suggestion}"?` : ""}`,
32
+ file: file.getFilePath(),
33
+ line: call.getStartLineNumber(),
34
+ context: { suggestion },
35
+ });
36
+ continue;
37
+ }
38
+ const args = call.getArguments();
39
+ const serviceDecl = contract.sourceFile
40
+ .getExportedDeclarations()
41
+ .get(serviceName)
42
+ ?.find((d) => ts_morph_1.Node.isClassDeclaration(d));
43
+ const methodDecl = serviceDecl && ts_morph_1.Node.isClassDeclaration(serviceDecl)
44
+ ? serviceDecl.getMethod(methodName)
45
+ : undefined;
46
+ const requiredParams = methodDecl
47
+ ? methodDecl.getParameters().filter((p) => !p.isOptional())
48
+ : methodContract.params.filter((p) => !p.isOptional);
49
+ if (args.length < requiredParams.length) {
50
+ findings.push({
51
+ id: "SERVICE_ARGUMENTS_COUNT_MISMATCH",
52
+ category: "TYPE_MISMATCH",
53
+ severity: "ERROR",
54
+ message: `Method ${serviceName}.${methodName} expects at least ${requiredParams.length} arguments, but got ${args.length}.`,
55
+ file: file.getFilePath(),
56
+ line: call.getStartLineNumber(),
57
+ });
58
+ continue;
59
+ }
60
+ for (let i = 0; i < Math.min(args.length, methodContract.params.length); i++) {
61
+ const expectedType = this.getExpectedParameterType(contract, serviceName, methodName, i);
62
+ if (!expectedType)
63
+ continue;
64
+ const providedType = checker.getTypeAtLocation(args[i]);
65
+ if (!providedType.isAssignableTo(expectedType)) {
66
+ findings.push({
67
+ id: "SERVICE_ARGUMENT_TYPE_MISMATCH",
68
+ category: "TYPE_MISMATCH",
69
+ severity: "ERROR",
70
+ message: `Argument #${i + 1} type mismatch in ${serviceName}.${methodName}. Expected ${expectedType.getText()}, got ${providedType.getText()}.`,
71
+ file: file.getFilePath(),
72
+ line: args[i].getStartLineNumber(),
73
+ });
74
+ }
75
+ }
76
+ }
77
+ }
78
+ return findings;
79
+ }
80
+ getExpectedParameterType(contract, serviceName, methodName, paramIndex) {
81
+ const exportedDecl = contract.sourceFile
82
+ .getExportedDeclarations()
83
+ .get(serviceName)
84
+ ?.find((d) => ts_morph_1.Node.isClassDeclaration(d));
85
+ const method = exportedDecl && ts_morph_1.Node.isClassDeclaration(exportedDecl)
86
+ ? exportedDecl.getMethod(methodName)
87
+ : undefined;
88
+ const param = method?.getParameters()[paramIndex];
89
+ return param?.getType();
90
+ }
91
+ }
92
+ exports.ServiceRule = ServiceRule;
@@ -0,0 +1,52 @@
1
+ import type { SourceFile } from "ts-morph";
2
+ import type { ProjectContext } from "./core/ProjectContext";
3
+ export interface MethodMetadata {
4
+ name: string;
5
+ params: {
6
+ name: string;
7
+ type: string;
8
+ isOptional: boolean;
9
+ }[];
10
+ returnType: string;
11
+ }
12
+ export interface Contract {
13
+ services: Record<string, MethodMetadata[]>;
14
+ schemas: string[];
15
+ models: string[];
16
+ sourceFile: SourceFile;
17
+ }
18
+ export interface Finding {
19
+ id: string;
20
+ severity: "ERROR" | "WARNING";
21
+ category: "INVALID_IMPORT" | "MISSING_EXPORT" | "RENAMED_SYMBOL" | "TYPE_MISMATCH" | "UNUSED" | "CONFIG" | "USAGE";
22
+ message: string;
23
+ file: string;
24
+ line: number;
25
+ context?: any;
26
+ }
27
+ export interface Stats {
28
+ usedMethods: Set<string>;
29
+ usedSchemas: Set<string>;
30
+ usedModels: Set<string>;
31
+ }
32
+ export interface CoverageReport {
33
+ methods: {
34
+ total: number;
35
+ used: number;
36
+ percent: string;
37
+ };
38
+ schemas: {
39
+ total: number;
40
+ used: number;
41
+ percent: string;
42
+ };
43
+ models: {
44
+ total: number;
45
+ used: number;
46
+ percent: string;
47
+ };
48
+ }
49
+ export interface Rule {
50
+ check(context: ProjectContext, contract: Contract, stats: Stats): Promise<Finding[]>;
51
+ }
52
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cli/analyzeUsage/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAC9D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;IAC3C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,QAAQ,EACJ,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,GAChB,eAAe,GACf,QAAQ,GACR,QAAQ,GACR,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,GAAG,CAAC;CACf;AAED,MAAM,WAAW,KAAK;IACpB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1D,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1D,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1D;AAED,MAAM,WAAW,IAAI;IACjB,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;CACxF"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Ищет наиболее подходящую замену из списка доступных опций.
3
+ */
4
+ export declare function findBestMatch(target: string, options: string[], threshold?: number): string | null;
5
+ //# sourceMappingURL=fuzzy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzy.d.ts","sourceRoot":"","sources":["../../../../src/cli/analyzeUsage/utils/fuzzy.ts"],"names":[],"mappings":"AAwBA;;GAEG;AACH,wBAAgB,aAAa,CACzB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,SAAI,GACd,MAAM,GAAG,IAAI,CAaf"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findBestMatch = findBestMatch;
4
+ /**
5
+ * Вычисляет расстояние Левенштейна между двумя строками.
6
+ */
7
+ function getLevenshteinDistance(a, b) {
8
+ const matrix = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
9
+ for (let i = 0; i <= a.length; i++)
10
+ matrix[i][0] = i;
11
+ for (let j = 0; j <= b.length; j++)
12
+ matrix[0][j] = j;
13
+ for (let i = 1; i <= a.length; i++) {
14
+ for (let j = 1; j <= b.length; j++) {
15
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
16
+ matrix[i][j] = Math.min(matrix[i - 1][j] + 1, // удаление
17
+ matrix[i][j - 1] + 1, // вставка
18
+ matrix[i - 1][j - 1] + cost // замена
19
+ );
20
+ }
21
+ }
22
+ return matrix[a.length][b.length];
23
+ }
24
+ /**
25
+ * Ищет наиболее подходящую замену из списка доступных опций.
26
+ */
27
+ function findBestMatch(target, options, threshold = 3) {
28
+ let bestMatch = null;
29
+ let minDistance = Infinity;
30
+ for (const option of options) {
31
+ const distance = getLevenshteinDistance(target, option);
32
+ if (distance < minDistance && distance <= threshold) {
33
+ minDistance = distance;
34
+ bestMatch = option;
35
+ }
36
+ }
37
+ return bestMatch;
38
+ }
@@ -0,0 +1,16 @@
1
+ import type { CoverageReport, Finding, Stats } from "../types";
2
+ export declare class Reporter {
3
+ /**
4
+ * Выводит сводную таблицу и результаты в консоль
5
+ */
6
+ static renderConsole(findings: Finding[], coverage: CoverageReport): void;
7
+ /**
8
+ * Сохраняет отчет в формате JSON для CI/CD инструментов
9
+ */
10
+ static saveJsonReport(filePath: string, findings: Finding[], coverage: CoverageReport): void;
11
+ /**
12
+ * Вычисляет процент покрытия на основе статистики
13
+ */
14
+ static calculateCoverage(stats: Stats, contract: any): CoverageReport;
15
+ }
16
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../../src/cli/analyzeUsage/utils/report.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAC,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAE9D,qBAAa,QAAQ;IACnB;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI;IA8BzE;;OAEG;IACH,MAAM,CAAC,cAAc,CACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,OAAO,EAAE,EACnB,QAAQ,EAAE,cAAc,GACvB,IAAI;IAwBP;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,GAAG,cAAc;CA0BtE"}
@@ -0,0 +1,85 @@
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
+ exports.Reporter = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ class Reporter {
10
+ /**
11
+ * Выводит сводную таблицу и результаты в консоль
12
+ */
13
+ static renderConsole(findings, coverage) {
14
+ console.log("\n📊 API Coverage:");
15
+ console.log(` Methods: ${coverage.methods.used}/${coverage.methods.total} (${coverage.methods.percent})`);
16
+ console.log(` Schemas: ${coverage.schemas.used}/${coverage.schemas.total} (${coverage.schemas.percent})`);
17
+ console.log(` Models: ${coverage.models.used}/${coverage.models.total} (${coverage.models.percent})`);
18
+ if (findings.length === 0) {
19
+ console.log("\n✅ No mismatches found. Project is in sync.");
20
+ return;
21
+ }
22
+ console.log("\n⚠️ Findings:");
23
+ // Форматируем данные для console.table
24
+ const tableData = findings.map((f) => ({
25
+ Status: f.severity === "ERROR" ? "🔴 ERROR" : "🟡 WARN",
26
+ Category: f.category,
27
+ Location: `${path_1.default.basename(f.file)}:${f.line}`,
28
+ Message: f.message,
29
+ }));
30
+ console.table(tableData);
31
+ }
32
+ /**
33
+ * Сохраняет отчет в формате JSON для CI/CD инструментов
34
+ */
35
+ static saveJsonReport(filePath, findings, coverage) {
36
+ const report = {
37
+ timestamp: new Date().toISOString(),
38
+ summary: {
39
+ totalIssues: findings.length,
40
+ errors: findings.filter((f) => f.severity === "ERROR").length,
41
+ warnings: findings.filter((f) => f.severity === "WARNING").length,
42
+ },
43
+ categories: findings.reduce((acc, finding) => {
44
+ acc[finding.category] = (acc[finding.category] || 0) + 1;
45
+ return acc;
46
+ }, {}),
47
+ coverage,
48
+ findings,
49
+ };
50
+ try {
51
+ fs_1.default.writeFileSync(filePath, JSON.stringify(report, null, 2));
52
+ console.log(`\n💾 Report saved: ${path_1.default.resolve(filePath)}`);
53
+ }
54
+ catch (error) {
55
+ console.error(`\n❌ Failed to save JSON report: ${error.message}`);
56
+ }
57
+ }
58
+ /**
59
+ * Вычисляет процент покрытия на основе статистики
60
+ */
61
+ static calculateCoverage(stats, contract) {
62
+ const totalMethods = Object.values(contract.services).flat().length;
63
+ const totalSchemas = contract.schemas.length;
64
+ const totalModels = contract.models.length;
65
+ const getPercent = (used, total) => total > 0 ? ((used / total) * 100).toFixed(2) + "%" : "0%";
66
+ return {
67
+ methods: {
68
+ total: totalMethods,
69
+ used: stats.usedMethods.size,
70
+ percent: getPercent(stats.usedMethods.size, totalMethods),
71
+ },
72
+ schemas: {
73
+ total: totalSchemas,
74
+ used: stats.usedSchemas.size,
75
+ percent: getPercent(stats.usedSchemas.size, totalSchemas),
76
+ },
77
+ models: {
78
+ total: totalModels,
79
+ used: stats.usedModels.size,
80
+ percent: getPercent(stats.usedModels.size, totalModels),
81
+ },
82
+ };
83
+ }
84
+ }
85
+ exports.Reporter = Reporter;
@@ -11,52 +11,42 @@ const node_test_1 = require("node:test");
11
11
  const Consts_1 = require("../../../common/Consts");
12
12
  const HttpClient_enum_1 = require("../../../core/types/enums/HttpClient.enum");
13
13
  const checkConfig_1 = require("../checkConfig");
14
- class ProcessExitError extends Error {
15
- exitCode;
16
- constructor(exitCode) {
17
- super(`process.exit(${exitCode})`);
18
- this.exitCode = exitCode;
19
- this.name = 'ProcessExitError';
20
- }
21
- }
22
14
  /** Config without schema-default fields so checkConfig does not open enquirer. */
23
15
  const flatConfig = {
24
16
  input: './test/spec/v3.json',
25
17
  output: './test/generated',
26
18
  httpClient: HttpClient_enum_1.HttpClient.AXIOS,
27
19
  };
28
- const mockProcessExit = () => node_test_1.mock.method(process, 'exit', (code) => {
29
- throw new ProcessExitError(Number(code ?? 0));
30
- });
31
20
  async function writeConfig(dir, content) {
32
21
  const configPath = (0, node_path_1.join)(dir, 'openapi.config.json');
33
22
  await (0, promises_1.writeFile)(configPath, JSON.stringify(content, null, 2), 'utf8');
34
23
  return configPath;
35
24
  }
36
25
  (0, node_test_1.describe)('@unit: checkConfig', () => {
37
- (0, node_test_1.test)('exits when options fail schema validation', async () => {
38
- const exitMock = mockProcessExit();
26
+ (0, node_test_1.test)('returns failure when options fail schema validation', async () => {
39
27
  const shutdownMock = node_test_1.mock.method(Consts_1.APP_LOGGER, 'shutdownLoggerAsync', async () => undefined);
40
28
  const errorMock = node_test_1.mock.method(Consts_1.APP_LOGGER, 'error', () => undefined);
41
- await node_assert_1.default.rejects(() => (0, checkConfig_1.checkConfig)({ openapiConfig: 123 }), ProcessExitError);
42
- exitMock.mock.restore();
29
+ const result = await (0, checkConfig_1.checkConfig)({ openapiConfig: 123 });
30
+ node_assert_1.default.strictEqual(result.success, false);
31
+ node_assert_1.default.ok(result.error);
43
32
  shutdownMock.mock.restore();
44
33
  errorMock.mock.restore();
45
34
  });
46
- (0, node_test_1.test)('exits when config file is missing', async () => {
35
+ (0, node_test_1.test)('returns failure when config file is missing', async () => {
47
36
  const dir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'check-config-'));
48
37
  const configPath = (0, node_path_1.join)(dir, 'missing.json');
49
- const exitMock = mockProcessExit();
50
38
  const shutdownMock = node_test_1.mock.method(Consts_1.APP_LOGGER, 'shutdownLoggerAsync', async () => undefined);
51
- await node_assert_1.default.rejects(() => (0, checkConfig_1.checkConfig)({ openapiConfig: configPath }), ProcessExitError);
52
- exitMock.mock.restore();
39
+ const result = await (0, checkConfig_1.checkConfig)({ openapiConfig: configPath });
40
+ node_assert_1.default.strictEqual(result.success, false);
41
+ node_assert_1.default.ok(result.error);
53
42
  shutdownMock.mock.restore();
54
43
  });
55
44
  (0, node_test_1.test)('reports valid config without prompting when up to date', async () => {
56
45
  const dir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'check-config-'));
57
46
  const configPath = await writeConfig(dir, flatConfig);
58
47
  const infoMock = node_test_1.mock.method(Consts_1.APP_LOGGER, 'info', () => undefined);
59
- await (0, checkConfig_1.checkConfig)({ openapiConfig: configPath });
48
+ const result = await (0, checkConfig_1.checkConfig)({ openapiConfig: configPath });
49
+ node_assert_1.default.strictEqual(result.success, true);
60
50
  node_assert_1.default.strictEqual(infoMock.mock.callCount(), 1);
61
51
  infoMock.mock.restore();
62
52
  });
@@ -11,51 +11,41 @@ const node_test_1 = require("node:test");
11
11
  const Consts_1 = require("../../../common/Consts");
12
12
  const HttpClient_enum_1 = require("../../../core/types/enums/HttpClient.enum");
13
13
  const updateConfig_1 = require("../updateConfig");
14
- class ProcessExitError extends Error {
15
- exitCode;
16
- constructor(exitCode) {
17
- super(`process.exit(${exitCode})`);
18
- this.exitCode = exitCode;
19
- this.name = 'ProcessExitError';
20
- }
21
- }
22
14
  const flatConfig = {
23
15
  input: './test/spec/v3.json',
24
16
  output: './test/generated',
25
17
  httpClient: HttpClient_enum_1.HttpClient.FETCH,
26
18
  };
27
- const mockProcessExit = () => node_test_1.mock.method(process, 'exit', (code) => {
28
- throw new ProcessExitError(Number(code ?? 0));
29
- });
30
19
  async function writeConfig(dir, content) {
31
20
  const configPath = (0, node_path_1.join)(dir, 'openapi.config.json');
32
21
  await (0, promises_1.writeFile)(configPath, JSON.stringify(content, null, 2), 'utf8');
33
22
  return configPath;
34
23
  }
35
24
  (0, node_test_1.describe)('@unit: updateConfig', () => {
36
- (0, node_test_1.test)('exits when options fail schema validation', async () => {
37
- const exitMock = mockProcessExit();
25
+ (0, node_test_1.test)('returns failure when options fail schema validation', async () => {
38
26
  const shutdownMock = node_test_1.mock.method(Consts_1.APP_LOGGER, 'shutdownLoggerAsync', async () => undefined);
39
27
  const errorMock = node_test_1.mock.method(Consts_1.APP_LOGGER, 'error', () => undefined);
40
- await node_assert_1.default.rejects(() => (0, updateConfig_1.updateConfig)({ openapiConfig: 123 }), ProcessExitError);
41
- exitMock.mock.restore();
28
+ const result = await (0, updateConfig_1.updateConfig)({ openapiConfig: 123 });
29
+ node_assert_1.default.strictEqual(result.success, false);
30
+ node_assert_1.default.ok(result.error);
42
31
  shutdownMock.mock.restore();
43
32
  errorMock.mock.restore();
44
33
  });
45
- (0, node_test_1.test)('exits when config file is missing', async () => {
34
+ (0, node_test_1.test)('returns failure when config file is missing', async () => {
46
35
  const dir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'update-config-'));
47
36
  const configPath = (0, node_path_1.join)(dir, 'missing.json');
48
- const exitMock = mockProcessExit();
49
37
  const shutdownMock = node_test_1.mock.method(Consts_1.APP_LOGGER, 'shutdownLoggerAsync', async () => undefined);
50
- await node_assert_1.default.rejects(() => (0, updateConfig_1.updateConfig)({ openapiConfig: configPath }), ProcessExitError);
51
- exitMock.mock.restore();
38
+ const result = await (0, updateConfig_1.updateConfig)({ openapiConfig: configPath });
39
+ node_assert_1.default.strictEqual(result.success, false);
40
+ node_assert_1.default.ok(result.error);
52
41
  shutdownMock.mock.restore();
53
42
  });
54
43
  (0, node_test_1.test)('logs up to date when config is current', async () => {
55
44
  const dir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'update-config-'));
56
45
  const configPath = await writeConfig(dir, flatConfig);
57
46
  const infoMock = node_test_1.mock.method(Consts_1.APP_LOGGER, 'info', () => undefined);
58
- await (0, updateConfig_1.updateConfig)({ openapiConfig: configPath });
47
+ const result = await (0, updateConfig_1.updateConfig)({ openapiConfig: configPath });
48
+ node_assert_1.default.strictEqual(result.success, true);
59
49
  node_assert_1.default.strictEqual(infoMock.mock.callCount(), 1);
60
50
  infoMock.mock.restore();
61
51
  });
@@ -1,4 +1,5 @@
1
1
  import { OptionValues } from 'commander';
2
+ import { CLICommandResult } from '../types';
2
3
  /**
3
4
  * Проверяет конфигурационный файл на корректность и актуальность.
4
5
  * Если обнаружены проблемы, предлагает действия для их исправления.
@@ -9,5 +10,5 @@ import { OptionValues } from 'commander';
9
10
  * @example
10
11
  * await checkConfig('./openapi-config.json');
11
12
  */
12
- export declare function checkConfig(options: OptionValues): Promise<void>;
13
+ export declare function checkConfig(options: OptionValues): Promise<CLICommandResult>;
13
14
  //# sourceMappingURL=checkConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"checkConfig.d.ts","sourceRoot":"","sources":["../../../src/cli/checkAndUpdateConfig/checkConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAWzC;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDtE"}
1
+ {"version":3,"file":"checkConfig.d.ts","sourceRoot":"","sources":["../../../src/cli/checkAndUpdateConfig/checkConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAOzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAK5C;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAoDlF"}