@crvouga/mockingbird-service-easypost

中文文档
3.11.0发布于 2026/11/11MITTypeScriptES Module构建来源已验证近 30 天下载 3107

Stateful emulator of the EasyPost trackers API: create/re-use trackers, EasyPost's test tracking codes, admin status transitions and EasyPost's error envelope.

原始使用文档
文档目录7 节
  1. Install
  2. Usage
  3. Routes
  4. Admin (beyond the standard contract)
  5. Namespaces
  6. Deliberately not modelled
  7. API

@crvouga/mockingbird-service-easypost

Local emulators. Real API contracts. Part of Mockingbird.

Stateful emulator of the EasyPost trackers API for test suites: POST /v2/trackers (create or re-use a tracker for a tracking code), GET /v2/trackers/{id} and GET /v2/trackers. EasyPost's documented test tracking codes answer their fixed statuses, and any other code moves through admin transitions, so the genomics admin's shipping-leg states can be driven deterministically.

  • Operation coverage: SUPPORT.md
  • The contract (openapi.yaml) is trimmed from EasyPost's published reference to what our tracking lookup (packages/lib/src/shipment-tracking-status/easypost-client.ts) calls.

Install

npm install -D @crvouga/mockingbird-service-easypost

ESM only. Node >= 22 or Bun >= 1.2. No native dependencies. Serve it with npx mockingbird-easypost serve, createServer from ./server (Node), or createRuntime with any Fetch server.

Usage

The app hardcodes https://api.easypost.com/v2/trackers (seam G-Y1: add a base-URL env to easypost-client.ts). Point that base URL at the emulator; EASYPOST_API_KEY can be any value (--api-key restricts it).

npx mockingbird-easypost serve --port 8818
import EasyPostClient from "@easypost/api"
import { createServer } from "@crvouga/mockingbird-service-easypost/server"

const server = await createServer()

// Test setup: seed a status before the app looks the code up (or move an existing tracker).
await fetch(`${server.url}/__admin/trackers/1Z999AA10123456784/transition`, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ status: "out_for_delivery" }),
})

// The EasyPost SDK your application already uses. Only its base URL changes.
// @ts-ignore @easypost/api 8.9.0 types its ESM default export as CommonJS (NodeNext only).
const easypost = new EasyPostClient("EZTK_test", { baseUrl: `${server.url}/v2/` })
const tracker = await easypost.Tracker.create({ tracking_code: "1Z999AA10123456784", carrier: "UPS" })
console.log(tracker.id, tracker.status, tracker.carrier) // trk_… out_for_delivery UPS

await server.close()

Routes

RouteBehaviour
POST /v2/trackersForm (tracker[tracking_code], tracker[carrier]) or JSON ({tracker: {…}}), Authorization: Basic base64(key:). Answers 201 with the Tracker (id, object, mode, tracking_code, status, status_detail, carrier, tracking_details, public_url, signed_by, est_delivery_date, …). The same code and carrier re-use the existing tracker, as EasyPost does. Carrier: the given one (DHL is normalised to DHLExpress), else detected from the code's shape, else USPS. A blank code is 422 PARAMETER.REQUIRED; a bad carrier 422 PARAMETER.INVALID.
GET /v2/trackers/{id}The tracker, or 404 NOT_FOUND.
GET /v2/trackers?tracking_code=&carrier=&page_size= → {trackers, has_more}, newest first.

Every error is EasyPost's envelope {error: {code, message, errors}}; our client reads error.message. A missing key is 401 APIKEY.REQUIRED, a key outside apiKeys 401 APIKEY.INACTIVE. Keys starting EZAK are production mode (test codes are not special there); anything else is test mode.

Test tracking codes (test mode, carrier USPS): EZ1000000001 pre_transit, EZ2000000002 in_transit, EZ3000000003 out_for_delivery, EZ4000000004 delivered, EZ5000000005 return_to_sender, EZ6000000006 failure, EZ7000000007 unknown. Any other code starts unknown / unknown.

Admin (beyond the standard contract)

RouteEffect
POST /__admin/trackers/:idOrCode/transition{status, status_detail?, message?, signed_by?, carrier?}. Moves the tracker (by id or tracking code) and appends a tracking detail. With no tracker for that code yet, registers one first, so the app's next lookup sees the status. status is one of unknown, pre_transit, in_transit, out_for_delivery, delivered, available_for_pickup, return_to_sender, failure, cancelled, error.
GET /__admin/trackersThe namespace's trackers.
GET/PUT /__admin/settings{apiKeys?: string[]}: accept only these keys (default: any).

Fault presets (POST /__admin/faults {"preset": "<name>", "count"?: n}): rate_limited (429), server_error (500), invalid_api_key (401), gateway_html (502 HTML, our client falls back to EasyPost tracker request failed (502)), connection_drop (fetch rejects; our batch lookup records unknown and warns), slow (5 s).

Namespaces

x-mockingbird-namespace, a /__admin/ns/<name> prefix on the base URL, or by API key: PUT /__admin/credentials {"credentials": {"<EASYPOST_API_KEY>": "<namespace>"}}.

Deliberately not modelled

  • Tracker webhooks (tracker.updated, X-Hmac-Signature): our app has no receiver.
  • Carrier lookups: a real-shaped code never moves on its own; statuses come from admin transitions.
  • Shipments, rates, labels, addresses, batches and every other EasyPost resource.
  • Pagination cursors (before_id / after_id) on the list: page_size and has_more only.

API

ExportKindDescription
EasyPostAPIclassThe in-process emulator: fetch(request), reset(), transition(idOrCode, {status, …}, carrier?), trackers(). Options: sqlite, now, namespace, settings.
createRuntimefunctionThe emulator with the full service contract (health, admin, namespaces, credentials, presets). Options: settings, clock, seed, adminKey, onLog, sqlite.
EASYPOST_PRESETSobjectEvery named fault preset.
EASYPOST_NAMESPACEstringThe service name, "easypost".
TEST_TRACKING_CODESobjectEasyPost's test codes and the status / detail each answers.
TRACKER_STATUSESarrayEvery Tracker status.
apiKeyCredentialfunctionThe API key from Basic base64(key:) (how credentials map to namespaces).
detectCarrierfunctionThe carrier the emulator assigns a code with no carrier given.
easyPostErrorfunctionBuild an EasyPost error response {error: {code, message, errors}}.
isTrackerStatusfunctionWhether a value is a Tracker status.
document, operationIds, supportedOperationIdsvaluesThe vendored OpenAPI contract and its operation ids.
createServer, serveTarget, DEFAULT_PORT (./server)NodeServe over node:http; the serve CLI target; port 8818.

Part of mockingbird.

版本与发布记录

@crvouga/mockingbird-service-easypost 共发布 42 个版本,首次发布于 2026/09/23;过去 12 个月发布了 42 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
3.11.0latest2026/11/11今天
3.10.92026/11/038 天前
3.10.82026/11/038 天前
3.10.72026/11/038 天前
3.10.62026/11/038 天前
3.10.52026/11/038 天前

关于 @crvouga/mockingbird-service-easypost 的常见问题

@crvouga/mockingbird-service-easypost 是什么?

Stateful emulator of the EasyPost trackers API: create/re-use trackers, EasyPost's test tracking codes, admin status transitions and EasyPost's error envelope.

如何安装 @crvouga/mockingbird-service-easypost?

在项目目录运行 npm install @crvouga/mockingbird-service-easypost,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 mockingbird-easypost,可以用 npx mockingbird-easypost 直接运行。

@crvouga/mockingbird-service-easypost 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@crvouga/mockingbird-service-easypost 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@crvouga/mockingbird-service-easypost 可以商用吗?

@crvouga/mockingbird-service-easypost 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@crvouga/mockingbird-service-easypost 的下载量有多少?

根据 npm 官方下载统计,@crvouga/mockingbird-service-easypost 在 2026/10/11 – 2026/11/09 这 30 天内被下载 3,107 次,日均约 104 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@crvouga/mockingbird-service-easypost 还在维护吗?

最新版本 3.11.0 发布于 2026/11/11(今天);至今共发布 42 个版本,其中过去 12 个月发布了 42 个;首次发布于 2026/09/23。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。