两套命名空间
/api/admin/* 要登录,响应统一包一层 data;/api/public/* 匿名可读,结果直接返回。可见性规则只在 service 里定义一次,加接口不用重新想一遍。
Prisma · Zod · NestJS · Next.js
keel 把数据库、接口契约、管理后台、官网串成一条类型链路。字段改了但某处忘了跟上,是构建失败,不是上线之后才发现的线上问题。
model Post { publishedAt DateTime?}publicPostSchema = z.object({ publishedAt: z.coerce.date(),})const post: PublicPost = ... post.publishedAt // ^ 改上面任一层,这里编译报错/api/admin/* 要登录,响应统一包一层 data;/api/public/* 匿名可读,结果直接返回。可见性规则只在 service 里定义一次,加接口不用重新想一遍。
公开接口的字段是挑出来的,不是从完整实体里删掉几个。数据库加一列,默认不会漏出去 —— 最坏的情况是官网少显示一个字段,而不是把草稿泄露给访客。
测「编辑删不了」的同时必须测「管理员删得了」。只写被拒的那一半,删除功能整个坏掉时用例照样全绿。
一个后端两个前端,靠一层共享契约把它们绑在一起。为什么是这个形状,以及哪些东西被有意留在了外面。
类型只定义一次,前后端各自推导。改一个字段,忘了跟上的地方会在构建时报错,而不是上线后报错。
/api/admin/* 要登录、包一层 data;/api/public/* 匿名可读、直接返回。可见性规则只写一次。