@crvouga/mockingbird-service-rxvortex

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

Stateful emulator of the RxVortex (Strive) pharmacy API: OAuth token, order submit, status, cancel, recovery by sender order id, preset catalog, and signed status webhooks.

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

@crvouga/mockingbird-service-rxvortex

Local emulators. Real API contracts. Part of Mockingbird.

Stateful emulator of the RxVortex (Strive) compounding-pharmacy API for test suites: the client-credentials token, order submit, status, cancel, the recovery lookup by sender order id, the preset catalog, and the signed status webhooks the pharmacy posts back. Orders move only when a test says so (an admin transition or an auto-advance path on the emulator clock), so an eRx suite that waited up to 60 s on the real sandbox resolves in milliseconds.

  • Operation coverage: SUPPORT.md
  • The vendor publishes no spec: the contract (openapi.yaml) is hand-authored from the wire shapes our consumer reads and writes, and every field fallback it relies on is served.

Install

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

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

Usage

Point RXVORTEX_API_URL at the emulator. Set RXVORTEX_WEBHOOK_SECRET in the app and pass the same value as --webhook-secret.

npx mockingbird-rxvortex serve --port 8791 \
  --webhook-url http://127.0.0.1:3000/prescriptions/webhooks/rxvortex \
  --webhook-secret "$RXVORTEX_WEBHOOK_SECRET" \
  --auto-advance "2000:Fill,Shipping,Delivered" \
  --catalog ./preset-catalog.json

--catalog loads your own preset catalog into every namespace: a JSON array of rows, or the {data: [...]} body GET /api/v1/preset-catalog-items answers with, so a recorded sandbox response loads as-is. Only catalog_id and medication_name are required. POST /__admin/reset returns to these rows. Pass --unknown-presets accept to take any well-formed preset id instead.

import { createServer } from "@crvouga/mockingbird-service-rxvortex/server"

// Test setup: a local RxVortex that posts its status webhooks to the app.
const server = await createServer({
  webhooks: { url: "http://127.0.0.1:3000/prescriptions/webhooks/rxvortex", secret: "whsec-test" },
})
const baseUrl = server.url // the app's RXVORTEX_API_URL
const post = (path: string, body: unknown, headers: Record<string, string> = {}) =>
  fetch(`${baseUrl}${path}`, {
    method: "POST",
    headers: { "content-type": "application/json", ...headers },
    body: JSON.stringify(body),
  })

// Application code: the requests it sends to RxVortex.
const { access_token } = (await (
  await post("/api/v1/generate-access-token", { client_id: "acme", client_secret: "s" })
).json()) as { access_token: string }
// …then POST /api/v1/orders with Authorization: Bearer <access_token> and sender_order_id "pay_123"…

// Test control: move that order the way the pharmacy would; each step emits the signed status webhook.
await post("/__admin/orders/pay_123/transition", { to: "Shipping", trackingnumber: "1Z999" })
await post("/__admin/orders/pay_123/transition", { to: "Delivered" })

await server.close()

Routes

RouteBehaviour
POST /api/v1/generate-access-tokenJSON {client_id, client_secret} → {access_token, token_type: "Bearer", expires_in: 86400}. Any pair works unless clients is set (PUT /__admin/settings). Tokens stay valid 24 h on the emulator clock; our client caches for 24 h and never refreshes on 401.
POST /api/v1/ordersValidates the submit payload against the contract; a violation is 422 {message, errors: {"patient.phone": ["…"]}}. An inactive or unknown preset_catalog_id is 422 (under unknownPresets: "accept" an unknown UUID becomes an active catalog row named after the request's medication_name). A repeated order.sender_order_id is 409. Success: {success: true, order_tracking_id: "RXV-…", sender_order_id, status: "Created"} (the tracking id is always a string).
GET /api/v1/orders/{id}id is the tracking id or the sender order id (our payment id, the recovery lookup). Returns rxstatus, orderstatus, shipping_status, delivered_date, trackingnumber, shippingservice, shippingcarrier, shipmenttrackingurl, cancellable, and the id under order_tracking_id, tracking_id and orderReferenceID.
DELETE /api/v1/orders/{id}Cancels while cancellable (until shipped), emitting the webhook; otherwise 409.
GET /api/v1/preset-catalog-items{data: [...]} rows with catalog_id, medication_name, medication_strength, package_size, quantity, quantity_units, medication_form, route, states, status. Includes the custom-cream anchor preset e404ad76-0f82-4b04-8f25-841650e2e819 and one inactive row.

Webhooks

Every status change posts {event: "order.status_updated", orderReferenceID, order_tracking_id, tracking_id, sender_order_id, rxstatus, orderstatus, shipping_status, delivered_date, trackingnumber, shippingcarrier, shippingservice, shipmenttrackingurl, updated_at} with header x-rxvortex-webhook-secret: <secret> (plain equality, as our receiver checks). Non-2xx answers are retried (immediately, 5 s, 5 min, 30 min, 2 h). GET /__admin/webhooks lists deliveries, GET /__admin/webhooks/events the payloads, POST /__admin/webhooks/flush runs pending retries now, and PUT /__admin/webhook-endpoints sets per-namespace receivers.

Admin (beyond the standard contract)

RouteEffect
POST /__admin/orders/:id/transition{to, trackingnumber?, shippingcarrier?, shippingservice?, delivered_date?}. to is a vendor status: Fill, PV1 Complete, Compound, Out of Stock, On Hold, Shipping, Delivered, Cancelled, Rejected, Error, or any string (used verbatim). The three status fields move together; shipping generates tracking when none is given.
PUT /__admin/catalog{items: [{catalog_id, medication_name, medication_strength?, package_size?, quantity?, quantity_units?, medication_form?, route?, states?, status?}], mode?: "replace" | "merge"} for the calling namespace (replace is the default; merge upserts by catalog_id). Answers {count}, the namespace's row count. items may also be sent as data.
GET /__admin/catalogThe namespace's rows, as {data: [...]}.
PUT /__admin/settings{tokenTtlSeconds?, staticTokens?, clients?, autoAdvance?: {afterMs, path} | null, unknownPresets?: "reject" | "accept"} for the calling namespace. unknownPresets defaults to reject, as the sandbox does. staticTokens admits RXVORTEX_API_TOKEN (the catalog client's static bearer).
POST /__admin/tickApply every auto-advance step that is due on the emulator clock (the served emulator also ticks every 100 ms).
GET /__admin/ordersThe namespace's orders.

Fault presets (POST /__admin/faults {"preset": "<name>", "count"?: n}; GET /__admin/faults/presets): duplicate_sender_order_id, created_but_500 (creates, then 500; recovery succeeds), numeric_tracking_id, token_expired, stale_error_with_delivered_date, validation_errors_array, validation_errors_object, validation_errors_empty, server_error, webhook_duplicate, webhook_reorder, webhook_drop.

Namespaces

Our backend's fetch cannot add headers, so a namespace can be chosen three ways: x-mockingbird-namespace, a /__admin/ns/<name> prefix on RXVORTEX_API_URL, or by client id: PUT /__admin/credentials {"credentials": {"<RXVORTEX_CLIENT_ID>": "<namespace>"}} (tokens carry the client id they were issued to).

Deliberately not modelled

  • Real fulfilment timing: nothing moves on its own unless autoAdvance is set.
  • Patient and prescriber details are validated, never stored or echoed back.
  • The live catalog: the default rows are synthesised in the live client's field names (no sandbox recording exists). Load recorded rows with serve --catalog, PUT /__admin/catalog, or the catalog option.
  • Refills and multi-order shipments.

API

ExportKindDescription
RxVortexAPIclassThe in-process emulator: fetch(request), reset(), transition(id, {to, …}), tick(), orders(). Options: sqlite, now, namespace, catalog, settings, onWebhook.
createRuntimefunctionThe emulator with the full service contract (health, admin, namespaces, credentials, presets, webhooks). Options: webhooks: {url, secret, retryDelaysMs?, fetch?}, settings, catalog, tickMs, clock, seed, adminKey, onLog.
RXVORTEX_PRESETSobjectEvery named fault preset.
RXVORTEX_NAMESPACEstringThe service name, "rxvortex".
tokenCredentialfunctionThe client id a bearer token was issued to (how credentials map to namespaces).
CUSTOM_CREAM_ANCHOR_PRESET_IDstringThe sandbox custom-cream anchor preset id.
DEFAULT_CATALOGarrayThe default preset catalog rows.
parseCatalog, parseCatalogItemfunctionsCatalog rows from a JSON array or a recorded {data: [...]} body (missing optional fields default to null, states to [], status to "active"); throw on a malformed row.
document, operationIds, supportedOperationIdsvaluesThe vendored OpenAPI contract and its operation ids.
createServer, serveTarget, DEFAULT_PORT, loadCatalogFile (./server)NodeServe over node:http (auto-advance ticks every 100 ms); the serve CLI target; port 8791; read a --catalog file.

Part of mockingbird.

版本与发布记录

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

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

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

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

Stateful emulator of the RxVortex (Strive) pharmacy API: OAuth token, order submit, status, cancel, recovery by sender order id, preset catalog, and signed status webhooks.

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

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

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

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

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

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

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

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

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

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

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

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