@metaobjectsdev/migrate-ts 0.5.0 → 0.6.0-rc.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 +34 -0
- package/dist/emit/d1-safety-pass.d.ts +15 -0
- package/dist/emit/d1-safety-pass.d.ts.map +1 -0
- package/dist/emit/d1-safety-pass.js +80 -0
- package/dist/emit/d1-safety-pass.js.map +1 -0
- package/dist/emit/d1.d.ts +3 -0
- package/dist/emit/d1.d.ts.map +1 -0
- package/dist/emit/d1.js +11 -0
- package/dist/emit/d1.js.map +1 -0
- package/dist/emit/index.d.ts.map +1 -1
- package/dist/emit/index.js +2 -0
- package/dist/emit/index.js.map +1 -1
- package/dist/emit/postgres.js +28 -3
- package/dist/emit/postgres.js.map +1 -1
- package/dist/emit/sqlite.d.ts +1 -1
- package/dist/emit/sqlite.d.ts.map +1 -1
- package/dist/emit/sqlite.js.map +1 -1
- package/dist/errors.d.ts +17 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +28 -0
- package/dist/errors.js.map +1 -1
- package/dist/expected-schema.d.ts +7 -7
- package/dist/expected-schema.d.ts.map +1 -1
- package/dist/expected-schema.js +78 -35
- package/dist/expected-schema.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/introspect/d1.d.ts +21 -0
- package/dist/introspect/d1.d.ts.map +1 -0
- package/dist/introspect/d1.js +149 -0
- package/dist/introspect/d1.js.map +1 -0
- package/dist/introspect/index.d.ts.map +1 -1
- package/dist/introspect/index.js +1 -0
- package/dist/introspect/index.js.map +1 -1
- package/dist/introspect/sqlite-shared.d.ts +14 -0
- package/dist/introspect/sqlite-shared.d.ts.map +1 -0
- package/dist/introspect/sqlite-shared.js +74 -0
- package/dist/introspect/sqlite-shared.js.map +1 -0
- package/dist/introspect/sqlite.js +1 -73
- package/dist/introspect/sqlite.js.map +1 -1
- package/dist/referential-actions.d.ts +49 -0
- package/dist/referential-actions.d.ts.map +1 -0
- package/dist/referential-actions.js +110 -0
- package/dist/referential-actions.js.map +1 -0
- package/dist/types.d.ts +15 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/wrangler-config.d.ts +25 -0
- package/dist/wrangler-config.d.ts.map +1 -0
- package/dist/wrangler-config.js +91 -0
- package/dist/wrangler-config.js.map +1 -0
- package/dist/write-migration-d1.d.ts +17 -0
- package/dist/write-migration-d1.d.ts.map +1 -0
- package/dist/write-migration-d1.js +50 -0
- package/dist/write-migration-d1.js.map +1 -0
- package/package.json +28 -27
- package/src/emit/d1-safety-pass.ts +94 -0
- package/src/emit/d1.ts +16 -0
- package/src/emit/index.ts +2 -0
- package/src/emit/postgres.ts +35 -3
- package/src/emit/sqlite.ts +1 -1
- package/src/errors.ts +33 -0
- package/src/expected-schema.ts +100 -52
- package/src/index.ts +22 -1
- package/src/introspect/d1.ts +185 -0
- package/src/introspect/index.ts +1 -0
- package/src/introspect/sqlite-shared.ts +77 -0
- package/src/introspect/sqlite.ts +2 -69
- package/src/referential-actions.ts +134 -0
- package/src/types.ts +15 -1
- package/src/wrangler-config.ts +103 -0
- package/src/write-migration-d1.ts +74 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { sql } from "kysely";
|
|
2
|
+
import { parseSqliteDefault, sqliteTypeToSqlType, sqliteRuleToAction } from "./sqlite-shared.js";
|
|
2
3
|
export async function introspectSqlite(db) {
|
|
3
4
|
const k = db;
|
|
4
5
|
const versionRow = await sql `SELECT sqlite_version() AS v`.execute(k);
|
|
@@ -59,69 +60,6 @@ async function readSqlitePrimaryKey(k, table) {
|
|
|
59
60
|
`.execute(k);
|
|
60
61
|
return rows.rows.map((r) => r.name);
|
|
61
62
|
}
|
|
62
|
-
function sqliteTypeToSqlType(declaredType) {
|
|
63
|
-
const t = declaredType.trim().toUpperCase();
|
|
64
|
-
// SQLite's type affinity is loose; we honor the declared type literally for round-trip stability.
|
|
65
|
-
// Affinity rules per sqlite.org/datatype3.html — adapted to canonical SqlType.
|
|
66
|
-
// text affinity
|
|
67
|
-
const varcharMatch = /^(?:VARCHAR|CHAR|CHARACTER|TEXT)\((\d+)\)$/.exec(t);
|
|
68
|
-
if (varcharMatch)
|
|
69
|
-
return { kind: "text", maxLength: parseInt(varcharMatch[1] ?? "0", 10) };
|
|
70
|
-
if (/TEXT|CLOB|VARCHAR|CHAR/.test(t))
|
|
71
|
-
return { kind: "text" };
|
|
72
|
-
// numeric affinity
|
|
73
|
-
const numMatch = /^(?:NUMERIC|DECIMAL)\((\d+)(?:,\s*(\d+))?\)$/.exec(t);
|
|
74
|
-
if (numMatch) {
|
|
75
|
-
const out = { kind: "numeric" };
|
|
76
|
-
if (numMatch[1])
|
|
77
|
-
out.precision = parseInt(numMatch[1], 10);
|
|
78
|
-
if (numMatch[2])
|
|
79
|
-
out.scale = parseInt(numMatch[2], 10);
|
|
80
|
-
return out;
|
|
81
|
-
}
|
|
82
|
-
if (t === "BOOLEAN" || t === "BOOL")
|
|
83
|
-
return { kind: "boolean" };
|
|
84
|
-
if (t === "DATE")
|
|
85
|
-
return { kind: "date" };
|
|
86
|
-
if (t === "DATETIME" || t === "TIMESTAMP")
|
|
87
|
-
return { kind: "timestamp", withTimezone: false };
|
|
88
|
-
// integer affinity (SQLite stores all INTEGER as 64-bit internally).
|
|
89
|
-
// Distinguish INT (32-bit) from INTEGER/BIGINT (64-bit) for round-trip fidelity:
|
|
90
|
-
// the emitter uses "INT" for integer{32} and "INTEGER" for integer{64}.
|
|
91
|
-
if (t === "INT" || t === "SMALLINT" || t === "TINYINT")
|
|
92
|
-
return { kind: "integer", bits: 32 };
|
|
93
|
-
if (/INT/.test(t))
|
|
94
|
-
return { kind: "integer", bits: 64 };
|
|
95
|
-
// real affinity
|
|
96
|
-
if (/REAL|FLOA|DOUB/.test(t))
|
|
97
|
-
return { kind: "real" };
|
|
98
|
-
// blob affinity
|
|
99
|
-
if (t === "BLOB" || t === "")
|
|
100
|
-
return { kind: "blob" };
|
|
101
|
-
// numeric affinity fallback
|
|
102
|
-
if (/NUMERIC|DECIMAL/.test(t))
|
|
103
|
-
return { kind: "numeric" };
|
|
104
|
-
// json (libsql/sqlite have JSON1)
|
|
105
|
-
if (t === "JSON")
|
|
106
|
-
return { kind: "json" };
|
|
107
|
-
return { kind: "text" };
|
|
108
|
-
}
|
|
109
|
-
const SQLITE_EXPR_DEFAULT_PATTERNS = [
|
|
110
|
-
/^current_timestamp$/i,
|
|
111
|
-
/^current_date$/i,
|
|
112
|
-
/^current_time$/i,
|
|
113
|
-
/\(.*\)/, // anything function-like
|
|
114
|
-
];
|
|
115
|
-
function parseSqliteDefault(raw) {
|
|
116
|
-
if (raw === null || raw === undefined || raw === "")
|
|
117
|
-
return undefined;
|
|
118
|
-
const isExpr = SQLITE_EXPR_DEFAULT_PATTERNS.some((re) => re.test(raw));
|
|
119
|
-
if (isExpr)
|
|
120
|
-
return { kind: "expr", value: raw };
|
|
121
|
-
// SQLite stores literal string defaults with surrounding quotes.
|
|
122
|
-
const cleaned = raw.replace(/^'(.*)'$/, "$1");
|
|
123
|
-
return { kind: "literal", value: cleaned };
|
|
124
|
-
}
|
|
125
63
|
async function readSqliteIndexes(k, table) {
|
|
126
64
|
// SELECT * avoids "unique" being treated as a reserved keyword by libsql.
|
|
127
65
|
const listRows = await sql `
|
|
@@ -179,14 +117,4 @@ async function readSqliteForeignKeys(k, table) {
|
|
|
179
117
|
return fk;
|
|
180
118
|
});
|
|
181
119
|
}
|
|
182
|
-
function sqliteRuleToAction(rule) {
|
|
183
|
-
const r = rule.toUpperCase();
|
|
184
|
-
if (r === "CASCADE")
|
|
185
|
-
return "cascade";
|
|
186
|
-
if (r === "SET NULL")
|
|
187
|
-
return "set-null";
|
|
188
|
-
if (r === "RESTRICT")
|
|
189
|
-
return "restrict";
|
|
190
|
-
return "no-action";
|
|
191
|
-
}
|
|
192
120
|
//# sourceMappingURL=sqlite.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/introspect/sqlite.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../../src/introspect/sqlite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type MetaObject, type MetaReferenceIdentity, type MetaData } from "@metaobjectsdev/metadata";
|
|
2
|
+
import type { FkAction } from "./types.js";
|
|
3
|
+
export declare function readIdentityFields(identity: MetaData): string[];
|
|
4
|
+
export declare function findField(entity: MetaObject, name: string): MetaData | undefined;
|
|
5
|
+
export declare function isRequired(field: MetaData): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the referential actions for a foreign key inferred from an
|
|
8
|
+
* identity.reference, by correlating it with a sibling relationship on the
|
|
9
|
+
* same entity (matched on target-entity name).
|
|
10
|
+
*
|
|
11
|
+
* - No correlated relationship → both undefined (no ON DELETE / ON UPDATE clause).
|
|
12
|
+
* - With a relationship: onDelete defaults from the relationship subtype
|
|
13
|
+
* (composition→cascade, aggregation→set-null, association→restrict);
|
|
14
|
+
* onUpdate defaults to "cascade". Explicit @onDelete / @onUpdate override.
|
|
15
|
+
* - Resolved "no-action" → undefined: introspection in introspect/{postgres,sqlite}.ts
|
|
16
|
+
* omits actions when the DB value is "no-action", so the expected side does the same
|
|
17
|
+
* to keep round-trip diffs clean.
|
|
18
|
+
*
|
|
19
|
+
* If multiple relationships target the same entity (rare), the first one is used.
|
|
20
|
+
*
|
|
21
|
+
* The single `as FkAction` cast in normalize() is safe because REFERENTIAL_ACTIONS
|
|
22
|
+
* (metadata package) and FkAction (migrate-ts/src/types.ts) are the same four-value
|
|
23
|
+
* set: "cascade" | "set-null" | "restrict" | "no-action". The invariant is
|
|
24
|
+
* documented in relationship-constants.ts and enforced by both the type system
|
|
25
|
+
* (FkAction is the union literal) and a runtime-set-equality test in
|
|
26
|
+
* referential-actions.test.ts.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveReferentialActions(entity: MetaObject, ref: MetaReferenceIdentity): {
|
|
29
|
+
onDelete: FkAction | undefined;
|
|
30
|
+
onUpdate: FkAction | undefined;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Validate that a FK whose resolved ON DELETE action is "set-null" does not
|
|
34
|
+
* contain any NOT NULL column.
|
|
35
|
+
*
|
|
36
|
+
* ON DELETE SET NULL requires all FK columns to be nullable. Postgres and
|
|
37
|
+
* SQLite both reject the combination at DDL execution time.
|
|
38
|
+
*
|
|
39
|
+
* Call this from buildExpectedSchema AFTER resolving the referential action
|
|
40
|
+
* (i.e. after resolveReferentialActions) so that explicit overrides such as
|
|
41
|
+
* @onDelete: "restrict" are already applied before the check.
|
|
42
|
+
*
|
|
43
|
+
* @param entity The owning entity.
|
|
44
|
+
* @param ref The identity.reference node being processed.
|
|
45
|
+
* @param onDelete The resolved onDelete action (undefined = no-action).
|
|
46
|
+
* @param constraintName The FK constraint name as it will appear in the DDL.
|
|
47
|
+
*/
|
|
48
|
+
export declare function validateSetNullNullability(entity: MetaObject, ref: MetaReferenceIdentity, onDelete: FkAction | undefined, constraintName: string): void;
|
|
49
|
+
//# sourceMappingURL=referential-actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"referential-actions.d.ts","sourceRoot":"","sources":["../src/referential-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,QAAQ,EACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAO3C,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,EAAE,CAM/D;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAKhF;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAMnD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,qBAAqB,GACzB;IAAE,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAE,CAoBpE;AAWD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,qBAAqB,EAC1B,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAC9B,cAAc,EAAE,MAAM,GACrB,IAAI,CAeN"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { ON_DELETE_DEFAULT_BY_SUBTYPE, ON_UPDATE_DEFAULT, FIELD_ATTR_REQUIRED, IDENTITY_ATTR_FIELDS, TYPE_VALIDATOR, VALIDATOR_SUBTYPE_REQUIRED, } from "@metaobjectsdev/metadata";
|
|
2
|
+
import { SetNullNotNullableError } from "./errors.js";
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Shared field helpers — exported for use by expected-schema.ts
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
export function readIdentityFields(identity) {
|
|
7
|
+
const raw = identity.ownAttr(IDENTITY_ATTR_FIELDS);
|
|
8
|
+
if (Array.isArray(raw))
|
|
9
|
+
return raw.map(String).filter((s) => s.length > 0);
|
|
10
|
+
// Fallback: comma-separated string form (defensive; canonical form is array)
|
|
11
|
+
if (typeof raw === "string")
|
|
12
|
+
return raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
export function findField(entity, name) {
|
|
16
|
+
for (const field of entity.fields()) {
|
|
17
|
+
if (field.name === name)
|
|
18
|
+
return field;
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
export function isRequired(field) {
|
|
23
|
+
const attr = field.ownAttr(FIELD_ATTR_REQUIRED);
|
|
24
|
+
if (attr === true || attr === "true")
|
|
25
|
+
return true;
|
|
26
|
+
return field.ownChildren().some((c) => c.type === TYPE_VALIDATOR && c.subType === VALIDATOR_SUBTYPE_REQUIRED);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolve the referential actions for a foreign key inferred from an
|
|
30
|
+
* identity.reference, by correlating it with a sibling relationship on the
|
|
31
|
+
* same entity (matched on target-entity name).
|
|
32
|
+
*
|
|
33
|
+
* - No correlated relationship → both undefined (no ON DELETE / ON UPDATE clause).
|
|
34
|
+
* - With a relationship: onDelete defaults from the relationship subtype
|
|
35
|
+
* (composition→cascade, aggregation→set-null, association→restrict);
|
|
36
|
+
* onUpdate defaults to "cascade". Explicit @onDelete / @onUpdate override.
|
|
37
|
+
* - Resolved "no-action" → undefined: introspection in introspect/{postgres,sqlite}.ts
|
|
38
|
+
* omits actions when the DB value is "no-action", so the expected side does the same
|
|
39
|
+
* to keep round-trip diffs clean.
|
|
40
|
+
*
|
|
41
|
+
* If multiple relationships target the same entity (rare), the first one is used.
|
|
42
|
+
*
|
|
43
|
+
* The single `as FkAction` cast in normalize() is safe because REFERENTIAL_ACTIONS
|
|
44
|
+
* (metadata package) and FkAction (migrate-ts/src/types.ts) are the same four-value
|
|
45
|
+
* set: "cascade" | "set-null" | "restrict" | "no-action". The invariant is
|
|
46
|
+
* documented in relationship-constants.ts and enforced by both the type system
|
|
47
|
+
* (FkAction is the union literal) and a runtime-set-equality test in
|
|
48
|
+
* referential-actions.test.ts.
|
|
49
|
+
*/
|
|
50
|
+
export function resolveReferentialActions(entity, ref) {
|
|
51
|
+
const target = ref.targetEntity;
|
|
52
|
+
if (target === undefined)
|
|
53
|
+
return { onDelete: undefined, onUpdate: undefined };
|
|
54
|
+
// Correlation is by exact-string match. Every fixture in the corpus uses
|
|
55
|
+
// bare entity names for @objectRef and @references (no `::`-FQN form), so
|
|
56
|
+
// bare-vs-bare matching is sufficient today. If a future author writes an
|
|
57
|
+
// FQN value on either side, this find returns undefined and both actions
|
|
58
|
+
// resolve to undefined (no clause emitted) — surfacing the mismatch as a
|
|
59
|
+
// silent loss of intent rather than a wrong action. Cross-language ports
|
|
60
|
+
// should match the same correlation rule.
|
|
61
|
+
const rel = entity.relationships().find((r) => r.objectRef === target);
|
|
62
|
+
if (rel === undefined)
|
|
63
|
+
return { onDelete: undefined, onUpdate: undefined };
|
|
64
|
+
const onDeleteRaw = rel.onDelete ?? ON_DELETE_DEFAULT_BY_SUBTYPE[rel.subType];
|
|
65
|
+
const onUpdateRaw = rel.onUpdate ?? ON_UPDATE_DEFAULT;
|
|
66
|
+
return {
|
|
67
|
+
onDelete: normalize(onDeleteRaw),
|
|
68
|
+
onUpdate: normalize(onUpdateRaw),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function normalize(a) {
|
|
72
|
+
if (a === undefined || a === "no-action")
|
|
73
|
+
return undefined;
|
|
74
|
+
return a;
|
|
75
|
+
}
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Set-null / NOT NULL guard
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
/**
|
|
80
|
+
* Validate that a FK whose resolved ON DELETE action is "set-null" does not
|
|
81
|
+
* contain any NOT NULL column.
|
|
82
|
+
*
|
|
83
|
+
* ON DELETE SET NULL requires all FK columns to be nullable. Postgres and
|
|
84
|
+
* SQLite both reject the combination at DDL execution time.
|
|
85
|
+
*
|
|
86
|
+
* Call this from buildExpectedSchema AFTER resolving the referential action
|
|
87
|
+
* (i.e. after resolveReferentialActions) so that explicit overrides such as
|
|
88
|
+
* @onDelete: "restrict" are already applied before the check.
|
|
89
|
+
*
|
|
90
|
+
* @param entity The owning entity.
|
|
91
|
+
* @param ref The identity.reference node being processed.
|
|
92
|
+
* @param onDelete The resolved onDelete action (undefined = no-action).
|
|
93
|
+
* @param constraintName The FK constraint name as it will appear in the DDL.
|
|
94
|
+
*/
|
|
95
|
+
export function validateSetNullNullability(entity, ref, onDelete, constraintName) {
|
|
96
|
+
if (onDelete !== "set-null")
|
|
97
|
+
return;
|
|
98
|
+
const fkFieldJsNames = readIdentityFields(ref);
|
|
99
|
+
const offending = [];
|
|
100
|
+
for (const jsName of fkFieldJsNames) {
|
|
101
|
+
const field = findField(entity, jsName);
|
|
102
|
+
if (field !== undefined && isRequired(field)) {
|
|
103
|
+
offending.push(jsName);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (offending.length > 0) {
|
|
107
|
+
throw new SetNullNotNullableError(entity.name, constraintName, offending);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=referential-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"referential-actions.js","sourceRoot":"","sources":["../src/referential-actions.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -24,6 +24,13 @@ export interface TableDescriptor {
|
|
|
24
24
|
indexes: IndexDescriptor[];
|
|
25
25
|
foreignKeys: FkDescriptor[];
|
|
26
26
|
primaryKey: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Human-readable description threaded from entity `@description`.
|
|
29
|
+
* Postgres: emitted as `COMMENT ON TABLE … IS '…';` after CREATE TABLE.
|
|
30
|
+
* SQLite: silently ignored (no native COMMENT support).
|
|
31
|
+
* Introspect side: not read back in v1 (no change-description variant yet).
|
|
32
|
+
*/
|
|
33
|
+
description?: string;
|
|
27
34
|
}
|
|
28
35
|
export interface ColumnDescriptor {
|
|
29
36
|
name: string;
|
|
@@ -31,6 +38,13 @@ export interface ColumnDescriptor {
|
|
|
31
38
|
nullable: boolean;
|
|
32
39
|
default?: ColumnDefault;
|
|
33
40
|
identity?: "increment" | "uuid";
|
|
41
|
+
/**
|
|
42
|
+
* Human-readable description threaded from field `@description`.
|
|
43
|
+
* Postgres: emitted as `COMMENT ON COLUMN … IS '…';` after CREATE TABLE or ADD COLUMN.
|
|
44
|
+
* SQLite: silently ignored (no native COMMENT support).
|
|
45
|
+
* Introspect side: not read back in v1 (no change-description variant yet).
|
|
46
|
+
*/
|
|
47
|
+
description?: string;
|
|
34
48
|
}
|
|
35
49
|
export interface ColumnDefault {
|
|
36
50
|
kind: "literal" | "expr";
|
|
@@ -219,5 +233,5 @@ export interface EmitResult {
|
|
|
219
233
|
*/
|
|
220
234
|
recreatedTables: ReadonlySet<string>;
|
|
221
235
|
}
|
|
222
|
-
export type Dialect = "postgres" | "sqlite";
|
|
236
|
+
export type Dialect = "postgres" | "sqlite" | "d1";
|
|
223
237
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAO7C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,8EAA8E;IAC9E,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB;;;OAGG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,QAAQ,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAO7C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,8EAA8E;IAC9E,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB;;;OAGG;IACH,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,QAAQ,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAChC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;AAEzE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;CAEjB;AAMD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,MAAM,GACd;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACvF;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAC5E;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACzF;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACtG;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAC7F;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACzG;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAC3E,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,wBAAwB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAC/E,IAAI,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,uBAAuB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAC9E,IAAI,CAAC,EAAE,aAAa,CAAC;IAAC,EAAE,CAAC,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACnG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAC3F;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAC1F;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAErF;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC;AAEzE,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;AAExC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mFAAmF;IACnF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,wBAAwB,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IACzC,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CACxC,GACD;IACE,IAAI,EAAE,uBAAuB,CAAC;IAC9B,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEN,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;AAElE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,EAAE,eAAe,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAErF,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iGAAiG;IACjG,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAMD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,IAAI,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface D1Binding {
|
|
2
|
+
binding: string;
|
|
3
|
+
database_name: string;
|
|
4
|
+
database_id: string;
|
|
5
|
+
migrations_dir: string | undefined;
|
|
6
|
+
}
|
|
7
|
+
export interface WranglerConfig {
|
|
8
|
+
d1Bindings: D1Binding[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Walk from `startDir` upward looking for wrangler.toml, wrangler.jsonc, or wrangler.json.
|
|
12
|
+
* Returns the first match or undefined. Probe order: toml > jsonc > json at each level,
|
|
13
|
+
* matching wrangler's own resolution order.
|
|
14
|
+
*/
|
|
15
|
+
export declare function findWranglerConfig(startDir: string): string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Parse a wrangler.toml or wrangler.jsonc file. Returns extracted D1 bindings.
|
|
18
|
+
*/
|
|
19
|
+
export declare function parseWranglerConfig(path: string): WranglerConfig;
|
|
20
|
+
/**
|
|
21
|
+
* Pick a D1 binding by name. If `name` is undefined and there's exactly one
|
|
22
|
+
* binding, return it. Otherwise throw a helpful error.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveD1Binding(bindings: readonly D1Binding[], name: string | undefined): D1Binding;
|
|
25
|
+
//# sourceMappingURL=wrangler-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrangler-config.d.ts","sourceRoot":"","sources":["../src/wrangler-config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAavE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CA0BhE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAiBpG"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join, isAbsolute, resolve } from "node:path";
|
|
3
|
+
import TOML from "@iarna/toml";
|
|
4
|
+
/**
|
|
5
|
+
* Walk from `startDir` upward looking for wrangler.toml, wrangler.jsonc, or wrangler.json.
|
|
6
|
+
* Returns the first match or undefined. Probe order: toml > jsonc > json at each level,
|
|
7
|
+
* matching wrangler's own resolution order.
|
|
8
|
+
*/
|
|
9
|
+
export function findWranglerConfig(startDir) {
|
|
10
|
+
let dir = resolve(startDir);
|
|
11
|
+
while (true) {
|
|
12
|
+
const toml = join(dir, "wrangler.toml");
|
|
13
|
+
if (existsSync(toml))
|
|
14
|
+
return toml;
|
|
15
|
+
const jsonc = join(dir, "wrangler.jsonc");
|
|
16
|
+
if (existsSync(jsonc))
|
|
17
|
+
return jsonc;
|
|
18
|
+
const json = join(dir, "wrangler.json");
|
|
19
|
+
if (existsSync(json))
|
|
20
|
+
return json;
|
|
21
|
+
const parent = dirname(dir);
|
|
22
|
+
if (parent === dir)
|
|
23
|
+
return undefined;
|
|
24
|
+
dir = parent;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse a wrangler.toml or wrangler.jsonc file. Returns extracted D1 bindings.
|
|
29
|
+
*/
|
|
30
|
+
export function parseWranglerConfig(path) {
|
|
31
|
+
if (!isAbsolute(path))
|
|
32
|
+
path = resolve(path);
|
|
33
|
+
const raw = readFileSync(path, "utf8");
|
|
34
|
+
const isJsonc = path.endsWith(".jsonc") || path.endsWith(".json");
|
|
35
|
+
const obj = isJsonc ? parseJsoncLoose(raw) : TOML.parse(raw);
|
|
36
|
+
const rawArr = obj.d1_databases;
|
|
37
|
+
if (rawArr !== undefined && !Array.isArray(rawArr)) {
|
|
38
|
+
throw new Error(`${path}: d1_databases must be an array (got ${typeof rawArr})`);
|
|
39
|
+
}
|
|
40
|
+
const rawBindings = rawArr ?? [];
|
|
41
|
+
const d1Bindings = rawBindings.map((b, i) => {
|
|
42
|
+
if (b === null || typeof b !== "object") {
|
|
43
|
+
throw new Error(`${path}: d1_databases[${i}] must be an object`);
|
|
44
|
+
}
|
|
45
|
+
const r = b;
|
|
46
|
+
if (typeof r.binding !== "string" || r.binding.length === 0) {
|
|
47
|
+
throw new Error(`${path}: d1_databases[${i}] is missing required 'binding' field`);
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
binding: r.binding,
|
|
51
|
+
database_name: typeof r.database_name === "string" ? r.database_name : "",
|
|
52
|
+
database_id: typeof r.database_id === "string" ? r.database_id : "",
|
|
53
|
+
migrations_dir: typeof r.migrations_dir === "string" ? r.migrations_dir : undefined,
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
return { d1Bindings };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Pick a D1 binding by name. If `name` is undefined and there's exactly one
|
|
60
|
+
* binding, return it. Otherwise throw a helpful error.
|
|
61
|
+
*/
|
|
62
|
+
export function resolveD1Binding(bindings, name) {
|
|
63
|
+
if (bindings.length === 0) {
|
|
64
|
+
throw new Error("no d1 bindings found in wrangler config");
|
|
65
|
+
}
|
|
66
|
+
if (name === undefined) {
|
|
67
|
+
if (bindings.length === 1)
|
|
68
|
+
return bindings[0];
|
|
69
|
+
throw new Error(`multiple d1 bindings in wrangler config; pass --d1 <binding>. Available: ${bindings.map((b) => b.binding).join(", ")}`);
|
|
70
|
+
}
|
|
71
|
+
const found = bindings.find((b) => b.binding === name);
|
|
72
|
+
if (!found) {
|
|
73
|
+
throw new Error(`d1 binding '${name}' not found in wrangler config. Available: ${bindings.map((b) => b.binding).join(", ")}`);
|
|
74
|
+
}
|
|
75
|
+
return found;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Minimal JSONC parser: strips `//` line comments and block comments (`/`+`* ... *`+`/`),
|
|
79
|
+
* then JSON.parse. Wrangler's jsonc is small; this is sufficient.
|
|
80
|
+
*
|
|
81
|
+
* Limitation: a `//` sequence inside a JSON string value would be incorrectly
|
|
82
|
+
* stripped. Wrangler's config vocabulary (UUIDs, identifiers, paths) does not
|
|
83
|
+
* use such substrings, so this is acceptable in scope.
|
|
84
|
+
*/
|
|
85
|
+
function parseJsoncLoose(raw) {
|
|
86
|
+
const stripped = raw
|
|
87
|
+
.replace(/\/\*[\s\S]*?\*\//g, "")
|
|
88
|
+
.replace(/(^|[^:])\/\/.*$/gm, "$1");
|
|
89
|
+
return JSON.parse(stripped);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=wrangler-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrangler-config.js","sourceRoot":"","sources":["../src/wrangler-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { EmitResult } from "./types.js";
|
|
2
|
+
export interface WriteMigrationD1Options {
|
|
3
|
+
/** Migrations dir (e.g., "migrations"). Created if missing. */
|
|
4
|
+
dir: string;
|
|
5
|
+
/** Human-readable slug; sanitized to lowercase + hyphens. */
|
|
6
|
+
slug: string;
|
|
7
|
+
}
|
|
8
|
+
export interface WriteMigrationD1Result {
|
|
9
|
+
/** Full path to the up SQL file. */
|
|
10
|
+
upPath: string;
|
|
11
|
+
/** Full path to the down sidecar SQL file. */
|
|
12
|
+
downPath: string;
|
|
13
|
+
/** Assigned sequence number (e.g., 1, 2, 10000). */
|
|
14
|
+
sequence: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function writeMigrationD1(result: Pick<EmitResult, "up" | "down">, opts: WriteMigrationD1Options): Promise<WriteMigrationD1Result>;
|
|
17
|
+
//# sourceMappingURL=write-migration-d1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-migration-d1.d.ts","sourceRoot":"","sources":["../src/write-migration-d1.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,uBAAuB;IACtC,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,sBAAsB;IACrC,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC,EACvC,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,sBAAsB,CAAC,CAgBjC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { mkdir, readdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
const SEQ_RE = /^(\d+)_/;
|
|
4
|
+
export async function writeMigrationD1(result, opts) {
|
|
5
|
+
await mkdir(opts.dir, { recursive: true });
|
|
6
|
+
await mkdir(join(opts.dir, ".down"), { recursive: true });
|
|
7
|
+
const seq = await nextSequence(opts.dir);
|
|
8
|
+
const padded = String(seq).padStart(4, "0");
|
|
9
|
+
const slug = sanitizeSlug(opts.slug);
|
|
10
|
+
const filename = `${padded}_${slug}.sql`;
|
|
11
|
+
const upPath = join(opts.dir, filename);
|
|
12
|
+
const downPath = join(opts.dir, ".down", filename);
|
|
13
|
+
await writeFile(upPath, ensureTrailingNewline(result.up), "utf8");
|
|
14
|
+
await writeFile(downPath, ensureTrailingNewline(result.down), "utf8");
|
|
15
|
+
return { upPath, downPath, sequence: seq };
|
|
16
|
+
}
|
|
17
|
+
async function nextSequence(dir) {
|
|
18
|
+
let entries;
|
|
19
|
+
// Best-effort: dir was just mkdir'd above, but in race/permission edge cases the
|
|
20
|
+
// listing can still fail; treat as empty (next seq = 1) rather than rethrow.
|
|
21
|
+
try {
|
|
22
|
+
entries = await readdir(dir);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return 1;
|
|
26
|
+
}
|
|
27
|
+
let max = 0;
|
|
28
|
+
for (const entry of entries) {
|
|
29
|
+
if (!entry.endsWith(".sql"))
|
|
30
|
+
continue;
|
|
31
|
+
const m = SEQ_RE.exec(entry);
|
|
32
|
+
if (!m)
|
|
33
|
+
continue;
|
|
34
|
+
const n = parseInt(m[1], 10);
|
|
35
|
+
if (n > max)
|
|
36
|
+
max = n;
|
|
37
|
+
}
|
|
38
|
+
return max + 1;
|
|
39
|
+
}
|
|
40
|
+
function sanitizeSlug(raw) {
|
|
41
|
+
return raw
|
|
42
|
+
.toLowerCase()
|
|
43
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
44
|
+
.replace(/^-+|-+$/g, "")
|
|
45
|
+
.substring(0, 60);
|
|
46
|
+
}
|
|
47
|
+
function ensureTrailingNewline(s) {
|
|
48
|
+
return s.endsWith("\n") ? s : s + "\n";
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=write-migration-d1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-migration-d1.js","sourceRoot":"","sources":["../src/write-migration-d1.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAmBjC,MAAM,MAAM,GAAG,SAAS,CAAC;AAEzB,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAuC,EACvC,IAA6B;IAE7B,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE1D,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,IAAI,MAAM,CAAC;IAEzC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAEnD,MAAM,SAAS,CAAC,MAAM,EAAE,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;IAClE,MAAM,SAAS,CAAC,QAAQ,EAAE,qBAAqB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;IAEtE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AAC7C,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,GAAW;IACrC,IAAI,OAAiB,CAAC;IACtB,iFAAiF;IACjF,6EAA6E;IAC7E,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,SAAS;QACtC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG,GAAG;YAAE,GAAG,GAAG,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,GAAG,GAAG,CAAC,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,GAAG;SACP,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACtB,CAAC;AAED,SAAS,qBAAqB,CAAC,CAAS;IACtC,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;AACzC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metaobjectsdev/migrate-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-rc.1",
|
|
4
4
|
"description": "Schema migration tooling for MetaObjects: diff metadata vs DB and emit SQL for Postgres and SQLite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -21,30 +21,31 @@
|
|
|
21
21
|
"author": "Doug Mealing <doug@dougmealing.com>",
|
|
22
22
|
"homepage": "https://metaobjects.dev",
|
|
23
23
|
"bugs": {
|
|
24
|
-
|
|
25
|
-
},
|
|
26
|
-
"repository": {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
},
|
|
31
|
-
"keywords": ["metaobjects", "migrate", "postgres", "sqlite", "schema-diff"],
|
|
32
|
-
"publishConfig": {
|
|
33
|
-
"access": "public"
|
|
34
|
-
},
|
|
35
|
-
"dependencies": {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
24
|
+
"url": "https://github.com/metaobjectsdev/metaobjects/issues"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/metaobjectsdev/metaobjects.git",
|
|
29
|
+
"directory": "server/typescript/packages/migrate-ts"
|
|
30
|
+
},
|
|
31
|
+
"keywords": ["metaobjects", "migrate", "postgres", "sqlite", "schema-diff"],
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@iarna/toml": "^2.2.5",
|
|
37
|
+
"@metaobjectsdev/metadata": "0.6.0-rc.1"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"kysely": ">=0.27.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@libsql/kysely-libsql": "^0.4.1",
|
|
44
|
+
"@types/pg": "^8.20.0",
|
|
45
|
+
"bun-types": "latest",
|
|
46
|
+
"kysely": "^0.27.0",
|
|
47
|
+
"pg": "^8.20.0",
|
|
48
|
+
"pg-mem": "^3.0.4",
|
|
49
|
+
"typescript": "^5.6.0"
|
|
50
|
+
}
|
|
50
51
|
}
|