Directus 沙箱 sandbox() 函数全解析为测试与开发一键拉起可编程的 API 实例【免费下载链接】directusThe flexible backend for all your projects Turn your DB into a headless CMS, admin panels, or apps with a custom UI, instant APIs, auth more.项目地址: https://gitcode.com/GitHub_Trending/di/directus在 Directus 的 tests/sandbox/readme.md 中官方提供了一套名为directus/sandbox的工具包它把“准备数据库、引导 schema、以指定环境变量启动 API”这一整套繁琐流程封装成可复用的函数与 CLI用于黑盒测试、开发调试与 CI 场景。本文以 TypeDoc 自动生成的 API 参考文档 tests/sandbox/docs/_media/sandbox.md 为核心骨架结合 sandbox() 的源码实现 与配套的dockercompose 文件、环境变量生成逻辑系统讲解sandbox()函数的全部参数、返回对象与底层工作流帮助你掌握如何用几行 TypeScript 代码按需拉起/销毁一套隔离的 Directus 运行环境。sandbox()是什么函数签名与定位directus/sandbox是 Directus 仓库内用于测试与开发的沙箱工具提供两种交互方式CLI 命令行与JS/TS API。其中 JS API 的入口就是本文主角sandbox()sandbox(database, options?): PromiseSandbox在代码层面它定义于 tests/sandbox/src/sandbox.ts:258完整的类型约束为export type Database ExcludeDatabaseClient, redshift | maria;即第一个参数必须取自 tests/sandbox/src/sandbox.ts:26 声明的类型运行时函数还会做一次白名单校验传入非受支持的值会直接抛出Invalid database providedexport const databases: Database[] [maria, cockroachdb, mssql, mysql, oracle, postgres, sqlite] as const;从源码结构tests/sandbox/src/sandbox.ts:258-347可以推断sandbox()内部遵循一条顺序固定的启动流水线build → license → dockerUp → bootstrap → loadSchema → startApi → startApp任一步骤抛出异常都会触发stop()做全量清理后再向上抛出保证失败场景下不留残留进程。参数 database支持哪些数据库引擎database为必填参数可选项与 tests/sandbox/src/index.ts 导出、并在 tests/sandbox/src/cli.ts:8 中作为 CLI 的choices保持一致database 值底层连接默认镜像/版本见 config.tsmariamysqlMariaDBDB_VERSION: 11mysqlmysqlMySQL8.4postgrespgPostgreSQL18-3.6-alpinecockroachdbcockroachdblatest-v25.3mssqlmssqlSQL Server2022-latestoracleoracledbOracle21-slim-faststartsqlitesqlite3无需 Docker文件型./test.db各 Docker 化数据库的启动编排定义在 tests/sandbox/src/docker/ 目录下的 compose 文件里例如postgres.yml、mysql.yml、oracle.yml、cockroachdb.yml等沙箱启动时会按需读取并执行。options 详解从build到hooks的全部开关options是可选的深度部分覆盖对象类型上为DeepPartialOptionsOptions完整定义见 tests/sandbox/src/sandbox.ts:28-90。其默认值由getOptions()使用lodash-es的merge合并生成tests/sandbox/src/sandbox.ts:112-152。下面按官方 API 文档 tests/sandbox/docs/_media/sandbox.md 的参数顺序逐项展开。构建与运行模式build/dev/watchbuild?: boolean是否每次启动沙箱前从源码重新构建 Directus。默认false。dev?: boolean以开发模式启动 Directus。与build互斥源码中通过if (opts.build !opts.dev)条件保证二者不会同时生效对应NODE_ENV会被设为development。watch?: boolean监听源码改动并自动重启 API适合快速迭代。构建流程会随之联动buildApi(opts, logger, restartApis)把重启回调传入构建进程。API 端口与实例port/instances/killPortsport?: stringAPI 启动端口。默认取8055process.env.PORT存在时优先见 tests/sandbox/src/sandbox.ts:115。getPort()会自动寻找空闲端口。instances?: string水平扩展的 API 实例数量默认1。当实例数 1 时redis会被强制开启用于缓存同步。killPorts?: boolean强制杀掉占用 API 所需端口的所有进程后再启动。Docker 行为dockerdocker是一个子对象默认见 tests/sandbox/src/sandbox.ts:42-51docker.keep?: boolean调用stop()时是否保留容器运行。默认false即停止沙箱时容器也会被回收置为true可在下次启动时复用已有容器大幅缩短启动耗时。docker.name?: string覆盖 Docker 项目名。docker.suffix?: string为 Docker 项目名追加后缀可保证多套沙箱互不冲突该选项存在于源码Options类型中见 sandbox.ts:49CLI 侧对应--docker.suffix。docker.basePort?: stringDocker 容器端口分配的下限。CLI 默认使用8100–8200区间见 tests/sandbox/src/cli.ts:46端口内存在$PORT、$PORT_LICENSE之类的占位符会被动态替换。环境变量注入envenv?: Recordstring, string以键值对形式追加 API 启动所需的环境变量。在getEnv()的合并顺序中处于较高优先级见 tests/sandbox/src/config.ts:148-177可覆盖数据库连接、认证、缓存等配置。日志辅助prefixprefix?: string为日志加前缀。当同时启动多个沙箱时非常有用可区分不同实例的输出。Schema 快照schemaschema?: string启动时额外加载一份 schema snapshotJSON 快照文件路径。注意一处便捷行为当传入schema: true时源码会自动将其改写为snapshot.jsontests/sandbox/src/sandbox.ts:113。其加载发生在bootstrap之后、API 启动之前。调试与诊断inspectinspect?: boolean是否以调试器模式--inspect启动 API默认true。CLI 中该选项同样默认开启tests/sandbox/src/cli.ts:14。周期导出exportexport?: boolean每 2 秒导出一份 schema snapshot 与类型定义。源码通过saveSchema(env)返回的setInterval句柄实现在stop()中会被clearInterval清理见 sandbox.ts:289 与 sandbox.ts:321。适合在开发过程中持续观察 schema 变化产物。附加服务extrasextras子对象用于开启可选的“周边”容器默认全部false定义见 tests/sandbox/src/sandbox.ts:66-78字段类型作用对应 docker 编排extras.redisboolean缓存用 Redis实例数 1 时被强制置为truetests/sandbox/src/docker/redis.ymlextras.maildevbooleanSMTP 邮件服务器开发时拦截邮件tests/sandbox/src/docker/maildev.ymlextras.miniobooleanS3 兼容对象存储文件上传测试用tests/sandbox/src/docker/minio.ymlextras.samlbooleanSAML 认证服务tests/sandbox/src/docker/saml.ymlextras对应的环境变量注入在 config.ts 中集中定义例如开启minio会注入STORAGE_LOCATIONS: minio,local及完整的 S3 驱动参数开启saml会注入AUTH_PROVIDERS: saml与 SP/IdP 两段 metadata 证书。缓存开关cachecache?: boolean是否启用缓存默认false。该值会映射为环境变量CACHE_ENABLED与REDIS_ENABLED见 config.ts:154-155。其他可用选项源码补充API 文档未逐条列出、但在Options类型与 CLI 中存在的补充选项还包括app?: boolean | Port是否同时以开发模式拉起前端 app 并连接 APIsandbox()中默认在opts.app ! false时启动见 sandbox.ts:287。CLI 对应-a, --app [port]。dbVersion?: string覆盖数据库镜像版本CLI--db-version设置后覆盖DB_VERSION见 config.ts:179-181。silent?: boolean除错误外静默全部日志CLI--silent。skipSetup?: boolean跳过初始 admin/owner 的创建否则默认注入adminexample.com/ 密码pw/ tokenadmin见 config.ts:157-164。knex?: boolean额外打开一条 Knex 连接通过sandbox.knex直接访问数据库便于断言库内数据。hooks.beforeApi?在 bootstrap与 schema 加载之后、API 启动之前执行的生命周期钩子回调上下文携带{ env, logger, knex? }。返回值Sandbox对象结构sandbox()返回PromiseSandbox。Sandbox类型别名见 tests/sandbox/docs/type-aliases/Sandbox.md 与 sandbox.ts:103-110包含以下成员成员类型说明envEnv沙箱实际使用的完整环境变量含数据库连接、PORT、PUBLIC_URL、admin 凭据等loggerLogger当前沙箱的日志器实例apis[Api, ...Api[]]已启动的 API 进程/端口列表测试代码通过apis[0].port拼接请求地址knexKnex \| undefined开启knex选项时的数据库直连句柄restartApi()() Promisevoid杀死当前 API 进程并重启。注意实现细节sandbox.ts:296-316重启前会重新解析端口——被杀的 API 可能让旧端口短暂处于TIME_WAIT此时getPort会自动回退到空闲端口并把新端口同步回opts.port、env.PORT与env.PUBLIC_URLstop()() Promisevoid停止整个沙箱清理导出定时器、杀掉 build/API/app/license 子进程、销毁 knex 连接并打印耗时统计apis通过 getter 暴露sandbox.ts:343-345保证restartApi()重新赋值后调用方始终拿到最新实例。最小可运行示例参照 tests/sandbox/readme.md 中给出的用法一个完整的起停流程如下import { sandbox } from directus/sandbox; const sb await sandbox(postgres, { dev: true }); // 通过 REST / GraphQL / WebSocket 与实例交互 const result await fetch(http://localhost:${sb.apis[0].port}/items/articles); console.log(await result.json()); // 结束时清理全部资源 await sb.close();若需要直接断言数据库状态可叠加knex与hooksconst sb await sandbox(postgres, { knex: true, hooks: { beforeApi: async ({ env, logger }) { logger.info(API 即将监听 ${env.PORT}); }, }, }); // 直连数据库做数据校验 const rows await sb.knex(articles).select(*); await sb.stop();多实例场景sandboxes()与 CLI并行拉起多套沙箱如需同时对多个数据库运行同一套测试使用sandboxes()签名见 tests/sandbox/docs/_media/sandboxes.md实现见 sandbox.ts:173-256。它接收一个由{ database, options }组成的数组内部通过Promise.all并发启动并提供统一的stop()与restartApis()const multi await sandboxes([ { database: sqlite, options: { schema: snapshot.json } }, { database: postgres, options: { env: { DB_PASSWORD: secret } } }, ], { dev: true });值得注意的是其公共 options 只允许覆盖build、dev、watch三项各沙箱自身的差异化配置须放在各自的options中类型定义见 sandbox.ts:168-171。与 CLI 的参数映射CLI入口 tests/sandbox/src/cli.ts本质上是对sandbox()的一层薄封装两者参数一一对应sandbox postgres \ --dev \ --port 8055 \ --instances 2 \ --extras redis,minio,maildev \ --env KEYVALUE \ --schema snapshot.json \ --docker.port 8100 \ --docker.keepCLI 解析后调用sandbox(database, options)其中extras的a,b,c逗号串会被转换为{ a: true, b: true, c: true }cli.ts:51-57。CLI 进程会监听SIGINT/SIGTERM在退出前调用sb.stop()做资源回收cli.ts:60-69——因此通过编程方式使用sandbox()时同样记得在测试收尾或进程退出处显式调用stop()。底层工作流一次sandbox()调用做了什么根据 tests/sandbox/readme.md 的 Inner workings 章节并结合源码一次调用会按序执行以下步骤依配置不同部分步骤会被跳过构建 API可选开启build时每次启动都会重新构建 Directus配合watch可快速迭代。启动 Docker 容器拉起所需数据库与extrasredis/minio/saml/maildev 等容器并等待其健康。若容器仍在运行则直接复用不重复创建——这正是docker.keep存在的意义。引导数据库bootstrap若库尚未引导补齐 Directus 所需的全部系统表。加载 schema 快照可选设置了schema选项时在启动前将快照应用到数据库。启动 API以正确的环境变量启动一个或多个 API 实例。启动 app可选开启app时以开发模式拉起前端并连接 API。沙箱运行所需的整套环境变量由getEnv()生成tests/sandbox/src/config.ts:148-201它内置了一批贴近真实的默认值SECRET: directus-test、TELEMETRY: false、RATE_LIMITER_ENABLED: false、WEBSOCKETS_ENABLED: true、ACCESS_TOKEN_TTL: 25d等并把env参数、PORT/PUBLIC_URL作为最终权威值合入保证进程实际绑定端口与测试可访问端口始终一致。何时使用sandbox()适用场景小结综合官方定位quickly spinning up and down instances of directus for usage such as testing or development与仓库内实现sandbox()最典型的落地场景包括黑盒 API 测试在测试套件beforeAll中拉起sqlite/postgres沙箱通过真实 HTTP 请求断言/items、认证、GraphQL 与 WebSocket 行为多数据库兼容性验证利用sandboxes()在maria、mssql、oracle等不同引擎上重复执行同一套用例仓库的tests/blackbox与tests/e2e即遵循此思路扩展开发与调试用devwatchinspect快速验证扩展代码用app同时预览前端schema 演进观察开启export周期导出快照或借助schema加载既有快照还原特定库结构。需要提醒的是使用本工具依赖 Docker 环境与仓库内预置的镜像编排文件sqlite是唯一不依赖 Docker 的数据库选项适合无容器环境下的快速验证。【免费下载链接】directusThe flexible backend for all your projects Turn your DB into a headless CMS, admin panels, or apps with a custom UI, instant APIs, auth more.项目地址: https://gitcode.com/GitHub_Trending/di/directus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考