@crvouga/mockingbird-service-rxvortex 0.2.0 → 1.1.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.
- package/CHANGELOG.md +13 -1
- package/README.md +16 -6
- package/dist/{chunk-ZAM35JQO.js → chunk-SNW7NYY6.js} +37 -3
- package/dist/chunk-SNW7NYY6.js.map +7 -0
- package/dist/{chunk-DNELVPK4.js → chunk-VQAJFAUO.js} +124 -18
- package/dist/{chunk-DNELVPK4.js.map → chunk-VQAJFAUO.js.map} +3 -3
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +31 -2
- package/dist/index.js +5 -1
- package/dist/server.d.ts +39 -16
- package/dist/server.js +4 -2
- package/package.json +7 -3
- package/dist/chunk-ZAM35JQO.js.map +0 -7
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -619,6 +619,17 @@ declare const CUSTOM_CREAM_ANCHOR_PRESET_ID = "e404ad76-0f82-4b04-8f25-841650e2e
|
|
|
619
619
|
* it with the real rows); the custom-cream anchor preset must always resolve.
|
|
620
620
|
*/
|
|
621
621
|
declare const DEFAULT_CATALOG: readonly CatalogItem[];
|
|
622
|
+
/**
|
|
623
|
+
* One catalog row from loose input: `catalog_id` and `medication_name` are required; the
|
|
624
|
+
* other fields default to `null`, `states` to `[]` and `status` to `"active"`.
|
|
625
|
+
*/
|
|
626
|
+
declare const parseCatalogItem: (value: unknown) => CatalogItem;
|
|
627
|
+
/**
|
|
628
|
+
* Catalog rows from a JSON value: a bare array, or the `{data: [...]}` envelope
|
|
629
|
+
* `GET /api/v1/preset-catalog-items` answers with (so a recorded response loads as-is).
|
|
630
|
+
* Throws on the first malformed row.
|
|
631
|
+
*/
|
|
632
|
+
declare const parseCatalog: (value: unknown) => CatalogItem[];
|
|
622
633
|
|
|
623
634
|
/**
|
|
624
635
|
* One order as the vendor tracks it. Patient and prescriber details are validated but never
|
|
@@ -662,6 +673,12 @@ type Settings = {
|
|
|
662
673
|
client_secret: string;
|
|
663
674
|
}[];
|
|
664
675
|
autoAdvance: AutoAdvance | null;
|
|
676
|
+
/**
|
|
677
|
+
* What a submit does with a well-formed `preset_catalog_id` the catalog does not hold:
|
|
678
|
+
* `"reject"` answers 422 as the sandbox does; `"accept"` adds it as an active row named
|
|
679
|
+
* after the request's `medication_name`. Inactive rows are refused either way.
|
|
680
|
+
*/
|
|
681
|
+
unknownPresets: "reject" | "accept";
|
|
665
682
|
};
|
|
666
683
|
declare class RxVortexState {
|
|
667
684
|
private readonly seed;
|
|
@@ -670,11 +687,14 @@ declare class RxVortexState {
|
|
|
670
687
|
readonly settings: Collection<Settings>;
|
|
671
688
|
readonly ids: IdSequence;
|
|
672
689
|
constructor(sqlite: SqliteClient, namespace: string, seed: {
|
|
673
|
-
catalog: readonly CatalogItem[];
|
|
690
|
+
catalog: readonly CatalogItem[] | undefined;
|
|
674
691
|
settings: Partial<Settings>;
|
|
675
692
|
});
|
|
676
693
|
/** Re-apply the catalog and settings after a reset. */
|
|
677
694
|
ensureSeeded(): void;
|
|
695
|
+
/** Load rows: `replace` drops every other row first, `merge` upserts by `catalog_id`. */
|
|
696
|
+
putCatalog(items: readonly CatalogItem[], mode: "replace" | "merge"): number;
|
|
697
|
+
catalogRows(): CatalogItem[];
|
|
678
698
|
current(): Settings;
|
|
679
699
|
update(patch: Partial<Settings>): Settings;
|
|
680
700
|
/** By vendor tracking id first, then by our sender order id (the recovery lookup). */
|
|
@@ -864,6 +884,10 @@ type RxVortexRuntimeOptions = {
|
|
|
864
884
|
seed?: number | string;
|
|
865
885
|
adminKey?: string;
|
|
866
886
|
onLog?: (entry: RequestLog) => void;
|
|
887
|
+
/**
|
|
888
|
+
* Rows every namespace starts with, and returns to on `POST /__admin/reset` (`serve
|
|
889
|
+
* --catalog <file>`). Default: `DEFAULT_CATALOG`.
|
|
890
|
+
*/
|
|
867
891
|
catalog?: readonly CatalogItem[];
|
|
868
892
|
settings?: Partial<Settings>;
|
|
869
893
|
/** Where status webhooks go (`POST /prescriptions/webhooks/rxvortex`), sent with the secret header. */
|
|
@@ -950,6 +974,11 @@ declare class RxVortexAPI implements FetchAPI$1 {
|
|
|
950
974
|
private iso;
|
|
951
975
|
private generateToken;
|
|
952
976
|
private createOrder;
|
|
977
|
+
/**
|
|
978
|
+
* Under `unknownPresets: "accept"`, a well-formed preset id the catalog lacks becomes an
|
|
979
|
+
* active row described by the request, so later submits and catalog reads see it.
|
|
980
|
+
*/
|
|
981
|
+
private adoptPreset;
|
|
953
982
|
private getOrder;
|
|
954
983
|
private cancelOrder;
|
|
955
984
|
/** Move an order to a vendor status, set the three fields coherently, emit the webhook. */
|
|
@@ -962,5 +991,5 @@ declare class RxVortexAPI implements FetchAPI$1 {
|
|
|
962
991
|
orders(): OrderRecord[];
|
|
963
992
|
}
|
|
964
993
|
|
|
965
|
-
export { CUSTOM_CREAM_ANCHOR_PRESET_ID, DEFAULT_CATALOG, RXVORTEX_NAMESPACE, RXVORTEX_PRESETS, RxVortexAPI, createRuntime, document, operationIds, supportedOperationIds, tokenCredential };
|
|
994
|
+
export { CUSTOM_CREAM_ANCHOR_PRESET_ID, DEFAULT_CATALOG, RXVORTEX_NAMESPACE, RXVORTEX_PRESETS, RxVortexAPI, createRuntime, document, operationIds, parseCatalog, parseCatalogItem, supportedOperationIds, tokenCredential };
|
|
966
995
|
export type { AutoAdvance, CatalogItem, FetchAPI$1 as FetchAPI, OperationId, OrderRecord, RxVortexAPIOptions, RxVortexRuntime, RxVortexRuntimeOptions, RxVortexWebhook, Settings, SqliteClient, SupportedOperationId, TransitionInput };
|
package/dist/index.js
CHANGED
|
@@ -7,9 +7,11 @@ import {
|
|
|
7
7
|
createRuntime,
|
|
8
8
|
document,
|
|
9
9
|
operationIds,
|
|
10
|
+
parseCatalog,
|
|
11
|
+
parseCatalogItem,
|
|
10
12
|
supportedOperationIds,
|
|
11
13
|
tokenCredential
|
|
12
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-VQAJFAUO.js";
|
|
13
15
|
export {
|
|
14
16
|
CUSTOM_CREAM_ANCHOR_PRESET_ID,
|
|
15
17
|
DEFAULT_CATALOG,
|
|
@@ -19,6 +21,8 @@ export {
|
|
|
19
21
|
createRuntime,
|
|
20
22
|
document,
|
|
21
23
|
operationIds,
|
|
24
|
+
parseCatalog,
|
|
25
|
+
parseCatalogItem,
|
|
22
26
|
supportedOperationIds,
|
|
23
27
|
tokenCredential
|
|
24
28
|
};
|
package/dist/server.d.ts
CHANGED
|
@@ -523,6 +523,20 @@ type Listening = {
|
|
|
523
523
|
close(): Promise<void>;
|
|
524
524
|
};
|
|
525
525
|
|
|
526
|
+
/** One preset catalog row, in the field names `GET /api/v1/preset-catalog-items` uses. */
|
|
527
|
+
type CatalogItem = {
|
|
528
|
+
catalog_id: string;
|
|
529
|
+
medication_name: string;
|
|
530
|
+
medication_strength: string | null;
|
|
531
|
+
package_size: string | null;
|
|
532
|
+
quantity: number | null;
|
|
533
|
+
quantity_units: string | null;
|
|
534
|
+
medication_form: string | null;
|
|
535
|
+
route: string | null;
|
|
536
|
+
states: string[];
|
|
537
|
+
status: "active" | "inactive";
|
|
538
|
+
};
|
|
539
|
+
|
|
526
540
|
/**
|
|
527
541
|
* The single source of time for a service.
|
|
528
542
|
*
|
|
@@ -1098,20 +1112,6 @@ interface SqliteClient {
|
|
|
1098
1112
|
transaction<T>(fn: () => T): T;
|
|
1099
1113
|
}
|
|
1100
1114
|
|
|
1101
|
-
/** One preset catalog row, in the field names `GET /api/v1/preset-catalog-items` uses. */
|
|
1102
|
-
type CatalogItem = {
|
|
1103
|
-
catalog_id: string;
|
|
1104
|
-
medication_name: string;
|
|
1105
|
-
medication_strength: string | null;
|
|
1106
|
-
package_size: string | null;
|
|
1107
|
-
quantity: number | null;
|
|
1108
|
-
quantity_units: string | null;
|
|
1109
|
-
medication_form: string | null;
|
|
1110
|
-
route: string | null;
|
|
1111
|
-
states: string[];
|
|
1112
|
-
status: "active" | "inactive";
|
|
1113
|
-
};
|
|
1114
|
-
|
|
1115
1115
|
/**
|
|
1116
1116
|
* Anything that can answer a Fetch `Request` with a `Response`.
|
|
1117
1117
|
*
|
|
@@ -1164,6 +1164,12 @@ type Settings = {
|
|
|
1164
1164
|
client_secret: string;
|
|
1165
1165
|
}[];
|
|
1166
1166
|
autoAdvance: AutoAdvance | null;
|
|
1167
|
+
/**
|
|
1168
|
+
* What a submit does with a well-formed `preset_catalog_id` the catalog does not hold:
|
|
1169
|
+
* `"reject"` answers 422 as the sandbox does; `"accept"` adds it as an active row named
|
|
1170
|
+
* after the request's `medication_name`. Inactive rows are refused either way.
|
|
1171
|
+
*/
|
|
1172
|
+
unknownPresets: "reject" | "accept";
|
|
1167
1173
|
};
|
|
1168
1174
|
declare class RxVortexState {
|
|
1169
1175
|
private readonly seed;
|
|
@@ -1172,11 +1178,14 @@ declare class RxVortexState {
|
|
|
1172
1178
|
readonly settings: Collection<Settings>;
|
|
1173
1179
|
readonly ids: IdSequence;
|
|
1174
1180
|
constructor(sqlite: SqliteClient, namespace: string, seed: {
|
|
1175
|
-
catalog: readonly CatalogItem[];
|
|
1181
|
+
catalog: readonly CatalogItem[] | undefined;
|
|
1176
1182
|
settings: Partial<Settings>;
|
|
1177
1183
|
});
|
|
1178
1184
|
/** Re-apply the catalog and settings after a reset. */
|
|
1179
1185
|
ensureSeeded(): void;
|
|
1186
|
+
/** Load rows: `replace` drops every other row first, `merge` upserts by `catalog_id`. */
|
|
1187
|
+
putCatalog(items: readonly CatalogItem[], mode: "replace" | "merge"): number;
|
|
1188
|
+
catalogRows(): CatalogItem[];
|
|
1180
1189
|
current(): Settings;
|
|
1181
1190
|
update(patch: Partial<Settings>): Settings;
|
|
1182
1191
|
/** By vendor tracking id first, then by our sender order id (the recovery lookup). */
|
|
@@ -1235,6 +1244,11 @@ declare class RxVortexAPI implements FetchAPI {
|
|
|
1235
1244
|
private iso;
|
|
1236
1245
|
private generateToken;
|
|
1237
1246
|
private createOrder;
|
|
1247
|
+
/**
|
|
1248
|
+
* Under `unknownPresets: "accept"`, a well-formed preset id the catalog lacks becomes an
|
|
1249
|
+
* active row described by the request, so later submits and catalog reads see it.
|
|
1250
|
+
*/
|
|
1251
|
+
private adoptPreset;
|
|
1238
1252
|
private getOrder;
|
|
1239
1253
|
private cancelOrder;
|
|
1240
1254
|
/** Move an order to a vendor status, set the three fields coherently, emit the webhook. */
|
|
@@ -1253,6 +1267,10 @@ type RxVortexRuntimeOptions = {
|
|
|
1253
1267
|
seed?: number | string;
|
|
1254
1268
|
adminKey?: string;
|
|
1255
1269
|
onLog?: (entry: RequestLog) => void;
|
|
1270
|
+
/**
|
|
1271
|
+
* Rows every namespace starts with, and returns to on `POST /__admin/reset` (`serve
|
|
1272
|
+
* --catalog <file>`). Default: `DEFAULT_CATALOG`.
|
|
1273
|
+
*/
|
|
1256
1274
|
catalog?: readonly CatalogItem[];
|
|
1257
1275
|
settings?: Partial<Settings>;
|
|
1258
1276
|
/** Where status webhooks go (`POST /prescriptions/webhooks/rxvortex`), sent with the secret header. */
|
|
@@ -1287,8 +1305,13 @@ type RxVortexServer = Listening & {
|
|
|
1287
1305
|
};
|
|
1288
1306
|
/** Serve the RxVortex mock over `node:http`, with auto-advance ticking every 100 ms. */
|
|
1289
1307
|
declare const createServer: (options?: RxVortexServerOptions) => Promise<RxVortexServer>;
|
|
1308
|
+
/**
|
|
1309
|
+
* Read a catalog file: a JSON array of rows, or the `{data: [...]}` body
|
|
1310
|
+
* `GET /api/v1/preset-catalog-items` answers with, so a recorded response loads as-is.
|
|
1311
|
+
*/
|
|
1312
|
+
declare const loadCatalogFile: (path: string) => CatalogItem[];
|
|
1290
1313
|
/** How `serve` (and `serve --config`) builds the RxVortex mock from flags. */
|
|
1291
1314
|
declare const serveTarget: ServeTarget;
|
|
1292
1315
|
|
|
1293
|
-
export { DEFAULT_PORT, createServer, serveTarget };
|
|
1316
|
+
export { DEFAULT_PORT, createServer, loadCatalogFile, serveTarget };
|
|
1294
1317
|
export type { RxVortexServer, RxVortexServerOptions };
|
package/dist/server.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_PORT,
|
|
3
3
|
createServer,
|
|
4
|
+
loadCatalogFile,
|
|
4
5
|
serveTarget
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-SNW7NYY6.js";
|
|
7
|
+
import "./chunk-VQAJFAUO.js";
|
|
7
8
|
export {
|
|
8
9
|
DEFAULT_PORT,
|
|
9
10
|
createServer,
|
|
11
|
+
loadCatalogFile,
|
|
10
12
|
serveTarget
|
|
11
13
|
};
|
|
12
14
|
//# sourceMappingURL=server.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crvouga/mockingbird-service-rxvortex",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Stateful mock of the RxVortex (Strive) pharmacy API: OAuth token, order submit, status, cancel, recovery by sender order id, preset catalog, and signed status webhooks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -52,7 +52,11 @@
|
|
|
52
52
|
"layer": "service",
|
|
53
53
|
"category": "pharmacy",
|
|
54
54
|
"displayName": "RxVortex",
|
|
55
|
-
"
|
|
55
|
+
"vendor": {
|
|
56
|
+
"website": "https://www.rxvortex.com",
|
|
57
|
+
"description": "RxVortex is a pharmacy order platform whose API lets telehealth partners submit, track and cancel prescription orders with pharmacies such as Strive."
|
|
58
|
+
},
|
|
59
|
+
"status": "ready"
|
|
56
60
|
},
|
|
57
61
|
"scripts": {
|
|
58
62
|
"generate": "bun ../../openapi/codegen/dist/cli.js",
|
|
@@ -67,7 +71,7 @@
|
|
|
67
71
|
"pack:check": "bun ../../../scripts/pack-check.ts"
|
|
68
72
|
},
|
|
69
73
|
"dependencies": {
|
|
70
|
-
"@crvouga/mockingbird-service-sqlite": "0.
|
|
74
|
+
"@crvouga/mockingbird-service-sqlite": "1.0.0",
|
|
71
75
|
"hono": "4.11.9"
|
|
72
76
|
},
|
|
73
77
|
"devDependencies": {
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../adapters/node/src/cli.ts", "../../../adapters/node/src/serve.ts", "../../../adapters/node/src/listen.ts", "../src/server.ts"],
|
|
4
|
-
"sourcesContent": ["import { readFile } from \"node:fs/promises\"\nimport { type ParseArgsConfig, parseArgs } from \"node:util\"\nimport type { RequestLog, ServiceInstance, ServiceRuntime } from \"@crvouga/mockingbird-service\"\nimport { type Listening, listen } from \"./listen.js\"\n\nexport type CliOption = {\n type: \"string\" | \"boolean\"\n description: string\n /** Shown in help; the value placeholder, e.g. `<port>`. */\n value?: string\n default?: string | boolean\n}\n\nexport type CliValues = Record<string, string | boolean | undefined>\n\nexport type CliCommand = {\n summary: string\n usage?: string\n options?: Record<string, CliOption>\n /** Resolves to an exit code; a server command resolves only when it stops. */\n run(values: CliValues, positionals: string[]): Promise<number>\n}\n\nexport type CliSpec = {\n bin: string\n description: string\n commands: Record<string, CliCommand>\n}\n\nconst optionHelp = (options: Record<string, CliOption>): string[] =>\n Object.entries(options).map(([name, option]) => {\n const flag = `--${name}${option.type === \"string\" ? ` ${option.value ?? \"<value>\"}` : \"\"}`\n const fallback = option.default !== undefined ? ` (default: ${String(option.default)})` : \"\"\n return ` ${flag.padEnd(30)} ${option.description}${fallback}`\n })\n\nconst help = (spec: CliSpec): string =>\n [\n `${spec.bin} \u2014 ${spec.description}`,\n \"\",\n \"Usage:\",\n ` ${spec.bin} <command> [options]`,\n \"\",\n \"Commands:\",\n ...Object.entries(spec.commands).map(([name, c]) => ` ${name.padEnd(30)} ${c.summary}`),\n \"\",\n `Run \\`${spec.bin} <command> --help\\` for a command's options.`,\n ].join(\"\\n\")\n\nconst commandHelp = (spec: CliSpec, name: string, command: CliCommand): string =>\n [\n `${spec.bin} ${name} \u2014 ${command.summary}`,\n \"\",\n \"Usage:\",\n ` ${command.usage ?? `${spec.bin} ${name} [options]`}`,\n ...(command.options ? [\"\", \"Options:\", ...optionHelp(command.options)] : []),\n ].join(\"\\n\")\n\n/** Parse `argv` against `spec` and run the chosen command. Resolves to an exit code. */\nexport const runCli = async (spec: CliSpec, argv: string[]): Promise<number> => {\n // Two-word commands (`corpus pull`) win over one-word ones.\n const pair = argv.length >= 2 ? `${argv[0]} ${argv[1]}` : undefined\n const words = pair !== undefined && spec.commands[pair] ? 2 : 1\n const name = words === 2 ? pair : argv[0]\n const rest = argv.slice(words)\n if (name === undefined || name === \"--help\" || name === \"-h\" || name === \"help\") {\n console.log(help(spec))\n return 0\n }\n const command = spec.commands[name]\n if (!command) {\n console.error(`${spec.bin}: unknown command ${JSON.stringify(name)}\\n\\n${help(spec)}`)\n return 2\n }\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\n console.log(commandHelp(spec, name, command))\n return 0\n }\n let parsed: { values: CliValues; positionals: string[] }\n try {\n parsed = parseArgs({\n args: rest,\n allowPositionals: true,\n strict: true,\n options: Object.fromEntries(\n Object.entries(command.options ?? {}).map(([key, option]) => [\n key,\n {\n type: option.type,\n ...(option.default !== undefined ? { default: option.default } : {}),\n },\n ]),\n ) as ParseArgsConfig[\"options\"],\n }) as { values: CliValues; positionals: string[] }\n } catch (error) {\n console.error(\n `${spec.bin} ${name}: ${error instanceof Error ? error.message : String(error)}\\n\\n${commandHelp(spec, name, command)}`,\n )\n return 2\n }\n return command.run(parsed.values, parsed.positionals)\n}\n\n// \u2500\u2500 serve \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport type LogFormat = \"pretty\" | \"json\" | \"off\"\n\nexport type CommonServeOptions = {\n adminKey: string | undefined\n seed: string | undefined\n onLog: ((entry: RequestLog) => void) | undefined\n}\n\n/**\n * What a service contributes to `serve`: how to build its runtime from CLI flags,\n * and what to say at startup. Every service's `./server` entry exports one as\n * `serveTarget`, which is also how `serve --config` finds services by name.\n */\nexport type ServeTarget = {\n name: string\n defaultPort: number\n /** Serve flags beyond the common ones. */\n options?: Record<string, CliOption>\n create(\n values: CliValues,\n common: CommonServeOptions,\n ): Promise<ServiceRuntime<ServiceInstance>> | ServiceRuntime<ServiceInstance>\n /** Startup lines after the listen address, e.g. the loaded corpus version. */\n banner?(runtime: ServiceRuntime<ServiceInstance>): string[]\n}\n\nconst COMMON_SERVE_OPTIONS: Record<string, CliOption> = {\n port: { type: \"string\", value: \"<port>\", description: \"Port to listen on\" },\n host: { type: \"string\", value: \"<host>\", description: \"Interface to bind\", default: \"127.0.0.1\" },\n \"admin-key\": {\n type: \"string\",\n value: \"<key>\",\n description: \"Require x-mockingbird-admin-key on /__admin/* (env MOCKINGBIRD_ADMIN_KEY)\",\n },\n seed: { type: \"string\", value: \"<seed>\", description: \"Seed for every random choice\" },\n log: {\n type: \"string\",\n value: \"<pretty|json|off>\",\n description: \"Request log format\",\n default: \"pretty\",\n },\n \"log-requests\": {\n type: \"boolean\",\n description:\n \"One JSON line per request: namespace, operationId, status, ids touched (never bodies). Same as --log json\",\n },\n config: {\n type: \"string\",\n value: \"<file>\",\n description: \"Serve every service in a mockingbird.json config instead\",\n },\n}\n\nconst formatLog = (format: LogFormat) => {\n if (format === \"off\") return undefined\n if (format === \"json\") return (entry: RequestLog) => console.log(JSON.stringify(entry))\n return (entry: RequestLog) => {\n const op = entry.operationId ?? (entry.unmatched ? \"UNMATCHED\" : \"-\")\n const ns = entry.namespace === \"default\" ? \"\" : ` [${entry.namespace}]`\n const fault = entry.faultId ? ` fault=${entry.faultId}` : \"\"\n const adopted = entry.adopted ? \" adopted\" : \"\"\n console.log(\n `${entry.service} ${entry.method} ${entry.path} ${entry.status} ${op} ${entry.durationMs}ms${ns}${fault}${adopted}`,\n )\n }\n}\n\nconst asString = (value: string | boolean | undefined): string | undefined =>\n typeof value === \"string\" ? value : undefined\n\n/** A service entry in `mockingbird.json`. */\nexport type ConfigService = {\n port?: number\n host?: string\n adminKey?: string\n seed?: string\n /** Service-specific serve flags, by long name: `{ \"webhook-url\": \"\u2026\" }`. */\n options?: Record<string, string | boolean>\n}\n\nexport type MockingbirdConfig = {\n /** Keyed by service name: `junction` loads `@crvouga/mockingbird-service-junction`. */\n services: Record<string, ConfigService>\n log?: LogFormat\n}\n\nconst loadTarget = async (name: string, own: ServeTarget): Promise<ServeTarget> => {\n if (name === own.name) return own\n const specifier = `@crvouga/mockingbird-service-${name}/server`\n try {\n const mod = (await import(specifier)) as { serveTarget?: ServeTarget }\n if (!mod.serveTarget) throw new Error(`${specifier} exports no serveTarget`)\n return mod.serveTarget\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n throw new Error(\n `cannot load service \"${name}\": ${reason}. Install @crvouga/mockingbird-service-${name}.`,\n )\n }\n}\n\nconst start = async (\n target: ServeTarget,\n values: CliValues,\n config: { port: number; host: string; adminKey?: string; seed?: string; log: LogFormat },\n): Promise<Listening> => {\n const runtime = await target.create(values, {\n adminKey: config.adminKey,\n seed: config.seed,\n onLog: formatLog(config.log),\n })\n const listening = await listen(runtime, { port: config.port, host: config.host })\n console.log(`${target.name} mock listening on ${listening.url}`)\n console.log(`${target.name} health: GET ${listening.url}/health`)\n console.log(\n `${target.name} admin: ${listening.url}/__admin (${config.adminKey ? \"x-mockingbird-admin-key required\" : \"open \u2014 pass --admin-key to lock\"})`,\n )\n for (const line of target.banner?.(runtime) ?? []) console.log(`${target.name} ${line}`)\n return listening\n}\n\nconst untilSignal = async (servers: Listening[]): Promise<number> =>\n new Promise((resolve) => {\n const stop = async () => {\n await Promise.allSettled(servers.map((s) => s.close()))\n resolve(0)\n }\n process.once(\"SIGINT\", stop)\n process.once(\"SIGTERM\", stop)\n })\n\n/** The standard `serve` command for a service, including multi-service `--config`. */\nexport const serveCommand = (target: ServeTarget): CliCommand => ({\n summary: `Serve the ${target.name} mock over HTTP`,\n options: { ...COMMON_SERVE_OPTIONS, ...target.options },\n async run(values) {\n const log = (\n values[\"log-requests\"] === true ? \"json\" : (asString(values.log) ?? \"pretty\")\n ) as LogFormat\n if (![\"pretty\", \"json\", \"off\"].includes(log)) {\n console.error(`--log must be pretty, json or off (got ${log})`)\n return 2\n }\n const configPath = asString(values.config)\n if (configPath !== undefined) {\n const config = JSON.parse(await readFile(configPath, \"utf8\")) as MockingbirdConfig\n const servers: Listening[] = []\n try {\n for (const [name, entry] of Object.entries(config.services ?? {})) {\n const each = await loadTarget(name, target)\n servers.push(\n await start(each, entry.options ?? {}, {\n port: entry.port ?? each.defaultPort,\n host: entry.host ?? \"127.0.0.1\",\n ...(entry.adminKey !== undefined ? { adminKey: entry.adminKey } : {}),\n ...(entry.seed !== undefined ? { seed: entry.seed } : {}),\n log: config.log ?? log,\n }),\n )\n }\n } catch (error) {\n await Promise.allSettled(servers.map((s) => s.close()))\n console.error(error instanceof Error ? error.message : String(error))\n return 1\n }\n return untilSignal(servers)\n }\n const port = asString(values.port)\n const adminKey = asString(values[\"admin-key\"]) ?? process.env.MOCKINGBIRD_ADMIN_KEY\n const seed = asString(values.seed)\n let listening: Listening\n try {\n listening = await start(target, values, {\n port: port === undefined ? target.defaultPort : Number.parseInt(port, 10),\n host: asString(values.host) ?? \"127.0.0.1\",\n ...(adminKey !== undefined ? { adminKey } : {}),\n ...(seed !== undefined ? { seed } : {}),\n log,\n })\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n return 1\n }\n return untilSignal([listening])\n },\n})\n", "import { createServer } from \"node:http\"\nimport type { FetchAPI } from \"@crvouga/mockingbird-core\"\n\n/** Options for {@link serve}. */\nexport type NodeServeOptions = {\n port?: number\n host?: string\n}\n\n/**\n * Serve any Mockingbird {@link FetchAPI} over `node:http`.\n * Port defaults to `0`, so the OS assigns an ephemeral port (read from `server.address()`).\n */\nexport const serve = async (api: FetchAPI, options: NodeServeOptions = {}) => {\n const server = createServer(async (req, res) => {\n const chunks: Buffer[] = []\n for await (const chunk of req) {\n chunks.push(Buffer.from(chunk))\n }\n const body = Buffer.concat(chunks)\n const address = server.address()\n const port = typeof address === \"object\" && address !== null ? address.port : undefined\n const base = `http://${req.headers.host ?? `localhost:${port ?? 80}`}`\n const raw = req.url ?? \"/\"\n const url = new URL(raw.replace(/^\\/+/, \"/\"), base)\n const method = req.method ?? \"GET\"\n const init: RequestInit = { method, headers: req.headers as Record<string, string> }\n if (method !== \"GET\" && method !== \"HEAD\" && body.length > 0) {\n init.body = body\n }\n const aborted = new AbortController()\n res.once(\"close\", () => {\n if (!res.writableFinished) aborted.abort()\n })\n init.signal = aborted.signal\n const request = new Request(url, init)\n let response: Response\n try {\n response = await api.fetch(request)\n } catch (error) {\n // A `drop` fault: destroy the socket so the client sees the connection die.\n if ((error as { code?: string }).code === \"MOCKINGBIRD_DROP\") {\n req.socket.destroy()\n return\n }\n res.writeHead(500, { \"content-type\": \"application/json\" })\n res.end(\n JSON.stringify({\n error: {\n type: \"mockingbird_internal\",\n message: error instanceof Error ? error.message : String(error),\n },\n }),\n )\n return\n }\n // Headers#entries() joins repeated headers; Set-Cookie must stay one header per cookie.\n const headers: Record<string, string | string[]> = Object.fromEntries(response.headers)\n const cookies = response.headers.getSetCookie()\n if (cookies.length > 0) headers[\"set-cookie\"] = cookies\n if (!response.body) {\n res.writeHead(response.status, headers)\n res.end()\n return\n }\n // Stream the body chunk by chunk: event streams and long-polls must not be buffered.\n res.writeHead(response.status, headers)\n res.flushHeaders()\n const reader = response.body.getReader()\n try {\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n if (!res.write(value)) await new Promise<void>((resolve) => res.once(\"drain\", resolve))\n }\n res.end()\n } catch {\n res.destroy()\n } finally {\n reader.releaseLock()\n }\n })\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(options.port ?? 0, options.host, resolve)\n })\n return server\n}\n", "import type { Server } from \"node:http\"\nimport type { FetchAPI } from \"@crvouga/mockingbird-core\"\nimport { serve } from \"./serve.js\"\n\nexport type ListenOptions = {\n /** Default `0`: the OS picks a free port. */\n port?: number\n /** Default `127.0.0.1`: a mock should not be reachable off the machine by accident. */\n host?: string\n}\n\n/** A running server, with the address it actually bound. */\nexport type Listening = {\n url: string\n port: number\n host: string\n server: Server\n close(): Promise<void>\n}\n\nexport const listen = async (api: FetchAPI, options: ListenOptions = {}): Promise<Listening> => {\n const host = options.host ?? \"127.0.0.1\"\n const server = await serve(api, { port: options.port ?? 0, host })\n const address = server.address()\n const port = typeof address === \"object\" && address !== null ? address.port : (options.port ?? 0)\n const shown = host.includes(\":\") ? `[${host}]` : host\n return {\n url: `http://${shown}:${port}`,\n port,\n host,\n server,\n close: () =>\n new Promise<void>((resolve, reject) => {\n // Stop accepting first, then drop keep-alive sockets so close() can finish.\n server.close((error) => {\n if (error && (error as { code?: string }).code !== \"ERR_SERVER_NOT_RUNNING\") reject(error)\n else resolve()\n })\n server.closeAllConnections?.()\n }),\n }\n}\n", "/// <reference types=\"node\" />\nimport { type Listening, listen, type ServeTarget } from \"@crvouga/mockingbird-adapter-node\"\nimport { createRuntime, type RxVortexRuntime, type RxVortexRuntimeOptions } from \"./runtime.js\"\n\n/** Port `mockingbird-rxvortex serve` listens on when none is given. */\nexport const DEFAULT_PORT = 8791\n\nexport type RxVortexServerOptions = RxVortexRuntimeOptions & {\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 RxVortexServer = Listening & { runtime: RxVortexRuntime }\n\n/** Serve the RxVortex mock over `node:http`, with auto-advance ticking every 100 ms. */\nexport const createServer = async (\n options: RxVortexServerOptions = {},\n): Promise<RxVortexServer> => {\n const { port, host, ...rest } = options\n const runtime = createRuntime({ tickMs: 100, ...rest })\n const listening = await listen(runtime, {\n port: port ?? 0,\n ...(host !== undefined ? { host } : {}),\n })\n return {\n ...listening,\n runtime,\n close: async () => {\n runtime.stop()\n await listening.close()\n },\n }\n}\n\nconst text = (value: string | boolean | undefined) =>\n typeof value === \"string\" ? value : undefined\n\n/** How `serve` (and `serve --config`) builds the RxVortex mock from flags. */\nexport const serveTarget: ServeTarget = {\n name: \"rxvortex\",\n defaultPort: DEFAULT_PORT,\n options: {\n \"webhook-url\": {\n type: \"string\",\n value: \"<url>\",\n description:\n \"Deliver status webhooks here (e.g. http://127.0.0.1:3000/prescriptions/webhooks/rxvortex)\",\n },\n \"webhook-secret\": {\n type: \"string\",\n value: \"<secret>\",\n description: \"Sent as x-rxvortex-webhook-secret (the app's RXVORTEX_WEBHOOK_SECRET)\",\n },\n \"api-token\": {\n type: \"string\",\n value: \"<token>\",\n description: \"A static bearer token to accept (the app's RXVORTEX_API_TOKEN)\",\n },\n \"auto-advance\": {\n type: \"string\",\n value: \"<ms:Status,Status,\u2026>\",\n description: 'Walk every new order along a path, e.g. \"2000:Fill,Shipping,Delivered\"',\n },\n },\n create: (values, common) => {\n const url = text(values[\"webhook-url\"])\n const secret = text(values[\"webhook-secret\"])\n const token = text(values[\"api-token\"])\n const auto = text(values[\"auto-advance\"])\n const plan = auto ? /^(\\d+):(.+)$/.exec(auto) : null\n if (auto && !plan)\n throw new Error('--auto-advance must look like \"2000:Fill,Shipping,Delivered\"')\n return createRuntime({\n tickMs: 100,\n ...(url ? { webhooks: { url, ...(secret ? { secret } : {}) } } : {}),\n settings: {\n ...(token ? { staticTokens: [token] } : {}),\n ...(plan\n ? {\n autoAdvance: {\n afterMs: Number(plan[1]),\n path: (plan[2] as string).split(\",\").map((s) => s.trim()),\n },\n }\n : {}),\n },\n ...(common.adminKey !== undefined ? { adminKey: common.adminKey } : {}),\n ...(common.seed !== undefined ? { seed: common.seed } : {}),\n ...(common.onLog ? { onLog: common.onLog } : {}),\n })\n },\n banner: () => [\n \"auth: POST /api/v1/generate-access-token {client_id, client_secret}, then Authorization: Bearer <token>\",\n \"namespaces: x-mockingbird-namespace, /ns/<name>/\u2026, or PUT /__admin/credentials {<client_id>: <ns>}\",\n ],\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["createServer"]
|
|
7
|
-
}
|