@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.
- package/CHANGELOG.md +422 -0
- package/LICENSE +202 -0
- package/README.md +656 -0
- package/dist/src/builders/array.d.ts +12 -0
- package/dist/src/builders/array.d.ts.map +1 -0
- package/dist/src/builders/array.js +29 -0
- package/dist/src/builders/array.js.map +1 -0
- package/dist/src/builders/object.d.ts +62 -0
- package/dist/src/builders/object.d.ts.map +1 -0
- package/dist/src/builders/object.js +263 -0
- package/dist/src/builders/object.js.map +1 -0
- package/dist/src/builders/primitives.d.ts +37 -0
- package/dist/src/builders/primitives.d.ts.map +1 -0
- package/dist/src/builders/primitives.js +125 -0
- package/dist/src/builders/primitives.js.map +1 -0
- package/dist/src/builders/s.d.ts +27 -0
- package/dist/src/builders/s.d.ts.map +1 -0
- package/dist/src/builders/s.js +39 -0
- package/dist/src/builders/s.js.map +1 -0
- package/dist/src/builders/schema.d.ts +70 -0
- package/dist/src/builders/schema.d.ts.map +1 -0
- package/dist/src/builders/schema.js +98 -0
- package/dist/src/builders/schema.js.map +1 -0
- package/dist/src/cli-integration.d.ts +43 -0
- package/dist/src/cli-integration.d.ts.map +1 -0
- package/dist/src/cli-integration.js +48 -0
- package/dist/src/cli-integration.js.map +1 -0
- package/dist/src/errors/issue.d.ts +34 -0
- package/dist/src/errors/issue.d.ts.map +1 -0
- package/dist/src/errors/issue.js +89 -0
- package/dist/src/errors/issue.js.map +1 -0
- package/dist/src/generators/errors.d.ts +31 -0
- package/dist/src/generators/errors.d.ts.map +1 -0
- package/dist/src/generators/errors.js +34 -0
- package/dist/src/generators/errors.js.map +1 -0
- package/dist/src/generators/header.d.ts +42 -0
- package/dist/src/generators/header.d.ts.map +1 -0
- package/dist/src/generators/header.js +43 -0
- package/dist/src/generators/header.js.map +1 -0
- package/dist/src/generators/json-schema-meta.d.ts +36 -0
- package/dist/src/generators/json-schema-meta.d.ts.map +1 -0
- package/dist/src/generators/json-schema-meta.js +35 -0
- package/dist/src/generators/json-schema-meta.js.map +1 -0
- package/dist/src/generators/json-schema.d.ts +26 -0
- package/dist/src/generators/json-schema.d.ts.map +1 -0
- package/dist/src/generators/json-schema.js +88 -0
- package/dist/src/generators/json-schema.js.map +1 -0
- package/dist/src/generators/openapi.d.ts +33 -0
- package/dist/src/generators/openapi.d.ts.map +1 -0
- package/dist/src/generators/openapi.js +61 -0
- package/dist/src/generators/openapi.js.map +1 -0
- package/dist/src/generators/schema-fragment.d.ts +55 -0
- package/dist/src/generators/schema-fragment.d.ts.map +1 -0
- package/dist/src/generators/schema-fragment.js +253 -0
- package/dist/src/generators/schema-fragment.js.map +1 -0
- package/dist/src/generators/ts.d.ts +19 -0
- package/dist/src/generators/ts.d.ts.map +1 -0
- package/dist/src/generators/ts.js +252 -0
- package/dist/src/generators/ts.js.map +1 -0
- package/dist/src/generators/types.d.ts +96 -0
- package/dist/src/generators/types.d.ts.map +1 -0
- package/dist/src/generators/types.js +10 -0
- package/dist/src/generators/types.js.map +1 -0
- package/dist/src/generators/version.d.ts +11 -0
- package/dist/src/generators/version.d.ts.map +1 -0
- package/dist/src/generators/version.js +11 -0
- package/dist/src/generators/version.js.map +1 -0
- package/dist/src/generators/zod-mapping.d.ts +90 -0
- package/dist/src/generators/zod-mapping.d.ts.map +1 -0
- package/dist/src/generators/zod-mapping.js +174 -0
- package/dist/src/generators/zod-mapping.js.map +1 -0
- package/dist/src/generators/zod.d.ts +17 -0
- package/dist/src/generators/zod.d.ts.map +1 -0
- package/dist/src/generators/zod.js +118 -0
- package/dist/src/generators/zod.js.map +1 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +43 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/ir/hash.d.ts +19 -0
- package/dist/src/ir/hash.d.ts.map +1 -0
- package/dist/src/ir/hash.js +22 -0
- package/dist/src/ir/hash.js.map +1 -0
- package/dist/src/ir/nodes.d.ts +121 -0
- package/dist/src/ir/nodes.d.ts.map +1 -0
- package/dist/src/ir/nodes.js +14 -0
- package/dist/src/ir/nodes.js.map +1 -0
- package/dist/src/ir/serialize.d.ts +8 -0
- package/dist/src/ir/serialize.d.ts.map +1 -0
- package/dist/src/ir/serialize.js +23 -0
- package/dist/src/ir/serialize.js.map +1 -0
- package/dist/src/migrations/build-migration-registry.d.ts +46 -0
- package/dist/src/migrations/build-migration-registry.d.ts.map +1 -0
- package/dist/src/migrations/build-migration-registry.js +134 -0
- package/dist/src/migrations/build-migration-registry.js.map +1 -0
- package/dist/src/migrations/handlers/list.d.ts +35 -0
- package/dist/src/migrations/handlers/list.d.ts.map +1 -0
- package/dist/src/migrations/handlers/list.js +55 -0
- package/dist/src/migrations/handlers/list.js.map +1 -0
- package/dist/src/migrations/handlers/plan.d.ts +26 -0
- package/dist/src/migrations/handlers/plan.d.ts.map +1 -0
- package/dist/src/migrations/handlers/plan.js +28 -0
- package/dist/src/migrations/handlers/plan.js.map +1 -0
- package/dist/src/migrations/handlers/stub.d.ts +22 -0
- package/dist/src/migrations/handlers/stub.d.ts.map +1 -0
- package/dist/src/migrations/handlers/stub.js +24 -0
- package/dist/src/migrations/handlers/stub.js.map +1 -0
- package/dist/src/migrations/handlers/verify.d.ts +25 -0
- package/dist/src/migrations/handlers/verify.d.ts.map +1 -0
- package/dist/src/migrations/handlers/verify.js +27 -0
- package/dist/src/migrations/handlers/verify.js.map +1 -0
- package/dist/src/migrations/parse-provenance.d.ts +78 -0
- package/dist/src/migrations/parse-provenance.d.ts.map +1 -0
- package/dist/src/migrations/parse-provenance.js +157 -0
- package/dist/src/migrations/parse-provenance.js.map +1 -0
- package/dist/src/migrations/plan-migration.d.ts +50 -0
- package/dist/src/migrations/plan-migration.d.ts.map +1 -0
- package/dist/src/migrations/plan-migration.js +256 -0
- package/dist/src/migrations/plan-migration.js.map +1 -0
- package/dist/src/migrations/stub.d.ts +55 -0
- package/dist/src/migrations/stub.d.ts.map +1 -0
- package/dist/src/migrations/stub.js +201 -0
- package/dist/src/migrations/stub.js.map +1 -0
- package/dist/src/migrations/types.d.ts +297 -0
- package/dist/src/migrations/types.d.ts.map +1 -0
- package/dist/src/migrations/types.js +28 -0
- package/dist/src/migrations/types.js.map +1 -0
- package/dist/src/migrations/verify-provenance.d.ts +46 -0
- package/dist/src/migrations/verify-provenance.d.ts.map +1 -0
- package/dist/src/migrations/verify-provenance.js +158 -0
- package/dist/src/migrations/verify-provenance.js.map +1 -0
- package/dist/src/registry/build-registry.d.ts +65 -0
- package/dist/src/registry/build-registry.d.ts.map +1 -0
- package/dist/src/registry/build-registry.js +172 -0
- package/dist/src/registry/build-registry.js.map +1 -0
- package/dist/src/registry/diff.d.ts +25 -0
- package/dist/src/registry/diff.d.ts.map +1 -0
- package/dist/src/registry/diff.js +497 -0
- package/dist/src/registry/diff.js.map +1 -0
- package/dist/src/registry/handlers/check.d.ts +57 -0
- package/dist/src/registry/handlers/check.d.ts.map +1 -0
- package/dist/src/registry/handlers/check.js +181 -0
- package/dist/src/registry/handlers/check.js.map +1 -0
- package/dist/src/registry/handlers/diff.d.ts +33 -0
- package/dist/src/registry/handlers/diff.d.ts.map +1 -0
- package/dist/src/registry/handlers/diff.js +61 -0
- package/dist/src/registry/handlers/diff.js.map +1 -0
- package/dist/src/registry/handlers/generate.d.ts +87 -0
- package/dist/src/registry/handlers/generate.d.ts.map +1 -0
- package/dist/src/registry/handlers/generate.js +223 -0
- package/dist/src/registry/handlers/generate.js.map +1 -0
- package/dist/src/registry/handlers/list.d.ts +36 -0
- package/dist/src/registry/handlers/list.d.ts.map +1 -0
- package/dist/src/registry/handlers/list.js +84 -0
- package/dist/src/registry/handlers/list.js.map +1 -0
- package/dist/src/registry/parse-provenance.d.ts +63 -0
- package/dist/src/registry/parse-provenance.d.ts.map +1 -0
- package/dist/src/registry/parse-provenance.js +182 -0
- package/dist/src/registry/parse-provenance.js.map +1 -0
- package/dist/src/registry/source-hash.d.ts +28 -0
- package/dist/src/registry/source-hash.d.ts.map +1 -0
- package/dist/src/registry/source-hash.js +32 -0
- package/dist/src/registry/source-hash.js.map +1 -0
- package/dist/src/registry/types.d.ts +185 -0
- package/dist/src/registry/types.d.ts.map +1 -0
- package/dist/src/registry/types.js +22 -0
- package/dist/src/registry/types.js.map +1 -0
- package/dist/src/runtime/compile.d.ts +38 -0
- package/dist/src/runtime/compile.d.ts.map +1 -0
- package/dist/src/runtime/compile.js +45 -0
- package/dist/src/runtime/compile.js.map +1 -0
- package/dist/src/runtime/errors.d.ts +25 -0
- package/dist/src/runtime/errors.d.ts.map +1 -0
- package/dist/src/runtime/errors.js +43 -0
- package/dist/src/runtime/errors.js.map +1 -0
- package/dist/src/runtime/normalize-issues.d.ts +65 -0
- package/dist/src/runtime/normalize-issues.d.ts.map +1 -0
- package/dist/src/runtime/normalize-issues.js +208 -0
- package/dist/src/runtime/normalize-issues.js.map +1 -0
- package/dist/src/runtime/parse.d.ts +62 -0
- package/dist/src/runtime/parse.d.ts.map +1 -0
- package/dist/src/runtime/parse.js +107 -0
- package/dist/src/runtime/parse.js.map +1 -0
- package/dist/src/runtime/strip-defaults.d.ts +51 -0
- package/dist/src/runtime/strip-defaults.d.ts.map +1 -0
- package/dist/src/runtime/strip-defaults.js +81 -0
- package/dist/src/runtime/strip-defaults.js.map +1 -0
- package/dist/src/runtime/zod-compile.d.ts +27 -0
- package/dist/src/runtime/zod-compile.d.ts.map +1 -0
- package/dist/src/runtime/zod-compile.js +92 -0
- package/dist/src/runtime/zod-compile.js.map +1 -0
- package/dist/src/types.d.ts +116 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/docs/ABSENCE_SEMANTICS.md +37 -0
- package/docs/BENCHMARKS.md +64 -0
- package/docs/COMPOSITION.md +206 -0
- package/docs/DIFF_CLASSIFICATION.md +137 -0
- package/docs/EXAMPLES.md +221 -0
- package/docs/HEADER_FORMAT.md +66 -0
- package/docs/INVARIANTS.md +58 -0
- package/docs/IR_CONTRACT.md +67 -0
- package/docs/ISSUE_CODES.md +99 -0
- package/docs/JSON_SCHEMA_MAPPING.md +149 -0
- package/docs/MIGRATIONS.md +406 -0
- package/docs/MIGRATION_GUIDE.md +150 -0
- package/docs/OPENAPI_MAPPING.md +66 -0
- package/docs/REGISTRY.md +336 -0
- package/docs/RUNTIME.md +279 -0
- package/docs/SCOPE.md +119 -0
- package/docs/USAGE.md +376 -0
- package/docs/ZOD_MODIFIER_ORDERING.md +77 -0
- 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"}
|