Files
UHD_Media_Tool/packages/db/src/migration-helpers.ts
T
rootandClaude Fable 5.1 cc8b3a7df4 feat(db,contracts): full v0.1 data model migrations and shared zod contracts (W1-1)
- migrations 0002-0012 split by domain (foundation/instances/content/identity/
  sources/assets/policy/execution/agent/ops/organization): 41 tables, uuid pk,
  created_at/updated_at + touch trigger, text+CHECK status sets, pgcrypto/pg_trgm
- key constraints: source_release(site_id, site_release_id), observation(feed_id, guid),
  external_identity accepted partial unique, download_task(instance_id, torrent_hash),
  one active acquisition_plan per slot, one active path_binding per entity/season,
  asset_location root+path uniqueness, organization_record change_seq/change_xid cursor
- secret table (ciphertext/nonce/kdf) + secret_ref columns; outbox dispatch fields (ADR-002)
- src/types.ts generated from the migrated schema (scripts/gen-types.ts), drift-checked in tests;
  int8 -> number, date -> string parsers; migrator accepts migrationTableSchema
- contracts: Row/Create/Update schemas per domain, public organization-record API
  (changeSeq cursor), GlobalSettings, CapabilityDescriptor + 14 capability IO schemas,
  typed SSE events, Api endpoint table
- tests: migration up/down round trip on real PG in an isolated schema, constraint checks,
  contracts<->db column/enum sync, positive/negative parse for every exported schema

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-27 18:11:37 +08:00

38 lines
1.4 KiB
TypeScript

import { type Kysely, sql } from "kysely";
// 迁移辅助:迁移以原生 DDL 书写,便于评审与对照 REQ §12。
// 注意:已发布迁移引用的辅助函数行为不得再改变,只能新增函数。
/** 执行一段不带参数的 DDL(可含多条语句,pg 简单查询协议) */
// biome-ignore lint/suspicious/noExplicitAny: 迁移不依赖应用表类型
export async function execDdl(db: Kysely<any>, ddl: string): Promise<void> {
await sql.raw(ddl).execute(db);
}
/** text 列的枚举 CHECK:`check (col in ('a','b'))` */
export function oneOf(column: string, values: readonly string[]): string {
return `check (${column} in (${values.map((v) => `'${v.replace(/'/g, "''")}'`).join(", ")}))`;
}
/**
* 标准实体表:uuid 主键 + created_at/updated_at + updated_at 自动刷新触发器。
* body 为其余列与表级约束(逗号分隔,不含首尾逗号)。
*/
export function entityTable(name: string, body: string): string {
return `
create table ${name} (
id uuid primary key default gen_random_uuid(),
${body.trim()},
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
create trigger ${name}_touch_updated_at before update on ${name}
for each row execute function umt_touch_updated_at();
`;
}
/** 按顺序 drop 表(调用方按依赖逆序传入) */
export function dropTables(names: readonly string[]): string {
return names.map((n) => `drop table if exists ${n} cascade;`).join("\n");
}