fix: complete production data migration rehearsal
This commit is contained in:
@@ -7,9 +7,11 @@ import {
|
||||
SafeProductionMigrationError,
|
||||
assertActiveAdminUsers,
|
||||
assertTargetEmpty,
|
||||
copiedDeferredForeignKeys,
|
||||
normalizeAuthUser,
|
||||
normalizeAuthUsers,
|
||||
parseMode,
|
||||
prepareColumnValues,
|
||||
readActiveAdminUserIds,
|
||||
readConfiguration,
|
||||
readSchema,
|
||||
@@ -29,6 +31,8 @@ function table(
|
||||
generated?: boolean;
|
||||
identity?: boolean;
|
||||
identityGeneration?: string | null;
|
||||
dataType?: string;
|
||||
udtName?: string;
|
||||
}>,
|
||||
primaryKey = ["id"],
|
||||
foreignKeys: Array<{
|
||||
@@ -45,6 +49,8 @@ function table(
|
||||
generated: false,
|
||||
identity: false,
|
||||
identityGeneration: null,
|
||||
dataType: "text",
|
||||
udtName: "text",
|
||||
...column,
|
||||
})),
|
||||
primaryKey,
|
||||
@@ -65,6 +71,7 @@ test("configuration requires an explicit Owner and ciphertext decision", () => {
|
||||
SUPABASE_SOURCE_DATABASE_URL: "postgresql://source.invalid/jyotisha",
|
||||
PRODUCTION_TARGET_DATABASE_URL: "postgresql://target.invalid/jyotisha",
|
||||
PRODUCTION_OWNER_USER_ID: "018f4e6d-7a11-7000-8000-000000000001",
|
||||
PRODUCTION_OWNER_EMAIL: "luna@copse.life",
|
||||
};
|
||||
|
||||
assert.equal(
|
||||
@@ -161,15 +168,19 @@ test("active administrators become usable identity admins", () => {
|
||||
);
|
||||
|
||||
assert.deepEqual(users.map((user) => user.role), ["admin", "admin"]);
|
||||
assert.doesNotThrow(() => assertActiveAdminUsers(users, activeAdminUserIds, ownerId));
|
||||
assert.doesNotThrow(() => assertActiveAdminUsers(users, activeAdminUserIds, ownerId, `${ownerId}@example.com`));
|
||||
assert.throws(
|
||||
() => assertActiveAdminUsers(users, new Set([adminId]), ownerId),
|
||||
() => assertActiveAdminUsers(users, new Set([adminId]), ownerId, `${ownerId}@example.com`),
|
||||
/Owner is not an active source administrator/,
|
||||
);
|
||||
assert.throws(
|
||||
() => assertActiveAdminUsers([{ ...users[0], banned: true }, users[1]], activeAdminUserIds, ownerId),
|
||||
() => assertActiveAdminUsers([{ ...users[0], banned: true }, users[1]], activeAdminUserIds, ownerId, `${ownerId}@example.com`),
|
||||
/Owner is blocked/,
|
||||
);
|
||||
assert.throws(
|
||||
() => assertActiveAdminUsers(users, activeAdminUserIds, ownerId, "wrong@example.com"),
|
||||
/UUID does not match/,
|
||||
);
|
||||
});
|
||||
|
||||
test("schema reader preserves PostgreSQL identity metadata", async () => {
|
||||
@@ -185,6 +196,8 @@ test("schema reader preserves PostgreSQL identity metadata", async () => {
|
||||
generated: false,
|
||||
identity: true,
|
||||
identity_generation: "ALWAYS",
|
||||
data_type: "bigint",
|
||||
udt_name: "int8",
|
||||
}],
|
||||
};
|
||||
}
|
||||
@@ -203,9 +216,42 @@ test("schema reader preserves PostgreSQL identity metadata", async () => {
|
||||
generated: false,
|
||||
identity: true,
|
||||
identityGeneration: "ALWAYS",
|
||||
dataType: "bigint",
|
||||
udtName: "int8",
|
||||
});
|
||||
});
|
||||
|
||||
test("JSON columns are serialized without changing PostgreSQL arrays", () => {
|
||||
const target = table([
|
||||
{ name: "payload", dataType: "jsonb", udtName: "jsonb" },
|
||||
{ name: "tags", dataType: "ARRAY", udtName: "_text" },
|
||||
]);
|
||||
const tags = ["a", "b"];
|
||||
|
||||
assert.deepEqual(
|
||||
prepareColumnValues({ payload: [], tags }, ["payload", "tags"], target),
|
||||
["[]", tags],
|
||||
);
|
||||
});
|
||||
|
||||
test("target-only nullable foreign keys are not restored from the legacy source", () => {
|
||||
const target = table(
|
||||
[{ name: "id" }, { name: "new_session_id", nullable: true }],
|
||||
["id"],
|
||||
[{
|
||||
columns: ["new_session_id"],
|
||||
refSchema: "public",
|
||||
refTable: "chat_sessions",
|
||||
refColumns: ["id"],
|
||||
}],
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
copiedDeferredForeignKeys("requests", target, new Set(["chat_sessions"]), ["id"]),
|
||||
[],
|
||||
);
|
||||
});
|
||||
|
||||
test("transfer plan rejects source-only public columns", () => {
|
||||
const source = new Map([
|
||||
["profiles", table([{ name: "id" }, { name: "legacy_value" }])],
|
||||
|
||||
Reference in New Issue
Block a user