@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,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provenance parser for `*.migration.ts` files (v0.8 Step 2).
|
|
3
|
+
*
|
|
4
|
+
* Reads the migration-header metadata out of an authored migration
|
|
5
|
+
* file so `buildMigrationRegistry` can index by
|
|
6
|
+
* `(schemaId, fromVersion, toVersion)` and `verifyMigrationProvenance`
|
|
7
|
+
* can compare the recorded hashes against the current schema
|
|
8
|
+
* registry. Migration files use **JSDoc-only** carriers — there is
|
|
9
|
+
* no JSON variant because migrations are TypeScript modules, not
|
|
10
|
+
* data documents.
|
|
11
|
+
*
|
|
12
|
+
* Expected header shape (generated by the v0.8 stub generator;
|
|
13
|
+
* humans edit the body, not the header):
|
|
14
|
+
*
|
|
15
|
+
* /**
|
|
16
|
+
* * @migration by @nekostack/schema
|
|
17
|
+
* * schemaId: com.x.User
|
|
18
|
+
* * fromVersion: 1.0.0
|
|
19
|
+
* * toVersion: 2.0.0
|
|
20
|
+
* * fromIrHash: sha256:<64-hex>
|
|
21
|
+
* * toIrHash: sha256:<64-hex>
|
|
22
|
+
* * fromSourceHash: sha256:<64-hex>
|
|
23
|
+
* * toSourceHash: sha256:<64-hex>
|
|
24
|
+
* * generator: neko-schema-migrate-stub
|
|
25
|
+
* * generatorVersion: @nekostack/schema@0.8.0
|
|
26
|
+
* *
|
|
27
|
+
* * DO NOT REMOVE THE HEADER. Authors EDIT THE BODY.
|
|
28
|
+
* * /
|
|
29
|
+
*
|
|
30
|
+
* The function is **pure**: no `fs.*`, no `import()`, no path
|
|
31
|
+
* argument, no module evaluation. The CLI reads the migration file
|
|
32
|
+
* text from disk and hands it in; this module parses and returns.
|
|
33
|
+
* Master plan Decision #1 boundary applies.
|
|
34
|
+
*
|
|
35
|
+
* **Fail-loud, never silent** (v0.8 Round-2 lock — intentional
|
|
36
|
+
* departure from v0.7 Decision #5). A `.migration.ts` file exists
|
|
37
|
+
* specifically to declare a `(schemaId, fromVersion, toVersion)`
|
|
38
|
+
* transition. Missing or malformed provenance is treated as an
|
|
39
|
+
* invalid declaration, not a "skip and continue" condition.
|
|
40
|
+
* Malformed input surfaces as `Result<...>` failure with one
|
|
41
|
+
* `integrity_error` `Issue` whose `metadata.reason` records the
|
|
42
|
+
* sub-mode (`missing_migration_provenance`, `missing_field`,
|
|
43
|
+
* `malformed_hash`, `malformed_field`, `unknown_format`).
|
|
44
|
+
*
|
|
45
|
+
* The shape of `reason` deliberately overlaps with the v0.7
|
|
46
|
+
* provenance-parser reasons where the failure mode is the same —
|
|
47
|
+
* a missing JSDoc block reads identically in both worlds, so
|
|
48
|
+
* `missing_provenance` would have worked, but the migration-specific
|
|
49
|
+
* `missing_migration_provenance` name lets downstream consumers
|
|
50
|
+
* disambiguate without parsing `message`.
|
|
51
|
+
*/
|
|
52
|
+
const SHA256_PATTERN = /^sha256:[0-9a-f]{64}$/;
|
|
53
|
+
/**
|
|
54
|
+
* Parse the migration JSDoc header out of a migration file's text
|
|
55
|
+
* content. Returns `Result.success` with the parsed fields on a
|
|
56
|
+
* valid header, `Result.failure` with an `integrity_error` `Issue`
|
|
57
|
+
* on every failure mode.
|
|
58
|
+
*/
|
|
59
|
+
export function parseMigrationProvenanceFromText(content) {
|
|
60
|
+
const trimmed = content.trimStart();
|
|
61
|
+
if (!trimmed.startsWith("/**")) {
|
|
62
|
+
return fail("unknown_format", "Migration file does not start with a `/** ... */` JSDoc header.");
|
|
63
|
+
}
|
|
64
|
+
return parseJsdocHeader(content);
|
|
65
|
+
}
|
|
66
|
+
// =============================================================================
|
|
67
|
+
// JSDoc header parsing
|
|
68
|
+
// =============================================================================
|
|
69
|
+
const JSDOC_BLOCK = /\/\*\*([\s\S]*?)\*\//;
|
|
70
|
+
const JSDOC_FIELD = /^\s*\*\s+(\w+):\s*(.+?)\s*$/;
|
|
71
|
+
function parseJsdocHeader(content) {
|
|
72
|
+
const block = JSDOC_BLOCK.exec(content);
|
|
73
|
+
if (!block) {
|
|
74
|
+
return fail("missing_migration_provenance", "No `/** ... */` JSDoc header found at the top of the migration file.");
|
|
75
|
+
}
|
|
76
|
+
const fields = new Map();
|
|
77
|
+
for (const line of block[1].split(/\r?\n/)) {
|
|
78
|
+
const m = JSDOC_FIELD.exec(line);
|
|
79
|
+
if (!m)
|
|
80
|
+
continue;
|
|
81
|
+
fields.set(m[1], m[2]);
|
|
82
|
+
}
|
|
83
|
+
return assembleMigrationProvenance(fields);
|
|
84
|
+
}
|
|
85
|
+
// =============================================================================
|
|
86
|
+
// Field assembly + validation
|
|
87
|
+
// =============================================================================
|
|
88
|
+
const REQUIRED_FIELDS = [
|
|
89
|
+
"generator",
|
|
90
|
+
"generatorVersion",
|
|
91
|
+
"schemaId",
|
|
92
|
+
"fromVersion",
|
|
93
|
+
"toVersion",
|
|
94
|
+
"fromIrHash",
|
|
95
|
+
"toIrHash",
|
|
96
|
+
"fromSourceHash",
|
|
97
|
+
"toSourceHash",
|
|
98
|
+
];
|
|
99
|
+
const HASH_FIELDS = [
|
|
100
|
+
"fromIrHash",
|
|
101
|
+
"toIrHash",
|
|
102
|
+
"fromSourceHash",
|
|
103
|
+
"toSourceHash",
|
|
104
|
+
];
|
|
105
|
+
function assembleMigrationProvenance(fields) {
|
|
106
|
+
// 1. Every required field must be present.
|
|
107
|
+
for (const name of REQUIRED_FIELDS) {
|
|
108
|
+
if (fields.get(name) === undefined) {
|
|
109
|
+
return fail("missing_field", `Migration provenance is missing required field \`${name}\`.`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// 2. String-shape fields must be non-empty (the JSDoc regex
|
|
113
|
+
// already rejects whitespace-only values, but an empty value
|
|
114
|
+
// after a colon could still slip through on a malformed line —
|
|
115
|
+
// treat that as `malformed_field`).
|
|
116
|
+
for (const name of REQUIRED_FIELDS) {
|
|
117
|
+
const value = fields.get(name);
|
|
118
|
+
if (value.length === 0) {
|
|
119
|
+
return fail("malformed_field", `Migration provenance field \`${name}\` is empty.`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// 3. Every hash field must match the sha256 shape.
|
|
123
|
+
for (const name of HASH_FIELDS) {
|
|
124
|
+
const value = fields.get(name);
|
|
125
|
+
if (!SHA256_PATTERN.test(value)) {
|
|
126
|
+
return fail("malformed_hash", `Migration provenance \`${name}\` must match \`sha256:<64 hex>\`; got "${value}".`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
success: true,
|
|
131
|
+
data: {
|
|
132
|
+
generator: fields.get("generator"),
|
|
133
|
+
generatorVersion: fields.get("generatorVersion"),
|
|
134
|
+
schemaId: fields.get("schemaId"),
|
|
135
|
+
fromVersion: fields.get("fromVersion"),
|
|
136
|
+
toVersion: fields.get("toVersion"),
|
|
137
|
+
fromIrHash: fields.get("fromIrHash"),
|
|
138
|
+
toIrHash: fields.get("toIrHash"),
|
|
139
|
+
fromSourceHash: fields.get("fromSourceHash"),
|
|
140
|
+
toSourceHash: fields.get("toSourceHash"),
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// =============================================================================
|
|
145
|
+
// Failure helper
|
|
146
|
+
// =============================================================================
|
|
147
|
+
function fail(reason, message) {
|
|
148
|
+
const issue = {
|
|
149
|
+
code: "integrity_error",
|
|
150
|
+
path: [],
|
|
151
|
+
message,
|
|
152
|
+
severity: "error",
|
|
153
|
+
metadata: { reason },
|
|
154
|
+
};
|
|
155
|
+
return { success: false, issues: [issue] };
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=parse-provenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-provenance.js","sourceRoot":"","sources":["../../../src/migrations/parse-provenance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `planMigration(opts)` — diff-aware migration planner (v0.8 Step 4).
|
|
3
|
+
*
|
|
4
|
+
* The v0.8 Round-3 lock: this primitive consumes BOTH the schema
|
|
5
|
+
* registry AND the migration registry. Without the schema registry
|
|
6
|
+
* it can't compute the diff that determines whether a missing
|
|
7
|
+
* migration is acceptable; without the migration registry it can't
|
|
8
|
+
* resolve a chain when one is required. The signature mirrors what
|
|
9
|
+
* the audit pinned in `PHASE_PLAN_v0.8.md`.
|
|
10
|
+
*
|
|
11
|
+
* Locked behavior (Round-3 contract — restated here so the
|
|
12
|
+
* implementation is easy to compare against the plan doc):
|
|
13
|
+
*
|
|
14
|
+
* 1. Resolve endpoints in `schemaRegistry`. If either is absent
|
|
15
|
+
* → `Result.failure` with `migration_missing_endpoint`. No
|
|
16
|
+
* diff is computed in this case.
|
|
17
|
+
* 2. Compute `diffNodes(from.schema.node, to.schema.node)`.
|
|
18
|
+
* `worstSeverity` is the max-severity over the change list
|
|
19
|
+
* (precedence `breaking > additive > cosmetic`; `null` when
|
|
20
|
+
* empty), exactly as `diffHandler` aggregates it in v0.7.
|
|
21
|
+
* 3. Look up the exact migration for `(schemaId, fromVersion,
|
|
22
|
+
* toVersion)` if any.
|
|
23
|
+
* 4. Dispatch on `worstSeverity`:
|
|
24
|
+
* - `null` / `"cosmetic"` → success with empty chain. If an
|
|
25
|
+
* exact migration exists for the pair, attach an
|
|
26
|
+
* `over_specified` `PlanNote`. The migration is NOT included
|
|
27
|
+
* in the chain — at this severity the diff says no
|
|
28
|
+
* transformation is needed.
|
|
29
|
+
* - `"additive"` → if an exact migration exists, include it
|
|
30
|
+
* in the chain. If not, success with empty chain plus an
|
|
31
|
+
* `additive_no_migration` note.
|
|
32
|
+
* - `"breaking"` → chain is **required**. Run DFS chain
|
|
33
|
+
* resolution over the schemaId's `from → to` adjacency map.
|
|
34
|
+
* 0 chains: `migration_not_found` (no migrations for the
|
|
35
|
+
* schemaId at all) or `migration_chain_broken` (some exist
|
|
36
|
+
* but can't bridge). 1 chain: success. 2+ chains:
|
|
37
|
+
* `migration_ambiguous_chain`.
|
|
38
|
+
*
|
|
39
|
+
* **Pure.** No `fs.*`, no `import()`, no `process.*`, no
|
|
40
|
+
* `console.*`. **Never invokes `migration.transform`** — chain
|
|
41
|
+
* resolution is structural; transform execution is v0.9+.
|
|
42
|
+
*
|
|
43
|
+
* `MigrationPlan.versionPath` always reflects the actual hop
|
|
44
|
+
* sequence: `[fromVersion, toVersion]` for empty chains;
|
|
45
|
+
* `[fromVersion, ...intermediateVersions, toVersion]` for non-empty
|
|
46
|
+
* chains derived from the chain entries.
|
|
47
|
+
*/
|
|
48
|
+
import type { MigrationPlanOpts, MigrationPlanResult } from "./types.js";
|
|
49
|
+
export declare function planMigration(opts: MigrationPlanOpts): MigrationPlanResult;
|
|
50
|
+
//# sourceMappingURL=plan-migration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-migration.d.ts","sourceRoot":"","sources":["../../../src/migrations/plan-migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAUH,OAAO,KAAK,EAGV,iBAAiB,EACjB,mBAAmB,EAGpB,MAAM,YAAY,CAAC;AAMpB,wBAAgB,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,mBAAmB,CAiG1E"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `planMigration(opts)` — diff-aware migration planner (v0.8 Step 4).
|
|
3
|
+
*
|
|
4
|
+
* The v0.8 Round-3 lock: this primitive consumes BOTH the schema
|
|
5
|
+
* registry AND the migration registry. Without the schema registry
|
|
6
|
+
* it can't compute the diff that determines whether a missing
|
|
7
|
+
* migration is acceptable; without the migration registry it can't
|
|
8
|
+
* resolve a chain when one is required. The signature mirrors what
|
|
9
|
+
* the audit pinned in `PHASE_PLAN_v0.8.md`.
|
|
10
|
+
*
|
|
11
|
+
* Locked behavior (Round-3 contract — restated here so the
|
|
12
|
+
* implementation is easy to compare against the plan doc):
|
|
13
|
+
*
|
|
14
|
+
* 1. Resolve endpoints in `schemaRegistry`. If either is absent
|
|
15
|
+
* → `Result.failure` with `migration_missing_endpoint`. No
|
|
16
|
+
* diff is computed in this case.
|
|
17
|
+
* 2. Compute `diffNodes(from.schema.node, to.schema.node)`.
|
|
18
|
+
* `worstSeverity` is the max-severity over the change list
|
|
19
|
+
* (precedence `breaking > additive > cosmetic`; `null` when
|
|
20
|
+
* empty), exactly as `diffHandler` aggregates it in v0.7.
|
|
21
|
+
* 3. Look up the exact migration for `(schemaId, fromVersion,
|
|
22
|
+
* toVersion)` if any.
|
|
23
|
+
* 4. Dispatch on `worstSeverity`:
|
|
24
|
+
* - `null` / `"cosmetic"` → success with empty chain. If an
|
|
25
|
+
* exact migration exists for the pair, attach an
|
|
26
|
+
* `over_specified` `PlanNote`. The migration is NOT included
|
|
27
|
+
* in the chain — at this severity the diff says no
|
|
28
|
+
* transformation is needed.
|
|
29
|
+
* - `"additive"` → if an exact migration exists, include it
|
|
30
|
+
* in the chain. If not, success with empty chain plus an
|
|
31
|
+
* `additive_no_migration` note.
|
|
32
|
+
* - `"breaking"` → chain is **required**. Run DFS chain
|
|
33
|
+
* resolution over the schemaId's `from → to` adjacency map.
|
|
34
|
+
* 0 chains: `migration_not_found` (no migrations for the
|
|
35
|
+
* schemaId at all) or `migration_chain_broken` (some exist
|
|
36
|
+
* but can't bridge). 1 chain: success. 2+ chains:
|
|
37
|
+
* `migration_ambiguous_chain`.
|
|
38
|
+
*
|
|
39
|
+
* **Pure.** No `fs.*`, no `import()`, no `process.*`, no
|
|
40
|
+
* `console.*`. **Never invokes `migration.transform`** — chain
|
|
41
|
+
* resolution is structural; transform execution is v0.9+.
|
|
42
|
+
*
|
|
43
|
+
* `MigrationPlan.versionPath` always reflects the actual hop
|
|
44
|
+
* sequence: `[fromVersion, toVersion]` for empty chains;
|
|
45
|
+
* `[fromVersion, ...intermediateVersions, toVersion]` for non-empty
|
|
46
|
+
* chains derived from the chain entries.
|
|
47
|
+
*/
|
|
48
|
+
import { findSchema } from "../registry/build-registry.js";
|
|
49
|
+
import { diffNodes } from "../registry/diff.js";
|
|
50
|
+
// =============================================================================
|
|
51
|
+
// Public entry
|
|
52
|
+
// =============================================================================
|
|
53
|
+
export function planMigration(opts) {
|
|
54
|
+
// 1. Resolve endpoints in the schema registry.
|
|
55
|
+
const fromEntry = findSchema(opts.schemaRegistry, opts.schemaId, opts.fromVersion);
|
|
56
|
+
const toEntry = findSchema(opts.schemaRegistry, opts.schemaId, opts.toVersion);
|
|
57
|
+
if (fromEntry === undefined || toEntry === undefined) {
|
|
58
|
+
return failure(missingEndpointIssue(opts.schemaId, opts.fromVersion, opts.toVersion, fromEntry === undefined, toEntry === undefined));
|
|
59
|
+
}
|
|
60
|
+
// 2. Compute the endpoint-to-endpoint diff and worst severity.
|
|
61
|
+
const changes = diffNodes(fromEntry.schema.node, toEntry.schema.node);
|
|
62
|
+
const worstSeverity = computeWorstSeverity(changes);
|
|
63
|
+
// 3. Look up the exact-pair migration (if any) for the
|
|
64
|
+
// over_specified / additive-with-migration branches.
|
|
65
|
+
const exact = findExactMigration(opts.migrationRegistry, opts.schemaId, opts.fromVersion, opts.toVersion);
|
|
66
|
+
// 4. Dispatch on severity.
|
|
67
|
+
if (worstSeverity === null || worstSeverity === "cosmetic") {
|
|
68
|
+
const notes = exact !== undefined ? [{ kind: "over_specified", migration: exact }] : [];
|
|
69
|
+
return success({
|
|
70
|
+
schemaId: opts.schemaId,
|
|
71
|
+
chain: [],
|
|
72
|
+
versionPath: [opts.fromVersion, opts.toVersion],
|
|
73
|
+
worstSeverity,
|
|
74
|
+
notes,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (worstSeverity === "additive") {
|
|
78
|
+
if (exact !== undefined) {
|
|
79
|
+
return success({
|
|
80
|
+
schemaId: opts.schemaId,
|
|
81
|
+
chain: [exact],
|
|
82
|
+
versionPath: [opts.fromVersion, opts.toVersion],
|
|
83
|
+
worstSeverity,
|
|
84
|
+
notes: [],
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return success({
|
|
88
|
+
schemaId: opts.schemaId,
|
|
89
|
+
chain: [],
|
|
90
|
+
versionPath: [opts.fromVersion, opts.toVersion],
|
|
91
|
+
worstSeverity,
|
|
92
|
+
notes: [{ kind: "additive_no_migration", worstSeverity }],
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// worstSeverity === "breaking" — chain is required.
|
|
96
|
+
const adjacency = opts.migrationRegistry.get(opts.schemaId);
|
|
97
|
+
const noMigrationsForSchema = adjacency === undefined || adjacency.size === 0;
|
|
98
|
+
if (noMigrationsForSchema) {
|
|
99
|
+
return failure(notFoundIssue(opts.schemaId, opts.fromVersion, opts.toVersion));
|
|
100
|
+
}
|
|
101
|
+
const chains = enumerateChains(adjacency, opts.fromVersion, opts.toVersion);
|
|
102
|
+
if (chains.length === 0) {
|
|
103
|
+
return failure(chainBrokenIssue(opts.schemaId, opts.fromVersion, opts.toVersion));
|
|
104
|
+
}
|
|
105
|
+
if (chains.length > 1) {
|
|
106
|
+
return failure(ambiguousChainIssue(opts.schemaId, opts.fromVersion, opts.toVersion, chains));
|
|
107
|
+
}
|
|
108
|
+
const chain = chains[0];
|
|
109
|
+
return success({
|
|
110
|
+
schemaId: opts.schemaId,
|
|
111
|
+
chain,
|
|
112
|
+
versionPath: versionPathFromChain(opts.fromVersion, chain),
|
|
113
|
+
worstSeverity,
|
|
114
|
+
notes: [],
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// =============================================================================
|
|
118
|
+
// Helpers — registry lookups
|
|
119
|
+
// =============================================================================
|
|
120
|
+
function findExactMigration(registry, schemaId, fromVersion, toVersion) {
|
|
121
|
+
return registry.get(schemaId)?.get(fromVersion)?.get(toVersion);
|
|
122
|
+
}
|
|
123
|
+
// =============================================================================
|
|
124
|
+
// Helpers — worstSeverity (same precedence as v0.7 diffHandler)
|
|
125
|
+
// =============================================================================
|
|
126
|
+
const SEVERITY_RANK = {
|
|
127
|
+
cosmetic: 0,
|
|
128
|
+
additive: 1,
|
|
129
|
+
breaking: 2,
|
|
130
|
+
};
|
|
131
|
+
function computeWorstSeverity(changes) {
|
|
132
|
+
if (changes.length === 0)
|
|
133
|
+
return null;
|
|
134
|
+
let worst = "cosmetic";
|
|
135
|
+
for (const c of changes) {
|
|
136
|
+
if (SEVERITY_RANK[c.severity] > SEVERITY_RANK[worst]) {
|
|
137
|
+
worst = c.severity;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return worst;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Enumerate every simple path of migration entries from `start` to
|
|
144
|
+
* `end` over the schemaId's adjacency map. "Simple" = no version
|
|
145
|
+
* is visited twice within a single chain (no cycles).
|
|
146
|
+
*
|
|
147
|
+
* v0.8 doesn't cap the number of enumerated chains — but it stops
|
|
148
|
+
* walking each path at the first revisit of any version it already
|
|
149
|
+
* entered on that path. The graph is the consumer's authored
|
|
150
|
+
* migrations, so practical depth is small.
|
|
151
|
+
*/
|
|
152
|
+
function enumerateChains(adjacency, start, end) {
|
|
153
|
+
if (start === end)
|
|
154
|
+
return [];
|
|
155
|
+
const out = [];
|
|
156
|
+
const visited = new Set([start]);
|
|
157
|
+
const chain = [];
|
|
158
|
+
dfs(adjacency, start, end, visited, chain, out);
|
|
159
|
+
return out;
|
|
160
|
+
}
|
|
161
|
+
function dfs(adjacency, current, end, visited, chain, out) {
|
|
162
|
+
const outgoing = adjacency.get(current);
|
|
163
|
+
if (outgoing === undefined)
|
|
164
|
+
return;
|
|
165
|
+
for (const [toVer, entry] of outgoing) {
|
|
166
|
+
if (visited.has(toVer))
|
|
167
|
+
continue;
|
|
168
|
+
chain.push(entry);
|
|
169
|
+
if (toVer === end) {
|
|
170
|
+
out.push([...chain]);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
visited.add(toVer);
|
|
174
|
+
dfs(adjacency, toVer, end, visited, chain, out);
|
|
175
|
+
visited.delete(toVer);
|
|
176
|
+
}
|
|
177
|
+
chain.pop();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function versionPathFromChain(fromVersion, chain) {
|
|
181
|
+
if (chain.length === 0)
|
|
182
|
+
return [fromVersion, fromVersion];
|
|
183
|
+
const path = [fromVersion];
|
|
184
|
+
for (const entry of chain)
|
|
185
|
+
path.push(entry.toVersion);
|
|
186
|
+
return path;
|
|
187
|
+
}
|
|
188
|
+
// =============================================================================
|
|
189
|
+
// Result + Issue helpers
|
|
190
|
+
// =============================================================================
|
|
191
|
+
function success(data) {
|
|
192
|
+
return { success: true, data };
|
|
193
|
+
}
|
|
194
|
+
function failure(issue) {
|
|
195
|
+
return { success: false, issues: [issue] };
|
|
196
|
+
}
|
|
197
|
+
function missingEndpointIssue(schemaId, fromVersion, toVersion, fromMissing, toMissing) {
|
|
198
|
+
const missing = [];
|
|
199
|
+
if (fromMissing)
|
|
200
|
+
missing.push(`from=${fromVersion}`);
|
|
201
|
+
if (toMissing)
|
|
202
|
+
missing.push(`to=${toVersion}`);
|
|
203
|
+
return {
|
|
204
|
+
code: "migration_missing_endpoint",
|
|
205
|
+
path: [],
|
|
206
|
+
message: `Cannot plan migration for \`${schemaId}\`: ` +
|
|
207
|
+
`${missing.join(", ")} not in the schema registry.`,
|
|
208
|
+
severity: "error",
|
|
209
|
+
metadata: {
|
|
210
|
+
schemaId,
|
|
211
|
+
fromVersion,
|
|
212
|
+
toVersion,
|
|
213
|
+
missing: missing.map((s) => s.split("=")[0]),
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function notFoundIssue(schemaId, fromVersion, toVersion) {
|
|
218
|
+
return {
|
|
219
|
+
code: "migration_not_found",
|
|
220
|
+
path: [],
|
|
221
|
+
message: `Breaking transition for \`${schemaId}\` requires a migration; ` +
|
|
222
|
+
`no migrations are registered for this schemaId.`,
|
|
223
|
+
severity: "error",
|
|
224
|
+
metadata: { schemaId, fromVersion, toVersion },
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function chainBrokenIssue(schemaId, fromVersion, toVersion) {
|
|
228
|
+
return {
|
|
229
|
+
code: "migration_chain_broken",
|
|
230
|
+
path: [],
|
|
231
|
+
message: `Migrations exist for \`${schemaId}\` but no chain bridges ` +
|
|
232
|
+
`${fromVersion} → ${toVersion}.`,
|
|
233
|
+
severity: "error",
|
|
234
|
+
metadata: { schemaId, fromVersion, toVersion },
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function ambiguousChainIssue(schemaId, fromVersion, toVersion, chains) {
|
|
238
|
+
return {
|
|
239
|
+
code: "migration_ambiguous_chain",
|
|
240
|
+
path: [],
|
|
241
|
+
message: `Multiple distinct migration chains bridge \`${schemaId}\` ` +
|
|
242
|
+
`${fromVersion} → ${toVersion}; the planner refuses to pick. ` +
|
|
243
|
+
`Remove one or constrain the registry.`,
|
|
244
|
+
severity: "error",
|
|
245
|
+
metadata: {
|
|
246
|
+
schemaId,
|
|
247
|
+
fromVersion,
|
|
248
|
+
toVersion,
|
|
249
|
+
chainCount: chains.length,
|
|
250
|
+
chainSummaries: chains.map((chain) => chain
|
|
251
|
+
.map((entry) => `${entry.fromVersion}→${entry.toVersion}`)
|
|
252
|
+
.join(", ")),
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=plan-migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-migration.js","sourceRoot":"","sources":["../../../src/migrations/plan-migration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `stubMigration(opts)` — pure migration-stub generator (v0.8 Step 6).
|
|
3
|
+
*
|
|
4
|
+
* Produces a `MigrationStub` payload — a `suggestedPath` and the
|
|
5
|
+
* full file `content` for a new `*.migration.ts` file. The CLI is
|
|
6
|
+
* responsible for actually writing the file; this primitive is
|
|
7
|
+
* pure (no `fs.*`, no `import()`, no `process.*`, no `console.*`).
|
|
8
|
+
*
|
|
9
|
+
* The content follows the locked migration shape (Decision #5 +
|
|
10
|
+
* Decision #6):
|
|
11
|
+
*
|
|
12
|
+
* - JSDoc provenance header on top, generated by this function.
|
|
13
|
+
* - `import type { Migration } from "@nekostack/schema/cli";`
|
|
14
|
+
* (NOT root — Decision #6 keeps the v0.8 surface package-internal).
|
|
15
|
+
* - A `const migration: Migration<schemaId, from, to> = { ... }`
|
|
16
|
+
* with a skeleton `transform` that throws "Not yet implemented".
|
|
17
|
+
* Authors edit the body; v0.8 never invokes `transform`.
|
|
18
|
+
* - `export default migration;` so `buildMigrationRegistry` /
|
|
19
|
+
* `verifyMigrationProvenance` can find it via the
|
|
20
|
+
* `MigrationSourceEntry.migration` field.
|
|
21
|
+
*
|
|
22
|
+
* `suggestedPath` follows the locked path convention
|
|
23
|
+
* (Decision #5):
|
|
24
|
+
*
|
|
25
|
+
* <schema-dir>/migrations/<basename>.<from-slug>-to-<to-slug>.migration.ts
|
|
26
|
+
*
|
|
27
|
+
* with the slug rule reused verbatim from `v0.7 src/registry/handlers/generate.ts`:
|
|
28
|
+
* `lowercase → non-alphanumeric runs collapse to "-" → trim`.
|
|
29
|
+
*
|
|
30
|
+
* Reusing v0.7's `slugify` shape means one slug rule across the
|
|
31
|
+
* whole package — and it handles prerelease/build version markers
|
|
32
|
+
* (`1.0.0-beta.1`, `2.0.0+build.5`) cleanly.
|
|
33
|
+
*
|
|
34
|
+
* Failure path: if either operand version is absent from the schema
|
|
35
|
+
* registry → `Result.failure` with `migration_missing_endpoint`
|
|
36
|
+
* (same code as Step 4's planner uses for the same condition).
|
|
37
|
+
*/
|
|
38
|
+
import type { MigrationStubOpts, MigrationStubResult } from "./types.js";
|
|
39
|
+
export declare function stubMigration(opts: MigrationStubOpts): MigrationStubResult;
|
|
40
|
+
/**
|
|
41
|
+
* Translate a schema's `sourcePath` plus a version pair into the
|
|
42
|
+
* locked migration-file path:
|
|
43
|
+
*
|
|
44
|
+
* <schema-dir>/migrations/<basename>.<from-slug>-to-<to-slug>.migration.ts
|
|
45
|
+
*
|
|
46
|
+
* `basename` strips a `.schema.{ts,js,mts,cts}` suffix when present;
|
|
47
|
+
* falls back to "filename minus last extension" otherwise. Forward
|
|
48
|
+
* slashes are canonical even on Windows — the CLI normalizes back
|
|
49
|
+
* to platform separators on write.
|
|
50
|
+
*
|
|
51
|
+
* Exported so the CLI's `stub` verb can advertise the same path
|
|
52
|
+
* without re-deriving the rule.
|
|
53
|
+
*/
|
|
54
|
+
export declare function suggestedMigrationPathFor(sourcePath: string, fromVersion: string, toVersion: string): string;
|
|
55
|
+
//# sourceMappingURL=stub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub.d.ts","sourceRoot":"","sources":["../../../src/migrations/stub.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAKH,OAAO,KAAK,EAEV,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAMpB,wBAAgB,aAAa,CAC3B,IAAI,EAAE,iBAAiB,GACtB,mBAAmB,CAuCrB;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,MAAM,CAUR"}
|