fix(api): requireDatabaseUrl 早失败守卫;typecheck 门禁;build 排除 test;池生命周期注释
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
import './src/db/env.js'
|
||||
import { requireDatabaseUrl } from './src/db/env.js'
|
||||
import { defineConfig } from 'drizzle-kit'
|
||||
|
||||
// 故意不做 DATABASE_URL_TEST 回退:迁移永不指向临时测试库(Task 13 helper 用显式连接串迁移临时库)
|
||||
const url = requireDatabaseUrl({ allowTestUrl: false })
|
||||
|
||||
export default defineConfig({
|
||||
dialect: 'postgresql',
|
||||
schema: './src/db/schema.ts',
|
||||
out: './drizzle',
|
||||
dbCredentials: { url: process.env.DATABASE_URL! },
|
||||
dbCredentials: { url },
|
||||
})
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"description": "SiteForge API:NestJS 模块化单体骨架(本切片以 standalone context 供 CLI 使用,不监听端口)+ Drizzle/postgres.js 接入",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"build": "tsc -p tsconfig.build.json",
|
||||
"typecheck": "tsc -p tsconfig.json --noEmit",
|
||||
"db:generate": "drizzle-kit generate",
|
||||
"db:migrate": "drizzle-kit migrate"
|
||||
},
|
||||
|
||||
@@ -2,12 +2,10 @@ import './env.js'
|
||||
import { drizzle } from 'drizzle-orm/postgres-js'
|
||||
import postgres from 'postgres'
|
||||
import * as schema from './schema.js'
|
||||
import { requireDatabaseUrl } from './env.js'
|
||||
|
||||
// DATABASE_URL_TEST ?? DATABASE_URL 的回退链是 Task 13 集成测试的接线:
|
||||
// 测试临时库优先,开发库兜底。env 加载见 ./env.ts(向上查找仓库根 .env)。
|
||||
export function getDb(
|
||||
connectionString = process.env.DATABASE_URL_TEST ?? process.env.DATABASE_URL!,
|
||||
) {
|
||||
// 每次调用都会新建连接池、由调用方持有其生命周期;`db.$client.end()` 可关闭(drizzle-orm 0.45 已暴露)。
|
||||
export function getDb(connectionString = requireDatabaseUrl()) {
|
||||
const sql = postgres(connectionString, { max: 5 })
|
||||
return drizzle(sql, { schema })
|
||||
}
|
||||
|
||||
@@ -16,3 +16,17 @@ for (;;) {
|
||||
if (parent === dir) break
|
||||
dir = parent
|
||||
}
|
||||
|
||||
// 早失败守卫:postgres(undefined) 会静默回退到 OS 用户@localhost:5432(postgres.js 源码行为),
|
||||
// 本机多 PG 实例时 select 1 仍会通过、迁移可能打错库,故必须在建客户端前拦截。
|
||||
// allowTestUrl(默认 true):运行时连接允许 DATABASE_URL_TEST ?? DATABASE_URL 回退链(Task 13 集成测试接线);
|
||||
// 传 false 则只认 DATABASE_URL——drizzle 迁移用它,保证迁移永不指向临时测试库。
|
||||
export function requireDatabaseUrl({ allowTestUrl = true }: { allowTestUrl?: boolean } = {}): string {
|
||||
const url = (allowTestUrl ? process.env.DATABASE_URL_TEST : undefined) ?? process.env.DATABASE_URL
|
||||
if (!url) {
|
||||
throw new Error(
|
||||
'DATABASE_URL not set — copy .env.example to <repo-root>/.env (searched upward from cwd)',
|
||||
)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
@@ -9,4 +9,18 @@ describe('数据库连接', () => {
|
||||
const r = (await db.execute('select 1 as ok')) as any
|
||||
expect(Number(r[0].ok)).toBe(1)
|
||||
})
|
||||
|
||||
it('DATABASE_URL 缺失时 getDb 早失败并给出诊断信息(不静默连 localhost)', () => {
|
||||
const savedTest = process.env.DATABASE_URL_TEST
|
||||
const saved = process.env.DATABASE_URL
|
||||
delete process.env.DATABASE_URL_TEST
|
||||
delete process.env.DATABASE_URL
|
||||
try {
|
||||
// postgres(undefined) 会静默回退 OS 用户@localhost:5432,必须在此前置拦截
|
||||
expect(() => getDb()).toThrow(/DATABASE_URL not set/)
|
||||
} finally {
|
||||
if (savedTest !== undefined) process.env.DATABASE_URL_TEST = savedTest
|
||||
if (saved !== undefined) process.env.DATABASE_URL = saved
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "."
|
||||
},
|
||||
"exclude": ["test"]
|
||||
}
|
||||
Reference in New Issue
Block a user