@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,201 @@
|
|
|
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 { findSchema } from "../registry/build-registry.js";
|
|
39
|
+
import { GENERATOR_VERSION } from "../generators/version.js";
|
|
40
|
+
// =============================================================================
|
|
41
|
+
// Public entry
|
|
42
|
+
// =============================================================================
|
|
43
|
+
export function stubMigration(opts) {
|
|
44
|
+
const fromEntry = findSchema(opts.schemaRegistry, opts.schemaId, opts.fromVersion);
|
|
45
|
+
const toEntry = findSchema(opts.schemaRegistry, opts.schemaId, opts.toVersion);
|
|
46
|
+
if (fromEntry === undefined || toEntry === undefined) {
|
|
47
|
+
return failure(missingEndpointIssue(opts.schemaId, opts.fromVersion, opts.toVersion, fromEntry === undefined, toEntry === undefined));
|
|
48
|
+
}
|
|
49
|
+
const suggestedPath = suggestedMigrationPathFor(fromEntry.sourcePath, opts.fromVersion, opts.toVersion);
|
|
50
|
+
const content = renderStubContent({
|
|
51
|
+
schemaId: opts.schemaId,
|
|
52
|
+
fromVersion: opts.fromVersion,
|
|
53
|
+
toVersion: opts.toVersion,
|
|
54
|
+
fromIrHash: fromEntry.irHash,
|
|
55
|
+
toIrHash: toEntry.irHash,
|
|
56
|
+
fromSourceHash: fromEntry.sourceHash,
|
|
57
|
+
toSourceHash: toEntry.sourceHash,
|
|
58
|
+
});
|
|
59
|
+
const stub = {
|
|
60
|
+
schemaId: opts.schemaId,
|
|
61
|
+
fromVersion: opts.fromVersion,
|
|
62
|
+
toVersion: opts.toVersion,
|
|
63
|
+
suggestedPath,
|
|
64
|
+
content,
|
|
65
|
+
};
|
|
66
|
+
return { success: true, data: stub };
|
|
67
|
+
}
|
|
68
|
+
// =============================================================================
|
|
69
|
+
// Path convention (Decision #5)
|
|
70
|
+
// =============================================================================
|
|
71
|
+
/**
|
|
72
|
+
* Translate a schema's `sourcePath` plus a version pair into the
|
|
73
|
+
* locked migration-file path:
|
|
74
|
+
*
|
|
75
|
+
* <schema-dir>/migrations/<basename>.<from-slug>-to-<to-slug>.migration.ts
|
|
76
|
+
*
|
|
77
|
+
* `basename` strips a `.schema.{ts,js,mts,cts}` suffix when present;
|
|
78
|
+
* falls back to "filename minus last extension" otherwise. Forward
|
|
79
|
+
* slashes are canonical even on Windows — the CLI normalizes back
|
|
80
|
+
* to platform separators on write.
|
|
81
|
+
*
|
|
82
|
+
* Exported so the CLI's `stub` verb can advertise the same path
|
|
83
|
+
* without re-deriving the rule.
|
|
84
|
+
*/
|
|
85
|
+
export function suggestedMigrationPathFor(sourcePath, fromVersion, toVersion) {
|
|
86
|
+
const normalized = sourcePath.replace(/\\/g, "/");
|
|
87
|
+
const lastSlash = normalized.lastIndexOf("/");
|
|
88
|
+
const dir = lastSlash >= 0 ? normalized.slice(0, lastSlash) : "";
|
|
89
|
+
const filename = lastSlash >= 0 ? normalized.slice(lastSlash + 1) : normalized;
|
|
90
|
+
const basename = basenameOf(filename);
|
|
91
|
+
const stem = `${basename}.${slugify(fromVersion)}-to-${slugify(toVersion)}`;
|
|
92
|
+
const migrationsDir = dir === "" ? "migrations" : `${dir}/migrations`;
|
|
93
|
+
return `${migrationsDir}/${stem}.migration.ts`;
|
|
94
|
+
}
|
|
95
|
+
function basenameOf(filename) {
|
|
96
|
+
const schemaMatch = filename.match(/^(.+?)\.schema\.(ts|js|mts|cts)$/);
|
|
97
|
+
if (schemaMatch)
|
|
98
|
+
return schemaMatch[1];
|
|
99
|
+
const lastDot = filename.lastIndexOf(".");
|
|
100
|
+
return lastDot > 0 ? filename.slice(0, lastDot) : filename;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Same shape as v0.7's `src/registry/handlers/generate.ts` slugify().
|
|
104
|
+
* One slug rule across the whole package — Round-2 lock.
|
|
105
|
+
*/
|
|
106
|
+
function slugify(s) {
|
|
107
|
+
return s
|
|
108
|
+
.toLowerCase()
|
|
109
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
110
|
+
.replace(/^-+|-+$/g, "");
|
|
111
|
+
}
|
|
112
|
+
function renderStubContent(input) {
|
|
113
|
+
// Pad keys to 16 columns so the value column lines up visually,
|
|
114
|
+
// matching the v0.7 generator-header convention. The parser is
|
|
115
|
+
// whitespace-tolerant so consumers may edit the alignment without
|
|
116
|
+
// breaking provenance reads.
|
|
117
|
+
const header = renderHeader({
|
|
118
|
+
schemaId: input.schemaId,
|
|
119
|
+
fromVersion: input.fromVersion,
|
|
120
|
+
toVersion: input.toVersion,
|
|
121
|
+
fromIrHash: input.fromIrHash,
|
|
122
|
+
toIrHash: input.toIrHash,
|
|
123
|
+
fromSourceHash: input.fromSourceHash,
|
|
124
|
+
toSourceHash: input.toSourceHash,
|
|
125
|
+
generator: "neko-schema-migrate-stub",
|
|
126
|
+
generatorVersion: GENERATOR_VERSION,
|
|
127
|
+
});
|
|
128
|
+
const literalSchemaId = JSON.stringify(input.schemaId);
|
|
129
|
+
const literalFrom = JSON.stringify(input.fromVersion);
|
|
130
|
+
const literalTo = JSON.stringify(input.toVersion);
|
|
131
|
+
return `${header}
|
|
132
|
+
import type { Migration } from "@nekostack/schema/cli";
|
|
133
|
+
|
|
134
|
+
const migration: Migration<${literalSchemaId}, ${literalFrom}, ${literalTo}> = {
|
|
135
|
+
schemaId: ${literalSchemaId},
|
|
136
|
+
from: ${literalFrom},
|
|
137
|
+
to: ${literalTo},
|
|
138
|
+
transform(input) {
|
|
139
|
+
// Author fills this in.
|
|
140
|
+
throw new Error("Not yet implemented");
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export default migration;
|
|
145
|
+
`;
|
|
146
|
+
}
|
|
147
|
+
function renderHeader(fields) {
|
|
148
|
+
const keys = [
|
|
149
|
+
"schemaId",
|
|
150
|
+
"fromVersion",
|
|
151
|
+
"toVersion",
|
|
152
|
+
"fromIrHash",
|
|
153
|
+
"toIrHash",
|
|
154
|
+
"fromSourceHash",
|
|
155
|
+
"toSourceHash",
|
|
156
|
+
"generator",
|
|
157
|
+
"generatorVersion",
|
|
158
|
+
];
|
|
159
|
+
const colon = ":";
|
|
160
|
+
const targetWidth = Math.max(...keys.map((k) => k.length + colon.length));
|
|
161
|
+
const lines = [
|
|
162
|
+
"/**",
|
|
163
|
+
" * @migration by @nekostack/schema",
|
|
164
|
+
...keys.map((k) => {
|
|
165
|
+
const label = `${k}${colon}`;
|
|
166
|
+
return ` * ${label.padEnd(targetWidth + 1)}${fields[k]}`;
|
|
167
|
+
}),
|
|
168
|
+
" *",
|
|
169
|
+
" * DO NOT REMOVE THE HEADER. Authors EDIT THE BODY.",
|
|
170
|
+
" */",
|
|
171
|
+
];
|
|
172
|
+
return lines.join("\n");
|
|
173
|
+
}
|
|
174
|
+
// =============================================================================
|
|
175
|
+
// Failure helpers
|
|
176
|
+
// =============================================================================
|
|
177
|
+
function failure(issue) {
|
|
178
|
+
return { success: false, issues: [issue] };
|
|
179
|
+
}
|
|
180
|
+
function missingEndpointIssue(schemaId, fromVersion, toVersion, fromMissing, toMissing) {
|
|
181
|
+
const missing = [];
|
|
182
|
+
if (fromMissing)
|
|
183
|
+
missing.push("from");
|
|
184
|
+
if (toMissing)
|
|
185
|
+
missing.push("to");
|
|
186
|
+
return {
|
|
187
|
+
code: "migration_missing_endpoint",
|
|
188
|
+
path: [],
|
|
189
|
+
message: `Cannot stub migration for \`${schemaId}\`: ` +
|
|
190
|
+
`${missing.join(", ")} version not in the schema registry ` +
|
|
191
|
+
`(from=${fromVersion}, to=${toVersion}).`,
|
|
192
|
+
severity: "error",
|
|
193
|
+
metadata: {
|
|
194
|
+
schemaId,
|
|
195
|
+
fromVersion,
|
|
196
|
+
toVersion,
|
|
197
|
+
missing,
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=stub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub.js","sourceRoot":"","sources":["../../../src/migrations/stub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the v0.8 schema-side migration surface.
|
|
3
|
+
*
|
|
4
|
+
* This module is **types only** — no functions, no constants beyond
|
|
5
|
+
* what TypeScript requires for the type definitions themselves. All
|
|
6
|
+
* runtime behavior (migration registry construction, chain planning,
|
|
7
|
+
* provenance verification, stub generation) lives in the sibling
|
|
8
|
+
* modules that import these types.
|
|
9
|
+
*
|
|
10
|
+
* Boundary recap (Master plan Decision #1, continued from v0.6 / v0.7):
|
|
11
|
+
* - `@nekostack/schema` is **pure** — no `fs.*`, no `import()`, no
|
|
12
|
+
* `process.*`, no `console.*`. Takes data, returns data.
|
|
13
|
+
* - `@nekostack/cli` is the **filesystem shell** — walks
|
|
14
|
+
* `*.migration.ts` files, loads them via `tsx`, reads source bytes,
|
|
15
|
+
* writes stub files, owns stdout / stderr / exit codes.
|
|
16
|
+
*
|
|
17
|
+
* Re-exported from the package-internal integration subpath
|
|
18
|
+
* `@nekostack/schema/cli` (Master plan Decision #10) in a later
|
|
19
|
+
* sequencing step. Root `@nekostack/schema` does NOT expose these
|
|
20
|
+
* names.
|
|
21
|
+
*
|
|
22
|
+
* **Hard-locked v0.8 boundary**: nothing in this file mentions
|
|
23
|
+
* `apply`. Migration execution is deferred to v0.9+. The `transform`
|
|
24
|
+
* function on `Migration<...>` exists so the file shape is stable
|
|
25
|
+
* for the eventual apply phase, but v0.8 never invokes it.
|
|
26
|
+
*/
|
|
27
|
+
import type { Result } from "../errors/issue.js";
|
|
28
|
+
import type { DiffSeverity } from "../registry/types.js";
|
|
29
|
+
import type { Registry } from "../registry/types.js";
|
|
30
|
+
/**
|
|
31
|
+
* The default export of a `*.migration.ts` file.
|
|
32
|
+
*
|
|
33
|
+
* The five type parameters cascade from coarsest to finest:
|
|
34
|
+
*
|
|
35
|
+
* - `SchemaId` — string literal of the schema this migration
|
|
36
|
+
* targets (e.g. `"com.x.User"`).
|
|
37
|
+
* - `FromVersion` — string literal of the source version
|
|
38
|
+
* (e.g. `"1.0.0"`).
|
|
39
|
+
* - `ToVersion` — string literal of the destination version.
|
|
40
|
+
* - `Input` — the static type of `s.output<FromSchema>`.
|
|
41
|
+
* Defaults to `unknown` so loosely-typed
|
|
42
|
+
* migrations still compile; consumers who want
|
|
43
|
+
* static safety pass the inferred type here.
|
|
44
|
+
* - `Output` — the static type of `s.output<ToSchema>`.
|
|
45
|
+
* Defaults to `unknown`.
|
|
46
|
+
*
|
|
47
|
+
* v0.8 NEVER calls `transform`. The function signature exists so
|
|
48
|
+
* authors write a v0.9+-ready migration file in v0.8, but the
|
|
49
|
+
* planner / verifier / stub primitives only inspect provenance,
|
|
50
|
+
* not behavior.
|
|
51
|
+
*/
|
|
52
|
+
export interface Migration<SchemaId extends string = string, FromVersion extends string = string, ToVersion extends string = string, Input = unknown, Output = unknown> {
|
|
53
|
+
readonly schemaId: SchemaId;
|
|
54
|
+
readonly from: FromVersion;
|
|
55
|
+
readonly to: ToVersion;
|
|
56
|
+
/**
|
|
57
|
+
* The data transformation. **NEVER invoked by v0.8.** Authors
|
|
58
|
+
* write the body; v0.9+ runtime apply will execute it.
|
|
59
|
+
*/
|
|
60
|
+
readonly transform: (input: Input) => Output;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Widest legal `Migration`. Useful as a registry value type and as
|
|
64
|
+
* the loaded-export shape of `MigrationSourceEntry.migration`.
|
|
65
|
+
*/
|
|
66
|
+
export type AnyMigration = Migration<string, string, string, unknown, unknown>;
|
|
67
|
+
/**
|
|
68
|
+
* One discovered `*.migration.ts` source file, after the CLI has
|
|
69
|
+
* read its bytes and dynamic-imported the module via `tsx`.
|
|
70
|
+
*
|
|
71
|
+
* `migration` is the module's default export. The CLI is responsible
|
|
72
|
+
* for asserting the export shape (`{ schemaId, from, to, transform }`)
|
|
73
|
+
* before constructing this entry; the schema-side primitives assume
|
|
74
|
+
* the field is a valid `AnyMigration`.
|
|
75
|
+
*
|
|
76
|
+
* Mirrors the v0.7 `RegistrySourceEntry` shape so the walker
|
|
77
|
+
* pipeline composes cleanly.
|
|
78
|
+
*/
|
|
79
|
+
export interface MigrationSourceEntry {
|
|
80
|
+
readonly sourcePath: string;
|
|
81
|
+
readonly sourceText: string;
|
|
82
|
+
readonly migration: AnyMigration;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* One indexed migration. Identity is the `(schemaId, fromVersion,
|
|
86
|
+
* toVersion)` triple per Decision #8. The four hash fields are
|
|
87
|
+
* **provenance binding**, not identity — they let the verifier
|
|
88
|
+
* detect when the migration was authored against a schema state
|
|
89
|
+
* that has since changed.
|
|
90
|
+
*
|
|
91
|
+
* `fromIrHash` / `toIrHash` come from the v0.2-format provenance
|
|
92
|
+
* header on the migration source file; `fromSourceHash` /
|
|
93
|
+
* `toSourceHash` come from the same header (v0.8 always emits them
|
|
94
|
+
* via the stub generator).
|
|
95
|
+
*/
|
|
96
|
+
export interface MigrationEntry {
|
|
97
|
+
readonly schemaId: string;
|
|
98
|
+
readonly fromVersion: string;
|
|
99
|
+
readonly toVersion: string;
|
|
100
|
+
readonly fromIrHash: `sha256:${string}`;
|
|
101
|
+
readonly toIrHash: `sha256:${string}`;
|
|
102
|
+
readonly fromSourceHash: `sha256:${string}`;
|
|
103
|
+
readonly toSourceHash: `sha256:${string}`;
|
|
104
|
+
readonly sourcePath: string;
|
|
105
|
+
readonly migration: AnyMigration;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Three-level map: outer key is `schemaId`, middle key is the
|
|
109
|
+
* `fromVersion`, inner key is the `toVersion`. The shape supports
|
|
110
|
+
* two access patterns the planner needs:
|
|
111
|
+
*
|
|
112
|
+
* - **Exact lookup** by triple — `reg.get(id)?.get(from)?.get(to)`.
|
|
113
|
+
* - **All outgoing edges from a fromVersion** — `reg.get(id)?.get(from)`
|
|
114
|
+
* yields the full `Map<toVersion, MigrationEntry>`, which is the
|
|
115
|
+
* set of edges BFS needs to expand a node.
|
|
116
|
+
*
|
|
117
|
+
* `buildMigrationRegistry` is the only legitimate producer.
|
|
118
|
+
*/
|
|
119
|
+
export type MigrationRegistry = ReadonlyMap<string, ReadonlyMap<string, ReadonlyMap<string, MigrationEntry>>>;
|
|
120
|
+
/**
|
|
121
|
+
* Free-form annotation on a `MigrationPlan`. Documents *why* the
|
|
122
|
+
* chain came out the way it did when the result isn't a simple
|
|
123
|
+
* "found the chain":
|
|
124
|
+
*
|
|
125
|
+
* - `over_specified` — the diff classifier said no migration is
|
|
126
|
+
* required (`worstSeverity` is `null` or `cosmetic`), but a
|
|
127
|
+
* migration is registered for the pair anyway. The plan still
|
|
128
|
+
* succeeds with an empty chain; this note records the
|
|
129
|
+
* discrepancy for the CLI to surface.
|
|
130
|
+
* - `additive_no_migration` — `worstSeverity` is `additive` and no
|
|
131
|
+
* migration is registered. The plan succeeds with an empty chain;
|
|
132
|
+
* this note records that a consumer review may be desired.
|
|
133
|
+
*/
|
|
134
|
+
export type PlanNote = {
|
|
135
|
+
readonly kind: "over_specified";
|
|
136
|
+
readonly migration: MigrationEntry;
|
|
137
|
+
} | {
|
|
138
|
+
readonly kind: "additive_no_migration";
|
|
139
|
+
readonly worstSeverity: DiffSeverity;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* The output of `planMigration`. Always carries the resolved
|
|
143
|
+
* `versionPath` and `worstSeverity` so consumers can see the diff
|
|
144
|
+
* that drove the decision, even when the chain is empty.
|
|
145
|
+
*
|
|
146
|
+
* Decision #10 maps `worstSeverity` to the chain requirement:
|
|
147
|
+
*
|
|
148
|
+
* - `null` / `"cosmetic"` — chain is empty.
|
|
149
|
+
* - `"additive"` — chain is empty unless a migration is
|
|
150
|
+
* registered for the pair.
|
|
151
|
+
* - `"breaking"` — chain is required; failure paths emit
|
|
152
|
+
* `migration_not_found` /
|
|
153
|
+
* `migration_chain_broken` /
|
|
154
|
+
* `migration_ambiguous_chain` on the
|
|
155
|
+
* `Result.failure` branch.
|
|
156
|
+
*
|
|
157
|
+
* `versionPath` always includes both endpoints. For an empty chain
|
|
158
|
+
* the array is `[fromVersion, toVersion]`.
|
|
159
|
+
*/
|
|
160
|
+
export interface MigrationPlan {
|
|
161
|
+
readonly schemaId: string;
|
|
162
|
+
readonly chain: readonly MigrationEntry[];
|
|
163
|
+
readonly versionPath: readonly string[];
|
|
164
|
+
readonly worstSeverity: DiffSeverity | null;
|
|
165
|
+
readonly notes: readonly PlanNote[];
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Per-migration outcome of the two-hash provenance check, mirroring
|
|
169
|
+
* the v0.7 `FreshnessVerdict` shape for artifacts. The four-value
|
|
170
|
+
* mapping is Decision #9 of the v0.8 plan:
|
|
171
|
+
*
|
|
172
|
+
* - `bound` — both `irHash` and `sourceHash` match at
|
|
173
|
+
* both endpoints. Migration is current.
|
|
174
|
+
* - `cosmetic_drift` — `irHash` matches at both endpoints, but at
|
|
175
|
+
* least one `sourceHash` differs. Source was
|
|
176
|
+
* edited without semantic effect. CLI warns
|
|
177
|
+
* on stderr; exit code stays `SUCCESS`.
|
|
178
|
+
* - `drift` — at least one endpoint's `irHash` differs
|
|
179
|
+
* from the schema registry. The migration
|
|
180
|
+
* was authored against a schema state that
|
|
181
|
+
* has since changed semantically. CLI exits
|
|
182
|
+
* `LOGICAL_FAILURE`.
|
|
183
|
+
* - `missing_endpoint` — one or both versions are not in the schema
|
|
184
|
+
* registry. Indicates a stale migration or a
|
|
185
|
+
* deleted schema version. CLI exits
|
|
186
|
+
* `LOGICAL_FAILURE`.
|
|
187
|
+
*
|
|
188
|
+
* The discriminated-union shape mirrors v0.7's `FreshnessVerdict`
|
|
189
|
+
* so downstream tooling can pattern-match on `status` uniformly.
|
|
190
|
+
*/
|
|
191
|
+
export type MigrationVerdict = {
|
|
192
|
+
readonly status: "bound";
|
|
193
|
+
readonly sourcePath: string;
|
|
194
|
+
readonly schemaId: string;
|
|
195
|
+
readonly fromVersion: string;
|
|
196
|
+
readonly toVersion: string;
|
|
197
|
+
} | {
|
|
198
|
+
readonly status: "cosmetic_drift";
|
|
199
|
+
readonly sourcePath: string;
|
|
200
|
+
readonly schemaId: string;
|
|
201
|
+
readonly fromVersion: string;
|
|
202
|
+
readonly toVersion: string;
|
|
203
|
+
} | {
|
|
204
|
+
readonly status: "drift";
|
|
205
|
+
readonly sourcePath: string;
|
|
206
|
+
readonly schemaId: string;
|
|
207
|
+
readonly fromVersion: string;
|
|
208
|
+
readonly toVersion: string;
|
|
209
|
+
} | {
|
|
210
|
+
readonly status: "missing_endpoint";
|
|
211
|
+
readonly sourcePath: string;
|
|
212
|
+
readonly schemaId: string;
|
|
213
|
+
readonly fromVersion: string;
|
|
214
|
+
readonly toVersion: string;
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* Cumulative output of `verifyMigrationProvenance`. `verdicts` is
|
|
218
|
+
* one entry per registered migration in input order. `summary`
|
|
219
|
+
* is the per-status tally for header rendering.
|
|
220
|
+
*/
|
|
221
|
+
export interface VerificationResult {
|
|
222
|
+
readonly verdicts: readonly MigrationVerdict[];
|
|
223
|
+
readonly summary: {
|
|
224
|
+
readonly bound: number;
|
|
225
|
+
readonly cosmetic_drift: number;
|
|
226
|
+
readonly drift: number;
|
|
227
|
+
readonly missing_endpoint: number;
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* `stubMigration` produces a file *content* string and a
|
|
232
|
+
* `suggestedPath`. The CLI is responsible for the filesystem write;
|
|
233
|
+
* this primitive is pure.
|
|
234
|
+
*
|
|
235
|
+
* Mirrors `GeneratedArtifact` from v0.7 — same separation between
|
|
236
|
+
* planner output and CLI write step.
|
|
237
|
+
*/
|
|
238
|
+
export interface MigrationStub {
|
|
239
|
+
readonly schemaId: string;
|
|
240
|
+
readonly fromVersion: string;
|
|
241
|
+
readonly toVersion: string;
|
|
242
|
+
readonly suggestedPath: string;
|
|
243
|
+
readonly content: string;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* `listMigrationsHandler({ migrationRegistry })` — enumerate every
|
|
247
|
+
* `MigrationEntry`. Deterministic ordering is the handler's
|
|
248
|
+
* responsibility (sort by schemaId, then by fromVersion, then by
|
|
249
|
+
* toVersion).
|
|
250
|
+
*/
|
|
251
|
+
export interface MigrationListOpts {
|
|
252
|
+
readonly migrationRegistry: MigrationRegistry;
|
|
253
|
+
}
|
|
254
|
+
export type MigrationListResult = Result<{
|
|
255
|
+
readonly entries: readonly MigrationEntry[];
|
|
256
|
+
}>;
|
|
257
|
+
/**
|
|
258
|
+
* `planMigrationHandler({ schemaRegistry, migrationRegistry, ... })`
|
|
259
|
+
* — the diff-aware planner (Round-3 amendment). Receives BOTH
|
|
260
|
+
* registries plus the operand triple. Resolves endpoints in
|
|
261
|
+
* `schemaRegistry`, computes `worstSeverity` via `diffNodes`,
|
|
262
|
+
* severity-gates the chain requirement.
|
|
263
|
+
*/
|
|
264
|
+
export interface MigrationPlanOpts {
|
|
265
|
+
readonly schemaRegistry: Registry;
|
|
266
|
+
readonly migrationRegistry: MigrationRegistry;
|
|
267
|
+
readonly schemaId: string;
|
|
268
|
+
readonly fromVersion: string;
|
|
269
|
+
readonly toVersion: string;
|
|
270
|
+
}
|
|
271
|
+
export type MigrationPlanResult = Result<MigrationPlan>;
|
|
272
|
+
/**
|
|
273
|
+
* `verifyMigrationsHandler({ schemaRegistry, migrationRegistry })`
|
|
274
|
+
* — provenance verification for every registered migration. Receives
|
|
275
|
+
* BOTH registries so `findSchema(schemaRegistry, ...)` can supply the
|
|
276
|
+
* current `irHash` / `sourceHash` for comparison against each
|
|
277
|
+
* migration's recorded values.
|
|
278
|
+
*/
|
|
279
|
+
export interface MigrationVerifyOpts {
|
|
280
|
+
readonly schemaRegistry: Registry;
|
|
281
|
+
readonly migrationRegistry: MigrationRegistry;
|
|
282
|
+
}
|
|
283
|
+
export type MigrationVerifyResult = Result<VerificationResult>;
|
|
284
|
+
/**
|
|
285
|
+
* `stubMigrationHandler({ schemaRegistry, schemaId, fromVersion,
|
|
286
|
+
* toVersion })` — generate stub content. Does NOT consume a
|
|
287
|
+
* migration registry; the stub is brand new. Endpoint hashes come
|
|
288
|
+
* from `schemaRegistry` via `findSchema`.
|
|
289
|
+
*/
|
|
290
|
+
export interface MigrationStubOpts {
|
|
291
|
+
readonly schemaRegistry: Registry;
|
|
292
|
+
readonly schemaId: string;
|
|
293
|
+
readonly fromVersion: string;
|
|
294
|
+
readonly toVersion: string;
|
|
295
|
+
}
|
|
296
|
+
export type MigrationStubResult = Result<MigrationStub>;
|
|
297
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/migrations/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the v0.8 schema-side migration surface.
|
|
3
|
+
*
|
|
4
|
+
* This module is **types only** — no functions, no constants beyond
|
|
5
|
+
* what TypeScript requires for the type definitions themselves. All
|
|
6
|
+
* runtime behavior (migration registry construction, chain planning,
|
|
7
|
+
* provenance verification, stub generation) lives in the sibling
|
|
8
|
+
* modules that import these types.
|
|
9
|
+
*
|
|
10
|
+
* Boundary recap (Master plan Decision #1, continued from v0.6 / v0.7):
|
|
11
|
+
* - `@nekostack/schema` is **pure** — no `fs.*`, no `import()`, no
|
|
12
|
+
* `process.*`, no `console.*`. Takes data, returns data.
|
|
13
|
+
* - `@nekostack/cli` is the **filesystem shell** — walks
|
|
14
|
+
* `*.migration.ts` files, loads them via `tsx`, reads source bytes,
|
|
15
|
+
* writes stub files, owns stdout / stderr / exit codes.
|
|
16
|
+
*
|
|
17
|
+
* Re-exported from the package-internal integration subpath
|
|
18
|
+
* `@nekostack/schema/cli` (Master plan Decision #10) in a later
|
|
19
|
+
* sequencing step. Root `@nekostack/schema` does NOT expose these
|
|
20
|
+
* names.
|
|
21
|
+
*
|
|
22
|
+
* **Hard-locked v0.8 boundary**: nothing in this file mentions
|
|
23
|
+
* `apply`. Migration execution is deferred to v0.9+. The `transform`
|
|
24
|
+
* function on `Migration<...>` exists so the file shape is stable
|
|
25
|
+
* for the eventual apply phase, but v0.8 never invokes it.
|
|
26
|
+
*/
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/migrations/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG"}
|
|
@@ -0,0 +1,46 @@
|
|
|
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 type { MigrationVerifyOpts, MigrationVerifyResult } from "./types.js";
|
|
45
|
+
export declare function verifyMigrationProvenance(opts: MigrationVerifyOpts): MigrationVerifyResult;
|
|
46
|
+
//# sourceMappingURL=verify-provenance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-provenance.d.ts","sourceRoot":"","sources":["../../../src/migrations/verify-provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAIH,OAAO,KAAK,EAIV,mBAAmB,EACnB,qBAAqB,EAEtB,MAAM,YAAY,CAAC;AAMpB,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,mBAAmB,GACxB,qBAAqB,CAwBvB"}
|