chore(deno): migrate toolchain from Node 24 + pnpm to Deno 2.9.7 + TypeScript 7.0.2 (W1.5)
- root deno.json workspace (nodeModulesDir auto), npm versions registered once in imports, deno.lock; remove pnpm-lock/pnpm-workspace/root package.json; members keep minimal package.json (name/type/exports) - tasks: dev, typecheck (tsc 7.0.2 per member + deno check), lint/fmt (biome, useImportExtensions), test (vitest via deno), check:tokens, build (web + deno compile), ci, db:migrate/reset, gen:types - tsconfig base moved to config/ (no root tsconfig.json); deno types -> types/deno.d.ts; web drops baseUrl - server: Deno.serve entry with graceful shutdown, --role migrate|preflight|probe, WEB_ROOT static SPA hosting; drop @hono/node-server, tsx, esbuild build.mjs - logger: redact child() bindings and serialize err by message/stack; sync stdout destination; tests - relative imports get explicit extensions (sites/mp-sync paths left for follow-up) - crash-recovery tests spawn `deno run -A`; tasks tests use unique per-file schemas - single-container Dockerfile + entrypoint (migrate -> preflight -> api+worker watchdog), docker-compose.yml - docs: README, runbook, ADR-001 superseded, plan §1 validation row Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
1 parent
d9f2af2f3c
commit
304feea141
226 files changed
+6601
-8620
No files matched your search
@@ -5,7 +5,7 @@ PostgreSQL 访问层:Kysely 客户端与连接池、表类型(`src/types.ts`)、
|
||||
## 规则
|
||||
|
||||
- **迁移是唯一事实来源**。所有 schema 变更只能新增迁移,已发布迁移不得修改。迁移用原生 DDL 书写(`src/migration-helpers.ts`:`entityTable()` 统一加 uuid 主键 `gen_random_uuid()`、`created_at/updated_at` 与 updated_at 触发器;`oneOf()` 生成状态 CHECK)。`migrations/` 内相对导入必须带 `.ts` 扩展名(Kysely 用原生 `import()` 加载)。
|
||||
- **`src/types.ts` 是生成物**:`pnpm db:migrate && pnpm --filter @umt/db gen:types`。CHECK 枚举自动变成字面量联合(如 `AcquisitionSlotStatus`)。`test/schema.test.ts` 会在隔离 schema 里重新反射并比对,漂移即失败;`packages/contracts/test/db-sync.test.ts` 再校验 contracts 的 Row schema 与枚举和这里一致。
|
||||
- **`src/types.ts` 是生成物**:`deno task db:migrate && deno task gen:types`。CHECK 枚举自动变成字面量联合(如 `AcquisitionSlotStatus`)。`test/schema.test.ts` 会在隔离 schema 里重新反射并比对,漂移即失败;`packages/contracts/test/db-sync.test.ts` 再校验 contracts 的 Row schema 与枚举和这里一致。
|
||||
- 状态列一律 `text + CHECK`,不用 PG enum(便于迁移加值)。JSONB 只放证据、规则参数、原文快照与演进字段;稳定查询字段用关系列。
|
||||
- 凭证只存 `secret_ref`(→ `secret.id`),明文不入库、不进日志。
|
||||
- `createDb()` 把 `int8` 解析为 `number`(超出 2^53 抛错)、`date` 保持 `YYYY-MM-DD` 字符串。写 jsonb 数组时须先 `JSON.stringify`(pg 会把 JS 数组当 PG 数组)。
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@umt/db",
|
||||
"version": "0.0.0",
|
||||
"exports": { ".": "./src/index.ts" },
|
||||
"tasks": {
|
||||
"test": "deno run -A npm:vitest run",
|
||||
"typecheck": "deno run -A npm:typescript/tsc --noEmit -p tsconfig.json",
|
||||
"migrate": "deno run -A --env-file=../../.env scripts/migrate.ts latest",
|
||||
"reset": "deno run -A --env-file=../../.env scripts/migrate.ts reset",
|
||||
"gen:types": "deno run -A --env-file=../../.env scripts/gen-types.ts"
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,8 @@
|
||||
{
|
||||
"name": "@umt/db",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"typecheck": "tsc -p tsconfig.json",
|
||||
"test": "vitest run",
|
||||
"migrate": "tsx --env-file-if-exists=../../.env scripts/migrate.ts latest",
|
||||
"reset": "tsx --env-file-if-exists=../../.env scripts/migrate.ts reset",
|
||||
"gen:types": "tsx --env-file-if-exists=../../.env scripts/gen-types.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"kysely": "^0.29.6",
|
||||
"pg": "^8.23.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/pg": "^8.23.1"
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { fileURLToPath } from "node:url";
|
||||
import { type Kysely, sql } from "kysely";
|
||||
|
||||
// 从已迁移的数据库反射出 src/types.ts:列类型 + CHECK (col in (...)) 枚举字面量联合。
|
||||
// 迁移是唯一事实来源;改表后运行 `pnpm --filter @umt/db gen:types`,测试会校验两者无漂移。
|
||||
// 迁移是唯一事实来源;改表后运行 `deno task gen:types`,测试会校验两者无漂移。
|
||||
|
||||
interface ColumnInfo {
|
||||
table_name: string;
|
||||
@@ -73,7 +73,7 @@ export async function generateTypesSource(db: Kysely<any>): Promise<string> {
|
||||
|
||||
const out: string[] = [
|
||||
"// 本文件由 scripts/gen-types.ts 从迁移后的数据库反射生成,请勿手改。",
|
||||
"// 改表:新增迁移 → pnpm db:migrate → pnpm --filter @umt/db gen:types。",
|
||||
"// 改表:新增迁移 → deno task db:migrate → deno task gen:types。",
|
||||
"",
|
||||
'import type { ColumnType, Generated, Insertable, Selectable, Updateable } from "kysely";',
|
||||
"",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// 用法:tsx scripts/gen-types.ts —— 对 DATABASE_URL 的当前 schema 反射并重写 src/types.ts
|
||||
// 用法:deno task gen:types —— 对 DATABASE_URL 的当前 schema 反射并重写 src/types.ts
|
||||
import { writeFileSync } from "node:fs";
|
||||
import { createDb } from "../src";
|
||||
import { formatWithBiome, generateTypesSource, TYPES_FILE } from "./gen-types-lib";
|
||||
import { createDb } from "../src/index.ts";
|
||||
import { formatWithBiome, generateTypesSource, TYPES_FILE } from "./gen-types-lib.ts";
|
||||
|
||||
const db = createDb({ max: 1 });
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// 用法:tsx scripts/migrate.ts latest|reset
|
||||
import { createDb, migrateToLatest, resetSchema } from "../src";
|
||||
// 用法:deno task db:migrate / db:reset(= deno run -A --env-file=.env packages/db/scripts/migrate.ts latest|reset)
|
||||
import { createDb, migrateToLatest, resetSchema } from "../src/index.ts";
|
||||
|
||||
const cmd = process.argv[2] ?? "latest";
|
||||
const db = createDb({ max: 1 });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Kysely, PostgresDialect } from "kysely";
|
||||
import pg from "pg";
|
||||
import type { DB } from "./types";
|
||||
import type { DB } from "./types.ts";
|
||||
|
||||
// int8 → number(大小/序号都在 2^53 内;超出即报错而不是静默丢精度)
|
||||
pg.types.setTypeParser(pg.types.builtins.INT8, (v: string) => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// 统一从本包取 Kysely 与 sql,避免各包各装一份 kysely
|
||||
export { type Kysely, sql, type Transaction } from "kysely";
|
||||
export { type CreateDbOptions, createDb } from "./client";
|
||||
export { createMigrator, MIGRATIONS_DIR, type MigratorOptions, migrateToLatest, resetSchema } from "./migrator";
|
||||
export type * from "./types";
|
||||
export { type CreateDbOptions, createDb } from "./client.ts";
|
||||
export { createMigrator, MIGRATIONS_DIR, type MigratorOptions, migrateToLatest, resetSchema } from "./migrator.ts";
|
||||
export type * from "./types.ts";
|
||||
@@ -1,5 +1,5 @@
|
||||
// 本文件由 scripts/gen-types.ts 从迁移后的数据库反射生成,请勿手改。
|
||||
// 改表:新增迁移 → pnpm db:migrate → pnpm --filter @umt/db gen:types。
|
||||
// 改表:新增迁移 → deno task db:migrate → deno task gen:types。
|
||||
|
||||
import type { ColumnType, Generated, Insertable, Selectable, Updateable } from "kysely";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { readdirSync } from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { MIGRATIONS_DIR } from "../src";
|
||||
import { MIGRATIONS_DIR } from "../src/index.ts";
|
||||
|
||||
describe("migrations", () => {
|
||||
it("迁移文件按 NNNN_name.ts 命名且导出 up/down", async () => {
|
||||
|
||||
@@ -3,8 +3,8 @@ import { Kysely, PostgresDialect, sql } from "kysely";
|
||||
import { NO_MIGRATIONS } from "kysely/migration";
|
||||
import pg from "pg";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
||||
import { formatWithBiome, generateTypesSource, TYPES_FILE } from "../scripts/gen-types-lib";
|
||||
import { createMigrator, type DB, migrateToLatest } from "../src";
|
||||
import { formatWithBiome, generateTypesSource, TYPES_FILE } from "../scripts/gen-types-lib.ts";
|
||||
import { createMigrator, type DB, migrateToLatest } from "../src/index.ts";
|
||||
|
||||
// 对真实 PG(默认开发库 55433)跑迁移往返;每次测试用独立 schema,互不干扰且不碰 public。
|
||||
// 无数据库环境可设 UMT_SKIP_DB_TESTS=1 跳过(CI 默认要求数据库可用)。
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
// 迁移文件由 Kysely FileMigrationProvider 用原生 import() 加载(Node 类型剥离,不做无扩展名解析),
|
||||
// 因此 migrations/ 内相对导入必须写 .ts 扩展名
|
||||
"allowImportingTsExtensions": true
|
||||
},
|
||||
"extends": "../../config/tsconfig.base.json",
|
||||
"include": ["src", "test", "scripts", "migrations"]
|
||||
}
|
||||
Reference in new issue
Block a user