@nekostack/schema 1.0.0

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 (214) hide show
  1. package/CHANGELOG.md +422 -0
  2. package/LICENSE +202 -0
  3. package/README.md +656 -0
  4. package/dist/src/builders/array.d.ts +12 -0
  5. package/dist/src/builders/array.d.ts.map +1 -0
  6. package/dist/src/builders/array.js +29 -0
  7. package/dist/src/builders/array.js.map +1 -0
  8. package/dist/src/builders/object.d.ts +62 -0
  9. package/dist/src/builders/object.d.ts.map +1 -0
  10. package/dist/src/builders/object.js +263 -0
  11. package/dist/src/builders/object.js.map +1 -0
  12. package/dist/src/builders/primitives.d.ts +37 -0
  13. package/dist/src/builders/primitives.d.ts.map +1 -0
  14. package/dist/src/builders/primitives.js +125 -0
  15. package/dist/src/builders/primitives.js.map +1 -0
  16. package/dist/src/builders/s.d.ts +27 -0
  17. package/dist/src/builders/s.d.ts.map +1 -0
  18. package/dist/src/builders/s.js +39 -0
  19. package/dist/src/builders/s.js.map +1 -0
  20. package/dist/src/builders/schema.d.ts +70 -0
  21. package/dist/src/builders/schema.d.ts.map +1 -0
  22. package/dist/src/builders/schema.js +98 -0
  23. package/dist/src/builders/schema.js.map +1 -0
  24. package/dist/src/cli-integration.d.ts +43 -0
  25. package/dist/src/cli-integration.d.ts.map +1 -0
  26. package/dist/src/cli-integration.js +48 -0
  27. package/dist/src/cli-integration.js.map +1 -0
  28. package/dist/src/errors/issue.d.ts +34 -0
  29. package/dist/src/errors/issue.d.ts.map +1 -0
  30. package/dist/src/errors/issue.js +89 -0
  31. package/dist/src/errors/issue.js.map +1 -0
  32. package/dist/src/generators/errors.d.ts +31 -0
  33. package/dist/src/generators/errors.d.ts.map +1 -0
  34. package/dist/src/generators/errors.js +34 -0
  35. package/dist/src/generators/errors.js.map +1 -0
  36. package/dist/src/generators/header.d.ts +42 -0
  37. package/dist/src/generators/header.d.ts.map +1 -0
  38. package/dist/src/generators/header.js +43 -0
  39. package/dist/src/generators/header.js.map +1 -0
  40. package/dist/src/generators/json-schema-meta.d.ts +36 -0
  41. package/dist/src/generators/json-schema-meta.d.ts.map +1 -0
  42. package/dist/src/generators/json-schema-meta.js +35 -0
  43. package/dist/src/generators/json-schema-meta.js.map +1 -0
  44. package/dist/src/generators/json-schema.d.ts +26 -0
  45. package/dist/src/generators/json-schema.d.ts.map +1 -0
  46. package/dist/src/generators/json-schema.js +88 -0
  47. package/dist/src/generators/json-schema.js.map +1 -0
  48. package/dist/src/generators/openapi.d.ts +33 -0
  49. package/dist/src/generators/openapi.d.ts.map +1 -0
  50. package/dist/src/generators/openapi.js +61 -0
  51. package/dist/src/generators/openapi.js.map +1 -0
  52. package/dist/src/generators/schema-fragment.d.ts +55 -0
  53. package/dist/src/generators/schema-fragment.d.ts.map +1 -0
  54. package/dist/src/generators/schema-fragment.js +253 -0
  55. package/dist/src/generators/schema-fragment.js.map +1 -0
  56. package/dist/src/generators/ts.d.ts +19 -0
  57. package/dist/src/generators/ts.d.ts.map +1 -0
  58. package/dist/src/generators/ts.js +252 -0
  59. package/dist/src/generators/ts.js.map +1 -0
  60. package/dist/src/generators/types.d.ts +96 -0
  61. package/dist/src/generators/types.d.ts.map +1 -0
  62. package/dist/src/generators/types.js +10 -0
  63. package/dist/src/generators/types.js.map +1 -0
  64. package/dist/src/generators/version.d.ts +11 -0
  65. package/dist/src/generators/version.d.ts.map +1 -0
  66. package/dist/src/generators/version.js +11 -0
  67. package/dist/src/generators/version.js.map +1 -0
  68. package/dist/src/generators/zod-mapping.d.ts +90 -0
  69. package/dist/src/generators/zod-mapping.d.ts.map +1 -0
  70. package/dist/src/generators/zod-mapping.js +174 -0
  71. package/dist/src/generators/zod-mapping.js.map +1 -0
  72. package/dist/src/generators/zod.d.ts +17 -0
  73. package/dist/src/generators/zod.d.ts.map +1 -0
  74. package/dist/src/generators/zod.js +118 -0
  75. package/dist/src/generators/zod.js.map +1 -0
  76. package/dist/src/index.d.ts +21 -0
  77. package/dist/src/index.d.ts.map +1 -0
  78. package/dist/src/index.js +43 -0
  79. package/dist/src/index.js.map +1 -0
  80. package/dist/src/ir/hash.d.ts +19 -0
  81. package/dist/src/ir/hash.d.ts.map +1 -0
  82. package/dist/src/ir/hash.js +22 -0
  83. package/dist/src/ir/hash.js.map +1 -0
  84. package/dist/src/ir/nodes.d.ts +121 -0
  85. package/dist/src/ir/nodes.d.ts.map +1 -0
  86. package/dist/src/ir/nodes.js +14 -0
  87. package/dist/src/ir/nodes.js.map +1 -0
  88. package/dist/src/ir/serialize.d.ts +8 -0
  89. package/dist/src/ir/serialize.d.ts.map +1 -0
  90. package/dist/src/ir/serialize.js +23 -0
  91. package/dist/src/ir/serialize.js.map +1 -0
  92. package/dist/src/migrations/build-migration-registry.d.ts +46 -0
  93. package/dist/src/migrations/build-migration-registry.d.ts.map +1 -0
  94. package/dist/src/migrations/build-migration-registry.js +134 -0
  95. package/dist/src/migrations/build-migration-registry.js.map +1 -0
  96. package/dist/src/migrations/handlers/list.d.ts +35 -0
  97. package/dist/src/migrations/handlers/list.d.ts.map +1 -0
  98. package/dist/src/migrations/handlers/list.js +55 -0
  99. package/dist/src/migrations/handlers/list.js.map +1 -0
  100. package/dist/src/migrations/handlers/plan.d.ts +26 -0
  101. package/dist/src/migrations/handlers/plan.d.ts.map +1 -0
  102. package/dist/src/migrations/handlers/plan.js +28 -0
  103. package/dist/src/migrations/handlers/plan.js.map +1 -0
  104. package/dist/src/migrations/handlers/stub.d.ts +22 -0
  105. package/dist/src/migrations/handlers/stub.d.ts.map +1 -0
  106. package/dist/src/migrations/handlers/stub.js +24 -0
  107. package/dist/src/migrations/handlers/stub.js.map +1 -0
  108. package/dist/src/migrations/handlers/verify.d.ts +25 -0
  109. package/dist/src/migrations/handlers/verify.d.ts.map +1 -0
  110. package/dist/src/migrations/handlers/verify.js +27 -0
  111. package/dist/src/migrations/handlers/verify.js.map +1 -0
  112. package/dist/src/migrations/parse-provenance.d.ts +78 -0
  113. package/dist/src/migrations/parse-provenance.d.ts.map +1 -0
  114. package/dist/src/migrations/parse-provenance.js +157 -0
  115. package/dist/src/migrations/parse-provenance.js.map +1 -0
  116. package/dist/src/migrations/plan-migration.d.ts +50 -0
  117. package/dist/src/migrations/plan-migration.d.ts.map +1 -0
  118. package/dist/src/migrations/plan-migration.js +256 -0
  119. package/dist/src/migrations/plan-migration.js.map +1 -0
  120. package/dist/src/migrations/stub.d.ts +55 -0
  121. package/dist/src/migrations/stub.d.ts.map +1 -0
  122. package/dist/src/migrations/stub.js +201 -0
  123. package/dist/src/migrations/stub.js.map +1 -0
  124. package/dist/src/migrations/types.d.ts +297 -0
  125. package/dist/src/migrations/types.d.ts.map +1 -0
  126. package/dist/src/migrations/types.js +28 -0
  127. package/dist/src/migrations/types.js.map +1 -0
  128. package/dist/src/migrations/verify-provenance.d.ts +46 -0
  129. package/dist/src/migrations/verify-provenance.d.ts.map +1 -0
  130. package/dist/src/migrations/verify-provenance.js +158 -0
  131. package/dist/src/migrations/verify-provenance.js.map +1 -0
  132. package/dist/src/registry/build-registry.d.ts +65 -0
  133. package/dist/src/registry/build-registry.d.ts.map +1 -0
  134. package/dist/src/registry/build-registry.js +172 -0
  135. package/dist/src/registry/build-registry.js.map +1 -0
  136. package/dist/src/registry/diff.d.ts +25 -0
  137. package/dist/src/registry/diff.d.ts.map +1 -0
  138. package/dist/src/registry/diff.js +497 -0
  139. package/dist/src/registry/diff.js.map +1 -0
  140. package/dist/src/registry/handlers/check.d.ts +57 -0
  141. package/dist/src/registry/handlers/check.d.ts.map +1 -0
  142. package/dist/src/registry/handlers/check.js +181 -0
  143. package/dist/src/registry/handlers/check.js.map +1 -0
  144. package/dist/src/registry/handlers/diff.d.ts +33 -0
  145. package/dist/src/registry/handlers/diff.d.ts.map +1 -0
  146. package/dist/src/registry/handlers/diff.js +61 -0
  147. package/dist/src/registry/handlers/diff.js.map +1 -0
  148. package/dist/src/registry/handlers/generate.d.ts +87 -0
  149. package/dist/src/registry/handlers/generate.d.ts.map +1 -0
  150. package/dist/src/registry/handlers/generate.js +223 -0
  151. package/dist/src/registry/handlers/generate.js.map +1 -0
  152. package/dist/src/registry/handlers/list.d.ts +36 -0
  153. package/dist/src/registry/handlers/list.d.ts.map +1 -0
  154. package/dist/src/registry/handlers/list.js +84 -0
  155. package/dist/src/registry/handlers/list.js.map +1 -0
  156. package/dist/src/registry/parse-provenance.d.ts +63 -0
  157. package/dist/src/registry/parse-provenance.d.ts.map +1 -0
  158. package/dist/src/registry/parse-provenance.js +182 -0
  159. package/dist/src/registry/parse-provenance.js.map +1 -0
  160. package/dist/src/registry/source-hash.d.ts +28 -0
  161. package/dist/src/registry/source-hash.d.ts.map +1 -0
  162. package/dist/src/registry/source-hash.js +32 -0
  163. package/dist/src/registry/source-hash.js.map +1 -0
  164. package/dist/src/registry/types.d.ts +185 -0
  165. package/dist/src/registry/types.d.ts.map +1 -0
  166. package/dist/src/registry/types.js +22 -0
  167. package/dist/src/registry/types.js.map +1 -0
  168. package/dist/src/runtime/compile.d.ts +38 -0
  169. package/dist/src/runtime/compile.d.ts.map +1 -0
  170. package/dist/src/runtime/compile.js +45 -0
  171. package/dist/src/runtime/compile.js.map +1 -0
  172. package/dist/src/runtime/errors.d.ts +25 -0
  173. package/dist/src/runtime/errors.d.ts.map +1 -0
  174. package/dist/src/runtime/errors.js +43 -0
  175. package/dist/src/runtime/errors.js.map +1 -0
  176. package/dist/src/runtime/normalize-issues.d.ts +65 -0
  177. package/dist/src/runtime/normalize-issues.d.ts.map +1 -0
  178. package/dist/src/runtime/normalize-issues.js +208 -0
  179. package/dist/src/runtime/normalize-issues.js.map +1 -0
  180. package/dist/src/runtime/parse.d.ts +62 -0
  181. package/dist/src/runtime/parse.d.ts.map +1 -0
  182. package/dist/src/runtime/parse.js +107 -0
  183. package/dist/src/runtime/parse.js.map +1 -0
  184. package/dist/src/runtime/strip-defaults.d.ts +51 -0
  185. package/dist/src/runtime/strip-defaults.d.ts.map +1 -0
  186. package/dist/src/runtime/strip-defaults.js +81 -0
  187. package/dist/src/runtime/strip-defaults.js.map +1 -0
  188. package/dist/src/runtime/zod-compile.d.ts +27 -0
  189. package/dist/src/runtime/zod-compile.d.ts.map +1 -0
  190. package/dist/src/runtime/zod-compile.js +92 -0
  191. package/dist/src/runtime/zod-compile.js.map +1 -0
  192. package/dist/src/types.d.ts +116 -0
  193. package/dist/src/types.d.ts.map +1 -0
  194. package/dist/src/types.js +2 -0
  195. package/dist/src/types.js.map +1 -0
  196. package/docs/ABSENCE_SEMANTICS.md +37 -0
  197. package/docs/BENCHMARKS.md +64 -0
  198. package/docs/COMPOSITION.md +206 -0
  199. package/docs/DIFF_CLASSIFICATION.md +137 -0
  200. package/docs/EXAMPLES.md +221 -0
  201. package/docs/HEADER_FORMAT.md +66 -0
  202. package/docs/INVARIANTS.md +58 -0
  203. package/docs/IR_CONTRACT.md +67 -0
  204. package/docs/ISSUE_CODES.md +99 -0
  205. package/docs/JSON_SCHEMA_MAPPING.md +149 -0
  206. package/docs/MIGRATIONS.md +406 -0
  207. package/docs/MIGRATION_GUIDE.md +150 -0
  208. package/docs/OPENAPI_MAPPING.md +66 -0
  209. package/docs/REGISTRY.md +336 -0
  210. package/docs/RUNTIME.md +279 -0
  211. package/docs/SCOPE.md +119 -0
  212. package/docs/USAGE.md +376 -0
  213. package/docs/ZOD_MODIFIER_ORDERING.md +77 -0
  214. package/package.json +45 -0
@@ -0,0 +1,158 @@
1
+ /**
2
+ * `verifyMigrationProvenance(opts)` — per-migration two-hash
3
+ * provenance verifier (v0.8 Step 5).
4
+ *
5
+ * For every `MigrationEntry` in the migration registry, compares
6
+ * the migration's recorded `(fromIrHash, toIrHash, fromSourceHash,
7
+ * toSourceHash)` against the current schema registry's
8
+ * `findSchema(...).irHash` / `.sourceHash` for the same versions.
9
+ * Emits one `MigrationVerdict` per migration plus a per-status
10
+ * summary on the success branch.
11
+ *
12
+ * **Pure.** No `fs.*`, no `import()`, no `process.*`, no
13
+ * `console.*`. **Never invokes `migration.transform`** — verification
14
+ * is a `provenance-says-what-it-says` check, not a behavior check.
15
+ * Transform execution is deferred to v0.9+.
16
+ *
17
+ * Verdict mapping (Decision #9 — mirrors the v0.7 two-hash
18
+ * freshness matrix):
19
+ *
20
+ * | irHash match | sourceHash match | verdict |
21
+ * |--------------|-----------------|-------------------|
22
+ * | both | both | `bound` |
23
+ * | both | at least one ≠ | `cosmetic_drift` |
24
+ * | at least one ≠ | (any) | `drift` |
25
+ * | endpoint absent | n/a | `missing_endpoint`|
26
+ *
27
+ * Result-envelope rules:
28
+ *
29
+ * - Every verdict is recorded in `verdicts[]` regardless of status.
30
+ * - `summary` carries per-status counts.
31
+ * - `Result.success` when every verdict is `bound` or
32
+ * `cosmetic_drift` (no `drift` and no `missing_endpoint`).
33
+ * `cosmetic_drift` is warning-class and does NOT fail the run.
34
+ * - `Result.failure` with one `Issue` per `drift` / `missing_endpoint`
35
+ * verdict otherwise. The CLI dispatcher (Step 9 handler / Step 22
36
+ * verb) maps to `LOGICAL_FAILURE`.
37
+ *
38
+ * Deterministic iteration: registry entries are visited in
39
+ * `(schemaId, fromVersion, toVersion)` lexicographic order so the
40
+ * `verdicts[]` array shape is stable regardless of how the input
41
+ * registry was built. Downstream tooling (CLI pretty/JSON output)
42
+ * relies on the order being predictable across runs.
43
+ */
44
+ import { findSchema } from "../registry/build-registry.js";
45
+ // =============================================================================
46
+ // Public entry
47
+ // =============================================================================
48
+ export function verifyMigrationProvenance(opts) {
49
+ const verdicts = [];
50
+ const issues = [];
51
+ const summary = {
52
+ bound: 0,
53
+ cosmetic_drift: 0,
54
+ drift: 0,
55
+ missing_endpoint: 0,
56
+ };
57
+ for (const entry of iterateRegistry(opts.migrationRegistry)) {
58
+ const verdict = classifyMigration(entry, opts.schemaRegistry);
59
+ verdicts.push(verdict);
60
+ summary[verdict.status] += 1;
61
+ if (verdict.status === "drift" || verdict.status === "missing_endpoint") {
62
+ issues.push(verdictIssue(verdict));
63
+ }
64
+ }
65
+ if (issues.length > 0) {
66
+ return { success: false, issues };
67
+ }
68
+ const result = { verdicts, summary };
69
+ return { success: true, data: result };
70
+ }
71
+ // =============================================================================
72
+ // Deterministic iteration
73
+ // =============================================================================
74
+ /**
75
+ * Yield every `MigrationEntry` in the registry in
76
+ * `(schemaId, fromVersion, toVersion)` lexicographic order. The
77
+ * underlying `Map`s preserve insertion order, but we sort
78
+ * explicitly so the verifier's output is stable across different
79
+ * upstream-build sequences.
80
+ */
81
+ function* iterateRegistry(registry) {
82
+ const schemaIds = [...registry.keys()].sort();
83
+ for (const schemaId of schemaIds) {
84
+ const byFrom = registry.get(schemaId);
85
+ const fromVersions = [...byFrom.keys()].sort();
86
+ for (const fromVersion of fromVersions) {
87
+ const byTo = byFrom.get(fromVersion);
88
+ const toVersions = [...byTo.keys()].sort();
89
+ for (const toVersion of toVersions) {
90
+ yield byTo.get(toVersion);
91
+ }
92
+ }
93
+ }
94
+ }
95
+ // =============================================================================
96
+ // Classification
97
+ // =============================================================================
98
+ function classifyMigration(entry, schemaRegistry) {
99
+ const base = {
100
+ sourcePath: entry.sourcePath,
101
+ schemaId: entry.schemaId,
102
+ fromVersion: entry.fromVersion,
103
+ toVersion: entry.toVersion,
104
+ };
105
+ const fromSchema = findSchema(schemaRegistry, entry.schemaId, entry.fromVersion);
106
+ const toSchema = findSchema(schemaRegistry, entry.schemaId, entry.toVersion);
107
+ if (fromSchema === undefined || toSchema === undefined) {
108
+ return { status: "missing_endpoint", ...base };
109
+ }
110
+ const fromIrMatch = entry.fromIrHash === fromSchema.irHash;
111
+ const toIrMatch = entry.toIrHash === toSchema.irHash;
112
+ if (!fromIrMatch || !toIrMatch) {
113
+ return { status: "drift", ...base };
114
+ }
115
+ const fromSourceMatch = entry.fromSourceHash === fromSchema.sourceHash;
116
+ const toSourceMatch = entry.toSourceHash === toSchema.sourceHash;
117
+ if (!fromSourceMatch || !toSourceMatch) {
118
+ return { status: "cosmetic_drift", ...base };
119
+ }
120
+ return { status: "bound", ...base };
121
+ }
122
+ // =============================================================================
123
+ // Issue helpers
124
+ // =============================================================================
125
+ function verdictIssue(verdict) {
126
+ if (verdict.status === "missing_endpoint") {
127
+ return {
128
+ code: "migration_missing_endpoint",
129
+ path: [verdict.sourcePath],
130
+ message: `Migration \`${verdict.schemaId}\` ` +
131
+ `${verdict.fromVersion} → ${verdict.toVersion} references a schema ` +
132
+ `version that is not in the registry.`,
133
+ severity: "error",
134
+ metadata: {
135
+ schemaId: verdict.schemaId,
136
+ fromVersion: verdict.fromVersion,
137
+ toVersion: verdict.toVersion,
138
+ sourcePath: verdict.sourcePath,
139
+ },
140
+ };
141
+ }
142
+ // drift
143
+ return {
144
+ code: "migration_drift",
145
+ path: [verdict.sourcePath],
146
+ message: `Migration \`${verdict.schemaId}\` ` +
147
+ `${verdict.fromVersion} → ${verdict.toVersion} was authored against a ` +
148
+ `schema state that has since changed (irHash mismatch).`,
149
+ severity: "error",
150
+ metadata: {
151
+ schemaId: verdict.schemaId,
152
+ fromVersion: verdict.fromVersion,
153
+ toVersion: verdict.toVersion,
154
+ sourcePath: verdict.sourcePath,
155
+ },
156
+ };
157
+ }
158
+ //# sourceMappingURL=verify-provenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-provenance.js","sourceRoot":"","sources":["../../../src/migrations/verify-provenance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * `buildRegistry(entries)` — pure registry construction (Master plan
3
+ * Step 6).
4
+ *
5
+ * Walks the CLI-supplied `RegistrySourceEntry[]` (one per loaded
6
+ * `*.schema.{ts,js}` file) and builds the two-level lookup map
7
+ * `Registry = ReadonlyMap<schemaId, ReadonlyMap<versionKey,
8
+ * RegistryEntry>>`. Returns `Result<Registry>` so duplicate detection
9
+ * surfaces as `Issue[]` rather than `throw` (Master plan Decision #4).
10
+ *
11
+ * **Pure.** No `fs.*`, no `import()`, no `path.*`. The CLI is
12
+ * responsible for reading the source text and dynamic-importing the
13
+ * schema files; this function takes the loaded data and indexes it.
14
+ * Master plan Decision #1 boundary.
15
+ *
16
+ * Rules:
17
+ * - Anonymous schemas (no `.id()`) are silently ignored. They remain
18
+ * legal per v0.1; they just don't participate in registry lookup.
19
+ * The CLI emits a stderr warning per anonymous schema it finds
20
+ * (Master plan Decision #5), but that's an I/O concern owned by
21
+ * the CLI, not by this function.
22
+ * - Unversioned schemas (`.id()` but no `.version()`) are indexed
23
+ * under the empty-string inner key. The on-entry
24
+ * `schemaVersion` field stays `undefined` per the Step 1 type.
25
+ * - Duplicate `(schemaId, versionKey)` pairs across the entry list
26
+ * are collected into one `Issue` per dupe with code
27
+ * `"duplicate_schema_id"`. The function does not throw; the CLI
28
+ * formats the issue list and exits non-zero.
29
+ *
30
+ * `sourceHash` is computed once per `RegistrySourceEntry` via
31
+ * `sourceHashFromText(entry.sourceText)`. All `RegistryEntry`s
32
+ * produced from the same source file therefore share the same
33
+ * `sourceHash` value — correct because they share the same source
34
+ * text.
35
+ *
36
+ * `findSchema(registry, schemaId, version?)` is the lookup helper.
37
+ * When `version` is omitted, returns the highest-semver entry for
38
+ * the given id. If only unversioned entries exist for that id, the
39
+ * unversioned entry is returned. See the function comment for the
40
+ * full lookup rules.
41
+ */
42
+ import type { Result } from "../errors/issue.js";
43
+ import type { Registry, RegistryEntry, RegistrySourceEntry } from "./types.js";
44
+ export declare function buildRegistry(entries: readonly RegistrySourceEntry[]): Result<Registry>;
45
+ /**
46
+ * Look up a schema by `(schemaId, schemaVersion)`.
47
+ *
48
+ * Rules:
49
+ * - When `version` is provided: exact match against the inner key.
50
+ * - `findSchema(reg, "X", "1.0.0")` returns the entry whose
51
+ * `schemaVersion` is `"1.0.0"`, or `undefined`.
52
+ * - `findSchema(reg, "X", "")` returns the unversioned entry if
53
+ * one exists (the empty-string key); this is the intentional
54
+ * way to address an unversioned schema by exact lookup.
55
+ * - When `version` is omitted: returns the highest-semver entry
56
+ * for `schemaId`. If only unversioned entries exist, returns the
57
+ * unversioned entry. If both versioned and unversioned entries
58
+ * exist for the same id, **versioned wins** — `findSchema` returns
59
+ * the highest semver, never the unversioned entry, when at least
60
+ * one versioned entry exists.
61
+ * - Returns `undefined` if `schemaId` is not in the registry, or
62
+ * if the explicit `version` does not match any inner key.
63
+ */
64
+ export declare function findSchema(registry: Registry, schemaId: string, version?: string): RegistryEntry | undefined;
65
+ //# sourceMappingURL=build-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-registry.d.ts","sourceRoot":"","sources":["../../../src/registry/build-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAGH,OAAO,KAAK,EAAS,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,EACV,QAAQ,EACR,aAAa,EACb,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAMpB,wBAAgB,aAAa,CAC3B,OAAO,EAAE,SAAS,mBAAmB,EAAE,GACtC,MAAM,CAAC,QAAQ,CAAC,CAmDlB;AA4BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,aAAa,GAAG,SAAS,CAuB3B"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * `buildRegistry(entries)` — pure registry construction (Master plan
3
+ * Step 6).
4
+ *
5
+ * Walks the CLI-supplied `RegistrySourceEntry[]` (one per loaded
6
+ * `*.schema.{ts,js}` file) and builds the two-level lookup map
7
+ * `Registry = ReadonlyMap<schemaId, ReadonlyMap<versionKey,
8
+ * RegistryEntry>>`. Returns `Result<Registry>` so duplicate detection
9
+ * surfaces as `Issue[]` rather than `throw` (Master plan Decision #4).
10
+ *
11
+ * **Pure.** No `fs.*`, no `import()`, no `path.*`. The CLI is
12
+ * responsible for reading the source text and dynamic-importing the
13
+ * schema files; this function takes the loaded data and indexes it.
14
+ * Master plan Decision #1 boundary.
15
+ *
16
+ * Rules:
17
+ * - Anonymous schemas (no `.id()`) are silently ignored. They remain
18
+ * legal per v0.1; they just don't participate in registry lookup.
19
+ * The CLI emits a stderr warning per anonymous schema it finds
20
+ * (Master plan Decision #5), but that's an I/O concern owned by
21
+ * the CLI, not by this function.
22
+ * - Unversioned schemas (`.id()` but no `.version()`) are indexed
23
+ * under the empty-string inner key. The on-entry
24
+ * `schemaVersion` field stays `undefined` per the Step 1 type.
25
+ * - Duplicate `(schemaId, versionKey)` pairs across the entry list
26
+ * are collected into one `Issue` per dupe with code
27
+ * `"duplicate_schema_id"`. The function does not throw; the CLI
28
+ * formats the issue list and exits non-zero.
29
+ *
30
+ * `sourceHash` is computed once per `RegistrySourceEntry` via
31
+ * `sourceHashFromText(entry.sourceText)`. All `RegistryEntry`s
32
+ * produced from the same source file therefore share the same
33
+ * `sourceHash` value — correct because they share the same source
34
+ * text.
35
+ *
36
+ * `findSchema(registry, schemaId, version?)` is the lookup helper.
37
+ * When `version` is omitted, returns the highest-semver entry for
38
+ * the given id. If only unversioned entries exist for that id, the
39
+ * unversioned entry is returned. See the function comment for the
40
+ * full lookup rules.
41
+ */
42
+ import { irHash } from "../ir/hash.js";
43
+ import { sourceHashFromText } from "./source-hash.js";
44
+ // =============================================================================
45
+ // buildRegistry
46
+ // =============================================================================
47
+ export function buildRegistry(entries) {
48
+ const out = new Map();
49
+ const duplicates = [];
50
+ for (const entry of entries) {
51
+ const entrySourceHash = sourceHashFromText(entry.sourceText);
52
+ for (const schema of entry.schemas) {
53
+ const schemaId = schema.node.metadata?.id;
54
+ if (schemaId === undefined) {
55
+ // Anonymous schemas don't participate in registry lookup.
56
+ // The CLI warns; this layer is silent.
57
+ continue;
58
+ }
59
+ const schemaVersion = schema.node.metadata?.version;
60
+ const versionKey = schemaVersion ?? "";
61
+ const built = {
62
+ schemaId,
63
+ schemaVersion,
64
+ irHash: `sha256:${irHash(schema.node)}`,
65
+ sourceHash: entrySourceHash,
66
+ sourcePath: entry.sourcePath,
67
+ schema,
68
+ };
69
+ let inner = out.get(schemaId);
70
+ if (inner === undefined) {
71
+ inner = new Map();
72
+ out.set(schemaId, inner);
73
+ }
74
+ const existing = inner.get(versionKey);
75
+ if (existing !== undefined) {
76
+ duplicates.push(duplicateIssue(schemaId, schemaVersion, [
77
+ existing.sourcePath,
78
+ entry.sourcePath,
79
+ ]));
80
+ // Keep the first-seen entry. Re-indexing would let the
81
+ // duplicate replace the original silently, which is the
82
+ // exact failure mode this Result is meant to surface.
83
+ continue;
84
+ }
85
+ inner.set(versionKey, built);
86
+ }
87
+ }
88
+ if (duplicates.length > 0) {
89
+ return { success: false, issues: duplicates };
90
+ }
91
+ return { success: true, data: out };
92
+ }
93
+ function duplicateIssue(schemaId, schemaVersion, sourcePaths) {
94
+ const versionLabel = schemaVersion === undefined ? "(unversioned)" : `v${schemaVersion}`;
95
+ return {
96
+ code: "duplicate_schema_id",
97
+ path: [],
98
+ message: `Duplicate schema "${schemaId}" ${versionLabel} found in: ${sourcePaths.join(", ")}`,
99
+ severity: "error",
100
+ metadata: {
101
+ schemaId,
102
+ schemaVersion: schemaVersion ?? null,
103
+ sourcePaths: [...sourcePaths],
104
+ },
105
+ };
106
+ }
107
+ // =============================================================================
108
+ // findSchema
109
+ // =============================================================================
110
+ /**
111
+ * Look up a schema by `(schemaId, schemaVersion)`.
112
+ *
113
+ * Rules:
114
+ * - When `version` is provided: exact match against the inner key.
115
+ * - `findSchema(reg, "X", "1.0.0")` returns the entry whose
116
+ * `schemaVersion` is `"1.0.0"`, or `undefined`.
117
+ * - `findSchema(reg, "X", "")` returns the unversioned entry if
118
+ * one exists (the empty-string key); this is the intentional
119
+ * way to address an unversioned schema by exact lookup.
120
+ * - When `version` is omitted: returns the highest-semver entry
121
+ * for `schemaId`. If only unversioned entries exist, returns the
122
+ * unversioned entry. If both versioned and unversioned entries
123
+ * exist for the same id, **versioned wins** — `findSchema` returns
124
+ * the highest semver, never the unversioned entry, when at least
125
+ * one versioned entry exists.
126
+ * - Returns `undefined` if `schemaId` is not in the registry, or
127
+ * if the explicit `version` does not match any inner key.
128
+ */
129
+ export function findSchema(registry, schemaId, version) {
130
+ const inner = registry.get(schemaId);
131
+ if (inner === undefined)
132
+ return undefined;
133
+ if (version !== undefined) {
134
+ return inner.get(version);
135
+ }
136
+ // No version supplied — pick the highest-semver entry.
137
+ const versionedKeys = [];
138
+ let unversioned;
139
+ for (const [key, entry] of inner) {
140
+ if (key === "") {
141
+ unversioned = entry;
142
+ }
143
+ else {
144
+ versionedKeys.push(key);
145
+ }
146
+ }
147
+ if (versionedKeys.length > 0) {
148
+ versionedKeys.sort(compareSemver);
149
+ return inner.get(versionedKeys[versionedKeys.length - 1]);
150
+ }
151
+ return unversioned;
152
+ }
153
+ /**
154
+ * Compare two semver-shaped strings numerically by major.minor.patch.
155
+ * Falls back to `localeCompare` for non-matching inputs so we never
156
+ * throw on a non-standard version string — that would defeat the
157
+ * fail-loud-not-throw discipline. Matches the shape used by
158
+ * `scripts/generate-status.mjs`.
159
+ */
160
+ function compareSemver(a, b) {
161
+ const ax = a.match(/(\d+)\.(\d+)\.(\d+)/);
162
+ const bx = b.match(/(\d+)\.(\d+)\.(\d+)/);
163
+ if (!ax || !bx)
164
+ return a.localeCompare(b);
165
+ for (let i = 1; i <= 3; i++) {
166
+ const d = Number(ax[i]) - Number(bx[i]);
167
+ if (d !== 0)
168
+ return d;
169
+ }
170
+ return a.localeCompare(b);
171
+ }
172
+ //# sourceMappingURL=build-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-registry.js","sourceRoot":"","sources":["../../../src/registry/build-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Schema diff classifier (Master plan Step 7).
3
+ *
4
+ * `diffNodes(before, after)` walks two `SchemaNode` trees and emits a
5
+ * list of `DiffChange`s with severity per the locked Master plan
6
+ * Decision #12 table. The **input-acceptance compatibility** lens is
7
+ * primary: severity reflects whether the new schema accepts every
8
+ * input the old one did (additive) or rejects some (breaking).
9
+ * Output-side caveats are reflected in `kind` / `message` where they
10
+ * matter (`default_removed`, etc.) but do not split the severity.
11
+ *
12
+ * **Pure.** No registry lookup, no `Issue[]` surface, no filesystem.
13
+ * The function returns `readonly DiffChange[]`; an empty array means
14
+ * the schemas are equivalent. `worstSeverity` aggregation lives in
15
+ * `diffHandler` (Step 9).
16
+ *
17
+ * Unsupported IR kinds (`date`, `union`, `recursiveRef`, `transform`)
18
+ * throw `UnsupportedNodeKindError({ generator: "diff", kind })` per
19
+ * Master plan Decision #14 — same fail-loud discipline as the v0.3 /
20
+ * v0.6 generators.
21
+ */
22
+ import type { SchemaNode } from "../ir/nodes.js";
23
+ import type { DiffChange } from "./types.js";
24
+ export declare function diffNodes(before: SchemaNode, after: SchemaNode): readonly DiffChange[];
25
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/registry/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAUV,UAAU,EACX,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,YAAY,CAAC;AAa3D,wBAAgB,SAAS,CACvB,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,UAAU,GAChB,SAAS,UAAU,EAAE,CAIvB"}