@btravstack/ 合同
合同层次: 客户端和服务器同时执行 需要,没有交通工具。 声明 哪些安全计划 a. 程序 接受 和每个范围必须给予什么, 没有关于谁的呼叫者 是;并描述 名单的一页 一次,像一个端口所说的类型 和计划 合同出版。 根没有依赖性——a 客户端可以在没有服务器的情况下接受合同,任何运输合同 可使用同一标记.
pnpm add @btravstack/contract
没有安装在旁边, 除非你使用页面 计划 下级
@btravstack/contract/zod,其 zod 是一个可选的对等点。 可选
@btravstack/contract/orpc 需要输入 @orpc/contract页:1
contractInputSchema 财务报告和审定财务报表 contractOutputSchema 检索程序
最初的Zod计划 和他们的具体类型. 一个包裹
一艘标有标记的合同将这艘作为 peerDependency 而不是一个
普通的——标记基于身份,所以每个应用程序有一个副本是
点; 见 为什么是同行 见下文.
节点 >=22。 。 。 .
使用量
import { authenticated } from "@btravstack/contract";
export const contract = {
orders: authenticated({ user: [] })({
place,
find,
// Overrides the group default for itself: a `user` token needs the scope,
// or a `service` token needs nothing.
export: authenticated(
{ user: ["orders:export"] },
{ service: [] },
)(oc.output(z.object({ csv: z.string() }))),
}),
customers: { find },
};
authenticated 实值 剪辑: 它需要一个或多个 OpenAPI 安全
要求——按照它必须给予的范围绘制的计划名称——和手
返回标记节点的函数。 有几个要求是: 命令,尝试
以给出的顺序。 标记记录是对下面每个程序的默认
它; 标记程序 替换 自我默认。 最接近的标记
胜出,这是OpenAPI自己的规则. 在构建链完成后应用它,
从不在里面.
合约上写着哪些计划保护一条路线
defineHttp({ authenticators }) 说出每个人的意志. 无身份
类型在此命名, 所以服务器对呼叫器本身的视图没有到达
一个客户,丰富它 永远不会改变合同.
标记是弱地图,不是地产
标记是 基于身份 a 包括: WeakMap,该节点上没有财产——该节点
为什么一个包裹的运输 标有标记的合同 把这个作为一个 端点
依赖性而不是普通的:两份将意味着两份登记处,
一份没有标记的契约是受保护的路线
服务开放。 登记簿是防止复制的 (它挂断)
globalThis 下级 Symbol.for("@btravstack/contract/requirements")因此,每个
复制共享 1 WeakMap),因此,一个偏差的第二份副本需要一个编译错误
不匹配的标记符号, 不是打开的路由 .
isAuthenticated(node) 读回 Requirements 一个节点的标志是,
或者说 undefined 当没有人标出它.
输入列表
一页,一页描述:一个端口说话的类型和合同的计划 出版是相同的形状, 测试针是它们无法分开的.
import { pageOf, pageRequestOf } from "@btravstack/contract/zod";
export const orders = oc.router({
list: oc
.input(pageRequestOf({ minQuantity: z.number().int().min(1).optional() }))
.output(pageOf(orderView)),
});
旗帜和光标是一个事实. hasNextPage: true 携带
nextCursor 继续列名 hasNextPage: false 没有这样的
田地——所以"还有更多,没有什么可跟随它",是无法形容的,
和检查旗子的客户端持有光标,且不能将光标放大.
after 财务报告和审定财务报表 before 属于该类的结合,但被该类人拒绝为一对
schema:一个页面向一个方向运行.
适配器页面列表 keyset(request)对象
持有两半键集页面—— take (页外加一行)
这证明下一个, backward, (中文(简体) ), cursor,则a page 折叠什么
商店回答:
import { keyset } from "@btravstack/contract";
const keys = keyset(request);
const listed = keys.page(store.seek(keys), (row) => String(row.id));
过度牵引和修饰 通过建筑,这是整个原因
它们是一个物体. keyset 不运行查询——这是一件事
此级不能表示——当商店报告两个光标本身时,
page(items, { previous, next }) 直接带走 控制器转动
对端口的有效输入 PageRequest 与 pageRequest(input)。 。 。 .
排序列表
列表会声明它自己的可分类词汇表, 对照它的项目检查 已经发布,并且需要默认,即隐含的默认是 列表由无人选择的东西排序 :
import { sortableBy } from "@btravstack/contract/zod";
export const sortedOrders = oc.router({
list: oc
.input(
pageRequestOf(
{ minQuantity: z.number().int().min(1).optional() },
{
sortableBy: sortableBy(orderView, ["quantity"]),
defaultSort: { field: "quantity", direction: "desc" },
},
),
)
.output(pageOf(orderView)),
});
光标带有该类 逐字记录,不是散发 —— 说 field:direction, (中文(简体) ),
现场 encodeURIComponentd, 就像排序值和结节
旁边——因为词汇表已经在发布的 OpenAPI 中公开了
文档。 光标是
只对以下类型有效:, keyset(request)
答题 SortedKeyset<F> | CursorRefused,适配器必须分支
而不是一个未过滤的页 从错误的一面:
import { keyset } from "@btravstack/contract";
const sortedKeys = keyset(sortedRequest);
const sortedListed = sortedKeys.resumable
? sortedKeys.page(sortedRows, (row) => [String(row.quantity), String(row.id)])
: sortedKeys.reason; // "malformed" or "sort-mismatch"
SortedKeyset<F>.page是因为 cursorOf 返回时 两者 排序搜索的值
所以被遗忘的断了就是
编译出错,而不是静默地跳过绑定行的密钥集.
许可证
麻省理工学院 贝诺伊特旅行社