@crvouga/mockingbird-service-prism 0.2.0 → 1.0.1

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 CHANGED
@@ -1,6 +1,19 @@
1
1
  # Changelog — @crvouga/mockingbird-service-prism
2
2
 
3
- ## 0.2.0 (2026-09-24)
3
+ ## 1.0.1 (2026-09-26)
4
+
5
+ ### Fixes and improvements
6
+
7
+ - take the rejected-request byte count from content-length, never by reading the body ([a0e5fb2](https://github.com/crvouga/mockingbird/commit/a0e5fb2fc80ab725c3552b612f3f091fd6c857fb))
8
+ - reject a present body by media type, and log what a rejected request sent ([12e351a](https://github.com/crvouga/mockingbird/commit/12e351aba53cfb7b41e31a7809419455fc2902eb))
9
+
10
+ ## 1.0.0 (2026-09-24)
11
+
12
+ ### ⚠️ Breaking changes
13
+
14
+ - vendor branding for every service; purge internal mocks and consumer names ([f689534](https://github.com/crvouga/mockingbird/commit/f6895343543550dafcb7d76b426cae7635e03226))
15
+
16
+ ## 0.2.0 (2026-09-23)
4
17
 
5
18
  ### Features
6
19
 
@@ -1366,6 +1366,90 @@ var operationMetadata = (operation) => {
1366
1366
 
1367
1367
  // ../core/dist/service.js
1368
1368
  import { Hono } from "hono";
1369
+
1370
+ // ../core/dist/validation.js
1371
+ var requestBodyOf = (context) => {
1372
+ const requestBody = context.operation.operation.requestBody;
1373
+ return requestBody ? deref(context.document, requestBody) : void 0;
1374
+ };
1375
+ var mediaTypeMatches = (accepted, actual) => {
1376
+ const pattern = mediaTypeOf(accepted) ?? accepted.toLowerCase();
1377
+ if (pattern === actual || pattern === "*/*")
1378
+ return true;
1379
+ const [type, subtype] = pattern.split("/");
1380
+ const [actualType, actualSubtype] = actual.split("/");
1381
+ if (type !== actualType && type !== "*")
1382
+ return false;
1383
+ if (subtype === void 0 || subtype === "*")
1384
+ return true;
1385
+ if (subtype.startsWith("*+"))
1386
+ return actualSubtype?.endsWith(subtype.slice(1)) === true;
1387
+ return false;
1388
+ };
1389
+ var acceptedKeyFor = (content, mediaType) => {
1390
+ if (!content || mediaType === void 0)
1391
+ return void 0;
1392
+ const keys = Object.keys(content);
1393
+ return keys.find((key) => mediaTypeOf(key) === mediaType) ?? keys.find((key) => mediaTypeMatches(key, mediaType));
1394
+ };
1395
+ var unsupportedMediaType = (context, options = {}) => {
1396
+ if (context.body.kind === "empty" && options.includeEmpty !== true)
1397
+ return void 0;
1398
+ const content = requestBodyOf(context)?.content;
1399
+ if (!content || Object.keys(content).length === 0)
1400
+ return void 0;
1401
+ const mediaType = mediaTypeOf(context.request.headers.get("content-type"));
1402
+ if (acceptedKeyFor(content, mediaType) !== void 0)
1403
+ return void 0;
1404
+ return { mediaType: mediaType ?? null, accepted: Object.keys(content) };
1405
+ };
1406
+ var recorded = /* @__PURE__ */ new WeakMap();
1407
+ var recordedIssues = (request) => recorded.get(request);
1408
+ var bodyIssues = (context, contentType = "application/json") => {
1409
+ const issues = findBodyIssues(context, contentType);
1410
+ if (issues.length > 0)
1411
+ recorded.set(context.request, issues);
1412
+ return issues;
1413
+ };
1414
+ var findBodyIssues = (context, contentType) => {
1415
+ const resolved = requestBodyOf(context);
1416
+ if (!resolved)
1417
+ return [];
1418
+ const unsupported = unsupportedMediaType(context);
1419
+ if (unsupported) {
1420
+ return [
1421
+ {
1422
+ path: "",
1423
+ kind: "media_type",
1424
+ message: unsupported.mediaType === null ? "request body has no content-type" : `request body media type ${unsupported.mediaType} is not supported`
1425
+ }
1426
+ ];
1427
+ }
1428
+ const key = acceptedKeyFor(resolved.content, mediaTypeOf(context.request.headers.get("content-type"))) ?? contentType;
1429
+ const schema = resolved.content?.[key]?.schema;
1430
+ if (!schema)
1431
+ return [];
1432
+ if (context.body.kind === "invalid") {
1433
+ return [
1434
+ {
1435
+ path: "",
1436
+ kind: "syntax",
1437
+ message: `request body is not valid ${context.body.mediaType}`
1438
+ }
1439
+ ];
1440
+ }
1441
+ const value = context.body.kind === "json" || context.body.kind === "form" || context.body.kind === "text" ? context.body.value : void 0;
1442
+ if (value === void 0) {
1443
+ return resolved.required && context.body.kind === "empty" ? [{ path: "", kind: "required", message: "request body is required" }] : [];
1444
+ }
1445
+ return validateValue(context.document, resolveSchema(context.document, schema), value).map((issue) => ({ path: issue.path.join("."), kind: "schema", message: issue.message }));
1446
+ };
1447
+
1448
+ // ../core/dist/service.js
1449
+ var withIssues = (request, response) => {
1450
+ const issues = response.status >= 400 ? recordedIssues(request) : void 0;
1451
+ return issues && issues.length > 0 ? annotateResponse(response, { issues }) : response;
1452
+ };
1369
1453
  var defineOperations = (handlers) => handlers;
1370
1454
  var OperationRegistryError = class extends Error {
1371
1455
  problems;
@@ -1451,9 +1535,7 @@ var createService = (options) => {
1451
1535
  now
1452
1536
  };
1453
1537
  const short = await options.before?.(context);
1454
- if (short)
1455
- return short;
1456
- return handler(context);
1538
+ return withIssues(request, short ?? await handler(context));
1457
1539
  };
1458
1540
  app.on(operation.method.toUpperCase(), honoPath(operation.path), route);
1459
1541
  }
@@ -1490,7 +1572,7 @@ var restoreNamespace = (sqlite, namespace, snapshot) => {
1490
1572
  };
1491
1573
 
1492
1574
  // ../core/dist/version.js
1493
- var PACKAGE_VERSION = true ? "0.2.0" : UNRELEASED_VERSION;
1575
+ var PACKAGE_VERSION = true ? "1.0.1" : UNRELEASED_VERSION;
1494
1576
 
1495
1577
  // ../core/dist/webhooks.js
1496
1578
  var json2 = (status, body) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
@@ -1930,8 +2012,15 @@ var createRuntime = (options) => {
1930
2012
  const started = monotonicNow();
1931
2013
  const url = new URL(request.url);
1932
2014
  const operationId = operationIdFor(request, url.pathname);
2015
+ const contentLength = request.headers.get("content-length");
2016
+ const received = {
2017
+ contentType: request.headers.get("content-type"),
2018
+ bodyBytes: contentLength !== null && /^\d+$/.test(contentLength) ? Number(contentLength) : null,
2019
+ transferEncoding: request.headers.get("transfer-encoding")
2020
+ };
1933
2021
  const log = (status, faultId, response2) => {
1934
2022
  const noted = response2 ? responseNotes(response2) : void 0;
2023
+ const rejected = status >= 400 && faultId === void 0;
1935
2024
  const entry = {
1936
2025
  service: options.name,
1937
2026
  namespace,
@@ -1943,7 +2032,9 @@ var createRuntime = (options) => {
1943
2032
  unmatched: options.document !== void 0 && operationId === void 0,
1944
2033
  ...faultId !== void 0 ? { faultId } : {},
1945
2034
  ...noted?.ids && Object.keys(noted.ids).length > 0 ? { ids: noted.ids } : {},
1946
- ...noted?.adopted ? { adopted: true } : {}
2035
+ ...noted?.adopted ? { adopted: true } : {},
2036
+ ...rejected ? { request: { ...received } } : {},
2037
+ ...rejected && noted?.issues && noted.issues.length > 0 ? { issues: noted.issues.map((issue) => ({ ...issue })) } : {}
1947
2038
  };
1948
2039
  metrics.record(entry);
1949
2040
  journal.record({ ...entry, at: new Date(clock.now()).toISOString() });
@@ -2150,25 +2241,6 @@ var presetRoutes = (presets, runtime) => ({
2150
2241
  }
2151
2242
  });
2152
2243
 
2153
- // ../core/dist/validation.js
2154
- var bodyIssues = (context, contentType = "application/json") => {
2155
- const requestBody = context.operation.operation.requestBody;
2156
- if (!requestBody)
2157
- return [];
2158
- const resolved = deref(context.document, requestBody);
2159
- const schema = resolved.content?.[contentType]?.schema;
2160
- if (!schema)
2161
- return [];
2162
- const value = context.body.kind === "json" || context.body.kind === "form" ? context.body.value : void 0;
2163
- if (context.body.kind === "invalid") {
2164
- return [{ path: "", message: `request body is not valid ${context.body.mediaType}` }];
2165
- }
2166
- if (value === void 0) {
2167
- return resolved.required ? [{ path: "", message: "request body is required" }] : [];
2168
- }
2169
- return validateValue(context.document, resolveSchema(context.document, schema), value).map((issue) => ({ path: issue.path.join("."), message: issue.message }));
2170
- };
2171
-
2172
2244
  // src/generated/openapi.ts
2173
2245
  var document = JSON.parse(`{"openapi":"3.1.0","info":{"title":"Prism Labs body-scan API (Mockingbird subset)","description":"Stateful mock subset of the Prism Labs API (\`Accept: application/json;v=1\`): subject upsert, scans, the presigned capture upload, per-stage processing states, and the READY-scan results (body composition, measurements, health report, asset URLs). Hand-authored from the consumer's zod schemas (prism-scan.adapter.ts).\\n","version":"1","x-mockingbird-upstream":{"note":"Wire shapes from apps/backend/src/modules/body-scan/adapters/outbound/prism-scan.adapter.ts and packages/body-scan-capture-page/src/main.ts (the PUT upload)."}},"servers":[{"url":"https://sandbox-api.hosted.prismlabs.tech"}],"security":[{"bearerAuth":[]}],"paths":{"/users":{"post":{"operationId":"UpsertUser","description":"Create or update the scan subject identified by \`token\`.","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserBody"}}}}}},"/scans":{"post":{"operationId":"CreateScan","description":"Start a scan for a subject.","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Scan"}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown user token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanBody"}}}}}},"/scans/{scanId}":{"get":{"operationId":"GetScan","description":"A scan's status and weight.","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"The scan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Scan"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown scan, or results not ready yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string","x-mockingbird-resource-ref":{"type":"scan","missing":"00000000-0000-4000-8000-000000000000"}}},{"name":"unit-system","in":"query","required":false,"schema":{"type":"string","enum":["metric","imperial"]}}]}},"/scans/{scanId}/upload-url":{"post":{"operationId":"CreateUploadUrl","description":"A presigned PUT URL for the capture video (15 minutes).","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":false}},"responses":{"200":{"description":"Upload target","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadTarget"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown scan, or results not ready yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The scan already has its capture","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string","x-mockingbird-resource-ref":{"type":"scan","missing":"00000000-0000-4000-8000-000000000000"}}}]}},"/scans/{scanId}/scan-assets":{"get":{"operationId":"GetScanAssets","description":"Per-stage processing states.","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Stage states","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanAssets"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown scan, or results not ready yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string","x-mockingbird-resource-ref":{"type":"scan","missing":"00000000-0000-4000-8000-000000000000"}}}]}},"/scans/{scanId}/bodyfat":{"get":{"operationId":"GetBodyfat","description":"Body composition (READY scans).","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Body composition","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Bodyfat"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown scan, or results not ready yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string","x-mockingbird-resource-ref":{"type":"scan","missing":"00000000-0000-4000-8000-000000000000"}}}]}},"/scans/{scanId}/measurements":{"get":{"operationId":"GetMeasurements","description":"Circumferences and indices (READY scans).","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Measurements","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Measurements"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown scan, or results not ready yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string","x-mockingbird-resource-ref":{"type":"scan","missing":"00000000-0000-4000-8000-000000000000"}}},{"name":"unit-system","in":"query","required":false,"schema":{"type":"string","enum":["metric","imperial"]}}]}},"/scans/{scanId}/health-report":{"get":{"operationId":"GetHealthReport","description":"Health report incl. metabolic age (READY scans).","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"Report","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthReport"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown scan, or results not ready yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string","x-mockingbird-resource-ref":{"type":"scan","missing":"00000000-0000-4000-8000-000000000000"}}}]}},"/scans/{scanId}/asset-urls":{"get":{"operationId":"GetAssetUrls","description":"Signed URLs for the scan's 3D assets (READY scans).","x-mockingbird":{"supported":true,"parity":{"enabled":true,"safe":true}},"responses":{"200":{"description":"URLs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetUrls"}}}},"401":{"description":"Missing or unknown API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown scan, or results not ready yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string","x-mockingbird-resource-ref":{"type":"scan","missing":"00000000-0000-4000-8000-000000000000"}}}]}},"/uploads/{scanId}":{"put":{"operationId":"UploadCapture","description":"The presigned upload target (what the capture page PUTs the video to). Moves the scan to PROCESSING.","security":[],"x-mockingbird":{"supported":true,"parity":{"enabled":false,"reason":"Binary video upload through a presigned URL; covered by acceptance tests."}},"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string"}},{"name":"expires","in":"query","required":true,"schema":{"type":"string"}},{"name":"signature","in":"query","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}},"video/mp4":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Stored"},"403":{"description":"Expired or bad signature (S3-style XML)","content":{"application/xml":{"schema":{"type":"string"}}}},"404":{"description":"Unknown scan"}}}},"/assets/{scanId}/{file}":{"get":{"operationId":"GetAsset","description":"A signed 3D asset (tiny placeholder bytes).","security":[],"x-mockingbird":{"supported":true,"parity":{"enabled":false,"reason":"Binary asset bytes; covered by acceptance tests."}},"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string"}},{"name":"file","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Asset bytes","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"Unknown asset"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"UserBody":{"type":"object","required":["token","sex","region","birthDate","weight","height","researchConsent","termsOfService"],"properties":{"token":{"type":"string","minLength":1,"maxLength":64,"examples":["user-token-1","user-token-2"]},"sex":{"type":"string","enum":["male","female","neutral","undefined"]},"region":{"type":"string","enum":["africa","asia","caribbean","central_america","europe","north_america","oceania","south_america"]},"birthDate":{"type":"string","pattern":"^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-8])$"},"weight":{"type":"object","required":["value","unit"],"properties":{"value":{"type":"number","exclusiveMinimum":0,"maximum":400},"unit":{"type":"string","enum":["kg","lb"]}}},"height":{"type":"object","required":["value","unit"],"properties":{"value":{"type":"number","exclusiveMinimum":0,"maximum":400},"unit":{"type":"string","enum":["m","in"]}}},"researchConsent":{"type":"boolean"},"termsOfService":{"type":"object","required":["accepted","version"],"properties":{"accepted":{"type":"boolean"},"version":{"type":"string","minLength":1,"maxLength":20}}}}},"User":{"type":"object","required":["id","token","sex","region","birthDate","weight","height","createdAt"],"properties":{"id":{"type":"string","x-mockingbird-volatile":{"kind":"id"}},"token":{"type":"string"},"sex":{"type":"string"},"region":{"type":"string"},"birthDate":{"type":"string"},"weight":{"type":"object"},"height":{"type":"object"},"researchConsent":{"type":"boolean"},"termsOfService":{"type":"object"},"createdAt":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"updatedAt":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}}}},"ScanBody":{"type":"object","required":["userToken","deviceConfigName","bodyfatMethod"],"properties":{"userToken":{"type":"string","minLength":1,"maxLength":64,"examples":["user-token-1","user-token-2"]},"deviceConfigName":{"type":"string","enum":["IPHONE_SCANNER","ANDROID_SCANNER"]},"bodyfatMethod":{"type":"string","enum":["coco2","coco","army","extended_navy_thinboost"]},"assetConfigId":{"type":"string","enum":["25f6d3a6-a634-40c3-8452-0342bee242d0","ee651a9e-6de1-4621-a5c9-5d31ca874718"]}}},"Scan":{"type":"object","required":["id","status","userToken","createdAt","updatedAt"],"properties":{"id":{"type":"string","x-mockingbird-resource":{"type":"scan","identity":true},"x-mockingbird-volatile":{"kind":"id"}},"status":{"type":"string","enum":["CREATED","PROCESSING","READY","FAILED"]},"userToken":{"type":"string"},"deviceConfigName":{"type":"string"},"bodyfatMethod":{"type":"string"},"assetConfigId":{"type":["string","null"]},"weight":{"type":["object","null"],"properties":{"value":{"type":"number"},"unit":{"type":"string"}}},"height":{"type":["object","null"]},"createdAt":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}},"updatedAt":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}}}},"UploadTarget":{"type":"object","required":["url","expirationTime"],"properties":{"url":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"expirationTime":{"type":"string","x-mockingbird-volatile":{"kind":"timestamp"}}}},"ScanAssets":{"type":"object","properties":{"captureData":{"type":["string","null"],"enum":["started","succeeded","failed",null]},"captureDataUpdatedAt":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"timestamp"}},"body":{"type":["string","null"],"enum":["started","succeeded","failed",null]},"bodyUpdatedAt":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"timestamp"}},"fittedBody":{"type":["string","null"],"enum":["started","succeeded","failed",null]},"fittedBodyUpdatedAt":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"timestamp"}},"measurement":{"type":["string","null"],"enum":["started","succeeded","failed",null]},"measurementUpdatedAt":{"type":["string","null"],"x-mockingbird-volatile":{"kind":"timestamp"}}}},"Bodyfat":{"type":"object","required":["bodyfatMethod","bodyfatPercentage","leanMass","fatMass"],"properties":{"bodyfatMethod":{"type":"string"},"bodyfatPercentage":{"type":"number"},"leanMass":{"type":"number"},"fatMass":{"type":"number"},"skeletalMuscleMass":{"type":"number"},"unit":{"type":"string"}}},"Measurements":{"type":"object","required":["waistFit","hipsFit","chestFit","waistToHipRatio"],"properties":{"waistFit":{"type":"number"},"hipsFit":{"type":"number"},"chestFit":{"type":"number"},"waistToHipRatio":{"type":"number"},"bodyRoundnessIndex":{"type":"number"},"bmiPredicted":{"type":"number"},"unit":{"type":"string"}}},"HealthReport":{"type":"object","properties":{"metabolicAgeReport":{"type":["object","null"],"properties":{"metabolicAgeYears":{"type":["number","null"]},"chronologicalAgeYears":{"type":["number","null"]},"ageDeltaYears":{"type":["number","null"]},"percentile":{"type":["number","null"]}}},"bodyShapeReport":{"type":"object"}}},"AssetUrls":{"type":"object","properties":{"previewImage":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"model":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"canonicalBody":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"texture":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"material":{"type":"string","x-mockingbird-volatile":{"kind":"url"}},"stripes":{"type":"string","x-mockingbird-volatile":{"kind":"url"}}}},"Error":{"type":"object","required":["message"],"properties":{"message":{"type":"string"},"errors":{"type":"array","items":{"type":"object"}}}}}}}`);
2174
2246
  var operationIds = ["UpsertUser", "CreateScan", "GetScan", "CreateUploadUrl", "GetScanAssets", "GetBodyfat", "GetMeasurements", "GetHealthReport", "GetAssetUrls", "UploadCapture", "GetAsset"];
@@ -2763,4 +2835,4 @@ export {
2763
2835
  scanResults,
2764
2836
  PrismAPI
2765
2837
  };
2766
- //# sourceMappingURL=chunk-P5X7EJGX.js.map
2838
+ //# sourceMappingURL=chunk-AYUAQ3D2.js.map