@unispechq/unispec-core 0.3.0 → 0.3.2

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 (306) hide show
  1. package/dist/cjs/diff/annotators.js +36 -9
  2. package/dist/cjs/src/cache/cache-factory.js +72 -0
  3. package/dist/cjs/src/cache/cache-manager.js +128 -0
  4. package/dist/cjs/src/cache/constants.js +25 -0
  5. package/dist/cjs/src/cache/hash-utils.js +19 -0
  6. package/dist/cjs/src/cache/hashing.js +230 -0
  7. package/dist/cjs/src/cache/index.js +24 -0
  8. package/dist/cjs/src/cache/lru-cache.js +144 -0
  9. package/dist/cjs/src/cache/types.js +5 -0
  10. package/dist/cjs/src/diff/annotators.js +160 -0
  11. package/dist/cjs/src/diff/change-reports.js +369 -0
  12. package/dist/cjs/src/diff/core.js +158 -0
  13. package/dist/cjs/src/diff/enhanced-diff.js +65 -0
  14. package/dist/cjs/src/diff/impact-strategies-refactored.js +230 -0
  15. package/dist/cjs/src/diff/impact-strategies.js +219 -0
  16. package/dist/cjs/src/diff/index.js +27 -0
  17. package/dist/cjs/src/diff/metrics-calculator.js +69 -0
  18. package/dist/cjs/src/diff/risk-calculator.js +58 -0
  19. package/dist/cjs/src/diff/suggestion-generator.js +78 -0
  20. package/dist/cjs/src/diff/types.js +11 -0
  21. package/dist/cjs/src/errors/base-error.js +33 -0
  22. package/dist/cjs/src/errors/config-error.js +11 -0
  23. package/dist/cjs/src/errors/error-factory.js +48 -0
  24. package/dist/cjs/src/errors/index.js +19 -0
  25. package/dist/cjs/src/errors/loader-error.js +11 -0
  26. package/dist/cjs/src/errors/reference-error.js +11 -0
  27. package/dist/cjs/src/errors/schema-error.js +11 -0
  28. package/dist/cjs/src/errors/security-error.js +11 -0
  29. package/dist/cjs/src/errors/semantic-error.js +11 -0
  30. package/dist/cjs/src/generated-schemas.js +2100 -0
  31. package/dist/cjs/src/index.js +59 -0
  32. package/dist/cjs/src/loader/index.js +13 -0
  33. package/dist/cjs/src/loader/security-validator.js +53 -0
  34. package/dist/cjs/src/loader/types.js +11 -0
  35. package/dist/cjs/src/loader/unispec-loader.js +84 -0
  36. package/dist/cjs/src/loader/yaml-loader.js +76 -0
  37. package/dist/cjs/src/normalizer/core.js +37 -0
  38. package/dist/cjs/src/normalizer/graphql-normalizer.js +67 -0
  39. package/dist/cjs/src/normalizer/index.js +7 -0
  40. package/dist/cjs/src/normalizer/rest-normalizer.js +51 -0
  41. package/dist/cjs/src/normalizer/types.js +2 -0
  42. package/dist/cjs/src/normalizer/utils.js +49 -0
  43. package/dist/cjs/src/normalizer/websocket-normalizer.js +81 -0
  44. package/dist/cjs/src/optimizer/core.js +140 -0
  45. package/dist/cjs/src/optimizer/index.js +17 -0
  46. package/dist/cjs/src/optimizer/optimization-functions.js +185 -0
  47. package/dist/cjs/src/optimizer/types.js +2 -0
  48. package/dist/cjs/src/optimizer/utils.js +32 -0
  49. package/dist/cjs/src/schemas/dedupe.js +113 -0
  50. package/dist/cjs/src/schemas/index.js +14 -0
  51. package/dist/cjs/src/schemas/resolver.js +42 -0
  52. package/dist/cjs/src/schemas/utils.js +53 -0
  53. package/dist/cjs/src/types/index.js +2 -0
  54. package/dist/cjs/src/validator/ajv-validator.js +82 -0
  55. package/dist/cjs/src/validator/config-validator-main.js +34 -0
  56. package/dist/cjs/src/validator/config-validator.js +17 -0
  57. package/dist/cjs/src/validator/index.js +23 -0
  58. package/dist/cjs/src/validator/object-traversal.js +112 -0
  59. package/dist/cjs/src/validator/reference-validator.js +233 -0
  60. package/dist/cjs/src/validator/schema-references.js +116 -0
  61. package/dist/cjs/src/validator/semantic-validator.js +328 -0
  62. package/dist/cjs/src/validator/tests-validator.js +16 -0
  63. package/dist/cjs/src/validator/types.js +2 -0
  64. package/dist/cjs/src/validator/unispec-validator.js +80 -0
  65. package/dist/cjs/src/validator/validator-factory.js +77 -0
  66. package/dist/cjs/src/versions.js +147 -0
  67. package/dist/cjs/tests/cache/cache.test.js +274 -0
  68. package/dist/cjs/tests/cache/utils.js +32 -0
  69. package/dist/cjs/tests/concurrency-normalizer-optimizer.test.js +1 -0
  70. package/dist/cjs/tests/diff/diff-annotators.test.js +280 -0
  71. package/dist/cjs/tests/diff/diff-comprehensive.test.js +262 -0
  72. package/dist/cjs/tests/diff/diff-extended.test.js +235 -0
  73. package/dist/cjs/tests/diff/diff.test.js +189 -0
  74. package/dist/cjs/tests/diff/utils.js +8 -0
  75. package/dist/cjs/tests/errors/errors-integration.test.js +173 -0
  76. package/dist/cjs/tests/errors/errors.test.js +280 -0
  77. package/dist/cjs/tests/errors/utils.js +7 -0
  78. package/dist/cjs/tests/loader/integration.test.js +216 -0
  79. package/dist/cjs/tests/loader/loader.test.js +341 -0
  80. package/dist/cjs/tests/normalizer/normalizer-comprehensive.test.js +648 -0
  81. package/dist/cjs/tests/normalizer/normalizer-invalid.test.js +258 -0
  82. package/dist/cjs/tests/normalizer/normalizer-valid.test.js +238 -0
  83. package/dist/cjs/tests/normalizer/utils.js +47 -0
  84. package/dist/cjs/tests/optimizer/compress-references.test.js +304 -0
  85. package/dist/cjs/tests/optimizer/deduplication.test.js +132 -0
  86. package/dist/cjs/tests/optimizer/integration.test.js +131 -0
  87. package/dist/cjs/tests/optimizer/optimization-report.test.js +222 -0
  88. package/dist/cjs/tests/optimizer/optimize-document.test.js +187 -0
  89. package/dist/cjs/tests/optimizer/orphaned-schemas.test.js +194 -0
  90. package/dist/cjs/tests/optimizer/sort-schemas.test.js +131 -0
  91. package/dist/cjs/tests/optimizer/utils.js +209 -0
  92. package/dist/cjs/tests/schemas/schemas-edge-cases.test.js +223 -0
  93. package/dist/cjs/tests/schemas/schemas.test.js +400 -0
  94. package/dist/cjs/tests/schemas/utils.js +7 -0
  95. package/dist/cjs/tests/utils.js +131 -0
  96. package/dist/cjs/tests/validator/config-validator.test.js +78 -0
  97. package/dist/cjs/tests/validator/debug-config.js +1 -0
  98. package/dist/cjs/tests/validator/debug-missing-service.js +1 -0
  99. package/dist/cjs/tests/validator/debug-other-configs.js +1 -0
  100. package/dist/cjs/tests/validator/debug-references.js +1 -0
  101. package/dist/cjs/tests/validator/unispec-validator.test.js +103 -0
  102. package/dist/cjs/tests/validator/utils.js +25 -0
  103. package/dist/diff/annotators.js +36 -9
  104. package/dist/src/cache/cache-factory.d.ts +31 -0
  105. package/dist/src/cache/cache-factory.js +65 -0
  106. package/dist/src/cache/cache-manager.d.ts +62 -0
  107. package/dist/src/cache/cache-manager.js +124 -0
  108. package/dist/src/cache/constants.d.ts +21 -0
  109. package/dist/src/cache/constants.js +22 -0
  110. package/dist/src/cache/hash-utils.d.ts +11 -0
  111. package/dist/src/cache/hash-utils.js +15 -0
  112. package/dist/src/cache/hashing.d.ts +28 -0
  113. package/dist/src/cache/hashing.js +193 -0
  114. package/dist/src/cache/index.d.ts +6 -0
  115. package/dist/src/cache/index.js +10 -0
  116. package/dist/src/cache/lru-cache.d.ts +44 -0
  117. package/dist/src/cache/lru-cache.js +140 -0
  118. package/dist/src/cache/types.d.ts +24 -0
  119. package/dist/src/cache/types.js +4 -0
  120. package/dist/src/diff/annotators.d.ts +4 -0
  121. package/dist/src/diff/annotators.js +155 -0
  122. package/dist/src/diff/change-reports.d.ts +37 -0
  123. package/dist/src/diff/change-reports.js +366 -0
  124. package/dist/src/diff/core.d.ts +26 -0
  125. package/dist/src/diff/core.js +155 -0
  126. package/dist/src/diff/enhanced-diff.d.ts +51 -0
  127. package/dist/src/diff/enhanced-diff.js +62 -0
  128. package/dist/src/diff/impact-strategies-refactored.d.ts +69 -0
  129. package/dist/src/diff/impact-strategies-refactored.js +223 -0
  130. package/dist/src/diff/impact-strategies.d.ts +41 -0
  131. package/dist/src/diff/impact-strategies.js +212 -0
  132. package/dist/src/diff/index.d.ts +8 -0
  133. package/dist/src/diff/index.js +11 -0
  134. package/dist/src/diff/metrics-calculator.d.ts +23 -0
  135. package/dist/src/diff/metrics-calculator.js +65 -0
  136. package/dist/src/diff/risk-calculator.d.ts +23 -0
  137. package/dist/src/diff/risk-calculator.js +55 -0
  138. package/dist/src/diff/suggestion-generator.d.ts +18 -0
  139. package/dist/src/diff/suggestion-generator.js +74 -0
  140. package/dist/src/diff/types.d.ts +24 -0
  141. package/dist/src/diff/types.js +8 -0
  142. package/dist/src/errors/base-error.d.ts +20 -0
  143. package/dist/src/errors/base-error.js +29 -0
  144. package/dist/src/errors/config-error.d.ts +4 -0
  145. package/dist/src/errors/config-error.js +7 -0
  146. package/dist/src/errors/error-factory.d.ts +22 -0
  147. package/dist/src/errors/error-factory.js +45 -0
  148. package/dist/src/errors/index.d.ts +8 -0
  149. package/dist/src/errors/index.js +8 -0
  150. package/dist/src/errors/loader-error.d.ts +4 -0
  151. package/dist/src/errors/loader-error.js +7 -0
  152. package/dist/src/errors/reference-error.d.ts +4 -0
  153. package/dist/src/errors/reference-error.js +7 -0
  154. package/dist/src/errors/schema-error.d.ts +4 -0
  155. package/dist/src/errors/schema-error.js +7 -0
  156. package/dist/src/errors/security-error.d.ts +4 -0
  157. package/dist/src/errors/security-error.js +7 -0
  158. package/dist/src/errors/semantic-error.d.ts +4 -0
  159. package/dist/src/errors/semantic-error.js +7 -0
  160. package/dist/src/generated-schemas.d.ts +2073 -0
  161. package/dist/src/generated-schemas.js +2097 -0
  162. package/dist/src/index.d.ts +13 -0
  163. package/dist/src/index.js +43 -0
  164. package/dist/src/loader/index.d.ts +5 -0
  165. package/dist/src/loader/index.js +5 -0
  166. package/dist/src/loader/security-validator.d.ts +5 -0
  167. package/dist/src/loader/security-validator.js +50 -0
  168. package/dist/src/loader/types.d.ts +30 -0
  169. package/dist/src/loader/types.js +8 -0
  170. package/dist/src/loader/unispec-loader.d.ts +10 -0
  171. package/dist/src/loader/unispec-loader.js +81 -0
  172. package/dist/src/loader/yaml-loader.d.ts +10 -0
  173. package/dist/src/loader/yaml-loader.js +39 -0
  174. package/dist/src/normalizer/core.d.ts +24 -0
  175. package/dist/src/normalizer/core.js +34 -0
  176. package/dist/src/normalizer/graphql-normalizer.d.ts +8 -0
  177. package/dist/src/normalizer/graphql-normalizer.js +64 -0
  178. package/dist/src/normalizer/index.d.ts +2 -0
  179. package/dist/src/normalizer/index.js +3 -0
  180. package/dist/src/normalizer/rest-normalizer.d.ts +8 -0
  181. package/dist/src/normalizer/rest-normalizer.js +48 -0
  182. package/dist/src/normalizer/types.d.ts +7 -0
  183. package/dist/src/normalizer/types.js +1 -0
  184. package/dist/src/normalizer/utils.d.ts +17 -0
  185. package/dist/src/normalizer/utils.js +45 -0
  186. package/dist/src/normalizer/websocket-normalizer.d.ts +8 -0
  187. package/dist/src/normalizer/websocket-normalizer.js +78 -0
  188. package/dist/src/optimizer/core.d.ts +17 -0
  189. package/dist/src/optimizer/core.js +136 -0
  190. package/dist/src/optimizer/index.d.ts +4 -0
  191. package/dist/src/optimizer/index.js +7 -0
  192. package/dist/src/optimizer/optimization-functions.d.ts +32 -0
  193. package/dist/src/optimizer/optimization-functions.js +179 -0
  194. package/dist/src/optimizer/types.d.ts +28 -0
  195. package/dist/src/optimizer/types.js +1 -0
  196. package/dist/src/optimizer/utils.d.ts +7 -0
  197. package/dist/src/optimizer/utils.js +29 -0
  198. package/dist/src/schemas/dedupe.d.ts +9 -0
  199. package/dist/src/schemas/dedupe.js +110 -0
  200. package/dist/src/schemas/index.d.ts +3 -0
  201. package/dist/src/schemas/index.js +6 -0
  202. package/dist/src/schemas/resolver.d.ts +19 -0
  203. package/dist/src/schemas/resolver.js +38 -0
  204. package/dist/src/schemas/utils.d.ts +20 -0
  205. package/dist/src/schemas/utils.js +49 -0
  206. package/dist/src/types/index.d.ts +434 -0
  207. package/dist/src/types/index.js +1 -0
  208. package/dist/src/validator/ajv-validator.d.ts +15 -0
  209. package/dist/src/validator/ajv-validator.js +75 -0
  210. package/dist/src/validator/config-validator-main.d.ts +10 -0
  211. package/dist/src/validator/config-validator-main.js +31 -0
  212. package/dist/src/validator/config-validator.d.ts +5 -0
  213. package/dist/src/validator/config-validator.js +14 -0
  214. package/dist/src/validator/index.d.ts +10 -0
  215. package/dist/src/validator/index.js +11 -0
  216. package/dist/src/validator/object-traversal.d.ts +52 -0
  217. package/dist/src/validator/object-traversal.js +104 -0
  218. package/dist/src/validator/reference-validator.d.ts +31 -0
  219. package/dist/src/validator/reference-validator.js +230 -0
  220. package/dist/src/validator/schema-references.d.ts +23 -0
  221. package/dist/src/validator/schema-references.js +111 -0
  222. package/dist/src/validator/semantic-validator.d.ts +26 -0
  223. package/dist/src/validator/semantic-validator.js +325 -0
  224. package/dist/src/validator/tests-validator.d.ts +9 -0
  225. package/dist/src/validator/tests-validator.js +13 -0
  226. package/dist/src/validator/types.d.ts +29 -0
  227. package/dist/src/validator/types.js +1 -0
  228. package/dist/src/validator/unispec-validator.d.ts +15 -0
  229. package/dist/src/validator/unispec-validator.js +77 -0
  230. package/dist/src/validator/validator-factory.d.ts +10 -0
  231. package/dist/src/validator/validator-factory.js +73 -0
  232. package/dist/src/versions.d.ts +10 -0
  233. package/dist/src/versions.js +143 -0
  234. package/dist/tests/cache/cache.test.d.ts +1 -0
  235. package/dist/tests/cache/cache.test.js +269 -0
  236. package/dist/tests/cache/utils.d.ts +4 -0
  237. package/dist/tests/cache/utils.js +24 -0
  238. package/dist/tests/concurrency-normalizer-optimizer.test.d.ts +0 -0
  239. package/dist/tests/concurrency-normalizer-optimizer.test.js +1 -0
  240. package/dist/tests/diff/diff-annotators.test.d.ts +1 -0
  241. package/dist/tests/diff/diff-annotators.test.js +275 -0
  242. package/dist/tests/diff/diff-comprehensive.test.d.ts +1 -0
  243. package/dist/tests/diff/diff-comprehensive.test.js +257 -0
  244. package/dist/tests/diff/diff-extended.test.d.ts +1 -0
  245. package/dist/tests/diff/diff-extended.test.js +230 -0
  246. package/dist/tests/diff/diff.test.d.ts +1 -0
  247. package/dist/tests/diff/diff.test.js +184 -0
  248. package/dist/tests/diff/utils.d.ts +2 -0
  249. package/dist/tests/diff/utils.js +3 -0
  250. package/dist/tests/errors/errors-integration.test.d.ts +1 -0
  251. package/dist/tests/errors/errors-integration.test.js +168 -0
  252. package/dist/tests/errors/errors.test.d.ts +1 -0
  253. package/dist/tests/errors/errors.test.js +275 -0
  254. package/dist/tests/errors/utils.d.ts +2 -0
  255. package/dist/tests/errors/utils.js +3 -0
  256. package/dist/tests/loader/integration.test.d.ts +1 -0
  257. package/dist/tests/loader/integration.test.js +211 -0
  258. package/dist/tests/loader/loader.test.d.ts +1 -0
  259. package/dist/tests/loader/loader.test.js +336 -0
  260. package/dist/tests/normalizer/normalizer-comprehensive.test.d.ts +1 -0
  261. package/dist/tests/normalizer/normalizer-comprehensive.test.js +643 -0
  262. package/dist/tests/normalizer/normalizer-invalid.test.d.ts +1 -0
  263. package/dist/tests/normalizer/normalizer-invalid.test.js +253 -0
  264. package/dist/tests/normalizer/normalizer-valid.test.d.ts +1 -0
  265. package/dist/tests/normalizer/normalizer-valid.test.js +233 -0
  266. package/dist/tests/normalizer/utils.d.ts +18 -0
  267. package/dist/tests/normalizer/utils.js +36 -0
  268. package/dist/tests/optimizer/compress-references.test.d.ts +1 -0
  269. package/dist/tests/optimizer/compress-references.test.js +299 -0
  270. package/dist/tests/optimizer/deduplication.test.d.ts +1 -0
  271. package/dist/tests/optimizer/deduplication.test.js +127 -0
  272. package/dist/tests/optimizer/integration.test.d.ts +1 -0
  273. package/dist/tests/optimizer/integration.test.js +126 -0
  274. package/dist/tests/optimizer/optimization-report.test.d.ts +1 -0
  275. package/dist/tests/optimizer/optimization-report.test.js +217 -0
  276. package/dist/tests/optimizer/optimize-document.test.d.ts +1 -0
  277. package/dist/tests/optimizer/optimize-document.test.js +182 -0
  278. package/dist/tests/optimizer/orphaned-schemas.test.d.ts +1 -0
  279. package/dist/tests/optimizer/orphaned-schemas.test.js +189 -0
  280. package/dist/tests/optimizer/sort-schemas.test.d.ts +1 -0
  281. package/dist/tests/optimizer/sort-schemas.test.js +126 -0
  282. package/dist/tests/optimizer/utils.d.ts +8 -0
  283. package/dist/tests/optimizer/utils.js +199 -0
  284. package/dist/tests/schemas/schemas-edge-cases.test.d.ts +1 -0
  285. package/dist/tests/schemas/schemas-edge-cases.test.js +218 -0
  286. package/dist/tests/schemas/schemas.test.d.ts +1 -0
  287. package/dist/tests/schemas/schemas.test.js +395 -0
  288. package/dist/tests/schemas/utils.d.ts +2 -0
  289. package/dist/tests/schemas/utils.js +3 -0
  290. package/dist/tests/utils.d.ts +10 -0
  291. package/dist/tests/utils.js +118 -0
  292. package/dist/tests/validator/config-validator.test.d.ts +1 -0
  293. package/dist/tests/validator/config-validator.test.js +73 -0
  294. package/dist/tests/validator/debug-config.d.ts +0 -0
  295. package/dist/tests/validator/debug-config.js +1 -0
  296. package/dist/tests/validator/debug-missing-service.d.ts +0 -0
  297. package/dist/tests/validator/debug-missing-service.js +1 -0
  298. package/dist/tests/validator/debug-other-configs.d.ts +0 -0
  299. package/dist/tests/validator/debug-other-configs.js +1 -0
  300. package/dist/tests/validator/debug-references.d.ts +0 -0
  301. package/dist/tests/validator/debug-references.js +1 -0
  302. package/dist/tests/validator/unispec-validator.test.d.ts +1 -0
  303. package/dist/tests/validator/unispec-validator.test.js +98 -0
  304. package/dist/tests/validator/utils.d.ts +6 -0
  305. package/dist/tests/validator/utils.js +20 -0
  306. package/package.json +4 -3
@@ -0,0 +1,299 @@
1
+ import assert from "node:assert";
2
+ import { describe, it } from "node:test";
3
+ import { compressSchemaReferences } from "../../src/optimizer/optimization-functions.js";
4
+ import { createDocumentWithLongReferences, getExamplePath, loadExample, } from "./utils.js";
5
+ describe("compressSchemaReferences", () => {
6
+ it("should compress JSON Pointer references", () => {
7
+ const doc = createDocumentWithLongReferences();
8
+ const compressedCount = compressSchemaReferences(doc);
9
+ assert.strictEqual(compressedCount, 1);
10
+ // Check that reference was compressed
11
+ const route = doc.service?.protocols?.rest?.routes?.[0];
12
+ const schemaRef = route?.responses?.["200"]?.content?.["application/json"]?.schemaRef;
13
+ assert.strictEqual(schemaRef, "TestSchema");
14
+ });
15
+ it("should compress hash references", () => {
16
+ const doc = {
17
+ unispecVersion: "1.0.0",
18
+ service: {
19
+ name: "test",
20
+ schemas: {
21
+ TestSchema: {
22
+ name: "TestSchema",
23
+ description: "Test schema",
24
+ jsonSchema: { type: "string" },
25
+ },
26
+ },
27
+ protocols: {
28
+ rest: {
29
+ routes: [
30
+ {
31
+ name: "testRoute",
32
+ method: "GET",
33
+ path: "/test",
34
+ responses: {
35
+ "200": {
36
+ description: "Success",
37
+ content: {
38
+ "application/json": {
39
+ schemaRef: "#TestSchema", // Hash format
40
+ },
41
+ },
42
+ },
43
+ },
44
+ },
45
+ ],
46
+ },
47
+ },
48
+ },
49
+ };
50
+ const compressedCount = compressSchemaReferences(doc);
51
+ assert.strictEqual(compressedCount, 1);
52
+ const route = doc.service?.protocols?.rest?.routes?.[0];
53
+ const schemaRef = route?.responses?.["200"]?.content?.["application/json"]?.schemaRef;
54
+ assert.strictEqual(schemaRef, "TestSchema");
55
+ });
56
+ it("should compress path references", () => {
57
+ const doc = {
58
+ unispecVersion: "1.0.0",
59
+ service: {
60
+ name: "test",
61
+ schemas: {
62
+ TestSchema: {
63
+ name: "TestSchema",
64
+ description: "Test schema",
65
+ jsonSchema: { type: "string" },
66
+ },
67
+ },
68
+ protocols: {
69
+ rest: {
70
+ routes: [
71
+ {
72
+ name: "testRoute",
73
+ method: "GET",
74
+ path: "/test",
75
+ responses: {
76
+ "200": {
77
+ description: "Success",
78
+ content: {
79
+ "application/json": {
80
+ schemaRef: "path/to/TestSchema", // Path format
81
+ },
82
+ },
83
+ },
84
+ },
85
+ },
86
+ ],
87
+ },
88
+ },
89
+ },
90
+ };
91
+ const compressedCount = compressSchemaReferences(doc);
92
+ assert.strictEqual(compressedCount, 1);
93
+ const route = doc.service?.protocols?.rest?.routes?.[0];
94
+ const schemaRef = route?.responses?.["200"]?.content?.["application/json"]?.schemaRef;
95
+ assert.strictEqual(schemaRef, "TestSchema");
96
+ });
97
+ it("should not compress already simple references", () => {
98
+ const doc = {
99
+ unispecVersion: "1.0.0",
100
+ service: {
101
+ name: "test",
102
+ schemas: {
103
+ TestSchema: {
104
+ name: "TestSchema",
105
+ description: "Test schema",
106
+ jsonSchema: { type: "string" },
107
+ },
108
+ },
109
+ protocols: {
110
+ rest: {
111
+ routes: [
112
+ {
113
+ name: "testRoute",
114
+ method: "GET",
115
+ path: "/test",
116
+ responses: {
117
+ "200": {
118
+ description: "Success",
119
+ content: {
120
+ "application/json": {
121
+ schemaRef: "TestSchema", // Already simple
122
+ },
123
+ },
124
+ },
125
+ },
126
+ },
127
+ ],
128
+ },
129
+ },
130
+ },
131
+ };
132
+ const compressedCount = compressSchemaReferences(doc);
133
+ assert.strictEqual(compressedCount, 0);
134
+ const route = doc.service?.protocols?.rest?.routes?.[0];
135
+ const schemaRef = route?.responses?.["200"]?.content?.["application/json"]?.schemaRef;
136
+ assert.strictEqual(schemaRef, "TestSchema");
137
+ });
138
+ it("should handle multiple references", () => {
139
+ const doc = {
140
+ unispecVersion: "1.0.0",
141
+ service: {
142
+ name: "test",
143
+ schemas: {
144
+ TestSchema: {
145
+ name: "TestSchema",
146
+ description: "Test schema",
147
+ jsonSchema: { type: "string" },
148
+ },
149
+ },
150
+ protocols: {
151
+ rest: {
152
+ routes: [
153
+ {
154
+ name: "testRoute1",
155
+ method: "GET",
156
+ path: "/test1",
157
+ responses: {
158
+ "200": {
159
+ description: "Success",
160
+ content: {
161
+ "application/json": {
162
+ schemaRef: "#/service/schemas/TestSchema",
163
+ },
164
+ },
165
+ },
166
+ },
167
+ },
168
+ {
169
+ name: "testRoute2",
170
+ method: "POST",
171
+ path: "/test2",
172
+ requestBody: {
173
+ content: {
174
+ "application/json": {
175
+ schemaRef: "#TestSchema",
176
+ },
177
+ },
178
+ },
179
+ responses: {
180
+ "201": {
181
+ description: "Created",
182
+ content: {
183
+ "application/json": {
184
+ schemaRef: "path/to/TestSchema",
185
+ },
186
+ },
187
+ },
188
+ },
189
+ },
190
+ ],
191
+ },
192
+ },
193
+ },
194
+ };
195
+ const compressedCount = compressSchemaReferences(doc);
196
+ assert.strictEqual(compressedCount, 3);
197
+ // Check all references were compressed
198
+ const routes = doc.service?.protocols?.rest?.routes || [];
199
+ const ref1 = routes[0]?.responses?.["200"]?.content?.["application/json"]?.schemaRef;
200
+ const ref2 = routes[1]?.requestBody?.content?.["application/json"]?.schemaRef;
201
+ const ref3 = routes[1]?.responses?.["201"]?.content?.["application/json"]?.schemaRef;
202
+ assert.strictEqual(ref1, "TestSchema");
203
+ assert.strictEqual(ref2, "TestSchema");
204
+ assert.strictEqual(ref3, "TestSchema");
205
+ });
206
+ it("should handle documents without schemas", () => {
207
+ const doc = { unispecVersion: "1.0.0", service: { name: "test" } };
208
+ const compressedCount = compressSchemaReferences(doc);
209
+ assert.strictEqual(compressedCount, 0);
210
+ });
211
+ it("should handle empty references", () => {
212
+ const doc = {
213
+ unispecVersion: "1.0.0",
214
+ service: {
215
+ name: "test",
216
+ protocols: {
217
+ rest: {
218
+ routes: [
219
+ {
220
+ name: "testRoute",
221
+ method: "GET",
222
+ path: "/test",
223
+ responses: {
224
+ "200": {
225
+ description: "Success",
226
+ content: {
227
+ "application/json": {
228
+ schemaRef: "",
229
+ },
230
+ },
231
+ },
232
+ },
233
+ },
234
+ ],
235
+ },
236
+ },
237
+ },
238
+ };
239
+ const compressedCount = compressSchemaReferences(doc);
240
+ assert.strictEqual(compressedCount, 0);
241
+ });
242
+ it("should work with real examples from node_modules", () => {
243
+ const doc = loadExample(getExamplePath("valid", "spec", "mixed-complete.json"));
244
+ const compressedCount = compressSchemaReferences(JSON.parse(JSON.stringify(doc)));
245
+ // mixed-complete.json uses simple references, so nothing should be compressed
246
+ assert.strictEqual(compressedCount, 0);
247
+ });
248
+ it("should find references in nested structures", () => {
249
+ const doc = {
250
+ unispecVersion: "1.0.0",
251
+ service: {
252
+ name: "test",
253
+ schemas: {
254
+ TestSchema: {
255
+ name: "TestSchema",
256
+ description: "Test schema",
257
+ jsonSchema: { type: "string" },
258
+ },
259
+ },
260
+ protocols: {
261
+ rest: {
262
+ routes: [
263
+ {
264
+ name: "testRoute",
265
+ method: "GET",
266
+ path: "/test",
267
+ responses: {
268
+ "200": {
269
+ description: "Success",
270
+ content: {
271
+ "application/json": {
272
+ schemaRef: "#/service/schemas/TestSchema",
273
+ },
274
+ },
275
+ },
276
+ },
277
+ },
278
+ ],
279
+ },
280
+ websocket: {
281
+ channels: [
282
+ {
283
+ name: "testChannel",
284
+ messages: [
285
+ {
286
+ name: "testMessage",
287
+ schemaRef: "#/service/schemas/TestSchema",
288
+ },
289
+ ],
290
+ },
291
+ ],
292
+ },
293
+ },
294
+ },
295
+ };
296
+ const compressedCount = compressSchemaReferences(doc);
297
+ assert.strictEqual(compressedCount, 2); // One in REST response, one in WebSocket
298
+ });
299
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,127 @@
1
+ import assert from "node:assert";
2
+ import { describe, it } from "node:test";
3
+ import { deduplicateSchemas } from "../../src/optimizer/optimization-functions.js";
4
+ import { createDocumentWithDuplicateSchemas, getExamplePath, loadExample, } from "./utils.js";
5
+ describe("deduplicateSchemas", () => {
6
+ it("should remove duplicate schemas and update references", () => {
7
+ const doc = createDocumentWithDuplicateSchemas();
8
+ const result = deduplicateSchemas(doc);
9
+ assert.strictEqual(result.removedSchemas.length, 1);
10
+ assert.ok(result.removedSchemas.includes("Person") ||
11
+ result.removedSchemas.includes("User"));
12
+ assert.strictEqual(result.updatedReferences, 0);
13
+ // Check that only one of the duplicate schemas remains
14
+ const remainingSchemas = Object.keys(doc.service?.schemas || {});
15
+ assert.ok(remainingSchemas.includes("User") || remainingSchemas.includes("Person"));
16
+ assert.strictEqual(remainingSchemas.filter((name) => name === "User" || name === "Person")
17
+ .length, 1);
18
+ assert.ok(remainingSchemas.includes("Profile"));
19
+ });
20
+ it("should prefer referenced schema over unreferenced one", () => {
21
+ const doc = createDocumentWithDuplicateSchemas();
22
+ // Add reference to User schema
23
+ if (doc.service?.protocols?.rest?.routes?.[0]) {
24
+ doc.service.protocols.rest.routes[0].responses = {
25
+ "200": {
26
+ description: "Success",
27
+ content: {
28
+ "application/json": {
29
+ schemaRef: "User",
30
+ },
31
+ },
32
+ },
33
+ };
34
+ }
35
+ const result = deduplicateSchemas(doc);
36
+ assert.strictEqual(result.removedSchemas.length, 1);
37
+ assert.ok(result.removedSchemas.includes("Person"));
38
+ assert.ok(!result.removedSchemas.includes("User"));
39
+ assert.ok(doc.service?.schemas?.User);
40
+ assert.ok(!doc.service?.schemas?.Person);
41
+ });
42
+ it("should handle documents without schemas", () => {
43
+ const doc = { unispecVersion: "1.0.0", service: { name: "test" } };
44
+ const result = deduplicateSchemas(doc);
45
+ assert.strictEqual(result.removedSchemas.length, 0);
46
+ assert.strictEqual(result.updatedReferences, 0);
47
+ });
48
+ it("should handle documents without service", () => {
49
+ const doc = { unispecVersion: "1.0.0", service: { name: "test" } };
50
+ const result = deduplicateSchemas(doc);
51
+ assert.strictEqual(result.removedSchemas.length, 0);
52
+ assert.strictEqual(result.updatedReferences, 0);
53
+ });
54
+ it("should handle empty schemas object", () => {
55
+ const doc = {
56
+ unispecVersion: "1.0.0",
57
+ service: { name: "test", schemas: {} },
58
+ };
59
+ const result = deduplicateSchemas(doc);
60
+ assert.strictEqual(result.removedSchemas.length, 0);
61
+ assert.strictEqual(result.updatedReferences, 0);
62
+ });
63
+ it("should update schema references when removing duplicates", () => {
64
+ // Test case where reference points to Person (which will be kept)
65
+ const doc = createDocumentWithDuplicateSchemas();
66
+ if (doc.service?.protocols?.rest?.routes?.[0]) {
67
+ doc.service.protocols.rest.routes[0].responses = {
68
+ "200": {
69
+ description: "Success",
70
+ content: {
71
+ "application/json": {
72
+ schemaRef: "Person", // This will be kept, User will be removed
73
+ },
74
+ },
75
+ },
76
+ };
77
+ }
78
+ const result = deduplicateSchemas(doc);
79
+ // Should remove User (no reference update needed since Person stays)
80
+ assert.strictEqual(result.removedSchemas.length, 1);
81
+ assert.ok(result.removedSchemas.includes("User"));
82
+ assert.strictEqual(result.updatedReferences, 0);
83
+ // Check that Person still exists and reference points to it
84
+ assert.ok(doc.service?.schemas?.Person);
85
+ assert.ok(!doc.service?.schemas?.User);
86
+ const route = doc.service?.protocols?.rest?.routes?.[0];
87
+ const schemaRef = route?.responses?.["200"]?.content?.["application/json"]?.schemaRef;
88
+ assert.strictEqual(schemaRef, "Person");
89
+ });
90
+ it("should work with real examples from node_modules", () => {
91
+ const doc = loadExample(getExamplePath("valid", "spec", "mixed-complete.json"));
92
+ const result = deduplicateSchemas(JSON.parse(JSON.stringify(doc)));
93
+ // mixed-complete.json has no duplicates, so nothing should be removed
94
+ assert.strictEqual(result.removedSchemas.length, 0);
95
+ assert.strictEqual(result.updatedReferences, 0);
96
+ });
97
+ it("should handle schemas with null jsonSchema", () => {
98
+ const doc = {
99
+ unispecVersion: "1.0.0",
100
+ service: {
101
+ name: "test",
102
+ schemas: {
103
+ Schema1: {
104
+ name: "Schema1",
105
+ description: "Schema 1",
106
+ jsonSchema: {},
107
+ },
108
+ Schema2: {
109
+ name: "Schema2",
110
+ description: "Schema 2",
111
+ jsonSchema: {},
112
+ },
113
+ Schema3: {
114
+ name: "Schema3",
115
+ description: "Schema 3",
116
+ jsonSchema: { type: "string" },
117
+ },
118
+ },
119
+ },
120
+ };
121
+ const result = deduplicateSchemas(doc);
122
+ // Two schemas with empty jsonSchema should be considered duplicates
123
+ assert.strictEqual(result.removedSchemas.length, 1);
124
+ assert.strictEqual(result.updatedReferences, 0);
125
+ assert.strictEqual(Object.keys(doc.service?.schemas || {}).length, 2);
126
+ });
127
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,126 @@
1
+ import assert from "node:assert";
2
+ import { describe, it } from "node:test";
3
+ import { generateOptimizationReport, optimizeDocument } from "../../src/optimizer/core.js";
4
+ import { compressSchemaReferences, deduplicateSchemas, removeOrphanedSchemas, sortSchemas, } from "../../src/optimizer/optimization-functions.js";
5
+ import { getExamplePath, loadExample } from "./utils.js";
6
+ describe("Optimizer Integration Tests", () => {
7
+ it("should work with real examples from node_modules", () => {
8
+ const doc = loadExample(getExamplePath("valid", "spec", "mixed-complete.json"));
9
+ // Test individual functions
10
+ const dedupResult = deduplicateSchemas(JSON.parse(JSON.stringify(doc)));
11
+ assert.ok(dedupResult.removedSchemas.length >= 0);
12
+ const orphanedResult = removeOrphanedSchemas(JSON.parse(JSON.stringify(doc)));
13
+ assert.ok(orphanedResult.length >= 0);
14
+ const sortResult = sortSchemas(JSON.parse(JSON.stringify(doc)));
15
+ assert.ok(sortResult >= 0);
16
+ const compressResult = compressSchemaReferences(JSON.parse(JSON.stringify(doc)));
17
+ assert.ok(compressResult >= 0);
18
+ // Test optimizeDocument
19
+ const optimizeResult = optimizeDocument(JSON.parse(JSON.stringify(doc)));
20
+ assert.ok(optimizeResult.document);
21
+ assert.ok(optimizeResult.statistics);
22
+ assert.ok(Array.isArray(optimizeResult.changes));
23
+ // Test generateOptimizationReport
24
+ const report = generateOptimizationReport(JSON.parse(JSON.stringify(doc)));
25
+ assert.ok(report.recommendations);
26
+ assert.ok(report.potentialSavings);
27
+ });
28
+ it("should handle edge cases gracefully", () => {
29
+ // Empty document
30
+ const emptyDoc = { unispecVersion: "1.0.0", service: { name: "test" } };
31
+ const optimizeResult = optimizeDocument(emptyDoc);
32
+ assert.strictEqual(optimizeResult.statistics.originalSchemas, 0);
33
+ assert.strictEqual(optimizeResult.statistics.optimizedSchemas, 0);
34
+ const report = generateOptimizationReport(emptyDoc);
35
+ assert.strictEqual(report.recommendations.length, 0);
36
+ assert.strictEqual(report.potentialSavings.schemaReduction, 0);
37
+ });
38
+ it("should preserve document integrity", () => {
39
+ const doc = loadExample(getExamplePath("valid", "spec", "rest-simple.json"));
40
+ const result = optimizeDocument(JSON.parse(JSON.stringify(doc)));
41
+ // Should preserve required fields
42
+ assert.strictEqual(result.document.unispecVersion, doc.unispecVersion);
43
+ assert.strictEqual(result.document.service?.name, doc.service?.name);
44
+ assert.ok(result.document.service?.protocols);
45
+ assert.ok(result.document.service?.schemas);
46
+ });
47
+ it("should handle complex optimization scenarios", () => {
48
+ const doc = {
49
+ unispecVersion: "1.0.0",
50
+ service: {
51
+ name: "test",
52
+ schemas: {
53
+ // Duplicate schemas
54
+ User: {
55
+ description: "User schema",
56
+ jsonSchema: {
57
+ type: "object",
58
+ properties: { id: { type: "string" } },
59
+ },
60
+ },
61
+ Person: {
62
+ description: "Person schema",
63
+ jsonSchema: {
64
+ type: "object",
65
+ properties: { id: { type: "string" } },
66
+ },
67
+ },
68
+ // Orphaned schema
69
+ Orphaned: {
70
+ description: "Orphaned schema",
71
+ jsonSchema: { type: "string" },
72
+ },
73
+ // Referenced schema
74
+ Profile: {
75
+ description: "Profile schema",
76
+ jsonSchema: {
77
+ type: "object",
78
+ properties: { profileId: { type: "string" } },
79
+ },
80
+ },
81
+ },
82
+ protocols: {
83
+ rest: {
84
+ routes: [
85
+ {
86
+ name: "testRoute",
87
+ method: "GET",
88
+ path: "/test",
89
+ responses: {
90
+ "200": {
91
+ description: "Success",
92
+ content: {
93
+ "application/json": {
94
+ schemaRef: "#/service/schemas/Person", // Long reference to duplicate
95
+ },
96
+ },
97
+ },
98
+ },
99
+ },
100
+ ],
101
+ },
102
+ },
103
+ },
104
+ };
105
+ const result = optimizeDocument(doc, {
106
+ dedupeSchemas: true,
107
+ sortSchemas: true,
108
+ removeUnusedSchemas: true,
109
+ compressReferences: true,
110
+ });
111
+ // Should optimize correctly
112
+ assert.strictEqual(result.statistics.originalSchemas, 4);
113
+ assert.strictEqual(result.statistics.optimizedSchemas, 1); // Person (Profile is orphaned)
114
+ assert.strictEqual(result.statistics.removedSchemas, 3); // User + Orphaned + Profile
115
+ assert.strictEqual(result.statistics.deduplicatedSchemas, 1);
116
+ // Should have changes recorded
117
+ assert.ok(result.changes.length >= 3);
118
+ // Check final state
119
+ const schemas = Object.keys(result.document.service?.schemas || {});
120
+ assert.deepStrictEqual(schemas, ["Person"]); // Only Person remains
121
+ // Check reference was updated and compressed
122
+ const route = result.document.service?.protocols?.rest?.routes?.[0];
123
+ const schemaRef = route?.responses?.["200"]?.content?.["application/json"]?.schemaRef;
124
+ assert.strictEqual(schemaRef, "Person");
125
+ });
126
+ });
@@ -0,0 +1 @@
1
+ export {};