1. TypeScript 数据库编程里为什么先要搞定 settings.jsonTypeScript 做数据库编程真正让人卡住的往往不是 ORM 语法而是「连接配置散落在哪、怎么统一管」。你写一个 TypeORM 项目数据库地址、账号、密钥可能写在.env、ormconfig.json、data-source.ts三个地方再换一个 MongoDB 项目连接串又塞进代码里。项目一多配置就成了复制粘贴的重灾区。我这次要聊的落点是settings.json把数据库编程里那些「跟业务无关、但每个项目都要填」的通道参数收敛到一个 JSON 骨架里。它不替代 ORM也不替代驱动而是作为一层统一的配置入口让 TypeScript 项目在进入实体建模、Repository 编写之前先确认「通道是通的」。适合谁看已经会用 TypeScript 写 Node 服务、准备接数据库但对配置管理还没形成套路的开发者或者你手上有多套环境本地、测试、预发想让连接参数可切换、可校验。核心检索词就三个TypeScript、数据库编程、settings.json 配置骨架。下面按「先建骨架 → 再验连通 → 最后接 ORM」的顺序走每一步都能直接复制。TaoToken 在这里的角色是统一 Key/API 通道帮你把模型调用和配置校验这条链路先跑通再进数据库层开发。2. TaoToken 前置统一 Key 与 API 通道准备在写settings.json之前先把通道侧的东西准备好。TaoToken 提供统一的 Key 和 API 入口TypeScript 项目里读配置时只需要认一个 base URL 和一个 Key不用为每个模型或服务单独记地址。你需要做两件事第一拿到 API Key。登录后进入控制台在 API Keys 页面创建一个新 Key复制保存。这个 Key 后面会写进环境变量不直接进settings.json明文。第二确认 API 入口地址。统一入口是https://taotoken.net/api模型对话、编码类请求都走这里。注意这个地址不带任何查询参数保持干净。注意Key 只放环境变量或本地未提交的.envsettings.json里用占位符引用别把真实 Key 提交到 Git。如果你后面要做长期编码或 Agent 类任务可以了解 Coding Plan只是验证模型通不通用模型对话页面就够。接入细节看接入文档Key 管理在 API Keys。3. 可复制的 settings.json 骨架与 TypeScript 读取层这一节是全文的技术核心。目标一个settings.json管住通道参数一个config.ts负责读取和类型校验数据库连接层只消费配置对象。3.1 settings.json 骨架在项目根目录建config/settings.json{ channel: { baseUrl: https://taotoken.net/api, apiKeyEnv: TAOTOKEN_API_KEY, timeoutMs: 15000, retry: { maxAttempts: 3, backoffMs: 500 } }, database: { driver: postgres, host: 127.0.0.1, port: 5432, database: app_dev, user: app_user, passwordEnv: DB_PASSWORD, poolSize: 10, ssl: false }, env: development }几个设计点说明。apiKeyEnv和passwordEnv存的是「环境变量名」而不是值这样settings.json可以安全提交。retry块给通道请求留了重试空间网络抖动时不用改代码。database.poolSize是连接池大小高并发场景下比默认值更可控。3.2 用 TypeScript 定义配置类型建src/config/types.tsexport interface ChannelConfig { baseUrl: string; apiKeyEnv: string; timeoutMs: number; retry: { maxAttempts: number; backoffMs: number }; } export interface DatabaseConfig { driver: postgres | mysql | sqlite; host: string; port: number; database: string; user: string; passwordEnv: string; poolSize: number; ssl: boolean; } export interface AppSettings { channel: ChannelConfig; database: DatabaseConfig; env: development | staging | production; }类型定义的好处是settings.json里少一个字段、类型写错编译期就报出来不用等运行时连不上库才发现。3.3 读取与校验建src/config/load.tsimport { readFileSync } from fs; import { resolve } from path; import type { AppSettings } from ./types; function assertSettings(raw: unknown): asserts raw is AppSettings { const s raw as AppSettings; if (!s.channel?.baseUrl) throw new Error(settings.channel.baseUrl 缺失); if (!s.database?.driver) throw new Error(settings.database.driver 缺失); if (typeof s.database.port ! number) throw new Error(database.port 必须是数字); } export function loadSettings(): AppSettings { const file resolve(process.cwd(), config/settings.json); const raw JSON.parse(readFileSync(file, utf-8)); assertSettings(raw); return raw; } export function resolveSecret(envName: string): string { const value process.env[envName]; if (!value) throw new Error(环境变量 ${envName} 未设置); return value; }assertSettings用断言函数做最小校验resolveSecret把「环境变量名 → 实际值」这一步单独抽出来数据库层和通道层都能复用。3.4 组装数据库连接参数建src/db/connection-options.tsimport { loadSettings, resolveSecret } from ../config/load; export function buildDbOptions() { const settings loadSettings(); const db settings.database; return { type: db.driver, host: db.host, port: db.port, database: db.database, username: db.user, password: resolveSecret(db.passwordEnv), extra: { max: db.poolSize }, ssl: db.ssl, }; }到这里配置骨架就完整了settings.json存结构types.ts存类型load.ts做校验connection-options.ts产出 ORM 能直接吃的对象。TypeORM 的DataSource、Prisma 的 datasource、Knex 的 client 配置都能从这个对象映射过去。4. 验证请求确认通道与数据库都通配置写完不能直接进业务先做两步最小验证。4.1 验证通道可用建scripts/check-channel.tsimport { loadSettings, resolveSecret } from ../src/config/load; async function main() { const settings loadSettings(); const key resolveSecret(settings.channel.apiKeyEnv); const url ${settings.channel.baseUrl}/v1/models; const controller new AbortController(); const timer setTimeout(() controller.abort(), settings.channel.timeoutMs); try { const res await fetch(url, { headers: { Authorization: Bearer ${key} }, signal: controller.signal, }); console.log(通道状态码:, res.status); if (!res.ok) throw new Error(通道返回 ${res.status}); console.log(通道验证通过); } finally { clearTimeout(timer); } } main().catch((e) { console.error(通道验证失败:, e.message); process.exit(1); });运行export TAOTOKEN_API_KEY你的Key npx ts-node scripts/check-channel.ts成功时输出通道状态码: 200和通道验证通过。如果超时先看timeoutMs是不是太小再确认网络能到taotoken.net。4.2 验证数据库连通建scripts/check-db.ts以pg驱动为例import { Client } from pg; import { buildDbOptions } from ../src/db/connection-options; async function main() { const opts buildDbOptions(); const client new Client({ host: opts.host, port: opts.port, database: opts.database, user: opts.username, password: opts.password, }); await client.connect(); const res await client.query(SELECT 1 AS ok); console.log(数据库返回:, res.rows[0]); await client.end(); } main().catch((e) { console.error(数据库验证失败:, e.message); process.exit(1); });运行export DB_PASSWORD你的库密码 npx ts-node scripts/check-db.ts看到数据库返回: { ok: 1 }就说明配置骨架到真实连接这条链路是通的。两个脚本都通过后再进 TypeORM 或 Prisma 的实体层出问题就能快速定位是配置层还是 ORM 层。5. 本篇常见错排查配置骨架跑不通八成是下面几类问题。环境变量没导出。resolveSecret抛环境变量 TAOTOKEN_API_KEY 未设置说明 shell 里没export或者.env没被加载。用node --env-file.env或在入口手动dotenv.config()。settings.json 路径不对。loadSettings用的是process.cwd()如果你在子目录跑脚本config/settings.json就找不到。统一在项目根目录执行或把路径改成基于__dirname解析。端口写成字符串。settings.json里port: 5432带引号assertSettings会抛database.port 必须是数字。JSON 里数字不要加引号。通道 401。Key 复制时带了空格或者用了别的服务的 Key。重新在 API Keys 页面生成一个确认请求头是Authorization: Bearer key。数据库 ECONNREFUSED。库没启动或host/port和实际不符。先用psql或客户端工具连一次确认参数一致再回来看脚本。超时但状态码正常。把timeoutMs从 15000 调到 30000 试试同时检查是否有本地网络策略拦截了出站请求。排查顺序建议先跑check-channel.ts再跑check-db.ts两个都过再动 ORM。这样能把「通道问题」和「数据库问题」彻底分开不用在一堆堆栈里猜。6. 接下来怎么走从配置骨架到 ORM 层配置骨架验证通过后进 ORM 就顺了。TypeORM 里把buildDbOptions()的返回值喂给new DataSource({...})Prisma 里把settings.json的字段映射到schema.prisma的datasource块Knex 里直接当connection对象用。核心原则不变业务代码不碰原始连接参数只消费配置对象。如果你要长期做编码类任务比如让 Agent 自动生成 Repository 或迁移脚本可以看 Coding Plan把通道能力固定下来。只是验证模型响应用模型对话页面手动发一条就行。Key 的创建和管理在 API Keys接入细节和字段说明看接入文档。我自己的习惯是每接一个新库先复制这套settings.json骨架改database块跑两个验证脚本全绿了再写实体。这样即使后面换库、换环境改动也只集中在 JSON 里TypeScript 代码一行不用动。