TypeORM 开发环境搭建与构建测试实战:从克隆仓库到发布 npm 包
本文基于 TypeORM 仓库根目录的开发者指南 DEVELOPER.md,系统讲解如何搭建 TypeORM 的本地开发环境:安装依赖、配置多数据库测试连接(ormconfig.json)、用 Docker 一键拉起 13 种数据库、构建可分发的 build/package 产物、编写并快速迭代 Mocha 测试,以及 master/v0 双分支的发布流程。读完本文,你可以独立完成从克隆代码到跑通全量测试、乃至走通一次稳定版/预发布/nightly 发布的完整闭环。
一、环境前置与工具链版本
在构建和测试 TypeORM 之前,开发机上需要以下工具:
- Git:用于克隆仓库与维护 fork/upstream 远程;
- Node.js:建议使用 fnm 或 nvm 等版本管理器安装。注意 package.json 对运行环境有硬性约束:
"node": "^20.19.0 || ^22.13.0 || >=24.11.0",同时 package.json 通过"packageManager": "pnpm@10.34.4"与devEngines字段锁定了 pnpm 10.34.4,版本不符会直接报错; - 数据库(本地安装或 Docker 均可):MySQL、MariaDB、PostgreSQL 为必需测试平台;Oracle、Microsoft SQL Server 同理。
各数据库连接所需的驱动(mysql2、pg、mssql、oracledb、mongodb、better-sqlite3、sql.js、@sap/hana-client、@google-cloud/spanner 等)都声明在 package.json 的 peerDependencies(均为可选)或 devDependencies 中,pnpm install 会一并安装,无需手动处理。
官方提供了 docker-compose.yml,可以只拉起某个数据库,例如:
docker compose up postgres-17
二、获取源码
贡献者需要 Fork 并克隆仓库(可参考 CONTRIBUTING.md 的贡献规范):
- 登录你的 GitHub 账号(或注册一个);
- Fork TypeORM 主仓库到你的账号下;
- 克隆自己的 fork,并添加指向上游主仓库的
upstream远程:
# 克隆仓库(以下为镜像地址,Fork 后请替换为你自己的 fork 地址)
git clone https://gitcode.com/GitHub_Trending/ty/typeorm.git
# 进入 TypeORM 目录
cd typeorm
# 添加上游主仓库作为 upstream 远程
git remote add upstream <上游主仓库地址>
三、安装依赖与配置 ormconfig.json
3.1 安装依赖
pnpm install
3.2 创建测试配置文件
cp ormconfig.sample.json ormconfig.json
ormconfig.sample.json 是一个 JSON 数组,每个元素描述一种数据库驱动的测试连接,示例文件共包含 13 条配置,覆盖:aurora-mysql、aurora-postgres(默认 "skip": true,因为需要 AWS RDS Data API 凭据)、better-sqlite3、cockroachdb、mariadb、mongodb、mssql、mysql、oracle、postgres、sap(HANA Express)、spanner、sqljs。
其中两个控制字段决定了测试会连接哪些数据库,语义定义在 test/utils/test-utils.ts:
| 字段 | 作用 | 源码行为 |
|---|---|---|
skip |
true 时该连接永远不参与测试 |
setupTestingConnections 中 if (connectionOptions.skip === true) return false |
disabledIfNotEnabledImplicitly |
true 时,除非测试代码显式声明 enabledDrivers 包含该驱动,否则不启用 |
同文件 L243-L244 的过滤分支(如示例中的 mongodb 条目) |
示例中的账号口令与 docker-compose.yml 中各容器注入的环境变量一一对应(如 Postgres 的 username/password、MariaDB 的 root/admin、MSSQL 的 sa/Admin12345 加 trustServerCertificate: true),因此只要按 compose 文件启动容器,即可直接复用示例配置,只需把不想跑的数据库标记 "skip": true 即可。
配置文件位置的解析逻辑见 getOrmFilepath:优先找 build/compiled/ormconfig.json(便于在 Docker CI 中注入自定义配置),找不到再回退到仓库根目录;两者都不存在时会抛出明确报错提示你从 ormconfig.sample.json 复制。
四、用 Docker 一键启动全部数据库
除了单个数据库,可以在项目根目录直接运行 docker compose up 拉起 docker-compose.yml 中的全部 13 个服务,再执行测试。各服务的镜像与端口映射如下:
| 服务 | 镜像 | 宿主机端口 | 备注 |
|---|---|---|---|
mysql-5 |
mysql:5.7.44 |
3306 | 与 mysql-9 共用 3306,二者不要同时跑 |
mysql-9 |
mysql:9.5.0 |
3306 | 同上 |
mariadb-10 |
mariadb:10.11.16 |
3307 | 与 mariadb-12 共用 3307 |
mariadb-12 |
mariadb:12.2.2 |
3307 | 同上 |
postgres-14 |
ghcr.io/typeorm/docker:postgres-14.22-postgis-3.6.2-pgvector-0.8.2 |
5432 | 内置 PostGIS + pgvector |
postgres-17 |
ghcr.io/typeorm/docker:postgres-17.9-postgis-3.6.2-pgvector-0.8.2 |
5432 | 同上 |
mssql |
mcr.microsoft.com/mssql/server:2025-latest |
1433 | Express 版 |
cockroachdb |
cockroachdb/cockroach:v24.3.8 |
26257 | 单节点 insecure 模式 |
oracle |
container-registry.oracle.com/database/free:23.7.0.0-lite |
1521 | 启动脚本挂载自 docker/oracle/startup |
spanner |
roryq/spanner-emulator:latest |
9010/9020 | Spanner 模拟器 |
hanaexpress |
saplabs/hanaexpress:2.00.088... |
39041 | 仅 Linux,Docker 至少 10GB 内存 |
mongodb |
mongo:8.2.5 |
27017 | — |
两个资源提示(来自 DEVELOPER.md):
- MSSQL Server 镜像至少需要 3.25GB 内存;
- 在 Docker for Mac / Windows 上请为 Docker 虚拟机分配足够的内存。
注意同一端口冲突的服务(两个 MySQL、两个 MariaDB、两个 Postgres)不能同时运行,按你要测的驱动挑一个即可。
五、构建可分发包(pnpm run package)
构建 TypeORM 的分发产物:
pnpm run package
该命令在 package.json 中映射为 gulp package,其任务编排见 gulpfile.ts:先清空 ./build,然后并行执行「拷贝浏览器端源码(排除 src/commands/、src/cli.ts 等 Node 专属模块)+ 拷贝 src/platform/*.template 平台模板」与「tsc -p tsconfig.node.json / tsc -p tsconfig.browser.json 双端编译」,最后生成 ESM 入口、整理 package.json、拷贝 README 与 shim 文件。完成后:
build/package目录:一个可以直接使用(npm link或整体拷贝)的 TypeORM 发行目录。你可以把它链接或拷贝到项目里测试(注意保留 TypeORM 所需的node_modules);- 其中的 copyPackageFile 步骤会剥离开发脚本,但特意保留
@types/node、ts-node、typescript三个 devDependency——因为typeorm init命令生成脚手架项目时要把它们写进目标项目的package.json; - 生成的
index.mjs由 nodeCreateEsmIndex 动态扫描 CJS 导出生成,保证import与require的具名导出一致(对应 package.json 的exports双入口设计)。
打成 npm tar 包:
cd build/package && pnpm pack
会在 build 目录生成 build/typeorm-x.x.x.tgz(版本号取自 package.json,当前仓库版本为 1.1.0,即 v1.x 稳定线)。你可以把 tar 包拷入任意项目,然后:
npm install ./typeorm-x.x.x.tgz
即可把你本地构建的 TypeORM 打进依赖。
六、本地编写与运行测试
6.1 测试基建与标准模板
仓库鼓励「改代码的 PR 附带相应测试」。新测试应参考 test/functional/ 下已有的功能测试,视情况新建 .test.ts 文件或修改现有文件;如果是针对某个 GitHub issue 的回归测试,请在测试中用注释注明 issue 编号(仓库 test/github-issues/ 目录即按 issue 编号组织)。
测试统一使用 test/utils/test-utils.ts 提供的工具函数,标准模板如下(与 DEVELOPER.md 一致,可原样复制):
import { expect } from "chai"
import {
closeTestingConnections,
createTestingConnections,
reloadTestingDatabases,
} from "../../../utils/test-utils"
import { DataSource } from "../../../../src/data-source/DataSource"
describe("description of the functionality you're testing", () => {
let dataSources: DataSource[]
before(
async () =>
(dataSources = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: true,
dropSchema: true,
})),
)
beforeEach(() => reloadTestingDatabases(dataSources))
after(() => closeTestingConnections(dataSources))
// optional: test fix for issue https://github.com/typeorm/typeorm/issues/<issue-number>
it("should <put a detailed description of what it should do here>", () =>
Promise.all(
dataSources.map(async (dataSource) => {
// tests go here:
expect(result).to.equal(expected)
}),
))
// you can add additional tests if needed
})
模板要点,结合源码进一步说明:
- 同一用例在多个数据库上重复执行:
createTestingConnections会遍历ormconfig.json中所有启用的连接,为每个驱动new DataSource(options).initialize()(见 createTestingConnections),因此it内部用Promise.all(dataSources.map(...))对每个连接断言,一份用例天然覆盖多种 DBMS; - 实体自动加载:把实体放在测试文件同级的
./entity/<entity-name>.ts中即会被加载——setupTestingConnections 会把__dirname选项转写为entities: [__dirname + "/entity/*{.js,.ts}"]与migrations: [__dirname + "/migration/*{.js,.ts}"]两个 glob; schemaCreate/dropSchema:前者映射为连接的synchronize: true(建表),后者在连接建立时先清库;beforeEach中的reloadTestingDatabases负责在每个用例前重置数据,保证用例间隔离;- 驱动级裁剪:
createTestingConnections的TestingOptions(test/utils/test-utils.ts)还支持enabledDrivers/disabledDrivers(按 L230-L247 的过滤链:先skip,再disabledDrivers,再enabledDrivers,最后disabledIfNotEnabledImplicitly)、cache(database/redis 缓存策略)、namingStrategy、metadataTableName、relationLoadStrategy("join"或"query")等参数,用于针对特定驱动行为编写用例。个别数据库还有额外初始化,例如 createTestingConnections 会为 CockroachDB 调低副本数、为 MySQL 打开performance_schema的事务事件,支撑其性能相关测试。
6.2 运行测试
先确保已复制 ormconfig.sample.json 为 ormconfig.json 并替换为你本地的连接参数。测试会对文件中每个定义的数据库各跑一遍;如果你改动的功能与特定数据库无关,可以删掉部分连接对象(或置 "skip": true)来加快反馈速度。
pnpm run test
从 package.json 可见其实际为 pnpm run compile && pnpm run test:fast --:先删除旧产物、重新编译整个 TypeScript 代码库,再用 Mocha 执行。Mocha 的运行细节由 .mocharc.json 决定:只运行 ./build/compiled/test/**/*.test.{js,ts} 下的编译产物(这就是必须先 compile 的原因)、单测超时 90 秒、加载 test/utils/test-setup.js 全局初始化文件、开启泄漏检查(mongodb@7.2+ 的 allowedDriverRequire 已被列入白名单)。另有 pnpm run test:ci 即 mocha --bail,供 CI 首个失败即中止。
提交 PR 前应确认测试套件通过:PR 会在 GitHub Actions 上跑测试(需审批后触发),你的 fork 仓库自身也应能跑 CI;所有测试通过是 PR 合并的前提。
6.3 只运行部分测试
方式一:给目标 describe / it 临时加上 Mocha 的 .only(对应 describe.only、it.only):
describe.only('your describe test', ....)
方式二:用 --grep 传正则给 Mocha,只有匹配的 describe/it 会执行:
pnpm run test -- --grep "your test name"
(test 脚本末尾的 -- 会把参数原样透传给 Mocha。)
6.4 更快的开发循环
pnpm run test 每次都会删除已构建的 TypeScript 代码并全量重编,耗时较长。更快的节奏是:
pnpm run compile -- --watch
这会先做一次全新构建,随后让 TypeScript 进入 watch 模式、只增量编译你改动的代码(compile 脚本为 gulp clean && tsc,--watch 最终附加在 tsc 上)。编译完成后改用:
pnpm run test:fast
test:fast 直接执行 mocha(package.json),不再触发重编译,从而显著加快「改代码 → 看结果」的循环。
七、发布流程:双分支与 npm 发布
TypeORM 维护两条活跃分支(与 DEVELOPER.md 的表格一致):
| 分支 | npm dist-tag(稳定版) | npm dist-tag(nightly) | 定位 |
|---|---|---|---|
master |
latest |
dev |
v1.x(稳定线,当前仓库版本 1.1.0) |
v0 |
legacy |
nightly |
v0.3.x(遗留线) |
发布由 publish-package.yml 工作流承担,采用 npm Trusted Publishing(OIDC),全程无需 npm token。该工作流有单文件约束(Trusted Publishing 每个包只支持一个工作流文件),因此稳定版、预发布、nightly 的逻辑全部收敛在这一个文件里,由三个触发器驱动:release: published 事件、Cron 定时任务 0 2 * * *(即每天 02:00 UTC)、以及 workflow_dispatch 手动触发(可选目标 release / master / v0)。
7.1 稳定版(Stable release)
- 从目标分支拉出发布分支(例如从
v0拉release-0.3.32,或从master拉release-1.1.1); - 更新 package.json 中的版本号;
- 运行
pnpm run changelog(即 package.json 中映射的standard-changelog)生成变更日志; - 提交变更并创建指向发布分支的 Pull Request;
- 合并后,创建与版本号一致的 GitHub Release(如
0.3.32或1.1.1)并打同名 tag; - 工作流被
release: published事件触发,自动发布到 npm。dist-tag 按规则自动判定:版本号大于 npm 上当前latest时打latest,否则打legacy(工作流头部注释明确了该判定,防止旧分支覆盖新发布)。
7.2 预发布(Pre-release,面向 v1.0 阶段)
- 从
master拉分支(如release-1.0.0-alpha.2); - 更新 package.json 版本号为预发布标识(如
1.0.0-alpha.2); - 运行
pnpm run changelog生成变更日志; - 提交变更并创建指向
master的 Pull Request; - 合并后,从
master创建带匹配 tag 的 GitHub Release,并勾选 pre-release; - 工作流发布到 npm 时自动使用
nextdist-tag——任何包含预发布标识(如-alpha、-beta)的版本号都会被判定为next。
7.3 Nightly 构建
master 与 v0 的 nightly 版本在每天 02:00 UTC 自动发布,前提是「自上一次 nightly 发布以来有新 commit」(工作流通过对比 HEAD 与该 dist-tag 最近一次发布记录的 gitHead 实现跳过逻辑),也可通过 workflow_dispatch 手动触发。nightly 在 npm 上的 dist-tag 为:master → dev,v0 → nightly。定时触发时还会为两条分支分别指定 Node 版本(master 用 Node 24,v0 用 Node 20,见 publish-package.yml 的 matrix 逻辑)。
小结
围绕 DEVELOPER.md 的主线,TypeORM 开发者工作流可归纳为:pnpm install + cp ormconfig.sample.json ormconfig.json 完成环境准备 → docker compose up(或单库 docker compose up postgres-17)准备数据库 → pnpm run test(日常迭代用 compile -- --watch + test:fast + --grep 提速)→ pnpm run package / pnpm pack 产出可分发包 → 按双分支策略走稳定版、预发布或 nightly 发布。所有关键机制——连接过滤(skip / disabledIfNotEnabledImplicitly)、Mocha 编译产物规格(.mocharc.json)、打包管线(gulpfile.ts)与发布矩阵(publish-package.yml)——都可以在上述仓库文件中逐行查证。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00