npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aipt/api-contract

v0.2.4

Published

与传输无关的 API 请求、响应和错误合同。

Readme

API Contract

@aipt/[email protected] 让一份端点定义同时产出类型、运行时校验和 mock。契约声明一次,客户端调用、服务端处理和开发期 mock 共用同一个 schema,三者无法互相漂移。

本包不依赖任何具体校验器。它消费 Standard Schema 规范,因此 zod、valibot、arktype 都可直接作为 schema 传入;平台不锁定其中任何一个。本包也不含 React、HTTP 框架、Provider SDK 或产品领域类型。

安装与导入

pnpm add @aipt/[email protected]
import { createApiClient, createRouteHandler, defineEndpoint } from "@aipt/api-contract";
import { fetchTransport } from "@aipt/api-contract/fetch";

最小用法

import { z } from "zod";

const readStation = defineEndpoint({
  operationId: "weather.readStation",
  method: "GET",
  path: "/stations/:stationId/latest",
  params: z.object({ stationId: z.string().min(1) }),
  response: z.object({ reading: z.object({ celsius: z.number() }) }),
});

// 客户端:返回判别联合,不抛业务异常
const client = createApiClient({ baseUrl: "https://api.example", endpoints: { readStation }, transport: fetchTransport(), timeoutMs: 10_000 });
const result = await client.readStation({ params: { stationId: "PEK001" } });
if (result.ok) console.log(result.data.reading.celsius); // number
else console.log(result.error.code);

// 服务端:同一个定义,输入自动校验,输出必须符合契约
const handler = createRouteHandler(readStation, ({ params }) => ({ reading: { celsius: latestOf(params.stationId) } }));

开发期把 transport 换成 mock,其余代码一行不改:

import { createMockTransport } from "@aipt/api-contract";

const transport = createMockTransport({
  endpoints: { readStation },
  handlers: { readStation: () => ({ reading: { celsius: 21.5 } }) },
});

mock 返回值同样经过端点的 response schema 校验,mock 数据无法偏离契约。

错误与边界

  • API_ENDPOINT_INVALID:端点定义非法(非法 operationId、路径穿越、GET 携带 body、路径参数与 params schema 不匹配)。装配期即失败。
  • API_INPUT_INVALID:params/query/body 不符合 schema。客户端不发出请求;服务端回落为 fail 信封。
  • API_RESPONSE_INVALID:响应载荷不符合 response schema。服务端漂移在此 fail closed,业务拿不到半截数据。
  • API_ENVELOPE_INVALID:响应不是合法信封。
  • API_TRANSPORT_FAILED:传输层失败、取消或超时。
  • API_TIMEOUT_INVALID:deadline 不是正数。
  • API_MOCK_UNHANDLED:mock 未登记该端点,不静默返回空数据。

其他边界:

  • 线格式为 { ok: true, ...载荷 } / { ok: false, error: { code, message } },与既有服务端一致。
  • 失败信封是数据(result.ok === false),只有契约违例和传输故障才抛异常。
  • 服务端输出非法时抛出而非回落——那是服务端缺陷,绝不把不符合契约的数据发出去。
  • 每次调用必须有正数 deadline,可与调用方 AbortSignal 组合。
  • 中间件为洋葱模型,失败用普通 try/catch 观察,不需要独立错误通道。
  • 不记录请求体、响应体、Header 或 Secret。

与服务端状态层的关系

本包只负责契约与传输,不做缓存、去重、重试或失效。客户端产出的 (input) => Promise<ApiResult<T>> 可直接作为 TanStack Query 的 queryFn,两者组合而非替代。

退出方式

端点定义是纯数据,schema 由调用方拥有。替换 createApiClient 与 createRouteHandler 后删除依赖即可;本包不持有持久状态,也不拥有任何已发出的请求。