@crvouga/mockingbird-service-junction 1.5.0 → 1.6.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 +10 -0
- package/dist/{chunk-AKZJPCBU.js → chunk-LNHFCMWC.js} +1453 -648
- package/dist/chunk-LNHFCMWC.js.map +7 -0
- package/dist/{chunk-7HA4XGOS.js → chunk-QPWK4BSX.js} +2 -2
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +1 -5
- package/dist/index.js +1 -1
- package/dist/server.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-AKZJPCBU.js.map +0 -7
- /package/dist/{chunk-7HA4XGOS.js.map → chunk-QPWK4BSX.js.map} +0 -0
|
@@ -537,10 +537,10 @@ var OpenAPIReferenceError = class extends Error {
|
|
|
537
537
|
};
|
|
538
538
|
var unescapePointer = (segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
539
539
|
var isReference = (value) => typeof value === "object" && value !== null && typeof value.$ref === "string";
|
|
540
|
-
var resolveRef = (
|
|
540
|
+
var resolveRef = (document3, ref) => {
|
|
541
541
|
if (!ref.startsWith("#/"))
|
|
542
542
|
throw new OpenAPIReferenceError(ref);
|
|
543
|
-
let cursor =
|
|
543
|
+
let cursor = document3;
|
|
544
544
|
for (const raw of ref.slice(2).split("/")) {
|
|
545
545
|
const segment = unescapePointer(raw);
|
|
546
546
|
if (typeof cursor !== "object" || cursor === null || !(segment in cursor)) {
|
|
@@ -552,14 +552,14 @@ var resolveRef = (document2, ref) => {
|
|
|
552
552
|
throw new OpenAPIReferenceError(ref);
|
|
553
553
|
return cursor;
|
|
554
554
|
};
|
|
555
|
-
var deref = (
|
|
555
|
+
var deref = (document3, value) => {
|
|
556
556
|
let current = value;
|
|
557
557
|
const seen = /* @__PURE__ */ new Set();
|
|
558
558
|
while (isReference(current)) {
|
|
559
559
|
if (seen.has(current.$ref))
|
|
560
560
|
throw new OpenAPIReferenceError(`${current.$ref} (cycle)`);
|
|
561
561
|
seen.add(current.$ref);
|
|
562
|
-
current = resolveRef(
|
|
562
|
+
current = resolveRef(document3, current.$ref);
|
|
563
563
|
}
|
|
564
564
|
return current;
|
|
565
565
|
};
|
|
@@ -577,36 +577,36 @@ var HTTP_METHODS = [
|
|
|
577
577
|
];
|
|
578
578
|
|
|
579
579
|
// ../../openapi/core/dist/document.js
|
|
580
|
-
var mergeParameters = (
|
|
580
|
+
var mergeParameters = (document3, item, own) => {
|
|
581
581
|
const merged = /* @__PURE__ */ new Map();
|
|
582
582
|
for (const raw of item.parameters ?? []) {
|
|
583
|
-
const parameter = deref(
|
|
583
|
+
const parameter = deref(document3, raw);
|
|
584
584
|
merged.set(`${parameter.in}:${parameter.name}`, parameter);
|
|
585
585
|
}
|
|
586
586
|
for (const raw of own ?? []) {
|
|
587
|
-
const parameter = deref(
|
|
587
|
+
const parameter = deref(document3, raw);
|
|
588
588
|
merged.set(`${parameter.in}:${parameter.name}`, parameter);
|
|
589
589
|
}
|
|
590
590
|
return [...merged.values()];
|
|
591
591
|
};
|
|
592
|
-
var listOperations = (
|
|
592
|
+
var listOperations = (document3) => {
|
|
593
593
|
const operations = [];
|
|
594
|
-
for (const [path, item] of Object.entries(
|
|
594
|
+
for (const [path, item] of Object.entries(document3.paths)) {
|
|
595
595
|
for (const method of HTTP_METHODS) {
|
|
596
596
|
const operation = item[method];
|
|
597
597
|
if (operation?.operationId === void 0)
|
|
598
598
|
continue;
|
|
599
599
|
const responses = {};
|
|
600
600
|
for (const [status, response] of Object.entries(operation.responses)) {
|
|
601
|
-
responses[status] = deref(
|
|
601
|
+
responses[status] = deref(document3, response);
|
|
602
602
|
}
|
|
603
603
|
operations.push({
|
|
604
604
|
operationId: operation.operationId,
|
|
605
605
|
method,
|
|
606
606
|
path,
|
|
607
607
|
operation,
|
|
608
|
-
parameters: mergeParameters(
|
|
609
|
-
requestBody: operation.requestBody === void 0 ? void 0 : deref(
|
|
608
|
+
parameters: mergeParameters(document3, item, operation.parameters),
|
|
609
|
+
requestBody: operation.requestBody === void 0 ? void 0 : deref(document3, operation.requestBody),
|
|
610
610
|
responses
|
|
611
611
|
});
|
|
612
612
|
}
|
|
@@ -1142,6 +1142,1232 @@ var clearNamespace = (sqlite, namespace) => {
|
|
|
1142
1142
|
});
|
|
1143
1143
|
};
|
|
1144
1144
|
|
|
1145
|
+
// ../../ui/dist/reset.js
|
|
1146
|
+
var CSS_RESET = `*,
|
|
1147
|
+
*::before,
|
|
1148
|
+
*::after {
|
|
1149
|
+
box-sizing: border-box;
|
|
1150
|
+
margin: 0;
|
|
1151
|
+
padding: 0;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
* {
|
|
1155
|
+
scrollbar-width: thin;
|
|
1156
|
+
scrollbar-color: color-mix(in srgb, CanvasText 35%, Canvas) Canvas;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
*::-webkit-scrollbar {
|
|
1160
|
+
width: 12px;
|
|
1161
|
+
height: 12px;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
*::-webkit-scrollbar-track,
|
|
1165
|
+
*::-webkit-scrollbar-corner {
|
|
1166
|
+
background: Canvas;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
*::-webkit-scrollbar-thumb {
|
|
1170
|
+
background: color-mix(in srgb, CanvasText 35%, Canvas);
|
|
1171
|
+
border: 3px solid Canvas;
|
|
1172
|
+
border-radius: 999px;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
html {
|
|
1176
|
+
hanging-punctuation: first allow-end last;
|
|
1177
|
+
-webkit-text-size-adjust: none;
|
|
1178
|
+
text-size-adjust: none;
|
|
1179
|
+
tab-size: 4;
|
|
1180
|
+
font-family:
|
|
1181
|
+
ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI Variable", "Segoe UI",
|
|
1182
|
+
"Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
|
1183
|
+
font-size: 16px;
|
|
1184
|
+
line-height: 1.5;
|
|
1185
|
+
-webkit-font-smoothing: antialiased;
|
|
1186
|
+
-moz-osx-font-smoothing: grayscale;
|
|
1187
|
+
text-rendering: optimizeLegibility;
|
|
1188
|
+
-webkit-tap-highlight-color: transparent;
|
|
1189
|
+
scroll-behavior: smooth;
|
|
1190
|
+
background: Canvas;
|
|
1191
|
+
color: CanvasText;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
body {
|
|
1195
|
+
min-height: 100svh;
|
|
1196
|
+
line-height: 1.5;
|
|
1197
|
+
background: Canvas;
|
|
1198
|
+
color: CanvasText;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
h1 {
|
|
1202
|
+
font-size: 2em;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
h2 {
|
|
1206
|
+
font-size: 1.5em;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
h3 {
|
|
1210
|
+
font-size: 1.17em;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
h4 {
|
|
1214
|
+
font-size: 1em;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
h5 {
|
|
1218
|
+
font-size: 0.83em;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
h6 {
|
|
1222
|
+
font-size: 0.67em;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
h1,
|
|
1226
|
+
h2,
|
|
1227
|
+
h3,
|
|
1228
|
+
h4,
|
|
1229
|
+
h5,
|
|
1230
|
+
h6 {
|
|
1231
|
+
font-weight: 700;
|
|
1232
|
+
line-height: 1.2;
|
|
1233
|
+
text-wrap: balance;
|
|
1234
|
+
overflow-wrap: break-word;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
p,
|
|
1238
|
+
li,
|
|
1239
|
+
figcaption,
|
|
1240
|
+
dd,
|
|
1241
|
+
dt,
|
|
1242
|
+
blockquote {
|
|
1243
|
+
overflow-wrap: break-word;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
p,
|
|
1247
|
+
li,
|
|
1248
|
+
figcaption,
|
|
1249
|
+
blockquote {
|
|
1250
|
+
text-wrap: pretty;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
ul,
|
|
1254
|
+
ol,
|
|
1255
|
+
menu {
|
|
1256
|
+
list-style: none;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
a {
|
|
1260
|
+
color: inherit;
|
|
1261
|
+
text-decoration: underline;
|
|
1262
|
+
text-decoration-thickness: 1px;
|
|
1263
|
+
text-underline-offset: 0.15em;
|
|
1264
|
+
text-decoration-skip-ink: auto;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
b,
|
|
1268
|
+
strong {
|
|
1269
|
+
font-weight: 700;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
small {
|
|
1273
|
+
font-size: 0.875em;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
code,
|
|
1277
|
+
kbd,
|
|
1278
|
+
samp,
|
|
1279
|
+
pre {
|
|
1280
|
+
font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
|
|
1281
|
+
font-size: 1em;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
sub,
|
|
1285
|
+
sup {
|
|
1286
|
+
font-size: 75%;
|
|
1287
|
+
line-height: 0;
|
|
1288
|
+
position: relative;
|
|
1289
|
+
vertical-align: baseline;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
sub {
|
|
1293
|
+
bottom: -0.25em;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
sup {
|
|
1297
|
+
top: -0.5em;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
abbr[title] {
|
|
1301
|
+
text-decoration: underline dotted;
|
|
1302
|
+
text-underline-offset: 0.15em;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
mark {
|
|
1306
|
+
background: Mark;
|
|
1307
|
+
color: MarkText;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
hr {
|
|
1311
|
+
height: 0;
|
|
1312
|
+
border: 0;
|
|
1313
|
+
border-top: 1px solid color-mix(in srgb, CanvasText 20%, transparent);
|
|
1314
|
+
color: inherit;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
img,
|
|
1318
|
+
picture,
|
|
1319
|
+
video,
|
|
1320
|
+
canvas {
|
|
1321
|
+
display: block;
|
|
1322
|
+
max-width: 100%;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
img,
|
|
1326
|
+
video {
|
|
1327
|
+
height: auto;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
svg {
|
|
1331
|
+
overflow: hidden;
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
iframe {
|
|
1335
|
+
border: 0;
|
|
1336
|
+
max-width: 100%;
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
table {
|
|
1340
|
+
border-collapse: collapse;
|
|
1341
|
+
border-spacing: 0;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
fieldset {
|
|
1345
|
+
border: 0;
|
|
1346
|
+
min-inline-size: 0;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
legend {
|
|
1350
|
+
padding: 0;
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
button,
|
|
1354
|
+
input,
|
|
1355
|
+
select,
|
|
1356
|
+
textarea,
|
|
1357
|
+
optgroup {
|
|
1358
|
+
font: inherit;
|
|
1359
|
+
letter-spacing: inherit;
|
|
1360
|
+
color: inherit;
|
|
1361
|
+
margin: 0;
|
|
1362
|
+
vertical-align: middle;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
button,
|
|
1366
|
+
input[type="button"],
|
|
1367
|
+
input[type="submit"],
|
|
1368
|
+
input[type="reset"] {
|
|
1369
|
+
appearance: none;
|
|
1370
|
+
background: none;
|
|
1371
|
+
border: 0;
|
|
1372
|
+
padding: 0;
|
|
1373
|
+
cursor: pointer;
|
|
1374
|
+
text-align: center;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
input,
|
|
1378
|
+
textarea,
|
|
1379
|
+
select {
|
|
1380
|
+
background-color: Canvas;
|
|
1381
|
+
border: 1px solid color-mix(in srgb, CanvasText 28%, transparent);
|
|
1382
|
+
border-radius: 0;
|
|
1383
|
+
padding: 0.5em 0.65em;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
input[type="checkbox"],
|
|
1387
|
+
input[type="radio"],
|
|
1388
|
+
input[type="range"],
|
|
1389
|
+
input[type="file"],
|
|
1390
|
+
input[type="color"],
|
|
1391
|
+
input[type="button"],
|
|
1392
|
+
input[type="submit"],
|
|
1393
|
+
input[type="reset"],
|
|
1394
|
+
input[type="image"],
|
|
1395
|
+
input[type="hidden"] {
|
|
1396
|
+
background: none;
|
|
1397
|
+
border: 0;
|
|
1398
|
+
padding: 0;
|
|
1399
|
+
border-radius: 0;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
input[type="checkbox"],
|
|
1403
|
+
input[type="radio"] {
|
|
1404
|
+
accent-color: CanvasText;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
input[type="search"] {
|
|
1408
|
+
appearance: none;
|
|
1409
|
+
background-color: Canvas;
|
|
1410
|
+
border: 1px solid color-mix(in srgb, CanvasText 28%, transparent);
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
input[type="search"]::-webkit-search-decoration,
|
|
1414
|
+
input[type="search"]::-webkit-search-cancel-button,
|
|
1415
|
+
input[type="search"]::-webkit-search-results-button,
|
|
1416
|
+
input[type="search"]::-webkit-search-results-decoration {
|
|
1417
|
+
-webkit-appearance: none;
|
|
1418
|
+
display: none;
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
input[type="number"] {
|
|
1422
|
+
appearance: textfield;
|
|
1423
|
+
background-color: Canvas;
|
|
1424
|
+
border: 1px solid color-mix(in srgb, CanvasText 28%, transparent);
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
input[type="number"]::-webkit-inner-spin-button,
|
|
1428
|
+
input[type="number"]::-webkit-outer-spin-button {
|
|
1429
|
+
-webkit-appearance: none;
|
|
1430
|
+
margin: 0;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
textarea {
|
|
1434
|
+
resize: vertical;
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
::placeholder {
|
|
1438
|
+
opacity: 1;
|
|
1439
|
+
color: color-mix(in srgb, CanvasText 45%, transparent);
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
:focus-visible {
|
|
1443
|
+
outline: 2px solid CanvasText;
|
|
1444
|
+
outline-offset: 2px;
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
:focus:not(:focus-visible) {
|
|
1448
|
+
outline: none;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
:disabled,
|
|
1452
|
+
[disabled] {
|
|
1453
|
+
cursor: default;
|
|
1454
|
+
opacity: 0.6;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
label,
|
|
1458
|
+
summary,
|
|
1459
|
+
select,
|
|
1460
|
+
[role="button"] {
|
|
1461
|
+
cursor: pointer;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
summary {
|
|
1465
|
+
display: list-item;
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
details {
|
|
1469
|
+
display: block;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
dialog {
|
|
1473
|
+
margin: auto;
|
|
1474
|
+
padding: 1rem;
|
|
1475
|
+
border: 1px solid color-mix(in srgb, CanvasText 20%, transparent);
|
|
1476
|
+
background: Canvas;
|
|
1477
|
+
color: CanvasText;
|
|
1478
|
+
max-width: calc(100vw - 2rem);
|
|
1479
|
+
max-height: calc(100svh - 2rem);
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
dialog:not([open]) {
|
|
1483
|
+
display: none;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
::backdrop {
|
|
1487
|
+
background: color-mix(in srgb, CanvasText 40%, transparent);
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
[hidden] {
|
|
1491
|
+
display: none !important;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
::selection {
|
|
1495
|
+
background: Highlight;
|
|
1496
|
+
color: HighlightText;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1500
|
+
*,
|
|
1501
|
+
*::before,
|
|
1502
|
+
*::after {
|
|
1503
|
+
animation-duration: 0.01ms !important;
|
|
1504
|
+
animation-iteration-count: 1 !important;
|
|
1505
|
+
transition-duration: 0.01ms !important;
|
|
1506
|
+
scroll-behavior: auto !important;
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
@media (pointer: coarse) {
|
|
1511
|
+
input,
|
|
1512
|
+
select,
|
|
1513
|
+
textarea {
|
|
1514
|
+
font-size: max(16px, 1em);
|
|
1515
|
+
}
|
|
1516
|
+
}`;
|
|
1517
|
+
|
|
1518
|
+
// ../core/dist/admin-client.js
|
|
1519
|
+
function isRecord2(value) {
|
|
1520
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1521
|
+
}
|
|
1522
|
+
function mountAdminBrand(doc, host, service, catalog) {
|
|
1523
|
+
const clip = (value, max) => {
|
|
1524
|
+
if (typeof value !== "string")
|
|
1525
|
+
return null;
|
|
1526
|
+
const trimmed = value.trim();
|
|
1527
|
+
if (trimmed === "")
|
|
1528
|
+
return null;
|
|
1529
|
+
return trimmed.length > max ? trimmed.slice(0, max) : trimmed;
|
|
1530
|
+
};
|
|
1531
|
+
const httpUrl = (value) => {
|
|
1532
|
+
if (typeof value !== "string" || value.length > 2e3)
|
|
1533
|
+
return null;
|
|
1534
|
+
try {
|
|
1535
|
+
const url = new URL(value);
|
|
1536
|
+
if (url.protocol !== "https:" && url.protocol !== "http:")
|
|
1537
|
+
return null;
|
|
1538
|
+
return url.href;
|
|
1539
|
+
} catch {
|
|
1540
|
+
return null;
|
|
1541
|
+
}
|
|
1542
|
+
};
|
|
1543
|
+
const hexColor = (value) => {
|
|
1544
|
+
if (typeof value !== "string")
|
|
1545
|
+
return null;
|
|
1546
|
+
const raw = value.trim();
|
|
1547
|
+
return /^#[0-9a-fA-F]{3,8}$/.test(raw) ? raw : null;
|
|
1548
|
+
};
|
|
1549
|
+
const hostname = (value) => {
|
|
1550
|
+
try {
|
|
1551
|
+
return new URL(value).hostname.replace(/^www\./, "");
|
|
1552
|
+
} catch {
|
|
1553
|
+
return value;
|
|
1554
|
+
}
|
|
1555
|
+
};
|
|
1556
|
+
host.replaceChildren();
|
|
1557
|
+
host.hidden = true;
|
|
1558
|
+
if (!isRecord2(catalog) || !Object.hasOwn(catalog, service))
|
|
1559
|
+
return;
|
|
1560
|
+
const row = catalog[service];
|
|
1561
|
+
if (!isRecord2(row))
|
|
1562
|
+
return;
|
|
1563
|
+
const vendor = clip(row.vendor, 80);
|
|
1564
|
+
const website = httpUrl(row.website);
|
|
1565
|
+
const guide = httpUrl(row.guide);
|
|
1566
|
+
const docs = httpUrl(row.docs);
|
|
1567
|
+
const logo = httpUrl(row.logo);
|
|
1568
|
+
const color = hexColor(row.color);
|
|
1569
|
+
const description = clip(row.description, 280);
|
|
1570
|
+
if (vendor === null || website === null && guide === null && docs === null)
|
|
1571
|
+
return;
|
|
1572
|
+
const add = (node) => {
|
|
1573
|
+
host.append(node);
|
|
1574
|
+
return node;
|
|
1575
|
+
};
|
|
1576
|
+
if (logo !== null) {
|
|
1577
|
+
const img = doc.createElement("img");
|
|
1578
|
+
img.alt = "";
|
|
1579
|
+
img.src = logo;
|
|
1580
|
+
img.width = 16;
|
|
1581
|
+
img.height = 16;
|
|
1582
|
+
img.decoding = "async";
|
|
1583
|
+
img.referrerPolicy = "no-referrer";
|
|
1584
|
+
if (color !== null)
|
|
1585
|
+
img.style.borderColor = color;
|
|
1586
|
+
add(img);
|
|
1587
|
+
}
|
|
1588
|
+
const name = doc.createElement("span");
|
|
1589
|
+
name.className = "vendor-name";
|
|
1590
|
+
name.textContent = vendor;
|
|
1591
|
+
if (description !== null)
|
|
1592
|
+
name.title = description;
|
|
1593
|
+
add(name);
|
|
1594
|
+
const sep = () => {
|
|
1595
|
+
const node = doc.createElement("span");
|
|
1596
|
+
node.className = "vendor-sep";
|
|
1597
|
+
node.setAttribute("aria-hidden", "true");
|
|
1598
|
+
node.textContent = "\xB7";
|
|
1599
|
+
return node;
|
|
1600
|
+
};
|
|
1601
|
+
const link = (href, label, title) => {
|
|
1602
|
+
const node = doc.createElement("a");
|
|
1603
|
+
node.className = "vendor-link";
|
|
1604
|
+
node.href = href;
|
|
1605
|
+
node.target = "_blank";
|
|
1606
|
+
node.rel = "noopener noreferrer";
|
|
1607
|
+
node.referrerPolicy = "no-referrer";
|
|
1608
|
+
node.textContent = label;
|
|
1609
|
+
node.title = title;
|
|
1610
|
+
return node;
|
|
1611
|
+
};
|
|
1612
|
+
if (website !== null) {
|
|
1613
|
+
add(sep());
|
|
1614
|
+
add(link(website, hostname(website), `${vendor} website`));
|
|
1615
|
+
}
|
|
1616
|
+
if (guide !== null) {
|
|
1617
|
+
add(sep());
|
|
1618
|
+
add(link(guide, "Docs", `Docs for ${vendor}`));
|
|
1619
|
+
}
|
|
1620
|
+
if (docs !== null) {
|
|
1621
|
+
add(sep());
|
|
1622
|
+
add(link(docs, "API", `${vendor} API reference`));
|
|
1623
|
+
}
|
|
1624
|
+
host.removeAttribute("hidden");
|
|
1625
|
+
host.hidden = false;
|
|
1626
|
+
}
|
|
1627
|
+
function startAdminBrand(env) {
|
|
1628
|
+
const requested = env.params.get("brands");
|
|
1629
|
+
let brandsUrl = env.brandsUrl;
|
|
1630
|
+
if (requested) {
|
|
1631
|
+
try {
|
|
1632
|
+
const url = new URL(requested, env.location.href);
|
|
1633
|
+
const local = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1" || url.hostname === "[::1]" || url.origin === env.location.origin;
|
|
1634
|
+
if ((url.protocol === "https:" || url.protocol === "http:") && local)
|
|
1635
|
+
brandsUrl = url.href;
|
|
1636
|
+
} catch {
|
|
1637
|
+
brandsUrl = env.brandsUrl;
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
const vendorHost = env.$("vendor");
|
|
1641
|
+
const brandRoot = env.document.querySelector("[data-mockingbird-admin]");
|
|
1642
|
+
const brandService = brandRoot?.getAttribute("data-service") || "";
|
|
1643
|
+
if (vendorHost === null)
|
|
1644
|
+
return;
|
|
1645
|
+
env.fetch(brandsUrl, {
|
|
1646
|
+
headers: { accept: "application/json" },
|
|
1647
|
+
signal: AbortSignal.timeout(5e3)
|
|
1648
|
+
}).then(async (response) => {
|
|
1649
|
+
if (!response.ok)
|
|
1650
|
+
return null;
|
|
1651
|
+
const catalog = await response.json();
|
|
1652
|
+
return catalog;
|
|
1653
|
+
}).then((catalog) => {
|
|
1654
|
+
mountAdminBrand(env.document, vendorHost, brandService, catalog);
|
|
1655
|
+
}).catch(() => {
|
|
1656
|
+
});
|
|
1657
|
+
}
|
|
1658
|
+
function faultPresetList(value) {
|
|
1659
|
+
if (!isRecord2(value))
|
|
1660
|
+
throw new Error("Fault presets response was not an object");
|
|
1661
|
+
if (!Object.hasOwn(value, "presets") || value.presets === void 0 || value.presets === null) {
|
|
1662
|
+
return { presets: [] };
|
|
1663
|
+
}
|
|
1664
|
+
if (!Array.isArray(value.presets))
|
|
1665
|
+
throw new Error("Fault presets response was not a list");
|
|
1666
|
+
return {
|
|
1667
|
+
presets: value.presets.flatMap((item) => {
|
|
1668
|
+
if (!isRecord2(item) || typeof item.name !== "string")
|
|
1669
|
+
return [];
|
|
1670
|
+
return [{ name: item.name }];
|
|
1671
|
+
})
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
function bootAdmin(config) {
|
|
1675
|
+
const fieldKinds = ["string", "number", "boolean", "null", "object", "array", "unknown"];
|
|
1676
|
+
const sources = ["declared", "inferred", "mixed"];
|
|
1677
|
+
const isFieldKind = (value) => typeof value === "string" && fieldKinds.some((kind) => kind === value);
|
|
1678
|
+
const isSource = (value) => typeof value === "string" && sources.some((source) => source === value);
|
|
1679
|
+
const readJson3 = (text) => {
|
|
1680
|
+
const value = JSON.parse(text);
|
|
1681
|
+
return value;
|
|
1682
|
+
};
|
|
1683
|
+
const esc = (value) => String(value ?? "").replace(/[&<>"']/g, (char) => {
|
|
1684
|
+
switch (char) {
|
|
1685
|
+
case "&":
|
|
1686
|
+
return "&";
|
|
1687
|
+
case "<":
|
|
1688
|
+
return "<";
|
|
1689
|
+
case ">":
|
|
1690
|
+
return ">";
|
|
1691
|
+
case '"':
|
|
1692
|
+
return """;
|
|
1693
|
+
default:
|
|
1694
|
+
return "'";
|
|
1695
|
+
}
|
|
1696
|
+
});
|
|
1697
|
+
const el = (id, kind) => {
|
|
1698
|
+
const node = document.getElementById(id);
|
|
1699
|
+
if (!(node instanceof kind))
|
|
1700
|
+
throw new Error(`admin shell is missing #${id}`);
|
|
1701
|
+
return node;
|
|
1702
|
+
};
|
|
1703
|
+
const errorMessage = (data, fallback) => {
|
|
1704
|
+
if (!isRecord2(data))
|
|
1705
|
+
return fallback;
|
|
1706
|
+
const error = data.error;
|
|
1707
|
+
if (!isRecord2(error) || typeof error.message !== "string" || error.message === "") {
|
|
1708
|
+
return fallback;
|
|
1709
|
+
}
|
|
1710
|
+
return error.message;
|
|
1711
|
+
};
|
|
1712
|
+
const requireList = (value, label) => {
|
|
1713
|
+
if (value === void 0 || value === null)
|
|
1714
|
+
return [];
|
|
1715
|
+
if (!Array.isArray(value))
|
|
1716
|
+
throw new Error(`${label} was not a list`);
|
|
1717
|
+
return value;
|
|
1718
|
+
};
|
|
1719
|
+
const state = {
|
|
1720
|
+
namespace: "default",
|
|
1721
|
+
key: sessionStorage.getItem("mockingbird-admin-key") || "",
|
|
1722
|
+
view: "overview",
|
|
1723
|
+
collection: "",
|
|
1724
|
+
shape: null,
|
|
1725
|
+
route: null,
|
|
1726
|
+
editing: null
|
|
1727
|
+
};
|
|
1728
|
+
const standard = new Set(config.standardRoutes);
|
|
1729
|
+
const banner = el("banner", HTMLElement);
|
|
1730
|
+
const keyInput = el("admin-key", HTMLInputElement);
|
|
1731
|
+
keyInput.value = state.key;
|
|
1732
|
+
const params = new URLSearchParams(location.search);
|
|
1733
|
+
const queryKey = params.get("key");
|
|
1734
|
+
if (queryKey) {
|
|
1735
|
+
state.key = queryKey;
|
|
1736
|
+
keyInput.value = state.key;
|
|
1737
|
+
sessionStorage.setItem("mockingbird-admin-key", state.key);
|
|
1738
|
+
params.delete("key");
|
|
1739
|
+
const next = params.toString();
|
|
1740
|
+
history.replaceState(null, "", location.pathname + (next ? `?${next}` : ""));
|
|
1741
|
+
}
|
|
1742
|
+
const queryNamespace = params.get("namespace");
|
|
1743
|
+
if (queryNamespace)
|
|
1744
|
+
state.namespace = queryNamespace;
|
|
1745
|
+
const showError = (error) => {
|
|
1746
|
+
banner.textContent = error instanceof Error ? error.message : String(error);
|
|
1747
|
+
banner.classList.add("show");
|
|
1748
|
+
};
|
|
1749
|
+
const clearError = () => {
|
|
1750
|
+
banner.classList.remove("show");
|
|
1751
|
+
};
|
|
1752
|
+
const api = async (method, path, body) => {
|
|
1753
|
+
const headers = { accept: "application/json" };
|
|
1754
|
+
if (state.key !== "")
|
|
1755
|
+
headers[config.adminKeyHeader] = state.key;
|
|
1756
|
+
if (state.namespace !== "")
|
|
1757
|
+
headers["x-mockingbird-namespace"] = state.namespace;
|
|
1758
|
+
if (body !== void 0)
|
|
1759
|
+
headers["content-type"] = "application/json";
|
|
1760
|
+
const init = { method, headers };
|
|
1761
|
+
if (body !== void 0)
|
|
1762
|
+
init.body = JSON.stringify(body);
|
|
1763
|
+
const response = await fetch(config.adminPrefix + path, init);
|
|
1764
|
+
const text = await response.text();
|
|
1765
|
+
let data = null;
|
|
1766
|
+
if (text !== "") {
|
|
1767
|
+
try {
|
|
1768
|
+
data = readJson3(text);
|
|
1769
|
+
} catch {
|
|
1770
|
+
data = { raw: text };
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
if (response.status === 401) {
|
|
1774
|
+
keyInput.focus();
|
|
1775
|
+
throw new Error(errorMessage(data, "Admin key required"));
|
|
1776
|
+
}
|
|
1777
|
+
if (!response.ok) {
|
|
1778
|
+
throw new Error(errorMessage(data, `${response.status} ${method} ${path}`));
|
|
1779
|
+
}
|
|
1780
|
+
return data;
|
|
1781
|
+
};
|
|
1782
|
+
const originGet = async (path) => {
|
|
1783
|
+
const response = await fetch(path, { headers: { accept: "application/json" } });
|
|
1784
|
+
if (!response.ok)
|
|
1785
|
+
throw new Error(`${response.status} ${path}`);
|
|
1786
|
+
const value = await response.json();
|
|
1787
|
+
return value;
|
|
1788
|
+
};
|
|
1789
|
+
const panelApi = {
|
|
1790
|
+
get: (path) => api("GET", path),
|
|
1791
|
+
send: (method, path, body) => api(method, path, body),
|
|
1792
|
+
namespace: () => state.namespace
|
|
1793
|
+
};
|
|
1794
|
+
const isPanelScript = (value) => typeof value === "function";
|
|
1795
|
+
const setTheme = (theme) => {
|
|
1796
|
+
if (theme)
|
|
1797
|
+
document.documentElement.dataset.theme = theme;
|
|
1798
|
+
else
|
|
1799
|
+
delete document.documentElement.dataset.theme;
|
|
1800
|
+
};
|
|
1801
|
+
const storedTheme = localStorage.getItem("mockingbird-admin-theme");
|
|
1802
|
+
if (storedTheme)
|
|
1803
|
+
setTheme(storedTheme);
|
|
1804
|
+
el("theme", HTMLButtonElement).addEventListener("click", () => {
|
|
1805
|
+
const current = document.documentElement.dataset.theme;
|
|
1806
|
+
const dark = current ? current === "dark" : matchMedia("(prefers-color-scheme: dark)").matches;
|
|
1807
|
+
const next = dark ? "light" : "dark";
|
|
1808
|
+
localStorage.setItem("mockingbird-admin-theme", next);
|
|
1809
|
+
setTheme(next);
|
|
1810
|
+
});
|
|
1811
|
+
const show = (view) => {
|
|
1812
|
+
state.view = view;
|
|
1813
|
+
for (const button of document.querySelectorAll("#nav button")) {
|
|
1814
|
+
if (!(button instanceof HTMLButtonElement))
|
|
1815
|
+
continue;
|
|
1816
|
+
button.setAttribute("aria-current", button.dataset.view === view ? "true" : "false");
|
|
1817
|
+
}
|
|
1818
|
+
for (const section of document.querySelectorAll("main .view")) {
|
|
1819
|
+
if (!(section instanceof HTMLElement))
|
|
1820
|
+
continue;
|
|
1821
|
+
section.hidden = section.id !== `view-${view}`;
|
|
1822
|
+
}
|
|
1823
|
+
};
|
|
1824
|
+
el("nav", HTMLElement).addEventListener("click", (event) => {
|
|
1825
|
+
const target = event.target;
|
|
1826
|
+
if (!(target instanceof Element))
|
|
1827
|
+
return;
|
|
1828
|
+
const button = target.closest("button[data-view]");
|
|
1829
|
+
if (!(button instanceof HTMLButtonElement))
|
|
1830
|
+
return;
|
|
1831
|
+
const view = button.dataset.view;
|
|
1832
|
+
if (view === void 0)
|
|
1833
|
+
return;
|
|
1834
|
+
show(view);
|
|
1835
|
+
refresh().catch(showError);
|
|
1836
|
+
});
|
|
1837
|
+
const cards = (items) => `<div class="grid">${items.map((item) => `<article class="card"><div class="k">${item.k}</div><div class="v">${item.v}</div></article>`).join("")}</div>`;
|
|
1838
|
+
const table = (columns, rows) => {
|
|
1839
|
+
if (rows.length === 0)
|
|
1840
|
+
return '<p class="empty">Nothing here yet.</p>';
|
|
1841
|
+
const head = `<tr>${columns.map((column) => `<th>${column.label}</th>`).join("")}</tr>`;
|
|
1842
|
+
const body = rows.map((row) => {
|
|
1843
|
+
const cells = columns.map((column) => `<td data-label="${column.label}">${column.cell(row)}</td>`).join("");
|
|
1844
|
+
const attrs = "attrs" in row && typeof row.attrs === "string" ? row.attrs : "";
|
|
1845
|
+
return `<tr${attrs}>${cells}</tr>`;
|
|
1846
|
+
}).join("");
|
|
1847
|
+
return `<table><thead>${head}</thead><tbody>${body}</tbody></table>`;
|
|
1848
|
+
};
|
|
1849
|
+
const preview = (value) => {
|
|
1850
|
+
const text = JSON.stringify(value) ?? "null";
|
|
1851
|
+
return esc(text.length > 180 ? `${text.slice(0, 180)}\u2026` : text);
|
|
1852
|
+
};
|
|
1853
|
+
const when = (epoch) => {
|
|
1854
|
+
const date = new Date(epoch);
|
|
1855
|
+
return Number.isNaN(date.getTime()) ? String(epoch) : date.toISOString();
|
|
1856
|
+
};
|
|
1857
|
+
const clockCard = (epoch) => {
|
|
1858
|
+
const date = new Date(epoch);
|
|
1859
|
+
if (Number.isNaN(date.getTime()))
|
|
1860
|
+
return esc(String(epoch));
|
|
1861
|
+
const iso = date.toISOString();
|
|
1862
|
+
return `${esc(iso.slice(0, 10))}<span class="clock-time">${esc(iso.slice(11, 19))} UTC</span>`;
|
|
1863
|
+
};
|
|
1864
|
+
const decodeClock = (value) => {
|
|
1865
|
+
if (!isRecord2(value) || typeof value.now !== "number" || typeof value.offsetMs !== "number" || typeof value.frozen !== "boolean") {
|
|
1866
|
+
throw new Error("Clock response was not a clock");
|
|
1867
|
+
}
|
|
1868
|
+
return { now: value.now, offsetMs: value.offsetMs, frozen: value.frozen };
|
|
1869
|
+
};
|
|
1870
|
+
const decodeField = (value) => {
|
|
1871
|
+
if (!isRecord2(value) || typeof value.name !== "string" || !isFieldKind(value.kind)) {
|
|
1872
|
+
return void 0;
|
|
1873
|
+
}
|
|
1874
|
+
const field = {
|
|
1875
|
+
name: value.name,
|
|
1876
|
+
kind: value.kind,
|
|
1877
|
+
optional: value.optional === true
|
|
1878
|
+
};
|
|
1879
|
+
if (typeof value.description === "string")
|
|
1880
|
+
field.description = value.description;
|
|
1881
|
+
if (Array.isArray(value.fields)) {
|
|
1882
|
+
field.fields = value.fields.flatMap((item) => {
|
|
1883
|
+
const child = decodeField(item);
|
|
1884
|
+
return child === void 0 ? [] : [child];
|
|
1885
|
+
});
|
|
1886
|
+
}
|
|
1887
|
+
return field;
|
|
1888
|
+
};
|
|
1889
|
+
const decodeCollection = (value) => {
|
|
1890
|
+
if (!isRecord2(value) || typeof value.name !== "string")
|
|
1891
|
+
return void 0;
|
|
1892
|
+
const fields = Array.isArray(value.fields) ? value.fields.flatMap((item) => {
|
|
1893
|
+
const field = decodeField(item);
|
|
1894
|
+
return field === void 0 ? [] : [field];
|
|
1895
|
+
}) : [];
|
|
1896
|
+
const collection = {
|
|
1897
|
+
name: value.name,
|
|
1898
|
+
label: typeof value.label === "string" ? value.label : value.name,
|
|
1899
|
+
count: typeof value.count === "number" ? value.count : 0,
|
|
1900
|
+
source: isSource(value.source) ? value.source : "inferred",
|
|
1901
|
+
fields
|
|
1902
|
+
};
|
|
1903
|
+
if (typeof value.description === "string")
|
|
1904
|
+
collection.description = value.description;
|
|
1905
|
+
return collection;
|
|
1906
|
+
};
|
|
1907
|
+
const decodeState = (value) => {
|
|
1908
|
+
if (!isRecord2(value) || !Array.isArray(value.collections)) {
|
|
1909
|
+
throw new Error("State response has no collection list");
|
|
1910
|
+
}
|
|
1911
|
+
return {
|
|
1912
|
+
namespace: typeof value.namespace === "string" ? value.namespace : state.namespace,
|
|
1913
|
+
storageNamespace: typeof value.storageNamespace === "string" ? value.storageNamespace : "",
|
|
1914
|
+
collections: value.collections.flatMap((item) => {
|
|
1915
|
+
const collection = decodeCollection(item);
|
|
1916
|
+
return collection === void 0 ? [] : [collection];
|
|
1917
|
+
})
|
|
1918
|
+
};
|
|
1919
|
+
};
|
|
1920
|
+
const decodeRecords = (value) => requireList(isRecord2(value) ? value.records : void 0, "Records").flatMap((item) => {
|
|
1921
|
+
if (!isRecord2(item) || typeof item.id !== "string")
|
|
1922
|
+
return [];
|
|
1923
|
+
return [
|
|
1924
|
+
{
|
|
1925
|
+
id: item.id,
|
|
1926
|
+
seq: typeof item.seq === "number" ? item.seq : 0,
|
|
1927
|
+
value: item.value,
|
|
1928
|
+
attrs: ` class="clickable" data-id="${esc(item.id)}"`
|
|
1929
|
+
}
|
|
1930
|
+
];
|
|
1931
|
+
});
|
|
1932
|
+
const textOf = (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : "";
|
|
1933
|
+
const decodeJournal = (value) => requireList(isRecord2(value) ? value.requests : void 0, "Journal").flatMap((item) => {
|
|
1934
|
+
if (!isRecord2(item))
|
|
1935
|
+
return [];
|
|
1936
|
+
return [
|
|
1937
|
+
{
|
|
1938
|
+
at: textOf(item.at),
|
|
1939
|
+
method: textOf(item.method),
|
|
1940
|
+
path: textOf(item.path),
|
|
1941
|
+
status: textOf(item.status),
|
|
1942
|
+
durationMs: textOf(item.durationMs),
|
|
1943
|
+
operationId: textOf(item.operationId)
|
|
1944
|
+
}
|
|
1945
|
+
];
|
|
1946
|
+
});
|
|
1947
|
+
const decodeFaults = (value) => requireList(isRecord2(value) ? value.faults : void 0, "Faults").flatMap((item) => {
|
|
1948
|
+
if (!isRecord2(item))
|
|
1949
|
+
return [];
|
|
1950
|
+
return [
|
|
1951
|
+
{
|
|
1952
|
+
id: textOf(item.id),
|
|
1953
|
+
method: typeof item.method === "string" ? item.method : void 0,
|
|
1954
|
+
pathPrefix: typeof item.pathPrefix === "string" ? item.pathPrefix : void 0,
|
|
1955
|
+
operationId: typeof item.operationId === "string" ? item.operationId : void 0,
|
|
1956
|
+
status: typeof item.status === "number" ? item.status : void 0,
|
|
1957
|
+
effect: typeof item.effect === "string" ? item.effect : void 0,
|
|
1958
|
+
drop: typeof item.drop === "boolean" ? item.drop : void 0,
|
|
1959
|
+
latencyMs: typeof item.latencyMs === "number" ? item.latencyMs : void 0
|
|
1960
|
+
}
|
|
1961
|
+
];
|
|
1962
|
+
});
|
|
1963
|
+
const loadNamespaces = async () => {
|
|
1964
|
+
const data = await api("GET", "/namespaces");
|
|
1965
|
+
const select = el("namespace", HTMLSelectElement);
|
|
1966
|
+
const listed = requireList(isRecord2(data) ? data.namespaces : void 0, "Namespaces");
|
|
1967
|
+
const fallback = isRecord2(data) && typeof data.default === "string" && data.default !== "" ? data.default : "default";
|
|
1968
|
+
const names = (listed.length > 0 ? listed.map((name) => String(name)) : [fallback]).slice();
|
|
1969
|
+
if (!names.includes(state.namespace))
|
|
1970
|
+
names.unshift(state.namespace);
|
|
1971
|
+
select.innerHTML = names.map((name) => `<option value="${esc(name)}">${esc(name)}</option>`).join("");
|
|
1972
|
+
select.value = state.namespace;
|
|
1973
|
+
};
|
|
1974
|
+
const renderOverview = async () => {
|
|
1975
|
+
const [health, shape, clock, journal] = await Promise.all([
|
|
1976
|
+
originGet("/health"),
|
|
1977
|
+
api("GET", "/state"),
|
|
1978
|
+
api("GET", "/clock"),
|
|
1979
|
+
api("GET", "/requests?limit=8")
|
|
1980
|
+
]);
|
|
1981
|
+
if (!isRecord2(health))
|
|
1982
|
+
throw new Error("Health response was not an object");
|
|
1983
|
+
const decoded = decodeState(shape);
|
|
1984
|
+
state.shape = decoded;
|
|
1985
|
+
const time = decodeClock(clock);
|
|
1986
|
+
el("overview-cards", HTMLElement).innerHTML = cards([
|
|
1987
|
+
{
|
|
1988
|
+
k: "Service",
|
|
1989
|
+
v: esc(typeof health.service === "string" && health.service !== "" ? health.service : config.service)
|
|
1990
|
+
},
|
|
1991
|
+
{
|
|
1992
|
+
k: "Status",
|
|
1993
|
+
v: esc(typeof health.status === "string" && health.status !== "" ? health.status : "ok")
|
|
1994
|
+
},
|
|
1995
|
+
{ k: "Namespace", v: esc(state.namespace) },
|
|
1996
|
+
{ k: "Collections", v: String(decoded.collections.length) },
|
|
1997
|
+
{
|
|
1998
|
+
k: "Records",
|
|
1999
|
+
v: String(decoded.collections.reduce((sum, item) => sum + item.count, 0))
|
|
2000
|
+
},
|
|
2001
|
+
{ k: "Clock", v: clockCard(time.now) }
|
|
2002
|
+
]);
|
|
2003
|
+
el("overview-requests", HTMLElement).innerHTML = table([
|
|
2004
|
+
{ label: "Method", cell: (row) => esc(row.method) },
|
|
2005
|
+
{ label: "Path", cell: (row) => esc(row.path) },
|
|
2006
|
+
{
|
|
2007
|
+
label: "Status",
|
|
2008
|
+
cell: (row) => `<span class="status-${row.status.charAt(0)}">${esc(row.status)}</span>`
|
|
2009
|
+
},
|
|
2010
|
+
{ label: "Operation", cell: (row) => esc(row.operationId) }
|
|
2011
|
+
], decodeJournal(journal));
|
|
2012
|
+
};
|
|
2013
|
+
const schemaChips = (collection) => {
|
|
2014
|
+
if (collection.fields.length === 0) {
|
|
2015
|
+
return '<p class="empty">No fields yet. Add a record or declare the collection on the service.</p>';
|
|
2016
|
+
}
|
|
2017
|
+
return `<div class="chips">${collection.fields.map((field) => `<span class="chip">${esc(field.name)} <i>${esc(field.kind)}${field.optional ? "?" : ""}</i></span>`).join("")}</div>`;
|
|
2018
|
+
};
|
|
2019
|
+
const renderState = async () => {
|
|
2020
|
+
const shape = decodeState(await api("GET", "/state"));
|
|
2021
|
+
state.shape = shape;
|
|
2022
|
+
const host = el("collections", HTMLElement);
|
|
2023
|
+
if (shape.collections.length === 0) {
|
|
2024
|
+
host.innerHTML = '<p class="empty">This namespace has no collections yet.</p>';
|
|
2025
|
+
el("schema", HTMLElement).innerHTML = "";
|
|
2026
|
+
el("records", HTMLElement).innerHTML = "";
|
|
2027
|
+
return;
|
|
2028
|
+
}
|
|
2029
|
+
if (!shape.collections.some((item) => item.name === state.collection)) {
|
|
2030
|
+
const first = shape.collections[0];
|
|
2031
|
+
if (first === void 0)
|
|
2032
|
+
return;
|
|
2033
|
+
state.collection = first.name;
|
|
2034
|
+
}
|
|
2035
|
+
host.innerHTML = shape.collections.map((item) => `<button type="button" class="collection" data-collection="${esc(item.name)}" aria-current="${item.name === state.collection ? "true" : "false"}"><strong>${esc(item.label)}</strong><small>${esc(item.count)} \xB7 ${esc(item.source)}</small></button>`).join("");
|
|
2036
|
+
const selected = shape.collections.find((item) => item.name === state.collection);
|
|
2037
|
+
if (selected === void 0)
|
|
2038
|
+
return;
|
|
2039
|
+
const description = selected.description ? `<p class="lede">${esc(selected.description)}</p>` : "";
|
|
2040
|
+
el("schema", HTMLElement).innerHTML = `<h3>${esc(selected.label)}</h3>${description}${schemaChips(selected)}`;
|
|
2041
|
+
const page = await api("GET", `/state/${encodeURIComponent(state.collection)}?limit=50`);
|
|
2042
|
+
el("records", HTMLElement).innerHTML = table([
|
|
2043
|
+
{ label: "Id", cell: (row) => `<code>${esc(row.id)}</code>` },
|
|
2044
|
+
{ label: "Seq", cell: (row) => esc(row.seq) },
|
|
2045
|
+
{ label: "Value", cell: (row) => preview(row.value) }
|
|
2046
|
+
], decodeRecords(page));
|
|
2047
|
+
};
|
|
2048
|
+
const renderClock = async () => {
|
|
2049
|
+
const clock = decodeClock(await api("GET", "/clock"));
|
|
2050
|
+
el("clock-readout", HTMLElement).innerHTML = `<div class="k">Now</div><div class="v">${esc(when(clock.now))}</div><p>${esc(clock.now)} ms \xB7 offset ${esc(clock.offsetMs)} ms ${clock.frozen ? "<span class='badge warn'>frozen</span>" : "<span class='badge ok'>live</span>"}</p>`;
|
|
2051
|
+
const freeze = el("freeze", HTMLButtonElement);
|
|
2052
|
+
freeze.textContent = clock.frozen ? "Unfreeze" : "Freeze";
|
|
2053
|
+
freeze.dataset.frozen = clock.frozen ? "1" : "0";
|
|
2054
|
+
};
|
|
2055
|
+
const renderFaults = async () => {
|
|
2056
|
+
const [faults, presets] = await Promise.all([
|
|
2057
|
+
api("GET", "/faults"),
|
|
2058
|
+
api("GET", "/faults/presets").catch(() => ({ presets: [] }))
|
|
2059
|
+
]);
|
|
2060
|
+
const select = el("fault-preset", HTMLSelectElement);
|
|
2061
|
+
const current = select.value;
|
|
2062
|
+
const list = faultPresetList(presets).presets;
|
|
2063
|
+
select.innerHTML = `<option value="">Custom rule</option>${list.map((preset) => `<option value="${esc(preset.name)}">${esc(preset.name)}</option>`).join("")}`;
|
|
2064
|
+
select.value = current;
|
|
2065
|
+
el("fault-list", HTMLElement).innerHTML = table([
|
|
2066
|
+
{ label: "Id", cell: (row) => esc(row.id) },
|
|
2067
|
+
{
|
|
2068
|
+
label: "Match",
|
|
2069
|
+
cell: (row) => esc([row.method, row.pathPrefix, row.operationId].filter((part) => Boolean(part)).join(" ") || "all")
|
|
2070
|
+
},
|
|
2071
|
+
{
|
|
2072
|
+
label: "Effect",
|
|
2073
|
+
cell: (row) => esc(row.status ?? row.effect ?? (row.drop ? "drop" : row.latencyMs || ""))
|
|
2074
|
+
}
|
|
2075
|
+
], decodeFaults(faults));
|
|
2076
|
+
};
|
|
2077
|
+
const renderJournal = async () => {
|
|
2078
|
+
const journal = await api("GET", "/requests?limit=100");
|
|
2079
|
+
el("journal", HTMLElement).innerHTML = table([
|
|
2080
|
+
{ label: "When", cell: (row) => esc(row.at) },
|
|
2081
|
+
{ label: "Method", cell: (row) => esc(row.method) },
|
|
2082
|
+
{ label: "Path", cell: (row) => esc(row.path) },
|
|
2083
|
+
{ label: "Status", cell: (row) => esc(row.status) },
|
|
2084
|
+
{ label: "ms", cell: (row) => esc(row.durationMs) }
|
|
2085
|
+
], decodeJournal(journal));
|
|
2086
|
+
};
|
|
2087
|
+
const renderRoutes = async () => {
|
|
2088
|
+
const data = await api("GET", "/");
|
|
2089
|
+
if (!isRecord2(data))
|
|
2090
|
+
throw new Error("Route list was not an object");
|
|
2091
|
+
const routes = requireList(data.routes, "Routes").map((route) => String(route));
|
|
2092
|
+
el("route-list", HTMLElement).innerHTML = routes.map((route) => {
|
|
2093
|
+
const extra = standard.has(route) ? "" : " <span class='badge'>extension</span>";
|
|
2094
|
+
const parts = route.split(" ");
|
|
2095
|
+
const method = parts[0] ?? "";
|
|
2096
|
+
const path = parts.slice(1).join(" ");
|
|
2097
|
+
return `<div class="route"><span class="method">${esc(method)}</span><span>${esc(path)}${extra}</span><button class="btn" type="button" data-route="${esc(route)}">Use</button></div>`;
|
|
2098
|
+
}).join("");
|
|
2099
|
+
};
|
|
2100
|
+
const renderers = {
|
|
2101
|
+
overview: renderOverview,
|
|
2102
|
+
state: renderState,
|
|
2103
|
+
clock: renderClock,
|
|
2104
|
+
faults: renderFaults,
|
|
2105
|
+
journal: renderJournal,
|
|
2106
|
+
routes: renderRoutes
|
|
2107
|
+
};
|
|
2108
|
+
async function refresh() {
|
|
2109
|
+
clearError();
|
|
2110
|
+
const render2 = renderers[state.view];
|
|
2111
|
+
if (render2)
|
|
2112
|
+
await render2();
|
|
2113
|
+
}
|
|
2114
|
+
el("namespace", HTMLSelectElement).addEventListener("change", () => {
|
|
2115
|
+
state.namespace = el("namespace", HTMLSelectElement).value;
|
|
2116
|
+
refresh().catch(showError);
|
|
2117
|
+
});
|
|
2118
|
+
keyInput.addEventListener("change", () => {
|
|
2119
|
+
state.key = keyInput.value.trim();
|
|
2120
|
+
sessionStorage.setItem("mockingbird-admin-key", state.key);
|
|
2121
|
+
refresh().catch(showError);
|
|
2122
|
+
});
|
|
2123
|
+
el("refresh", HTMLButtonElement).addEventListener("click", () => {
|
|
2124
|
+
refresh().catch(showError);
|
|
2125
|
+
});
|
|
2126
|
+
el("collections", HTMLElement).addEventListener("click", (event) => {
|
|
2127
|
+
const target = event.target;
|
|
2128
|
+
if (!(target instanceof Element))
|
|
2129
|
+
return;
|
|
2130
|
+
const button = target.closest("[data-collection]");
|
|
2131
|
+
if (!(button instanceof HTMLElement))
|
|
2132
|
+
return;
|
|
2133
|
+
const collection = button.dataset.collection;
|
|
2134
|
+
if (collection === void 0)
|
|
2135
|
+
return;
|
|
2136
|
+
state.collection = collection;
|
|
2137
|
+
renderState().catch(showError);
|
|
2138
|
+
});
|
|
2139
|
+
el("records", HTMLElement).addEventListener("click", (event) => {
|
|
2140
|
+
const target = event.target;
|
|
2141
|
+
if (!(target instanceof Element))
|
|
2142
|
+
return;
|
|
2143
|
+
const row = target.closest("[data-id]");
|
|
2144
|
+
if (!(row instanceof HTMLElement))
|
|
2145
|
+
return;
|
|
2146
|
+
const id = row.dataset.id;
|
|
2147
|
+
if (id === void 0)
|
|
2148
|
+
return;
|
|
2149
|
+
openEditor(id).catch(showError);
|
|
2150
|
+
});
|
|
2151
|
+
const editor = el("editor", HTMLDialogElement);
|
|
2152
|
+
const editorId = el("editor-id", HTMLInputElement);
|
|
2153
|
+
const editorValue = el("editor-value", HTMLTextAreaElement);
|
|
2154
|
+
const editorDelete = el("editor-delete", HTMLButtonElement);
|
|
2155
|
+
async function openEditor(id) {
|
|
2156
|
+
state.editing = id;
|
|
2157
|
+
el("editor-title", HTMLElement).textContent = id ? "Edit record" : "New record";
|
|
2158
|
+
editorId.value = id ?? "";
|
|
2159
|
+
editorId.readOnly = id !== null;
|
|
2160
|
+
editorDelete.hidden = id === null;
|
|
2161
|
+
if (id) {
|
|
2162
|
+
const record = await api("GET", `/state/${encodeURIComponent(state.collection)}/${encodeURIComponent(id)}`);
|
|
2163
|
+
if (!isRecord2(record))
|
|
2164
|
+
throw new Error("Record response was not an object");
|
|
2165
|
+
editorValue.value = JSON.stringify(record.value, null, 2) ?? "";
|
|
2166
|
+
} else {
|
|
2167
|
+
editorValue.value = "{\n \n}";
|
|
2168
|
+
}
|
|
2169
|
+
editor.showModal();
|
|
2170
|
+
}
|
|
2171
|
+
el("new-record", HTMLButtonElement).addEventListener("click", () => {
|
|
2172
|
+
openEditor(null).catch(showError);
|
|
2173
|
+
});
|
|
2174
|
+
el("editor-form", HTMLFormElement).addEventListener("submit", (event) => {
|
|
2175
|
+
const submitter = event.submitter;
|
|
2176
|
+
if (!(submitter instanceof HTMLButtonElement) || submitter.value !== "save")
|
|
2177
|
+
return;
|
|
2178
|
+
event.preventDefault();
|
|
2179
|
+
let value;
|
|
2180
|
+
try {
|
|
2181
|
+
value = readJson3(editorValue.value);
|
|
2182
|
+
} catch {
|
|
2183
|
+
showError(new Error("Value is not JSON"));
|
|
2184
|
+
return;
|
|
2185
|
+
}
|
|
2186
|
+
const id = editorId.value.trim();
|
|
2187
|
+
const path = `/state/${encodeURIComponent(state.collection)}`;
|
|
2188
|
+
const request2 = state.editing ? api("PUT", `${path}/${encodeURIComponent(id)}`, { value }) : api("POST", path, { id: id || void 0, value });
|
|
2189
|
+
request2.then(() => {
|
|
2190
|
+
editor.close();
|
|
2191
|
+
return renderState();
|
|
2192
|
+
}).catch(showError);
|
|
2193
|
+
});
|
|
2194
|
+
editorDelete.addEventListener("click", () => {
|
|
2195
|
+
const id = state.editing;
|
|
2196
|
+
if (!id)
|
|
2197
|
+
return;
|
|
2198
|
+
api("DELETE", `/state/${encodeURIComponent(state.collection)}/${encodeURIComponent(id)}`).then(() => {
|
|
2199
|
+
editor.close();
|
|
2200
|
+
return renderState();
|
|
2201
|
+
}).catch(showError);
|
|
2202
|
+
});
|
|
2203
|
+
for (const button of document.querySelectorAll("[data-advance]")) {
|
|
2204
|
+
if (!(button instanceof HTMLButtonElement))
|
|
2205
|
+
continue;
|
|
2206
|
+
button.addEventListener("click", () => {
|
|
2207
|
+
const raw = button.dataset.advance;
|
|
2208
|
+
if (raw === void 0)
|
|
2209
|
+
return;
|
|
2210
|
+
api("POST", "/clock", { advance: Number(raw) }).then(() => renderClock()).catch(showError);
|
|
2211
|
+
});
|
|
2212
|
+
}
|
|
2213
|
+
el("freeze", HTMLButtonElement).addEventListener("click", () => {
|
|
2214
|
+
const frozen = el("freeze", HTMLButtonElement).dataset.frozen === "1";
|
|
2215
|
+
api("POST", "/clock", { freeze: !frozen }).then(() => renderClock()).catch(showError);
|
|
2216
|
+
});
|
|
2217
|
+
el("clock-reset", HTMLButtonElement).addEventListener("click", () => {
|
|
2218
|
+
api("POST", "/clock", { reset: true }).then(() => renderClock()).catch(showError);
|
|
2219
|
+
});
|
|
2220
|
+
el("clock-set", HTMLFormElement).addEventListener("submit", (event) => {
|
|
2221
|
+
event.preventDefault();
|
|
2222
|
+
const raw = el("clock-instant", HTMLInputElement).value.trim();
|
|
2223
|
+
const set = /^-?\d+$/.test(raw) ? Number(raw) : raw;
|
|
2224
|
+
api("POST", "/clock", { set }).then(() => renderClock()).catch(showError);
|
|
2225
|
+
});
|
|
2226
|
+
el("fault-form", HTMLFormElement).addEventListener("submit", (event) => {
|
|
2227
|
+
event.preventDefault();
|
|
2228
|
+
const preset = el("fault-preset", HTMLSelectElement).value;
|
|
2229
|
+
if (preset !== "") {
|
|
2230
|
+
api("POST", "/faults", { preset }).then(() => renderFaults()).catch(showError);
|
|
2231
|
+
return;
|
|
2232
|
+
}
|
|
2233
|
+
const status = Number(el("fault-status", HTMLInputElement).value);
|
|
2234
|
+
if (!Number.isFinite(status)) {
|
|
2235
|
+
showError(new Error("Status must be a number, or choose a preset"));
|
|
2236
|
+
return;
|
|
2237
|
+
}
|
|
2238
|
+
const path = el("fault-path", HTMLInputElement).value;
|
|
2239
|
+
const method = el("fault-method", HTMLInputElement).value;
|
|
2240
|
+
api("POST", "/faults", {
|
|
2241
|
+
status,
|
|
2242
|
+
...path !== "" ? { pathPrefix: path } : {},
|
|
2243
|
+
...method !== "" ? { method } : {}
|
|
2244
|
+
}).then(() => renderFaults()).catch(showError);
|
|
2245
|
+
});
|
|
2246
|
+
el("fault-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2247
|
+
api("DELETE", "/faults").then(() => renderFaults()).catch(showError);
|
|
2248
|
+
});
|
|
2249
|
+
el("journal-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2250
|
+
api("DELETE", "/requests").then(() => renderJournal()).catch(showError);
|
|
2251
|
+
});
|
|
2252
|
+
el("route-list", HTMLElement).addEventListener("click", (event) => {
|
|
2253
|
+
const target = event.target;
|
|
2254
|
+
if (!(target instanceof Element))
|
|
2255
|
+
return;
|
|
2256
|
+
const button = target.closest("[data-route]");
|
|
2257
|
+
if (!(button instanceof HTMLElement))
|
|
2258
|
+
return;
|
|
2259
|
+
const route = button.dataset.route;
|
|
2260
|
+
if (route === void 0)
|
|
2261
|
+
return;
|
|
2262
|
+
state.route = route;
|
|
2263
|
+
el("route-title", HTMLElement).textContent = route;
|
|
2264
|
+
const method = route.split(" ")[0] ?? "";
|
|
2265
|
+
el("route-body", HTMLTextAreaElement).disabled = method === "GET" || method === "DELETE";
|
|
2266
|
+
});
|
|
2267
|
+
el("route-form", HTMLFormElement).addEventListener("submit", (event) => {
|
|
2268
|
+
event.preventDefault();
|
|
2269
|
+
const send = async () => {
|
|
2270
|
+
if (state.route === null)
|
|
2271
|
+
throw new Error("Choose a route first");
|
|
2272
|
+
const parts = state.route.split(" ");
|
|
2273
|
+
const method = parts[0];
|
|
2274
|
+
const path = parts.slice(1).join(" ");
|
|
2275
|
+
if (method === void 0)
|
|
2276
|
+
throw new Error("Choose a route first");
|
|
2277
|
+
const concrete = path.replace(/:([A-Za-z0-9_]+)/g, (_match, key) => prompt(`Value for ${key}`) || "");
|
|
2278
|
+
let body;
|
|
2279
|
+
const routeBody = el("route-body", HTMLTextAreaElement);
|
|
2280
|
+
if (method !== "GET" && method !== "DELETE" && routeBody.value.trim() !== "") {
|
|
2281
|
+
try {
|
|
2282
|
+
body = readJson3(routeBody.value);
|
|
2283
|
+
} catch {
|
|
2284
|
+
throw new Error("Body is not JSON");
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
const data = await api(method, concrete, body);
|
|
2288
|
+
el("route-result", HTMLElement).textContent = JSON.stringify(data, null, 2);
|
|
2289
|
+
};
|
|
2290
|
+
send().catch(showError);
|
|
2291
|
+
});
|
|
2292
|
+
const decodePanel = (value) => {
|
|
2293
|
+
if (!isRecord2(value) || typeof value.id !== "string" || typeof value.title !== "string") {
|
|
2294
|
+
return void 0;
|
|
2295
|
+
}
|
|
2296
|
+
const panel = {
|
|
2297
|
+
id: value.id,
|
|
2298
|
+
title: value.title,
|
|
2299
|
+
description: typeof value.description === "string" ? value.description : "",
|
|
2300
|
+
html: typeof value.html === "string" ? value.html : ""
|
|
2301
|
+
};
|
|
2302
|
+
if (typeof value.script === "string")
|
|
2303
|
+
panel.script = value.script;
|
|
2304
|
+
return panel;
|
|
2305
|
+
};
|
|
2306
|
+
const mountPanels = (panels) => {
|
|
2307
|
+
const nav = el("nav", HTMLElement);
|
|
2308
|
+
const views = el("views", HTMLElement);
|
|
2309
|
+
for (const panel of panels) {
|
|
2310
|
+
const button = document.createElement("button");
|
|
2311
|
+
button.type = "button";
|
|
2312
|
+
button.dataset.view = panel.id;
|
|
2313
|
+
button.textContent = panel.title;
|
|
2314
|
+
nav.append(button);
|
|
2315
|
+
const section = document.createElement("section");
|
|
2316
|
+
section.className = "view";
|
|
2317
|
+
section.id = `view-${panel.id}`;
|
|
2318
|
+
section.hidden = true;
|
|
2319
|
+
const title = document.createElement("h2");
|
|
2320
|
+
title.textContent = panel.title;
|
|
2321
|
+
const lede = document.createElement("p");
|
|
2322
|
+
lede.className = "lede";
|
|
2323
|
+
lede.textContent = panel.description;
|
|
2324
|
+
const body = document.createElement("div");
|
|
2325
|
+
body.className = "panel-body";
|
|
2326
|
+
body.id = `panel-${panel.id}`;
|
|
2327
|
+
body.innerHTML = panel.html;
|
|
2328
|
+
section.append(title, lede, body);
|
|
2329
|
+
views.append(section);
|
|
2330
|
+
if (panel.script === void 0)
|
|
2331
|
+
continue;
|
|
2332
|
+
try {
|
|
2333
|
+
const compiled = new Function("root", "api", panel.script);
|
|
2334
|
+
if (!isPanelScript(compiled))
|
|
2335
|
+
throw new Error("panel script did not compile");
|
|
2336
|
+
compiled(body, panelApi);
|
|
2337
|
+
} catch (error) {
|
|
2338
|
+
const note = document.createElement("p");
|
|
2339
|
+
note.className = "banner show";
|
|
2340
|
+
note.textContent = error instanceof Error ? error.message : String(error);
|
|
2341
|
+
body.append(note);
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
};
|
|
2345
|
+
startAdminBrand({
|
|
2346
|
+
document,
|
|
2347
|
+
$: (id) => document.getElementById(id),
|
|
2348
|
+
params,
|
|
2349
|
+
location: { href: location.href, origin: location.origin },
|
|
2350
|
+
fetch,
|
|
2351
|
+
brandsUrl: config.brandsUrl
|
|
2352
|
+
});
|
|
2353
|
+
loadNamespaces().then(() => api("GET", "/ui/manifest")).then((manifest) => {
|
|
2354
|
+
const panels = requireList(isRecord2(manifest) ? manifest.panels : void 0, "Panels").flatMap((panel) => {
|
|
2355
|
+
const decoded = decodePanel(panel);
|
|
2356
|
+
return decoded === void 0 ? [] : [decoded];
|
|
2357
|
+
});
|
|
2358
|
+
mountPanels(panels);
|
|
2359
|
+
return refresh();
|
|
2360
|
+
}).catch(showError);
|
|
2361
|
+
}
|
|
2362
|
+
var clientPrelude = [isRecord2, mountAdminBrand, startAdminBrand, faultPresetList, bootAdmin].map((fn) => fn.toString()).join("\n");
|
|
2363
|
+
var adminClientSource = (config) => {
|
|
2364
|
+
const payload = JSON.stringify(config).replace(/</g, "\\u003c");
|
|
2365
|
+
return `<script>
|
|
2366
|
+
${clientPrelude}
|
|
2367
|
+
bootAdmin(${payload});
|
|
2368
|
+
</script>`;
|
|
2369
|
+
};
|
|
2370
|
+
|
|
1145
2371
|
// ../core/dist/surface.js
|
|
1146
2372
|
var defineMock = (runtime) => runtime;
|
|
1147
2373
|
var STANDARD_ADMIN_ROUTES = [
|
|
@@ -1210,94 +2436,106 @@ var escapeHtml = (value) => value.replace(/[&<>"']/g, (char) => {
|
|
|
1210
2436
|
return "'";
|
|
1211
2437
|
}
|
|
1212
2438
|
});
|
|
2439
|
+
var ADMIN_BRANDS_URL = "https://mockingbird.chrisvouga.dev/brands.json";
|
|
1213
2440
|
var renderAdminDocument = (service) => {
|
|
1214
2441
|
const name = escapeHtml(service);
|
|
1215
|
-
const
|
|
2442
|
+
const script = adminClientSource({
|
|
2443
|
+
standardRoutes: STANDARD_ADMIN_ROUTES,
|
|
2444
|
+
adminPrefix: ADMIN_PREFIX,
|
|
2445
|
+
adminKeyHeader: ADMIN_KEY_HEADER,
|
|
2446
|
+
brandsUrl: ADMIN_BRANDS_URL,
|
|
2447
|
+
service
|
|
2448
|
+
});
|
|
1216
2449
|
return `<!DOCTYPE html>
|
|
1217
2450
|
<html lang="en">
|
|
1218
2451
|
<head>
|
|
1219
2452
|
<meta charset="utf-8">
|
|
1220
2453
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
1221
2454
|
<meta name="color-scheme" content="light dark">
|
|
1222
|
-
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='
|
|
2455
|
+
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='2' fill='%2327272a'/%3E%3C/svg%3E">
|
|
1223
2456
|
<title>${name} admin</title>
|
|
1224
2457
|
<style>
|
|
2458
|
+
${CSS_RESET}
|
|
1225
2459
|
:root {
|
|
1226
2460
|
color-scheme: light;
|
|
1227
|
-
--bg: #
|
|
2461
|
+
--bg: #fafafa;
|
|
1228
2462
|
--bg-elev: #ffffff;
|
|
1229
|
-
--bg-muted: #
|
|
1230
|
-
--bg-inset: #
|
|
1231
|
-
--line: #
|
|
1232
|
-
--line-strong: #
|
|
1233
|
-
--ink: #
|
|
1234
|
-
--muted: #
|
|
1235
|
-
--faint: #
|
|
1236
|
-
--accent: #
|
|
1237
|
-
--accent-ink: #
|
|
1238
|
-
--accent-soft: #
|
|
1239
|
-
--ok: #
|
|
1240
|
-
--ok-soft: #
|
|
1241
|
-
--warn: #
|
|
1242
|
-
--warn-soft: #
|
|
1243
|
-
--err: #
|
|
1244
|
-
--err-soft: #
|
|
1245
|
-
--shadow:
|
|
1246
|
-
--sans: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
2463
|
+
--bg-muted: #f4f4f5;
|
|
2464
|
+
--bg-inset: #f4f4f5;
|
|
2465
|
+
--line: #dedee3;
|
|
2466
|
+
--line-strong: #c4c4cc;
|
|
2467
|
+
--ink: #18181b;
|
|
2468
|
+
--muted: #62626b;
|
|
2469
|
+
--faint: #71717a;
|
|
2470
|
+
--accent: #27272a;
|
|
2471
|
+
--accent-ink: #ffffff;
|
|
2472
|
+
--accent-soft: #f4f4f5;
|
|
2473
|
+
--ok: #166534;
|
|
2474
|
+
--ok-soft: #f0fdf4;
|
|
2475
|
+
--warn: #a16207;
|
|
2476
|
+
--warn-soft: #fefce8;
|
|
2477
|
+
--err: #a82d32;
|
|
2478
|
+
--err-soft: #fef2f2;
|
|
2479
|
+
--shadow: none;
|
|
2480
|
+
--sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
1247
2481
|
--mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
|
|
1248
|
-
--radius:
|
|
1249
|
-
--header:
|
|
1250
|
-
--nav:
|
|
2482
|
+
--radius: 10px;
|
|
2483
|
+
--header: 56px;
|
|
2484
|
+
--nav: 200px;
|
|
1251
2485
|
}
|
|
1252
2486
|
:root[data-theme="dark"] {
|
|
1253
2487
|
color-scheme: dark;
|
|
1254
|
-
--bg: #
|
|
1255
|
-
--bg-elev: #
|
|
1256
|
-
--bg-muted: #
|
|
1257
|
-
--bg-inset: #
|
|
1258
|
-
--line: #
|
|
1259
|
-
--line-strong: #
|
|
1260
|
-
--ink: #
|
|
1261
|
-
--muted: #
|
|
1262
|
-
--faint: #
|
|
1263
|
-
--accent: #
|
|
1264
|
-
--accent-ink: #
|
|
1265
|
-
--accent-soft: #
|
|
1266
|
-
--ok: #
|
|
1267
|
-
--ok-soft: #
|
|
1268
|
-
--warn: #
|
|
1269
|
-
--warn-soft: #
|
|
1270
|
-
--err: #
|
|
1271
|
-
--err-soft: #
|
|
1272
|
-
--shadow:
|
|
2488
|
+
--bg: #111113;
|
|
2489
|
+
--bg-elev: #19191c;
|
|
2490
|
+
--bg-muted: #242428;
|
|
2491
|
+
--bg-inset: #111113;
|
|
2492
|
+
--line: #36363c;
|
|
2493
|
+
--line-strong: #52525b;
|
|
2494
|
+
--ink: #f4f4f5;
|
|
2495
|
+
--muted: #a9a9b2;
|
|
2496
|
+
--faint: #71717a;
|
|
2497
|
+
--accent: #e4e4e7;
|
|
2498
|
+
--accent-ink: #18181b;
|
|
2499
|
+
--accent-soft: #242428;
|
|
2500
|
+
--ok: #86efac;
|
|
2501
|
+
--ok-soft: #14241b;
|
|
2502
|
+
--warn: #fde68a;
|
|
2503
|
+
--warn-soft: #2a2410;
|
|
2504
|
+
--err: #ffaaaa;
|
|
2505
|
+
--err-soft: #2c1516;
|
|
2506
|
+
--shadow: none;
|
|
1273
2507
|
}
|
|
1274
2508
|
@media (prefers-color-scheme: dark) {
|
|
1275
2509
|
:root:not([data-theme="light"]) {
|
|
1276
2510
|
color-scheme: dark;
|
|
1277
|
-
--bg: #
|
|
1278
|
-
--bg-elev: #
|
|
1279
|
-
--bg-muted: #
|
|
1280
|
-
--bg-inset: #
|
|
1281
|
-
--line: #
|
|
1282
|
-
--line-strong: #
|
|
1283
|
-
--ink: #
|
|
1284
|
-
--muted: #
|
|
1285
|
-
--faint: #
|
|
1286
|
-
--accent: #
|
|
1287
|
-
--accent-ink: #
|
|
1288
|
-
--accent-soft: #
|
|
1289
|
-
--ok: #
|
|
1290
|
-
--ok-soft: #
|
|
1291
|
-
--warn: #
|
|
1292
|
-
--warn-soft: #
|
|
1293
|
-
--err: #
|
|
1294
|
-
--err-soft: #
|
|
1295
|
-
--shadow:
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
html
|
|
2511
|
+
--bg: #111113;
|
|
2512
|
+
--bg-elev: #19191c;
|
|
2513
|
+
--bg-muted: #242428;
|
|
2514
|
+
--bg-inset: #111113;
|
|
2515
|
+
--line: #36363c;
|
|
2516
|
+
--line-strong: #52525b;
|
|
2517
|
+
--ink: #f4f4f5;
|
|
2518
|
+
--muted: #a9a9b2;
|
|
2519
|
+
--faint: #71717a;
|
|
2520
|
+
--accent: #e4e4e7;
|
|
2521
|
+
--accent-ink: #18181b;
|
|
2522
|
+
--accent-soft: #242428;
|
|
2523
|
+
--ok: #86efac;
|
|
2524
|
+
--ok-soft: #14241b;
|
|
2525
|
+
--warn: #fde68a;
|
|
2526
|
+
--warn-soft: #2a2410;
|
|
2527
|
+
--err: #ffaaaa;
|
|
2528
|
+
--err-soft: #2c1516;
|
|
2529
|
+
--shadow: none;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
/* Fill the viewport, then grow with the content so the background covers the scroll. */
|
|
2533
|
+
html { height: 100%; }
|
|
1300
2534
|
body {
|
|
2535
|
+
margin: 0;
|
|
2536
|
+
min-height: 100%;
|
|
2537
|
+
display: flex;
|
|
2538
|
+
flex-direction: column;
|
|
1301
2539
|
font-family: var(--sans);
|
|
1302
2540
|
background: var(--bg);
|
|
1303
2541
|
color: var(--ink);
|
|
@@ -1306,24 +2544,37 @@ var renderAdminDocument = (service) => {
|
|
|
1306
2544
|
padding-right: env(safe-area-inset-right);
|
|
1307
2545
|
-webkit-text-size-adjust: 100%;
|
|
1308
2546
|
}
|
|
1309
|
-
button, input, select, textarea { font: inherit; color: inherit; }
|
|
1310
|
-
button { cursor: pointer; }
|
|
1311
2547
|
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
1312
|
-
|
|
1313
|
-
* { scroll-behavior: auto !important; transition: none !important; }
|
|
1314
|
-
}
|
|
1315
|
-
.app { min-height: 100%; display: flex; flex-direction: column; }
|
|
2548
|
+
.app { flex: 1 0 auto; display: flex; flex-direction: column; min-width: 0; width: 100%; }
|
|
1316
2549
|
header.top {
|
|
1317
2550
|
position: sticky; top: 0; z-index: 5;
|
|
1318
2551
|
display: flex; align-items: center; gap: 12px;
|
|
1319
2552
|
min-height: var(--header); padding: 10px 16px;
|
|
1320
|
-
background:
|
|
2553
|
+
background: var(--bg-elev);
|
|
1321
2554
|
border-bottom: 1px solid var(--line);
|
|
1322
|
-
|
|
1323
|
-
}
|
|
1324
|
-
.brand {
|
|
1325
|
-
|
|
1326
|
-
|
|
2555
|
+
min-width: 0; max-width: 100%;
|
|
2556
|
+
}
|
|
2557
|
+
.brand {
|
|
2558
|
+
display: flex; flex-flow: row wrap; align-items: center; gap: 14px;
|
|
2559
|
+
min-width: 0; max-width: 100%; margin-right: auto;
|
|
2560
|
+
}
|
|
2561
|
+
.brand-id { display: flex; flex-direction: column; min-width: 0; flex: none; }
|
|
2562
|
+
.brand-id strong { font-size: 15px; letter-spacing: -0.01em; }
|
|
2563
|
+
.brand-id span { color: var(--faint); font-size: 12px; }
|
|
2564
|
+
.vendor {
|
|
2565
|
+
display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
|
|
2566
|
+
min-width: 0; max-width: 100%; font-size: 12px; color: var(--muted);
|
|
2567
|
+
}
|
|
2568
|
+
.vendor[hidden] { display: none; }
|
|
2569
|
+
/* Logos are drawn for a light tile, same as the docs site, so the plate stays white. */
|
|
2570
|
+
.vendor img {
|
|
2571
|
+
width: 16px; height: 16px; padding: 2px; box-sizing: content-box;
|
|
2572
|
+
border-radius: 4px; border: 1px solid var(--line); background: #fff; object-fit: contain;
|
|
2573
|
+
}
|
|
2574
|
+
.vendor-name { color: var(--ink); font-weight: 600; }
|
|
2575
|
+
.vendor-sep { color: var(--faint); }
|
|
2576
|
+
.vendor-link { color: inherit; text-decoration: none; }
|
|
2577
|
+
.vendor-link:hover { color: var(--ink); text-decoration: underline; }
|
|
1327
2578
|
.controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
1328
2579
|
label.field { display: flex; flex-direction: column; gap: 2px; font-size: 11px; color: var(--faint); }
|
|
1329
2580
|
label.field input, label.field select, .controls input[type="password"] {
|
|
@@ -1341,7 +2592,7 @@ var renderAdminDocument = (service) => {
|
|
|
1341
2592
|
record or the full nav row would widen the page past the viewport. */
|
|
1342
2593
|
.layout {
|
|
1343
2594
|
display: grid; grid-template-columns: var(--nav) minmax(0, 1fr);
|
|
1344
|
-
flex: 1
|
|
2595
|
+
flex: 1 0 auto; min-width: 0;
|
|
1345
2596
|
}
|
|
1346
2597
|
nav.side {
|
|
1347
2598
|
border-right: 1px solid var(--line); padding: 12px;
|
|
@@ -1395,8 +2646,8 @@ var renderAdminDocument = (service) => {
|
|
|
1395
2646
|
.banner.show { display: block; }
|
|
1396
2647
|
.empty { color: var(--muted); padding: 24px 8px; }
|
|
1397
2648
|
dialog {
|
|
1398
|
-
border: 1px solid var(--line); border-radius:
|
|
1399
|
-
color: var(--ink); width: min(640px, calc(100vw - 24px)); box-shadow:
|
|
2649
|
+
border: 1px solid var(--line); border-radius: var(--radius); padding: 0; background: var(--bg-elev);
|
|
2650
|
+
color: var(--ink); width: min(640px, calc(100vw - 24px)); box-shadow: none;
|
|
1400
2651
|
}
|
|
1401
2652
|
dialog::backdrop { background: rgb(20 19 17 / 0.45); }
|
|
1402
2653
|
dialog form, .dialog-body { padding: 16px; display: flex; flex-direction: column; gap: 10px; }
|
|
@@ -1423,7 +2674,7 @@ var renderAdminDocument = (service) => {
|
|
|
1423
2674
|
padding-top: max(10px, env(safe-area-inset-top));
|
|
1424
2675
|
}
|
|
1425
2676
|
input, select, textarea { font-size: 16px; }
|
|
1426
|
-
.controls { width: 100%; }
|
|
2677
|
+
.brand, .vendor, .controls { width: 100%; }
|
|
1427
2678
|
label.field, label.field select, label.field input { flex: 1; min-width: 0; }
|
|
1428
2679
|
.layout { grid-template-columns: minmax(0, 1fr); }
|
|
1429
2680
|
nav.side {
|
|
@@ -1454,8 +2705,11 @@ var renderAdminDocument = (service) => {
|
|
|
1454
2705
|
<div class="app" data-service="${name}" data-mockingbird-admin>
|
|
1455
2706
|
<header class="top">
|
|
1456
2707
|
<div class="brand">
|
|
1457
|
-
<
|
|
1458
|
-
|
|
2708
|
+
<div class="brand-id">
|
|
2709
|
+
<strong>${name}</strong>
|
|
2710
|
+
<span>Admin</span>
|
|
2711
|
+
</div>
|
|
2712
|
+
<div class="vendor" id="vendor" hidden></div>
|
|
1459
2713
|
</div>
|
|
1460
2714
|
<div class="controls">
|
|
1461
2715
|
<label class="field">Namespace
|
|
@@ -1585,460 +2839,7 @@ var renderAdminDocument = (service) => {
|
|
|
1585
2839
|
</div>
|
|
1586
2840
|
</form>
|
|
1587
2841
|
</dialog>
|
|
1588
|
-
|
|
1589
|
-
(() => {
|
|
1590
|
-
const STANDARD = new Set(${standard})
|
|
1591
|
-
const state = {
|
|
1592
|
-
namespace: "default",
|
|
1593
|
-
key: sessionStorage.getItem("mockingbird-admin-key") || "",
|
|
1594
|
-
view: "overview",
|
|
1595
|
-
collection: "",
|
|
1596
|
-
shape: null,
|
|
1597
|
-
route: null,
|
|
1598
|
-
editing: null
|
|
1599
|
-
}
|
|
1600
|
-
const $ = (id) => document.getElementById(id)
|
|
1601
|
-
const banner = $("banner")
|
|
1602
|
-
const keyInput = $("admin-key")
|
|
1603
|
-
keyInput.value = state.key
|
|
1604
|
-
const params = new URLSearchParams(location.search)
|
|
1605
|
-
if (params.get("key")) {
|
|
1606
|
-
state.key = params.get("key")
|
|
1607
|
-
keyInput.value = state.key
|
|
1608
|
-
sessionStorage.setItem("mockingbird-admin-key", state.key)
|
|
1609
|
-
params.delete("key")
|
|
1610
|
-
const next = params.toString()
|
|
1611
|
-
history.replaceState(null, "", location.pathname + (next ? "?" + next : ""))
|
|
1612
|
-
}
|
|
1613
|
-
if (params.get("namespace")) state.namespace = params.get("namespace")
|
|
1614
|
-
|
|
1615
|
-
const showError = (error) => {
|
|
1616
|
-
banner.textContent = error instanceof Error ? error.message : String(error)
|
|
1617
|
-
banner.classList.add("show")
|
|
1618
|
-
}
|
|
1619
|
-
const clearError = () => banner.classList.remove("show")
|
|
1620
|
-
|
|
1621
|
-
async function originGet(path) {
|
|
1622
|
-
const response = await fetch(path, { headers: { accept: "application/json" } })
|
|
1623
|
-
if (!response.ok) throw new Error(response.status + " " + path)
|
|
1624
|
-
return response.json()
|
|
1625
|
-
}
|
|
1626
|
-
async function api(method, path, body) {
|
|
1627
|
-
const headers = { accept: "application/json" }
|
|
1628
|
-
if (state.key) headers["${ADMIN_KEY_HEADER}"] = state.key
|
|
1629
|
-
if (state.namespace) headers["x-mockingbird-namespace"] = state.namespace
|
|
1630
|
-
if (body !== undefined) headers["content-type"] = "application/json"
|
|
1631
|
-
const response = await fetch("${ADMIN_PREFIX}" + path, {
|
|
1632
|
-
method,
|
|
1633
|
-
headers,
|
|
1634
|
-
body: body === undefined ? undefined : JSON.stringify(body)
|
|
1635
|
-
})
|
|
1636
|
-
const text = await response.text()
|
|
1637
|
-
let data = null
|
|
1638
|
-
if (text) {
|
|
1639
|
-
try { data = JSON.parse(text) } catch { data = { raw: text } }
|
|
1640
|
-
}
|
|
1641
|
-
if (response.status === 401) {
|
|
1642
|
-
keyInput.focus()
|
|
1643
|
-
throw new Error((data && data.error && data.error.message) || "Admin key required")
|
|
1644
|
-
}
|
|
1645
|
-
if (!response.ok) {
|
|
1646
|
-
throw new Error((data && data.error && data.error.message) || (response.status + " " + method + " " + path))
|
|
1647
|
-
}
|
|
1648
|
-
return data
|
|
1649
|
-
}
|
|
1650
|
-
const panelApi = {
|
|
1651
|
-
get: (path) => api("GET", path),
|
|
1652
|
-
send: (method, path, body) => api(method, path, body),
|
|
1653
|
-
namespace: () => state.namespace
|
|
1654
|
-
}
|
|
1655
|
-
|
|
1656
|
-
function setTheme(theme) {
|
|
1657
|
-
if (theme) document.documentElement.dataset.theme = theme
|
|
1658
|
-
else delete document.documentElement.dataset.theme
|
|
1659
|
-
}
|
|
1660
|
-
const storedTheme = localStorage.getItem("mockingbird-admin-theme")
|
|
1661
|
-
if (storedTheme) setTheme(storedTheme)
|
|
1662
|
-
$("theme").addEventListener("click", () => {
|
|
1663
|
-
const current = document.documentElement.dataset.theme
|
|
1664
|
-
const dark = current ? current === "dark" : matchMedia("(prefers-color-scheme: dark)").matches
|
|
1665
|
-
const next = dark ? "light" : "dark"
|
|
1666
|
-
localStorage.setItem("mockingbird-admin-theme", next)
|
|
1667
|
-
setTheme(next)
|
|
1668
|
-
})
|
|
1669
|
-
|
|
1670
|
-
function show(view) {
|
|
1671
|
-
state.view = view
|
|
1672
|
-
for (const button of document.querySelectorAll("#nav button")) {
|
|
1673
|
-
button.setAttribute("aria-current", button.dataset.view === view ? "true" : "false")
|
|
1674
|
-
}
|
|
1675
|
-
for (const section of document.querySelectorAll("main .view")) {
|
|
1676
|
-
section.hidden = section.id !== "view-" + view
|
|
1677
|
-
}
|
|
1678
|
-
}
|
|
1679
|
-
document.getElementById("nav").addEventListener("click", (event) => {
|
|
1680
|
-
const button = event.target.closest("button[data-view]")
|
|
1681
|
-
if (!button) return
|
|
1682
|
-
show(button.dataset.view)
|
|
1683
|
-
refresh().catch(showError)
|
|
1684
|
-
})
|
|
1685
|
-
|
|
1686
|
-
function cards(items) {
|
|
1687
|
-
return '<div class="grid">' + items.map((item) =>
|
|
1688
|
-
'<article class="card"><div class="k">' + item.k + '</div><div class="v">' + item.v + '</div></article>'
|
|
1689
|
-
).join("") + "</div>"
|
|
1690
|
-
}
|
|
1691
|
-
function table(columns, rows) {
|
|
1692
|
-
if (rows.length === 0) return '<p class="empty">Nothing here yet.</p>'
|
|
1693
|
-
const head = "<tr>" + columns.map((column) => "<th>" + column.label + "</th>").join("") + "</tr>"
|
|
1694
|
-
const body = rows.map((row) => "<tr" + (row.attrs || "") + ">" + columns.map((column) =>
|
|
1695
|
-
'<td data-label="' + column.label + '">' + column.cell(row) + "</td>"
|
|
1696
|
-
).join("") + "</tr>").join("")
|
|
1697
|
-
return "<table><thead>" + head + "</thead><tbody>" + body + "</tbody></table>"
|
|
1698
|
-
}
|
|
1699
|
-
const esc = (value) => String(value ?? "").replace(/[&<>"']/g, (char) => ({
|
|
1700
|
-
"&": "&", "<": "<", ">": ">", '"': """, "'": "'"
|
|
1701
|
-
}[char]))
|
|
1702
|
-
const preview = (value) => {
|
|
1703
|
-
const text = JSON.stringify(value)
|
|
1704
|
-
return esc(text.length > 180 ? text.slice(0, 180) + "\u2026" : text)
|
|
1705
|
-
}
|
|
1706
|
-
const when = (epoch) => {
|
|
1707
|
-
const date = new Date(epoch)
|
|
1708
|
-
return Number.isNaN(date.getTime()) ? String(epoch) : date.toISOString()
|
|
1709
|
-
}
|
|
1710
|
-
const clockCard = (epoch) => {
|
|
1711
|
-
const date = new Date(epoch)
|
|
1712
|
-
if (Number.isNaN(date.getTime())) return esc(String(epoch))
|
|
1713
|
-
const iso = date.toISOString()
|
|
1714
|
-
return esc(iso.slice(0, 10)) + '<span class="clock-time">' + esc(iso.slice(11, 19)) + " UTC</span>"
|
|
1715
|
-
}
|
|
1716
|
-
|
|
1717
|
-
async function loadNamespaces() {
|
|
1718
|
-
const data = await api("GET", "/namespaces")
|
|
1719
|
-
const select = $("namespace")
|
|
1720
|
-
const names = data.namespaces && data.namespaces.length ? data.namespaces : [data.default || "default"]
|
|
1721
|
-
if (!names.includes(state.namespace)) names.unshift(state.namespace)
|
|
1722
|
-
select.innerHTML = names.map((name) =>
|
|
1723
|
-
'<option value="' + esc(name) + '">' + esc(name) + "</option>"
|
|
1724
|
-
).join("")
|
|
1725
|
-
select.value = state.namespace
|
|
1726
|
-
}
|
|
1727
|
-
|
|
1728
|
-
async function renderOverview() {
|
|
1729
|
-
const [health, shape, clock, journal] = await Promise.all([
|
|
1730
|
-
originGet("/health"),
|
|
1731
|
-
api("GET", "/state"),
|
|
1732
|
-
api("GET", "/clock"),
|
|
1733
|
-
api("GET", "/requests?limit=8")
|
|
1734
|
-
])
|
|
1735
|
-
state.shape = shape
|
|
1736
|
-
$("overview-cards").innerHTML = cards([
|
|
1737
|
-
{ k: "Service", v: esc(health.service || "${name}") },
|
|
1738
|
-
{ k: "Status", v: esc(health.status || "ok") },
|
|
1739
|
-
{ k: "Namespace", v: esc(state.namespace) },
|
|
1740
|
-
{ k: "Collections", v: String(shape.collections.length) },
|
|
1741
|
-
{ k: "Records", v: String(shape.collections.reduce((sum, item) => sum + item.count, 0)) },
|
|
1742
|
-
{ k: "Clock", v: clockCard(clock.now) }
|
|
1743
|
-
])
|
|
1744
|
-
const requests = (journal && journal.requests) || []
|
|
1745
|
-
$("overview-requests").innerHTML = table(
|
|
1746
|
-
[
|
|
1747
|
-
{ label: "Method", cell: (row) => esc(row.method) },
|
|
1748
|
-
{ label: "Path", cell: (row) => esc(row.path) },
|
|
1749
|
-
{ label: "Status", cell: (row) => '<span class="status-' + String(row.status).charAt(0) + '">' + esc(row.status) + "</span>" },
|
|
1750
|
-
{ label: "Operation", cell: (row) => esc(row.operationId || "") }
|
|
1751
|
-
],
|
|
1752
|
-
requests
|
|
1753
|
-
)
|
|
1754
|
-
}
|
|
1755
|
-
|
|
1756
|
-
function schemaChips(collection) {
|
|
1757
|
-
if (!collection || collection.fields.length === 0) {
|
|
1758
|
-
return '<p class="empty">No fields yet. Add a record or declare the collection on the service.</p>'
|
|
1759
|
-
}
|
|
1760
|
-
return '<div class="chips">' + collection.fields.map((field) =>
|
|
1761
|
-
'<span class="chip">' + esc(field.name) + ' <i>' + esc(field.kind) + (field.optional ? "?" : "") + "</i></span>"
|
|
1762
|
-
).join("") + "</div>"
|
|
1763
|
-
}
|
|
1764
|
-
|
|
1765
|
-
async function renderState() {
|
|
1766
|
-
const shape = await api("GET", "/state")
|
|
1767
|
-
state.shape = shape
|
|
1768
|
-
const host = $("collections")
|
|
1769
|
-
if (shape.collections.length === 0) {
|
|
1770
|
-
host.innerHTML = '<p class="empty">This namespace has no collections yet.</p>'
|
|
1771
|
-
$("schema").innerHTML = ""
|
|
1772
|
-
$("records").innerHTML = ""
|
|
1773
|
-
return
|
|
1774
|
-
}
|
|
1775
|
-
if (!shape.collections.some((item) => item.name === state.collection)) {
|
|
1776
|
-
state.collection = shape.collections[0].name
|
|
1777
|
-
}
|
|
1778
|
-
host.innerHTML = shape.collections.map((item) =>
|
|
1779
|
-
'<button type="button" class="collection" data-collection="' + esc(item.name) + '" aria-current="' +
|
|
1780
|
-
(item.name === state.collection ? "true" : "false") + '"><strong>' + esc(item.label) +
|
|
1781
|
-
'</strong><small>' + esc(item.count) + " \xB7 " + esc(item.source) + "</small></button>"
|
|
1782
|
-
).join("")
|
|
1783
|
-
const selected = shape.collections.find((item) => item.name === state.collection)
|
|
1784
|
-
$("schema").innerHTML = "<h3>" + esc(selected.label) + "</h3>" +
|
|
1785
|
-
(selected.description ? "<p class=" + '"lede">' + esc(selected.description) + "</p>" : "") +
|
|
1786
|
-
schemaChips(selected)
|
|
1787
|
-
const page = await api("GET", "/state/" + encodeURIComponent(state.collection) + "?limit=50")
|
|
1788
|
-
const rows = page.records.map((record) => ({
|
|
1789
|
-
...record,
|
|
1790
|
-
attrs: ' class="clickable" data-id="' + esc(record.id) + '"'
|
|
1791
|
-
}))
|
|
1792
|
-
$("records").innerHTML = table(
|
|
1793
|
-
[
|
|
1794
|
-
{ label: "Id", cell: (row) => "<code>" + esc(row.id) + "</code>" },
|
|
1795
|
-
{ label: "Seq", cell: (row) => esc(row.seq) },
|
|
1796
|
-
{ label: "Value", cell: (row) => preview(row.value) }
|
|
1797
|
-
],
|
|
1798
|
-
rows
|
|
1799
|
-
)
|
|
1800
|
-
}
|
|
1801
|
-
|
|
1802
|
-
async function renderClock() {
|
|
1803
|
-
const clock = await api("GET", "/clock")
|
|
1804
|
-
$("clock-readout").innerHTML = "<div class='k'>Now</div><div class='v'>" + esc(when(clock.now)) +
|
|
1805
|
-
"</div><p>" + esc(clock.now) + " ms \xB7 offset " + esc(clock.offsetMs) + " ms " +
|
|
1806
|
-
(clock.frozen ? "<span class='badge warn'>frozen</span>" : "<span class='badge ok'>live</span>") + "</p>"
|
|
1807
|
-
$("freeze").textContent = clock.frozen ? "Unfreeze" : "Freeze"
|
|
1808
|
-
$("freeze").dataset.frozen = clock.frozen ? "1" : "0"
|
|
1809
|
-
}
|
|
1810
|
-
|
|
1811
|
-
async function renderFaults() {
|
|
1812
|
-
const [faults, presets] = await Promise.all([
|
|
1813
|
-
api("GET", "/faults"),
|
|
1814
|
-
api("GET", "/faults/presets").catch(() => ({ presets: [] }))
|
|
1815
|
-
])
|
|
1816
|
-
const select = $("fault-preset")
|
|
1817
|
-
const current = select.value
|
|
1818
|
-
const list = presets.presets || []
|
|
1819
|
-
select.innerHTML = '<option value="">Custom rule</option>' + list.map((preset) =>
|
|
1820
|
-
'<option value="' + esc(preset.name) + '">' + esc(preset.name) + "</option>"
|
|
1821
|
-
).join("")
|
|
1822
|
-
select.value = current
|
|
1823
|
-
const rules = faults.faults || []
|
|
1824
|
-
$("fault-list").innerHTML = table(
|
|
1825
|
-
[
|
|
1826
|
-
{ label: "Id", cell: (row) => esc(row.id) },
|
|
1827
|
-
{ label: "Match", cell: (row) => esc([row.method, row.pathPrefix, row.operationId].filter(Boolean).join(" ") || "all") },
|
|
1828
|
-
{ label: "Effect", cell: (row) => esc(row.status ?? row.effect ?? (row.drop ? "drop" : row.latencyMs || "")) }
|
|
1829
|
-
],
|
|
1830
|
-
rules
|
|
1831
|
-
)
|
|
1832
|
-
}
|
|
1833
|
-
|
|
1834
|
-
async function renderJournal() {
|
|
1835
|
-
const journal = await api("GET", "/requests?limit=100")
|
|
1836
|
-
$("journal").innerHTML = table(
|
|
1837
|
-
[
|
|
1838
|
-
{ label: "When", cell: (row) => esc(row.at || "") },
|
|
1839
|
-
{ label: "Method", cell: (row) => esc(row.method) },
|
|
1840
|
-
{ label: "Path", cell: (row) => esc(row.path) },
|
|
1841
|
-
{ label: "Status", cell: (row) => esc(row.status) },
|
|
1842
|
-
{ label: "ms", cell: (row) => esc(row.durationMs) }
|
|
1843
|
-
],
|
|
1844
|
-
journal.requests || []
|
|
1845
|
-
)
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
|
-
async function renderRoutes() {
|
|
1849
|
-
const data = await api("GET", "/")
|
|
1850
|
-
const routes = data.routes || []
|
|
1851
|
-
$("route-list").innerHTML = routes.map((route) => {
|
|
1852
|
-
const extra = STANDARD.has(route) ? "" : " <span class='badge'>extension</span>"
|
|
1853
|
-
return '<div class="route"><span class="method">' + esc(route.split(" ")[0]) +
|
|
1854
|
-
'</span><span>' + esc(route.split(" ").slice(1).join(" ")) + extra +
|
|
1855
|
-
'</span><button class="btn" type="button" data-route="' + esc(route) + '">Use</button></div>'
|
|
1856
|
-
}).join("")
|
|
1857
|
-
}
|
|
1858
|
-
|
|
1859
|
-
const renderers = {
|
|
1860
|
-
overview: renderOverview,
|
|
1861
|
-
state: renderState,
|
|
1862
|
-
clock: renderClock,
|
|
1863
|
-
faults: renderFaults,
|
|
1864
|
-
journal: renderJournal,
|
|
1865
|
-
routes: renderRoutes
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
async function refresh() {
|
|
1869
|
-
clearError()
|
|
1870
|
-
if (state.view in renderers) await renderers[state.view]()
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
|
-
$("namespace").addEventListener("change", () => {
|
|
1874
|
-
state.namespace = $("namespace").value
|
|
1875
|
-
refresh().catch(showError)
|
|
1876
|
-
})
|
|
1877
|
-
keyInput.addEventListener("change", () => {
|
|
1878
|
-
state.key = keyInput.value.trim()
|
|
1879
|
-
sessionStorage.setItem("mockingbird-admin-key", state.key)
|
|
1880
|
-
refresh().catch(showError)
|
|
1881
|
-
})
|
|
1882
|
-
$("refresh").addEventListener("click", () => refresh().catch(showError))
|
|
1883
|
-
|
|
1884
|
-
$("collections").addEventListener("click", (event) => {
|
|
1885
|
-
const button = event.target.closest("[data-collection]")
|
|
1886
|
-
if (!button) return
|
|
1887
|
-
state.collection = button.dataset.collection
|
|
1888
|
-
renderState().catch(showError)
|
|
1889
|
-
})
|
|
1890
|
-
$("records").addEventListener("click", (event) => {
|
|
1891
|
-
const row = event.target.closest("[data-id]")
|
|
1892
|
-
if (!row) return
|
|
1893
|
-
openEditor(row.dataset.id).catch(showError)
|
|
1894
|
-
})
|
|
1895
|
-
|
|
1896
|
-
const editor = $("editor")
|
|
1897
|
-
async function openEditor(id) {
|
|
1898
|
-
state.editing = id || null
|
|
1899
|
-
$("editor-title").textContent = id ? "Edit record" : "New record"
|
|
1900
|
-
$("editor-id").value = id || ""
|
|
1901
|
-
$("editor-id").readOnly = Boolean(id)
|
|
1902
|
-
$("editor-delete").hidden = !id
|
|
1903
|
-
if (id) {
|
|
1904
|
-
const record = await api("GET", "/state/" + encodeURIComponent(state.collection) + "/" + encodeURIComponent(id))
|
|
1905
|
-
$("editor-value").value = JSON.stringify(record.value, null, 2)
|
|
1906
|
-
} else {
|
|
1907
|
-
$("editor-value").value = "{\\n \\n}"
|
|
1908
|
-
}
|
|
1909
|
-
editor.showModal()
|
|
1910
|
-
}
|
|
1911
|
-
$("new-record").addEventListener("click", () => openEditor(null).catch(showError))
|
|
1912
|
-
$("editor-form").addEventListener("submit", (event) => {
|
|
1913
|
-
const submitter = event.submitter
|
|
1914
|
-
if (!submitter || submitter.value !== "save") return
|
|
1915
|
-
event.preventDefault()
|
|
1916
|
-
let value
|
|
1917
|
-
try { value = JSON.parse($("editor-value").value) }
|
|
1918
|
-
catch { showError(new Error("Value is not JSON")); return }
|
|
1919
|
-
const id = $("editor-id").value.trim()
|
|
1920
|
-
const path = "/state/" + encodeURIComponent(state.collection)
|
|
1921
|
-
const request = state.editing
|
|
1922
|
-
? api("PUT", path + "/" + encodeURIComponent(id), { value })
|
|
1923
|
-
: api("POST", path, { id: id || undefined, value })
|
|
1924
|
-
request.then(() => { editor.close(); return renderState() }).catch(showError)
|
|
1925
|
-
})
|
|
1926
|
-
$("editor-delete").addEventListener("click", () => {
|
|
1927
|
-
const id = state.editing
|
|
1928
|
-
if (!id) return
|
|
1929
|
-
api("DELETE", "/state/" + encodeURIComponent(state.collection) + "/" + encodeURIComponent(id))
|
|
1930
|
-
.then(() => { editor.close(); return renderState() })
|
|
1931
|
-
.catch(showError)
|
|
1932
|
-
})
|
|
1933
|
-
|
|
1934
|
-
document.querySelectorAll("[data-advance]").forEach((button) => {
|
|
1935
|
-
button.addEventListener("click", () => {
|
|
1936
|
-
api("POST", "/clock", { advance: Number(button.dataset.advance) }).then(renderClock).catch(showError)
|
|
1937
|
-
})
|
|
1938
|
-
})
|
|
1939
|
-
$("freeze").addEventListener("click", () => {
|
|
1940
|
-
const frozen = $("freeze").dataset.frozen === "1"
|
|
1941
|
-
api("POST", "/clock", { freeze: !frozen }).then(renderClock).catch(showError)
|
|
1942
|
-
})
|
|
1943
|
-
$("clock-reset").addEventListener("click", () => {
|
|
1944
|
-
api("POST", "/clock", { reset: true }).then(renderClock).catch(showError)
|
|
1945
|
-
})
|
|
1946
|
-
$("clock-set").addEventListener("submit", (event) => {
|
|
1947
|
-
event.preventDefault()
|
|
1948
|
-
const raw = $("clock-instant").value.trim()
|
|
1949
|
-
const set = /^-?\\d+$/.test(raw) ? Number(raw) : raw
|
|
1950
|
-
api("POST", "/clock", { set }).then(renderClock).catch(showError)
|
|
1951
|
-
})
|
|
1952
|
-
|
|
1953
|
-
$("fault-form").addEventListener("submit", (event) => {
|
|
1954
|
-
event.preventDefault()
|
|
1955
|
-
const preset = $("fault-preset").value
|
|
1956
|
-
const body = preset
|
|
1957
|
-
? { preset }
|
|
1958
|
-
: {
|
|
1959
|
-
status: Number($("fault-status").value),
|
|
1960
|
-
...($("fault-path").value ? { pathPrefix: $("fault-path").value } : {}),
|
|
1961
|
-
...($("fault-method").value ? { method: $("fault-method").value } : {})
|
|
1962
|
-
}
|
|
1963
|
-
if (!preset && !Number.isFinite(body.status)) {
|
|
1964
|
-
showError(new Error("Status must be a number, or choose a preset"))
|
|
1965
|
-
return
|
|
1966
|
-
}
|
|
1967
|
-
api("POST", "/faults", body).then(renderFaults).catch(showError)
|
|
1968
|
-
})
|
|
1969
|
-
$("fault-clear").addEventListener("click", () => api("DELETE", "/faults").then(renderFaults).catch(showError))
|
|
1970
|
-
$("journal-clear").addEventListener("click", () => api("DELETE", "/requests").then(renderJournal).catch(showError))
|
|
1971
|
-
|
|
1972
|
-
$("route-list").addEventListener("click", (event) => {
|
|
1973
|
-
const button = event.target.closest("[data-route]")
|
|
1974
|
-
if (!button) return
|
|
1975
|
-
state.route = button.dataset.route
|
|
1976
|
-
$("route-title").textContent = state.route
|
|
1977
|
-
const method = state.route.split(" ")[0]
|
|
1978
|
-
$("route-body").disabled = method === "GET" || method === "DELETE"
|
|
1979
|
-
})
|
|
1980
|
-
$("route-form").addEventListener("submit", async (event) => {
|
|
1981
|
-
event.preventDefault()
|
|
1982
|
-
if (!state.route) return showError(new Error("Choose a route first"))
|
|
1983
|
-
const [method, path] = [state.route.split(" ")[0], state.route.split(" ").slice(1).join(" ")]
|
|
1984
|
-
const concrete = path.replace(/:([A-Za-z0-9_]+)/g, (_, key) => prompt("Value for " + key) || "")
|
|
1985
|
-
let body
|
|
1986
|
-
if (method !== "GET" && method !== "DELETE" && $("route-body").value.trim()) {
|
|
1987
|
-
try { body = JSON.parse($("route-body").value) }
|
|
1988
|
-
catch { return showError(new Error("Body is not JSON")) }
|
|
1989
|
-
}
|
|
1990
|
-
try {
|
|
1991
|
-
const data = await api(method, concrete, body)
|
|
1992
|
-
$("route-result").textContent = JSON.stringify(data, null, 2)
|
|
1993
|
-
} catch (error) {
|
|
1994
|
-
showError(error)
|
|
1995
|
-
}
|
|
1996
|
-
})
|
|
1997
|
-
|
|
1998
|
-
function mountPanels(panels) {
|
|
1999
|
-
const nav = $("nav")
|
|
2000
|
-
const views = $("views")
|
|
2001
|
-
for (const panel of panels) {
|
|
2002
|
-
const button = document.createElement("button")
|
|
2003
|
-
button.type = "button"
|
|
2004
|
-
button.dataset.view = panel.id
|
|
2005
|
-
button.textContent = panel.title
|
|
2006
|
-
nav.append(button)
|
|
2007
|
-
const section = document.createElement("section")
|
|
2008
|
-
section.className = "view"
|
|
2009
|
-
section.id = "view-" + panel.id
|
|
2010
|
-
section.hidden = true
|
|
2011
|
-
const title = document.createElement("h2")
|
|
2012
|
-
title.textContent = panel.title
|
|
2013
|
-
const lede = document.createElement("p")
|
|
2014
|
-
lede.className = "lede"
|
|
2015
|
-
lede.textContent = panel.description || ""
|
|
2016
|
-
const body = document.createElement("div")
|
|
2017
|
-
body.className = "panel-body"
|
|
2018
|
-
body.id = "panel-" + panel.id
|
|
2019
|
-
body.innerHTML = panel.html || ""
|
|
2020
|
-
section.append(title, lede, body)
|
|
2021
|
-
views.append(section)
|
|
2022
|
-
if (panel.script) {
|
|
2023
|
-
try {
|
|
2024
|
-
const run = new Function("root", "api", panel.script)
|
|
2025
|
-
run(body, panelApi)
|
|
2026
|
-
} catch (error) {
|
|
2027
|
-
const note = document.createElement("p")
|
|
2028
|
-
note.className = "banner show"
|
|
2029
|
-
note.textContent = error instanceof Error ? error.message : String(error)
|
|
2030
|
-
body.append(note)
|
|
2031
|
-
}
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2035
|
-
|
|
2036
|
-
loadNamespaces()
|
|
2037
|
-
.then(() => api("GET", "/ui/manifest"))
|
|
2038
|
-
.then((manifest) => { mountPanels((manifest && manifest.panels) || []); return refresh() })
|
|
2039
|
-
.catch(showError)
|
|
2040
|
-
})()
|
|
2041
|
-
</script>
|
|
2842
|
+
${script}
|
|
2042
2843
|
</body>
|
|
2043
2844
|
</html>`;
|
|
2044
2845
|
};
|
|
@@ -2055,10 +2856,10 @@ var json2 = (body) => new Response(JSON.stringify(body), {
|
|
|
2055
2856
|
});
|
|
2056
2857
|
var adminUiRoutes = (service, ui) => {
|
|
2057
2858
|
const shell = () => renderAdminDocument(service);
|
|
2058
|
-
const
|
|
2859
|
+
const document3 = () => ui?.render ? ui.render({ service, defaultHtml: shell }) : shell();
|
|
2059
2860
|
return {
|
|
2060
|
-
"GET /ui": () => htmlResponse(
|
|
2061
|
-
"GET /ui/": () => htmlResponse(
|
|
2861
|
+
"GET /ui": () => htmlResponse(document3()),
|
|
2862
|
+
"GET /ui/": () => htmlResponse(document3()),
|
|
2062
2863
|
"GET /ui/manifest": () => json2({
|
|
2063
2864
|
service,
|
|
2064
2865
|
panels: (ui?.panels ?? []).map((panel) => ({
|
|
@@ -2084,11 +2885,11 @@ var EXTENSION_KEYS = {
|
|
|
2084
2885
|
};
|
|
2085
2886
|
|
|
2086
2887
|
// ../../openapi/metadata/dist/read.js
|
|
2087
|
-
var
|
|
2888
|
+
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2088
2889
|
var extensionOf = (holder, key) => holder[key];
|
|
2089
2890
|
var operationMetadata = (operation) => {
|
|
2090
2891
|
const raw = extensionOf(operation, EXTENSION_KEYS.operation);
|
|
2091
|
-
const ext =
|
|
2892
|
+
const ext = isRecord3(raw) ? raw : {};
|
|
2092
2893
|
const supported = ext.supported ?? true;
|
|
2093
2894
|
const parity = ext.parity ?? {};
|
|
2094
2895
|
return {
|
|
@@ -2124,9 +2925,9 @@ ${problems.map((p) => ` - ${p}`).join("\n")}`);
|
|
|
2124
2925
|
this.name = "OperationRegistryError";
|
|
2125
2926
|
}
|
|
2126
2927
|
};
|
|
2127
|
-
var verifyOperations = (
|
|
2928
|
+
var verifyOperations = (document3, handlers) => {
|
|
2128
2929
|
const problems = [];
|
|
2129
|
-
const operations = listOperations(
|
|
2930
|
+
const operations = listOperations(document3);
|
|
2130
2931
|
const seen = /* @__PURE__ */ new Set();
|
|
2131
2932
|
for (const operation of operations) {
|
|
2132
2933
|
if (seen.has(operation.operationId))
|
|
@@ -2242,7 +3043,7 @@ var SAMPLE = 25;
|
|
|
2242
3043
|
var WALK_LIMIT = 1e4;
|
|
2243
3044
|
var SKIP_CTORS = /* @__PURE__ */ new Set(["Hono", "HonoRequest", "Router"]);
|
|
2244
3045
|
var fail = (status, message) => ({ ok: false, status, message });
|
|
2245
|
-
var
|
|
3046
|
+
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2246
3047
|
var kindOf = (value) => {
|
|
2247
3048
|
if (value === null)
|
|
2248
3049
|
return "null";
|
|
@@ -2341,7 +3142,7 @@ var absorb = (accum, value) => {
|
|
|
2341
3142
|
const kind = kindOf(value);
|
|
2342
3143
|
accum.kinds.add(kind);
|
|
2343
3144
|
accum.present++;
|
|
2344
|
-
if (!
|
|
3145
|
+
if (!isRecord4(value))
|
|
2345
3146
|
return;
|
|
2346
3147
|
for (const [key, child] of Object.entries(value)) {
|
|
2347
3148
|
const nested = accum.nested.get(key) ?? blankAccum(key);
|
|
@@ -2366,7 +3167,7 @@ var inferFields = (records) => {
|
|
|
2366
3167
|
if (records.length === 0)
|
|
2367
3168
|
return [];
|
|
2368
3169
|
const sample = records.slice(0, SAMPLE);
|
|
2369
|
-
const objects = sample.filter((record) =>
|
|
3170
|
+
const objects = sample.filter((record) => isRecord4(record.value));
|
|
2370
3171
|
if (objects.length === 0) {
|
|
2371
3172
|
const kinds = new Set(sample.map((record) => kindOf(record.value)));
|
|
2372
3173
|
const list = [...kinds];
|
|
@@ -2553,7 +3354,7 @@ var patchStateRecord = (scope, name, id, value) => {
|
|
|
2553
3354
|
const parsed = jsonValue(value);
|
|
2554
3355
|
if (!parsed.ok)
|
|
2555
3356
|
return parsed;
|
|
2556
|
-
const next =
|
|
3357
|
+
const next = isRecord4(current.value.value) && isRecord4(parsed.value) ? { ...current.value.value, ...parsed.value } : parsed.value;
|
|
2557
3358
|
return replaceStateRecord(scope, name, id, next);
|
|
2558
3359
|
};
|
|
2559
3360
|
var deleteStateRecord = (scope, name, id) => {
|
|
@@ -2621,7 +3422,7 @@ var stateAdminRoutes = (routes) => {
|
|
|
2621
3422
|
const scope = open(namespace);
|
|
2622
3423
|
if (!scope.ok)
|
|
2623
3424
|
return fromResult(scope, 201);
|
|
2624
|
-
if (!
|
|
3425
|
+
if (!isRecord4(body) || !("value" in body)) {
|
|
2625
3426
|
return adminError2(400, 'expected {"id?": "<id>", "value": <json>}');
|
|
2626
3427
|
}
|
|
2627
3428
|
const id = body.id;
|
|
@@ -2639,7 +3440,7 @@ var stateAdminRoutes = (routes) => {
|
|
|
2639
3440
|
const scope = open(namespace);
|
|
2640
3441
|
if (!scope.ok)
|
|
2641
3442
|
return fromResult(scope, 200);
|
|
2642
|
-
if (!
|
|
3443
|
+
if (!isRecord4(body) || !("value" in body))
|
|
2643
3444
|
return adminError2(400, 'expected {"value": <json>}');
|
|
2644
3445
|
const replaced = replaceStateRecord(scope.value, params.collection ?? "", params.id ?? "", body.value);
|
|
2645
3446
|
if (replaced.ok)
|
|
@@ -2650,7 +3451,7 @@ var stateAdminRoutes = (routes) => {
|
|
|
2650
3451
|
const scope = open(namespace);
|
|
2651
3452
|
if (!scope.ok)
|
|
2652
3453
|
return fromResult(scope, 200);
|
|
2653
|
-
if (!
|
|
3454
|
+
if (!isRecord4(body) || !("value" in body))
|
|
2654
3455
|
return adminError2(400, 'expected {"value": <json>}');
|
|
2655
3456
|
const patched = patchStateRecord(scope.value, params.collection ?? "", params.id ?? "", body.value);
|
|
2656
3457
|
if (patched.ok)
|
|
@@ -2670,14 +3471,14 @@ var stateAdminRoutes = (routes) => {
|
|
|
2670
3471
|
};
|
|
2671
3472
|
|
|
2672
3473
|
// ../core/dist/version.js
|
|
2673
|
-
var PACKAGE_VERSION = true ? "1.
|
|
3474
|
+
var PACKAGE_VERSION = true ? "1.6.0" : UNRELEASED_VERSION;
|
|
2674
3475
|
|
|
2675
3476
|
// ../core/dist/webhooks.js
|
|
2676
3477
|
var json4 = (status, body) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
|
|
2677
3478
|
var adminError3 = (status, message) => json4(status, { error: { type: "mockingbird_admin", message } });
|
|
2678
|
-
var
|
|
3479
|
+
var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2679
3480
|
var parseEndpoint = (value) => {
|
|
2680
|
-
if (!
|
|
3481
|
+
if (!isRecord5(value) || typeof value.url !== "string")
|
|
2681
3482
|
return "each endpoint needs a url";
|
|
2682
3483
|
try {
|
|
2683
3484
|
new URL(value.url);
|
|
@@ -2694,12 +3495,12 @@ var parseEndpoint = (value) => {
|
|
|
2694
3495
|
const events = value.events ?? value.enabledEvents;
|
|
2695
3496
|
if (Array.isArray(events))
|
|
2696
3497
|
endpoint.events = events.map(String);
|
|
2697
|
-
if (
|
|
3498
|
+
if (isRecord5(value.tags)) {
|
|
2698
3499
|
endpoint.tags = Object.fromEntries(Object.entries(value.tags).map(([k, v]) => [k, String(v)]));
|
|
2699
3500
|
}
|
|
2700
3501
|
if (typeof value.account === "string")
|
|
2701
3502
|
endpoint.tags = { ...endpoint.tags, account: value.account };
|
|
2702
|
-
if (
|
|
3503
|
+
if (isRecord5(value.headers)) {
|
|
2703
3504
|
endpoint.headers = Object.fromEntries(Object.entries(value.headers).map(([k, v]) => [k, String(v)]));
|
|
2704
3505
|
}
|
|
2705
3506
|
return endpoint;
|
|
@@ -2726,7 +3527,7 @@ var webhookAdminRoutes = (hub) => ({
|
|
|
2726
3527
|
return json4(200, { status: "ok" });
|
|
2727
3528
|
},
|
|
2728
3529
|
"POST /webhooks/faults": ({ body, namespace }) => {
|
|
2729
|
-
if (!
|
|
3530
|
+
if (!isRecord5(body) || !["duplicate", "reorder", "drop"].includes(String(body.mode))) {
|
|
2730
3531
|
return adminError3(400, "mode must be duplicate, reorder or drop");
|
|
2731
3532
|
}
|
|
2732
3533
|
const fault = { mode: body.mode };
|
|
@@ -2742,7 +3543,7 @@ var webhookAdminRoutes = (hub) => ({
|
|
|
2742
3543
|
}))
|
|
2743
3544
|
}),
|
|
2744
3545
|
"PUT /webhook-endpoints": ({ body, namespace }) => {
|
|
2745
|
-
const list = Array.isArray(body) ? body :
|
|
3546
|
+
const list = Array.isArray(body) ? body : isRecord5(body) ? body.endpoints : void 0;
|
|
2746
3547
|
if (!Array.isArray(list))
|
|
2747
3548
|
return adminError3(400, "expected [{url, secret?, events?}]");
|
|
2748
3549
|
const parsed = [];
|
|
@@ -2810,8 +3611,8 @@ var DroppedConnectionError = class extends TypeError {
|
|
|
2810
3611
|
this.name = "TypeError";
|
|
2811
3612
|
}
|
|
2812
3613
|
};
|
|
2813
|
-
var operationMatcher = (
|
|
2814
|
-
const matchers = listOperations(
|
|
3614
|
+
var operationMatcher = (document3) => {
|
|
3615
|
+
const matchers = listOperations(document3).map((operation) => ({
|
|
2815
3616
|
operationId: operation.operationId,
|
|
2816
3617
|
method: operation.method.toUpperCase(),
|
|
2817
3618
|
pattern: new RegExp(`^${operation.path.split("/").map((segment) => segment.startsWith("{") ? "[^/]+" : segment.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("/")}/?$`),
|
|
@@ -2906,10 +3707,10 @@ var createRuntime = (options) => {
|
|
|
2906
3707
|
const ensureBranch = (namespace, branch2, at) => {
|
|
2907
3708
|
if (!BRANCH_PATTERN2.test(branch2))
|
|
2908
3709
|
throw new RangeError(`branch must match ${BRANCH_PATTERN2}`);
|
|
2909
|
-
const
|
|
3710
|
+
const history2 = timeline(namespace);
|
|
2910
3711
|
if (branch2 === "main") {
|
|
2911
3712
|
if (at !== void 0) {
|
|
2912
|
-
const point =
|
|
3713
|
+
const point = history2.checkout("main", at);
|
|
2913
3714
|
restoreNamespace(sqlite, storageNamespace(namespace), point.value.snapshot);
|
|
2914
3715
|
captured.set(namespace, point.value.snapshot);
|
|
2915
3716
|
rng.setState(point.value.rngState);
|
|
@@ -2922,10 +3723,10 @@ var createRuntime = (options) => {
|
|
|
2922
3723
|
return namespace;
|
|
2923
3724
|
}
|
|
2924
3725
|
const storage = physicalBranch(namespace, branch2);
|
|
2925
|
-
if (!
|
|
3726
|
+
if (!history2.hasBranch(branch2)) {
|
|
2926
3727
|
if (at === void 0)
|
|
2927
|
-
|
|
2928
|
-
const point =
|
|
3728
|
+
history2.commit(capture(namespace));
|
|
3729
|
+
const point = history2.fork(branch2, at === void 0 ? {} : { from: at });
|
|
2929
3730
|
const branchRng = createRng(options.seed ?? 0);
|
|
2930
3731
|
if (point)
|
|
2931
3732
|
branchRng.setState(point.value.rngState);
|
|
@@ -2934,8 +3735,8 @@ var createRuntime = (options) => {
|
|
|
2934
3735
|
restoreNamespace(sqlite, storageNamespace(storage), point.value.snapshot);
|
|
2935
3736
|
if (point)
|
|
2936
3737
|
captured.set(storage, point.value.snapshot);
|
|
2937
|
-
} else if (at !== void 0 &&
|
|
2938
|
-
const point =
|
|
3738
|
+
} else if (at !== void 0 && history2.head(branch2)?.id !== at) {
|
|
3739
|
+
const point = history2.checkout(branch2, at);
|
|
2939
3740
|
if (!instances.has(storage)) {
|
|
2940
3741
|
const branchRng = createRng(options.seed ?? 0);
|
|
2941
3742
|
branchRng.setState(point.value.rngState);
|
|
@@ -2946,7 +3747,7 @@ var createRuntime = (options) => {
|
|
|
2946
3747
|
captured.set(storage, point.value.snapshot);
|
|
2947
3748
|
} else {
|
|
2948
3749
|
if (!instances.has(storage)) {
|
|
2949
|
-
const point =
|
|
3750
|
+
const point = history2.head(branch2);
|
|
2950
3751
|
const branchRng = createRng(options.seed ?? 0);
|
|
2951
3752
|
if (point)
|
|
2952
3753
|
branchRng.setState(point.value.rngState);
|
|
@@ -2970,8 +3771,8 @@ var createRuntime = (options) => {
|
|
|
2970
3771
|
const checkout = (checkpointId, checkoutOptions = {}) => {
|
|
2971
3772
|
const namespace = checkoutOptions.namespace ?? DEFAULT_NAMESPACE;
|
|
2972
3773
|
const branchName = checkoutOptions.branch ?? "main";
|
|
2973
|
-
const
|
|
2974
|
-
const point =
|
|
3774
|
+
const history2 = timeline(namespace);
|
|
3775
|
+
const point = history2.checkout(branchName, checkpointId);
|
|
2975
3776
|
const storage = ensureBranch(namespace, branchName);
|
|
2976
3777
|
restoreNamespace(sqlite, storageNamespace(storage), point.value.snapshot);
|
|
2977
3778
|
captured.set(storage, point.value.snapshot);
|
|
@@ -3021,9 +3822,9 @@ var createRuntime = (options) => {
|
|
|
3021
3822
|
instance(name);
|
|
3022
3823
|
restoreNamespace(sqlite, storageNamespace(name), from);
|
|
3023
3824
|
captured.set(name, from);
|
|
3024
|
-
const
|
|
3025
|
-
if (
|
|
3026
|
-
|
|
3825
|
+
const history2 = timelines.get(name);
|
|
3826
|
+
if (history2)
|
|
3827
|
+
history2.commit(capture(name), { branch: "main" });
|
|
3027
3828
|
else
|
|
3028
3829
|
timeline(name);
|
|
3029
3830
|
};
|
|
@@ -3252,10 +4053,10 @@ var createRuntime = (options) => {
|
|
|
3252
4053
|
},
|
|
3253
4054
|
release: (name, checkpointId) => timeline(name).release(checkpointId),
|
|
3254
4055
|
inspect: (name) => {
|
|
3255
|
-
const
|
|
4056
|
+
const history2 = timeline(name);
|
|
3256
4057
|
return {
|
|
3257
|
-
branches:
|
|
3258
|
-
checkpoints:
|
|
4058
|
+
branches: history2.branches(),
|
|
4059
|
+
checkpoints: history2.checkpoints().map(({ id, branch: branchName, parent, at }) => ({
|
|
3259
4060
|
id,
|
|
3260
4061
|
branch: branchName,
|
|
3261
4062
|
parent,
|
|
@@ -3270,11 +4071,11 @@ var createRuntime = (options) => {
|
|
|
3270
4071
|
} : {},
|
|
3271
4072
|
routes: {
|
|
3272
4073
|
...credentialRoutes(credentials),
|
|
3273
|
-
...options.presets ? presetRoutes(options.presets, runtime) : {},
|
|
3274
4074
|
...options.webhooks ? webhookAdminRoutes(options.webhooks) : {},
|
|
3275
4075
|
...options.admin?.(runtime) ?? {},
|
|
3276
|
-
//
|
|
3277
|
-
//
|
|
4076
|
+
// Shell routes win a colliding key. Fault presets are one of them: the admin page
|
|
4077
|
+
// maps `presets`, and a service route must not replace that list with a record.
|
|
4078
|
+
...options.presets ? presetRoutes(options.presets, runtime) : {},
|
|
3278
4079
|
...stateAdminRoutes({
|
|
3279
4080
|
open: stateScope,
|
|
3280
4081
|
afterWrite: (namespace) => {
|
|
@@ -3349,9 +4150,12 @@ var credentialRoutes = (registry) => ({
|
|
|
3349
4150
|
}
|
|
3350
4151
|
});
|
|
3351
4152
|
var presetRoutes = (presets, runtime) => ({
|
|
3352
|
-
"GET /faults/presets": () =>
|
|
3353
|
-
|
|
3354
|
-
|
|
4153
|
+
"GET /faults/presets": () => {
|
|
4154
|
+
const body = {
|
|
4155
|
+
presets: Object.entries(presets).map(([name, preset]) => ({ name, ...preset }))
|
|
4156
|
+
};
|
|
4157
|
+
return adminJson(200, body);
|
|
4158
|
+
},
|
|
3355
4159
|
"POST /faults/presets/:name": ({ params, body, namespace }) => {
|
|
3356
4160
|
const name = params.name;
|
|
3357
4161
|
if (!presets[name])
|
|
@@ -4410,7 +5214,7 @@ var JunctionState = class {
|
|
|
4410
5214
|
const zip = /^\d{5}/.test(zipCode) ? zipCode.slice(0, 5) : "00000";
|
|
4411
5215
|
const zipPrefix = Number(zip.slice(0, 3));
|
|
4412
5216
|
const cityState = zipPrefix >= 850 && zipPrefix <= 865 ? { city: "Phoenix", state: "AZ" } : zipPrefix >= 900 ? { city: "Los Angeles", state: "CA" } : zipPrefix >= 800 ? { city: "Denver", state: "CO" } : zipPrefix >= 600 ? { city: "Chicago", state: "IL" } : zipPrefix >= 300 && zipPrefix < 400 ? { city: "Atlanta", state: "GA" } : { city: "New York", state: "NY" };
|
|
4413
|
-
const
|
|
5217
|
+
const location2 = zip === "85004" ? { lat: 33.6242904, lng: -111.9283407 } : {
|
|
4414
5218
|
lat: 30 + zipPrefix % 20 * 0.4,
|
|
4415
5219
|
lng: -120 + zipPrefix % 30 * 0.5
|
|
4416
5220
|
};
|
|
@@ -4443,7 +5247,7 @@ var JunctionState = class {
|
|
|
4443
5247
|
unit: null,
|
|
4444
5248
|
access_notes: null
|
|
4445
5249
|
},
|
|
4446
|
-
location,
|
|
5250
|
+
location: location2,
|
|
4447
5251
|
consumed_by_order_id: null,
|
|
4448
5252
|
created_at: new Date(nowMs).toISOString()
|
|
4449
5253
|
});
|
|
@@ -4808,7 +5612,7 @@ var renderLabAccount = (entry) => ({
|
|
|
4808
5612
|
),
|
|
4809
5613
|
team_id_allowlist: [...entry.team_id_allowlist]
|
|
4810
5614
|
});
|
|
4811
|
-
var
|
|
5615
|
+
var isRecord6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4812
5616
|
var DELEGATED_FLOWS = [
|
|
4813
5617
|
"order_delegated",
|
|
4814
5618
|
"result_delegated",
|
|
@@ -4824,7 +5628,7 @@ var checkStates = (value, where) => {
|
|
|
4824
5628
|
};
|
|
4825
5629
|
var stringList = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string") ? [...value] : void 0;
|
|
4826
5630
|
var labAccountFromInput = (input, teamId = MOCK_TEAM_ID) => {
|
|
4827
|
-
if (!
|
|
5631
|
+
if (!isRecord6(input)) throw new TypeError("lab account must be an object");
|
|
4828
5632
|
if (typeof input.id !== "string" || input.id === "")
|
|
4829
5633
|
throw new TypeError("lab account needs a non-empty id");
|
|
4830
5634
|
const where = `lab account ${input.id}`;
|
|
@@ -4836,7 +5640,7 @@ var labAccountFromInput = (input, teamId = MOCK_TEAM_ID) => {
|
|
|
4836
5640
|
throw new TypeError(`${where}: delegated_flow must be one of ${DELEGATED_FLOWS.join(", ")}`);
|
|
4837
5641
|
if (input.states !== void 0) checkStates(input.states, `${where}: states`);
|
|
4838
5642
|
if (input.allowed_billing !== void 0) {
|
|
4839
|
-
if (!
|
|
5643
|
+
if (!isRecord6(input.allowed_billing))
|
|
4840
5644
|
throw new TypeError(`${where}: allowed_billing must map billing types to state lists`);
|
|
4841
5645
|
for (const [type, states] of Object.entries(input.allowed_billing)) {
|
|
4842
5646
|
if (!BILLING_TYPES.includes(type))
|
|
@@ -4875,7 +5679,7 @@ var labAccountFromInput = (input, teamId = MOCK_TEAM_ID) => {
|
|
|
4875
5679
|
};
|
|
4876
5680
|
};
|
|
4877
5681
|
var patchLabAccount = (existing, patch, teamId) => {
|
|
4878
|
-
if (!
|
|
5682
|
+
if (!isRecord6(patch)) throw new TypeError("lab account patch must be an object");
|
|
4879
5683
|
if (patch.id !== void 0 && patch.id !== existing.id)
|
|
4880
5684
|
throw new TypeError(`lab account ${existing.id}: id cannot be changed`);
|
|
4881
5685
|
const { states, ...rest } = patch;
|
|
@@ -4895,7 +5699,7 @@ var patchLabAccount = (existing, patch, teamId) => {
|
|
|
4895
5699
|
var labAccountFromClientFacing = (value, recordedTeamId) => {
|
|
4896
5700
|
if (typeof value.id !== "string" || typeof value.lab !== "string") return void 0;
|
|
4897
5701
|
const billing = {};
|
|
4898
|
-
if (
|
|
5702
|
+
if (isRecord6(value.allowed_billing)) {
|
|
4899
5703
|
for (const [type, states] of Object.entries(value.allowed_billing)) {
|
|
4900
5704
|
const list = stringList(states);
|
|
4901
5705
|
if (list) billing[type] = list;
|
|
@@ -5124,7 +5928,7 @@ var RESULT_FIXTURES = {
|
|
|
5124
5928
|
critical: { interpretation: "critical" },
|
|
5125
5929
|
missing_results: { interpretation: "normal", has_missing_results: true }
|
|
5126
5930
|
};
|
|
5127
|
-
var
|
|
5931
|
+
var FAULT_PRESET_RULES = {
|
|
5128
5932
|
sandbox_user_quota: {
|
|
5129
5933
|
operationId: "create_user_v2_user_post",
|
|
5130
5934
|
status: 400,
|
|
@@ -5139,6 +5943,24 @@ var FAULT_PRESETS = {
|
|
|
5139
5943
|
bad_gateway: { status: 502, body: { detail: "Bad Gateway" } },
|
|
5140
5944
|
unavailable: { status: 503, body: { detail: "Service Unavailable" } }
|
|
5141
5945
|
};
|
|
5946
|
+
var FAULT_PRESETS = FAULT_PRESET_RULES;
|
|
5947
|
+
var FAULT_PRESET_DESCRIPTIONS = {
|
|
5948
|
+
sandbox_user_quota: "create_user answers 400 when the sandbox user quota is full",
|
|
5949
|
+
rate_limited: "Every request answers 429 Too Many Requests",
|
|
5950
|
+
server_error: "Every request answers 500 Internal Server Error",
|
|
5951
|
+
bad_gateway: "Every request answers 502 Bad Gateway",
|
|
5952
|
+
unavailable: "Every request answers 503 Service Unavailable"
|
|
5953
|
+
};
|
|
5954
|
+
var faultPresetDescriptions = FAULT_PRESET_DESCRIPTIONS;
|
|
5955
|
+
var junctionFaultPresets = () => {
|
|
5956
|
+
const presets = {};
|
|
5957
|
+
for (const [name, rule] of Object.entries(FAULT_PRESET_RULES)) {
|
|
5958
|
+
const description = faultPresetDescriptions[name];
|
|
5959
|
+
if (description === void 0) continue;
|
|
5960
|
+
presets[name] = { description, rules: [rule] };
|
|
5961
|
+
}
|
|
5962
|
+
return presets;
|
|
5963
|
+
};
|
|
5142
5964
|
var methodOf = (order) => typeof order.lab_test.method === "string" && order.lab_test.method !== "" ? order.lab_test.method : typeof order.details?.type === "string" && order.details.type !== "" ? order.details.type : "at_home_phlebotomy";
|
|
5143
5965
|
var resolveTransition = (method, target) => {
|
|
5144
5966
|
const allowed = ORDER_STATUSES_BY_METHOD[method];
|
|
@@ -5159,7 +5981,7 @@ var resolveTransition = (method, target) => {
|
|
|
5159
5981
|
};
|
|
5160
5982
|
};
|
|
5161
5983
|
var adminError4 = (status, message) => jsonRes(status, { error: { type: "mockingbird_admin", message } });
|
|
5162
|
-
var
|
|
5984
|
+
var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5163
5985
|
var guarded = (run) => {
|
|
5164
5986
|
try {
|
|
5165
5987
|
return run();
|
|
@@ -5186,7 +6008,7 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5186
6008
|
}))
|
|
5187
6009
|
}),
|
|
5188
6010
|
"POST /orders/:id/transition": (request2) => {
|
|
5189
|
-
const body =
|
|
6011
|
+
const body = isRecord7(request2.body) ? request2.body : {};
|
|
5190
6012
|
const order = api(request2).order(request2.params.id);
|
|
5191
6013
|
if (!order) return adminError4(404, `no order ${request2.params.id} in ${request2.namespace}`);
|
|
5192
6014
|
if (typeof body.to !== "string") {
|
|
@@ -5195,7 +6017,7 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5195
6017
|
const method = methodOf(order);
|
|
5196
6018
|
const resolved = resolveTransition(method, body.to);
|
|
5197
6019
|
if ("error" in resolved) return adminError4(400, resolved.error);
|
|
5198
|
-
let flags =
|
|
6020
|
+
let flags = isRecord7(body.flags) ? body.flags : null;
|
|
5199
6021
|
if (typeof body.result === "string") {
|
|
5200
6022
|
const named = RESULT_FIXTURES[body.result];
|
|
5201
6023
|
if (!named) {
|
|
@@ -5222,7 +6044,7 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5222
6044
|
return fixture ? jsonRes(200, fixture) : adminError4(404, "no result fixture for that order");
|
|
5223
6045
|
},
|
|
5224
6046
|
"PUT /results/:id": (request2) => {
|
|
5225
|
-
if (!
|
|
6047
|
+
if (!isRecord7(request2.body)) return adminError4(400, "expected a result fixture object");
|
|
5226
6048
|
const fixture = { name: "custom", ...request2.body };
|
|
5227
6049
|
if (fixture.results !== void 0 && !Array.isArray(fixture.results)) {
|
|
5228
6050
|
return adminError4(400, "results must be an array of result lines");
|
|
@@ -5231,7 +6053,7 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5231
6053
|
},
|
|
5232
6054
|
"GET /lab-accounts": (request2) => jsonRes(200, { data: api(request2).labAccounts() }),
|
|
5233
6055
|
"PUT /lab-accounts": (request2) => {
|
|
5234
|
-
const body =
|
|
6056
|
+
const body = isRecord7(request2.body) ? request2.body : {};
|
|
5235
6057
|
const accounts = body.accounts;
|
|
5236
6058
|
const presets = body.presets;
|
|
5237
6059
|
if (accounts === void 0 && presets === void 0 || accounts !== void 0 && accounts !== null && !Array.isArray(accounts) || presets !== void 0 && !Array.isArray(presets)) {
|
|
@@ -5247,12 +6069,12 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5247
6069
|
return guarded(() => jsonRes(200, { data: api(request2).configureLabAccounts(layout) }));
|
|
5248
6070
|
},
|
|
5249
6071
|
"POST /lab-accounts": (request2) => {
|
|
5250
|
-
if (!
|
|
6072
|
+
if (!isRecord7(request2.body)) return adminError4(400, "expected one lab account object");
|
|
5251
6073
|
const input = request2.body;
|
|
5252
6074
|
return guarded(() => jsonRes(201, api(request2).addLabAccount(input)));
|
|
5253
6075
|
},
|
|
5254
6076
|
"PATCH /lab-accounts/:id": (request2) => {
|
|
5255
|
-
if (!
|
|
6077
|
+
if (!isRecord7(request2.body))
|
|
5256
6078
|
return adminError4(400, "expected an object of fields to change");
|
|
5257
6079
|
const patch = request2.body;
|
|
5258
6080
|
return guarded(() => {
|
|
@@ -5272,7 +6094,7 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5272
6094
|
synthetic: SYNTHETIC_LAB_ACCOUNT_PRESETS
|
|
5273
6095
|
}),
|
|
5274
6096
|
"POST /lab-accounts/presets/:name": (request2) => {
|
|
5275
|
-
const body =
|
|
6097
|
+
const body = isRecord7(request2.body) ? request2.body : {};
|
|
5276
6098
|
if (body.id !== void 0 && typeof body.id !== "string") {
|
|
5277
6099
|
return adminError4(400, "id must be a string");
|
|
5278
6100
|
}
|
|
@@ -5288,14 +6110,14 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5288
6110
|
"GET /team": (request2) => jsonRes(200, { teamId: api(request2).teamId }),
|
|
5289
6111
|
"GET /limits": (request2) => jsonRes(200, { limits: api(request2).limits }),
|
|
5290
6112
|
"PUT /limits": (request2) => {
|
|
5291
|
-
if (!
|
|
6113
|
+
if (!isRecord7(request2.body)) return adminError4(400, "expected an object of limits");
|
|
5292
6114
|
const input = request2.body;
|
|
5293
6115
|
return guarded(() => jsonRes(200, { limits: api(request2).configureLimits(input) }));
|
|
5294
6116
|
},
|
|
5295
6117
|
"GET /default-billing-types": (request2) => jsonRes(200, { defaultBillingTypes: api(request2).defaultBillingTypes }),
|
|
5296
6118
|
"PUT /default-billing-types": (request2) => {
|
|
5297
|
-
const input =
|
|
5298
|
-
if (!
|
|
6119
|
+
const input = isRecord7(request2.body) ? request2.body.defaultBillingTypes : void 0;
|
|
6120
|
+
if (!isRecord7(input))
|
|
5299
6121
|
return adminError4(
|
|
5300
6122
|
400,
|
|
5301
6123
|
'body needs "defaultBillingTypes": { "<lab slug>": "<billing_type>" } ({} restores client_bill)'
|
|
@@ -5307,7 +6129,7 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5307
6129
|
},
|
|
5308
6130
|
"GET /identity": (request2) => jsonRes(200, { identity: api(request2).identity }),
|
|
5309
6131
|
"PUT /identity": (request2) => {
|
|
5310
|
-
const mode =
|
|
6132
|
+
const mode = isRecord7(request2.body) ? request2.body.mode : void 0;
|
|
5311
6133
|
if (!IDENTITY_MODES.includes(mode)) {
|
|
5312
6134
|
return adminError4(400, `body needs "mode": one of ${IDENTITY_MODES.join(", ")}`);
|
|
5313
6135
|
}
|
|
@@ -5315,12 +6137,12 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5315
6137
|
return jsonRes(200, { identity: mode });
|
|
5316
6138
|
},
|
|
5317
6139
|
"POST /users": (request2) => {
|
|
5318
|
-
if (!
|
|
6140
|
+
if (!isRecord7(request2.body)) return adminError4(400, "expected one user object");
|
|
5319
6141
|
const input = request2.body;
|
|
5320
6142
|
return guarded(() => jsonRes(201, api(request2).insertUsers([input])[0]));
|
|
5321
6143
|
},
|
|
5322
6144
|
"POST /users/bulk": (request2) => {
|
|
5323
|
-
const users =
|
|
6145
|
+
const users = isRecord7(request2.body) ? request2.body.users : void 0;
|
|
5324
6146
|
if (!Array.isArray(users)) return adminError4(400, 'body needs "users": an array');
|
|
5325
6147
|
return guarded(
|
|
5326
6148
|
() => jsonRes(201, { users: api(request2).insertUsers(users) })
|
|
@@ -5328,7 +6150,7 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5328
6150
|
},
|
|
5329
6151
|
"DELETE /users/:id": (request2) => api(request2).hardDeleteUser(request2.params.id) ? jsonRes(200, { status: "ok" }) : adminError4(404, `no user ${request2.params.id} in ${request2.namespace}`),
|
|
5330
6152
|
"POST /orders": (request2) => {
|
|
5331
|
-
if (!
|
|
6153
|
+
if (!isRecord7(request2.body)) return adminError4(400, "expected one order object");
|
|
5332
6154
|
const { emitWebhooks, ...input } = request2.body;
|
|
5333
6155
|
return guarded(
|
|
5334
6156
|
() => jsonRes(
|
|
@@ -5340,7 +6162,7 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5340
6162
|
);
|
|
5341
6163
|
},
|
|
5342
6164
|
"POST /import": (request2) => {
|
|
5343
|
-
if (!
|
|
6165
|
+
if (!isRecord7(request2.body)) {
|
|
5344
6166
|
return adminError4(400, 'expected { "users": [...], "orders": [...] }');
|
|
5345
6167
|
}
|
|
5346
6168
|
const { emitWebhooks, ...fixtures } = request2.body;
|
|
@@ -5356,7 +6178,7 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5356
6178
|
geo: api(request2).geoMode
|
|
5357
6179
|
}),
|
|
5358
6180
|
"PUT /geo": (request2) => {
|
|
5359
|
-
const mode =
|
|
6181
|
+
const mode = isRecord7(request2.body) ? request2.body.mode : void 0;
|
|
5360
6182
|
if (mode !== "corpus" && mode !== "synthetic") {
|
|
5361
6183
|
return adminError4(400, 'body needs "mode": "corpus" or "synthetic"');
|
|
5362
6184
|
}
|
|
@@ -5377,24 +6199,6 @@ var junctionAdminRoutes = (options) => (runtime) => {
|
|
|
5377
6199
|
if (!options.webhooks) return adminError4(409, "webhook delivery is off");
|
|
5378
6200
|
await options.webhooks.flush();
|
|
5379
6201
|
return jsonRes(200, { status: "ok" });
|
|
5380
|
-
},
|
|
5381
|
-
"GET /faults/presets": () => jsonRes(200, { presets: FAULT_PRESETS }),
|
|
5382
|
-
"POST /faults/presets/:name": (request2) => {
|
|
5383
|
-
const preset = FAULT_PRESETS[request2.params.name];
|
|
5384
|
-
if (!preset) {
|
|
5385
|
-
return adminError4(
|
|
5386
|
-
404,
|
|
5387
|
-
`no preset ${request2.params.name}; one of ${Object.keys(FAULT_PRESETS).join(", ")}`
|
|
5388
|
-
);
|
|
5389
|
-
}
|
|
5390
|
-
const overrides = isRecord6(request2.body) ? request2.body : {};
|
|
5391
|
-
const rule = runtime.faults.add({
|
|
5392
|
-
namespace: request2.namespace,
|
|
5393
|
-
...preset,
|
|
5394
|
-
...overrides,
|
|
5395
|
-
id: typeof overrides.id === "string" ? overrides.id : request2.params.name
|
|
5396
|
-
});
|
|
5397
|
-
return jsonRes(201, rule);
|
|
5398
6202
|
}
|
|
5399
6203
|
};
|
|
5400
6204
|
};
|
|
@@ -8078,7 +8882,7 @@ var FixtureError = class extends Error {
|
|
|
8078
8882
|
}
|
|
8079
8883
|
status;
|
|
8080
8884
|
};
|
|
8081
|
-
var
|
|
8885
|
+
var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8082
8886
|
var instant = (value, field, fallback) => {
|
|
8083
8887
|
if (value === void 0) return fallback;
|
|
8084
8888
|
if (typeof value !== "string" || Number.isNaN(Date.parse(value)))
|
|
@@ -8102,7 +8906,7 @@ var DEFAULT_PATIENT_ADDRESS = {
|
|
|
8102
8906
|
country: "US"
|
|
8103
8907
|
};
|
|
8104
8908
|
var buildUser = (state, input, now) => {
|
|
8105
|
-
if (!
|
|
8909
|
+
if (!isRecord8(input)) throw new FixtureError(400, "a user fixture must be an object");
|
|
8106
8910
|
if (typeof input.client_user_id !== "string" || input.client_user_id === "")
|
|
8107
8911
|
throw new FixtureError(400, "client_user_id must be a non-empty string");
|
|
8108
8912
|
if (input.user_id !== void 0 && (typeof input.user_id !== "string" || !isUuid3(input.user_id)))
|
|
@@ -8152,7 +8956,7 @@ var insertOrders = (state, inputs, now, options = {}) => {
|
|
|
8152
8956
|
const prepared = [];
|
|
8153
8957
|
const ids = /* @__PURE__ */ new Set();
|
|
8154
8958
|
for (const input of inputs) {
|
|
8155
|
-
if (!
|
|
8959
|
+
if (!isRecord8(input)) throw new FixtureError(400, "an order fixture must be an object");
|
|
8156
8960
|
if (typeof input.user_id !== "string") throw new FixtureError(400, "user_id is required");
|
|
8157
8961
|
if (typeof input.lab_test_id !== "string")
|
|
8158
8962
|
throw new FixtureError(400, "lab_test_id is required");
|
|
@@ -8222,7 +9026,7 @@ var insertOrders = (state, inputs, now, options = {}) => {
|
|
|
8222
9026
|
return prepared.flatMap(({ order }) => state.orders.get(order.id) ?? []);
|
|
8223
9027
|
};
|
|
8224
9028
|
var importFixtures = (state, fixtures, now, options = {}) => {
|
|
8225
|
-
if (!
|
|
9029
|
+
if (!isRecord8(fixtures))
|
|
8226
9030
|
throw new FixtureError(400, 'fixtures must be { "users": [...], "orders": [...] }');
|
|
8227
9031
|
const { users = [], orders = [] } = fixtures;
|
|
8228
9032
|
if (!Array.isArray(users)) throw new FixtureError(400, "users must be an array");
|
|
@@ -8247,7 +9051,7 @@ var requireUser = (state, userId, context, detail = "User does not exist on this
|
|
|
8247
9051
|
var fixtureErrorMessage = (error) => {
|
|
8248
9052
|
if (error instanceof FixtureError) return { status: error.status, message: error.message };
|
|
8249
9053
|
if (error instanceof HttpError) {
|
|
8250
|
-
const detail =
|
|
9054
|
+
const detail = isRecord8(error.body) ? error.body.detail : error.body;
|
|
8251
9055
|
return {
|
|
8252
9056
|
status: error.status,
|
|
8253
9057
|
message: typeof detail === "string" ? detail : JSON.stringify(detail)
|
|
@@ -8257,7 +9061,7 @@ var fixtureErrorMessage = (error) => {
|
|
|
8257
9061
|
};
|
|
8258
9062
|
|
|
8259
9063
|
// src/generated/openapi.ts
|
|
8260
|
-
var document = JSON.parse(`{"openapi":"3.1.0","info":{"title":"Junction API (Mockingbird subset)","description":"Stateful mock subset of the Junction (Vital) API.\\nDocs: https://docs.junction.com/\\nAuth: https://docs.junction.com/api-details/junction-api\\nCreate user: https://docs.junction.com/api-reference/user/create-user\\nGet user: https://docs.junction.com/api-reference/user/get-user\\nDelete user: https://docs.junction.com/api-reference/user/delete-user\\nResolve user: https://docs.junction.com/api-reference/user/resolve-user\\nUpdate user: https://docs.junction.com/api-reference/user/patch-user\\nGet users: https://docs.junction.com/api-reference/user/get-users\\nCreate order: https://docs.junction.com/api-reference/lab-testing/create-order\\nGet order: https://docs.junction.com/api-reference/lab-testing/get-order\\nGet orders: https://docs.junction.com/api-reference/lab-testing/get-orders\\nGet order transaction: https://docs.junction.com/api-reference/lab-testing/order-transactions/get-order-transaction\\nGet order transaction result: https://docs.junction.com/api-reference/lab-testing/results/get-order-transaction-results\\nLab tests: https://docs.junction.com/api-reference/lab-testing/tests-paginated\\nLab tests (deprecated, unpaged): https://docs.junction.com/api-reference/lab-testing/tests/get-lab-tests\\nAppointment availability: https://docs.junction.com/api-reference/lab-testing/appointments/get-appointment-availability\\nBook appointment: https://docs.junction.com/api-reference/lab-testing/appointments/book-appointment\\nGet appointment: https://docs.junction.com/api-reference/lab-testing/appointments/get-appointment\\nReschedule appointment: https://docs.junction.com/api-reference/lab-testing/appointments/reschedule-appointment\\nCancel appointment: https://docs.junction.com/api-reference/lab-testing/appointments/cancel-appointment\\nAppointment cancellation reasons: https://docs.junction.com/api-reference/lab-testing/appointments/get-appointment-cancellation-reasons\\nArea info: https://docs.junction.com/api-reference/lab-testing/service-areas/get-area-info\\nPSC info: https://docs.junction.com/api-reference/lab-testing/service-areas/get-psc-info\\nLab locations: https://docs.junction.com/api-reference/lab-testing/service-areas/get-lab-locations\\nRaw results: https://docs.junction.com/api-reference/lab-testing/results/get-lab-results\\nResult metadata: https://docs.junction.com/api-reference/lab-testing/results/get-lab-results-metadata\\nResult PDF: https://docs.junction.com/api-reference/lab-testing/results/get-lab-result-pdf\\nRequisition form PDF: https://docs.junction.com/api-reference/lab-testing/orders/get-requisition-form\\nList labs: https://docs.junction.com/api-reference/lab-testing/tests/get-labs\\nTest markers: https://docs.junction.com/api-reference/lab-testing/tests/get-markers-for-lab-test\\nOrder-set markers: https://docs.junction.com/api-reference/lab-testing/results/get-order-set-markers\\nLatest user info: https://docs.junction.com/api-reference/user/get-latest-user-info\\n","version":"0.4.758","x-mockingbird-upstream":{"docs":"https://docs.junction.com/","note":"Hand-authored subset from Junction public OpenAPI snippets in the docs."}},"servers":[{"url":"https://api.sandbox.us.junction.com"}],"security":[{"apiKeyAuth":[]}],"paths":{"/v2/user":{"post":{"operationId":"create_user_v2_user_post","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreateBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingUser"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientUserIDConflictResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"operationId":"get_teams_users_v2_user_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedUsersResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"500":{"description":"Internal Server Error","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/v2/user/{user_id}":{"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_user_v2_user__user_id__get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingUser"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"operationId":"delete_user_v2_user__user_id__delete","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSuccessResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"operationId":"patch_user_v2_user__user_id__patch","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPatchBody"}}}},"responses":{"204":{"description":"Successful Response"},"400":{"description":"Nothing to patch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/user/resolve/{client_user_id}":{"parameters":[{"name":"client_user_id","in":"path","required":true,"schema":{"type":"string","minLength":1}}],"get":{"operationId":"get_user_by_client_user_id_v2_user_resolve__client_user_id__get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingUser"},{"$ref":"#/components/schemas/PaginatedUsersResponse"}]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/user/{user_id}/info":{"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user","missing":"00000000-0000-4000-8000-000000000000"}}}],"patch":{"operationId":"patch_user_info_v2_user__user_id__info_patch","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfoPatchBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfo"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/user/{user_id}/info/latest":{"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_latest_user_info_user_v2_user__user_id__info_latest_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfo"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/lab_test":{"get":{"operationId":"get_paginated_lab_tests_for_team_v3_lab_test_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabTestResourcesResponse"}}}}}}},"/v3/lab_test/lab_account":{"get":{"operationId":"get_team_lab_accounts_v3_lab_test_lab_account_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"lab-account inventory is fixture-owned; the mock models the documented shape, filters and routing rules, not a live account inventory"}},"parameters":[{"name":"lab_account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/LabAccountStatus"},{"type":"null"}]}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTeamLabAccountsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/lab_tests":{"get":{"operationId":"get_lab_tests_for_team_v3_lab_tests_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"summary":"Get Lab Tests For Team","description":"GET all the lab tests the team has access to.","deprecated":true,"parameters":[{"name":"generation_method","in":"query","required":false,"schema":{"$ref":"#/components/schemas/LabTestGenerationMethodFilter","description":"Filter on whether auto-generated lab tests created by Vital, manually created lab tests, or all lab tests should be returned.","default":"manual"},"description":"Filter on whether auto-generated lab tests created by Vital, manually created lab tests, or all lab tests should be returned."},{"name":"lab_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by the slug of the lab for these lab tests.","title":"Lab Slug"},"description":"Filter by the slug of the lab for these lab tests."},{"name":"collection_method","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/LabTestCollectionMethod"},{"type":"null"}],"description":"Filter by the collection method for these lab tests.","title":"Collection Method"},"description":"Filter by the collection method for these lab tests."},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/LabTestStatus"},{"type":"null"}],"description":"Filter by the status of these lab tests.","title":"Status"},"description":"Filter by the status of these lab tests."},{"name":"marker_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Filter to only include lab tests containing these marker IDs.","title":"Marker Ids"},"description":"Filter to only include lab tests containing these marker IDs."},{"name":"provider_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter to only include lab tests containing these provider IDs.","title":"Provider Ids"},"description":"Filter to only include lab tests containing these provider IDs."},{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by the name of the lab test (a case-insensitive substring search).","title":"Name"},"description":"Filter by the name of the lab test (a case-insensitive substring search)."},{"name":"order_key","in":"query","required":false,"schema":{"anyOf":[{"enum":["price","created_at","updated_at"],"type":"string"},{"type":"null"}],"title":"Order Key"}},{"name":"order_direction","in":"query","required":false,"schema":{"enum":["asc","desc"],"type":"string","default":"asc","title":"Order Direction"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingLabTest"},"title":"Response Get Lab Tests For Team V3 Lab Tests Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/lab_tests/{lab_test_id}":{"parameters":[{"name":"lab_test_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"lab_test","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_lab_test_for_team_v3_lab_tests__lab_test_id__get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingLabTest"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/lab_tests/labs":{"get":{"operationId":"get_labs_v3_lab_tests_labs_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingLab"}}}}}}}},"/v3/lab_tests/{lab_test_id}/markers":{"parameters":[{"name":"lab_test_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"lab_test","missing":"00000000-0000-4000-8000-000000000000"}}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"provider_id","in":"query","required":false,"schema":{"type":"string"}}],"get":{"operationId":"get_markers_for_lab_test_v3_lab_tests__lab_test_id__markers_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetMarkersResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/lab_tests/list_order_set_markers":{"post":{"operationId":"list_order_set_markers_v3_lab_tests_list_order_set_markers_post","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOrderSetMarkersRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetMarkersResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order":{"post":{"operationId":"create_order_v3_order_post","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostOrderResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"500":{"description":"Internal Server Error"}}}},"/v3/order/area/info":{"get":{"operationId":"get_area_info_v3_order_area_info_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"central_labs presence, within_radius counts and getlabs market coverage are provider-owned geo data that a mock cannot replicate per-zip; covered by the client-parity scenario shape checks instead"}},"parameters":[{"name":"zip_code","in":"query","required":true,"schema":{"type":"string","pattern":"^\\\\d{5}(?:-?\\\\d{4})?$"}},{"name":"radius","in":"query","required":false,"schema":{"$ref":"#/components/schemas/AllowedRadius"}},{"name":"lab_account_id","in":"query","required":false,"description":"Lab Account ID to use for availability checks","schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AreaInfo"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/psc/info":{"get":{"operationId":"get_psc_info_v3_order_psc_info_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"patient_service_centers are real site inventories per zip (thousands of sites, result-capped at 30) that a fixture mock cannot replicate per-zip; covered by the client-parity scenario shape checks instead"}},"parameters":[{"name":"zip_code","in":"query","required":true,"schema":{"type":"string","pattern":"^\\\\d{5}$"}},{"name":"lab_id","in":"query","required":true,"schema":{"type":"integer"}},{"name":"radius","in":"query","required":false,"schema":{"$ref":"#/components/schemas/AllowedRadius"}},{"name":"capabilities","in":"query","required":false,"schema":{"type":"array","items":{"$ref":"#/components/schemas/LabLocationCapability"}}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PscInfo"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/phlebotomy/appointment/availability":{"post":{"operationId":"get_phlebotomy_appointment_availability_v3_order_phlebotomy_appointment_availability_post","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"availability slots are provider-side data whose values shift between sandbox calls; covered by the mock-internal scheduling property suite instead"}},"parameters":[{"name":"start_date","in":"query","required":false,"schema":{"type":"string","format":"date"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsAddress"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentAvailabilitySlots"}}}},"400":{"description":"Availability not bookable for this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No availability found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/phlebotomy/appointment/cancellation-reasons":{"get":{"operationId":"get_phlebotomy_appointment_cancellation_reason_v3_order_phlebotomy_appointment_cancellation_reasons_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingAppointmentCancellationReason"}}}}}}}},"/v3/order/psc/appointment/availability":{"post":{"operationId":"get_psc_appointment_availability_v3_order_psc_appointment_availability_post","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"availability slots are provider-side data whose values shift between sandbox calls; covered by the mock-internal scheduling property suite instead"}},"parameters":[{"name":"lab","in":"query","required":true,"schema":{"$ref":"#/components/schemas/AppointmentPscLabs"}},{"name":"start_date","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"site_codes","in":"query","required":false,"schema":{"type":"string","description":"JSON-encoded array of site codes"}},{"name":"zip_code","in":"query","required":false,"schema":{"type":"string"}},{"name":"radius","in":"query","required":false,"schema":{"$ref":"#/components/schemas/AllowedRadius"}},{"name":"allow_stale","in":"query","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentAvailabilitySlots"}}}},"400":{"description":"Availability not bookable for this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No slots found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/psc/appointment/cancellation-reasons":{"get":{"operationId":"get_psc_appointment_cancellation_reason_v3_order_psc_appointment_cancellation_reasons_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingAppointmentCancellationReason"}}}}}}}},"/v3/order/{order_id}/phlebotomy/appointment":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"appointment payloads embed provider-side slot data; covered by the mock-internal scheduling property suite instead"}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/phlebotomy/appointment/book":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"post":{"operationId":"book_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_book_post","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"booking depends on live provider slot state; covered by the mock-internal scheduling property suite instead"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentBookingRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Booking failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/phlebotomy/appointment/reschedule":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"patch":{"operationId":"reschedule_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_reschedule_patch","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"rescheduling depends on live provider slot state; covered by the mock-internal scheduling property suite instead"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentRescheduleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Invalid or expired booking key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/phlebotomy/appointment/cancel":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"patch":{"operationId":"cancel_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_cancel_patch","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"cancellation depends on live provider appointment state; covered by the mock-internal scheduling property suite instead"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhlebotomyAppointmentCancelRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Invalid cancellation reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/psc/appointment":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_psc_appointment_v3_order__order_id__psc_appointment_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"appointment payloads embed provider-side slot data; covered by the mock-internal scheduling property suite instead"}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/psc/appointment/book":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"post":{"operationId":"book_psc_appointment_v3_order__order_id__psc_appointment_book_post","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"booking depends on live provider slot state; covered by the mock-internal scheduling property suite instead"}},"parameters":[{"name":"x-idempotency-key","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PscAppointmentBookingRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Booking failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/psc/appointment/reschedule":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"patch":{"operationId":"reschedule_psc_appointment_v3_order__order_id__psc_appointment_reschedule_patch","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"rescheduling depends on live provider slot state; covered by the mock-internal scheduling property suite instead"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentRescheduleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Invalid or expired booking key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/psc/appointment/cancel":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"patch":{"operationId":"cancel_psc_appointment_v3_order__order_id__psc_appointment_cancel_patch","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"cancellation depends on live provider appointment state; covered by the mock-internal scheduling property suite instead"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PscAppointmentCancelRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Invalid cancellation reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_order_v3_order__order_id__get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingOrder"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/cancel":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"post":{"operationId":"cancel_order_v3_order__order_id__cancel_post","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostOrderResponse"}}}},"400":{"description":"Order is not in a cancellable status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/test":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"post":{"operationId":"simulate_order_v3_order__order_id__test_post","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"final_status","in":"query","required":true,"schema":{"type":"string","enum":["received.walk_in_test.ordered","received.walk_in_test.requisition_created","received.walk_in_test.requisition_bypassed","completed.walk_in_test.completed","sample_with_lab.walk_in_test.partial_results","failed.walk_in_test.sample_error","cancelled.walk_in_test.cancelled","collecting_sample.walk_in_test.appointment_pending","collecting_sample.walk_in_test.appointment_scheduled","collecting_sample.walk_in_test.appointment_cancelled","collecting_sample.walk_in_test.redraw_available","received.at_home_phlebotomy.ordered","received.at_home_phlebotomy.requisition_created","received.at_home_phlebotomy.requisition_bypassed","collecting_sample.at_home_phlebotomy.appointment_pending","collecting_sample.at_home_phlebotomy.appointment_scheduled","collecting_sample.at_home_phlebotomy.draw_completed","collecting_sample.at_home_phlebotomy.appointment_cancelled","completed.at_home_phlebotomy.completed","sample_with_lab.at_home_phlebotomy.partial_results","cancelled.at_home_phlebotomy.cancelled","failed.at_home_phlebotomy.sample_error","received.testkit.ordered","received.testkit.awaiting_registration","received.testkit.requisition_created","received.testkit.requisition_bypassed","received.testkit.registered","collecting_sample.testkit.transit_customer","collecting_sample.testkit.out_for_delivery","collecting_sample.testkit.with_customer","collecting_sample.testkit.transit_lab","sample_with_lab.testkit.delivered_to_lab","sample_with_lab.testkit.lab_processing_blocked","completed.testkit.completed","failed.testkit.failure_to_deliver_to_customer","failed.testkit.failure_to_deliver_to_lab","failed.testkit.sample_error","failed.testkit.lost","cancelled.testkit.cancelled","cancelled.testkit.do_not_process","collecting_sample.testkit.problem_in_transit_customer","collecting_sample.testkit.problem_in_transit_lab","received.on_site_collection.ordered","received.on_site_collection.requisition_created","received.on_site_collection.requisition_bypassed","sample_with_lab.on_site_collection.draw_completed","completed.on_site_collection.completed","cancelled.on_site_collection.cancelled","sample_with_lab.on_site_collection.partial_results","failed.on_site_collection.sample_error","completed.walk_in_test.corrected","completed.at_home_phlebotomy.corrected","completed.on_site_collection.corrected","completed.testkit.corrected"]}},{"name":"delay","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Seconds to defer the status transition"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimulationFlags"}}}},"responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string","examples":["Success"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/result":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_result_raw_v3_order__order_id__result_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"results carry provider-side specimen data; covered by the mock-internal results property suite instead"}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabResultsRaw"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/result/metadata":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_result_metadata_v3_order__order_id__result_metadata_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabResultsMetadata"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/result/pdf":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_result_pdf_v3_order__order_id__result_pdf_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"PDF bytes are provider-rendered; compared by shape (byteLength) only in the scenario script"}},"responses":{"200":{"description":"Successful Response","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/requisition/pdf":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_order_requisition_pdf_v3_order__order_id__requisition_pdf_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"PDF bytes are provider-rendered; compared by shape (byteLength) only in the scenario script"}},"responses":{"200":{"description":"Successful Response","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/orders":{"get":{"operationId":"get_orders_v3_orders_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"user_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user","missing":"00000000-0000-4000-8000-000000000000"}}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOrdersResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order_transaction/{transaction_id}":{"parameters":[{"name":"transaction_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order_transaction","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_order_transaction_v3_order_transaction__transaction_id__get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"order transactions are not available to the sandbox team (feature not available)"}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOrderTransactionResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order_transaction/{transaction_id}/result":{"parameters":[{"name":"transaction_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order_transaction","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_order_transaction_result_v3_order_transaction__transaction_id__result_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"lab results are not available to the sandbox team (feature not available)"}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabResultsRaw"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"x-vital-api-key"}},"schemas":{"UserCreateBody":{"type":"object","required":["client_user_id"],"properties":{"client_user_id":{"type":"string","minLength":1,"maxLength":64,"examples":["mbr_8891","patient-1042","user.profile_52"]},"fallback_time_zone":{"type":["string","null"],"enum":["America/Los_Angeles","America/New_York","Europe/London","UTC",null]}}},"ClientFacingUser":{"type":"object","required":["user_id","team_id","client_user_id","created_on","connected_sources","fallback_time_zone"],"properties":{"user_id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"user","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"team_id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"account"}},"client_user_id":{"type":"string"},"created_on":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"connected_sources":{"type":"array","items":{"type":"object","additionalProperties":true}},"fallback_time_zone":{"type":["object","null"],"properties":{"id":{"type":"string"},"source_slug":{"type":"string"},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}},"fallback_birth_date":{"type":["object","null"],"properties":{"value":{"type":"string"},"source_slug":{"type":"string"},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}},"ingestion_start":{"type":["string","null"]},"ingestion_end":{"type":["string","null"]}}},"UserInfoPatchBody":{"type":"object","properties":{"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"dob":{"type":["string","null"]},"gender":{"type":["string","null"]},"phone_number":{"type":["string","null"]},"email":{"type":["string","null"]},"address":{"type":["object","null"],"additionalProperties":true}}},"UserInfo":{"type":"object","additionalProperties":true},"ClientUserIDConflictResponse":{"type":"object","required":["detail"],"properties":{"detail":{"type":"object","required":["error_type","error_message","user_id","created_on"],"properties":{"error_type":{"type":"string"},"error_message":{"type":"string"},"user_id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"id"}},"created_on":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}}}},"UserSuccessResponse":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean"}}},"PaginatedUsersResponse":{"type":"object","required":["users","total","offset","limit"],"properties":{"users":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingUser"}},"total":{"type":"integer"},"offset":{"type":"integer"},"limit":{"type":"integer"}}},"UserPatchBody":{"type":"object","properties":{"fallback_time_zone":{"type":["string","null"]},"fallback_birth_date":{"type":["string","null"],"format":"date"},"ingestion_start":{"type":["string","null"],"format":"date"},"ingestion_end":{"type":["string","null"],"format":"date"},"client_user_id":{"type":["string","null"]}}},"LabTestCollectionMethod":{"type":"string","enum":["testkit","walk_in_test","at_home_phlebotomy","on_site_collection"]},"LabTestGenerationMethodFilter":{"type":"string","enum":["auto","manual","all"]},"LabTestSampleType":{"type":"string","enum":["dried_blood_spot","arm_collector","serum","saliva","urine","stool"]},"LabTestStatus":{"type":"string","enum":["active","pending_approval","inactive"]},"MarkerType":{"type":"string","enum":["biomarker","panel"]},"ClientFacingLab":{"type":"object","required":["id","slug","name","first_line_address","city","zipcode","collection_methods","sample_types"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"id"}},"slug":{"type":"string"},"name":{"type":"string"},"first_line_address":{"type":"string"},"city":{"type":"string"},"zipcode":{"type":"string"},"collection_methods":{"type":"array","items":{"$ref":"#/components/schemas/LabTestCollectionMethod"}},"sample_types":{"type":"array","items":{"$ref":"#/components/schemas/LabTestSampleType"}},"logo_url":{"type":["string","null"]}}},"ClientFacingMarker":{"type":"object","required":["id","name","slug"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"id"}},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":["string","null"]},"lab_id":{"type":["integer","null"]},"provider_id":{"type":["string","null"]},"type":{"anyOf":[{"$ref":"#/components/schemas/MarkerType"},{"type":"null"}]},"unit":{"type":["string","null"]},"price":{"type":["string","null"]},"aoe":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]},"a_la_carte_enabled":{"type":"boolean","default":false},"common_tat_days":{"type":["integer","null"]},"worst_case_tat_days":{"type":["integer","null"]},"is_orderable":{"type":["boolean","null"],"default":true}}},"ClientFacingLabTest":{"type":"object","required":["id","slug","name","sample_type","method","price","is_active","status","lab","markers"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"lab_test","identity":true}},"slug":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"name":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"sample_type":{"$ref":"#/components/schemas/LabTestSampleType"},"method":{"$ref":"#/components/schemas/LabTestCollectionMethod"},"price":{"type":"number"},"is_active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/LabTestStatus"},"fasting":{"type":"boolean","default":false},"lab":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingLab"},{"type":"null"}]},"markers":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingMarker"}},{"type":"null"}]},"is_delegated":{"type":"boolean","default":false},"auto_generated":{"type":"boolean","default":false},"has_collection_instructions":{"type":["boolean","null"]},"common_tat_days":{"type":["integer","null"]},"worst_case_tat_days":{"type":["integer","null"]}}},"LabTestResourcesResponse":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingLabTest"}},"next_cursor":{"type":["string","null"]}}},"LabAccountStatus":{"type":"string","enum":["active","pending","suspended","ready_to_launch"]},"LabAccountDelegatedFlow":{"type":"string","enum":["order_delegated","result_delegated","fully_delegated","not_delegated"]},"USState":{"type":"string","enum":["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]},"Labs":{"type":"string","enum":["ayumetrix","spiriplex","ussl","quest","sonora_quest","labcorp","bioreference","us_biotek","manual","sanocardio","ihd","nexus","my_uti","crl","mtl"]},"ClientFacingLabAccount":{"type":"object","required":["id","lab","status","delegated_flow","provider_account_id","allowed_billing","team_id_allowlist"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"lab_account","identity":true}},"lab":{"$ref":"#/components/schemas/Labs"},"org_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"status":{"$ref":"#/components/schemas/LabAccountStatus"},"delegated_flow":{"$ref":"#/components/schemas/LabAccountDelegatedFlow"},"provider_account_id":{"type":"string"},"account_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"default_clinical_notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"business_units":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"allowed_billing":{"type":"object","propertyNames":{"$ref":"#/components/schemas/Billing"},"additionalProperties":{"type":"array","items":{"$ref":"#/components/schemas/USState"}}},"team_id_allowlist":{"type":"array","items":{"type":"string","format":"uuid"}}}},"GetTeamLabAccountsResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingLabAccount"}}}},"ClientFacingResult":{"type":"object","required":["name","slug","type"],"properties":{"name":{"type":"string"},"slug":{"type":"string"},"provider_id":{"type":["string","null"]},"type":{"$ref":"#/components/schemas/ResultType"},"value":{"type":["number","null"]},"unit":{"type":["string","null"]},"low_value":{"type":["number","null"]},"high_value":{"type":["number","null"]},"string_value":{"type":["string","null"]},"coded_value":{"type":["string","null"]},"is_abnormal":{"type":"boolean","default":false},"notes":{"type":["string","null"]}}},"GetMarkersResponse":{"type":"object","required":["markers"],"properties":{"markers":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingMarkerComplete"}},"total":{"type":["integer","null"]},"page":{"type":["integer","null"]},"size":{"type":["integer","null"]},"pages":{"type":["integer","null"]}}},"ClientFacingExpectedResult":{"type":"object","required":["id","name","slug","required"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"id"}},"name":{"type":"string"},"slug":{"type":"string"},"lab_id":{"type":["integer","null"]},"provider_id":{"type":["string","null"]},"required":{"type":"boolean"},"loinc":{"type":["object","null"],"required":["id","name","slug","code"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"id"}},"name":{"type":"string"},"slug":{"type":"string"},"code":{"type":"string"},"unit":{"type":["string","null"]}}}}},"ClientFacingMarkerComplete":{"type":"object","required":["id","name","slug","expected_results"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"id"}},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":["string","null"]},"lab_id":{"type":["integer","null"]},"provider_id":{"type":["string","null"]},"type":{"anyOf":[{"$ref":"#/components/schemas/MarkerType"},{"type":"null"}]},"unit":{"type":["string","null"]},"price":{"type":["string","null"]},"a_la_carte_enabled":{"type":"boolean","default":false},"common_tat_days":{"type":["integer","null"]},"worst_case_tat_days":{"type":["integer","null"]},"is_orderable":{"type":["boolean","null"],"default":true},"expected_results":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingExpectedResult"}}}},"ListOrderSetMarkersRequest":{"type":"object","required":["order_set_id"],"properties":{"order_set_id":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order_transaction","missing":"00000000-0000-4000-8000-000000000000"}},"provider_id":{"type":["string","null"]}}},"AllowedRadius":{"type":"integer","enum":[10,20,25,50,100]},"AppointmentPscLabs":{"type":"string","enum":["quest"]},"AppointmentProvider":{"type":"string","enum":["getlabs","phlebfinders","quest"]},"AppointmentType":{"type":"string","enum":["phlebotomy","patient_service_center"]},"AppointmentStatus":{"type":"string","enum":["confirmed","pending","reserved","in_progress","completed","cancelled"]},"AppointmentEventStatus":{"type":"string","enum":["pending","reserved","scheduled","completed","cancelled","in_progress"]},"AppointmentServiceType":{"type":"string","enum":["appointment-ready","appointment-request"]},"Billing":{"type":"string","enum":["client_bill","commercial_insurance","patient_bill_passthrough","patient_bill"]},"LabLocationCapability":{"type":"string","enum":["stat","appointment_scheduling_via_junction","appointment_scheduling_with_lab"]},"LngLat":{"type":"object","required":["lng","lat"],"properties":{"lng":{"type":"number"},"lat":{"type":"number"}}},"UsAddress":{"type":"object","required":["first_line","city","state","zip_code"],"properties":{"first_line":{"type":"string","minLength":1},"second_line":{"type":["string","null"]},"city":{"type":"string","minLength":1},"state":{"type":"string","minLength":1},"zip_code":{"type":"string","minLength":1},"unit":{"type":["string","null"]}}},"AppointmentLocation":{"type":"object","required":["location","address","code","name"],"properties":{"location":{"$ref":"#/components/schemas/LngLat"},"distance":{"type":["number","null"]},"address":{"$ref":"#/components/schemas/UsAddress"},"code":{"type":"string"},"name":{"type":"string"},"iana_timezone":{"type":["string","null"]}}},"TimeSlot":{"type":"object","required":["start","end","price","is_priority","num_appointments_available"],"properties":{"booking_key":{"type":["string","null"],"x-mockingbird-resource":{"type":"booking_key","identity":true},"x-mockingbird-volatile":{"kind":"token"}},"start":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"end":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"expires_at":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"timestamp"}},"price":{"type":"number"},"is_priority":{"type":"boolean"},"num_appointments_available":{"type":"integer"}}},"DaySlots":{"type":"object","required":["date","slots"],"properties":{"location":{"anyOf":[{"$ref":"#/components/schemas/AppointmentLocation"},{"type":"null"}]},"date":{"type":"string","format":"date"},"slots":{"type":"array","items":{"$ref":"#/components/schemas/TimeSlot"}}}},"AppointmentAvailabilitySlots":{"type":"object","required":["slots"],"properties":{"slots":{"type":"array","items":{"$ref":"#/components/schemas/DaySlots"}},"timezone":{"type":["string","null"]}}},"AppointmentBookingRequest":{"type":"object","required":["booking_key"],"properties":{"booking_key":{"type":"string","minLength":1,"x-mockingbird-resource-ref":{"type":"booking_key"}}}},"AppointmentRescheduleRequest":{"type":"object","required":["booking_key"],"properties":{"booking_key":{"type":"string","minLength":1,"x-mockingbird-resource-ref":{"type":"booking_key"}}}},"PscAppointmentBookingRequest":{"type":"object","required":["booking_key","site_code"],"properties":{"booking_key":{"type":"string","minLength":1,"x-mockingbird-resource-ref":{"type":"booking_key"}},"site_code":{"type":"string","minLength":1}}},"PhlebotomyAppointmentCancelRequest":{"type":"object","required":["cancellation_reason_id"],"properties":{"cancellation_reason_id":{"type":"string","minLength":1},"notes":{"type":["string","null"]}}},"PscAppointmentCancelRequest":{"type":"object","required":["cancellationReasonId"],"properties":{"cancellationReasonId":{"type":"string","minLength":1},"note":{"type":["string","null"]}}},"ClientFacingAppointmentEvent":{"type":"object","required":["created_at","status"],"properties":{"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"status":{"$ref":"#/components/schemas/AppointmentEventStatus"},"data":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"ClientFacingAppointment":{"type":"object","required":["id","user_id","order_id","address","location","type","provider","status","provider_id","can_reschedule","event_status","events"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"appointment","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"user_id":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user"}},"order_id":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order"}},"address":{"$ref":"#/components/schemas/UsAddress"},"location":{"$ref":"#/components/schemas/LngLat"},"start_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"end_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"iana_timezone":{"type":["string","null"]},"type":{"$ref":"#/components/schemas/AppointmentType"},"provider":{"$ref":"#/components/schemas/AppointmentProvider"},"status":{"$ref":"#/components/schemas/AppointmentStatus"},"provider_id":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"external_id":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"id"}},"can_reschedule":{"type":"boolean"},"event_status":{"$ref":"#/components/schemas/AppointmentEventStatus"},"event_data":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]},"order_transaction_id":{"type":["string","null"],"x-mockingbird-resource-ref":{"type":"order_transaction"}},"appointment_notes":{"type":["string","null"]},"events":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingAppointmentEvent"}}}},"ClientFacingAppointmentCancellationReason":{"type":"object","required":["id","name","is_refundable"],"properties":{"id":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"name":{"type":"string"},"is_refundable":{"type":"boolean"}}},"PhlebotomyAreaInfo":{"type":"object","required":["is_served","providers"],"properties":{"is_served":{"type":"boolean"},"providers":{"type":"array","items":{"$ref":"#/components/schemas/PhlebotomyProviderInfo"}}}},"PhlebotomyProviderInfo":{"type":"object","required":["name","service_types"],"properties":{"name":{"$ref":"#/components/schemas/AppointmentProvider"},"service_types":{"type":"array","items":{"$ref":"#/components/schemas/AppointmentServiceType"}}}},"PscAreaInfoDetails":{"type":"object","required":["appointment_with_vital","within_radius","radius"],"properties":{"appointment_with_vital":{"type":"boolean"},"within_radius":{"type":"number"},"radius":{"type":"string"},"capabilities":{"type":["array","null"],"items":{"$ref":"#/components/schemas/LabLocationCapability"}}}},"PscAreaInfo":{"type":"object","required":["patient_service_centers","supported_bill_types","lab_id"],"properties":{"patient_service_centers":{"$ref":"#/components/schemas/PscAreaInfoDetails"},"supported_bill_types":{"type":"array","items":{"$ref":"#/components/schemas/Billing"}},"lab_id":{"type":"integer"}}},"AreaInfo":{"type":"object","required":["zip_code","phlebotomy","central_labs"],"properties":{"zip_code":{"type":"string"},"phlebotomy":{"$ref":"#/components/schemas/PhlebotomyAreaInfo"},"central_labs":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PscAreaInfo"}}}},"LabLocationMetadata":{"type":"object","required":["name","state","city","zip_code","first_line"],"properties":{"name":{"type":"string"},"state":{"type":"string"},"city":{"type":"string"},"zip_code":{"type":"string"},"first_line":{"type":"string"},"second_line":{"type":["string","null"]},"phone_number":{"type":["string","null"]},"fax_number":{"type":["string","null"]},"hours":{"type":["object","null"],"additionalProperties":true}}},"ClientFacingLabLocation":{"type":"object","required":["metadata","distance","site_code","supported_bill_types","location","capabilities"],"properties":{"metadata":{"$ref":"#/components/schemas/LabLocationMetadata"},"distance":{"type":"number"},"site_code":{"type":"string"},"supported_bill_types":{"type":"array","items":{"$ref":"#/components/schemas/Billing"}},"location":{"$ref":"#/components/schemas/LngLat"},"capabilities":{"type":"array","items":{"$ref":"#/components/schemas/LabLocationCapability"}}}},"PscInfo":{"type":"object","required":["lab_id","slug","patient_service_centers"],"properties":{"lab_id":{"type":"integer"},"slug":{"type":"string"},"patient_service_centers":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingLabLocation"}}}},"OrderTopLevelStatus":{"type":"string","enum":["received","collecting_sample","sample_with_lab","completed","cancelled","failed"]},"OrderLowLevelStatus":{"type":"string","enum":["ordered","requisition_created","requisition_bypassed","transit_customer","out_for_delivery","with_customer","transit_lab","delivered_to_lab","completed","failure_to_deliver_to_lab","failure_to_deliver_to_customer","problem_in_transit_lab","problem_in_transit_customer","sample_error","appointment_scheduled","appointment_cancelled","appointment_pending","draw_completed","cancelled","lost","do_not_process","partial_results","awaiting_registration","registered","redraw_available","corrected","lab_processing_blocked"]},"OrderStatus":{"type":"string","enum":["received.walk_in_test.ordered","received.walk_in_test.requisition_created","received.walk_in_test.requisition_bypassed","completed.walk_in_test.completed","sample_with_lab.walk_in_test.partial_results","failed.walk_in_test.sample_error","cancelled.walk_in_test.cancelled","collecting_sample.walk_in_test.appointment_pending","collecting_sample.walk_in_test.appointment_scheduled","collecting_sample.walk_in_test.appointment_cancelled","collecting_sample.walk_in_test.redraw_available","received.at_home_phlebotomy.ordered","received.at_home_phlebotomy.requisition_created","received.at_home_phlebotomy.requisition_bypassed","collecting_sample.at_home_phlebotomy.appointment_pending","collecting_sample.at_home_phlebotomy.appointment_scheduled","collecting_sample.at_home_phlebotomy.draw_completed","collecting_sample.at_home_phlebotomy.appointment_cancelled","completed.at_home_phlebotomy.completed","sample_with_lab.at_home_phlebotomy.partial_results","cancelled.at_home_phlebotomy.cancelled","failed.at_home_phlebotomy.sample_error","received.testkit.ordered","received.testkit.awaiting_registration","received.testkit.requisition_created","received.testkit.requisition_bypassed","received.testkit.registered","collecting_sample.testkit.transit_customer","collecting_sample.testkit.out_for_delivery","collecting_sample.testkit.with_customer","collecting_sample.testkit.transit_lab","sample_with_lab.testkit.delivered_to_lab","sample_with_lab.testkit.lab_processing_blocked","completed.testkit.completed","failed.testkit.failure_to_deliver_to_customer","failed.testkit.failure_to_deliver_to_lab","failed.testkit.sample_error","failed.testkit.lost","cancelled.testkit.cancelled","cancelled.testkit.do_not_process","collecting_sample.testkit.problem_in_transit_customer","collecting_sample.testkit.problem_in_transit_lab","received.on_site_collection.ordered","received.on_site_collection.requisition_created","received.on_site_collection.requisition_bypassed","sample_with_lab.on_site_collection.draw_completed","completed.on_site_collection.completed","cancelled.on_site_collection.cancelled","sample_with_lab.on_site_collection.partial_results","failed.on_site_collection.sample_error","completed.walk_in_test.corrected","completed.at_home_phlebotomy.corrected","completed.on_site_collection.corrected","completed.testkit.corrected"]},"OrderStatusDetail":{"type":"string","enum":["fulfillment_error","date_of_collection_unspecified","demographic_information_unspecified","demographic_information_mismatch","sample_quantity_not_sufficient","sample_contaminated","sample_stability_exceeded","sample_hemolyzed","sample_improper_collection"]},"OrderTransactionStatus":{"type":"string","enum":["active","completed","cancelled"]},"ClientFacingOrderEvent":{"type":"object","required":["id","created_at","status"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"opaque"}},"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"status":{"$ref":"#/components/schemas/OrderStatus"},"status_detail":{"anyOf":[{"$ref":"#/components/schemas/OrderStatusDetail"},{"type":"null"}]}}},"ShippingAddress":{"type":"object","required":["receiver_name","first_line","city","state","zip","country","phone_number"],"properties":{"receiver_name":{"type":"string"},"first_line":{"type":"string"},"second_line":{"type":["string","null"]},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"},"phone_number":{"type":"string"}}},"ClientFacingPhysician":{"type":"object","required":["first_name","last_name","npi"],"properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"npi":{"type":"string"}}},"ClientFacingShipment":{"type":"object","required":["id","outbound_tracking_number","outbound_tracking_url","inbound_tracking_number","inbound_tracking_url","outbound_courier","inbound_courier","notes"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"id"}},"outbound_tracking_number":{"type":["string","null"]},"outbound_tracking_url":{"type":["string","null"]},"inbound_tracking_number":{"type":["string","null"]},"inbound_tracking_url":{"type":["string","null"]},"outbound_courier":{"type":["string","null"]},"inbound_courier":{"type":["string","null"]},"notes":{"type":["string","null"]}}},"ClientFacingTestkitOrder":{"type":"object","required":["id","shipment","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"id"}},"shipment":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingShipment"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"opaque"}},"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}},"ClientFacingWalkInOrder":{"type":"object","required":["id","appointment_id","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"id"}},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}},"ClientFacingTestKitOrderDetails":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["testkit","walk_in_test","at_home_phlebotomy","on_site_collection"]},"data":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingTestkitOrder"},{"$ref":"#/components/schemas/ClientFacingWalkInOrder"},{"type":"null"}]}}},"ClientFacingPatientDetailsCompatible":{"type":"object","required":["first_name","last_name","dob","gender","phone_number","email"],"properties":{"first_name":{"type":"string","minLength":1,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9 .,'-]*$","examples":["Ada","Chris","Maria","Jun"]},"last_name":{"type":"string","minLength":1,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9 .,'-]*$","examples":["Lovelace","Vouga","Delgado","Park"]},"dob":{"type":"string","format":"date-time","examples":["1990-06-15T00:00:00.000Z","1983-02-02T00:00:00.000Z"]},"gender":{"type":"string","minLength":1,"pattern":"\\\\S","examples":["male","female","other","prefer_not_to_say"]},"phone_number":{"type":"string","minLength":1,"pattern":"^\\\\+1[2-9]\\\\d{9}$","examples":["+14155550123","+12125550987","+13105554444"]},"email":{"type":"string","format":"email","minLength":1,"examples":["ada@example.com","chris@example.com","maria@example.com"]}}},"PatientAddressCompatible":{"type":"object","required":["first_line","city","state","zip","country"],"properties":{"receiver_name":{"type":"string","default":"","examples":["Ada Lovelace","Chris Vouga"]},"first_line":{"type":"string","minLength":1,"pattern":"\\\\S","examples":["1 Main St","450 Market St","88 Kearny St"]},"second_line":{"type":["string","null"]},"city":{"type":"string","minLength":1,"pattern":"\\\\S","examples":["San Diego","San Francisco","New York"]},"state":{"type":"string","minLength":1,"enum":["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]},"zip":{"type":"string","pattern":"^\\\\d{5}(-\\\\d{4})?$","examples":["92101","94105","10001"]},"country":{"type":"string","minLength":1,"pattern":"\\\\S","examples":["US"]},"access_notes":{"type":["string","null"],"examples":[null]},"phone_number":{"type":["string","null"],"examples":["+14155550123",null]}}},"AoeAnswerRequest":{"type":"object","required":["marker_id","question_id","answer"],"properties":{"marker_id":{"type":"integer","examples":[2075,1975]},"question_id":{"type":"integer","examples":[1]},"answer":{"type":"string","minLength":1,"examples":["No","Yes"]}}},"ClientFacingOrderInTransaction":{"type":"object","required":["id","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"low_level_status":{"anyOf":[{"$ref":"#/components/schemas/OrderLowLevelStatus"},{"type":"null"}]},"low_level_status_created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}},"ClientFacingOrderTransaction":{"type":"object","required":["id","status","orders"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"order_transaction","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"status":{"$ref":"#/components/schemas/OrderTransactionStatus"},"orders":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingOrderInTransaction"}}}},"OrderSummary":{"type":"object","required":["id","last_status","last_status_created_at","updated_at","created_at"],"properties":{"id":{"type":"string","format":"uuid"},"origin":{"anyOf":[{"type":"string","enum":["initial","redraw","recreation"]},{"type":"null"}]},"parent_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"last_status":{"$ref":"#/components/schemas/OrderLowLevelStatus"},"last_status_created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"GetOrderTransactionResponse":{"type":"object","required":["id","team_id","status"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"order_transaction","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"team_id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"account"}},"status":{"$ref":"#/components/schemas/OrderTransactionStatus"},"orders":{"type":"array","items":{"$ref":"#/components/schemas/OrderSummary"}}}},"ClientFacingOrder":{"type":"object","required":["user_id","id","team_id","patient_details","patient_address","lab_test","details","sample_id","notes","created_at","updated_at","events","last_event","health_insurance_id","requisition_form_url","shipping_details","has_abn"],"properties":{"user_id":{"type":"string","format":"uuid"},"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"order","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"team_id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"account"}},"patient_details":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingPatientDetailsCompatible"},{"type":"null"}]},"patient_address":{"anyOf":[{"$ref":"#/components/schemas/PatientAddressCompatible"},{"type":"null"}]},"lab_test":{"$ref":"#/components/schemas/ClientFacingLabTest"},"details":{"$ref":"#/components/schemas/ClientFacingTestKitOrderDetails"},"sample_id":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"opaque"}},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"clinical_notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingOrderEvent"}},"status":{"anyOf":[{"$ref":"#/components/schemas/OrderTopLevelStatus"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"opaque"}},"last_event":{"$ref":"#/components/schemas/ClientFacingOrderEvent"},"physician":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingPhysician"},{"type":"null"}]},"health_insurance_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"requisition_form_url":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"url"}},"priority":{"type":"boolean","default":false},"shipping_details":{"anyOf":[{"$ref":"#/components/schemas/ShippingAddress"},{"type":"null"}]},"activate_by":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"passthrough":{"anyOf":[{"type":"string"},{"type":"null"}]},"billing_type":{"type":"string","enum":["client_bill","commercial_insurance","patient_bill_passthrough","patient_bill","upfront_payment"],"default":"client_bill"},"icd_codes":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"has_abn":{"type":"boolean"},"interpretation":{"anyOf":[{"type":"string","enum":["normal","abnormal","critical","unknown"]},{"type":"null"}]},"has_missing_results":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"expected_result_by_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"worst_case_result_by_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"origin":{"anyOf":[{"type":"string","enum":["initial","redraw","recreation"]},{"type":"null"}]},"order_transaction":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingOrderTransaction"},{"type":"null"}]}}},"OrderSetRequest":{"type":"object","required":["lab_test_ids"],"properties":{"lab_test_ids":{"type":"array","minItems":1,"items":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"lab_test","missing":"00000000-0000-4000-8000-000000000000"}}}}},"CreateOrderRequest":{"type":"object","required":["user_id","patient_details","patient_address","order_set"],"properties":{"user_id":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user","missing":"00000000-0000-4000-8000-000000000000"}},"patient_details":{"$ref":"#/components/schemas/ClientFacingPatientDetailsCompatible"},"patient_address":{"$ref":"#/components/schemas/PatientAddressCompatible"},"order_set":{"$ref":"#/components/schemas/OrderSetRequest"},"clinical_notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"passthrough":{"anyOf":[{"type":"string"},{"type":"null"}]},"collection_method":{"$ref":"#/components/schemas/LabTestCollectionMethod"},"lab_account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"idempotency_key":{"type":["string","null"]},"idempotency_error":{"type":["string","null"]},"aoe_answers":{"type":["array","null"],"items":{"$ref":"#/components/schemas/AoeAnswerRequest"}}}},"PostOrderResponse":{"type":"object","required":["order","status","message"],"properties":{"order":{"$ref":"#/components/schemas/ClientFacingOrder"},"status":{"type":"string"},"message":{"type":"string"}}},"ResultType":{"type":"string","enum":["numeric","range","comment","coded_value"]},"ParentBiomarkerData":{"type":"object","required":["marker_id","name","slug"],"properties":{"marker_id":{"type":"integer"},"name":{"type":"string"},"slug":{"type":"string"},"provider_id":{"type":["string","null"]}}},"BiomarkerResult":{"type":"object","required":["name","result","type"],"properties":{"name":{"type":"string"},"slug":{"type":"string","default":""},"value":{"anyOf":[{"type":"number"},{"type":"null"}]},"result":{"type":"string"},"type":{"$ref":"#/components/schemas/ResultType"},"unit":{"type":["string","null"]},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"notes":{"type":["string","null"]},"reference_range":{"type":["string","null"]},"min_range_value":{"type":["number","null"]},"max_range_value":{"type":["number","null"]},"is_above_max_range":{"type":["boolean","null"]},"is_below_min_range":{"type":["boolean","null"]},"interpretation":{"type":"string","default":"normal"},"source_interpretation":{"type":"string","default":""},"loinc":{"type":["string","null"]},"loinc_slug":{"type":["string","null"]},"provider_id":{"type":["string","null"]},"source_markers":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/ParentBiomarkerData"}},{"type":"null"}]},"performing_laboratory":{"type":["string","null"]},"source_sample_id":{"type":["string","null"]}}},"FailureType":{"type":"string","enum":["quantity_not_sufficient_failure","collection_process_failure","drop_off_failure","internal_lab_failure","order_entry_failure","non_failure","unknown_failure","patient_condition_failure","missing_result_calc_failure","missing_demo_aoe_calc_failure","insufficient_volume"]},"MissingBiomarkerResult":{"type":"object","required":["name","slug","inferred_failure_type"],"properties":{"name":{"type":"string"},"slug":{"type":"string"},"inferred_failure_type":{"$ref":"#/components/schemas/FailureType"},"note":{"type":["string","null"]},"loinc":{"type":["string","null"]},"loinc_slug":{"type":["string","null"]},"provider_id":{"type":["string","null"]},"source_markers":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/ParentBiomarkerData"}},{"type":"null"}]}}},"SampleData":{"type":"object","properties":{"sample_id":{"type":["string","null"]},"control_number":{"type":["string","null"]},"date_collected":{"type":["string","null"]},"date_received":{"type":["string","null"]},"date_reported":{"type":["string","null"]},"performing_laboratories":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]},"clinical_information":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"LabResultsMetadata":{"type":"object","required":["age","dob","patient","date_reported","specimen_number"],"properties":{"age":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"dob":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"clia_#":{"anyOf":[{"type":"string"},{"type":"null"}]},"patient":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"token"}},"laboratory":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"token"}},"date_reported":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"date_collected":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"specimen_number":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"date_received":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"status":{"type":"string","default":"final"},"interpretation":{"anyOf":[{"type":"string"},{"type":"null"}]},"patient_id":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"id"}},"account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"id"}}}},"LabResultsRaw":{"type":"object","required":["metadata","results"],"properties":{"metadata":{"$ref":"#/components/schemas/LabResultsMetadata"},"results":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/BiomarkerResult"}},{"type":"object","additionalProperties":true}],"x-mockingbird-volatile":{"kind":"opaque"}},"missing_results":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/MissingBiomarkerResult"}},{"type":"null"}],"x-mockingbird-volatile":{"kind":"opaque"}},"sample_information":{"anyOf":[{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SampleData"}},{"type":"null"}],"x-mockingbird-volatile":{"kind":"opaque"}},"order_transaction":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingOrderTransaction"},{"type":"null"}]}}},"SimulationFlags":{"type":"object","properties":{"interpretation":{"anyOf":[{"type":"string","enum":["normal","abnormal","critical","unknown"]},{"type":"null"}]},"result_types":{"type":"array","items":{"$ref":"#/components/schemas/ResultType"}},"has_missing_results":{"type":"boolean"}}},"GetOrdersResponse":{"type":"object","required":["orders"],"properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingOrder"}},"total":{"anyOf":[{"type":"integer"},{"type":"null"}]},"page":{"anyOf":[{"type":"integer"},{"type":"null"}]},"size":{"anyOf":[{"type":"integer"},{"type":"null"}]}}},"HTTPValidationError":{"type":"object","properties":{"detail":{"title":"Detail"}}}}}}`);
|
|
9064
|
+
var document2 = JSON.parse(`{"openapi":"3.1.0","info":{"title":"Junction API (Mockingbird subset)","description":"Stateful mock subset of the Junction (Vital) API.\\nDocs: https://docs.junction.com/\\nAuth: https://docs.junction.com/api-details/junction-api\\nCreate user: https://docs.junction.com/api-reference/user/create-user\\nGet user: https://docs.junction.com/api-reference/user/get-user\\nDelete user: https://docs.junction.com/api-reference/user/delete-user\\nResolve user: https://docs.junction.com/api-reference/user/resolve-user\\nUpdate user: https://docs.junction.com/api-reference/user/patch-user\\nGet users: https://docs.junction.com/api-reference/user/get-users\\nCreate order: https://docs.junction.com/api-reference/lab-testing/create-order\\nGet order: https://docs.junction.com/api-reference/lab-testing/get-order\\nGet orders: https://docs.junction.com/api-reference/lab-testing/get-orders\\nGet order transaction: https://docs.junction.com/api-reference/lab-testing/order-transactions/get-order-transaction\\nGet order transaction result: https://docs.junction.com/api-reference/lab-testing/results/get-order-transaction-results\\nLab tests: https://docs.junction.com/api-reference/lab-testing/tests-paginated\\nLab tests (deprecated, unpaged): https://docs.junction.com/api-reference/lab-testing/tests/get-lab-tests\\nAppointment availability: https://docs.junction.com/api-reference/lab-testing/appointments/get-appointment-availability\\nBook appointment: https://docs.junction.com/api-reference/lab-testing/appointments/book-appointment\\nGet appointment: https://docs.junction.com/api-reference/lab-testing/appointments/get-appointment\\nReschedule appointment: https://docs.junction.com/api-reference/lab-testing/appointments/reschedule-appointment\\nCancel appointment: https://docs.junction.com/api-reference/lab-testing/appointments/cancel-appointment\\nAppointment cancellation reasons: https://docs.junction.com/api-reference/lab-testing/appointments/get-appointment-cancellation-reasons\\nArea info: https://docs.junction.com/api-reference/lab-testing/service-areas/get-area-info\\nPSC info: https://docs.junction.com/api-reference/lab-testing/service-areas/get-psc-info\\nLab locations: https://docs.junction.com/api-reference/lab-testing/service-areas/get-lab-locations\\nRaw results: https://docs.junction.com/api-reference/lab-testing/results/get-lab-results\\nResult metadata: https://docs.junction.com/api-reference/lab-testing/results/get-lab-results-metadata\\nResult PDF: https://docs.junction.com/api-reference/lab-testing/results/get-lab-result-pdf\\nRequisition form PDF: https://docs.junction.com/api-reference/lab-testing/orders/get-requisition-form\\nList labs: https://docs.junction.com/api-reference/lab-testing/tests/get-labs\\nTest markers: https://docs.junction.com/api-reference/lab-testing/tests/get-markers-for-lab-test\\nOrder-set markers: https://docs.junction.com/api-reference/lab-testing/results/get-order-set-markers\\nLatest user info: https://docs.junction.com/api-reference/user/get-latest-user-info\\n","version":"0.4.758","x-mockingbird-upstream":{"docs":"https://docs.junction.com/","note":"Hand-authored subset from Junction public OpenAPI snippets in the docs."}},"servers":[{"url":"https://api.sandbox.us.junction.com"}],"security":[{"apiKeyAuth":[]}],"paths":{"/v2/user":{"post":{"operationId":"create_user_v2_user_post","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreateBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingUser"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientUserIDConflictResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"operationId":"get_teams_users_v2_user_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"offset","in":"query","required":false,"schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedUsersResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"500":{"description":"Internal Server Error","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/v2/user/{user_id}":{"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_user_v2_user__user_id__get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingUser"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"operationId":"delete_user_v2_user__user_id__delete","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSuccessResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"operationId":"patch_user_v2_user__user_id__patch","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPatchBody"}}}},"responses":{"204":{"description":"Successful Response"},"400":{"description":"Nothing to patch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/user/resolve/{client_user_id}":{"parameters":[{"name":"client_user_id","in":"path","required":true,"schema":{"type":"string","minLength":1}}],"get":{"operationId":"get_user_by_client_user_id_v2_user_resolve__client_user_id__get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingUser"},{"$ref":"#/components/schemas/PaginatedUsersResponse"}]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/user/{user_id}/info":{"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user","missing":"00000000-0000-4000-8000-000000000000"}}}],"patch":{"operationId":"patch_user_info_v2_user__user_id__info_patch","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfoPatchBody"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfo"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v2/user/{user_id}/info/latest":{"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_latest_user_info_user_v2_user__user_id__info_latest_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfo"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/lab_test":{"get":{"operationId":"get_paginated_lab_tests_for_team_v3_lab_test_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabTestResourcesResponse"}}}}}}},"/v3/lab_test/lab_account":{"get":{"operationId":"get_team_lab_accounts_v3_lab_test_lab_account_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"lab-account inventory is fixture-owned; the mock models the documented shape, filters and routing rules, not a live account inventory"}},"parameters":[{"name":"lab_account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/LabAccountStatus"},{"type":"null"}]}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetTeamLabAccountsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/lab_tests":{"get":{"operationId":"get_lab_tests_for_team_v3_lab_tests_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"summary":"Get Lab Tests For Team","description":"GET all the lab tests the team has access to.","deprecated":true,"parameters":[{"name":"generation_method","in":"query","required":false,"schema":{"$ref":"#/components/schemas/LabTestGenerationMethodFilter","description":"Filter on whether auto-generated lab tests created by Vital, manually created lab tests, or all lab tests should be returned.","default":"manual"},"description":"Filter on whether auto-generated lab tests created by Vital, manually created lab tests, or all lab tests should be returned."},{"name":"lab_slug","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by the slug of the lab for these lab tests.","title":"Lab Slug"},"description":"Filter by the slug of the lab for these lab tests."},{"name":"collection_method","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/LabTestCollectionMethod"},{"type":"null"}],"description":"Filter by the collection method for these lab tests.","title":"Collection Method"},"description":"Filter by the collection method for these lab tests."},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/LabTestStatus"},{"type":"null"}],"description":"Filter by the status of these lab tests.","title":"Status"},"description":"Filter by the status of these lab tests."},{"name":"marker_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Filter to only include lab tests containing these marker IDs.","title":"Marker Ids"},"description":"Filter to only include lab tests containing these marker IDs."},{"name":"provider_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter to only include lab tests containing these provider IDs.","title":"Provider Ids"},"description":"Filter to only include lab tests containing these provider IDs."},{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by the name of the lab test (a case-insensitive substring search).","title":"Name"},"description":"Filter by the name of the lab test (a case-insensitive substring search)."},{"name":"order_key","in":"query","required":false,"schema":{"anyOf":[{"enum":["price","created_at","updated_at"],"type":"string"},{"type":"null"}],"title":"Order Key"}},{"name":"order_direction","in":"query","required":false,"schema":{"enum":["asc","desc"],"type":"string","default":"asc","title":"Order Direction"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingLabTest"},"title":"Response Get Lab Tests For Team V3 Lab Tests Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/lab_tests/{lab_test_id}":{"parameters":[{"name":"lab_test_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"lab_test","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_lab_test_for_team_v3_lab_tests__lab_test_id__get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingLabTest"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/lab_tests/labs":{"get":{"operationId":"get_labs_v3_lab_tests_labs_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingLab"}}}}}}}},"/v3/lab_tests/{lab_test_id}/markers":{"parameters":[{"name":"lab_test_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"lab_test","missing":"00000000-0000-4000-8000-000000000000"}}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"provider_id","in":"query","required":false,"schema":{"type":"string"}}],"get":{"operationId":"get_markers_for_lab_test_v3_lab_tests__lab_test_id__markers_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetMarkersResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/lab_tests/list_order_set_markers":{"post":{"operationId":"list_order_set_markers_v3_lab_tests_list_order_set_markers_post","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListOrderSetMarkersRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetMarkersResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order":{"post":{"operationId":"create_order_v3_order_post","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostOrderResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"500":{"description":"Internal Server Error"}}}},"/v3/order/area/info":{"get":{"operationId":"get_area_info_v3_order_area_info_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"central_labs presence, within_radius counts and getlabs market coverage are provider-owned geo data that a mock cannot replicate per-zip; covered by the client-parity scenario shape checks instead"}},"parameters":[{"name":"zip_code","in":"query","required":true,"schema":{"type":"string","pattern":"^\\\\d{5}(?:-?\\\\d{4})?$"}},{"name":"radius","in":"query","required":false,"schema":{"$ref":"#/components/schemas/AllowedRadius"}},{"name":"lab_account_id","in":"query","required":false,"description":"Lab Account ID to use for availability checks","schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AreaInfo"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/psc/info":{"get":{"operationId":"get_psc_info_v3_order_psc_info_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"patient_service_centers are real site inventories per zip (thousands of sites, result-capped at 30) that a fixture mock cannot replicate per-zip; covered by the client-parity scenario shape checks instead"}},"parameters":[{"name":"zip_code","in":"query","required":true,"schema":{"type":"string","pattern":"^\\\\d{5}$"}},{"name":"lab_id","in":"query","required":true,"schema":{"type":"integer"}},{"name":"radius","in":"query","required":false,"schema":{"$ref":"#/components/schemas/AllowedRadius"}},{"name":"capabilities","in":"query","required":false,"schema":{"type":"array","items":{"$ref":"#/components/schemas/LabLocationCapability"}}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PscInfo"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/phlebotomy/appointment/availability":{"post":{"operationId":"get_phlebotomy_appointment_availability_v3_order_phlebotomy_appointment_availability_post","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"availability slots are provider-side data whose values shift between sandbox calls; covered by the mock-internal scheduling property suite instead"}},"parameters":[{"name":"start_date","in":"query","required":false,"schema":{"type":"string","format":"date"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsAddress"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentAvailabilitySlots"}}}},"400":{"description":"Availability not bookable for this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No availability found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/phlebotomy/appointment/cancellation-reasons":{"get":{"operationId":"get_phlebotomy_appointment_cancellation_reason_v3_order_phlebotomy_appointment_cancellation_reasons_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingAppointmentCancellationReason"}}}}}}}},"/v3/order/psc/appointment/availability":{"post":{"operationId":"get_psc_appointment_availability_v3_order_psc_appointment_availability_post","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"availability slots are provider-side data whose values shift between sandbox calls; covered by the mock-internal scheduling property suite instead"}},"parameters":[{"name":"lab","in":"query","required":true,"schema":{"$ref":"#/components/schemas/AppointmentPscLabs"}},{"name":"start_date","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"site_codes","in":"query","required":false,"schema":{"type":"string","description":"JSON-encoded array of site codes"}},{"name":"zip_code","in":"query","required":false,"schema":{"type":"string"}},{"name":"radius","in":"query","required":false,"schema":{"$ref":"#/components/schemas/AllowedRadius"}},{"name":"allow_stale","in":"query","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentAvailabilitySlots"}}}},"400":{"description":"Availability not bookable for this address","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No slots found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/psc/appointment/cancellation-reasons":{"get":{"operationId":"get_psc_appointment_cancellation_reason_v3_order_psc_appointment_cancellation_reasons_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingAppointmentCancellationReason"}}}}}}}},"/v3/order/{order_id}/phlebotomy/appointment":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"appointment payloads embed provider-side slot data; covered by the mock-internal scheduling property suite instead"}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/phlebotomy/appointment/book":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"post":{"operationId":"book_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_book_post","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"booking depends on live provider slot state; covered by the mock-internal scheduling property suite instead"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentBookingRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Booking failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/phlebotomy/appointment/reschedule":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"patch":{"operationId":"reschedule_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_reschedule_patch","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"rescheduling depends on live provider slot state; covered by the mock-internal scheduling property suite instead"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentRescheduleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Invalid or expired booking key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/phlebotomy/appointment/cancel":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"patch":{"operationId":"cancel_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_cancel_patch","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"cancellation depends on live provider appointment state; covered by the mock-internal scheduling property suite instead"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhlebotomyAppointmentCancelRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Invalid cancellation reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/psc/appointment":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_psc_appointment_v3_order__order_id__psc_appointment_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"appointment payloads embed provider-side slot data; covered by the mock-internal scheduling property suite instead"}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/psc/appointment/book":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"post":{"operationId":"book_psc_appointment_v3_order__order_id__psc_appointment_book_post","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"booking depends on live provider slot state; covered by the mock-internal scheduling property suite instead"}},"parameters":[{"name":"x-idempotency-key","in":"header","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PscAppointmentBookingRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Booking failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/psc/appointment/reschedule":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"patch":{"operationId":"reschedule_psc_appointment_v3_order__order_id__psc_appointment_reschedule_patch","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"rescheduling depends on live provider slot state; covered by the mock-internal scheduling property suite instead"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentRescheduleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Invalid or expired booking key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/psc/appointment/cancel":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"patch":{"operationId":"cancel_psc_appointment_v3_order__order_id__psc_appointment_cancel_patch","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"cancellation depends on live provider appointment state; covered by the mock-internal scheduling property suite instead"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PscAppointmentCancelRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingAppointment"}}}},"400":{"description":"Invalid cancellation reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"No appointment for this order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_order_v3_order__order_id__get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientFacingOrder"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/cancel":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"post":{"operationId":"cancel_order_v3_order__order_id__cancel_post","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostOrderResponse"}}}},"400":{"description":"Order is not in a cancellable status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/test":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"post":{"operationId":"simulate_order_v3_order__order_id__test_post","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"final_status","in":"query","required":true,"schema":{"type":"string","enum":["received.walk_in_test.ordered","received.walk_in_test.requisition_created","received.walk_in_test.requisition_bypassed","completed.walk_in_test.completed","sample_with_lab.walk_in_test.partial_results","failed.walk_in_test.sample_error","cancelled.walk_in_test.cancelled","collecting_sample.walk_in_test.appointment_pending","collecting_sample.walk_in_test.appointment_scheduled","collecting_sample.walk_in_test.appointment_cancelled","collecting_sample.walk_in_test.redraw_available","received.at_home_phlebotomy.ordered","received.at_home_phlebotomy.requisition_created","received.at_home_phlebotomy.requisition_bypassed","collecting_sample.at_home_phlebotomy.appointment_pending","collecting_sample.at_home_phlebotomy.appointment_scheduled","collecting_sample.at_home_phlebotomy.draw_completed","collecting_sample.at_home_phlebotomy.appointment_cancelled","completed.at_home_phlebotomy.completed","sample_with_lab.at_home_phlebotomy.partial_results","cancelled.at_home_phlebotomy.cancelled","failed.at_home_phlebotomy.sample_error","received.testkit.ordered","received.testkit.awaiting_registration","received.testkit.requisition_created","received.testkit.requisition_bypassed","received.testkit.registered","collecting_sample.testkit.transit_customer","collecting_sample.testkit.out_for_delivery","collecting_sample.testkit.with_customer","collecting_sample.testkit.transit_lab","sample_with_lab.testkit.delivered_to_lab","sample_with_lab.testkit.lab_processing_blocked","completed.testkit.completed","failed.testkit.failure_to_deliver_to_customer","failed.testkit.failure_to_deliver_to_lab","failed.testkit.sample_error","failed.testkit.lost","cancelled.testkit.cancelled","cancelled.testkit.do_not_process","collecting_sample.testkit.problem_in_transit_customer","collecting_sample.testkit.problem_in_transit_lab","received.on_site_collection.ordered","received.on_site_collection.requisition_created","received.on_site_collection.requisition_bypassed","sample_with_lab.on_site_collection.draw_completed","completed.on_site_collection.completed","cancelled.on_site_collection.cancelled","sample_with_lab.on_site_collection.partial_results","failed.on_site_collection.sample_error","completed.walk_in_test.corrected","completed.at_home_phlebotomy.corrected","completed.on_site_collection.corrected","completed.testkit.corrected"]}},{"name":"delay","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Seconds to defer the status transition"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimulationFlags"}}}},"responses":{"200":{"description":"Successful Response","content":{"text/plain":{"schema":{"type":"string","examples":["Success"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/result":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_result_raw_v3_order__order_id__result_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"results carry provider-side specimen data; covered by the mock-internal results property suite instead"}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabResultsRaw"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/result/metadata":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_result_metadata_v3_order__order_id__result_metadata_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabResultsMetadata"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/result/pdf":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_result_pdf_v3_order__order_id__result_pdf_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"PDF bytes are provider-rendered; compared by shape (byteLength) only in the scenario script"}},"responses":{"200":{"description":"Successful Response","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order/{order_id}/requisition/pdf":{"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_order_requisition_pdf_v3_order__order_id__requisition_pdf_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"PDF bytes are provider-rendered; compared by shape (byteLength) only in the scenario script"}},"responses":{"200":{"description":"Successful Response","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/orders":{"get":{"operationId":"get_orders_v3_orders_get","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"parameters":[{"name":"user_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user","missing":"00000000-0000-4000-8000-000000000000"}}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOrdersResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order_transaction/{transaction_id}":{"parameters":[{"name":"transaction_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order_transaction","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_order_transaction_v3_order_transaction__transaction_id__get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"order transactions are not available to the sandbox team (feature not available)"}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetOrderTransactionResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v3/order_transaction/{transaction_id}/result":{"parameters":[{"name":"transaction_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order_transaction","missing":"00000000-0000-4000-8000-000000000000"}}}],"get":{"operationId":"get_order_transaction_result_v3_order_transaction__transaction_id__result_get","x-mockingbird":{"supported":true,"parity":{"enabled":false,"safe":true,"reason":"lab results are not available to the sandbox team (feature not available)"}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabResultsRaw"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"x-vital-api-key"}},"schemas":{"UserCreateBody":{"type":"object","required":["client_user_id"],"properties":{"client_user_id":{"type":"string","minLength":1,"maxLength":64,"examples":["mbr_8891","patient-1042","user.profile_52"]},"fallback_time_zone":{"type":["string","null"],"enum":["America/Los_Angeles","America/New_York","Europe/London","UTC",null]}}},"ClientFacingUser":{"type":"object","required":["user_id","team_id","client_user_id","created_on","connected_sources","fallback_time_zone"],"properties":{"user_id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"user","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"team_id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"account"}},"client_user_id":{"type":"string"},"created_on":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"connected_sources":{"type":"array","items":{"type":"object","additionalProperties":true}},"fallback_time_zone":{"type":["object","null"],"properties":{"id":{"type":"string"},"source_slug":{"type":"string"},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}},"fallback_birth_date":{"type":["object","null"],"properties":{"value":{"type":"string"},"source_slug":{"type":"string"},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}},"ingestion_start":{"type":["string","null"]},"ingestion_end":{"type":["string","null"]}}},"UserInfoPatchBody":{"type":"object","properties":{"first_name":{"type":["string","null"]},"last_name":{"type":["string","null"]},"dob":{"type":["string","null"]},"gender":{"type":["string","null"]},"phone_number":{"type":["string","null"]},"email":{"type":["string","null"]},"address":{"type":["object","null"],"additionalProperties":true}}},"UserInfo":{"type":"object","additionalProperties":true},"ClientUserIDConflictResponse":{"type":"object","required":["detail"],"properties":{"detail":{"type":"object","required":["error_type","error_message","user_id","created_on"],"properties":{"error_type":{"type":"string"},"error_message":{"type":"string"},"user_id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"id"}},"created_on":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}}}},"UserSuccessResponse":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean"}}},"PaginatedUsersResponse":{"type":"object","required":["users","total","offset","limit"],"properties":{"users":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingUser"}},"total":{"type":"integer"},"offset":{"type":"integer"},"limit":{"type":"integer"}}},"UserPatchBody":{"type":"object","properties":{"fallback_time_zone":{"type":["string","null"]},"fallback_birth_date":{"type":["string","null"],"format":"date"},"ingestion_start":{"type":["string","null"],"format":"date"},"ingestion_end":{"type":["string","null"],"format":"date"},"client_user_id":{"type":["string","null"]}}},"LabTestCollectionMethod":{"type":"string","enum":["testkit","walk_in_test","at_home_phlebotomy","on_site_collection"]},"LabTestGenerationMethodFilter":{"type":"string","enum":["auto","manual","all"]},"LabTestSampleType":{"type":"string","enum":["dried_blood_spot","arm_collector","serum","saliva","urine","stool"]},"LabTestStatus":{"type":"string","enum":["active","pending_approval","inactive"]},"MarkerType":{"type":"string","enum":["biomarker","panel"]},"ClientFacingLab":{"type":"object","required":["id","slug","name","first_line_address","city","zipcode","collection_methods","sample_types"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"id"}},"slug":{"type":"string"},"name":{"type":"string"},"first_line_address":{"type":"string"},"city":{"type":"string"},"zipcode":{"type":"string"},"collection_methods":{"type":"array","items":{"$ref":"#/components/schemas/LabTestCollectionMethod"}},"sample_types":{"type":"array","items":{"$ref":"#/components/schemas/LabTestSampleType"}},"logo_url":{"type":["string","null"]}}},"ClientFacingMarker":{"type":"object","required":["id","name","slug"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"id"}},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":["string","null"]},"lab_id":{"type":["integer","null"]},"provider_id":{"type":["string","null"]},"type":{"anyOf":[{"$ref":"#/components/schemas/MarkerType"},{"type":"null"}]},"unit":{"type":["string","null"]},"price":{"type":["string","null"]},"aoe":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]},"a_la_carte_enabled":{"type":"boolean","default":false},"common_tat_days":{"type":["integer","null"]},"worst_case_tat_days":{"type":["integer","null"]},"is_orderable":{"type":["boolean","null"],"default":true}}},"ClientFacingLabTest":{"type":"object","required":["id","slug","name","sample_type","method","price","is_active","status","lab","markers"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"lab_test","identity":true}},"slug":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"name":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"sample_type":{"$ref":"#/components/schemas/LabTestSampleType"},"method":{"$ref":"#/components/schemas/LabTestCollectionMethod"},"price":{"type":"number"},"is_active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/LabTestStatus"},"fasting":{"type":"boolean","default":false},"lab":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingLab"},{"type":"null"}]},"markers":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingMarker"}},{"type":"null"}]},"is_delegated":{"type":"boolean","default":false},"auto_generated":{"type":"boolean","default":false},"has_collection_instructions":{"type":["boolean","null"]},"common_tat_days":{"type":["integer","null"]},"worst_case_tat_days":{"type":["integer","null"]}}},"LabTestResourcesResponse":{"type":"object","required":["data","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingLabTest"}},"next_cursor":{"type":["string","null"]}}},"LabAccountStatus":{"type":"string","enum":["active","pending","suspended","ready_to_launch"]},"LabAccountDelegatedFlow":{"type":"string","enum":["order_delegated","result_delegated","fully_delegated","not_delegated"]},"USState":{"type":"string","enum":["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]},"Labs":{"type":"string","enum":["ayumetrix","spiriplex","ussl","quest","sonora_quest","labcorp","bioreference","us_biotek","manual","sanocardio","ihd","nexus","my_uti","crl","mtl"]},"ClientFacingLabAccount":{"type":"object","required":["id","lab","status","delegated_flow","provider_account_id","allowed_billing","team_id_allowlist"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"lab_account","identity":true}},"lab":{"$ref":"#/components/schemas/Labs"},"org_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"status":{"$ref":"#/components/schemas/LabAccountStatus"},"delegated_flow":{"$ref":"#/components/schemas/LabAccountDelegatedFlow"},"provider_account_id":{"type":"string"},"account_name":{"anyOf":[{"type":"string"},{"type":"null"}]},"default_clinical_notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"business_units":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"allowed_billing":{"type":"object","propertyNames":{"$ref":"#/components/schemas/Billing"},"additionalProperties":{"type":"array","items":{"$ref":"#/components/schemas/USState"}}},"team_id_allowlist":{"type":"array","items":{"type":"string","format":"uuid"}}}},"GetTeamLabAccountsResponse":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingLabAccount"}}}},"ClientFacingResult":{"type":"object","required":["name","slug","type"],"properties":{"name":{"type":"string"},"slug":{"type":"string"},"provider_id":{"type":["string","null"]},"type":{"$ref":"#/components/schemas/ResultType"},"value":{"type":["number","null"]},"unit":{"type":["string","null"]},"low_value":{"type":["number","null"]},"high_value":{"type":["number","null"]},"string_value":{"type":["string","null"]},"coded_value":{"type":["string","null"]},"is_abnormal":{"type":"boolean","default":false},"notes":{"type":["string","null"]}}},"GetMarkersResponse":{"type":"object","required":["markers"],"properties":{"markers":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingMarkerComplete"}},"total":{"type":["integer","null"]},"page":{"type":["integer","null"]},"size":{"type":["integer","null"]},"pages":{"type":["integer","null"]}}},"ClientFacingExpectedResult":{"type":"object","required":["id","name","slug","required"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"id"}},"name":{"type":"string"},"slug":{"type":"string"},"lab_id":{"type":["integer","null"]},"provider_id":{"type":["string","null"]},"required":{"type":"boolean"},"loinc":{"type":["object","null"],"required":["id","name","slug","code"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"id"}},"name":{"type":"string"},"slug":{"type":"string"},"code":{"type":"string"},"unit":{"type":["string","null"]}}}}},"ClientFacingMarkerComplete":{"type":"object","required":["id","name","slug","expected_results"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"id"}},"name":{"type":"string"},"slug":{"type":"string"},"description":{"type":["string","null"]},"lab_id":{"type":["integer","null"]},"provider_id":{"type":["string","null"]},"type":{"anyOf":[{"$ref":"#/components/schemas/MarkerType"},{"type":"null"}]},"unit":{"type":["string","null"]},"price":{"type":["string","null"]},"a_la_carte_enabled":{"type":"boolean","default":false},"common_tat_days":{"type":["integer","null"]},"worst_case_tat_days":{"type":["integer","null"]},"is_orderable":{"type":["boolean","null"],"default":true},"expected_results":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingExpectedResult"}}}},"ListOrderSetMarkersRequest":{"type":"object","required":["order_set_id"],"properties":{"order_set_id":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order_transaction","missing":"00000000-0000-4000-8000-000000000000"}},"provider_id":{"type":["string","null"]}}},"AllowedRadius":{"type":"integer","enum":[10,20,25,50,100]},"AppointmentPscLabs":{"type":"string","enum":["quest"]},"AppointmentProvider":{"type":"string","enum":["getlabs","phlebfinders","quest"]},"AppointmentType":{"type":"string","enum":["phlebotomy","patient_service_center"]},"AppointmentStatus":{"type":"string","enum":["confirmed","pending","reserved","in_progress","completed","cancelled"]},"AppointmentEventStatus":{"type":"string","enum":["pending","reserved","scheduled","completed","cancelled","in_progress"]},"AppointmentServiceType":{"type":"string","enum":["appointment-ready","appointment-request"]},"Billing":{"type":"string","enum":["client_bill","commercial_insurance","patient_bill_passthrough","patient_bill"]},"LabLocationCapability":{"type":"string","enum":["stat","appointment_scheduling_via_junction","appointment_scheduling_with_lab"]},"LngLat":{"type":"object","required":["lng","lat"],"properties":{"lng":{"type":"number"},"lat":{"type":"number"}}},"UsAddress":{"type":"object","required":["first_line","city","state","zip_code"],"properties":{"first_line":{"type":"string","minLength":1},"second_line":{"type":["string","null"]},"city":{"type":"string","minLength":1},"state":{"type":"string","minLength":1},"zip_code":{"type":"string","minLength":1},"unit":{"type":["string","null"]}}},"AppointmentLocation":{"type":"object","required":["location","address","code","name"],"properties":{"location":{"$ref":"#/components/schemas/LngLat"},"distance":{"type":["number","null"]},"address":{"$ref":"#/components/schemas/UsAddress"},"code":{"type":"string"},"name":{"type":"string"},"iana_timezone":{"type":["string","null"]}}},"TimeSlot":{"type":"object","required":["start","end","price","is_priority","num_appointments_available"],"properties":{"booking_key":{"type":["string","null"],"x-mockingbird-resource":{"type":"booking_key","identity":true},"x-mockingbird-volatile":{"kind":"token"}},"start":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"end":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"expires_at":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"timestamp"}},"price":{"type":"number"},"is_priority":{"type":"boolean"},"num_appointments_available":{"type":"integer"}}},"DaySlots":{"type":"object","required":["date","slots"],"properties":{"location":{"anyOf":[{"$ref":"#/components/schemas/AppointmentLocation"},{"type":"null"}]},"date":{"type":"string","format":"date"},"slots":{"type":"array","items":{"$ref":"#/components/schemas/TimeSlot"}}}},"AppointmentAvailabilitySlots":{"type":"object","required":["slots"],"properties":{"slots":{"type":"array","items":{"$ref":"#/components/schemas/DaySlots"}},"timezone":{"type":["string","null"]}}},"AppointmentBookingRequest":{"type":"object","required":["booking_key"],"properties":{"booking_key":{"type":"string","minLength":1,"x-mockingbird-resource-ref":{"type":"booking_key"}}}},"AppointmentRescheduleRequest":{"type":"object","required":["booking_key"],"properties":{"booking_key":{"type":"string","minLength":1,"x-mockingbird-resource-ref":{"type":"booking_key"}}}},"PscAppointmentBookingRequest":{"type":"object","required":["booking_key","site_code"],"properties":{"booking_key":{"type":"string","minLength":1,"x-mockingbird-resource-ref":{"type":"booking_key"}},"site_code":{"type":"string","minLength":1}}},"PhlebotomyAppointmentCancelRequest":{"type":"object","required":["cancellation_reason_id"],"properties":{"cancellation_reason_id":{"type":"string","minLength":1},"notes":{"type":["string","null"]}}},"PscAppointmentCancelRequest":{"type":"object","required":["cancellationReasonId"],"properties":{"cancellationReasonId":{"type":"string","minLength":1},"note":{"type":["string","null"]}}},"ClientFacingAppointmentEvent":{"type":"object","required":["created_at","status"],"properties":{"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"status":{"$ref":"#/components/schemas/AppointmentEventStatus"},"data":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"ClientFacingAppointment":{"type":"object","required":["id","user_id","order_id","address","location","type","provider","status","provider_id","can_reschedule","event_status","events"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"appointment","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"user_id":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user"}},"order_id":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"order"}},"address":{"$ref":"#/components/schemas/UsAddress"},"location":{"$ref":"#/components/schemas/LngLat"},"start_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"end_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"iana_timezone":{"type":["string","null"]},"type":{"$ref":"#/components/schemas/AppointmentType"},"provider":{"$ref":"#/components/schemas/AppointmentProvider"},"status":{"$ref":"#/components/schemas/AppointmentStatus"},"provider_id":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"external_id":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"id"}},"can_reschedule":{"type":"boolean"},"event_status":{"$ref":"#/components/schemas/AppointmentEventStatus"},"event_data":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]},"order_transaction_id":{"type":["string","null"],"x-mockingbird-resource-ref":{"type":"order_transaction"}},"appointment_notes":{"type":["string","null"]},"events":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingAppointmentEvent"}}}},"ClientFacingAppointmentCancellationReason":{"type":"object","required":["id","name","is_refundable"],"properties":{"id":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"name":{"type":"string"},"is_refundable":{"type":"boolean"}}},"PhlebotomyAreaInfo":{"type":"object","required":["is_served","providers"],"properties":{"is_served":{"type":"boolean"},"providers":{"type":"array","items":{"$ref":"#/components/schemas/PhlebotomyProviderInfo"}}}},"PhlebotomyProviderInfo":{"type":"object","required":["name","service_types"],"properties":{"name":{"$ref":"#/components/schemas/AppointmentProvider"},"service_types":{"type":"array","items":{"$ref":"#/components/schemas/AppointmentServiceType"}}}},"PscAreaInfoDetails":{"type":"object","required":["appointment_with_vital","within_radius","radius"],"properties":{"appointment_with_vital":{"type":"boolean"},"within_radius":{"type":"number"},"radius":{"type":"string"},"capabilities":{"type":["array","null"],"items":{"$ref":"#/components/schemas/LabLocationCapability"}}}},"PscAreaInfo":{"type":"object","required":["patient_service_centers","supported_bill_types","lab_id"],"properties":{"patient_service_centers":{"$ref":"#/components/schemas/PscAreaInfoDetails"},"supported_bill_types":{"type":"array","items":{"$ref":"#/components/schemas/Billing"}},"lab_id":{"type":"integer"}}},"AreaInfo":{"type":"object","required":["zip_code","phlebotomy","central_labs"],"properties":{"zip_code":{"type":"string"},"phlebotomy":{"$ref":"#/components/schemas/PhlebotomyAreaInfo"},"central_labs":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/PscAreaInfo"}}}},"LabLocationMetadata":{"type":"object","required":["name","state","city","zip_code","first_line"],"properties":{"name":{"type":"string"},"state":{"type":"string"},"city":{"type":"string"},"zip_code":{"type":"string"},"first_line":{"type":"string"},"second_line":{"type":["string","null"]},"phone_number":{"type":["string","null"]},"fax_number":{"type":["string","null"]},"hours":{"type":["object","null"],"additionalProperties":true}}},"ClientFacingLabLocation":{"type":"object","required":["metadata","distance","site_code","supported_bill_types","location","capabilities"],"properties":{"metadata":{"$ref":"#/components/schemas/LabLocationMetadata"},"distance":{"type":"number"},"site_code":{"type":"string"},"supported_bill_types":{"type":"array","items":{"$ref":"#/components/schemas/Billing"}},"location":{"$ref":"#/components/schemas/LngLat"},"capabilities":{"type":"array","items":{"$ref":"#/components/schemas/LabLocationCapability"}}}},"PscInfo":{"type":"object","required":["lab_id","slug","patient_service_centers"],"properties":{"lab_id":{"type":"integer"},"slug":{"type":"string"},"patient_service_centers":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingLabLocation"}}}},"OrderTopLevelStatus":{"type":"string","enum":["received","collecting_sample","sample_with_lab","completed","cancelled","failed"]},"OrderLowLevelStatus":{"type":"string","enum":["ordered","requisition_created","requisition_bypassed","transit_customer","out_for_delivery","with_customer","transit_lab","delivered_to_lab","completed","failure_to_deliver_to_lab","failure_to_deliver_to_customer","problem_in_transit_lab","problem_in_transit_customer","sample_error","appointment_scheduled","appointment_cancelled","appointment_pending","draw_completed","cancelled","lost","do_not_process","partial_results","awaiting_registration","registered","redraw_available","corrected","lab_processing_blocked"]},"OrderStatus":{"type":"string","enum":["received.walk_in_test.ordered","received.walk_in_test.requisition_created","received.walk_in_test.requisition_bypassed","completed.walk_in_test.completed","sample_with_lab.walk_in_test.partial_results","failed.walk_in_test.sample_error","cancelled.walk_in_test.cancelled","collecting_sample.walk_in_test.appointment_pending","collecting_sample.walk_in_test.appointment_scheduled","collecting_sample.walk_in_test.appointment_cancelled","collecting_sample.walk_in_test.redraw_available","received.at_home_phlebotomy.ordered","received.at_home_phlebotomy.requisition_created","received.at_home_phlebotomy.requisition_bypassed","collecting_sample.at_home_phlebotomy.appointment_pending","collecting_sample.at_home_phlebotomy.appointment_scheduled","collecting_sample.at_home_phlebotomy.draw_completed","collecting_sample.at_home_phlebotomy.appointment_cancelled","completed.at_home_phlebotomy.completed","sample_with_lab.at_home_phlebotomy.partial_results","cancelled.at_home_phlebotomy.cancelled","failed.at_home_phlebotomy.sample_error","received.testkit.ordered","received.testkit.awaiting_registration","received.testkit.requisition_created","received.testkit.requisition_bypassed","received.testkit.registered","collecting_sample.testkit.transit_customer","collecting_sample.testkit.out_for_delivery","collecting_sample.testkit.with_customer","collecting_sample.testkit.transit_lab","sample_with_lab.testkit.delivered_to_lab","sample_with_lab.testkit.lab_processing_blocked","completed.testkit.completed","failed.testkit.failure_to_deliver_to_customer","failed.testkit.failure_to_deliver_to_lab","failed.testkit.sample_error","failed.testkit.lost","cancelled.testkit.cancelled","cancelled.testkit.do_not_process","collecting_sample.testkit.problem_in_transit_customer","collecting_sample.testkit.problem_in_transit_lab","received.on_site_collection.ordered","received.on_site_collection.requisition_created","received.on_site_collection.requisition_bypassed","sample_with_lab.on_site_collection.draw_completed","completed.on_site_collection.completed","cancelled.on_site_collection.cancelled","sample_with_lab.on_site_collection.partial_results","failed.on_site_collection.sample_error","completed.walk_in_test.corrected","completed.at_home_phlebotomy.corrected","completed.on_site_collection.corrected","completed.testkit.corrected"]},"OrderStatusDetail":{"type":"string","enum":["fulfillment_error","date_of_collection_unspecified","demographic_information_unspecified","demographic_information_mismatch","sample_quantity_not_sufficient","sample_contaminated","sample_stability_exceeded","sample_hemolyzed","sample_improper_collection"]},"OrderTransactionStatus":{"type":"string","enum":["active","completed","cancelled"]},"ClientFacingOrderEvent":{"type":"object","required":["id","created_at","status"],"properties":{"id":{"type":"integer","x-mockingbird-volatile":{"kind":"opaque"}},"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"status":{"$ref":"#/components/schemas/OrderStatus"},"status_detail":{"anyOf":[{"$ref":"#/components/schemas/OrderStatusDetail"},{"type":"null"}]}}},"ShippingAddress":{"type":"object","required":["receiver_name","first_line","city","state","zip","country","phone_number"],"properties":{"receiver_name":{"type":"string"},"first_line":{"type":"string"},"second_line":{"type":["string","null"]},"city":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"},"country":{"type":"string"},"phone_number":{"type":"string"}}},"ClientFacingPhysician":{"type":"object","required":["first_name","last_name","npi"],"properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"npi":{"type":"string"}}},"ClientFacingShipment":{"type":"object","required":["id","outbound_tracking_number","outbound_tracking_url","inbound_tracking_number","inbound_tracking_url","outbound_courier","inbound_courier","notes"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"id"}},"outbound_tracking_number":{"type":["string","null"]},"outbound_tracking_url":{"type":["string","null"]},"inbound_tracking_number":{"type":["string","null"]},"inbound_tracking_url":{"type":["string","null"]},"outbound_courier":{"type":["string","null"]},"inbound_courier":{"type":["string","null"]},"notes":{"type":["string","null"]}}},"ClientFacingTestkitOrder":{"type":"object","required":["id","shipment","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"id"}},"shipment":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingShipment"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"opaque"}},"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}},"ClientFacingWalkInOrder":{"type":"object","required":["id","appointment_id","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"id"}},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}},"ClientFacingTestKitOrderDetails":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["testkit","walk_in_test","at_home_phlebotomy","on_site_collection"]},"data":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingTestkitOrder"},{"$ref":"#/components/schemas/ClientFacingWalkInOrder"},{"type":"null"}]}}},"ClientFacingPatientDetailsCompatible":{"type":"object","required":["first_name","last_name","dob","gender","phone_number","email"],"properties":{"first_name":{"type":"string","minLength":1,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9 .,'-]*$","examples":["Ada","Chris","Maria","Jun"]},"last_name":{"type":"string","minLength":1,"pattern":"^[a-zA-Z0-9][a-zA-Z0-9 .,'-]*$","examples":["Lovelace","Vouga","Delgado","Park"]},"dob":{"type":"string","format":"date-time","examples":["1990-06-15T00:00:00.000Z","1983-02-02T00:00:00.000Z"]},"gender":{"type":"string","minLength":1,"pattern":"\\\\S","examples":["male","female","other","prefer_not_to_say"]},"phone_number":{"type":"string","minLength":1,"pattern":"^\\\\+1[2-9]\\\\d{9}$","examples":["+14155550123","+12125550987","+13105554444"]},"email":{"type":"string","format":"email","minLength":1,"examples":["ada@example.com","chris@example.com","maria@example.com"]}}},"PatientAddressCompatible":{"type":"object","required":["first_line","city","state","zip","country"],"properties":{"receiver_name":{"type":"string","default":"","examples":["Ada Lovelace","Chris Vouga"]},"first_line":{"type":"string","minLength":1,"pattern":"\\\\S","examples":["1 Main St","450 Market St","88 Kearny St"]},"second_line":{"type":["string","null"]},"city":{"type":"string","minLength":1,"pattern":"\\\\S","examples":["San Diego","San Francisco","New York"]},"state":{"type":"string","minLength":1,"enum":["AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]},"zip":{"type":"string","pattern":"^\\\\d{5}(-\\\\d{4})?$","examples":["92101","94105","10001"]},"country":{"type":"string","minLength":1,"pattern":"\\\\S","examples":["US"]},"access_notes":{"type":["string","null"],"examples":[null]},"phone_number":{"type":["string","null"],"examples":["+14155550123",null]}}},"AoeAnswerRequest":{"type":"object","required":["marker_id","question_id","answer"],"properties":{"marker_id":{"type":"integer","examples":[2075,1975]},"question_id":{"type":"integer","examples":[1]},"answer":{"type":"string","minLength":1,"examples":["No","Yes"]}}},"ClientFacingOrderInTransaction":{"type":"object","required":["id","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"low_level_status":{"anyOf":[{"$ref":"#/components/schemas/OrderLowLevelStatus"},{"type":"null"}]},"low_level_status_created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}}}},"ClientFacingOrderTransaction":{"type":"object","required":["id","status","orders"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"order_transaction","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"status":{"$ref":"#/components/schemas/OrderTransactionStatus"},"orders":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingOrderInTransaction"}}}},"OrderSummary":{"type":"object","required":["id","last_status","last_status_created_at","updated_at","created_at"],"properties":{"id":{"type":"string","format":"uuid"},"origin":{"anyOf":[{"type":"string","enum":["initial","redraw","recreation"]},{"type":"null"}]},"parent_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"last_status":{"$ref":"#/components/schemas/OrderLowLevelStatus"},"last_status_created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"}}},"GetOrderTransactionResponse":{"type":"object","required":["id","team_id","status"],"properties":{"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"order_transaction","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"team_id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"account"}},"status":{"$ref":"#/components/schemas/OrderTransactionStatus"},"orders":{"type":"array","items":{"$ref":"#/components/schemas/OrderSummary"}}}},"ClientFacingOrder":{"type":"object","required":["user_id","id","team_id","patient_details","patient_address","lab_test","details","sample_id","notes","created_at","updated_at","events","last_event","health_insurance_id","requisition_form_url","shipping_details","has_abn"],"properties":{"user_id":{"type":"string","format":"uuid"},"id":{"type":"string","format":"uuid","x-mockingbird-resource":{"type":"order","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"team_id":{"type":"string","format":"uuid","x-mockingbird-volatile":{"kind":"account"}},"patient_details":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingPatientDetailsCompatible"},{"type":"null"}]},"patient_address":{"anyOf":[{"$ref":"#/components/schemas/PatientAddressCompatible"},{"type":"null"}]},"lab_test":{"$ref":"#/components/schemas/ClientFacingLabTest"},"details":{"$ref":"#/components/schemas/ClientFacingTestKitOrderDetails"},"sample_id":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"opaque"}},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"clinical_notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"updated_at":{"type":"string","format":"date-time","x-mockingbird-volatile":{"kind":"timestamp"}},"events":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingOrderEvent"}},"status":{"anyOf":[{"$ref":"#/components/schemas/OrderTopLevelStatus"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"opaque"}},"last_event":{"$ref":"#/components/schemas/ClientFacingOrderEvent"},"physician":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingPhysician"},{"type":"null"}]},"health_insurance_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"requisition_form_url":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"url"}},"priority":{"type":"boolean","default":false},"shipping_details":{"anyOf":[{"$ref":"#/components/schemas/ShippingAddress"},{"type":"null"}]},"activate_by":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"passthrough":{"anyOf":[{"type":"string"},{"type":"null"}]},"billing_type":{"type":"string","enum":["client_bill","commercial_insurance","patient_bill_passthrough","patient_bill","upfront_payment"],"default":"client_bill"},"icd_codes":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}]},"has_abn":{"type":"boolean"},"interpretation":{"anyOf":[{"type":"string","enum":["normal","abnormal","critical","unknown"]},{"type":"null"}]},"has_missing_results":{"anyOf":[{"type":"boolean"},{"type":"null"}]},"expected_result_by_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"worst_case_result_by_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}]},"origin":{"anyOf":[{"type":"string","enum":["initial","redraw","recreation"]},{"type":"null"}]},"order_transaction":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingOrderTransaction"},{"type":"null"}]}}},"OrderSetRequest":{"type":"object","required":["lab_test_ids"],"properties":{"lab_test_ids":{"type":"array","minItems":1,"items":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"lab_test","missing":"00000000-0000-4000-8000-000000000000"}}}}},"CreateOrderRequest":{"type":"object","required":["user_id","patient_details","patient_address","order_set"],"properties":{"user_id":{"type":"string","format":"uuid","x-mockingbird-resource-ref":{"type":"user","missing":"00000000-0000-4000-8000-000000000000"}},"patient_details":{"$ref":"#/components/schemas/ClientFacingPatientDetailsCompatible"},"patient_address":{"$ref":"#/components/schemas/PatientAddressCompatible"},"order_set":{"$ref":"#/components/schemas/OrderSetRequest"},"clinical_notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"passthrough":{"anyOf":[{"type":"string"},{"type":"null"}]},"collection_method":{"$ref":"#/components/schemas/LabTestCollectionMethod"},"lab_account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"idempotency_key":{"type":["string","null"]},"idempotency_error":{"type":["string","null"]},"aoe_answers":{"type":["array","null"],"items":{"$ref":"#/components/schemas/AoeAnswerRequest"}}}},"PostOrderResponse":{"type":"object","required":["order","status","message"],"properties":{"order":{"$ref":"#/components/schemas/ClientFacingOrder"},"status":{"type":"string"},"message":{"type":"string"}}},"ResultType":{"type":"string","enum":["numeric","range","comment","coded_value"]},"ParentBiomarkerData":{"type":"object","required":["marker_id","name","slug"],"properties":{"marker_id":{"type":"integer"},"name":{"type":"string"},"slug":{"type":"string"},"provider_id":{"type":["string","null"]}}},"BiomarkerResult":{"type":"object","required":["name","result","type"],"properties":{"name":{"type":"string"},"slug":{"type":"string","default":""},"value":{"anyOf":[{"type":"number"},{"type":"null"}]},"result":{"type":"string"},"type":{"$ref":"#/components/schemas/ResultType"},"unit":{"type":["string","null"]},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"notes":{"type":["string","null"]},"reference_range":{"type":["string","null"]},"min_range_value":{"type":["number","null"]},"max_range_value":{"type":["number","null"]},"is_above_max_range":{"type":["boolean","null"]},"is_below_min_range":{"type":["boolean","null"]},"interpretation":{"type":"string","default":"normal"},"source_interpretation":{"type":"string","default":""},"loinc":{"type":["string","null"]},"loinc_slug":{"type":["string","null"]},"provider_id":{"type":["string","null"]},"source_markers":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/ParentBiomarkerData"}},{"type":"null"}]},"performing_laboratory":{"type":["string","null"]},"source_sample_id":{"type":["string","null"]}}},"FailureType":{"type":"string","enum":["quantity_not_sufficient_failure","collection_process_failure","drop_off_failure","internal_lab_failure","order_entry_failure","non_failure","unknown_failure","patient_condition_failure","missing_result_calc_failure","missing_demo_aoe_calc_failure","insufficient_volume"]},"MissingBiomarkerResult":{"type":"object","required":["name","slug","inferred_failure_type"],"properties":{"name":{"type":"string"},"slug":{"type":"string"},"inferred_failure_type":{"$ref":"#/components/schemas/FailureType"},"note":{"type":["string","null"]},"loinc":{"type":["string","null"]},"loinc_slug":{"type":["string","null"]},"provider_id":{"type":["string","null"]},"source_markers":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/ParentBiomarkerData"}},{"type":"null"}]}}},"SampleData":{"type":"object","properties":{"sample_id":{"type":["string","null"]},"control_number":{"type":["string","null"]},"date_collected":{"type":["string","null"]},"date_received":{"type":["string","null"]},"date_reported":{"type":["string","null"]},"performing_laboratories":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]},"clinical_information":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}]}}},"LabResultsMetadata":{"type":"object","required":["age","dob","patient","date_reported","specimen_number"],"properties":{"age":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"dob":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"clia_#":{"anyOf":[{"type":"string"},{"type":"null"}]},"patient":{"type":"string","x-mockingbird-volatile":{"kind":"token"}},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"token"}},"laboratory":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"token"}},"date_reported":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"date_collected":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"specimen_number":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"date_received":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"timestamp"}},"status":{"type":"string","default":"final"},"interpretation":{"anyOf":[{"type":"string"},{"type":"null"}]},"patient_id":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"id"}},"account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"x-mockingbird-volatile":{"kind":"id"}}}},"LabResultsRaw":{"type":"object","required":["metadata","results"],"properties":{"metadata":{"$ref":"#/components/schemas/LabResultsMetadata"},"results":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/BiomarkerResult"}},{"type":"object","additionalProperties":true}],"x-mockingbird-volatile":{"kind":"opaque"}},"missing_results":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/MissingBiomarkerResult"}},{"type":"null"}],"x-mockingbird-volatile":{"kind":"opaque"}},"sample_information":{"anyOf":[{"type":"object","additionalProperties":{"$ref":"#/components/schemas/SampleData"}},{"type":"null"}],"x-mockingbird-volatile":{"kind":"opaque"}},"order_transaction":{"anyOf":[{"$ref":"#/components/schemas/ClientFacingOrderTransaction"},{"type":"null"}]}}},"SimulationFlags":{"type":"object","properties":{"interpretation":{"anyOf":[{"type":"string","enum":["normal","abnormal","critical","unknown"]},{"type":"null"}]},"result_types":{"type":"array","items":{"$ref":"#/components/schemas/ResultType"}},"has_missing_results":{"type":"boolean"}}},"GetOrdersResponse":{"type":"object","required":["orders"],"properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/ClientFacingOrder"}},"total":{"anyOf":[{"type":"integer"},{"type":"null"}]},"page":{"anyOf":[{"type":"integer"},{"type":"null"}]},"size":{"anyOf":[{"type":"integer"},{"type":"null"}]}}},"HTTPValidationError":{"type":"object","properties":{"detail":{"title":"Detail"}}}}}}`);
|
|
8261
9065
|
var operationIds = ["get_teams_users_v2_user_get", "create_user_v2_user_post", "get_user_v2_user__user_id__get", "delete_user_v2_user__user_id__delete", "patch_user_v2_user__user_id__patch", "get_user_by_client_user_id_v2_user_resolve__client_user_id__get", "patch_user_info_v2_user__user_id__info_patch", "get_latest_user_info_user_v2_user__user_id__info_latest_get", "get_paginated_lab_tests_for_team_v3_lab_test_get", "get_team_lab_accounts_v3_lab_test_lab_account_get", "get_lab_tests_for_team_v3_lab_tests_get", "get_lab_test_for_team_v3_lab_tests__lab_test_id__get", "get_labs_v3_lab_tests_labs_get", "get_markers_for_lab_test_v3_lab_tests__lab_test_id__markers_get", "list_order_set_markers_v3_lab_tests_list_order_set_markers_post", "create_order_v3_order_post", "get_area_info_v3_order_area_info_get", "get_psc_info_v3_order_psc_info_get", "get_phlebotomy_appointment_availability_v3_order_phlebotomy_appointment_availability_post", "get_phlebotomy_appointment_cancellation_reason_v3_order_phlebotomy_appointment_cancellation_reasons_get", "get_psc_appointment_availability_v3_order_psc_appointment_availability_post", "get_psc_appointment_cancellation_reason_v3_order_psc_appointment_cancellation_reasons_get", "get_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_get", "book_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_book_post", "reschedule_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_reschedule_patch", "cancel_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_cancel_patch", "get_psc_appointment_v3_order__order_id__psc_appointment_get", "book_psc_appointment_v3_order__order_id__psc_appointment_book_post", "reschedule_psc_appointment_v3_order__order_id__psc_appointment_reschedule_patch", "cancel_psc_appointment_v3_order__order_id__psc_appointment_cancel_patch", "get_order_v3_order__order_id__get", "cancel_order_v3_order__order_id__cancel_post", "simulate_order_v3_order__order_id__test_post", "get_result_raw_v3_order__order_id__result_get", "get_result_metadata_v3_order__order_id__result_metadata_get", "get_result_pdf_v3_order__order_id__result_pdf_get", "get_order_requisition_pdf_v3_order__order_id__requisition_pdf_get", "get_orders_v3_orders_get", "get_order_transaction_v3_order_transaction__transaction_id__get", "get_order_transaction_result_v3_order_transaction__transaction_id__result_get"];
|
|
8262
9066
|
var supportedOperationIds = ["get_teams_users_v2_user_get", "create_user_v2_user_post", "get_user_v2_user__user_id__get", "delete_user_v2_user__user_id__delete", "patch_user_v2_user__user_id__patch", "get_user_by_client_user_id_v2_user_resolve__client_user_id__get", "patch_user_info_v2_user__user_id__info_patch", "get_latest_user_info_user_v2_user__user_id__info_latest_get", "get_paginated_lab_tests_for_team_v3_lab_test_get", "get_team_lab_accounts_v3_lab_test_lab_account_get", "get_lab_tests_for_team_v3_lab_tests_get", "get_lab_test_for_team_v3_lab_tests__lab_test_id__get", "get_labs_v3_lab_tests_labs_get", "get_markers_for_lab_test_v3_lab_tests__lab_test_id__markers_get", "list_order_set_markers_v3_lab_tests_list_order_set_markers_post", "create_order_v3_order_post", "get_area_info_v3_order_area_info_get", "get_psc_info_v3_order_psc_info_get", "get_phlebotomy_appointment_availability_v3_order_phlebotomy_appointment_availability_post", "get_phlebotomy_appointment_cancellation_reason_v3_order_phlebotomy_appointment_cancellation_reasons_get", "get_psc_appointment_availability_v3_order_psc_appointment_availability_post", "get_psc_appointment_cancellation_reason_v3_order_psc_appointment_cancellation_reasons_get", "get_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_get", "book_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_book_post", "reschedule_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_reschedule_patch", "cancel_phlebotomy_appointment_v3_order__order_id__phlebotomy_appointment_cancel_patch", "get_psc_appointment_v3_order__order_id__psc_appointment_get", "book_psc_appointment_v3_order__order_id__psc_appointment_book_post", "reschedule_psc_appointment_v3_order__order_id__psc_appointment_reschedule_patch", "cancel_psc_appointment_v3_order__order_id__psc_appointment_cancel_patch", "get_order_v3_order__order_id__get", "cancel_order_v3_order__order_id__cancel_post", "simulate_order_v3_order__order_id__test_post", "get_result_raw_v3_order__order_id__result_get", "get_result_metadata_v3_order__order_id__result_metadata_get", "get_result_pdf_v3_order__order_id__result_pdf_get", "get_order_requisition_pdf_v3_order__order_id__requisition_pdf_get", "get_orders_v3_orders_get", "get_order_transaction_v3_order_transaction__transaction_id__get", "get_order_transaction_result_v3_order_transaction__transaction_id__result_get"];
|
|
8263
9067
|
|
|
@@ -10267,7 +11071,7 @@ var createRuntime2 = (options = {}) => {
|
|
|
10267
11071
|
const webhooks = options.webhooks ? createWebhookDispatcher(options.webhooks) : void 0;
|
|
10268
11072
|
const runtime = createRuntime({
|
|
10269
11073
|
name: JUNCTION_NAMESPACE,
|
|
10270
|
-
document,
|
|
11074
|
+
document: document2,
|
|
10271
11075
|
...options.sqlite ? { sqlite: options.sqlite } : {},
|
|
10272
11076
|
...options.clock ? { clock: options.clock } : {},
|
|
10273
11077
|
...options.seed !== void 0 ? { seed: options.seed } : {},
|
|
@@ -10309,6 +11113,7 @@ var createRuntime2 = (options = {}) => {
|
|
|
10309
11113
|
webhooks: webhooks ? "on" : "off"
|
|
10310
11114
|
};
|
|
10311
11115
|
},
|
|
11116
|
+
presets: junctionFaultPresets(),
|
|
10312
11117
|
admin: junctionAdminRoutes({ webhooks })
|
|
10313
11118
|
});
|
|
10314
11119
|
return Object.assign(runtime, { webhooks });
|
|
@@ -10814,7 +11619,7 @@ var JunctionAPI = class {
|
|
|
10814
11619
|
...resultsHandlers(state)
|
|
10815
11620
|
});
|
|
10816
11621
|
this.service = createService({
|
|
10817
|
-
document,
|
|
11622
|
+
document: document2,
|
|
10818
11623
|
handlers,
|
|
10819
11624
|
sqlite,
|
|
10820
11625
|
namespace,
|
|
@@ -11160,7 +11965,7 @@ export {
|
|
|
11160
11965
|
UNKNOWN_ZIP_ERROR_TYPE,
|
|
11161
11966
|
IDENTITY_MODES,
|
|
11162
11967
|
FixtureError,
|
|
11163
|
-
document,
|
|
11968
|
+
document2 as document,
|
|
11164
11969
|
operationIds,
|
|
11165
11970
|
supportedOperationIds,
|
|
11166
11971
|
PSC_AVAILABILITY_ZIPS,
|
|
@@ -11185,4 +11990,4 @@ export {
|
|
|
11185
11990
|
JunctionAPI,
|
|
11186
11991
|
LabAccountConflict
|
|
11187
11992
|
};
|
|
11188
|
-
//# sourceMappingURL=chunk-
|
|
11993
|
+
//# sourceMappingURL=chunk-LNHFCMWC.js.map
|