@crvouga/mockingbird-service-fullscript 3.14.0 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["<define:__MOCKINGBIRD_ADMIN_BRAND__>", "mockingbird-service-runtime:@crvouga/mockingbird-runtime/service", "../src/generated/openapi.ts", "../src/pdf.ts", "../src/state.ts", "../src/runtime.ts", "../src/index.ts"],
4
+ "sourcesContent": ["{\"vendor\":\"Fullscript\",\"website\":\"https://fullscript.com\",\"docs\":\"https://fullscript.dev\",\"guide\":\"https://mockingbird.chrisvouga.dev/services/fullscript\",\"logo\":\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjU2IiBoZWlnaHQ9IjI1NiIgdmlld0JveD0iMCAwIDI1NiAyNTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxtYXNrIGlkPSJtYXNrMF8yNV84IiBzdHlsZT0ibWFzay10eXBlOmx1bWluYW5jZSIgbWFza1VuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeD0iMCIgeT0iMTYiIHdpZHRoPSIyNTYiIGhlaWdodD0iMjI1Ij4KPHBhdGggZD0iTTI1NiAxNkgwVjI0MC42NjJIMjU2VjE2WiIgZmlsbD0id2hpdGUiLz4KPC9tYXNrPgo8ZyBtYXNrPSJ1cmwoI21hc2swXzI1XzgpIj4KPHBhdGggZD0iTTIzMC4xNzQgMTAzLjU4OUMyMzAuMTc0IDEwMy41ODkgMjMwLjE3NCAxMDMuOTk4IDIzMC4xNzQgMTA0LjQwN0MyMzAuMTc0IDEwNy42NzcgMjI1LjI1OCAxNzYuMzM1IDE0MC40NTUgMjA3LjM5NVYxNjQuNDgzTDE5MS42NjQgMTA4LjkwMkMxOTYuMTcxIDEwMy45OTggMTk2LjE3MSA5Ni4yMzMzIDE5MC44NDUgOTEuMzI5MkMxODUuOTI5IDg2LjgzMzMgMTc4LjE0NSA4Ni44MzMzIDE3My4yMjkgOTIuMTQ2MUwxNDAuNDU1IDEyOC4xMTFWOTEuMzI5MkMxNDAuNDU1IDkxLjMyOTIgMTQwLjQ1NSA5MS4zMjkyIDE0MC40NTUgOTAuOTIwNEMxNDQuNTUyIDgxLjUyMDQgMTY0LjIxNiA0NC43Mzg5IDIxMi41NTcgNDQuNzM4OUMyMTIuOTY3IDQ0LjczODkgMjEzLjM3NyA0NC43Mzg5IDIxMy43ODcgNDQuNzM4OUMyMzMuMDQxIDY3LjYyNTMgMjMwLjE3NCAxMDMuMTgxIDIzMC4xNzQgMTAzLjU4OVpNMTE1Ljg3NSAxMjguMTExTDgyLjY5MDggOTIuMTQ2MUM3OC4xODQzIDg3LjI0MiA3MC40MDA2IDg2LjgzMzMgNjUuNDg0NSA5MS4zMjkyQzYwLjU2ODUgOTUuODI0NiA2MC4xNTg5IDEwMy45OTggNjQuNjY1MyAxMDguOTAyTDExNS44NzUgMTY0LjQ4M1YyMDYuOTg3QzMxLjA3MiAxNzUuOTI3IDI2LjU2NTYgMTA2Ljg1OSAyNi4xNTU5IDEwMy45OThDMjYuMTU1OSAxMDMuNTg5IDI2LjE1NTkgMTAzLjU4OSAyNi4xNTU5IDEwMy4xODFDMjYuMTU1OSAxMDIuNzcyIDIyLjg3ODUgNjcuMjE2NiA0Mi4xMzMyIDQ0LjMzMDJDNDIuNTQyOCA0NC4zMzAyIDQyLjk1MjUgNDQuMzMwMiA0My43NzE5IDQ0LjMzMDJDOTIuNTIzIDQ0LjMzMDIgMTExLjc3OCA4MS41MjA0IDExNS44NzUgOTAuNTExN0MxMTUuODc1IDkwLjUxMTcgMTE1Ljg3NSA5MC41MTE3IDExNS44NzUgOTAuOTIwNFYxMjguMTExWk0yMjguNTM1IDIzLjQ4NzNDMjI2LjQ4NiAyMS40NDM5IDIyMy42MTkgMjAuMjE3OCAyMjAuNzUxIDE5LjgwOTJDMTc0LjQ1OCAxNi45NDg0IDE0NC4xNDIgNDAuNjUyMSAxMjguMTY1IDYyLjcyMTJDMTEyLjE4NyA0MC42NTIxIDgyLjI4MTIgMTYuOTQ4NCAzNS41Nzg0IDE5LjgwOTJDMzIuNzEwNyAxOS44MDkyIDI5Ljg0MjkgMjEuNDQzOSAyNy43OTQ2IDIzLjQ4NzNDLTIuMTExNjMgNTMuMzIxMyAxLjE2NTc3IDEwMC43MjkgMS41NzU0NSAxMDUuMjI0QzEuNTc1NDUgMTA4LjQ5NCAzLjYyMzgxIDEzMS43ODkgMTguNzgxNyAxNTguNzYyQzMzLjEyMDQgMTg0LjUwOSA2My40MzYxIDIxOC40MyAxMjMuNjU4IDIzNS41OTRDMTI0LjA2OCAyMzUuNTk0IDEyNC40NzggMjM1LjU5NCAxMjQuNDc4IDIzNi4wMDNDMTI0Ljg4NyAyMzYuMDAzIDEyNC44ODcgMjM2LjAwMyAxMjUuMjk3IDIzNi4wMDNDMTI1LjcwNyAyMzYuMDAzIDEyNS43MDcgMjM2LjAwMyAxMjYuMTE2IDIzNi4wMDNDMTI2LjUyNiAyMzYuMDAzIDEyNy4zNDYgMjM2LjAwMyAxMjcuNzU1IDIzNi4wMDNDMTI4LjE2NSAyMzYuMDAzIDEyOC45ODQgMjM2LjAwMyAxMjkuMzk0IDIzNi4wMDNDMTI5LjgwMyAyMzYuMDAzIDEyOS44MDMgMjM2LjAwMyAxMzAuMjEzIDIzNi4wMDNDMTMwLjYyMyAyMzYuMDAzIDEzMC42MjMgMjM2LjAwMyAxMzEuMDMyIDIzNi4wMDNDMTMxLjQ0MiAyMzYuMDAzIDEzMS44NTIgMjM2LjAwMyAxMzIuMjYyIDIzNS41OTRDMjQ0LjEwMiAyMDQuMTI2IDI1My45MzUgMTE0LjIxNSAyNTQuMzQ1IDEwNS42MzNDMjU0Ljc1NCAxMDMuMTgxIDI1OC44NTEgNTQuMTM4NyAyMjguNTM1IDIzLjQ4NzNaIiBmaWxsPSIjODhCMDRCIi8+CjwvZz4KPC9zdmc+Cg==\",\"color\":null,\"description\":\"Empowering providers and patients with clinical insights. Use Fullscript to order lab tests, manage supplement plans, and track health progress together.\"}", "export * from \"@crvouga/mockingbird-runtime/service\"\nimport { PACKAGE_VERSION as SHARED_VERSION, createRuntime as sharedRuntime } from \"@crvouga/mockingbird-runtime/service\"\nexport const PACKAGE_VERSION =\n typeof __MOCKINGBIRD_PACKAGE_VERSION__ === \"string\" ? __MOCKINGBIRD_PACKAGE_VERSION__ : SHARED_VERSION\nconst ADMIN_BRAND =\n typeof __MOCKINGBIRD_ADMIN_BRAND__ === \"object\" ? __MOCKINGBIRD_ADMIN_BRAND__ : undefined\nexport const createRuntime = (options) =>\n sharedRuntime({\n ...options,\n version: options.version ?? PACKAGE_VERSION,\n adminBrand: options.adminBrand ?? ADMIN_BRAND,\n })\n", "// Generated by @crvouga/mockingbird-openapi-codegen from openapi.yaml. Do not edit.\n\nimport type { OpenAPIDocument } from \"@crvouga/mockingbird-openapi\"\n\nexport const document: OpenAPIDocument = JSON.parse(`{\"openapi\":\"3.1.0\",\"info\":{\"title\":\"Fullscript API (Mockingbird subset)\",\"description\":\"Stateful emulator subset of the Fullscript API for lab ordering: per-practitioner OAuth (authorize, token with authorization_code and refresh_token grants, revoke), clinic, embeddable session grants, lab orders, lab-order events, expiring result PDFs, and signed webhooks. Hand-authored from the EMR consumer (fullscript-api-client.ts, fullscript-event-model.ts, fullscript-webhook-signature.ts).\\\\n\",\"version\":\"1\",\"x-mockingbird-upstream\":{\"note\":\"Wire shapes from the consumer app's EMR backend (its Fullscript services and routers); the vendor's API reference is behind a partner login.\"}},\"servers\":[{\"url\":\"https://api-us-snd.fullscript.io\"}],\"security\":[{\"bearerAuth\":[]}],\"paths\":{\"/api/oauth/token\":{\"post\":{\"operationId\":\"OAuthToken\",\"description\":\"Exchange an authorization code, or rotate a refresh token (the old refresh token stops working).\",\"x-mockingbird\":{\"supported\":true,\"parity\":{\"enabled\":true,\"safe\":true}},\"responses\":{\"200\":{\"description\":\"Token\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/OAuthTokenResponse\"}}}},\"400\":{\"description\":\"invalid_grant / unsupported_grant_type / invalid_request\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/OAuthError\"}}}},\"401\":{\"description\":\"invalid_client\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/OAuthError\"}}}},\"429\":{\"description\":\"Rate limited\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}}},\"security\":[],\"requestBody\":{\"required\":true,\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/TokenRequest\"}}}}}},\"/api/oauth/revoke\":{\"post\":{\"operationId\":\"OAuthRevoke\",\"description\":\"Revoke an access or refresh token (RFC 7009: always 200).\",\"x-mockingbird\":{\"supported\":true,\"parity\":{\"enabled\":true,\"safe\":false}},\"responses\":{\"200\":{\"description\":\"Revoked\",\"content\":{\"application/json\":{\"schema\":{\"type\":\"object\"}}}},\"400\":{\"description\":\"invalid_request\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/OAuthError\"}}}},\"401\":{\"description\":\"invalid_client\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/OAuthError\"}}}},\"429\":{\"description\":\"Rate limited\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}}},\"security\":[],\"requestBody\":{\"required\":true,\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/RevokeRequest\"}}}}}},\"/api/clinic\":{\"get\":{\"operationId\":\"GetClinic\",\"description\":\"The token's clinic.\",\"x-mockingbird\":{\"supported\":true,\"parity\":{\"enabled\":true,\"safe\":true}},\"responses\":{\"200\":{\"description\":\"Clinic\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ClinicResponse\"}}}},\"401\":{\"description\":\"Missing, invalid, expired or revoked access token\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}},\"429\":{\"description\":\"Rate limited\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}}}}},\"/api/clinic/embeddable/session_grants\":{\"post\":{\"operationId\":\"CreateSessionGrant\",\"description\":\"A short-lived secret for the embedded Fullscript widget.\",\"x-mockingbird\":{\"supported\":true,\"parity\":{\"enabled\":true,\"safe\":true}},\"responses\":{\"201\":{\"description\":\"Grant\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/SessionGrant\"}}}},\"401\":{\"description\":\"Missing, invalid, expired or revoked access token\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}},\"429\":{\"description\":\"Rate limited\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}}}}},\"/api/clinic/labs/orders\":{\"get\":{\"operationId\":\"ListLabOrders\",\"description\":\"The clinic's lab orders (optionally one patient's), paged.\",\"x-mockingbird\":{\"supported\":true,\"parity\":{\"enabled\":true,\"safe\":true}},\"responses\":{\"200\":{\"description\":\"Page\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/LabOrdersPage\"}}}},\"401\":{\"description\":\"Missing, invalid, expired or revoked access token\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}},\"429\":{\"description\":\"Rate limited\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}}},\"parameters\":[{\"name\":\"patient_id\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"string\",\"enum\":[\"pat_seed_1\",\"pat_seed_2\",\"pat_missing\"]}},{\"name\":\"page[number]\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":3}},{\"name\":\"page[size]\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":100}}]}},\"/api/clinic/labs/orders/{orderId}\":{\"get\":{\"operationId\":\"GetLabOrder\",\"description\":\"One lab order with tests, per-test results and the aggregated result.\",\"x-mockingbird\":{\"supported\":true,\"parity\":{\"enabled\":true,\"safe\":true}},\"responses\":{\"200\":{\"description\":\"Order\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/LabOrderResponse\"}}}},\"401\":{\"description\":\"Missing, invalid, expired or revoked access token\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}},\"404\":{\"description\":\"Unknown order\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}},\"429\":{\"description\":\"Rate limited\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}}},\"parameters\":[{\"name\":\"orderId\",\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"string\",\"enum\":[\"lo_seed_1\",\"lo_seed_2\",\"lo_seed_3\",\"lo_missing\"]}}]}},\"/api/events/lab_orders\":{\"get\":{\"operationId\":\"ListLabOrderEvents\",\"description\":\"The clinic's lab_order.updated events, newest first by default.\",\"x-mockingbird\":{\"supported\":true,\"parity\":{\"enabled\":true,\"safe\":true}},\"responses\":{\"200\":{\"description\":\"Page\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/EventsPage\"}}}},\"401\":{\"description\":\"Missing, invalid, expired or revoked access token\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}},\"429\":{\"description\":\"Rate limited\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}}},\"parameters\":[{\"name\":\"order_by\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"string\",\"enum\":[\"DESC\",\"ASC\"]}},{\"name\":\"page[number]\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":3}},{\"name\":\"page[size]\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":100}}]}},\"/api/events/{eventId}\":{\"get\":{\"operationId\":\"GetEvent\",\"description\":\"One event with its data.\",\"x-mockingbird\":{\"supported\":true,\"parity\":{\"enabled\":true,\"safe\":true}},\"responses\":{\"200\":{\"description\":\"Event\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/EventResponse\"}}}},\"401\":{\"description\":\"Missing, invalid, expired or revoked access token\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}},\"404\":{\"description\":\"Unknown event\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}},\"429\":{\"description\":\"Rate limited\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/ApiErrors\"}}}}},\"parameters\":[{\"name\":\"eventId\",\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"string\",\"enum\":[\"evt_1\",\"evt_2\",\"evt_3\",\"evt_missing\"]}}]}},\"/oauth/authorize\":{\"get\":{\"operationId\":\"Authorize\",\"description\":\"The consent page: auto-approves as the requested (or default) practitioner and redirects to redirect_uri with code and state.\",\"security\":[],\"x-mockingbird\":{\"supported\":true,\"parity\":{\"enabled\":false,\"reason\":\"Browser redirect flow; covered by acceptance tests.\"}},\"parameters\":[{\"name\":\"client_id\",\"in\":\"query\",\"required\":true,\"schema\":{\"type\":\"string\"}},{\"name\":\"redirect_uri\",\"in\":\"query\",\"required\":true,\"schema\":{\"type\":\"string\"}},{\"name\":\"response_type\",\"in\":\"query\",\"required\":true,\"schema\":{\"type\":\"string\",\"enum\":[\"code\"]}},{\"name\":\"state\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"string\"}},{\"name\":\"scope\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"string\"}},{\"name\":\"practitioner_id\",\"in\":\"query\",\"required\":false,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"302\":{\"description\":\"Redirect back with ?code=&state=\"},\"400\":{\"description\":\"Bad request\",\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/OAuthError\"}}}}}}},\"/results/{artifactId}\":{\"get\":{\"operationId\":\"GetResultPdf\",\"description\":\"An expiring result PDF URL (what pdf_url points at).\",\"security\":[],\"x-mockingbird\":{\"supported\":true,\"parity\":{\"enabled\":false,\"reason\":\"Binary PDF behind an expiring signed URL; covered by acceptance tests.\"}},\"parameters\":[{\"name\":\"artifactId\",\"in\":\"path\",\"required\":true,\"schema\":{\"type\":\"string\"}},{\"name\":\"expires\",\"in\":\"query\",\"required\":true,\"schema\":{\"type\":\"string\"}},{\"name\":\"signature\",\"in\":\"query\",\"required\":true,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"description\":\"The PDF\",\"content\":{\"application/pdf\":{\"schema\":{\"type\":\"string\",\"format\":\"binary\"}}}},\"403\":{\"description\":\"Expired or bad signature\"},\"404\":{\"description\":\"Unknown artifact\"}}}}},\"components\":{\"securitySchemes\":{\"bearerAuth\":{\"type\":\"http\",\"scheme\":\"bearer\"}},\"schemas\":{\"TokenRequest\":{\"type\":\"object\",\"required\":[\"grant_type\",\"client_id\",\"client_secret\"],\"properties\":{\"grant_type\":{\"type\":\"string\",\"enum\":[\"authorization_code\",\"refresh_token\"]},\"client_id\":{\"type\":\"string\",\"minLength\":1,\"maxLength\":64,\"examples\":[\"parity-client\"]},\"client_secret\":{\"type\":\"string\",\"minLength\":1,\"maxLength\":64,\"examples\":[\"parity-secret\"]},\"code\":{\"type\":\"string\",\"maxLength\":64},\"refresh_token\":{\"type\":\"string\",\"maxLength\":200},\"redirect_uri\":{\"type\":\"string\",\"maxLength\":200,\"examples\":[\"https://emr.example.com/v1/fullscript/oauth/callback\"]}}},\"RevokeRequest\":{\"type\":\"object\",\"required\":[\"client_id\",\"client_secret\",\"token\"],\"properties\":{\"client_id\":{\"type\":\"string\",\"minLength\":1,\"maxLength\":64},\"client_secret\":{\"type\":\"string\",\"minLength\":1,\"maxLength\":64},\"token\":{\"type\":\"string\",\"minLength\":1,\"maxLength\":200}}},\"OAuthTokenResponse\":{\"type\":\"object\",\"required\":[\"oauth\"],\"properties\":{\"oauth\":{\"type\":\"object\",\"required\":[\"access_token\",\"token_type\",\"expires_in\",\"refresh_token\",\"scope\",\"created_at\",\"resource_owner\"],\"properties\":{\"access_token\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"token\"}},\"token_type\":{\"type\":\"string\",\"enum\":[\"Bearer\"]},\"expires_in\":{\"type\":\"integer\"},\"refresh_token\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"token\"}},\"scope\":{\"type\":\"string\"},\"created_at\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"timestamp\"}},\"resource_owner\":{\"type\":\"object\",\"required\":[\"id\",\"type\"],\"properties\":{\"id\":{\"type\":\"string\"},\"type\":{\"type\":\"string\",\"enum\":[\"Practitioner\",\"Staff\"]},\"clinic_id\":{\"type\":\"string\"}}}}}}},\"OAuthError\":{\"type\":\"object\",\"required\":[\"error\"],\"properties\":{\"error\":{\"type\":\"string\"},\"error_description\":{\"type\":\"string\"}}},\"ApiErrors\":{\"type\":\"object\",\"required\":[\"errors\"],\"properties\":{\"errors\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"code\",\"message\"],\"properties\":{\"code\":{\"type\":\"string\"},\"message\":{\"type\":\"string\"}}}}}},\"ClinicResponse\":{\"type\":\"object\",\"required\":[\"clinic\"],\"properties\":{\"clinic\":{\"type\":\"object\",\"required\":[\"id\",\"name\"],\"properties\":{\"id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"},\"created_at\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"timestamp\"}}}}}},\"SessionGrant\":{\"type\":\"object\",\"required\":[\"secret_token\",\"expires_at\"],\"properties\":{\"secret_token\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"token\"}},\"expires_at\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"timestamp\"}}}},\"LabOrderSummary\":{\"type\":\"object\",\"required\":[\"id\",\"state\",\"treatment_plan_id\",\"patient_id\",\"created_at\",\"updated_at\"],\"properties\":{\"id\":{\"type\":\"string\"},\"state\":{\"type\":\"string\",\"enum\":[\"not_purchased\",\"purchased\",\"schedule_appointment\",\"upcoming_appointment\",\"processing\",\"partial_results\",\"results_ready\",\"interpretation_shared\",\"results_amended\"]},\"treatment_plan_id\":{\"type\":[\"string\",\"null\"]},\"patient_id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"},\"created_at\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"timestamp\"}},\"updated_at\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"timestamp\"}}}},\"LabOrdersPage\":{\"type\":\"object\",\"required\":[\"orders\",\"meta\"],\"properties\":{\"orders\":{\"type\":\"array\",\"items\":{\"$ref\":\"#/components/schemas/LabOrderSummary\"}},\"meta\":{\"type\":\"object\",\"required\":[\"current_page\",\"next_page\",\"prev_page\",\"total_pages\",\"total_count\"],\"properties\":{\"current_page\":{\"type\":\"integer\"},\"next_page\":{\"type\":[\"integer\",\"null\"]},\"prev_page\":{\"type\":[\"integer\",\"null\"]},\"total_pages\":{\"type\":\"integer\"},\"total_count\":{\"type\":\"integer\"}}}}},\"LabOrderResponse\":{\"type\":\"object\",\"required\":[\"order\"],\"properties\":{\"order\":{\"type\":\"object\",\"required\":[\"id\",\"state\",\"treatment_plan_id\",\"tests\",\"results\",\"latest_aggregated_result\"],\"properties\":{\"id\":{\"type\":\"string\"},\"state\":{\"type\":\"string\",\"enum\":[\"not_purchased\",\"purchased\",\"schedule_appointment\",\"upcoming_appointment\",\"processing\",\"partial_results\",\"results_ready\",\"interpretation_shared\",\"results_amended\"]},\"treatment_plan_id\":{\"type\":[\"string\",\"null\"]},\"patient_id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"},\"collection_method\":{\"type\":\"string\"},\"created_at\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"timestamp\"}},\"updated_at\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"timestamp\"}},\"tests\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"id\",\"name\"],\"properties\":{\"id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"},\"lab_type\":{\"type\":\"string\"}}}},\"results\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"required\":[\"id\",\"name\",\"state\",\"pdf_url\"],\"properties\":{\"id\":{\"type\":\"string\"},\"name\":{\"type\":\"string\"},\"state\":{\"type\":\"string\"},\"pdf_url\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"url\"}}}}},\"latest_aggregated_result\":{\"type\":[\"object\",\"null\"],\"properties\":{\"id\":{\"type\":\"string\"},\"artifact_id\":{\"type\":\"string\"},\"pdf_url\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"url\"}},\"status\":{\"type\":\"string\"}}}}}}},\"EventSummary\":{\"type\":\"object\",\"required\":[\"id\",\"type\",\"clinic_id\",\"created_at\"],\"properties\":{\"id\":{\"type\":\"string\"},\"type\":{\"type\":\"string\",\"enum\":[\"lab_order.updated\"]},\"clinic_id\":{\"type\":\"string\"},\"created_at\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"timestamp\"}}}},\"EventsPage\":{\"type\":\"object\",\"required\":[\"events\",\"meta\"],\"properties\":{\"events\":{\"type\":\"array\",\"items\":{\"$ref\":\"#/components/schemas/EventSummary\"}},\"meta\":{\"type\":\"object\",\"required\":[\"current_page\",\"next_page\",\"prev_page\",\"total_pages\",\"total_count\"],\"properties\":{\"current_page\":{\"type\":\"integer\"},\"next_page\":{\"type\":[\"integer\",\"null\"]},\"prev_page\":{\"type\":[\"integer\",\"null\"]},\"total_pages\":{\"type\":\"integer\"},\"total_count\":{\"type\":\"integer\"}}}}},\"EventResponse\":{\"type\":\"object\",\"required\":[\"event\"],\"properties\":{\"event\":{\"type\":\"object\",\"required\":[\"id\",\"type\",\"clinic_id\",\"created_at\",\"data\"],\"properties\":{\"id\":{\"type\":\"string\"},\"type\":{\"type\":\"string\"},\"clinic_id\":{\"type\":\"string\"},\"created_at\":{\"type\":\"string\",\"x-mockingbird-volatile\":{\"kind\":\"timestamp\"}},\"data\":{\"type\":\"object\"}}}}}}}}`) as OpenAPIDocument\n\nexport type OperationId = \"OAuthToken\" | \"OAuthRevoke\" | \"GetClinic\" | \"CreateSessionGrant\" | \"ListLabOrders\" | \"GetLabOrder\" | \"ListLabOrderEvents\" | \"GetEvent\" | \"Authorize\" | \"GetResultPdf\"\nexport type SupportedOperationId = \"OAuthToken\" | \"OAuthRevoke\" | \"GetClinic\" | \"CreateSessionGrant\" | \"ListLabOrders\" | \"GetLabOrder\" | \"ListLabOrderEvents\" | \"GetEvent\" | \"Authorize\" | \"GetResultPdf\"\nexport const operationIds = [\"OAuthToken\",\"OAuthRevoke\",\"GetClinic\",\"CreateSessionGrant\",\"ListLabOrders\",\"GetLabOrder\",\"ListLabOrderEvents\",\"GetEvent\",\"Authorize\",\"GetResultPdf\"] as const\nexport const supportedOperationIds = [\"OAuthToken\",\"OAuthRevoke\",\"GetClinic\",\"CreateSessionGrant\",\"ListLabOrders\",\"GetLabOrder\",\"ListLabOrderEvents\",\"GetEvent\",\"Authorize\",\"GetResultPdf\"] as const\n", "/** A minimal, valid one-page PDF: what every result URL serves (starts with `%PDF-`). */\nexport const RESULT_PDF: Uint8Array = new TextEncoder().encode(\n \"%PDF-1.4\\n1 0 obj\\n<< /Type /Catalog /Pages 2 0 R >>\\nendobj\\n2 0 obj\\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\\nendobj\\n3 0 obj\\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 4 0 R /Resources << /Font << /F1 5 0 R >> >> >>\\nendobj\\n4 0 obj\\n<< /Length 64 >>\\nstream\\nBT /F1 18 Tf 72 720 Td (Mockingbird Fullscript lab result) Tj ET\\nendstream\\nendobj\\n5 0 obj\\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\\nendobj\\nxref\\n0 6\\n0000000000 65535 f \\n0000000009 00000 n \\n0000000058 00000 n \\n0000000115 00000 n \\n0000000241 00000 n \\n0000000355 00000 n \\ntrailer\\n<< /Size 6 /Root 1 0 R >>\\nstartxref\\n425\\n%%EOF\\n\",\n)\n", "import { Collection } from \"@crvouga/mockingbird-service\"\nimport type { SqliteClient } from \"@crvouga/mockingbird-sqlite\"\n\n/** Lab order states, in the only order they may move (forward). */\nexport const LAB_ORDER_STATES = [\n \"not_purchased\",\n \"purchased\",\n \"schedule_appointment\",\n \"upcoming_appointment\",\n \"processing\",\n \"partial_results\",\n \"results_ready\",\n \"interpretation_shared\",\n \"results_amended\",\n] as const\n\nexport type LabOrderState = (typeof LAB_ORDER_STATES)[number]\n\nexport const isLabOrderState = (value: unknown): value is LabOrderState =>\n typeof value === \"string\" && (LAB_ORDER_STATES as readonly string[]).includes(value)\n\nexport const stateRank = (state: LabOrderState) => LAB_ORDER_STATES.indexOf(state)\n\nexport type Practitioner = { id: string; type: \"Practitioner\" | \"Staff\"; clinicId: string }\nexport type Clinic = { id: string; name: string; created_at: string }\n\nexport type LabResult = { id: string; name: string; state: string; artifactId: string }\n\nexport type LabOrderRecord = {\n id: string\n clinicId: string\n patientId: string\n treatmentPlanId: string | null\n name: string\n collectionMethod: string\n state: LabOrderState\n tests: { id: string; name: string; lab_type: string }[]\n results: LabResult[]\n aggregated: { id: string; artifactId: string; status: string } | null\n created_at: string\n updated_at: string\n}\n\nexport type EventRecord = {\n id: string\n type: \"lab_order.updated\" | \"order.placed\"\n clinic_id: string\n created_at: string\n data: Record<string, unknown>\n /** Insertion order, for ASC / DESC paging. */\n seq: number\n}\n\nexport type CodeRecord = {\n code: string\n practitionerId: string\n clientId: string\n redirectUri: string | null\n expiresAtMs: number\n used: boolean\n}\n\nexport type RefreshRecord = {\n token: string\n practitionerId: string\n clientId: string\n revoked: boolean\n}\n\n/** Per-namespace knobs, set through `PUT /__admin/settings`; cleared on reset. */\nexport type Settings = {\n /** Only these OAuth clients authenticate; empty means any id/secret pair does. */\n clients: { clientId: string; clientSecret: string }[]\n /** Access-token lifetime on the mock clock. Default 7200 s (2 h). */\n accessTokenTtlSeconds: number\n /** Authorization-code lifetime. Default 600 s. */\n codeTtlSeconds: number\n /** Lifetime of a result PDF URL. Default 900 s. */\n pdfUrlTtlSeconds: number\n /** Origin (plus optional path) result PDF URLs point at; default: the request's own origin. */\n resultsBaseUrl: string | null\n}\n\nexport const DEFAULT_SETTINGS: Settings = {\n clients: [],\n accessTokenTtlSeconds: 7_200,\n codeTtlSeconds: 600,\n pdfUrlTtlSeconds: 900,\n resultsBaseUrl: null,\n}\n\nexport const DEFAULT_CLINIC: Clinic = {\n id: \"clinic_mock_1\",\n name: \"Acme Mock Clinic\",\n created_at: \"2025-01-01T00:00:00.000Z\",\n}\nexport const DEFAULT_PRACTITIONER: Practitioner = {\n id: \"prac_mock_1\",\n type: \"Practitioner\",\n clinicId: DEFAULT_CLINIC.id,\n}\n\ntype Counters = { code: number; refresh: number; order: number; event: number; artifact: number }\n\nexport class FullscriptState {\n readonly practitioners: Collection<Practitioner>\n readonly clinics: Collection<Clinic>\n readonly codes: Collection<CodeRecord>\n readonly refresh: Collection<RefreshRecord>\n readonly revoked: Collection<{ token: string }>\n readonly orders: Collection<LabOrderRecord>\n readonly events: Collection<EventRecord>\n readonly settings: Collection<Settings>\n private readonly counters: Collection<Counters>\n\n constructor(\n sqlite: SqliteClient,\n namespace: string,\n private readonly seed: Partial<Settings>,\n ) {\n this.practitioners = new Collection(sqlite, namespace, \"practitioners\")\n this.clinics = new Collection(sqlite, namespace, \"clinics\")\n this.codes = new Collection(sqlite, namespace, \"codes\")\n this.refresh = new Collection(sqlite, namespace, \"refresh_tokens\")\n this.revoked = new Collection(sqlite, namespace, \"revoked_tokens\")\n this.orders = new Collection(sqlite, namespace, \"lab_orders\")\n this.events = new Collection(sqlite, namespace, \"events\")\n this.settings = new Collection(sqlite, namespace, \"settings\")\n this.counters = new Collection(sqlite, namespace, \"counters\")\n this.ensureSeeded()\n }\n\n ensureSeeded(): void {\n if (this.clinics.count() === 0) this.clinics.insert(DEFAULT_CLINIC.id, DEFAULT_CLINIC)\n if (this.practitioners.count() === 0) {\n this.practitioners.insert(DEFAULT_PRACTITIONER.id, DEFAULT_PRACTITIONER)\n }\n if (!this.settings.has(\"settings\")) {\n this.settings.insert(\"settings\", { ...DEFAULT_SETTINGS, ...this.seed })\n }\n }\n\n current(): Settings {\n return this.settings.get(\"settings\") ?? DEFAULT_SETTINGS\n }\n\n update(patch: Partial<Settings>): Settings {\n const next = { ...this.current(), ...patch }\n this.settings.insert(\"settings\", next)\n return next\n }\n\n next(kind: keyof Counters): number {\n const current = this.counters.get(\"counters\") ?? {\n code: 0,\n refresh: 0,\n order: 0,\n event: 0,\n artifact: 0,\n }\n const next = { ...current, [kind]: current[kind] + 1 }\n this.counters.insert(\"counters\", next)\n return next[kind]\n }\n}\n", "import {\n type AdminRoutes,\n type Clock,\n createRuntime as createServiceRuntime,\n createWebhookHub,\n type FaultPreset,\n HttpError,\n type MockControls,\n type RequestLog,\n type ServiceRuntime,\n signers,\n type WebhookEndpoint,\n type WebhookHub,\n} from \"@crvouga/mockingbird-service\"\nimport type { SqliteClient } from \"@crvouga/mockingbird-sqlite\"\nimport { document } from \"./generated/openapi.js\"\nimport {\n envelope,\n FULLSCRIPT_NAMESPACE,\n FullscriptAPI,\n type SeedOrder,\n tokenCredential,\n} from \"./index.js\"\nimport { isLabOrderState, type Settings } from \"./state.js\"\n\n/** The header our receiver verifies: `t=<unix>,v1=<hex HMAC-SHA256(secret, \"<t>.\" + body)>`. */\nexport const SIGNATURE_HEADER = \"Fullscript-Signature\"\n\nconst API = \"/api/\"\n\n/**\n * Every named Fullscript misbehaviour our EMR integration branches on, switched on with\n * `POST /__admin/faults {\"preset\": \"<name>\"}` (add `count` to limit it).\n */\nexport const FULLSCRIPT_PRESETS: Record<string, FaultPreset> = {\n token_expired: {\n description:\n \"API calls answer 401 token_expired before the token's 2 h (our token service refreshes)\",\n rules: [\n { pathPrefix: \"/api/clinic\", effect: \"token_expired\" },\n { pathPrefix: \"/api/events\", effect: \"token_expired\" },\n ],\n },\n invalid_grant: {\n description:\n \"The refresh_token grant answers 400 invalid_grant (the practitioner must reconnect)\",\n rules: [{ operationId: \"OAuthToken\", effect: \"invalid_grant\" }],\n },\n rate_limited: {\n description: \"API calls answer 429 rate_limited\",\n rules: [\n {\n pathPrefix: API,\n status: 429,\n body: { errors: [{ code: \"rate_limited\", message: \"Too many requests\" }] },\n },\n ],\n },\n server_error: {\n description: \"API calls answer 500\",\n rules: [\n {\n pathPrefix: API,\n status: 500,\n body: { errors: [{ code: \"internal_server_error\", message: \"Something went wrong\" }] },\n },\n ],\n },\n events_schema_drift: {\n description:\n \"The lab-order events list answers an unexpected event type (our zod literal rejects it)\",\n rules: [{ operationId: \"ListLabOrderEvents\", effect: \"events_schema_drift\" }],\n },\n pdf_not_pdf: {\n description: \"Result PDF URLs answer 200 text/html (our downloader rejects the content type)\",\n rules: [\n {\n operationId: \"GetResultPdf\",\n status: 200,\n body: \"<html>Sign in</html>\",\n headers: { \"content-type\": \"text/html\" },\n },\n ],\n },\n pdf_redirect: {\n description: \"Result PDF URLs answer a 302 (our downloader refuses redirects)\",\n rules: [\n {\n operationId: \"GetResultPdf\",\n status: 302,\n body: \"\",\n headers: { location: \"https://login.fullscript.com/\" },\n },\n ],\n },\n pdf_expired: {\n description: \"Result PDF URLs answer 403 as if expired\",\n rules: [\n {\n operationId: \"GetResultPdf\",\n status: 403,\n body: \"Request has expired\",\n headers: { \"content-type\": \"text/plain\" },\n },\n ],\n },\n connection_drop: {\n description: \"The connection drops before any answer (fetch rejects)\",\n rules: [{ pathPrefix: API, drop: true }],\n },\n slow: {\n description: \"API calls answer after 12 s (past our client's 10 s timeout)\",\n rules: [{ pathPrefix: API, latencyMs: 12_000 }],\n },\n webhook_duplicate: {\n description: \"The next webhook is delivered twice\",\n webhook: { mode: \"duplicate\" },\n },\n webhook_reorder: {\n description: \"The next two webhooks arrive swapped\",\n webhook: { mode: \"reorder\" },\n },\n webhook_drop: { description: \"The next webhook is never delivered\", webhook: { mode: \"drop\" } },\n}\n\nexport type FullscriptRuntimeOptions = {\n sqlite?: SqliteClient\n clock?: Clock\n seed?: number | string\n adminPrefix?: string\n adminKey?: string\n /** Admin controls to boot with: clock, latency, faults, seed, a starting snapshot. */\n adminControls?: MockControls\n onLog?: (entry: RequestLog) => void\n settings?: Partial<Settings>\n orders?: readonly SeedOrder[]\n /**\n * Where webhooks go (`POST /v1/fullscript/webhooks`), signed with `secret` (the app's\n * FULLSCRIPT_WEBHOOK_SECRET). With `challenge` (FULLSCRIPT_WEBHOOK_CHALLENGE_KEY), a delivery\n * counts only when the receiver echoes `{challenge}`, as Fullscript requires.\n */\n webhooks?: Omit<WebhookEndpoint, \"id\"> & {\n challenge?: string\n retryDelaysMs?: readonly number[]\n fetch?: (request: Request) => Promise<Response>\n }\n}\n\nexport type FullscriptRuntime = ServiceRuntime<FullscriptAPI> & { readonly webhooks: WebhookHub }\n\nconst json = (status: number, body: unknown) =>\n new Response(JSON.stringify(body), { status, headers: { \"content-type\": \"application/json\" } })\nconst adminError = (status: number, message: string) =>\n json(status, { error: { type: \"mockingbird_admin\", message } })\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value)\n\n/** Whether a receiver's answer echoes the challenge key (`{\"challenge\": \"<key>\"}`). */\nconst echoes = async (response: Response, challenge: string) => {\n try {\n const body = (await response.clone().json()) as { challenge?: unknown }\n return body.challenge === challenge\n } catch {\n return false\n }\n}\n\nconst adminRoutes =\n (send: (request: Request) => Promise<Response>, challenge: string | undefined) =>\n (runtime: ServiceRuntime<FullscriptAPI>): AdminRoutes => ({\n \"POST /oauth/codes\": ({ body, namespace }) => {\n const input = isRecord(body) ? body : {}\n const api = runtime.instance(namespace)\n const practitionerId =\n typeof input.practitionerId === \"string\" ? input.practitionerId : \"prac_mock_1\"\n if (!api.state.practitioners.get(practitionerId))\n return adminError(404, `no practitioner ${practitionerId}`)\n const code = api.issueCode(\n practitionerId,\n typeof input.clientId === \"string\" ? input.clientId : \"any\",\n typeof input.redirectUri === \"string\" ? input.redirectUri : null,\n )\n return json(201, { code })\n },\n \"POST /practitioners\": ({ body, namespace }) => {\n if (!isRecord(body) || typeof body.id !== \"string\" || typeof body.clinicId !== \"string\") {\n return adminError(\n 400,\n 'expected {\"id\", \"clinicId\", \"type\"?: \"Practitioner\"|\"Staff\", \"clinicName\"?}',\n )\n }\n const api = runtime.instance(namespace)\n if (!api.state.clinics.get(body.clinicId)) {\n api.state.clinics.insert(body.clinicId, {\n id: body.clinicId,\n name: typeof body.clinicName === \"string\" ? body.clinicName : body.clinicId,\n created_at: new Date(runtime.namespaceClock(namespace).now()).toISOString(),\n })\n }\n const practitioner = {\n id: body.id,\n clinicId: body.clinicId,\n type: body.type === \"Staff\" ? (\"Staff\" as const) : (\"Practitioner\" as const),\n }\n api.state.practitioners.insert(practitioner.id, practitioner)\n return json(201, practitioner)\n },\n \"GET /lab-orders\": ({ namespace }) =>\n json(200, { orders: runtime.instance(namespace).labOrders() }),\n \"POST /lab-orders\": ({ body, namespace }) => {\n if (!isRecord(body) || typeof body.patientId !== \"string\") {\n return adminError(\n 400,\n 'expected {\"patientId\", \"id\"?, \"clinicId\"?, \"treatmentPlanId\"?, \"name\"?, \"collectionMethod\"?, \"tests\"?: [names]}',\n )\n }\n const text = (key: string) =>\n typeof body[key] === \"string\" ? { [key]: body[key] as string } : {}\n const order = runtime.instance(namespace).createOrder({\n patientId: body.patientId,\n ...text(\"id\"),\n ...text(\"clinicId\"),\n ...text(\"treatmentPlanId\"),\n ...text(\"name\"),\n ...text(\"collectionMethod\"),\n ...(Array.isArray(body.tests) ? { tests: body.tests.map(String) } : {}),\n })\n return json(201, order)\n },\n \"POST /lab-orders/:id/transition\": ({ params, body, namespace }) => {\n if (!isRecord(body) || !isLabOrderState(body.to)) {\n return adminError(\n 400,\n 'expected {\"to\": \"<purchased|schedule_appointment|upcoming_appointment|processing|partial_results|results_ready|interpretation_shared|results_amended>\"}',\n )\n }\n try {\n return json(200, runtime.instance(namespace).transition(params.id as string, body.to))\n } catch (error) {\n if (error instanceof HttpError) return error.toResponse()\n throw error\n }\n },\n \"GET /events\": ({ namespace }) =>\n json(200, { events: runtime.instance(namespace).eventsList() }),\n \"POST /webhooks/verify\": async ({ namespace }) => {\n const endpoints = runtime.webhooks?.endpoints(namespace) ?? []\n const results = await Promise.all(\n endpoints.map(async (endpoint) => {\n try {\n const response = await send(\n new Request(endpoint.url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n }),\n )\n return {\n url: endpoint.url,\n status: response.status,\n challengeEchoed: challenge ? await echoes(response, challenge) : null,\n }\n } catch (error) {\n return {\n url: endpoint.url,\n status: null,\n error: error instanceof Error ? error.message : String(error),\n }\n }\n }),\n )\n return json(200, { endpoints: results })\n },\n \"GET /settings\": ({ namespace }) => json(200, runtime.instance(namespace).state.current()),\n \"PUT /settings\": ({ body, namespace }) => {\n if (!isRecord(body)) return adminError(400, \"expected a JSON object\")\n const patch: Partial<Settings> = {}\n for (const key of [\"accessTokenTtlSeconds\", \"codeTtlSeconds\", \"pdfUrlTtlSeconds\"] as const) {\n if (body[key] !== undefined) {\n if (typeof body[key] !== \"number\") return adminError(400, `${key}: number`)\n patch[key] = body[key] as number\n }\n }\n if (body.resultsBaseUrl !== undefined) {\n if (body.resultsBaseUrl !== null && typeof body.resultsBaseUrl !== \"string\")\n return adminError(400, \"resultsBaseUrl: string | null\")\n patch.resultsBaseUrl = body.resultsBaseUrl as string | null\n }\n if (body.clients !== undefined) {\n if (!Array.isArray(body.clients))\n return adminError(400, \"clients: [{clientId, clientSecret}]\")\n patch.clients = body.clients\n .filter(isRecord)\n .map((c) => ({ clientId: String(c.clientId), clientSecret: String(c.clientSecret) }))\n }\n return json(200, runtime.instance(namespace).state.update(patch))\n },\n })\n\n/**\n * The Fullscript mock with Mockingbird's full service contract: `/__admin/health`, `/__admin/*`,\n * namespaces by header, by `/__admin/ns/<name>` path prefix on FULLSCRIPT_API_URL, or by OAuth client\n * (for API calls), clock control, fault presets, signed webhooks and a request journal.\n */\nexport const createRuntime = (options: FullscriptRuntimeOptions = {}): FullscriptRuntime => {\n const { retryDelaysMs, fetch: rawSend, challenge, ...endpoint } = options.webhooks ?? { url: \"\" }\n const send = rawSend ?? ((request: Request) => fetch(request))\n const hub = createWebhookHub({\n signer: signers.timestamped(SIGNATURE_HEADER),\n ...(retryDelaysMs ? { retryDelaysMs } : {}),\n // Fullscript counts a delivery as acknowledged only when the receiver echoes the\n // challenge key; anything else is retried (recorded as a 502).\n fetch: async (request) => {\n const response = await send(request)\n if (!challenge || !response.ok || (await echoes(response, challenge))) return response\n return new Response(null, { status: 502, statusText: \"challenge not echoed\" })\n },\n endpoints: options.webhooks ? [endpoint as WebhookEndpoint] : [],\n })\n const runtime = createServiceRuntime<FullscriptAPI>({\n name: FULLSCRIPT_NAMESPACE,\n document,\n ...(options.sqlite ? { sqlite: options.sqlite } : {}),\n ...(options.clock ? { clock: options.clock } : {}),\n ...(options.seed !== undefined ? { seed: options.seed } : {}),\n ...(options.adminPrefix !== undefined ? { adminPrefix: options.adminPrefix } : {}),\n ...(options.adminKey !== undefined ? { adminKey: options.adminKey } : {}),\n ...(options.adminControls !== undefined ? { adminControls: options.adminControls } : {}),\n ...(options.onLog ? { onLog: options.onLog } : {}),\n credential: tokenCredential,\n presets: FULLSCRIPT_PRESETS,\n webhooks: hub,\n create: ({ sqlite, namespace, publicNamespace, adminPrefix, clock }) =>\n new FullscriptAPI({\n sqlite,\n namespace,\n publicNamespace,\n adminPrefix,\n now: clock.now,\n ...(options.settings ? { settings: options.settings } : {}),\n ...(options.orders ? { orders: options.orders } : {}),\n onEvent: (event) =>\n hub.publish({\n namespace: publicNamespace,\n type: event.type,\n id: event.id,\n body: envelope(event),\n }),\n }),\n describe: () => ({ webhooks: hub.endpoints(\"default\").length > 0 ? \"on\" : \"off\" }),\n admin: adminRoutes(send, challenge),\n })\n return Object.assign(runtime, { webhooks: hub })\n}\n", "import type { FetchAPI } from \"@crvouga/mockingbird-core\"\nimport {\n type APIOptions,\n annotateResponse,\n bearerToken,\n bodyIssues,\n bootSqlite,\n coerce,\n createService,\n defineOperations,\n faultEffect,\n fromBase64,\n HttpError,\n jsonRes,\n type OperationContext,\n opaqueToken,\n type Service,\n toBase64,\n} from \"@crvouga/mockingbird-service\"\nimport type { SqliteClient } from \"@crvouga/mockingbird-sqlite\"\nimport type { Hono } from \"hono\"\nimport { document, type SupportedOperationId } from \"./generated/openapi.js\"\nimport { RESULT_PDF } from \"./pdf.js\"\nimport {\n DEFAULT_PRACTITIONER,\n type EventRecord,\n FullscriptState,\n type LabOrderRecord,\n type LabOrderState,\n type Practitioner,\n type Settings,\n stateRank,\n} from \"./state.js\"\n\nexport type { FetchAPI } from \"@crvouga/mockingbird-core\"\nexport type { SqliteClient } from \"@crvouga/mockingbird-sqlite\"\nexport type { OperationId, SupportedOperationId } from \"./generated/openapi.js\"\nexport { document, operationIds, supportedOperationIds } from \"./generated/openapi.js\"\nexport { RESULT_PDF } from \"./pdf.js\"\nexport type {\n Clinic,\n EventRecord,\n LabOrderRecord,\n LabOrderState,\n Practitioner,\n Settings,\n} from \"./state.js\"\nexport {\n DEFAULT_CLINIC,\n DEFAULT_PRACTITIONER,\n isLabOrderState,\n LAB_ORDER_STATES,\n} from \"./state.js\"\n\nexport const FULLSCRIPT_NAMESPACE = \"fullscript\"\nconst SCOPE = \"clinic:read labs:read labs:write patients:read\"\nconst TOKEN_PREFIX = \"fsat_\"\n\n/** Fullscript API errors: `{errors: [{code, message}]}`. */\nexport const apiErrors = (status: number, code: string, message: string) =>\n jsonRes(status, { errors: [{ code, message }] })\n\n/** Doorkeeper OAuth errors: `{error, error_description}`. */\nexport const oauthError = (status: number, error: string, description: string) =>\n jsonRes(status, { error, error_description: description })\n\nconst INVALID_GRANT =\n \"The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.\"\nconst INVALID_CLIENT =\n \"Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.\"\n\nconst base64url = (value: string) =>\n toBase64(new TextEncoder().encode(value))\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\")\nconst fromBase64url = (value: string) => {\n try {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(\n fromBase64(value.replace(/-/g, \"+\").replace(/_/g, \"/\")),\n )\n } catch {\n return undefined\n }\n}\n\ntype TokenClaims = {\n clientId: string\n practitionerId: string\n clinicId: string\n type: Practitioner[\"type\"]\n}\n\nconst sign = (payload: string, issuedAt: number) =>\n opaqueToken(`fullscript:${payload}:${issuedAt}`, 32)\n\n/** Access tokens are self-describing and signed, so any instance can verify them. */\nexport const issueAccessToken = (claims: TokenClaims, issuedAtSeconds: number) => {\n const payload = base64url(\n JSON.stringify([claims.clientId, claims.practitionerId, claims.clinicId, claims.type]),\n )\n return `${TOKEN_PREFIX}${payload}.${issuedAtSeconds}.${sign(payload, issuedAtSeconds)}`\n}\n\nconst readAccessToken = (token: string): (TokenClaims & { issuedAt: number }) | undefined => {\n if (!token.startsWith(TOKEN_PREFIX)) return undefined\n const [payload, issued, signature] = token.slice(TOKEN_PREFIX.length).split(\".\")\n const issuedAt = Number(issued)\n if (!payload || !Number.isInteger(issuedAt) || signature !== sign(payload, issuedAt))\n return undefined\n const decoded = fromBase64url(payload)\n try {\n const [clientId, practitionerId, clinicId, type] = JSON.parse(decoded ?? \"\") as string[]\n if (!clientId || !practitionerId || !clinicId) return undefined\n return {\n clientId,\n practitionerId,\n clinicId,\n type: type === \"Staff\" ? \"Staff\" : \"Practitioner\",\n issuedAt,\n }\n } catch {\n return undefined\n }\n}\n\n/** The OAuth client an access token was issued to (how credentials map to namespaces). */\nexport const tokenCredential = (request: Request): string | undefined => {\n const token = bearerToken(request)\n return token ? (readAccessToken(token)?.clientId ?? token) : undefined\n}\n\n/** A lab order to start a namespace with, walked forward to `state` (events included). */\nexport type SeedOrder = {\n id: string\n patientId: string\n state: LabOrderState\n clinicId?: string\n treatmentPlanId?: string | null\n name?: string\n collectionMethod?: string\n tests?: string[]\n}\n\nexport type FullscriptAPIOptions = APIOptions & {\n settings?: Partial<Settings>\n orders?: readonly SeedOrder[]\n /** The public namespace, so result PDF URLs carry a `/__admin/ns/<name>` prefix. */\n adminPrefix?: string\n publicNamespace?: string\n /** Called for every event; the runtime signs and delivers it. */\n onEvent?: (event: EventRecord) => void\n}\n\n/** An event as the events API returns it. */\nexport const publicEvent = (event: EventRecord) => ({\n id: event.id,\n type: event.type,\n clinic_id: event.clinic_id,\n created_at: event.created_at,\n data: event.data,\n})\n\n/** The webhook body Fullscript posts for an event: `{event_payload: {event}}`. */\nexport const envelope = (event: EventRecord) => ({ event_payload: { event: publicEvent(event) } })\n\nconst page = (context: OperationContext) => {\n const q = context.query as Record<string, unknown>\n const block = (q.page ?? {}) as Record<string, unknown>\n const number = coerce.integer(block.number ?? \"1\")\n const size = coerce.integer(block.size ?? \"20\")\n return {\n number: number.ok && number.value > 0 ? number.value : 1,\n size: size.ok && size.value > 0 ? Math.min(size.value, 100) : 20,\n }\n}\n\nconst meta = (current: number, size: number, total: number) => {\n const totalPages = Math.max(1, Math.ceil(total / size))\n return {\n current_page: current,\n next_page: current < totalPages ? current + 1 : null,\n prev_page: current > 1 ? current - 1 : null,\n total_pages: totalPages,\n total_count: total,\n }\n}\n\n/**\n * Stateful mock of the Fullscript lab-ordering API. Practitioners connect through OAuth;\n * lab orders move forward only through admin transitions, each emitting a `lab_order.updated`\n * event (and `order.placed` on purchase) readable through the events API and delivered as a\n * signed webhook. Results appear with the results-bearing states, as expiring PDF URLs.\n */\nexport class FullscriptAPI implements FetchAPI {\n readonly app: Hono\n readonly sqlite: SqliteClient\n readonly state: FullscriptState\n private readonly service: Service\n private readonly now: () => number\n private readonly prefix: string\n private readonly onEvent: ((event: EventRecord) => void) | undefined\n\n constructor(options: FullscriptAPIOptions = {}) {\n const sqlite = bootSqlite(options.sqlite)\n const namespace = options.namespace ?? FULLSCRIPT_NAMESPACE\n this.now = options.now ?? (() => Date.now())\n this.onEvent = options.onEvent\n this.prefix =\n options.publicNamespace && options.publicNamespace !== \"default\"\n ? `${options.adminPrefix ?? \"/__admin\"}/ns/${encodeURIComponent(options.publicNamespace)}`\n : \"\"\n this.state = new FullscriptState(sqlite, namespace, options.settings ?? {})\n const handlers = defineOperations<SupportedOperationId>({\n OAuthToken: (context) => this.token(context),\n OAuthRevoke: (context) => this.revoke(context),\n GetClinic: (context) => {\n const claims = this.claims(context)\n const clinic = this.state.clinics.get(claims.clinicId)\n if (!clinic) return apiErrors(404, \"not_found\", \"Clinic not found\")\n return jsonRes(200, { clinic })\n },\n CreateSessionGrant: (context) => {\n const claims = this.claims(context)\n const expires = this.now() + 5 * 60_000\n return jsonRes(201, {\n secret_token: `sg_${opaqueToken(`${claims.practitionerId}:${this.now()}`, 40)}`,\n expires_at: new Date(expires).toISOString(),\n })\n },\n ListLabOrders: (context) => {\n const claims = this.claims(context)\n const patient =\n typeof context.query.patient_id === \"string\" ? context.query.patient_id : undefined\n const rows = this.state.orders\n .list({\n order: \"oldest\",\n where: (o) => o.clinicId === claims.clinicId && (!patient || o.patientId === patient),\n })\n .map((r) => r.value)\n const p = page(context)\n return jsonRes(200, {\n orders: rows\n .slice((p.number - 1) * p.size, p.number * p.size)\n .map((o) => this.summary(o)),\n meta: meta(p.number, p.size, rows.length),\n })\n },\n GetLabOrder: (context) => {\n const claims = this.claims(context)\n const order = this.state.orders.get(context.params.orderId ?? \"\")\n if (!order || order.clinicId !== claims.clinicId)\n return apiErrors(404, \"not_found\", \"Lab order not found\")\n return annotateResponse(jsonRes(200, { order: this.detail(order, context) }), {\n ids: { orderId: order.id },\n })\n },\n ListLabOrderEvents: (context) => {\n const claims = this.claims(context)\n const ascending = context.query.order_by === \"ASC\"\n const rows = this.state.events\n .list({\n order: ascending ? \"oldest\" : \"newest\",\n where: (e) => e.clinic_id === claims.clinicId && e.type === \"lab_order.updated\",\n })\n .map((r) => r.value)\n const p = page(context)\n const drift = faultEffect(context.request, \"events_schema_drift\") !== undefined\n return jsonRes(200, {\n events: rows.slice((p.number - 1) * p.size, p.number * p.size).map((e) => ({\n id: e.id,\n type: drift ? \"lab_order.changed\" : e.type,\n clinic_id: e.clinic_id,\n created_at: e.created_at,\n })),\n meta: meta(p.number, p.size, rows.length),\n })\n },\n GetEvent: (context) => {\n const claims = this.claims(context)\n const event = this.state.events.get(context.params.eventId ?? \"\")\n if (!event || event.clinic_id !== claims.clinicId)\n return apiErrors(404, \"not_found\", \"Event not found\")\n return jsonRes(200, { event: this.publicEvent(event) })\n },\n Authorize: (context) => this.authorize(context),\n GetResultPdf: (context) => this.pdf(context),\n })\n this.service = createService({\n document,\n handlers,\n sqlite,\n namespace,\n now: this.now,\n notFound: () => apiErrors(404, \"not_found\", \"Not Found\"),\n onError: (error) => {\n if (error instanceof HttpError) return error.toResponse()\n throw error\n },\n before: (context) => {\n const id = context.operation.operationId\n if (\n id === \"OAuthToken\" ||\n id === \"OAuthRevoke\" ||\n id === \"Authorize\" ||\n id === \"GetResultPdf\"\n ) {\n return undefined\n }\n const token = bearerToken(context.request)\n if (!token)\n return apiErrors(401, \"unauthorized\", \"You need to sign in or authenticate first\")\n if (faultEffect(context.request, \"token_expired\") !== undefined) {\n return apiErrors(401, \"token_expired\", \"The access token expired\")\n }\n const claims = readAccessToken(token)\n if (!claims || this.state.revoked.has(token)) {\n return apiErrors(401, \"invalid_token\", \"The access token is invalid\")\n }\n if (this.now() / 1000 >= claims.issuedAt + this.state.current().accessTokenTtlSeconds) {\n return apiErrors(401, \"token_expired\", \"The access token expired\")\n }\n return undefined\n },\n })\n this.app = this.service.app\n this.sqlite = this.service.sqlite\n for (const seed of options.orders ?? []) this.seedOrder(seed)\n }\n\n fetch(request: Request): Promise<Response> {\n return this.service.fetch(request)\n }\n\n async reset(): Promise<void> {\n await this.service.reset()\n this.state.ensureSeeded()\n }\n\n private iso(): string {\n return new Date(this.now()).toISOString()\n }\n\n private claims(context: OperationContext): TokenClaims {\n return readAccessToken(bearerToken(context.request) ?? \"\") as TokenClaims\n }\n\n private clientOk(clientId: unknown, secret: unknown): boolean {\n const clients = this.state.current().clients\n if (typeof clientId !== \"string\" || typeof secret !== \"string\" || !clientId || !secret)\n return false\n return (\n clients.length === 0 ||\n clients.some((c) => c.clientId === clientId && c.clientSecret === secret)\n )\n }\n\n private body(context: OperationContext): Record<string, unknown> {\n const issues = bodyIssues(context)\n if (issues.length > 0) {\n throw new HttpError(400, {\n error: \"invalid_request\",\n error_description: `The request is missing a required parameter or is otherwise malformed: ${issues.map((i) => `${i.path || \"body\"} ${i.message}`).join(\"; \")}`,\n })\n }\n return context.body.kind === \"json\" ? (context.body.value as Record<string, unknown>) : {}\n }\n\n /** Mint an authorization code for a practitioner (what the consent page does). */\n issueCode(practitionerId: string, clientId: string, redirectUri: string | null): string {\n const code = `code_${opaqueToken(`${practitionerId}:${this.state.next(\"code\")}`, 32)}`\n this.state.codes.insert(code, {\n code,\n practitionerId,\n clientId,\n redirectUri,\n expiresAtMs: this.now() + this.state.current().codeTtlSeconds * 1000,\n used: false,\n })\n return code\n }\n\n private tokenPair(practitioner: Practitioner, clientId: string) {\n const refresh = `fsrt_${opaqueToken(`${practitioner.id}:${this.state.next(\"refresh\")}`, 40)}`\n this.state.refresh.insert(refresh, {\n token: refresh,\n practitionerId: practitioner.id,\n clientId,\n revoked: false,\n })\n const issuedAt = Math.floor(this.now() / 1000)\n return jsonRes(200, {\n oauth: {\n access_token: issueAccessToken(\n {\n clientId,\n practitionerId: practitioner.id,\n clinicId: practitioner.clinicId,\n type: practitioner.type,\n },\n issuedAt,\n ),\n token_type: \"Bearer\",\n expires_in: this.state.current().accessTokenTtlSeconds,\n refresh_token: refresh,\n scope: SCOPE,\n created_at: new Date(issuedAt * 1000).toISOString(),\n resource_owner: {\n id: practitioner.id,\n type: practitioner.type,\n clinic_id: practitioner.clinicId,\n },\n },\n })\n }\n\n private token(context: OperationContext): Response {\n const body = this.body(context)\n const clientId = String(body.client_id)\n if (!this.clientOk(body.client_id, body.client_secret))\n return oauthError(401, \"invalid_client\", INVALID_CLIENT)\n if (body.grant_type === \"authorization_code\") {\n if (typeof body.code !== \"string\" || !body.code) {\n return oauthError(400, \"invalid_request\", \"Missing required parameter: code.\")\n }\n const code = this.state.codes.get(body.code)\n if (\n !code ||\n code.used ||\n code.clientId !== clientId ||\n this.now() > code.expiresAtMs ||\n (code.redirectUri !== null && body.redirect_uri !== code.redirectUri)\n ) {\n return oauthError(400, \"invalid_grant\", INVALID_GRANT)\n }\n this.state.codes.update(code.code, { ...code, used: true })\n const practitioner = this.state.practitioners.get(code.practitionerId) ?? DEFAULT_PRACTITIONER\n return this.tokenPair(practitioner, clientId)\n }\n if (typeof body.refresh_token !== \"string\" || !body.refresh_token) {\n return oauthError(400, \"invalid_request\", \"Missing required parameter: refresh_token.\")\n }\n if (faultEffect(context.request, \"invalid_grant\") !== undefined) {\n return oauthError(400, \"invalid_grant\", INVALID_GRANT)\n }\n const refresh = this.state.refresh.get(body.refresh_token)\n if (!refresh || refresh.revoked || refresh.clientId !== clientId) {\n return oauthError(400, \"invalid_grant\", INVALID_GRANT)\n }\n // Refresh tokens rotate: the presented one is spent.\n this.state.refresh.update(refresh.token, { ...refresh, revoked: true })\n const practitioner =\n this.state.practitioners.get(refresh.practitionerId) ?? DEFAULT_PRACTITIONER\n return this.tokenPair(practitioner, clientId)\n }\n\n private revoke(context: OperationContext): Response {\n const body = this.body(context)\n if (!this.clientOk(body.client_id, body.client_secret))\n return oauthError(401, \"invalid_client\", INVALID_CLIENT)\n const token = String(body.token)\n const refresh = this.state.refresh.get(token)\n if (refresh) this.state.refresh.update(token, { ...refresh, revoked: true })\n else if (readAccessToken(token)) this.state.revoked.insert(token, { token })\n return jsonRes(200, {})\n }\n\n private authorize(context: OperationContext): Response {\n const url = context.url\n const redirect = url.searchParams.get(\"redirect_uri\")\n const clientId = url.searchParams.get(\"client_id\")\n if (!redirect || !clientId || url.searchParams.get(\"response_type\") !== \"code\") {\n return oauthError(\n 400,\n \"invalid_request\",\n \"client_id, redirect_uri and response_type=code are required.\",\n )\n }\n const practitionerId = url.searchParams.get(\"practitioner_id\") ?? DEFAULT_PRACTITIONER.id\n if (!this.state.practitioners.get(practitionerId)) {\n return oauthError(400, \"invalid_request\", `Unknown practitioner ${practitionerId}.`)\n }\n const code = this.issueCode(practitionerId, clientId, redirect)\n const location = new URL(redirect)\n location.searchParams.set(\"code\", code)\n const state = url.searchParams.get(\"state\")\n if (state !== null) location.searchParams.set(\"state\", state)\n return new Response(null, { status: 302, headers: { location: location.toString() } })\n }\n\n private summary(order: LabOrderRecord) {\n return {\n id: order.id,\n state: order.state,\n treatment_plan_id: order.treatmentPlanId,\n patient_id: order.patientId,\n name: order.name,\n created_at: order.created_at,\n updated_at: order.updated_at,\n }\n }\n\n /** A signed, expiring URL for a result artifact, on the mock itself (or `resultsBaseUrl`). */\n private pdfUrl(artifactId: string, context: OperationContext): string {\n const base = this.state.current().resultsBaseUrl ?? `${context.url.origin}${this.prefix}`\n const expires = this.now() + this.state.current().pdfUrlTtlSeconds * 1000\n return `${base.replace(/\\/$/, \"\")}/results/${artifactId}?expires=${expires}&signature=${opaqueToken(`${artifactId}:${expires}`, 24)}`\n }\n\n private detail(order: LabOrderRecord, context: OperationContext) {\n return {\n ...this.summary(order),\n collection_method: order.collectionMethod,\n tests: order.tests,\n results: order.results.map((r) => ({\n id: r.id,\n name: r.name,\n state: r.state,\n pdf_url: this.pdfUrl(r.artifactId, context),\n })),\n latest_aggregated_result: order.aggregated\n ? {\n id: order.aggregated.id,\n artifact_id: order.aggregated.artifactId,\n pdf_url: this.pdfUrl(order.aggregated.artifactId, context),\n status: order.aggregated.status,\n }\n : null,\n }\n }\n\n private pdf(context: OperationContext): Response {\n const artifactId = context.params.artifactId ?? \"\"\n const expires = Number(context.url.searchParams.get(\"expires\"))\n const signature = context.url.searchParams.get(\"signature\")\n if (signature !== opaqueToken(`${artifactId}:${expires}`, 24)) {\n return new Response(\"Forbidden\", { status: 403, headers: { \"content-type\": \"text/plain\" } })\n }\n if (this.now() > expires)\n return new Response(\"Expired\", { status: 403, headers: { \"content-type\": \"text/plain\" } })\n const known = this.state.orders\n .list()\n .some(\n ({ value: o }) =>\n o.aggregated?.artifactId === artifactId ||\n o.results.some((r) => r.artifactId === artifactId),\n )\n if (!known) return new Response(null, { status: 404 })\n return new Response(new Blob([RESULT_PDF as BlobPart]), {\n status: 200,\n headers: {\n \"content-type\": \"application/pdf\",\n \"content-length\": String(RESULT_PDF.byteLength),\n },\n })\n }\n\n private publicEvent(event: EventRecord) {\n return {\n id: event.id,\n type: event.type,\n clinic_id: event.clinic_id,\n created_at: event.created_at,\n data: event.data,\n }\n }\n\n private emit(\n type: EventRecord[\"type\"],\n order: LabOrderRecord,\n data: Record<string, unknown>,\n ): EventRecord {\n const seq = this.state.next(\"event\")\n const event: EventRecord = {\n id: `evt_${seq}`,\n type,\n clinic_id: order.clinicId,\n created_at: this.iso(),\n data,\n seq,\n }\n this.state.events.insert(event.id, event)\n this.onEvent?.(event)\n return event\n }\n\n /** Create a lab order in `not_purchased` (a practitioner recommended labs in a treatment plan). */\n createOrder(input: Omit<SeedOrder, \"state\" | \"id\"> & { id?: string }): LabOrderRecord {\n const id = input.id ?? `lo_${this.state.next(\"order\")}`\n const now = this.iso()\n const order: LabOrderRecord = {\n id,\n clinicId: input.clinicId ?? DEFAULT_PRACTITIONER.clinicId,\n patientId: input.patientId,\n treatmentPlanId: input.treatmentPlanId === undefined ? `tp_${id}` : input.treatmentPlanId,\n name: input.name ?? \"Comprehensive Wellness Panel\",\n collectionMethod: input.collectionMethod ?? \"at_home_phlebotomy\",\n state: \"not_purchased\",\n tests: (input.tests ?? [\"Lipid Panel\", \"Comprehensive Metabolic Panel\"]).map((name, i) => ({\n id: `lt_${id}_${i + 1}`,\n name,\n lab_type: \"labs\",\n })),\n results: [],\n aggregated: null,\n created_at: now,\n updated_at: now,\n }\n this.state.orders.insert(id, order)\n return order\n }\n\n /**\n * Move an order forward (never back) and emit its events: `order.placed` on purchase and\n * `lab_order.updated` for every move. Results-bearing states attach result artifacts.\n */\n transition(orderId: string, to: LabOrderState): LabOrderRecord {\n const order = this.state.orders.get(orderId)\n if (!order)\n throw new HttpError(404, {\n error: { type: \"mockingbird_admin\", message: `no lab order ${orderId}` },\n })\n if (stateRank(to) <= stateRank(order.state)) {\n throw new HttpError(409, {\n error: {\n type: \"mockingbird_admin\",\n message: `lab orders only move forward: ${order.state} \u2192 ${to} is not allowed`,\n },\n })\n }\n const artifact = () => `art_${opaqueToken(`${order.id}:${this.state.next(\"artifact\")}`, 16)}`\n const next: LabOrderRecord = { ...order, state: to, updated_at: this.iso() }\n const rank = stateRank(to)\n if (rank >= stateRank(\"partial_results\")) {\n const wanted = rank >= stateRank(\"results_ready\") ? next.tests.length : 1\n const results = [...next.results]\n for (const test of next.tests.slice(results.length, wanted)) {\n results.push({\n id: `res_${test.id}`,\n name: test.name,\n state: \"final\",\n artifactId: artifact(),\n })\n }\n next.results = results\n }\n if (rank >= stateRank(\"results_ready\") && (!next.aggregated || to === \"results_amended\")) {\n next.aggregated = {\n id: `agg_${order.id}${to === \"results_amended\" ? \"_amended\" : \"\"}`,\n artifactId: artifact(),\n status: to === \"results_amended\" ? \"amended\" : \"final\",\n }\n }\n this.state.orders.update(order.id, next)\n if (to === \"purchased\" || (order.state === \"not_purchased\" && rank > stateRank(\"purchased\"))) {\n this.emit(\"order.placed\", next, {\n id: next.id,\n treatment_plan_ids: next.treatmentPlanId ? [next.treatmentPlanId] : [],\n patient_id: next.patientId,\n line_items: [{ type: \"labs\", lab_type: \"labs\", name: next.name }],\n })\n }\n this.emit(\"lab_order.updated\", next, {\n lab_order: {\n id: next.id,\n state: next.state,\n treatment_plan_id: next.treatmentPlanId,\n patient_id: next.patientId,\n },\n })\n return next\n }\n\n seedOrder(seed: SeedOrder): LabOrderRecord {\n const order = this.state.orders.get(seed.id) ?? this.createOrder(seed)\n return seed.state === order.state ? order : this.transition(order.id, seed.state)\n }\n\n labOrders(): LabOrderRecord[] {\n return this.state.orders.list({ order: \"oldest\" }).map((r) => r.value)\n }\n\n eventsList(): EventRecord[] {\n return this.state.events.list({ order: \"oldest\" }).map((r) => r.value)\n }\n}\n\nexport type { FullscriptRuntime, FullscriptRuntimeOptions } from \"./runtime.js\"\nexport { createRuntime, FULLSCRIPT_PRESETS, SIGNATURE_HEADER } from \"./runtime.js\"\n"],
5
+ "mappings": "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",
6
+ "names": ["createRuntime", "practitioner"]
7
+ }
@@ -0,0 +1,84 @@
1
+ import {
2
+ createRuntime
3
+ } from "./chunk-CJAYCSOW.js";
4
+
5
+ // src/server.ts
6
+ import { listen } from "@crvouga/mockingbird-runtime/adapter-node";
7
+ var DEFAULT_PORT = 8819;
8
+ var createServer = async (options = {}) => {
9
+ const { port, host, ...rest } = options;
10
+ const runtime = createRuntime(rest);
11
+ const listening = await listen(runtime, {
12
+ port: port ?? 0,
13
+ ...host !== void 0 ? { host } : {}
14
+ });
15
+ return { ...listening, runtime };
16
+ };
17
+ var text = (value) => typeof value === "string" ? value : void 0;
18
+ var serveTarget = {
19
+ name: "fullscript",
20
+ defaultPort: DEFAULT_PORT,
21
+ options: {
22
+ "webhook-url": {
23
+ type: "string",
24
+ value: "<url>",
25
+ description: "Deliver events here (e.g. http://127.0.0.1:4000/v1/fullscript/webhooks)"
26
+ },
27
+ "webhook-secret": {
28
+ type: "string",
29
+ value: "<secret>",
30
+ description: "Signs Fullscript-Signature (the app's FULLSCRIPT_WEBHOOK_SECRET)"
31
+ },
32
+ "webhook-challenge": {
33
+ type: "string",
34
+ value: "<key>",
35
+ description: "Require the receiver to echo {challenge} (FULLSCRIPT_WEBHOOK_CHALLENGE_KEY)"
36
+ },
37
+ client: {
38
+ type: "string",
39
+ value: "<client_id:client_secret>",
40
+ description: "Accept only this OAuth client (FULLSCRIPT_CLIENT_ID:FULLSCRIPT_CLIENT_SECRET); default: any"
41
+ },
42
+ "results-base-url": {
43
+ type: "string",
44
+ value: "<https url>",
45
+ description: "Origin for result PDF URLs (the app downloads only https from allowlisted hosts)"
46
+ }
47
+ },
48
+ create: (values, common) => {
49
+ const url = text(values["webhook-url"]);
50
+ const secret = text(values["webhook-secret"]);
51
+ const challenge = text(values["webhook-challenge"]);
52
+ const client = text(values.client);
53
+ const results = text(values["results-base-url"]);
54
+ const colon = client?.indexOf(":") ?? -1;
55
+ if (client && colon < 1) throw new Error('--client must look like "client_id:client_secret"');
56
+ return createRuntime({
57
+ ...url ? { webhooks: { url, ...secret ? { secret } : {}, ...challenge ? { challenge } : {} } } : {},
58
+ settings: {
59
+ ...client ? {
60
+ clients: [
61
+ { clientId: client.slice(0, colon), clientSecret: client.slice(colon + 1) }
62
+ ]
63
+ } : {},
64
+ ...results ? { resultsBaseUrl: results } : {}
65
+ },
66
+ ...common.adminPrefix !== void 0 ? { adminPrefix: common.adminPrefix } : {},
67
+ ...common.adminKey !== void 0 ? { adminKey: common.adminKey } : {},
68
+ ...common.adminControls !== void 0 ? { adminControls: common.adminControls } : {},
69
+ ...common.seed !== void 0 ? { seed: common.seed } : {},
70
+ ...common.onLog ? { onLog: common.onLog } : {}
71
+ });
72
+ },
73
+ banner: () => [
74
+ "oauth: GET /oauth/authorize (auto-consents as prac_mock_1), POST /api/oauth/token, POST /api/oauth/revoke",
75
+ "namespaces: x-mockingbird-namespace, or a /__admin/ns/<name>/ suffix on FULLSCRIPT_API_URL"
76
+ ]
77
+ };
78
+
79
+ export {
80
+ DEFAULT_PORT,
81
+ createServer,
82
+ serveTarget
83
+ };
84
+ //# sourceMappingURL=chunk-IVB27G3V.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/server.ts"],
4
+ "sourcesContent": ["/// <reference types=\"node\" />\nimport { type Listening, listen, type ServeTarget } from \"@crvouga/mockingbird-adapter-node\"\nimport { createRuntime, type FullscriptRuntime, type FullscriptRuntimeOptions } from \"./runtime.js\"\n\n/** Port `mockingbird-fullscript serve` listens on when none is given. */\nexport const DEFAULT_PORT = 8819\n\nexport type FullscriptServerOptions = FullscriptRuntimeOptions & {\n /** Default `0`: the OS picks a free port. */\n port?: number\n /** Default `127.0.0.1`. */\n host?: string\n}\n\nexport type FullscriptServer = Listening & { runtime: FullscriptRuntime }\n\n/** Serve the Fullscript mock over `node:http`. */\nexport const createServer = async (\n options: FullscriptServerOptions = {},\n): Promise<FullscriptServer> => {\n const { port, host, ...rest } = options\n const runtime = createRuntime(rest)\n const listening = await listen(runtime, {\n port: port ?? 0,\n ...(host !== undefined ? { host } : {}),\n })\n return { ...listening, runtime }\n}\n\nconst text = (value: string | boolean | undefined) =>\n typeof value === \"string\" ? value : undefined\n\n/** How `serve` (and `serve --config`) builds the Fullscript mock from flags. */\nexport const serveTarget: ServeTarget = {\n name: \"fullscript\",\n defaultPort: DEFAULT_PORT,\n options: {\n \"webhook-url\": {\n type: \"string\",\n value: \"<url>\",\n description: \"Deliver events here (e.g. http://127.0.0.1:4000/v1/fullscript/webhooks)\",\n },\n \"webhook-secret\": {\n type: \"string\",\n value: \"<secret>\",\n description: \"Signs Fullscript-Signature (the app's FULLSCRIPT_WEBHOOK_SECRET)\",\n },\n \"webhook-challenge\": {\n type: \"string\",\n value: \"<key>\",\n description: \"Require the receiver to echo {challenge} (FULLSCRIPT_WEBHOOK_CHALLENGE_KEY)\",\n },\n client: {\n type: \"string\",\n value: \"<client_id:client_secret>\",\n description:\n \"Accept only this OAuth client (FULLSCRIPT_CLIENT_ID:FULLSCRIPT_CLIENT_SECRET); default: any\",\n },\n \"results-base-url\": {\n type: \"string\",\n value: \"<https url>\",\n description:\n \"Origin for result PDF URLs (the app downloads only https from allowlisted hosts)\",\n },\n },\n create: (values, common) => {\n const url = text(values[\"webhook-url\"])\n const secret = text(values[\"webhook-secret\"])\n const challenge = text(values[\"webhook-challenge\"])\n const client = text(values.client)\n const results = text(values[\"results-base-url\"])\n const colon = client?.indexOf(\":\") ?? -1\n if (client && colon < 1) throw new Error('--client must look like \"client_id:client_secret\"')\n return createRuntime({\n ...(url\n ? { webhooks: { url, ...(secret ? { secret } : {}), ...(challenge ? { challenge } : {}) } }\n : {}),\n settings: {\n ...(client\n ? {\n clients: [\n { clientId: client.slice(0, colon), clientSecret: client.slice(colon + 1) },\n ],\n }\n : {}),\n ...(results ? { resultsBaseUrl: results } : {}),\n },\n ...(common.adminPrefix !== undefined ? { adminPrefix: common.adminPrefix } : {}),\n ...(common.adminKey !== undefined ? { adminKey: common.adminKey } : {}),\n ...(common.adminControls !== undefined ? { adminControls: common.adminControls } : {}),\n ...(common.seed !== undefined ? { seed: common.seed } : {}),\n ...(common.onLog ? { onLog: common.onLog } : {}),\n })\n },\n banner: () => [\n \"oauth: GET /oauth/authorize (auto-consents as prac_mock_1), POST /api/oauth/token, POST /api/oauth/revoke\",\n \"namespaces: x-mockingbird-namespace, or a /__admin/ns/<name>/ suffix on FULLSCRIPT_API_URL\",\n ],\n}\n"],
5
+ "mappings": ";;;;;AACA,SAAyB,cAAgC;AAIlD,IAAM,eAAe;AAYrB,IAAM,eAAe,OAC1B,UAAmC,CAAC,MACN;AAC9B,QAAM,EAAE,MAAM,MAAM,GAAG,KAAK,IAAI;AAChC,QAAM,UAAU,cAAc,IAAI;AAClC,QAAM,YAAY,MAAM,OAAO,SAAS;AAAA,IACtC,MAAM,QAAQ;AAAA,IACd,GAAI,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,EACvC,CAAC;AACD,SAAO,EAAE,GAAG,WAAW,QAAQ;AACjC;AAEA,IAAM,OAAO,CAAC,UACZ,OAAO,UAAU,WAAW,QAAQ;AAG/B,IAAM,cAA2B;AAAA,EACtC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,SAAS;AAAA,IACP,eAAe;AAAA,MACb,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,IACA,kBAAkB;AAAA,MAChB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,IACA,qBAAqB;AAAA,MACnB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IACf;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aACE;AAAA,IACJ;AAAA,IACA,oBAAoB;AAAA,MAClB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aACE;AAAA,IACJ;AAAA,EACF;AAAA,EACA,QAAQ,CAAC,QAAQ,WAAW;AAC1B,UAAM,MAAM,KAAK,OAAO,aAAa,CAAC;AACtC,UAAM,SAAS,KAAK,OAAO,gBAAgB,CAAC;AAC5C,UAAM,YAAY,KAAK,OAAO,mBAAmB,CAAC;AAClD,UAAM,SAAS,KAAK,OAAO,MAAM;AACjC,UAAM,UAAU,KAAK,OAAO,kBAAkB,CAAC;AAC/C,UAAM,QAAQ,QAAQ,QAAQ,GAAG,KAAK;AACtC,QAAI,UAAU,QAAQ,EAAG,OAAM,IAAI,MAAM,mDAAmD;AAC5F,WAAO,cAAc;AAAA,MACnB,GAAI,MACA,EAAE,UAAU,EAAE,KAAK,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC,GAAI,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC,EAAG,EAAE,IACxF,CAAC;AAAA,MACL,UAAU;AAAA,QACR,GAAI,SACA;AAAA,UACE,SAAS;AAAA,YACP,EAAE,UAAU,OAAO,MAAM,GAAG,KAAK,GAAG,cAAc,OAAO,MAAM,QAAQ,CAAC,EAAE;AAAA,UAC5E;AAAA,QACF,IACA,CAAC;AAAA,QACL,GAAI,UAAU,EAAE,gBAAgB,QAAQ,IAAI,CAAC;AAAA,MAC/C;AAAA,MACA,GAAI,OAAO,gBAAgB,SAAY,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;AAAA,MAC9E,GAAI,OAAO,aAAa,SAAY,EAAE,UAAU,OAAO,SAAS,IAAI,CAAC;AAAA,MACrE,GAAI,OAAO,kBAAkB,SAAY,EAAE,eAAe,OAAO,cAAc,IAAI,CAAC;AAAA,MACpF,GAAI,OAAO,SAAS,SAAY,EAAE,MAAM,OAAO,KAAK,IAAI,CAAC;AAAA,MACzD,GAAI,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;AAAA,IAChD,CAAC;AAAA,EACH;AAAA,EACA,QAAQ,MAAM;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
package/dist/cli.js CHANGED
@@ -1,13 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- runCli,
4
- serveCommand,
5
3
  serveTarget
6
- } from "./chunk-SLSXYUF2.js";
7
- import "./chunk-6VUU3NXU.js";
8
- import "./chunk-RJZUEZVH.js";
4
+ } from "./chunk-IVB27G3V.js";
5
+ import "./chunk-CJAYCSOW.js";
9
6
 
10
7
  // src/cli.ts
8
+ import { runCli, serveCommand } from "@crvouga/mockingbird-runtime/adapter-node";
11
9
  var code = await runCli(
12
10
  {
13
11
  bin: "mockingbird-fullscript",
package/dist/cli.js.map CHANGED
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/cli.ts"],
4
4
  "sourcesContent": ["#!/usr/bin/env node\n/// <reference types=\"node\" />\nimport { runCli, serveCommand } from \"@crvouga/mockingbird-adapter-node\"\nimport { serveTarget } from \"./server.js\"\n\nconst code = await runCli(\n {\n bin: \"mockingbird-fullscript\",\n description: \"stateful Fullscript lab-ordering API mock\",\n commands: { serve: serveCommand(serveTarget) },\n },\n process.argv.slice(2),\n)\nif (code !== 0) process.exitCode = code\n"],
5
- "mappings": ";;;;;;;;;;AAKA,IAAM,OAAO,MAAM;AAAA,EACjB;AAAA,IACE,KAAK;AAAA,IACL,aAAa;AAAA,IACb,UAAU,EAAE,OAAO,aAAa,WAAW,EAAE;AAAA,EAC/C;AAAA,EACA,QAAQ,KAAK,MAAM,CAAC;AACtB;AACA,IAAI,SAAS,EAAG,SAAQ,WAAW;",
5
+ "mappings": ";;;;;;;AAEA,SAAS,QAAQ,oBAAoB;AAGrC,IAAM,OAAO,MAAM;AAAA,EACjB;AAAA,IACE,KAAK;AAAA,IACL,aAAa;AAAA,IACb,UAAU,EAAE,OAAO,aAAa,WAAW,EAAE;AAAA,EAC/C;AAAA,EACA,QAAQ,KAAK,MAAM,CAAC;AACtB;AACA,IAAI,SAAS,EAAG,SAAQ,WAAW;",
6
6
  "names": []
7
7
  }