@prisma-next/migration-tools 0.3.0-dev.99 → 0.4.0-dev.1
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/README.md +10 -8
- package/dist/constants-DARNL_LD.mjs +10 -0
- package/dist/constants-DARNL_LD.mjs.map +1 -0
- package/dist/{errors-CqLiJwqA.mjs → errors-C_XuSbX7.mjs} +17 -17
- package/dist/errors-C_XuSbX7.mjs.map +1 -0
- package/dist/exports/attestation.d.mts +1 -1
- package/dist/exports/attestation.d.mts.map +1 -1
- package/dist/exports/attestation.mjs +4 -7
- package/dist/exports/attestation.mjs.map +1 -1
- package/dist/exports/constants.d.mts +9 -0
- package/dist/exports/constants.d.mts.map +1 -0
- package/dist/exports/constants.mjs +3 -0
- package/dist/exports/dag.d.mts +9 -9
- package/dist/exports/dag.mjs +18 -18
- package/dist/exports/dag.mjs.map +1 -1
- package/dist/exports/io.d.mts +6 -4
- package/dist/exports/io.d.mts.map +1 -1
- package/dist/exports/io.mjs +2 -2
- package/dist/exports/migration-ts.d.mts +34 -0
- package/dist/exports/migration-ts.d.mts.map +1 -0
- package/dist/exports/migration-ts.mjs +125 -0
- package/dist/exports/migration-ts.mjs.map +1 -0
- package/dist/exports/migration.d.mts +28 -0
- package/dist/exports/migration.d.mts.map +1 -0
- package/dist/exports/migration.mjs +105 -0
- package/dist/exports/migration.mjs.map +1 -0
- package/dist/exports/refs.mjs +1 -1
- package/dist/exports/types.d.mts +3 -3
- package/dist/exports/types.mjs +5 -2
- package/dist/exports/types.mjs.map +1 -1
- package/dist/{io-afog-e8J.mjs → io-BO18-Evu.mjs} +10 -4
- package/dist/io-BO18-Evu.mjs.map +1 -0
- package/dist/{types-9YQfIg6N.d.mts → types-DXjq7Fum.d.mts} +13 -9
- package/dist/types-DXjq7Fum.d.mts.map +1 -0
- package/package.json +18 -6
- package/src/attestation.ts +3 -5
- package/src/constants.ts +5 -0
- package/src/dag.ts +21 -21
- package/src/errors.ts +35 -27
- package/src/exports/constants.ts +1 -0
- package/src/exports/io.ts +2 -0
- package/src/exports/migration-ts.ts +6 -0
- package/src/exports/migration.ts +1 -0
- package/src/exports/types.ts +5 -3
- package/src/io.ts +16 -5
- package/src/migration-base.ts +141 -0
- package/src/migration-ts.ts +199 -0
- package/src/types.ts +15 -7
- package/dist/errors-CqLiJwqA.mjs.map +0 -1
- package/dist/io-afog-e8J.mjs.map +0 -1
- package/dist/types-9YQfIg6N.d.mts.map +0 -1
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join, relative, resolve } from "pathe";
|
|
3
|
+
|
|
4
|
+
//#region src/migration-ts.ts
|
|
5
|
+
/**
|
|
6
|
+
* Utilities for scaffolding and evaluating migration.ts files.
|
|
7
|
+
*
|
|
8
|
+
* - scaffoldMigrationTs: writes a migration.ts file with boilerplate
|
|
9
|
+
* - evaluateMigrationTs: loads migration.ts via native Node import, returns descriptors
|
|
10
|
+
*
|
|
11
|
+
* Shared by migration plan (scaffold), migration new (scaffold), and
|
|
12
|
+
* migration verify (evaluate).
|
|
13
|
+
*/
|
|
14
|
+
const MIGRATION_TS_FILE = "migration.ts";
|
|
15
|
+
function serializeQueryInput(input) {
|
|
16
|
+
if (typeof input === "boolean") return String(input);
|
|
17
|
+
if (typeof input === "symbol") return "TODO /* fill in using db.sql.from(...) */";
|
|
18
|
+
if (input === null || input === void 0) return "null";
|
|
19
|
+
if (Array.isArray(input)) {
|
|
20
|
+
if (input.length === 0) return "[]";
|
|
21
|
+
if (input.every((item) => typeof item === "symbol")) return "[TODO /* fill in using db.sql.from(...) */]";
|
|
22
|
+
return `[${input.map(serializeQueryInput).join(", ")}]`;
|
|
23
|
+
}
|
|
24
|
+
return JSON.stringify(input);
|
|
25
|
+
}
|
|
26
|
+
function descriptorToBuilderCall(desc) {
|
|
27
|
+
switch (desc.kind) {
|
|
28
|
+
case "createTable": return `createTable(${JSON.stringify(desc["table"])})`;
|
|
29
|
+
case "dropTable": return `dropTable(${JSON.stringify(desc["table"])})`;
|
|
30
|
+
case "addColumn": {
|
|
31
|
+
const args = [JSON.stringify(desc["table"]), JSON.stringify(desc["column"])];
|
|
32
|
+
if (desc["overrides"]) args.push(JSON.stringify(desc["overrides"]));
|
|
33
|
+
return `addColumn(${args.join(", ")})`;
|
|
34
|
+
}
|
|
35
|
+
case "dropColumn": return `dropColumn(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
|
|
36
|
+
case "alterColumnType": {
|
|
37
|
+
const opts = {};
|
|
38
|
+
if (desc["using"]) opts["using"] = desc["using"];
|
|
39
|
+
if (desc["toType"]) opts["toType"] = desc["toType"];
|
|
40
|
+
return Object.keys(opts).length > 0 ? `alterColumnType(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])}, ${JSON.stringify(opts)})` : `alterColumnType(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
|
|
41
|
+
}
|
|
42
|
+
case "setNotNull": return `setNotNull(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
|
|
43
|
+
case "dropNotNull": return `dropNotNull(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
|
|
44
|
+
case "setDefault": return `setDefault(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
|
|
45
|
+
case "dropDefault": return `dropDefault(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["column"])})`;
|
|
46
|
+
case "addPrimaryKey": return `addPrimaryKey(${JSON.stringify(desc["table"])})`;
|
|
47
|
+
case "addUnique": return `addUnique(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["columns"])})`;
|
|
48
|
+
case "addForeignKey": return `addForeignKey(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["columns"])})`;
|
|
49
|
+
case "dropConstraint": return `dropConstraint(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["constraintName"])})`;
|
|
50
|
+
case "createIndex": return `createIndex(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["columns"])})`;
|
|
51
|
+
case "dropIndex": return `dropIndex(${JSON.stringify(desc["table"])}, ${JSON.stringify(desc["indexName"])})`;
|
|
52
|
+
case "createEnumType": return desc["values"] ? `createEnumType(${JSON.stringify(desc["typeName"])}, ${JSON.stringify(desc["values"])})` : `createEnumType(${JSON.stringify(desc["typeName"])})`;
|
|
53
|
+
case "addEnumValues": return `addEnumValues(${JSON.stringify(desc["typeName"])}, ${JSON.stringify(desc["values"])})`;
|
|
54
|
+
case "dropEnumType": return `dropEnumType(${JSON.stringify(desc["typeName"])})`;
|
|
55
|
+
case "renameType": return `renameType(${JSON.stringify(desc["fromName"])}, ${JSON.stringify(desc["toName"])})`;
|
|
56
|
+
case "createDependency": return `createDependency(${JSON.stringify(desc["dependencyId"])})`;
|
|
57
|
+
case "dataTransform": return `dataTransform(${JSON.stringify(desc["name"])}, {\n check: ${serializeQueryInput(desc["check"])},\n run: ${serializeQueryInput(desc["run"])},\n })`;
|
|
58
|
+
default: throw new Error(`Unknown descriptor kind: ${desc.kind}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Scaffolds a migration.ts file in the given package directory.
|
|
63
|
+
* Serializes operation descriptors as builder calls that the user can edit.
|
|
64
|
+
* On verify, this file is re-evaluated to produce the final ops.
|
|
65
|
+
*/
|
|
66
|
+
async function scaffoldMigrationTs(packageDir, options = {}) {
|
|
67
|
+
const filePath = join(packageDir, MIGRATION_TS_FILE);
|
|
68
|
+
const descriptors = options.descriptors ?? [];
|
|
69
|
+
const hasDataTransform = descriptors.some((d) => d.kind === "dataTransform");
|
|
70
|
+
const lines = [];
|
|
71
|
+
if (hasDataTransform && options.contractJsonPath) {
|
|
72
|
+
const relativeContractDts = relative(packageDir, options.contractJsonPath).replace(/\.json$/, ".d");
|
|
73
|
+
lines.push(`import type { Contract } from "${relativeContractDts}"`);
|
|
74
|
+
lines.push(`import { createBuilders } from "@prisma-next/target-postgres/migration-builders"`);
|
|
75
|
+
lines.push("");
|
|
76
|
+
const importList = [...new Set(descriptors.map((d) => d.kind))];
|
|
77
|
+
importList.push("TODO");
|
|
78
|
+
lines.push(`const { ${importList.join(", ")} } = createBuilders<Contract>()`);
|
|
79
|
+
} else {
|
|
80
|
+
const importList = [...new Set(descriptors.map((d) => d.kind))];
|
|
81
|
+
if (importList.length === 0) importList.push("createTable");
|
|
82
|
+
if (hasDataTransform) importList.push("TODO");
|
|
83
|
+
lines.push(`import { ${importList.join(", ")} } from "@prisma-next/target-postgres/migration-builders"`);
|
|
84
|
+
}
|
|
85
|
+
const calls = descriptors.map((d) => ` ${descriptorToBuilderCall(d)},`).join("\n");
|
|
86
|
+
const body = calls.length > 0 ? `\n${calls}\n` : "";
|
|
87
|
+
lines.push("");
|
|
88
|
+
lines.push(`export default () => [${body}]`);
|
|
89
|
+
lines.push("");
|
|
90
|
+
await writeFile(filePath, lines.join("\n"));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Checks whether a migration.ts file exists in the package directory.
|
|
94
|
+
*/
|
|
95
|
+
async function hasMigrationTs(packageDir) {
|
|
96
|
+
try {
|
|
97
|
+
return (await stat(join(packageDir, MIGRATION_TS_FILE))).isFile();
|
|
98
|
+
} catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Evaluates a migration.ts file by loading it via native Node import.
|
|
104
|
+
* Returns the result of calling the default export (expected to be a
|
|
105
|
+
* function returning an array of operation descriptors).
|
|
106
|
+
*
|
|
107
|
+
* Requires Node ≥24 for native TypeScript support.
|
|
108
|
+
*/
|
|
109
|
+
async function evaluateMigrationTs(packageDir) {
|
|
110
|
+
const filePath = resolve(join(packageDir, MIGRATION_TS_FILE));
|
|
111
|
+
try {
|
|
112
|
+
await stat(filePath);
|
|
113
|
+
} catch {
|
|
114
|
+
throw new Error(`migration.ts not found at "${filePath}"`);
|
|
115
|
+
}
|
|
116
|
+
const mod = await import(filePath);
|
|
117
|
+
if (typeof mod.default !== "function") throw new Error(`migration.ts must export a default function returning an operation list. Got: ${typeof mod.default}`);
|
|
118
|
+
const result = mod.default();
|
|
119
|
+
if (!Array.isArray(result)) throw new Error(`migration.ts default export must return an array of operations. Got: ${typeof result}`);
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
//#endregion
|
|
124
|
+
export { evaluateMigrationTs, hasMigrationTs, scaffoldMigrationTs };
|
|
125
|
+
//# sourceMappingURL=migration-ts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-ts.mjs","names":["opts: Record<string, unknown>","lines: string[]","result: unknown"],"sources":["../../src/migration-ts.ts"],"sourcesContent":["/**\n * Utilities for scaffolding and evaluating migration.ts files.\n *\n * - scaffoldMigrationTs: writes a migration.ts file with boilerplate\n * - evaluateMigrationTs: loads migration.ts via native Node import, returns descriptors\n *\n * Shared by migration plan (scaffold), migration new (scaffold), and\n * migration verify (evaluate).\n */\n\nimport { stat, writeFile } from 'node:fs/promises';\nimport type { OperationDescriptor } from '@prisma-next/framework-components/control';\nimport { join, relative, resolve } from 'pathe';\n\nconst MIGRATION_TS_FILE = 'migration.ts';\n\n/**\n * Options for scaffolding a migration.ts file.\n */\nexport interface ScaffoldOptions {\n /** Operation descriptors to serialize as builder calls. */\n readonly descriptors?: readonly OperationDescriptor[];\n /** Absolute path to contract.json — used to derive contract.d.ts import for typed builders. */\n readonly contractJsonPath?: string;\n}\n\nfunction serializeQueryInput(input: unknown): string {\n if (typeof input === 'boolean') return String(input);\n if (typeof input === 'symbol') return 'TODO /* fill in using db.sql.from(...) */';\n if (input === null || input === undefined) return 'null';\n if (Array.isArray(input)) {\n if (input.length === 0) return '[]';\n if (input.every((item) => typeof item === 'symbol'))\n return '[TODO /* fill in using db.sql.from(...) */]';\n return `[${input.map(serializeQueryInput).join(', ')}]`;\n }\n return JSON.stringify(input);\n}\n\nfunction descriptorToBuilderCall(desc: OperationDescriptor): string {\n switch (desc.kind) {\n case 'createTable':\n return `createTable(${JSON.stringify(desc['table'])})`;\n case 'dropTable':\n return `dropTable(${JSON.stringify(desc['table'])})`;\n case 'addColumn': {\n const args = [JSON.stringify(desc['table']), JSON.stringify(desc['column'])];\n if (desc['overrides']) {\n args.push(JSON.stringify(desc['overrides']));\n }\n return `addColumn(${args.join(', ')})`;\n }\n case 'dropColumn':\n return `dropColumn(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['column'])})`;\n case 'alterColumnType': {\n const opts: Record<string, unknown> = {};\n if (desc['using']) opts['using'] = desc['using'];\n if (desc['toType']) opts['toType'] = desc['toType'];\n const hasOpts = Object.keys(opts).length > 0;\n return hasOpts\n ? `alterColumnType(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['column'])}, ${JSON.stringify(opts)})`\n : `alterColumnType(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['column'])})`;\n }\n case 'setNotNull':\n return `setNotNull(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['column'])})`;\n case 'dropNotNull':\n return `dropNotNull(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['column'])})`;\n case 'setDefault':\n return `setDefault(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['column'])})`;\n case 'dropDefault':\n return `dropDefault(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['column'])})`;\n case 'addPrimaryKey':\n return `addPrimaryKey(${JSON.stringify(desc['table'])})`;\n case 'addUnique':\n return `addUnique(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['columns'])})`;\n case 'addForeignKey':\n return `addForeignKey(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['columns'])})`;\n case 'dropConstraint':\n return `dropConstraint(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['constraintName'])})`;\n case 'createIndex':\n return `createIndex(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['columns'])})`;\n case 'dropIndex':\n return `dropIndex(${JSON.stringify(desc['table'])}, ${JSON.stringify(desc['indexName'])})`;\n case 'createEnumType':\n return desc['values']\n ? `createEnumType(${JSON.stringify(desc['typeName'])}, ${JSON.stringify(desc['values'])})`\n : `createEnumType(${JSON.stringify(desc['typeName'])})`;\n case 'addEnumValues':\n return `addEnumValues(${JSON.stringify(desc['typeName'])}, ${JSON.stringify(desc['values'])})`;\n case 'dropEnumType':\n return `dropEnumType(${JSON.stringify(desc['typeName'])})`;\n case 'renameType':\n return `renameType(${JSON.stringify(desc['fromName'])}, ${JSON.stringify(desc['toName'])})`;\n case 'createDependency':\n return `createDependency(${JSON.stringify(desc['dependencyId'])})`;\n case 'dataTransform':\n return `dataTransform(${JSON.stringify(desc['name'])}, {\\n check: ${serializeQueryInput(desc['check'])},\\n run: ${serializeQueryInput(desc['run'])},\\n })`;\n default:\n throw new Error(`Unknown descriptor kind: ${desc.kind}`);\n }\n}\n\n/**\n * Scaffolds a migration.ts file in the given package directory.\n * Serializes operation descriptors as builder calls that the user can edit.\n * On verify, this file is re-evaluated to produce the final ops.\n */\nexport async function scaffoldMigrationTs(\n packageDir: string,\n options: ScaffoldOptions = {},\n): Promise<void> {\n const filePath = join(packageDir, MIGRATION_TS_FILE);\n\n const descriptors = options.descriptors ?? [];\n const hasDataTransform = descriptors.some((d) => d.kind === 'dataTransform');\n\n const lines: string[] = [];\n\n if (hasDataTransform && options.contractJsonPath) {\n const relativeContractDts = relative(packageDir, options.contractJsonPath).replace(\n /\\.json$/,\n '.d',\n );\n lines.push(`import type { Contract } from \"${relativeContractDts}\"`);\n lines.push(`import { createBuilders } from \"@prisma-next/target-postgres/migration-builders\"`);\n lines.push('');\n const importList = [...new Set(descriptors.map((d) => d.kind))];\n importList.push('TODO');\n lines.push(`const { ${importList.join(', ')} } = createBuilders<Contract>()`);\n } else {\n const importList = [...new Set(descriptors.map((d) => d.kind))];\n if (importList.length === 0) {\n importList.push('createTable');\n }\n if (hasDataTransform) {\n importList.push('TODO');\n }\n lines.push(\n `import { ${importList.join(', ')} } from \"@prisma-next/target-postgres/migration-builders\"`,\n );\n }\n\n const calls = descriptors.map((d) => ` ${descriptorToBuilderCall(d)},`).join('\\n');\n const body = calls.length > 0 ? `\\n${calls}\\n` : '';\n\n lines.push('');\n lines.push(`export default () => [${body}]`);\n lines.push('');\n\n await writeFile(filePath, lines.join('\\n'));\n}\n\n/**\n * Checks whether a migration.ts file exists in the package directory.\n */\nexport async function hasMigrationTs(packageDir: string): Promise<boolean> {\n try {\n const s = await stat(join(packageDir, MIGRATION_TS_FILE));\n return s.isFile();\n } catch {\n return false;\n }\n}\n\n/**\n * Evaluates a migration.ts file by loading it via native Node import.\n * Returns the result of calling the default export (expected to be a\n * function returning an array of operation descriptors).\n *\n * Requires Node ≥24 for native TypeScript support.\n */\nexport async function evaluateMigrationTs(packageDir: string): Promise<readonly unknown[]> {\n const filePath = resolve(join(packageDir, MIGRATION_TS_FILE));\n\n try {\n await stat(filePath);\n } catch {\n throw new Error(`migration.ts not found at \"${filePath}\"`);\n }\n\n // Use native Node TS import (Node ≥24, stable type stripping)\n const mod = (await import(filePath)) as { default?: unknown };\n\n if (typeof mod.default !== 'function') {\n throw new Error(\n `migration.ts must export a default function returning an operation list. Got: ${typeof mod.default}`,\n );\n }\n\n const result: unknown = mod.default();\n\n if (!Array.isArray(result)) {\n throw new Error(\n `migration.ts default export must return an array of operations. Got: ${typeof result}`,\n );\n }\n\n return result;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/migration-base.d.ts
|
|
2
|
+
interface MigrationMeta {
|
|
3
|
+
readonly from: string;
|
|
4
|
+
readonly to: string;
|
|
5
|
+
readonly kind?: 'regular' | 'baseline';
|
|
6
|
+
readonly labels?: readonly string[];
|
|
7
|
+
}
|
|
8
|
+
declare abstract class Migration<TOperation = unknown> {
|
|
9
|
+
abstract plan(): TOperation[];
|
|
10
|
+
describe(): MigrationMeta | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Entrypoint guard for migration files. When called at module scope,
|
|
13
|
+
* detects whether the file is being run directly (e.g. `tsx migration.ts`)
|
|
14
|
+
* and if so, serializes the migration plan to `ops.json` (and optionally
|
|
15
|
+
* `migration.json`) in the same directory. When the file is imported by
|
|
16
|
+
* another module, this is a no-op.
|
|
17
|
+
*
|
|
18
|
+
* Usage (at module scope, after the class definition):
|
|
19
|
+
*
|
|
20
|
+
* class MyMigration extends Migration { ... }
|
|
21
|
+
* export default MyMigration;
|
|
22
|
+
* Migration.run(import.meta.url, MyMigration);
|
|
23
|
+
*/
|
|
24
|
+
static run(importMetaUrl: string, MigrationClass: new () => Migration): void;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { Migration, type MigrationMeta };
|
|
28
|
+
//# sourceMappingURL=migration.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.d.mts","names":[],"sources":["../../src/migration-base.ts"],"sourcesContent":[],"mappings":";UAKiB,aAAA;EAAA,SAAA,IAAA,EAAA,MAAa;EAcR,SAAA,EAAA,EAAS,MAAA;EACZ,SAAA,IAAA,CAAA,EAAA,SAAA,GAAA,UAAA;EAEL,SAAA,MAAA,CAAA,EAAA,SAAA,MAAA,EAAA;;AAiByD,uBApBjD,SAoBiD,CAAA,aAAA,OAAA,CAAA,CAAA;mBAnBpD;cAEL;;;;;;;;;;;;;;8DAiBgD"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { type } from "arktype";
|
|
2
|
+
import { dirname, join } from "pathe";
|
|
3
|
+
import { realpathSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
|
|
6
|
+
//#region src/migration-base.ts
|
|
7
|
+
const MigrationMetaSchema = type({
|
|
8
|
+
from: "string",
|
|
9
|
+
to: "string",
|
|
10
|
+
"kind?": "'regular' | 'baseline'",
|
|
11
|
+
"labels?": "string[]"
|
|
12
|
+
});
|
|
13
|
+
var Migration = class {
|
|
14
|
+
describe() {}
|
|
15
|
+
/**
|
|
16
|
+
* Entrypoint guard for migration files. When called at module scope,
|
|
17
|
+
* detects whether the file is being run directly (e.g. `tsx migration.ts`)
|
|
18
|
+
* and if so, serializes the migration plan to `ops.json` (and optionally
|
|
19
|
+
* `migration.json`) in the same directory. When the file is imported by
|
|
20
|
+
* another module, this is a no-op.
|
|
21
|
+
*
|
|
22
|
+
* Usage (at module scope, after the class definition):
|
|
23
|
+
*
|
|
24
|
+
* class MyMigration extends Migration { ... }
|
|
25
|
+
* export default MyMigration;
|
|
26
|
+
* Migration.run(import.meta.url, MyMigration);
|
|
27
|
+
*/
|
|
28
|
+
static run(importMetaUrl, MigrationClass) {
|
|
29
|
+
if (!importMetaUrl) return;
|
|
30
|
+
const metaFilename = fileURLToPath(importMetaUrl);
|
|
31
|
+
const argv1 = process.argv[1];
|
|
32
|
+
if (!argv1) return;
|
|
33
|
+
let isEntrypoint;
|
|
34
|
+
try {
|
|
35
|
+
isEntrypoint = realpathSync(metaFilename) === realpathSync(argv1);
|
|
36
|
+
} catch {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!isEntrypoint) return;
|
|
40
|
+
const args = process.argv.slice(2);
|
|
41
|
+
if (args.includes("--help")) {
|
|
42
|
+
printHelp();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const dryRun = args.includes("--dry-run");
|
|
46
|
+
const migrationDir = dirname(metaFilename);
|
|
47
|
+
try {
|
|
48
|
+
serializeMigration(MigrationClass, migrationDir, dryRun);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
|
|
51
|
+
process.exitCode = 1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
function printHelp() {
|
|
56
|
+
process.stdout.write([
|
|
57
|
+
"Usage: tsx <migration-file> [options]",
|
|
58
|
+
"",
|
|
59
|
+
"Options:",
|
|
60
|
+
" --dry-run Print operations to stdout without writing files",
|
|
61
|
+
" --help Show this help message",
|
|
62
|
+
""
|
|
63
|
+
].join("\n"));
|
|
64
|
+
}
|
|
65
|
+
function buildManifest(meta) {
|
|
66
|
+
return {
|
|
67
|
+
migrationId: null,
|
|
68
|
+
from: meta.from,
|
|
69
|
+
to: meta.to,
|
|
70
|
+
kind: meta.kind ?? "regular",
|
|
71
|
+
labels: meta.labels ?? [],
|
|
72
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function serializeMigration(MigrationClass, migrationDir, dryRun) {
|
|
76
|
+
const instance = new MigrationClass();
|
|
77
|
+
const ops = instance.plan();
|
|
78
|
+
if (!Array.isArray(ops)) throw new Error("plan() must return an array of operations");
|
|
79
|
+
const serializedOps = JSON.stringify(ops, null, 2);
|
|
80
|
+
let manifest;
|
|
81
|
+
if (typeof instance.describe === "function") {
|
|
82
|
+
const rawMeta = instance.describe();
|
|
83
|
+
if (rawMeta !== void 0) {
|
|
84
|
+
const parsed = MigrationMetaSchema(rawMeta);
|
|
85
|
+
if (parsed instanceof type.errors) throw new Error(`describe() returned invalid metadata: ${parsed.summary}`);
|
|
86
|
+
manifest = buildManifest(parsed);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (dryRun) {
|
|
90
|
+
if (manifest) {
|
|
91
|
+
process.stdout.write(`--- migration.json ---\n${JSON.stringify(manifest, null, 2)}\n`);
|
|
92
|
+
process.stdout.write("--- ops.json ---\n");
|
|
93
|
+
}
|
|
94
|
+
process.stdout.write(`${serializedOps}\n`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
writeFileSync(join(migrationDir, "ops.json"), serializedOps);
|
|
98
|
+
if (manifest) writeFileSync(join(migrationDir, "migration.json"), JSON.stringify(manifest, null, 2));
|
|
99
|
+
const files = manifest ? "ops.json + migration.json" : "ops.json";
|
|
100
|
+
process.stdout.write(`Wrote ${files} to ${migrationDir}\n`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
//#endregion
|
|
104
|
+
export { Migration };
|
|
105
|
+
//# sourceMappingURL=migration.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.mjs","names":["isEntrypoint: boolean","manifest: Record<string, unknown> | undefined","rawMeta: unknown"],"sources":["../../src/migration-base.ts"],"sourcesContent":["import { realpathSync, writeFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { type } from 'arktype';\nimport { dirname, join } from 'pathe';\n\nexport interface MigrationMeta {\n readonly from: string;\n readonly to: string;\n readonly kind?: 'regular' | 'baseline';\n readonly labels?: readonly string[];\n}\n\nconst MigrationMetaSchema = type({\n from: 'string',\n to: 'string',\n 'kind?': \"'regular' | 'baseline'\",\n 'labels?': 'string[]',\n});\n\nexport abstract class Migration<TOperation = unknown> {\n abstract plan(): TOperation[];\n\n describe(): MigrationMeta | undefined {\n return undefined;\n }\n\n /**\n * Entrypoint guard for migration files. When called at module scope,\n * detects whether the file is being run directly (e.g. `tsx migration.ts`)\n * and if so, serializes the migration plan to `ops.json` (and optionally\n * `migration.json`) in the same directory. When the file is imported by\n * another module, this is a no-op.\n *\n * Usage (at module scope, after the class definition):\n *\n * class MyMigration extends Migration { ... }\n * export default MyMigration;\n * Migration.run(import.meta.url, MyMigration);\n */\n static run(importMetaUrl: string, MigrationClass: new () => Migration): void {\n if (!importMetaUrl) return;\n\n const metaFilename = fileURLToPath(importMetaUrl);\n const argv1 = process.argv[1];\n if (!argv1) return;\n\n let isEntrypoint: boolean;\n try {\n isEntrypoint = realpathSync(metaFilename) === realpathSync(argv1);\n } catch {\n return;\n }\n if (!isEntrypoint) return;\n\n const args = process.argv.slice(2);\n\n if (args.includes('--help')) {\n printHelp();\n return;\n }\n\n const dryRun = args.includes('--dry-run');\n const migrationDir = dirname(metaFilename);\n\n try {\n serializeMigration(MigrationClass, migrationDir, dryRun);\n } catch (err) {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`);\n process.exitCode = 1;\n }\n }\n}\n\nfunction printHelp(): void {\n process.stdout.write(\n [\n 'Usage: tsx <migration-file> [options]',\n '',\n 'Options:',\n ' --dry-run Print operations to stdout without writing files',\n ' --help Show this help message',\n '',\n ].join('\\n'),\n );\n}\n\nfunction buildManifest(meta: MigrationMeta): Record<string, unknown> {\n return {\n migrationId: null,\n from: meta.from,\n to: meta.to,\n kind: meta.kind ?? 'regular',\n labels: meta.labels ?? [],\n createdAt: new Date().toISOString(),\n };\n}\n\nfunction serializeMigration(\n MigrationClass: new () => Migration,\n migrationDir: string,\n dryRun: boolean,\n): void {\n const instance = new MigrationClass();\n\n const ops = instance.plan();\n\n if (!Array.isArray(ops)) {\n throw new Error('plan() must return an array of operations');\n }\n\n const serializedOps = JSON.stringify(ops, null, 2);\n\n let manifest: Record<string, unknown> | undefined;\n if (typeof instance.describe === 'function') {\n const rawMeta: unknown = instance.describe();\n if (rawMeta !== undefined) {\n const parsed = MigrationMetaSchema(rawMeta);\n if (parsed instanceof type.errors) {\n throw new Error(`describe() returned invalid metadata: ${parsed.summary}`);\n }\n manifest = buildManifest(parsed);\n }\n }\n\n if (dryRun) {\n if (manifest) {\n process.stdout.write(`--- migration.json ---\\n${JSON.stringify(manifest, null, 2)}\\n`);\n process.stdout.write('--- ops.json ---\\n');\n }\n process.stdout.write(`${serializedOps}\\n`);\n return;\n }\n\n writeFileSync(join(migrationDir, 'ops.json'), serializedOps);\n if (manifest) {\n writeFileSync(join(migrationDir, 'migration.json'), JSON.stringify(manifest, null, 2));\n }\n\n const files = manifest ? 'ops.json + migration.json' : 'ops.json';\n process.stdout.write(`Wrote ${files} to ${migrationDir}\\n`);\n}\n"],"mappings":";;;;;;AAYA,MAAM,sBAAsB,KAAK;CAC/B,MAAM;CACN,IAAI;CACJ,SAAS;CACT,WAAW;CACZ,CAAC;AAEF,IAAsB,YAAtB,MAAsD;CAGpD,WAAsC;;;;;;;;;;;;;;CAiBtC,OAAO,IAAI,eAAuB,gBAA2C;AAC3E,MAAI,CAAC,cAAe;EAEpB,MAAM,eAAe,cAAc,cAAc;EACjD,MAAM,QAAQ,QAAQ,KAAK;AAC3B,MAAI,CAAC,MAAO;EAEZ,IAAIA;AACJ,MAAI;AACF,kBAAe,aAAa,aAAa,KAAK,aAAa,MAAM;UAC3D;AACN;;AAEF,MAAI,CAAC,aAAc;EAEnB,MAAM,OAAO,QAAQ,KAAK,MAAM,EAAE;AAElC,MAAI,KAAK,SAAS,SAAS,EAAE;AAC3B,cAAW;AACX;;EAGF,MAAM,SAAS,KAAK,SAAS,YAAY;EACzC,MAAM,eAAe,QAAQ,aAAa;AAE1C,MAAI;AACF,sBAAmB,gBAAgB,cAAc,OAAO;WACjD,KAAK;AACZ,WAAQ,OAAO,MAAM,GAAG,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CAAC,IAAI;AAC7E,WAAQ,WAAW;;;;AAKzB,SAAS,YAAkB;AACzB,SAAQ,OAAO,MACb;EACE;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,KAAK,KAAK,CACb;;AAGH,SAAS,cAAc,MAA8C;AACnE,QAAO;EACL,aAAa;EACb,MAAM,KAAK;EACX,IAAI,KAAK;EACT,MAAM,KAAK,QAAQ;EACnB,QAAQ,KAAK,UAAU,EAAE;EACzB,4BAAW,IAAI,MAAM,EAAC,aAAa;EACpC;;AAGH,SAAS,mBACP,gBACA,cACA,QACM;CACN,MAAM,WAAW,IAAI,gBAAgB;CAErC,MAAM,MAAM,SAAS,MAAM;AAE3B,KAAI,CAAC,MAAM,QAAQ,IAAI,CACrB,OAAM,IAAI,MAAM,4CAA4C;CAG9D,MAAM,gBAAgB,KAAK,UAAU,KAAK,MAAM,EAAE;CAElD,IAAIC;AACJ,KAAI,OAAO,SAAS,aAAa,YAAY;EAC3C,MAAMC,UAAmB,SAAS,UAAU;AAC5C,MAAI,YAAY,QAAW;GACzB,MAAM,SAAS,oBAAoB,QAAQ;AAC3C,OAAI,kBAAkB,KAAK,OACzB,OAAM,IAAI,MAAM,yCAAyC,OAAO,UAAU;AAE5E,cAAW,cAAc,OAAO;;;AAIpC,KAAI,QAAQ;AACV,MAAI,UAAU;AACZ,WAAQ,OAAO,MAAM,2BAA2B,KAAK,UAAU,UAAU,MAAM,EAAE,CAAC,IAAI;AACtF,WAAQ,OAAO,MAAM,qBAAqB;;AAE5C,UAAQ,OAAO,MAAM,GAAG,cAAc,IAAI;AAC1C;;AAGF,eAAc,KAAK,cAAc,WAAW,EAAE,cAAc;AAC5D,KAAI,SACF,eAAc,KAAK,cAAc,iBAAiB,EAAE,KAAK,UAAU,UAAU,MAAM,EAAE,CAAC;CAGxF,MAAM,QAAQ,WAAW,8BAA8B;AACvD,SAAQ,OAAO,MAAM,SAAS,MAAM,MAAM,aAAa,IAAI"}
|
package/dist/exports/refs.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as errorInvalidRefValue, l as errorInvalidRefs, s as errorInvalidRefName, t as MigrationToolsError } from "../errors-
|
|
1
|
+
import { c as errorInvalidRefValue, l as errorInvalidRefs, s as errorInvalidRefName, t as MigrationToolsError } from "../errors-C_XuSbX7.mjs";
|
|
2
2
|
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
3
|
import { type } from "arktype";
|
|
4
4
|
import { dirname, join } from "pathe";
|
package/dist/exports/types.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as DraftMigrationManifest, c as MigrationHints, d as isAttested, f as isDraft, i as DraftMigrationBundle, l as MigrationManifest, n as AttestedMigrationManifest, o as MigrationChainEntry, r as BaseMigrationBundle, s as MigrationGraph, t as AttestedMigrationBundle, u as MigrationOps } from "../types-DXjq7Fum.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/errors.d.ts
|
|
4
4
|
|
|
@@ -7,7 +7,7 @@ import { a as MigrationChainEntry, c as MigrationManifest, i as MigrationBundle,
|
|
|
7
7
|
*
|
|
8
8
|
* Follows the NAMESPACE.SUBCODE convention from ADR 027. All codes live under
|
|
9
9
|
* the MIGRATION namespace. These are tooling-time errors (file I/O, attestation,
|
|
10
|
-
* migration
|
|
10
|
+
* migration history reconstruction), distinct from the runtime MIGRATION.* codes for apply-time
|
|
11
11
|
* failures (PRECHECK_FAILED, POSTCHECK_FAILED, etc.).
|
|
12
12
|
*
|
|
13
13
|
* Fields:
|
|
@@ -31,5 +31,5 @@ declare class MigrationToolsError extends Error {
|
|
|
31
31
|
static is(error: unknown): error is MigrationToolsError;
|
|
32
32
|
}
|
|
33
33
|
//#endregion
|
|
34
|
-
export { type AttestedMigrationBundle, type AttestedMigrationManifest, type
|
|
34
|
+
export { type AttestedMigrationBundle, type AttestedMigrationManifest, type BaseMigrationBundle, type BaseMigrationBundle as MigrationBundle, type BaseMigrationBundle as MigrationPackage, type DraftMigrationBundle, type DraftMigrationManifest, type MigrationChainEntry, type MigrationGraph, type MigrationHints, type MigrationManifest, type MigrationOps, MigrationToolsError, isAttested, isDraft };
|
|
35
35
|
//# sourceMappingURL=types.d.mts.map
|
package/dist/exports/types.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as MigrationToolsError } from "../errors-
|
|
1
|
+
import { t as MigrationToolsError } from "../errors-C_XuSbX7.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/types.ts
|
|
4
4
|
/**
|
|
@@ -8,7 +8,10 @@ import { t as MigrationToolsError } from "../errors-CqLiJwqA.mjs";
|
|
|
8
8
|
function isAttested(bundle) {
|
|
9
9
|
return typeof bundle.manifest.migrationId === "string";
|
|
10
10
|
}
|
|
11
|
+
function isDraft(bundle) {
|
|
12
|
+
return bundle.manifest.migrationId === null;
|
|
13
|
+
}
|
|
11
14
|
|
|
12
15
|
//#endregion
|
|
13
|
-
export { MigrationToolsError, isAttested };
|
|
16
|
+
export { MigrationToolsError, isAttested, isDraft };
|
|
14
17
|
//# sourceMappingURL=types.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.mjs","names":[],"sources":["../../src/types.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"types.mjs","names":[],"sources":["../../src/types.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport type { MigrationPlanOperation } from '@prisma-next/framework-components/control';\n\nexport interface MigrationHints {\n readonly used: readonly string[];\n readonly applied: readonly string[];\n readonly plannerVersion: string;\n readonly planningStrategy: string;\n}\n\n/**\n * Shared fields for all migration manifests (draft and attested).\n */\ninterface MigrationManifestBase {\n readonly from: string;\n readonly to: string;\n readonly kind: 'regular' | 'baseline';\n readonly fromContract: Contract | null;\n readonly toContract: Contract;\n readonly hints: MigrationHints;\n readonly labels: readonly string[];\n readonly authorship?: { readonly author?: string; readonly email?: string };\n readonly signature?: { readonly keyId: string; readonly value: string } | null;\n readonly createdAt: string;\n}\n\n/**\n * A draft migration that has been planned but not yet attested.\n * Draft migrations have `migrationId: null` and are excluded from\n * graph reconstruction and apply.\n */\nexport interface DraftMigrationManifest extends MigrationManifestBase {\n readonly migrationId: null;\n}\n\n/**\n * An attested migration with a content-addressed migrationId.\n * Only attested migrations participate in the migration graph.\n */\nexport interface AttestedMigrationManifest extends MigrationManifestBase {\n readonly migrationId: string;\n}\n\n/**\n * Union of draft and attested manifests. This is what the on-disk\n * format represents — `migrationId` is `null` for drafts, a string\n * for attested migrations.\n */\nexport type MigrationManifest = DraftMigrationManifest | AttestedMigrationManifest;\n\nexport type MigrationOps = readonly MigrationPlanOperation[];\n\n/**\n * An on-disk migration directory containing a manifest and operations.\n * The manifest may be draft or attested.\n */\nexport interface BaseMigrationBundle {\n readonly dirName: string;\n readonly dirPath: string;\n readonly manifest: MigrationManifest;\n readonly ops: MigrationOps;\n}\n\n/**\n * A bundle known to be attested (migrationId is a string).\n * Use this after filtering bundles to attested-only.\n */\nexport interface AttestedMigrationBundle extends BaseMigrationBundle {\n readonly manifest: AttestedMigrationManifest;\n}\n\nexport interface DraftMigrationBundle extends BaseMigrationBundle {\n readonly manifest: DraftMigrationManifest;\n}\n\n/**\n * An entry in the migration graph. Only attested migrations appear in the\n * graph, so `migrationId` is always a string.\n */\nexport interface MigrationChainEntry {\n readonly from: string;\n readonly to: string;\n readonly migrationId: string;\n readonly dirName: string;\n readonly createdAt: string;\n readonly labels: readonly string[];\n}\n\nexport interface MigrationGraph {\n readonly nodes: ReadonlySet<string>;\n readonly forwardChain: ReadonlyMap<string, readonly MigrationChainEntry[]>;\n readonly reverseChain: ReadonlyMap<string, readonly MigrationChainEntry[]>;\n readonly migrationById: ReadonlyMap<string, MigrationChainEntry>;\n}\n\n/**\n * Type guard that narrows a MigrationBundle to an AttestedMigrationBundle.\n * Use with `.filter(isAttested)` to get a typed array of attested bundles.\n */\nexport function isAttested(bundle: BaseMigrationBundle): bundle is AttestedMigrationBundle {\n return typeof bundle.manifest.migrationId === 'string';\n}\n\nexport function isDraft(bundle: BaseMigrationBundle): bundle is DraftMigrationBundle {\n return bundle.manifest.migrationId === null;\n}\n"],"mappings":";;;;;;;AAmGA,SAAgB,WAAW,QAAgE;AACzF,QAAO,OAAO,OAAO,SAAS,gBAAgB;;AAGhD,SAAgB,QAAQ,QAA6D;AACnF,QAAO,OAAO,SAAS,gBAAgB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as errorInvalidJson, d as errorMissingFile, o as errorInvalidManifest, r as errorDirectoryExists, u as errorInvalidSlug } from "./errors-
|
|
1
|
+
import { a as errorInvalidJson, d as errorMissingFile, o as errorInvalidManifest, r as errorDirectoryExists, u as errorInvalidSlug } from "./errors-C_XuSbX7.mjs";
|
|
2
2
|
import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import { type } from "arktype";
|
|
4
4
|
import { basename, dirname, join } from "pathe";
|
|
@@ -37,7 +37,7 @@ const MigrationManifestSchema = type({
|
|
|
37
37
|
const MigrationOpsSchema = type({
|
|
38
38
|
id: "string",
|
|
39
39
|
label: "string",
|
|
40
|
-
operationClass: "'additive' | 'widening' | 'destructive'"
|
|
40
|
+
operationClass: "'additive' | 'widening' | 'destructive' | 'data'"
|
|
41
41
|
}).array();
|
|
42
42
|
async function writeMigrationPackage(dir, manifest, ops) {
|
|
43
43
|
await mkdir(dirname(dir), { recursive: true });
|
|
@@ -50,6 +50,12 @@ async function writeMigrationPackage(dir, manifest, ops) {
|
|
|
50
50
|
await writeFile(join(dir, MANIFEST_FILE), JSON.stringify(manifest, null, 2), { flag: "wx" });
|
|
51
51
|
await writeFile(join(dir, OPS_FILE), JSON.stringify(ops, null, 2), { flag: "wx" });
|
|
52
52
|
}
|
|
53
|
+
async function writeMigrationManifest(dir, manifest) {
|
|
54
|
+
await writeFile(join(dir, MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
55
|
+
}
|
|
56
|
+
async function writeMigrationOps(dir, ops) {
|
|
57
|
+
await writeFile(join(dir, OPS_FILE), `${JSON.stringify(ops, null, 2)}\n`);
|
|
58
|
+
}
|
|
53
59
|
async function readMigrationPackage(dir) {
|
|
54
60
|
const manifestPath = join(dir, MANIFEST_FILE);
|
|
55
61
|
const opsPath = join(dir, OPS_FILE);
|
|
@@ -126,5 +132,5 @@ function formatMigrationDirName(timestamp, slug) {
|
|
|
126
132
|
}
|
|
127
133
|
|
|
128
134
|
//#endregion
|
|
129
|
-
export {
|
|
130
|
-
//# sourceMappingURL=io-
|
|
135
|
+
export { writeMigrationOps as a, writeMigrationManifest as i, readMigrationPackage as n, writeMigrationPackage as o, readMigrationsDir as r, formatMigrationDirName as t };
|
|
136
|
+
//# sourceMappingURL=io-BO18-Evu.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"io-BO18-Evu.mjs","names":["manifestRaw: string","opsRaw: string","manifest: MigrationManifest","ops: MigrationOps","entries: string[]","packages: BaseMigrationBundle[]"],"sources":["../src/io.ts"],"sourcesContent":["import { mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises';\nimport { type } from 'arktype';\nimport { basename, dirname, join } from 'pathe';\nimport {\n errorDirectoryExists,\n errorInvalidJson,\n errorInvalidManifest,\n errorInvalidSlug,\n errorMissingFile,\n} from './errors';\nimport type { BaseMigrationBundle, MigrationManifest, MigrationOps } from './types';\n\nconst MANIFEST_FILE = 'migration.json';\nconst OPS_FILE = 'ops.json';\nconst MAX_SLUG_LENGTH = 64;\n\nfunction hasErrnoCode(error: unknown, code: string): boolean {\n return error instanceof Error && (error as { code?: string }).code === code;\n}\n\nconst MigrationHintsSchema = type({\n used: 'string[]',\n applied: 'string[]',\n plannerVersion: 'string',\n planningStrategy: 'string',\n});\n\nconst MigrationManifestSchema = type({\n from: 'string',\n to: 'string',\n migrationId: 'string | null',\n kind: \"'regular' | 'baseline'\",\n fromContract: 'object | null',\n toContract: 'object',\n hints: MigrationHintsSchema,\n labels: 'string[]',\n 'authorship?': type({\n 'author?': 'string',\n 'email?': 'string',\n }),\n 'signature?': type({\n keyId: 'string',\n value: 'string',\n }).or('null'),\n createdAt: 'string',\n});\n\nconst MigrationOpSchema = type({\n id: 'string',\n label: 'string',\n operationClass: \"'additive' | 'widening' | 'destructive' | 'data'\",\n});\n\n// Intentionally shallow: operation-specific payload validation is owned by planner/runner layers.\nconst MigrationOpsSchema = MigrationOpSchema.array();\n\nexport async function writeMigrationPackage(\n dir: string,\n manifest: MigrationManifest,\n ops: MigrationOps,\n): Promise<void> {\n await mkdir(dirname(dir), { recursive: true });\n\n try {\n await mkdir(dir);\n } catch (error) {\n if (hasErrnoCode(error, 'EEXIST')) {\n throw errorDirectoryExists(dir);\n }\n throw error;\n }\n\n await writeFile(join(dir, MANIFEST_FILE), JSON.stringify(manifest, null, 2), { flag: 'wx' });\n await writeFile(join(dir, OPS_FILE), JSON.stringify(ops, null, 2), { flag: 'wx' });\n}\n\nexport async function writeMigrationManifest(\n dir: string,\n manifest: MigrationManifest,\n): Promise<void> {\n await writeFile(join(dir, MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\\n`);\n}\n\nexport async function writeMigrationOps(dir: string, ops: MigrationOps): Promise<void> {\n await writeFile(join(dir, OPS_FILE), `${JSON.stringify(ops, null, 2)}\\n`);\n}\n\nexport async function readMigrationPackage(dir: string): Promise<BaseMigrationBundle> {\n const manifestPath = join(dir, MANIFEST_FILE);\n const opsPath = join(dir, OPS_FILE);\n\n let manifestRaw: string;\n try {\n manifestRaw = await readFile(manifestPath, 'utf-8');\n } catch (error) {\n if (hasErrnoCode(error, 'ENOENT')) {\n throw errorMissingFile(MANIFEST_FILE, dir);\n }\n throw error;\n }\n\n let opsRaw: string;\n try {\n opsRaw = await readFile(opsPath, 'utf-8');\n } catch (error) {\n if (hasErrnoCode(error, 'ENOENT')) {\n throw errorMissingFile(OPS_FILE, dir);\n }\n throw error;\n }\n\n let manifest: MigrationManifest;\n try {\n manifest = JSON.parse(manifestRaw);\n } catch (e) {\n throw errorInvalidJson(manifestPath, e instanceof Error ? e.message : String(e));\n }\n\n let ops: MigrationOps;\n try {\n ops = JSON.parse(opsRaw);\n } catch (e) {\n throw errorInvalidJson(opsPath, e instanceof Error ? e.message : String(e));\n }\n\n validateManifest(manifest, manifestPath);\n validateOps(ops, opsPath);\n\n return {\n dirName: basename(dir),\n dirPath: dir,\n manifest,\n ops,\n };\n}\n\nfunction validateManifest(\n manifest: unknown,\n filePath: string,\n): asserts manifest is MigrationManifest {\n const result = MigrationManifestSchema(manifest);\n if (result instanceof type.errors) {\n throw errorInvalidManifest(filePath, result.summary);\n }\n}\n\nfunction validateOps(ops: unknown, filePath: string): asserts ops is MigrationOps {\n const result = MigrationOpsSchema(ops);\n if (result instanceof type.errors) {\n throw errorInvalidManifest(filePath, result.summary);\n }\n}\n\nexport async function readMigrationsDir(\n migrationsRoot: string,\n): Promise<readonly BaseMigrationBundle[]> {\n let entries: string[];\n try {\n entries = await readdir(migrationsRoot);\n } catch (error) {\n if (hasErrnoCode(error, 'ENOENT')) {\n return [];\n }\n throw error;\n }\n\n const packages: BaseMigrationBundle[] = [];\n\n for (const entry of entries.sort()) {\n const entryPath = join(migrationsRoot, entry);\n const entryStat = await stat(entryPath);\n if (!entryStat.isDirectory()) continue;\n\n const manifestPath = join(entryPath, MANIFEST_FILE);\n try {\n await stat(manifestPath);\n } catch {\n continue; // skip non-migration directories\n }\n\n packages.push(await readMigrationPackage(entryPath));\n }\n\n return packages;\n}\n\nexport function formatMigrationDirName(timestamp: Date, slug: string): string {\n const sanitized = slug\n .toLowerCase()\n .replace(/[^a-z0-9]/g, '_')\n .replace(/_+/g, '_')\n .replace(/^_|_$/g, '');\n\n if (sanitized.length === 0) {\n throw errorInvalidSlug(slug);\n }\n\n const truncated = sanitized.slice(0, MAX_SLUG_LENGTH);\n\n const y = timestamp.getUTCFullYear();\n const mo = String(timestamp.getUTCMonth() + 1).padStart(2, '0');\n const d = String(timestamp.getUTCDate()).padStart(2, '0');\n const h = String(timestamp.getUTCHours()).padStart(2, '0');\n const mi = String(timestamp.getUTCMinutes()).padStart(2, '0');\n\n return `${y}${mo}${d}T${h}${mi}_${truncated}`;\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { MigrationPlanOperation } from "@prisma-next/
|
|
1
|
+
import { Contract } from "@prisma-next/contract/types";
|
|
2
|
+
import { MigrationPlanOperation } from "@prisma-next/framework-components/control";
|
|
3
3
|
|
|
4
4
|
//#region src/types.d.ts
|
|
5
5
|
interface MigrationHints {
|
|
@@ -15,8 +15,8 @@ interface MigrationManifestBase {
|
|
|
15
15
|
readonly from: string;
|
|
16
16
|
readonly to: string;
|
|
17
17
|
readonly kind: 'regular' | 'baseline';
|
|
18
|
-
readonly fromContract:
|
|
19
|
-
readonly toContract:
|
|
18
|
+
readonly fromContract: Contract | null;
|
|
19
|
+
readonly toContract: Contract;
|
|
20
20
|
readonly hints: MigrationHints;
|
|
21
21
|
readonly labels: readonly string[];
|
|
22
22
|
readonly authorship?: {
|
|
@@ -55,7 +55,7 @@ type MigrationOps = readonly MigrationPlanOperation[];
|
|
|
55
55
|
* An on-disk migration directory containing a manifest and operations.
|
|
56
56
|
* The manifest may be draft or attested.
|
|
57
57
|
*/
|
|
58
|
-
interface
|
|
58
|
+
interface BaseMigrationBundle {
|
|
59
59
|
readonly dirName: string;
|
|
60
60
|
readonly dirPath: string;
|
|
61
61
|
readonly manifest: MigrationManifest;
|
|
@@ -65,9 +65,12 @@ interface MigrationBundle {
|
|
|
65
65
|
* A bundle known to be attested (migrationId is a string).
|
|
66
66
|
* Use this after filtering bundles to attested-only.
|
|
67
67
|
*/
|
|
68
|
-
interface AttestedMigrationBundle extends
|
|
68
|
+
interface AttestedMigrationBundle extends BaseMigrationBundle {
|
|
69
69
|
readonly manifest: AttestedMigrationManifest;
|
|
70
70
|
}
|
|
71
|
+
interface DraftMigrationBundle extends BaseMigrationBundle {
|
|
72
|
+
readonly manifest: DraftMigrationManifest;
|
|
73
|
+
}
|
|
71
74
|
/**
|
|
72
75
|
* An entry in the migration graph. Only attested migrations appear in the
|
|
73
76
|
* graph, so `migrationId` is always a string.
|
|
@@ -90,7 +93,8 @@ interface MigrationGraph {
|
|
|
90
93
|
* Type guard that narrows a MigrationBundle to an AttestedMigrationBundle.
|
|
91
94
|
* Use with `.filter(isAttested)` to get a typed array of attested bundles.
|
|
92
95
|
*/
|
|
93
|
-
declare function isAttested(bundle:
|
|
96
|
+
declare function isAttested(bundle: BaseMigrationBundle): bundle is AttestedMigrationBundle;
|
|
97
|
+
declare function isDraft(bundle: BaseMigrationBundle): bundle is DraftMigrationBundle;
|
|
94
98
|
//#endregion
|
|
95
|
-
export {
|
|
96
|
-
//# sourceMappingURL=types-
|
|
99
|
+
export { DraftMigrationManifest as a, MigrationHints as c, isAttested as d, isDraft as f, DraftMigrationBundle as i, MigrationManifest as l, AttestedMigrationManifest as n, MigrationChainEntry as o, BaseMigrationBundle as r, MigrationGraph as s, AttestedMigrationBundle as t, MigrationOps as u };
|
|
100
|
+
//# sourceMappingURL=types-DXjq7Fum.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-DXjq7Fum.d.mts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;;;UAGiB,cAAA;;EAAA,SAAA,OAAA,EAAc,SAAA,MAAA,EAAA;EAUrB,SAAA,cAAA,EAAqB,MAAA;EAIN,SAAA,gBAAA,EAAA,MAAA;;;;AAczB;AAQA,UA1BU,qBAAA,CA0BiC;EAS/B,SAAA,IAAA,EAAA,MAAiB;EAEjB,SAAA,EAAA,EAAA,MAAY;EAMP,SAAA,IAAA,EAAA,SAAmB,GAAA,UAGf;EAQJ,SAAA,YAAA,EAlDQ,QAkDgB,GAAA,IACpB;EAGJ,SAAA,UAAA,EArDM,QAqDe;EAQrB,SAAA,KAAA,EA5DC,cA4DkB;EASnB,SAAA,MAAA,EAAc,SAAA,MAAA,EAAA;EACb,SAAA,UAAA,CAAA,EAAA;IACoC,SAAA,MAAA,CAAA,EAAA,MAAA;IAA7B,SAAA,KAAA,CAAA,EAAA,MAAA;EAC6B,CAAA;EAA7B,SAAA,SAAA,CAAA,EAAA;IACqB,SAAA,KAAA,EAAA,MAAA;IAApB,SAAA,KAAA,EAAA,MAAA;EAAW,CAAA,GAAA,IAAA;EAOrB,SAAA,SAAU,EAAA,MAAS;AAInC;;;;;;UAxEiB,sBAAA,SAA+B;;;;;;;UAQ/B,yBAAA,SAAkC;;;;;;;;KASvC,iBAAA,GAAoB,yBAAyB;KAE7C,YAAA,YAAwB;;;;;UAMnB,mBAAA;;;qBAGI;gBACL;;;;;;UAOC,uBAAA,SAAgC;qBAC5B;;UAGJ,oBAAA,SAA6B;qBACzB;;;;;;UAOJ,mBAAA;;;;;;;;UASA,cAAA;kBACC;yBACO,6BAA6B;yBAC7B,6BAA6B;0BAC5B,oBAAoB;;;;;;iBAO9B,UAAA,SAAmB,gCAAgC;iBAInD,OAAA,SAAgB,gCAAgC"}
|
package/package.json
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/migration-tools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-dev.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "On-disk migration persistence, attestation, and chain reconstruction for Prisma Next",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"arktype": "^2.1.29",
|
|
9
9
|
"pathe": "^2.0.3",
|
|
10
|
-
"@prisma-next/contract": "0.
|
|
11
|
-
"@prisma-next/utils": "0.
|
|
12
|
-
"@prisma-next/
|
|
10
|
+
"@prisma-next/contract": "0.4.0-dev.1",
|
|
11
|
+
"@prisma-next/utils": "0.4.0-dev.1",
|
|
12
|
+
"@prisma-next/framework-components": "0.4.0-dev.1"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"tsdown": "0.18.4",
|
|
16
16
|
"typescript": "5.9.3",
|
|
17
17
|
"vitest": "4.0.17",
|
|
18
|
-
"@prisma-next/
|
|
19
|
-
"@prisma-next/
|
|
18
|
+
"@prisma-next/tsdown": "0.0.0",
|
|
19
|
+
"@prisma-next/tsconfig": "0.0.0"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"dist",
|
|
@@ -46,6 +46,18 @@
|
|
|
46
46
|
"types": "./dist/exports/refs.d.mts",
|
|
47
47
|
"import": "./dist/exports/refs.mjs"
|
|
48
48
|
},
|
|
49
|
+
"./constants": {
|
|
50
|
+
"types": "./dist/exports/constants.d.mts",
|
|
51
|
+
"import": "./dist/exports/constants.mjs"
|
|
52
|
+
},
|
|
53
|
+
"./migration-ts": {
|
|
54
|
+
"types": "./dist/exports/migration-ts.d.mts",
|
|
55
|
+
"import": "./dist/exports/migration-ts.mjs"
|
|
56
|
+
},
|
|
57
|
+
"./migration": {
|
|
58
|
+
"types": "./dist/exports/migration.d.mts",
|
|
59
|
+
"import": "./dist/exports/migration.mjs"
|
|
60
|
+
},
|
|
49
61
|
"./package.json": "./package.json"
|
|
50
62
|
},
|
|
51
63
|
"repository": {
|
package/src/attestation.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import {
|
|
3
|
-
import { canonicalizeContract } from '@prisma-next/core-control-plane/emission';
|
|
4
|
-
import { join } from 'pathe';
|
|
2
|
+
import { canonicalizeContract } from '@prisma-next/contract/hashing';
|
|
5
3
|
import { canonicalizeJson } from './canonicalize-json';
|
|
6
|
-
import { readMigrationPackage } from './io';
|
|
4
|
+
import { readMigrationPackage, writeMigrationManifest } from './io';
|
|
7
5
|
import type { MigrationManifest, MigrationOps } from './types';
|
|
8
6
|
|
|
9
7
|
export interface VerifyResult {
|
|
@@ -49,7 +47,7 @@ export async function attestMigration(dir: string): Promise<string> {
|
|
|
49
47
|
const migrationId = computeMigrationId(pkg.manifest, pkg.ops);
|
|
50
48
|
|
|
51
49
|
const updated = { ...pkg.manifest, migrationId };
|
|
52
|
-
await
|
|
50
|
+
await writeMigrationManifest(dir, updated);
|
|
53
51
|
|
|
54
52
|
return migrationId;
|
|
55
53
|
}
|