从单一真实来源验证、文档、测试和数据库模式
一个 TypeScript 定义。验证、OpenAPI、AsyncAPI、BDD 测试、Gherkin 和数据库模式 — 所有内容均从同一真实来源生成。Triad 是一个以 TypeScript 为先的 API 框架,建立在一个理念上:API 的规范、实现、验证和测试永远不应该偏离,因为它们是同一件事情。您使用 Triad 的声明性 DSL 一次编写 TypeScript,然后您将获得:边缘的运行时验证(解析 + 以结构化错误拒绝)从相同模式派生的静态类型(t.infer<typeof X>)HTTP 端点的 OpenAPI 3.1 文档WebSocket 通道的 AsyncAPI 3.0 文档可执行的 BDD 场景,作为测试运行(triad test)从您的模式约束派生的自动对抗性测试(scenario.auto())生成的 Gherkin .feature 文件,供非技术利益相关者使用针对 React Query、Solid Query、Vue Query、Svelte Query 的类型化前端钩子(triad frontend generate)通过一种与方言无关的 Drizzle 桥接的数据库模式(triad db generate)没有代码生成的来回。没有手工维护的 OpenAPI YAML。没有过时的重复的 Zod + OpenAPI + 测试样板模式。为人和 AI 而建,Triad 的北极星是 AI 编码助手应该能够通过阅读一个地方理解整个 API。当模式、处理程序、响应、通道负载、测试和文档都存在于同一类型定义中时,LLM(或新的工程师)就不必从 Zod 文件、OpenAPI YAML、单独的测试样板和过时三次提交的 README 中拼凑上下文。只有一个真实来源,所有其他工件都是它的确定性投影。这就是保持人类高效的原因——这也让 AI 能够在不猜测的情况下推理您的 API。开始使用 Claude Code 此 repository 兼作 Claude Code 市场,因此通往工作 TriadJS 后端的最快路径是让 Claude 做脚手架。 1. 添加 TriadJS 市场并安装插件(一次性,在任何 Claude Code 会话中):/plugin marketplace add justhamade/triad /plugin install triadjs@triadjs 这将安装 10 个技能(模式 DSL、端点、通道、带有权威断言短语表的 BDD 行为、测试、适配器、Drizzle、CLI、DI)和 8 个斜杠命令(/triadjs:new、/triadjs:model、/triadjs:endpoint、/triadjs:channel、/triadjs:scenario、/triadjs:test、/triadjs:docs、/triadjs:validate)。 2. 搭建您的第一个项目:/triadjs:new 一个包含宠物、收养和聊天室通道的宠物商店 API Claude 将创建完整的项目布局 — package.json、triad.config.ts、模式、带有行为的端点、Fastify 服务器和测试设置 — 然后运行 triad test 确认每个场景都通过。运行 npm run dev,Swagger UI 会立即在 http://localhost:3000/api-docs 上直播,实时 OpenAPI 规范在 /api-docs/openapi.json。没有额外步骤。 3. 迭代:/triadjs:endpoint 为宠物添加一个软删除端点 /triadjs:scenario 覆盖 getPet 的 404 情况 /triadjs:test /triadjs:docs 每个命令仅加载其所需的技能,编写符合解析器期望的短语表的惯用 TriadJS 代码,并验证其自身的输出。有关完整的技能和命令目录,请参阅 plugin/README.md。 不使用 Claude Code?请跳到下面的体验部分以获取普通 TypeScript 的演练,或完整的快速入门。 体验部分 导入 { t,endpoint,scenario,createRouter } 来自 '@triadjs/core' ; const Pet = t . model ( 'Pet' , { id : t . string ( ) . format ( 'uuid' ) . identity ( ) , name : t . string ( ) . minLength ( 1 ) . example ( 'Buddy' ) , species : t . enum ( 'dog' , 'cat' , 'bird' , 'fish' ) , age : t . int32 ( ) . min ( 0 ) . max ( 100 ) , } ) ; const CreatePet = Pet . pick ( 'name' , 'species' , 'age' ) . named ( 'CreatePet' ) ; const createPet = endpoint ( { method : 'POST' , path : '/pets' , summary : '创建一只宠物' , body : CreatePet , responses : { 201 : Pet , 400 : ApiError } , handler : async ( ctx ) => { const pet = await ctx . services . petRepo . create ( ctx . body ) ; return ctx . respond [ 201 ] ( pet ) ; } , behaviors : [ scenario ( '用有效输入创建一只宠物' ) . when ( 'POST /pets' , { body : { name : 'Rex' , species : 'dog' , age : 3 } } ) . then ( '状态为 201' ) . and ( '响应体与 { name:
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡