十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

InsForge 共享 Schemas 开发指南:用 Zod 契约统一跨包 API 数据层

InsForge 共享 Schemas 开发指南:用 Zod 契约统一跨包 API 数据层 InsForge 共享 Schemas 开发指南用 Zod 契约统一跨包 API 数据层【免费下载链接】InsForgeThe all-in-one, open-source backend platform for agentic coding. InsForge gives your coding agent database, auth, storage, compute, hosting, and AI gateway to ship full-stack apps end-to-end.项目地址: https://gitcode.com/GitHub_Trending/in/InsForgeInsForge 是一个面向 Agent 编程场景的开源后端平台BaaS其仓库采用 monorepo 结构包含backendExpress 服务端、packages/dashboard管理面板、packages/uiUI 组件库等多个包。当同一个请求/响应/领域数据结构被多个包同时使用时如何保证前后端契约一致、类型可信、演进可控就成了工程质量的核心问题。本文基于仓库内维护者指南 .agents/skills/insforge-dev/shared-schemas/SKILL.md系统讲解insforge/shared-schemas包的设计定位、组织规范、变更流程与验证手段并结合仓库真实源码剖析其实现细节。读完本文你将掌握如何在 InsForge 中新增、修改和同步一个跨包共享契约并能理解其背后的以共享包为唯一真源source of truth的工程原则。一、Shared Schemas 包的定位与适用场景packages/shared-schemas/是 InsForge 仓库中所有跨包数据契约的唯一来源source of truth。它对外发布为 npm 包insforge/shared-schemas当前版本1.2.0见 packages/shared-schemas/package.json由仓库的 npm workspacesbackend、frontend、packages/*见 package.json统一管理。什么数据应该放进 Shared Schemas根据 SKILL.md 的 Scope 定义凡是满足以下任一条件的数据形状都应定义在本包中请求request载荷如POST /api/auth/users的创建用户请求体响应response载荷如登录成功返回的{ user, accessToken, ... }跨包共享的领域形状domain shape如数据库表结构、备份配置、支付订阅等业务实体。判断标准很简单如果一个请求、响应或领域形状在 InsForge 的多个表面backend 路由、dashboard 页面、MCP 工具、SDK之间共享就在这里定义它而不要在包局部文件里复制同一份契约。SKILL.md 特别强调该包不只服务于仓库内的 backend 和 dashboard 包还被仓库之外的 InsForge 工具链如 MCP 与 SDK 代码消费因此任何导出的名称和 schema 形状都属于公开契约面public contract surface而非内部重构目标。包的基础设施包内唯一运行时依赖是zod^3.23.8构建产物输出到dist/并通过exports字段暴露import与types入口packages/shared-schemas/package.json。TypeScript 编译配置采用严格模式strict: true、ESM 模块、declaration与declarationMap同时开启packages/shared-schemas/tsconfig.json保证消费方既能在运行时获得 Zod 校验器也能在编译期获得精确的类型推导。二、按领域组织的文件结构SKILL.md 要求 schema 按领域domain组织并遵循现有的*.schema.ts与*-api.schema.ts双文件拆分模式。从 packages/shared-schemas/src/ 目录可以看到这套命名约定在仓库中的实际落地领域领域模型文件API 契约文件数据库database.schema.tsdatabase-api.schema.ts认证auth.schema.tsauth-api.schema.tsAI 网关ai.schema.tsai-api.schema.ts日志logs.schema.tslogs-api.schema.ts函数functions.schema.tsfunctions-api.schema.ts存储storage.schema.tsstorage-api.schema.ts密钥secrets.schema.tssecrets-api.schema.ts实时消息realtime.schema.tsrealtime-api.schema.ts部署deployments.schema.tsdeployments-api.schema.ts定时任务schedules.schema.tsschedules-api.schema.ts支付payments.schema.tspayments-api.schema.ts计算服务compute-services.schema.tscompute-services-api.schema.ts分析posthog.schema.ts/posthog-config.schema.tsposthog-api.schema.ts这一拆分的用意在于*.schema.ts描述领域实体本身如用户、表、备份记录与传输层无关*-api.schema.ts描述HTTP 层契约请求体、响应体、查询参数、错误响应依赖前者进行组合。例如auth-api.schema.ts中的createUserRequestSchema就是通过组合auth.schema.ts导出的emailSchema、passwordSchema、nameSchema构建的packages/shared-schemas/src/auth-api.schema.ts。index.ts 是公开 API 的橱窗所有对外导出的符号都统一经过 packages/shared-schemas/src/index.ts 汇总。当前它 re-export 了 29 个 schema 模块覆盖数据库、认证、存储、AI、日志、函数、实时、部署、支付、计算服务、分析、Web 抓取、错误码、仪表盘事件等几乎全部产品领域。SKILL.md 明确要求保持index.ts与预期的公开 API 对齐——新增 schema 文件后必须在 index.ts 中导出否则外部消费者无法引用。三、核心工作规则如何正确修改契约3.1 先想清楚这属于共享层吗修改任何请求/响应/领域形状前先判断它是否跨包共享。若是则必须定义在packages/shared-schemas/中若否仅在单个包内部使用才允许留在包局部文件。严禁在 backend 或 dashboard 的局部文件中重复定义同一份契约否则会出现两处定义、一处修改、另一处悄然过期的经典契约漂移问题。3.2 用 schema 变更触发同步SKILL.md 将 schema 变更视为一次同步触发器修改契约后必须逐项检查下游backend 校验与响应使用更新 backend/src/api/routes/ 下对应路由对请求体的校验和对响应体的序列化。实际仓库中insforge/shared-schemas已被 40 个后端路由文件与中间件引用覆盖 auth、database、payments、storage、realtime、schedules、secrets 等领域可从backend/src/api/routes/auth/index.routes.ts等文件的 import 语句确认。dashboard 的服务、hooks 与 UI 假设更新 packages/dashboard/src/ 下的 API service、数据获取 hooks 及组件中对字段形状的假设。dashboard 的 AI、Auth、Analytics、Datagrid 等特性模块均直接 import 共享包中的类型与校验器。跨包 import 站点排查在packages/*、frontend/、backend/全仓库范围内搜索该导出符号的所有引用点确认没有遗漏。评估下游影响当变更涉及导出名称、schema 语义或载荷形状时要明确指出对 MCP、SDK 或仓库外 InsForge 工具链的潜在破坏性影响。3.3 破坏性变更要保守SKILL.md 对破坏性变更breaking change的态度是保守如果确有必要必须在交接说明handoff中显式标注。这一约束与包的公开契约定位直接相关——因为外部消费者MCP、SDK无法被本仓库的编译检查覆盖静默破坏他们的解析逻辑是代价极高的错误。3.4 永不使用anySKILL.md 有一条硬性规定共享契约中禁止使用 TypeScriptany类型。理由很直接跨包边界上类型必须是显式且可信的explicit and trustworthy。一旦某个字段被标为any所有下游的类型检查在该字段上都会失明契约的可信任性随之崩塌。仓库中的实际实现也严格遵循此规则所有 schema 都基于 Zod 原始类型、枚举或组合对象构建并大量使用z.infertypeof ...导出对应 TypeScript 类型。四、从源码看契约设计的实际落地4.1 数据库领域约束的精细建模packages/shared-schemas/src/database.schema.ts 是理解该包建模哲学的绝佳样本列类型枚举ColumnType枚举覆盖string、date、datetime、integer、float、boolean、uuid、json八种常见列类型同时columnSchema的type字段用z.union([columnTypeSchema, z.string()])允许自定义类型字符串兼顾封闭枚举与开放扩展外键的复合键建模foreignKeySchema将外键建模为表级约束——一个约束实体包含一个有序的(sourceColumn - referenceColumn)映射数组referenceColumns最小长度 1从而天然支持复合外键注释明确说明复合键是包含多对映射的单一实体绝不跨列重复ON UPDATE 动作完整性onUpdateActionSchema与onDeleteActionSchema都接受CASCADE、SET NULL、SET DEFAULT、RESTRICT、NO ACTION五种动作注释解释了原因——Postgres 的 ON UPDATE 与 ON DELETE 支持相同的参照动作introspection 可能返回SET NULL/SET DEFAULT因此 schema 必须接受它们否则从数据库反读元数据时会校验失败约束即文档每个 schema 上都有校验信息丰富的错误消息如列名max(64)、表名非空、外键至少一个映射、迁移版本号必须匹配/^\d{1,64}$/支持0001或20260418091500这种时间戳式版本等这些消息会直接透传给 API 调用方构成用户体验的一部分。4.2 认证领域请求与响应契约的完备覆盖packages/shared-schemas/src/auth-api.schema.ts 展示了 API 契约层的典型写法Discriminated Union 处理多方法登录createSessionRequestSchema使用z.preprocess将缺失/为空的method字段归一化为password兼容旧客户端再用z.discriminatedUnion(method, [...])在password与otp两种登录方式间做类型判别。preprocess 注释点明了设计意图缺席/空/undefined 的 method 视为传统密码流程存在但非法的 method 仍会在判别联合中失败auth-api.schema.tsOTP 六位数字校验sixDigitCodeSchema(label)工厂函数生成/^\d{6}$/的正则校验并为每个使用场景定制错误文案OTP 验证码、重置密码码等PKCE 严格校验OAuth 初始化与换码请求遵循 RFC 7636code_challenge/code_verifier均限制长度 43128 且必须匹配 base64url 字符集/^[A-Za-z0-9._~-]$/并特意用 snake_case 字段名对齐 OAuth 2.0 规范auth-api.schema.tsSMTP 条件校验upsertSmtpConfigRequestSchema用superRefine实现条件校验——当enabled: false时允许保存空连接字段用户主动停用字段无意义启用时则强制 host、username、senderName 非空、senderEmail 合法端口限定为 25/465/587/2525 四选一最小暴露原则getPublicAuthConfigResponseSchema从 admin 响应中.omit({ allowedRedirectUrls, smtpConfig })因为该路由无需认证任何敏感字段如内网 SMTP 主机名都会泄露基础设施信息。注释中的约定值得注意新管理员专属字段默认落在authConfigSchema并自动进入 admin 响应要公开某个字段必须主动从.omit()中移除它——忘记思考时的默认值是安全的auth-api.schema.ts。这套默认隐藏、主动暴露的安全设计正是共享契约层能够同时服务内部管理与外部客户端的关键。4.3 类型推导与消费方式每个 schema 文件末尾都会用z.infer导出强类型如TableSchema、ColumnSchema、CreateUserRequest、CreateSessionResponse等。消费方backend 路由、dashboard service既可以 import 运行时校验器做请求体验证也可以 import 类型做响应序列化约束一套定义、两处受益。dashboard 侧的services/*.service.ts、hooks/use*.ts与组件层大量采用这种模式例如 AI 特性模块的模型网关配置、Auth 页面的 SMTP 与 OAuth 配置表单。五、变更后的验证清单SKILL.md 给出了提交前必须通过的验证命令# 1. 构建共享 schemas 包确认新契约可被编译为声明与产物 cd packages/shared-schemas npm run build # 2. backend 全量类型检查确认所有路由消费方无类型错误 cd backend npx tsc --noEmit # 3. dashboard 类型检查确认 UI 层消费方无类型错误 cd packages/dashboard npm run typecheck此外若某个行为逻辑发生了变化需要运行对应包的针对性测试如 backend/tests/unit/ 下的单元测试。SKILL.md 特别提醒如果外部消费者如 MCP、SDK无法在本仓库内完成验证必须如实说明而不是暗示它们已被覆盖——这是对事实准确原则的工程化延伸避免发布未经验证的契约。在 monorepo 根目录下也可以直接使用npm run build/npm run typecheck通过 Turbo 编排所有 workspace见 package.json进行全仓统一校验。六、实操场景新增一个共享契约的完整流程综合 SKILL.md 的工作规则与仓库现有模式新增共享契约的推荐流程如下判定归属确认新数据形状跨包共享。例如要给 dashboard 新增一个工作区设置实体backend 路由与 dashboard 页面都需要它则应放入共享层建文件在packages/shared-schemas/src/下新建workspace.schema.ts领域实体与workspace-api.schema.ts请求/响应契约复用auth.schema.ts、database.schema.ts等既有模块导出的基础 schema 组合保持类型显式、不加any导出在packages/shared-schemas/src/index.ts中追加export * from ./workspace.schema.js;与export * from ./workspace-api.schema.js;注意 ESM 下使用.js后缀后端接入在 backend/src/api/routes/ 对应路由中 import 请求 schema 做safeParse校验import 响应 schema 约束输出形状前端接入在 packages/dashboard/src/ 的 service 与 hooks 中 import 同一份 schema让请求构造与响应解析共用一套定义全局排查在packages/*、frontend/、backend/下搜索该导出名确认所有引用点已更新评估对仓库外 MCP/SDK 的影响并显式说明验证按上文清单依次执行npm run buildshared-schemas、npx tsc --noEmitbackend、npm run typecheckdashboard并运行受影响模块的测试。七、总结insforge/shared-schemas是 InsForge monorepo 中连接 backend、dashboard 与外部工具链MCP/SDK的契约中枢。它通过 Zod 将每个跨包数据形状固化为运行时校验器 编译期类型的双重约束用领域化的双文件结构*.schema.ts/*-api.schema.ts保持组织清晰用index.ts 即公开 API 橱窗保证导出可控用默认隐藏敏感字段的安全约定守护未认证端点并用禁止any 保守破坏性变更 强制全仓同步三条铁律维持跨包边界的可信度。无论你是维护 backend 路由、dashboard 页面还是计划扩展 InsForge 的 MCP/SDK 工具链遵循 SKILL.md 中以共享包为唯一真源的原则都能让每一次契约变更可追溯、可验证、可安全演进。【免费下载链接】InsForgeThe all-in-one, open-source backend platform for agentic coding. InsForge gives your coding agent database, auth, storage, compute, hosting, and AI gateway to ship full-stack apps end-to-end.项目地址: https://gitcode.com/GitHub_Trending/in/InsForge创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表