@ovok/core 0.4.44 → 0.4.46

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/README.md CHANGED
@@ -18,6 +18,7 @@ Core TypeScript SDK for healthcare applications. Provides authentication, AI-FHI
18
18
  - 🧩 Typed accounts, projects, localization, and patient-observation APIs
19
19
  - 🏥 Typed Slim patient, device, telemetry, notification, and monitoring APIs
20
20
  - 🚨 Typed Signals thresholds, alerts, and project settings APIs
21
+ - ⌚ Typed cloud wearable-provider configuration and patient connections
21
22
 
22
23
  ## Installation
23
24
 
@@ -322,8 +323,8 @@ when `nextCursor` is `null`. Feed `noteCount` is nullable: `null` means the coun
322
323
  zero. Notification notes are practitioner-authored and do not acknowledge or otherwise change an
323
324
  alert. After a note mutation, mounted note and alert-feed hooks reload their data.
324
325
 
325
- Writes can return `OvokApiError`, which keeps the HTTP status, machine code, validation field errors,
326
- and any missing-baseline details. In particular, reload the affected record before retrying a 409;
326
+ Writes can return `OvokApiError`, which keeps the HTTP status, machine code, problem `type`, `traceId`,
327
+ validation field errors (each with its `FIELD_*` code), and any missing-baseline details. In particular, reload the affected record before retrying a 409;
327
328
  do not automatically replay a stale assignment. A 409 `signals_project_migrating` should be shown
328
329
  as a temporary home-migration conflict, not retried in a loop. Threshold writes can return 422
329
330
  validation errors or 424 when the baseline has not been collected. Hooks never replay a write with
@@ -374,7 +375,9 @@ try {
374
375
 
375
376
  The client also exposes typed application APIs for consent signatures, document upload credentials,
376
377
  document download endpoints, CMS content, LiveKit video calls, translation, AI chat, and AI FHIR
377
- search. These methods are additive and do not change the native observation or offline contracts.
378
+ search, and cloud wearable-provider connections. These methods are additive and do not change the
379
+ native observation or offline contracts. See the [wearable connection guide](docs/integrations/wearable-connections.md)
380
+ for provider setup, patient consent, and the app-return flow.
378
381
 
379
382
  ```ts
380
383
  const content = await client.searchContent("blog", "en-US", { search: "welcome" });
@@ -398,7 +401,7 @@ download elements; the backend remains responsible for authorization and signed
398
401
 
399
402
  The package exports additive hooks for capability discovery, project configuration, patient profile
400
403
  and health data, questionnaires, scheduling resources, Slim lists, telemetry, notifications,
401
- documents, content, video consultations, and localization. Every request hook returns `data`,
404
+ documents, content, video consultations, wearable connections, and localization. Every request hook returns `data`,
402
405
  `loading`, `error`, and `reload`; mutations expose `data`, `loading`, `error`, `mutate`, and `reset`.
403
406
 
404
407
  ```tsx
@@ -24,6 +24,22 @@ const retryAfterMs = async (response) => {
24
24
  }
25
25
  };
26
26
  exports.retryAfterMs = retryAfterMs;
27
+ // What `readOvokError` reads from Core's error body: the problem members and the legacy ones kept beside them.
28
+ const PRESERVED_ERROR_KEYS = [
29
+ "type",
30
+ "status",
31
+ "detail",
32
+ "instance",
33
+ "traceId",
34
+ "errors",
35
+ "code",
36
+ "error",
37
+ "message",
38
+ "requestId",
39
+ "retryAfterSec",
40
+ "statusCode",
41
+ "missing",
42
+ ];
27
43
  const timeoutError = () => (0, ovok_error_utils_1.namedError)("TimeoutError", "The request timed out.");
28
44
  const withHttpErrorMetadata = async (response, retry) => {
29
45
  var _a;
@@ -47,7 +63,7 @@ const withHttpErrorMetadata = async (response, retry) => {
47
63
  ? envelope.error
48
64
  : undefined;
49
65
  const safeResponse = envelope
50
- ? Object.fromEntries(Object.entries(envelope).filter(([key]) => ["code", "error", "message", "requestId", "retryAfterSec", "status", "statusCode", "errors", "missing"].includes(key)))
66
+ ? Object.fromEntries(Object.entries(envelope).filter(([key]) => PRESERVED_ERROR_KEYS.includes(key)))
51
67
  : { message: typeof body === "string" ? body : response.statusText };
52
68
  const status = response.status;
53
69
  const retryAfter = retry ? retry.milliseconds : await (0, exports.retryAfterMs)(response);
@@ -0,0 +1,2 @@
1
+ import { ValidationError } from "../../types/ValidationError";
2
+ export declare function readFieldErrors(payload: Record<string, unknown> | undefined): ValidationError[];
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readFieldErrors = readFieldErrors;
4
+ const ovok_error_utils_1 = require("./ovok-error-utils");
5
+ function readEnvelopeErrors(values) {
6
+ return values.flatMap((value) => {
7
+ const record = (0, ovok_error_utils_1.asRecord)(value);
8
+ if (!record || typeof record.message !== "string") {
9
+ return [];
10
+ }
11
+ const path = Array.isArray(record.path)
12
+ ? record.path.map((segment) => String(segment))
13
+ : [];
14
+ return [{
15
+ ...((0, ovok_error_utils_1.stringValue)(record.code) ? { code: (0, ovok_error_utils_1.stringValue)(record.code) } : {}),
16
+ message: record.message,
17
+ path,
18
+ ...((0, ovok_error_utils_1.stringValue)(record.validation)
19
+ ? { validation: (0, ovok_error_utils_1.stringValue)(record.validation) }
20
+ : {}),
21
+ }];
22
+ });
23
+ }
24
+ const samePath = (left, right) => left.join(".") === right.join(".");
25
+ /** Core's problem `errors[]` (`{ field, code, params }`), worded by the legacy message Core sends for the same path. */
26
+ function readProblemErrors(values, worded) {
27
+ return values.flatMap((value) => {
28
+ var _a, _b;
29
+ const record = (0, ovok_error_utils_1.asRecord)(value);
30
+ const code = (0, ovok_error_utils_1.stringValue)(record === null || record === void 0 ? void 0 : record.code);
31
+ if (!record || !code || typeof record.message === "string" || !("field" in record)) {
32
+ return [];
33
+ }
34
+ const path = typeof record.field === "string" ? record.field.split(".").filter(Boolean) : [];
35
+ const message = (_b = (_a = worded.find((entry) => samePath(entry.path, path))) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : code;
36
+ return [{ code, message, path }];
37
+ });
38
+ }
39
+ function readFieldErrors(payload) {
40
+ const nested = (0, ovok_error_utils_1.asRecord)(payload === null || payload === void 0 ? void 0 : payload.error);
41
+ const listed = Array.isArray(nested === null || nested === void 0 ? void 0 : nested.errors)
42
+ ? nested.errors
43
+ : Array.isArray(payload === null || payload === void 0 ? void 0 : payload.errors)
44
+ ? payload.errors
45
+ : [];
46
+ const legacy = readEnvelopeErrors(Array.isArray(payload === null || payload === void 0 ? void 0 : payload.message) ? payload.message : []);
47
+ const problemErrors = readProblemErrors(listed, legacy);
48
+ const listedErrors = readEnvelopeErrors(listed);
49
+ // A problem body lists its fields in `errors[]` and keeps the older `message` list beside it; read either.
50
+ const envelopeErrors = problemErrors.length > 0
51
+ ? problemErrors
52
+ : listedErrors.length > 0
53
+ ? listedErrors
54
+ : legacy;
55
+ const outcome = Array.isArray(payload === null || payload === void 0 ? void 0 : payload.issue) ? payload.issue : [];
56
+ const nestedEnvelopeErrors = outcome.flatMap((value) => {
57
+ var _a;
58
+ const issue = (0, ovok_error_utils_1.asRecord)(value);
59
+ const details = (0, ovok_error_utils_1.asRecord)(issue === null || issue === void 0 ? void 0 : issue.details);
60
+ const nested = (_a = (0, ovok_error_utils_1.asRecord)((0, ovok_error_utils_1.parseJson)(details === null || details === void 0 ? void 0 : details.text))) !== null && _a !== void 0 ? _a : (0, ovok_error_utils_1.asRecord)((0, ovok_error_utils_1.parseJson)(issue === null || issue === void 0 ? void 0 : issue.diagnostics));
61
+ return nested ? readFieldErrors(nested) : [];
62
+ });
63
+ const outcomeErrors = outcome.flatMap((value) => {
64
+ var _a;
65
+ const issue = (0, ovok_error_utils_1.asRecord)(value);
66
+ const details = (0, ovok_error_utils_1.asRecord)(issue === null || issue === void 0 ? void 0 : issue.details);
67
+ const message = (_a = (0, ovok_error_utils_1.stringValue)(details === null || details === void 0 ? void 0 : details.text)) !== null && _a !== void 0 ? _a : (0, ovok_error_utils_1.stringValue)(issue === null || issue === void 0 ? void 0 : issue.diagnostics);
68
+ if ((issue === null || issue === void 0 ? void 0 : issue.severity) !== "error" || !message) {
69
+ return [];
70
+ }
71
+ const expressions = Array.isArray(issue.expression)
72
+ ? issue.expression
73
+ : Array.isArray(issue.location)
74
+ ? issue.location
75
+ : [];
76
+ const path = expressions.flatMap((expression) => typeof expression === "string" ? expression.split(".").filter(Boolean) : []);
77
+ return [{
78
+ ...((0, ovok_error_utils_1.stringValue)(issue.code) ? { code: (0, ovok_error_utils_1.stringValue)(issue.code) } : {}),
79
+ message,
80
+ path,
81
+ }];
82
+ });
83
+ return [...envelopeErrors, ...nestedEnvelopeErrors, ...outcomeErrors];
84
+ }
@@ -1,4 +1,3 @@
1
- import { ValidationError } from "../../types/ValidationError";
2
1
  export declare const OVOK_HTTP_ERROR_EXTENSION_URL = "https://api.ovok.com/fhir/StructureDefinition/http-error-metadata";
3
2
  /** `reason` itself when it is an Error, else an Error carrying its string form. */
4
3
  export declare const toError: (reason: unknown) => Error;
@@ -8,7 +7,6 @@ export declare const namedError: (name: string, message: string) => Error;
8
7
  export declare const withCause: <T extends Error>(error: T, cause: unknown) => T;
9
8
  export declare const asRecord: (value: unknown) => Record<string, unknown> | undefined;
10
9
  export declare function readMessage(payload: Record<string, unknown> | undefined, error: unknown): string;
11
- export declare function readFieldErrors(payload: Record<string, unknown> | undefined): ValidationError[];
12
10
  export declare function codeValue(value: unknown): string | undefined;
13
11
  export declare function codeFromOutcome(value: unknown): string | undefined;
14
12
  export declare function statusFromOutcome(value: unknown): number | undefined;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.asRecord = exports.withCause = exports.namedError = exports.toError = exports.OVOK_HTTP_ERROR_EXTENSION_URL = void 0;
4
4
  exports.readMessage = readMessage;
5
- exports.readFieldErrors = readFieldErrors;
6
5
  exports.codeValue = codeValue;
7
6
  exports.codeFromOutcome = codeFromOutcome;
8
7
  exports.statusFromOutcome = statusFromOutcome;
@@ -37,66 +36,15 @@ function readMessage(payload, error) {
37
36
  return messages.join("; ");
38
37
  }
39
38
  }
39
+ const detail = stringValue(payload === null || payload === void 0 ? void 0 : payload.detail);
40
+ if (detail) {
41
+ return detail;
42
+ }
40
43
  if (error instanceof Error) {
41
44
  return error.message;
42
45
  }
43
46
  return typeof error === "string" ? error : String(error);
44
47
  }
45
- function readFieldErrors(payload) {
46
- const messageErrors = Array.isArray(payload === null || payload === void 0 ? void 0 : payload.message) ? payload.message : [];
47
- const nested = (0, exports.asRecord)(payload === null || payload === void 0 ? void 0 : payload.error);
48
- const rawErrors = Array.isArray(nested === null || nested === void 0 ? void 0 : nested.errors)
49
- ? nested.errors
50
- : Array.isArray(payload === null || payload === void 0 ? void 0 : payload.errors)
51
- ? payload.errors
52
- : messageErrors;
53
- const envelopeErrors = rawErrors.flatMap((value) => {
54
- const record = (0, exports.asRecord)(value);
55
- if (!record || typeof record.message !== "string") {
56
- return [];
57
- }
58
- const path = Array.isArray(record.path)
59
- ? record.path.map((segment) => String(segment))
60
- : [];
61
- return [{
62
- ...(stringValue(record.code) ? { code: stringValue(record.code) } : {}),
63
- message: record.message,
64
- path,
65
- ...(stringValue(record.validation)
66
- ? { validation: stringValue(record.validation) }
67
- : {}),
68
- }];
69
- });
70
- const outcome = Array.isArray(payload === null || payload === void 0 ? void 0 : payload.issue) ? payload.issue : [];
71
- const nestedEnvelopeErrors = outcome.flatMap((value) => {
72
- var _a;
73
- const issue = (0, exports.asRecord)(value);
74
- const details = (0, exports.asRecord)(issue === null || issue === void 0 ? void 0 : issue.details);
75
- const nested = (_a = (0, exports.asRecord)(parseJson(details === null || details === void 0 ? void 0 : details.text))) !== null && _a !== void 0 ? _a : (0, exports.asRecord)(parseJson(issue === null || issue === void 0 ? void 0 : issue.diagnostics));
76
- return nested ? readFieldErrors(nested) : [];
77
- });
78
- const outcomeErrors = outcome.flatMap((value) => {
79
- var _a;
80
- const issue = (0, exports.asRecord)(value);
81
- const details = (0, exports.asRecord)(issue === null || issue === void 0 ? void 0 : issue.details);
82
- const message = (_a = stringValue(details === null || details === void 0 ? void 0 : details.text)) !== null && _a !== void 0 ? _a : stringValue(issue === null || issue === void 0 ? void 0 : issue.diagnostics);
83
- if ((issue === null || issue === void 0 ? void 0 : issue.severity) !== "error" || !message) {
84
- return [];
85
- }
86
- const expressions = Array.isArray(issue.expression)
87
- ? issue.expression
88
- : Array.isArray(issue.location)
89
- ? issue.location
90
- : [];
91
- const path = expressions.flatMap((expression) => typeof expression === "string" ? expression.split(".").filter(Boolean) : []);
92
- return [{
93
- ...(stringValue(issue.code) ? { code: stringValue(issue.code) } : {}),
94
- message,
95
- path,
96
- }];
97
- });
98
- return [...envelopeErrors, ...nestedEnvelopeErrors, ...outcomeErrors];
99
- }
100
48
  function codeValue(value) {
101
49
  return typeof value === "string" && /^[a-z][a-z0-9_]+$/.test(value)
102
50
  ? value
@@ -1,12 +1,18 @@
1
1
  import { ValidationError } from "../../types/ValidationError";
2
- export { asRecord, readFieldErrors, readMessage } from "./ovok-error-utils";
2
+ export { asRecord, readMessage } from "./ovok-error-utils";
3
+ export { readFieldErrors } from "./field-errors";
3
4
  export type ParsedOvokError = {
4
5
  message: string;
5
6
  fieldErrors: ValidationError[];
6
7
  };
7
8
  export type OvokErrorDetails = ParsedOvokError & {
8
9
  status: number | undefined;
10
+ /** The condition the server named; undefined when the error is known only by its status. */
9
11
  code: string | undefined;
12
+ /** The problem type URI, `https://docs.ovok.com/errors/<code>`, which also names status-only errors. */
13
+ type?: string;
14
+ /** Equals the `x-trace-id` response header; quote it when reporting an error. */
15
+ traceId?: string;
10
16
  requestId?: string;
11
17
  retryAfterMs?: number;
12
18
  missing: string[];
@@ -17,6 +23,8 @@ export declare const readOvokError: (error: unknown) => OvokErrorDetails;
17
23
  export declare class OvokApiError extends Error {
18
24
  readonly status: number;
19
25
  readonly code: string | undefined;
26
+ readonly type: string | undefined;
27
+ readonly traceId: string | undefined;
20
28
  readonly fieldErrors: ValidationError[];
21
29
  readonly missing: string[];
22
30
  readonly requestId: string | undefined;
@@ -1,13 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseOvokError = exports.OvokApiError = exports.readOvokError = exports.readMessage = exports.readFieldErrors = exports.asRecord = void 0;
3
+ exports.parseOvokError = exports.OvokApiError = exports.readOvokError = exports.readFieldErrors = exports.readMessage = exports.asRecord = void 0;
4
4
  exports.isOvokApiError = isOvokApiError;
5
5
  exports.mapOvokApiError = mapOvokApiError;
6
+ const field_errors_1 = require("./field-errors");
6
7
  const ovok_error_utils_1 = require("./ovok-error-utils");
8
+ const problem_code_1 = require("./problem-code");
7
9
  var ovok_error_utils_2 = require("./ovok-error-utils");
8
10
  Object.defineProperty(exports, "asRecord", { enumerable: true, get: function () { return ovok_error_utils_2.asRecord; } });
9
- Object.defineProperty(exports, "readFieldErrors", { enumerable: true, get: function () { return ovok_error_utils_2.readFieldErrors; } });
10
11
  Object.defineProperty(exports, "readMessage", { enumerable: true, get: function () { return ovok_error_utils_2.readMessage; } });
12
+ var field_errors_2 = require("./field-errors");
13
+ Object.defineProperty(exports, "readFieldErrors", { enumerable: true, get: function () { return field_errors_2.readFieldErrors; } });
11
14
  const STATUS_BY_BARE_CODE = {
12
15
  INVALID_SETTING_VALUE: 422,
13
16
  APP_URL_NOT_ALLOWED: 400,
@@ -26,11 +29,13 @@ const HTTP_REASON_PHRASES = new Set([
26
29
  ]);
27
30
  /** Reads the error details Medplum preserves from Ovok's non-FHIR responses. */
28
31
  const readOvokError = (error) => {
29
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
32
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
30
33
  if (error instanceof OvokApiError) {
31
34
  return {
32
35
  status: error.status,
33
36
  code: error.code,
37
+ ...(error.type === undefined ? {} : { type: error.type }),
38
+ ...(error.traceId === undefined ? {} : { traceId: error.traceId }),
34
39
  ...(error.requestId === undefined ? {} : { requestId: error.requestId }),
35
40
  ...(error.retryAfterMs === undefined ? {} : { retryAfterMs: error.retryAfterMs }),
36
41
  message: error.message,
@@ -56,18 +61,23 @@ const readOvokError = (error) => {
56
61
  && !HTTP_REASON_PHRASES.has(bareMessage.toLowerCase())
57
62
  ? bareMessage
58
63
  : undefined;
59
- const code = (_l = (_k = (_j = (_h = (0, ovok_error_utils_1.stringValue)(payload === null || payload === void 0 ? void 0 : payload.code)) !== null && _h !== void 0 ? _h : (0, ovok_error_utils_1.stringValue)(nestedError === null || nestedError === void 0 ? void 0 : nestedError.code)) !== null && _j !== void 0 ? _j : (0, ovok_error_utils_1.codeValue)(payload === null || payload === void 0 ? void 0 : payload.error)) !== null && _k !== void 0 ? _k : bareCode) !== null && _l !== void 0 ? _l : (0, ovok_error_utils_1.codeFromOutcome)((_m = payload === null || payload === void 0 ? void 0 : payload.outcome) !== null && _m !== void 0 ? _m : payload);
60
- const status = (_v = (_t = (_s = (_r = (_q = (_p = (_o = metadata.status) !== null && _o !== void 0 ? _o : (0, ovok_error_utils_1.numberValue)(root === null || root === void 0 ? void 0 : root.status)) !== null && _p !== void 0 ? _p : (0, ovok_error_utils_1.numberValue)(root === null || root === void 0 ? void 0 : root.statusCode)) !== null && _q !== void 0 ? _q : (0, ovok_error_utils_1.numberValue)(response === null || response === void 0 ? void 0 : response.status)) !== null && _r !== void 0 ? _r : (0, ovok_error_utils_1.numberValue)(payload === null || payload === void 0 ? void 0 : payload.status)) !== null && _s !== void 0 ? _s : (0, ovok_error_utils_1.numberValue)(payload === null || payload === void 0 ? void 0 : payload.statusCode)) !== null && _t !== void 0 ? _t : (0, ovok_error_utils_1.statusFromOutcome)((_u = payload === null || payload === void 0 ? void 0 : payload.outcome) !== null && _u !== void 0 ? _u : payload)) !== null && _v !== void 0 ? _v : (code ? STATUS_BY_BARE_CODE[code] : undefined);
61
- const fieldErrors = (0, ovok_error_utils_1.readFieldErrors)(payload);
64
+ const writtenCode = (_h = (0, ovok_error_utils_1.stringValue)(nestedError === null || nestedError === void 0 ? void 0 : nestedError.code)) !== null && _h !== void 0 ? _h : (0, ovok_error_utils_1.codeValue)(payload === null || payload === void 0 ? void 0 : payload.error);
65
+ const type = (0, problem_code_1.problemTypeOf)(payload === null || payload === void 0 ? void 0 : payload.type);
66
+ const code = (_o = (_l = (_k = (_j = (0, problem_code_1.conditionCode)((0, problem_code_1.ownCode)(payload === null || payload === void 0 ? void 0 : payload.code), writtenCode)) !== null && _j !== void 0 ? _j : writtenCode) !== null && _k !== void 0 ? _k : bareCode) !== null && _l !== void 0 ? _l : (0, ovok_error_utils_1.codeFromOutcome)((_m = payload === null || payload === void 0 ? void 0 : payload.outcome) !== null && _m !== void 0 ? _m : payload)) !== null && _o !== void 0 ? _o : (0, problem_code_1.problemCodeOf)(type);
67
+ const traceId = (0, ovok_error_utils_1.stringValue)(payload === null || payload === void 0 ? void 0 : payload.traceId);
68
+ const status = (_w = (_u = (_t = (_s = (_r = (_q = (_p = metadata.status) !== null && _p !== void 0 ? _p : (0, ovok_error_utils_1.numberValue)(root === null || root === void 0 ? void 0 : root.status)) !== null && _q !== void 0 ? _q : (0, ovok_error_utils_1.numberValue)(root === null || root === void 0 ? void 0 : root.statusCode)) !== null && _r !== void 0 ? _r : (0, ovok_error_utils_1.numberValue)(response === null || response === void 0 ? void 0 : response.status)) !== null && _s !== void 0 ? _s : (0, ovok_error_utils_1.numberValue)(payload === null || payload === void 0 ? void 0 : payload.status)) !== null && _t !== void 0 ? _t : (0, ovok_error_utils_1.numberValue)(payload === null || payload === void 0 ? void 0 : payload.statusCode)) !== null && _u !== void 0 ? _u : (0, ovok_error_utils_1.statusFromOutcome)((_v = payload === null || payload === void 0 ? void 0 : payload.outcome) !== null && _v !== void 0 ? _v : payload)) !== null && _w !== void 0 ? _w : (code ? STATUS_BY_BARE_CODE[code] : undefined);
69
+ const fieldErrors = (0, field_errors_1.readFieldErrors)(payload);
62
70
  const missing = Array.isArray(payload === null || payload === void 0 ? void 0 : payload.missing)
63
71
  ? payload.missing.filter((entry) => typeof entry === "string")
64
72
  : [];
65
73
  const retryAfterSec = (0, ovok_error_utils_1.numberValue)(payload === null || payload === void 0 ? void 0 : payload.retryAfterSec);
66
- const retryAfterMs = (_x = (_w = metadata.retryAfterMs) !== null && _w !== void 0 ? _w : (0, ovok_error_utils_1.numberValue)(payload === null || payload === void 0 ? void 0 : payload.retryAfterMs)) !== null && _x !== void 0 ? _x : (retryAfterSec === undefined ? undefined : retryAfterSec * 1000);
67
- const requestId = (_y = metadata.requestId) !== null && _y !== void 0 ? _y : (0, ovok_error_utils_1.stringValue)(payload === null || payload === void 0 ? void 0 : payload.requestId);
74
+ const retryAfterMs = (_y = (_x = metadata.retryAfterMs) !== null && _x !== void 0 ? _x : (0, ovok_error_utils_1.numberValue)(payload === null || payload === void 0 ? void 0 : payload.retryAfterMs)) !== null && _y !== void 0 ? _y : (retryAfterSec === undefined ? undefined : retryAfterSec * 1000);
75
+ const requestId = (_z = metadata.requestId) !== null && _z !== void 0 ? _z : (0, ovok_error_utils_1.stringValue)(payload === null || payload === void 0 ? void 0 : payload.requestId);
68
76
  return {
69
77
  status,
70
78
  code,
79
+ ...(type === undefined ? {} : { type }),
80
+ ...(traceId === undefined ? {} : { traceId }),
71
81
  ...(requestId === undefined ? {} : { requestId }),
72
82
  ...(retryAfterMs === undefined ? {} : { retryAfterMs }),
73
83
  message: (0, ovok_error_utils_1.readMessage)(payload, error),
@@ -84,6 +94,8 @@ class OvokApiError extends Error {
84
94
  this.name = "OvokApiError";
85
95
  this.status = (_a = details.status) !== null && _a !== void 0 ? _a : 0;
86
96
  this.code = details.code;
97
+ this.type = details.type;
98
+ this.traceId = details.traceId;
87
99
  this.fieldErrors = details.fieldErrors;
88
100
  this.missing = details.missing;
89
101
  this.requestId = details.requestId;
@@ -103,7 +115,7 @@ function mapOvokApiError(error, options = {}) {
103
115
  }
104
116
  const details = (0, exports.readOvokError)(error);
105
117
  const typedStatuses = options.includeAccessErrors
106
- ? [403, 404, 409, 410, 422, 424, 503]
118
+ ? [403, 404, 409, 410, 422, 424, 501, 503]
107
119
  : [409, 410, 422, 424, 503];
108
120
  return typedStatuses.includes((_a = details.status) !== null && _a !== void 0 ? _a : 0)
109
121
  ? new OvokApiError(details, error)
@@ -0,0 +1,5 @@
1
+ export declare const ownCode: (value: unknown) => string | undefined;
2
+ /** Core sends a throw site's code upper-cased in `code` and as written in `error`: keep the written form. */
3
+ export declare const conditionCode: (problemCode: string | undefined, writtenCode: string | undefined) => string | undefined;
4
+ export declare const problemTypeOf: (value: unknown) => string | undefined;
5
+ export declare const problemCodeOf: (type: string | undefined) => string | undefined;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.problemCodeOf = exports.problemTypeOf = exports.conditionCode = exports.ownCode = void 0;
4
+ const ovok_error_utils_1 = require("./ovok-error-utils");
5
+ const PROBLEM_TYPE_PREFIX = "https://docs.ovok.com/errors/";
6
+ // The codes Core gives an error by its status alone: they name no condition, so `code` stays undefined for them.
7
+ const STATUS_ONLY_CODES = new Set([
8
+ "MALFORMED_REQUEST",
9
+ "UNAUTHENTICATED",
10
+ "FORBIDDEN",
11
+ "NOT_FOUND",
12
+ "METHOD_NOT_ALLOWED",
13
+ "NOT_ACCEPTABLE",
14
+ "REQUEST_TIMEOUT",
15
+ "CONFLICT",
16
+ "GONE",
17
+ "PRECONDITION_FAILED",
18
+ "CONTENT_TOO_LARGE",
19
+ "UNSUPPORTED_MEDIA_TYPE",
20
+ "VALIDATION_FAILED",
21
+ "LOCKED",
22
+ "FAILED_DEPENDENCY",
23
+ "PRECONDITION_REQUIRED",
24
+ "TOO_MANY_REQUESTS",
25
+ "INTERNAL_ERROR",
26
+ "NOT_IMPLEMENTED",
27
+ "UPSTREAM_ERROR",
28
+ "SERVICE_UNAVAILABLE",
29
+ "UPSTREAM_TIMEOUT",
30
+ "SERVER_ERROR",
31
+ "CLIENT_ERROR",
32
+ ]);
33
+ const ownCode = (value) => {
34
+ const code = (0, ovok_error_utils_1.stringValue)(value);
35
+ return code && !STATUS_ONLY_CODES.has(code) ? code : undefined;
36
+ };
37
+ exports.ownCode = ownCode;
38
+ /** Core sends a throw site's code upper-cased in `code` and as written in `error`: keep the written form. */
39
+ const conditionCode = (problemCode, writtenCode) => problemCode && (writtenCode === null || writtenCode === void 0 ? void 0 : writtenCode.toUpperCase()) === problemCode.toUpperCase() ? writtenCode : problemCode;
40
+ exports.conditionCode = conditionCode;
41
+ const problemTypeOf = (value) => {
42
+ const type = (0, ovok_error_utils_1.stringValue)(value);
43
+ return (type === null || type === void 0 ? void 0 : type.startsWith(PROBLEM_TYPE_PREFIX)) ? type : undefined;
44
+ };
45
+ exports.problemTypeOf = problemTypeOf;
46
+ const problemCodeOf = (type) => {
47
+ const slug = type === null || type === void 0 ? void 0 : type.slice(PROBLEM_TYPE_PREFIX.length);
48
+ if (!slug) {
49
+ return undefined;
50
+ }
51
+ const code = slug.replace(/-/g, "_").toUpperCase();
52
+ return STATUS_ONLY_CODES.has(code) ? undefined : code;
53
+ };
54
+ exports.problemCodeOf = problemCodeOf;
@@ -23,6 +23,7 @@ import * as platformMethods from "./platform/methods";
23
23
  import * as questionnaireResponseMethods from "./questionnaire-response/methods";
24
24
  import * as signalsMethods from "./signals/methods";
25
25
  import * as slimMethods from "./slim/methods";
26
+ import * as wearableMethods from "./wearables/methods";
26
27
  export { MAX_CONDITIONAL_OBSERVATION_ENTRIES, MAX_OBSERVATION_BUNDLE_BYTES, } from "./observation/observation-bundle-utils";
27
28
  export type { OvokUnauthenticatedReason } from "./auth/session-fetch";
28
29
  export type SaveObservationsResult = {
@@ -146,7 +147,7 @@ export declare class OvokClient extends MedplumClient {
146
147
  */
147
148
  getSubscriptionManager(): SubscriptionManager;
148
149
  }
149
- type Methods = typeof authMethods & typeof observationMethods & typeof questionnaireResponseMethods & typeof aiMethods & typeof aiFhirMethods & typeof botMethods & typeof slimMethods & typeof emailMethods & typeof cmsMethods & typeof changeHistoryMethods & typeof consentMethods & typeof platformMethods & typeof experienceMethods & typeof inviteMethods & typeof notificationMethods & typeof patientMethods & typeof patientSharingMethods & typeof signalsMethods;
150
+ type Methods = typeof authMethods & typeof observationMethods & typeof questionnaireResponseMethods & typeof aiMethods & typeof aiFhirMethods & typeof botMethods & typeof slimMethods & typeof emailMethods & typeof cmsMethods & typeof changeHistoryMethods & typeof consentMethods & typeof platformMethods & typeof experienceMethods & typeof inviteMethods & typeof notificationMethods & typeof patientMethods & typeof patientSharingMethods & typeof wearableMethods & typeof signalsMethods;
150
151
  type Omitted<T> = Omit<T, "executeBot">;
151
152
  declare module "./ovok-client" {
152
153
  interface OvokClient extends Omitted<Methods> {
@@ -66,6 +66,7 @@ const request_options_1 = require("./request-options");
66
66
  const errors_2 = require("./signals/errors");
67
67
  const signalsMethods = __importStar(require("./signals/methods"));
68
68
  const slimMethods = __importStar(require("./slim/methods"));
69
+ const wearableMethods = __importStar(require("./wearables/methods"));
69
70
  var observation_bundle_utils_2 = require("./observation/observation-bundle-utils");
70
71
  Object.defineProperty(exports, "MAX_CONDITIONAL_OBSERVATION_ENTRIES", { enumerable: true, get: function () { return observation_bundle_utils_2.MAX_CONDITIONAL_OBSERVATION_ENTRIES; } });
71
72
  Object.defineProperty(exports, "MAX_OBSERVATION_BUNDLE_BYTES", { enumerable: true, get: function () { return observation_bundle_utils_2.MAX_OBSERVATION_BUNDLE_BYTES; } });
@@ -143,6 +144,7 @@ class OvokClient extends core_1.MedplumClient {
143
144
  this.bindMethods(notificationMethods, (error) => (0, ovok_error_1.mapOvokApiError)((0, rate_limit_error_1.mapRateLimitError)(error), { includeAccessErrors: true }));
144
145
  this.bindMethods(patientMethods);
145
146
  this.bindMethods(patientSharingMethods);
147
+ this.bindMethods(wearableMethods, (error) => (0, ovok_error_1.mapOvokApiError)((0, rate_limit_error_1.mapRateLimitError)(error), { includeAccessErrors: true }));
146
148
  this.bindMethods(signalsMethods, (error) => {
147
149
  const mapped = (0, errors_2.mapSignalsError)((0, rate_limit_error_1.mapRateLimitError)(error), {
148
150
  signalsRequest: true,
@@ -0,0 +1,2 @@
1
+ export * from "./methods";
2
+ export * from "./types";
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./methods"), exports);
18
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,11 @@
1
+ import type { MedplumRequestOptions } from "@medplum/core";
2
+ import { OvokClient } from "../ovok-client";
3
+ import { CreateWearableProviderRequest, UpdateWearableProviderRequest, WearableConnectionAuthorization, WearableConnections, WearableProvider, WearableProviderSettings, WearableProviderSettingsList } from "./types";
4
+ export declare function listWearableProviders(this: OvokClient, requestOptions?: MedplumRequestOptions): Promise<WearableProviderSettingsList>;
5
+ export declare function getWearableProvider(this: OvokClient, provider: WearableProvider, requestOptions?: MedplumRequestOptions): Promise<WearableProviderSettings>;
6
+ export declare function createWearableProvider(this: OvokClient, body: CreateWearableProviderRequest, requestOptions?: MedplumRequestOptions): Promise<WearableProviderSettings>;
7
+ export declare function updateWearableProvider(this: OvokClient, provider: WearableProvider, body: UpdateWearableProviderRequest, requestOptions?: MedplumRequestOptions): Promise<WearableProviderSettings>;
8
+ export declare function deleteWearableProvider(this: OvokClient, provider: WearableProvider, requestOptions?: MedplumRequestOptions): Promise<void>;
9
+ export declare function listWearableConnections(this: OvokClient, requestOptions?: MedplumRequestOptions): Promise<WearableConnections>;
10
+ export declare function authorizeWearableConnection(this: OvokClient, provider: WearableProvider, requestOptions?: MedplumRequestOptions): Promise<WearableConnectionAuthorization>;
11
+ export declare function deleteWearableConnection(this: OvokClient, provider: WearableProvider, requestOptions?: MedplumRequestOptions): Promise<void>;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listWearableProviders = listWearableProviders;
4
+ exports.getWearableProvider = getWearableProvider;
5
+ exports.createWearableProvider = createWearableProvider;
6
+ exports.updateWearableProvider = updateWearableProvider;
7
+ exports.deleteWearableProvider = deleteWearableProvider;
8
+ exports.listWearableConnections = listWearableConnections;
9
+ exports.authorizeWearableConnection = authorizeWearableConnection;
10
+ exports.deleteWearableConnection = deleteWearableConnection;
11
+ const request_options_1 = require("../request-options");
12
+ const providerPath = (provider) => `/v1/wearables/providers/${encodeURIComponent(provider)}`;
13
+ const connectionPath = (provider) => `/v1/wearables/connections/${encodeURIComponent(provider)}`;
14
+ const invalidateProviderSettings = (client, provider) => {
15
+ client.invalidateUrl("/v1/wearables/providers");
16
+ if (provider) {
17
+ client.invalidateUrl(providerPath(provider));
18
+ }
19
+ };
20
+ function listWearableProviders(requestOptions) {
21
+ return this.get("/v1/wearables/providers", ...(0, request_options_1.optionalArg)(requestOptions));
22
+ }
23
+ function getWearableProvider(provider, requestOptions) {
24
+ return this.get(providerPath(provider), ...(0, request_options_1.optionalArg)(requestOptions));
25
+ }
26
+ function createWearableProvider(body, requestOptions) {
27
+ return this.post("/v1/wearables/providers", body, undefined, requestOptions).then((settings) => {
28
+ invalidateProviderSettings(this, body.provider);
29
+ return settings;
30
+ });
31
+ }
32
+ async function updateWearableProvider(provider, body, requestOptions) {
33
+ const settings = await this.patch(providerPath(provider), body, ...(0, request_options_1.optionalArg)(requestOptions));
34
+ invalidateProviderSettings(this, provider);
35
+ return settings;
36
+ }
37
+ async function deleteWearableProvider(provider, requestOptions) {
38
+ await this.delete(providerPath(provider), ...(0, request_options_1.optionalArg)(requestOptions));
39
+ invalidateProviderSettings(this, provider);
40
+ }
41
+ function listWearableConnections(requestOptions) {
42
+ return this.get("/v1/wearables/connections", ...(0, request_options_1.optionalArg)(requestOptions));
43
+ }
44
+ function authorizeWearableConnection(provider, requestOptions) {
45
+ return this.post(`${connectionPath(provider)}/authorize`, undefined, undefined, requestOptions);
46
+ }
47
+ async function deleteWearableConnection(provider, requestOptions) {
48
+ await this.delete(connectionPath(provider), ...(0, request_options_1.optionalArg)(requestOptions));
49
+ this.invalidateUrl("/v1/wearables/connections");
50
+ }
@@ -0,0 +1,38 @@
1
+ export type WearableProvider = "oura" | "whoop" | "strava" | "withings" | "polar" | "suunto" | "garmin" | "ultrahuman";
2
+ export type WearableErrorCode = "PROVIDER_CONFIGURED" | "PROVIDER_NOT_CONFIGURED" | "SUBSCRIPTION_KEY_REQUIRED" | "SUBSCRIPTION_KEY_NOT_USED" | "PROVIDER_NOT_AVAILABLE" | "APP_URL_NOT_CONFIGURED" | "CONNECTION_NOT_FOUND" | "STATE_STORE_UNAVAILABLE" | "FEATURE_NOT_CONFIGURED" | "PROJECT_CONTEXT_REQUIRED" | "PATIENT_PROFILE_REQUIRED";
3
+ export type WearableProviderSettings = {
4
+ provider: WearableProvider;
5
+ configured: boolean;
6
+ enabled: boolean;
7
+ clientId: string | null;
8
+ redirectUri: string | null;
9
+ };
10
+ export type WearableProviderSettingsList = {
11
+ providers: WearableProviderSettings[];
12
+ };
13
+ export type CreateWearableProviderRequest = {
14
+ provider: WearableProvider;
15
+ clientId: string;
16
+ secret: string;
17
+ subscriptionKey: string | null;
18
+ enabled: boolean;
19
+ };
20
+ export type UpdateWearableProviderRequest = {
21
+ clientId?: string;
22
+ secret?: string;
23
+ subscriptionKey?: string | null;
24
+ enabled?: boolean;
25
+ };
26
+ export type WearableConnection = {
27
+ provider: WearableProvider;
28
+ connection: {
29
+ connectedAt: string;
30
+ } | null;
31
+ };
32
+ export type WearableConnections = {
33
+ connections: WearableConnection[];
34
+ };
35
+ export type WearableConnectionAuthorization = {
36
+ provider: WearableProvider;
37
+ authorizationUrl: string;
38
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -48,7 +48,7 @@ exports.OVOK_CORE_REQUIREMENTS = {
48
48
  description: "The FHIR surface a server must provide for the @ovok/core client library's own methods to function.",
49
49
  software: {
50
50
  name: "@ovok/core",
51
- version: "0.4.44",
51
+ version: "0.4.46",
52
52
  },
53
53
  fhirVersion: "4.0.1",
54
54
  format: ["json"],
@@ -21,4 +21,5 @@ export { useCmsDocument, useCmsDocuments, useLegalPage, useReleaseNotes, useTran
21
21
  export { useAcceptInvite, useInvitePatient, useInvitePractitioner, } from "./invites-hooks";
22
22
  export { useCurrentPatientProfile, useExtractQuestionnaireObservations, usePatientAppointments, usePatientCarePlans, usePatientDevices, usePatientMeasurement, usePatientMeasurementHistory, usePatientDashboard, usePatientLatestObservations, usePatientNotifications, usePatientQuestionnaireResponses, usePatientQuestionnaires, usePatientSchedules, usePatientSlots, usePopulateQuestionnaire, useSubmitQuestionnaireResponse, } from "./patient-hooks";
23
23
  export { useCreatePatientSharingInvite, usePatientSharing, usePatientSharingSettings, useRedeemPatientSharingInvite, useRevokePatientSharing, useUpdatePatientSharingSettings, } from "./patient-sharing-hooks";
24
+ export { useAuthorizeWearableConnection, useCreateWearableProvider, useDeleteWearableConnection, useDeleteWearableProvider, useUpdateWearableProvider, useWearableConnections, useWearableProviders, } from "./wearables-hooks";
24
25
  export { useAcknowledgeSignalsAlert, useEnableSignalsForPatient, useRemoveSignalsThreshold, useSetSignalsThreshold, useSignalsAlert, useSignalsAlerts, useSignalsSettings, useSignalsThresholds, useUpdateSignalsSettings, } from "./signals-hooks";
@@ -36,7 +36,7 @@ var __importStar = (this && this.__importStar) || (function () {
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
37
  exports.useSlimPatientThresholdV2 = exports.useSetMedicalConsent = exports.useSetLegalConsent = exports.useRepushUnconfirmedLimits = exports.useMedicalConsent = exports.useLegalConsent = exports.useChangeHistory = exports.useEmailTemplates = exports.useUpdateProjectTextSetting = exports.useUpdateLocalization = exports.useUpdateI18nextDocument = exports.useLocalizations = exports.useLocales = exports.useI18nextDocument = exports.useVideoCallAppointments = exports.useVideoCallAccess = exports.useDocuments = exports.useCreateVideoCallUserAccess = exports.useCreateVideoCallAppointment = exports.useContent = exports.useConsentSignature = exports.useOvokPoll = exports.usePublicApiEndpoints = exports.useProjectSettings = exports.useProjectFeatures = exports.useOvokRequest = exports.useOvokMutation = exports.useCapabilityStatement = exports.useSlimPatients = exports.useSlimDevices = exports.useSlimDeviceTelemetry = exports.useAdministeredProjects = exports.useUrineTests = exports.useSaveMeasurement = exports.useObservations = exports.useEcgRecording = exports.observationsToMeasurements = exports.OvokProvider = exports.useClient = exports.useCachedBinaryUrl = exports.reactContext = exports.useSubscription = exports.useSearchResources = exports.useSearchOne = exports.useSearch = exports.useResource = exports.usePrevious = exports.useMedplumProfile = exports.useMedplumNavigate = exports.useMedplumContext = void 0;
38
38
  exports.usePatientSharingSettings = exports.usePatientSharing = exports.useCreatePatientSharingInvite = exports.useSubmitQuestionnaireResponse = exports.usePopulateQuestionnaire = exports.usePatientSlots = exports.usePatientSchedules = exports.usePatientQuestionnaires = exports.usePatientQuestionnaireResponses = exports.usePatientNotifications = exports.usePatientLatestObservations = exports.usePatientDashboard = exports.usePatientMeasurementHistory = exports.usePatientMeasurement = exports.usePatientDevices = exports.usePatientCarePlans = exports.usePatientAppointments = exports.useExtractQuestionnaireObservations = exports.useCurrentPatientProfile = exports.useInvitePractitioner = exports.useInvitePatient = exports.useAcceptInvite = exports.useTranslations = exports.useReleaseNotes = exports.useLegalPage = exports.useCmsDocuments = exports.useCmsDocument = exports.useAcknowledgeSlimMedicalNotification = exports.useAcknowledgeSlimAlarm = exports.useUpdateSignalsNote = exports.useUpdateNotificationNote = exports.useSignalsRawAlertNotes = exports.useSignalsAlertNotes = exports.useNotificationNotes = exports.useDeleteSignalsNote = exports.useDeleteNotificationNote = exports.useCreateSignalsRawAlertNote = exports.useCreateSignalsAlertNote = exports.useCreateNotificationNote = exports.useSlimOutOfBedNotifications = exports.useSlimNotifications = exports.useSlimMedicalNotifications = exports.useSlimAlarms = exports.useRecentSlimNotifications = exports.useRecentOutOfBed = exports.useRecentAlarms = exports.useUpdateSlimThresholdV2 = exports.useUpdateSlimPatientThresholdV2 = exports.useUnconfirmedLimits = exports.useSlimThresholdV2 = void 0;
39
- exports.useUpdateSignalsSettings = exports.useSignalsThresholds = exports.useSignalsSettings = exports.useSignalsAlerts = exports.useSignalsAlert = exports.useSetSignalsThreshold = exports.useRemoveSignalsThreshold = exports.useEnableSignalsForPatient = exports.useAcknowledgeSignalsAlert = exports.useUpdatePatientSharingSettings = exports.useRevokePatientSharing = exports.useRedeemPatientSharingInvite = void 0;
39
+ exports.useUpdateSignalsSettings = exports.useSignalsThresholds = exports.useSignalsSettings = exports.useSignalsAlerts = exports.useSignalsAlert = exports.useSetSignalsThreshold = exports.useRemoveSignalsThreshold = exports.useEnableSignalsForPatient = exports.useAcknowledgeSignalsAlert = exports.useWearableProviders = exports.useWearableConnections = exports.useUpdateWearableProvider = exports.useDeleteWearableProvider = exports.useDeleteWearableConnection = exports.useCreateWearableProvider = exports.useAuthorizeWearableConnection = exports.useUpdatePatientSharingSettings = exports.useRevokePatientSharing = exports.useRedeemPatientSharingInvite = void 0;
40
40
  /*
41
41
  * The only React-dependent module in the package.
42
42
  *
@@ -176,6 +176,14 @@ Object.defineProperty(exports, "usePatientSharingSettings", { enumerable: true,
176
176
  Object.defineProperty(exports, "useRedeemPatientSharingInvite", { enumerable: true, get: function () { return patient_sharing_hooks_1.useRedeemPatientSharingInvite; } });
177
177
  Object.defineProperty(exports, "useRevokePatientSharing", { enumerable: true, get: function () { return patient_sharing_hooks_1.useRevokePatientSharing; } });
178
178
  Object.defineProperty(exports, "useUpdatePatientSharingSettings", { enumerable: true, get: function () { return patient_sharing_hooks_1.useUpdatePatientSharingSettings; } });
179
+ var wearables_hooks_1 = require("./wearables-hooks");
180
+ Object.defineProperty(exports, "useAuthorizeWearableConnection", { enumerable: true, get: function () { return wearables_hooks_1.useAuthorizeWearableConnection; } });
181
+ Object.defineProperty(exports, "useCreateWearableProvider", { enumerable: true, get: function () { return wearables_hooks_1.useCreateWearableProvider; } });
182
+ Object.defineProperty(exports, "useDeleteWearableConnection", { enumerable: true, get: function () { return wearables_hooks_1.useDeleteWearableConnection; } });
183
+ Object.defineProperty(exports, "useDeleteWearableProvider", { enumerable: true, get: function () { return wearables_hooks_1.useDeleteWearableProvider; } });
184
+ Object.defineProperty(exports, "useUpdateWearableProvider", { enumerable: true, get: function () { return wearables_hooks_1.useUpdateWearableProvider; } });
185
+ Object.defineProperty(exports, "useWearableConnections", { enumerable: true, get: function () { return wearables_hooks_1.useWearableConnections; } });
186
+ Object.defineProperty(exports, "useWearableProviders", { enumerable: true, get: function () { return wearables_hooks_1.useWearableProviders; } });
179
187
  var signals_hooks_1 = require("./signals-hooks");
180
188
  Object.defineProperty(exports, "useAcknowledgeSignalsAlert", { enumerable: true, get: function () { return signals_hooks_1.useAcknowledgeSignalsAlert; } });
181
189
  Object.defineProperty(exports, "useEnableSignalsForPatient", { enumerable: true, get: function () { return signals_hooks_1.useEnableSignalsForPatient; } });
@@ -0,0 +1,5 @@
1
+ import { OvokClient } from "../client/ovok-client";
2
+ type WearableChange = "providers" | "connections";
3
+ export declare const subscribeToWearableChanges: (client: OvokClient, change: WearableChange, reload: () => void) => (() => void);
4
+ export declare const notifyWearableChanges: (client: OvokClient, change: WearableChange) => void;
5
+ export {};
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.notifyWearableChanges = exports.subscribeToWearableChanges = void 0;
4
+ const listeners = new WeakMap();
5
+ const subscribeToWearableChanges = (client, change, reload) => {
6
+ var _a;
7
+ const listener = (updated) => {
8
+ if (updated === change) {
9
+ reload();
10
+ }
11
+ };
12
+ const clientListeners = (_a = listeners.get(client)) !== null && _a !== void 0 ? _a : new Set();
13
+ clientListeners.add(listener);
14
+ listeners.set(client, clientListeners);
15
+ return () => clientListeners.delete(listener);
16
+ };
17
+ exports.subscribeToWearableChanges = subscribeToWearableChanges;
18
+ const notifyWearableChanges = (client, change) => {
19
+ var _a;
20
+ (_a = listeners.get(client)) === null || _a === void 0 ? void 0 : _a.forEach((listener) => listener(change));
21
+ };
22
+ exports.notifyWearableChanges = notifyWearableChanges;
@@ -0,0 +1,12 @@
1
+ import { CreateWearableProviderRequest, UpdateWearableProviderRequest, WearableConnectionAuthorization, WearableConnections, WearableProvider, WearableProviderSettings, WearableProviderSettingsList } from "../client/wearables";
2
+ import { OvokMutationState, OvokRequestState } from "./api-hooks";
3
+ export declare const useWearableProviders: () => OvokRequestState<WearableProviderSettingsList>;
4
+ export declare const useWearableConnections: () => OvokRequestState<WearableConnections>;
5
+ export declare const useCreateWearableProvider: () => OvokMutationState<CreateWearableProviderRequest, WearableProviderSettings>;
6
+ export declare const useUpdateWearableProvider: () => OvokMutationState<{
7
+ provider: WearableProvider;
8
+ body: UpdateWearableProviderRequest;
9
+ }, WearableProviderSettings>;
10
+ export declare const useDeleteWearableProvider: () => OvokMutationState<WearableProvider, void>;
11
+ export declare const useAuthorizeWearableConnection: () => OvokMutationState<WearableProvider, WearableConnectionAuthorization>;
12
+ export declare const useDeleteWearableConnection: () => OvokMutationState<WearableProvider, void>;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ "use client";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.useDeleteWearableConnection = exports.useAuthorizeWearableConnection = exports.useDeleteWearableProvider = exports.useUpdateWearableProvider = exports.useCreateWearableProvider = exports.useWearableConnections = exports.useWearableProviders = void 0;
38
+ const React = __importStar(require("react"));
39
+ const api_hooks_1 = require("./api-hooks");
40
+ const wearable_invalidation_1 = require("./wearable-invalidation");
41
+ const index_1 = require("./index");
42
+ const useWearableProviders = () => {
43
+ const client = (0, index_1.useClient)();
44
+ const state = (0, api_hooks_1.useOvokClientRequest)((current, signal) => current.listWearableProviders({ signal }));
45
+ React.useEffect(() => (0, wearable_invalidation_1.subscribeToWearableChanges)(client, "providers", state.reload), [client, state.reload]);
46
+ return state;
47
+ };
48
+ exports.useWearableProviders = useWearableProviders;
49
+ const useWearableConnections = () => {
50
+ const client = (0, index_1.useClient)();
51
+ const state = (0, api_hooks_1.useOvokClientRequest)((current, signal) => current.listWearableConnections({ signal }));
52
+ React.useEffect(() => (0, wearable_invalidation_1.subscribeToWearableChanges)(client, "connections", state.reload), [client, state.reload]);
53
+ return state;
54
+ };
55
+ exports.useWearableConnections = useWearableConnections;
56
+ const useCreateWearableProvider = () => (0, api_hooks_1.useOvokMutation)(async (client, body) => {
57
+ const settings = await client.createWearableProvider(body);
58
+ (0, wearable_invalidation_1.notifyWearableChanges)(client, "providers");
59
+ return settings;
60
+ });
61
+ exports.useCreateWearableProvider = useCreateWearableProvider;
62
+ const useUpdateWearableProvider = () => (0, api_hooks_1.useOvokMutation)(async (client, { provider, body }) => {
63
+ const settings = await client.updateWearableProvider(provider, body);
64
+ (0, wearable_invalidation_1.notifyWearableChanges)(client, "providers");
65
+ return settings;
66
+ });
67
+ exports.useUpdateWearableProvider = useUpdateWearableProvider;
68
+ const useDeleteWearableProvider = () => (0, api_hooks_1.useOvokMutation)(async (client, provider) => {
69
+ await client.deleteWearableProvider(provider);
70
+ (0, wearable_invalidation_1.notifyWearableChanges)(client, "providers");
71
+ });
72
+ exports.useDeleteWearableProvider = useDeleteWearableProvider;
73
+ const useAuthorizeWearableConnection = () => (0, api_hooks_1.useOvokMutation)((client, provider) => client.authorizeWearableConnection(provider));
74
+ exports.useAuthorizeWearableConnection = useAuthorizeWearableConnection;
75
+ const useDeleteWearableConnection = () => (0, api_hooks_1.useOvokMutation)(async (client, provider) => {
76
+ await client.deleteWearableConnection(provider);
77
+ (0, wearable_invalidation_1.notifyWearableChanges)(client, "connections");
78
+ });
79
+ exports.useDeleteWearableConnection = useDeleteWearableConnection;
package/dist/index.d.ts CHANGED
@@ -958,6 +958,7 @@ export * from "./client/slim/paging";
958
958
  export * from "./client/experience/types";
959
959
  export * from "./client/patient/types";
960
960
  export * from "./client/patient-sharing";
961
+ export * from "./client/wearables";
961
962
  export { SignalsError, isSignalsError, mapSignalsError } from "./client/signals/errors";
962
963
  export * from "./client/storage";
963
964
  export * from "./client/questionnaire-response/methods";
package/dist/index.js CHANGED
@@ -77,6 +77,7 @@ __exportStar(require("./client/slim/paging"), exports);
77
77
  __exportStar(require("./client/experience/types"), exports);
78
78
  __exportStar(require("./client/patient/types"), exports);
79
79
  __exportStar(require("./client/patient-sharing"), exports);
80
+ __exportStar(require("./client/wearables"), exports);
80
81
  var errors_1 = require("./client/signals/errors");
81
82
  Object.defineProperty(exports, "SignalsError", { enumerable: true, get: function () { return errors_1.SignalsError; } });
82
83
  Object.defineProperty(exports, "isSignalsError", { enumerable: true, get: function () { return errors_1.isSignalsError; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ovok/core",
3
- "version": "0.4.44",
3
+ "version": "0.4.46",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",