@crvouga/ mockingbird-service-vpi (英语)
本地模拟器。 真正的API合同. 部分 嘲笑鸟。 。 。 .
[尖叫声] 我们的应用程序
VPI_API_URL默认生产 (单位:千美元)https://api.vpicompounding.net,参见apps/backend/src/modules/erx/clients/vpi-api.client.ts) (中文(简体) ). 未设置的变量发送真实 给真正的药店开处方 堆叠 必须 设定VPI_API_URL给此模拟器( 例如 ).http://127.0.0.1:8802只要VPI铁路可以到达.
国家模拟器 妇女 我们的后端驱动器是一个
只有草案的eRx铁路:JWT认证,产品分类/细节/折扣,日用品,
运输状况和费率、诊所地点、提供者、病人名册和详细情况,
供应商签名重复检查, saveNewPrescription,以及三页处方
状况列表 我们的传票人读取。 处方只在测试时才移动( 管理员)
页:1 我们的后端民意调查第1页(限制5).
- 行动范围: 支助
- 供应商不公布具体内容:合同
openapi.yaml)是从我们的客户手取出 佐德计划( zod schemas )vpi-api.contracts.ts外加客户端- 本地策略vpi-api.client.ts) (中文(简体) ). 接收测试用这些图案的逐字端口来分析每个模拟器的反应.
安装
npm install -D @crvouga/mockingbird-service-vpi
仅限无害环境管理。 节点 22或 Bun 1.2. 无土生属地. 给它服务
npx mockingbird-vpi serve, (中文(简体) ), createServer 从 ./server (节点),或 createRuntime 带有任意
获取服务器 .
使用量
将应用程序指向模拟器并给予其任何证书(任何对日志,除非 accounts 已设定 :
npx mockingbird-vpi serve --port 8802
# app env:
# VPI_API_URL=http://127.0.0.1:8802 (REQUIRED: the default is production)
# [email protected] VPI_API_PASSWORD=anything
# VPI_CLINIC_LOCATION_ID=65a1c0de00000000000000d1
import { createServer } from "@crvouga/mockingbird-service-vpi/server"
// Test setup: a local VPI.
const server = await createServer()
const baseUrl = server.url // the app's VPI_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 VPI.
const { jwtToken } = (await (
await post("/accounts/authenticate", { email: "[email protected]", password: "x" })
).json()) as { jwtToken: string }
// …then POST /clinic/rxOrdering/saveNewPrescription (Bearer jwtToken) saves a draft…
// Test control: move it the way the pharmacy would; our poller maps each status.
await post("/__admin/prescriptions/66b200000000000000000001/transition", {
to: "Order Completed",
trackingNumber: "1Z999",
})
await server.close()
种子数据
每个命名空间开始于: 用户 65a1c0de00000000000000a1 (每个登录都决定,除非
accounts 诊所 65a1c0de00000000000000c1,诊所位置
65a1c0de00000000000000d1 ("Acme Main"),供货商格蕾丝·霍珀(NPI) 1234567893编号
65a1c0de00000000000000e1)和艾伦·图灵(NPI) 1987654320),患者艾达·洛芙蕾丝
(单位:千美元)65a1c0de00000000000000f1, DOB 1985-02-14, 1 Main St, Phoenix AZ 8504,并有4个产品:
睾丸酮 丙酮酸64f1c2a9e4b0a1b2c3d4e5f6 编号 : 2185_INJ(a) 无菌,10%的门诊折扣,
Se/ B6 特罗切(3097_POW,冷运), Enclomiphene(4410_CAP没有复合
和南德罗罗内(5120_INJ, (中文(简体) ), 控制: 被拒绝 saveNewPrescription) (中文(简体) ).
将其中任何一项替换为 createRuntime({ data: { products, providers, clinicLocations, patients } })。 。 。 .
路线
| 路线 | 行为 |
|---|---|
POST /accounts/authenticate | {email, password, isPatientLogin: false} → {id, jwtToken, refreshToken}. JWT有效载荷 sub (用户编号), email, (中文(简体) ), iat 财务报告和审定财务报表 exp = 模拟器- 时钟现在 + tokenTtlSeconds (默认360). 我们的客户缓存它直到 exp – 30 s,并在401上重新校正一次. isPatientLogin: true 被拒绝. |
| 其它路线 | 要求数 Authorization: Bearer <jwtToken>- 失踪或被篡改 Unauthorized; 在模拟时钟上过期 ~ 401 jwt expired。 。 。 . |
GET /products/getAllFamiliesAndCategories | [{family, categories: [subCategory1…]}]。 。 。 . |
POST /products/getProductsByCategory | {category, subCategory1} → [{subCategory2_item, commonNames: [{commonName, products: [...]}]}]。 。 。 . |
GET /products/getProductDetailsByProductId/{id} | 依据创用CC授权使用. sigOptions, (中文(简体) ), reasonForCompoundedMedication, (中文(简体) ), patientPayAmount, (中文(简体) ), ndc (数字) 404 如果未知的话. |
POST /products/getProductDiscountByProductIds | {clinicId, productIds} → [{id, productId, discountedPrice, unitPrice, discountedPercentage, controlledSubstance}] 对已知产品. |
POST /products/calculateDaySupply | {productId, quantity, sig} → {daySupply, daySupplyReason} (每个产品:每天1个;否则30个). |
GET /admin/rxOrdering/getShippingStates | {data: [{states: [{name: "Arizona", booleanCheck, nonSterile, sterile}]}]} (全名;无无菌运输至阿拉巴马州或华盛顿特区). |
POST /portal/getShippingRate | {clinicId, clinicLocationId, patientId, productIds, shippingState: "AZ", isRushOrder} → {shippingMethod, rushOrderCost, rushOrderMethod, isSignatureRequired}; 州级VPI的400不向. |
POST /clinic/rxOrdering/checkProviderSignatureNeededDuplicate | isDuplicate 当同一病人和同一产品存在活性(未存档)处方时,则属实; isProviderSignatureNeeded 从设置( 默认为真) . |
POST /clinic/rxOrdering/saveNewPrescription | 根据合同验证整个有效载荷(运输国必须是 犬科全名, (中文(简体) ), controlledSubstance 必须是 "0"——400个 {message, errors: [{path, message}]}(a) 未知的诊所/地点/提供者/病人/产品; 成功:草案 Provider Signature Needed 在不完整的清单中 {message, prescriptionId, isRefillRequest: false, refillFromPrescriptionId: null}。 。 。 . |
POST /patients/getPatientByPatientId, (中文(简体) ), …/getPatientAddressesByPatientId | {patientId, userId} - 患者(dateOfBirth, (中文(简体) ), phoneNumber, (中文(简体) ), cellPhone),或 {addresses: [...]}。 。 。 . |
POST /patients/getPatientsInClinic | {clinicId, userId, limit, currentPage} → {pagination: {hasNextPage, currentPage, limit, totalCount}, patients}。 。 。 . |
POST /staffs/getAllProvidersByClinicLocationId | {clinicLocationId, clinicId} * 供应商 npi。 。 。 . |
POST /clinicLocations/getClinicLocationByClinicLocationId | {clinicLocationId} → {id, clinicId, locationName, …}。 。 。 . |
POST /clinic/rxOrdering/getIncompleteSavedPrescriptionsInClinicLocation, (中文(简体) ), …/getSubmittedPrescriptionsInClinicLocation, (中文(简体) ), …/getArchivedPrescriptionsInClinic | {clinicLocationId, userId, limit, currentPage} 一页,最新一页 {prescriptionId, prescriptionStatus, trackingNumber, patientId, createdAt}每个信封 statusEnvelope (默认) vendor: 已提交 {message: {prescriptions}},存档 {message: [...]} 有行键 id,不完整的光线阵列). |
生命周期和状况清单
过渡 to | 列表 | 我们的消费者地图 |
|---|---|---|
Provider Signature Needed (草案), Signature Needed, (中文(简体) ), New Formula Pending | 不完整 | 处理 |
Received, (中文(简体) ), Order Received | 提交的 | 提交的 |
In Process, (中文(简体) ), Order In Process, (中文(简体) ), Prescriptions In Process, (中文(简体) ), On Hold, (中文(简体) ), Order On Hold | 提交的 | 处理 |
Completed, (中文(简体) ), Order Complete, (中文(简体) ), Order Completed (增加一个) 1Z… 当未给出时跟踪编号) | 提交的 | 已运出 |
Cancelled, (中文(简体) ), Order Cancelled | 存档 | 已取消 |
Archived,或任何其他字符串(已使用逐字记录) | 存档/ 提交 | 未刷新( 无刷新) |
我们的消费者 无已交付状态 vPI和铁路草案开始于 processing,所以一个
(b) 支付这种铁路运输的加工/发运(或取消).
管理员(超过标准合同)
| 路线 | 效果 |
|---|---|
POST /__admin/prescriptions/:id/transition | {to, trackingNumber?, list?: "incomplete" | "submitted" | "archived"}。 。 。 . |
GET /__admin/prescriptions | 取名空间的处方(只有标识和状态). |
POST /__admin/patients | 种子诊所病人 {firstName, lastName, dateOfBirth, email?, phoneNumber?, cellPhone?, id?, clinicId?, addresses?: [{addressLine1, addressLine2?, city, state, zipcode}]} (VPI病人的创作不属于我们的客户). GET 列出他们. |
GET /__admin/catalog | 产品、供应商和诊所地点. |
PUT /__admin/settings | {tokenTtlSeconds?, accounts?: [{email, password, id}], statusEnvelope?, isProviderSignatureNeeded?}。 。 。 . |
错误预设( E)POST /__admin/faults {"preset": "<name>", "count"?: n}· ; GET /__admin/faults/presets:
token_expired (401次授权电话 count: 1 我们的客户重新认证准确
一次复试成功, unauthorized_twice (重试也失败了), auth_rejected, (中文(简体) ),
server_error, (中文(简体) ), duplicate_prescription, (中文(简体) ), save_ambiguous_409 (保存草案,然后409:我们)
分类员说需要审查, save_rate_limited (429,未保存:需要 审查),, save_400
(通过浏览器代理重试), response_drift (分类和产品细节字段更改类型:
我们的zod剖析失败关闭.
命名空间
x-mockingbird-namespace页:1 /__admin/ns/<name> 前缀在 VPI_API_URL,或者通过登录电子邮件:
PUT /__admin/credentials {"credentials": {"<VPI_API_EMAIL>": "<namespace>"}} (JWT携带
电子邮件。 认证本身在默认名称空间( 或 /__admin/ns/ 1); 符号
在每个命名空间进行校验.
故意不模拟
- Webhooks:VPI没有;我们的后端民调.
- 患者创建、诊所违约卡计费(
encryptedBillingInfo)和提供者签名: 我们的客户没有抓住这些合同, 通过行政API的种子病人. - 刷新交换(我们的客户端用电子邮件/密码重新认证) .
- 实际定价、税费和运费率表:每名冷冻/消毒/冲刷的费率固定不变.
- 活目录:种子被合成到我们的客户端的域名中(没有沙盒记录).
API 密码
| 导出 | 仁爱 | 说明 |
|---|---|---|
VpiAPI | 类 | 进程模拟器 : fetch(request), (中文(简体) ), reset(), (中文(简体) ), transition(id, {to, trackingNumber?, list?}), (中文(简体) ), addPatient(input), (中文(简体) ), prescriptions()选项: sqlite, (中文(简体) ), now, (中文(简体) ), namespace, (中文(简体) ), seed, (中文(简体) ), settings。 。 。 . |
createRuntime | 函数 | 全面服务合同的仿真器(保健、管理、命名空间、证书、预设和日记)。 选项 : data, (中文(简体) ), settings, (中文(简体) ), clock, (中文(简体) ), seed, (中文(简体) ), adminKey, (中文(简体) ), onLog, (中文(简体) ), sqlite。 。 。 . |
VPI_PRESETS | 对象 | 每个命名的断层预设. |
VPI_NAMESPACE | 字符串 | 服务名称, "vpi"。 。 。 . |
tokenCredential | 函数 | 无记名 JWT 携带的登录电子邮件( 如何绘制命名空间的证书地图 ). |
issueJwt | 函数 | 模拟器接受的 JWT 薄荷 {sub, email, iat, exp}。 。 。 . |
DEFAULT_USER_ID, (中文(简体) ), DEFAULT_CLINIC_ID, (中文(简体) ), DEFAULT_CLINIC_LOCATION_ID, (中文(简体) ), DEFAULT_PROVIDER_ID, (中文(简体) ), DEFAULT_PATIENT_ID | 字符串 | 被种子的标识. |
DEFAULT_PRODUCTS, (中文(简体) ), DEFAULT_PROVIDERS, (中文(简体) ), DEFAULT_PATIENTS, (中文(简体) ), DEFAULT_CLINIC_LOCATION, (中文(简体) ), SHIPPING_STATES | 数值 | 种子数据. |
document, (中文(简体) ), operationIds, (中文(简体) ), supportedOperationIds | 数值 | 销售商为OpenAPI合同及其业务代号. |
createServer, (中文(简体) ), serveTarget, (中文(简体) ), DEFAULT_PORT (单位:千美元)./server(中文(简体) ) | 节点 | 服务过来 node:http; 数据 serve CLI目标(--token-ttl; 第8802号口. |
部分 嘲笑鸟。 。 。 .