@hipnation-truth/sdk 0.5.0 → 0.7.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/dist/index.d.mts +201 -1
- package/dist/index.d.ts +201 -1
- package/dist/index.js +294 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +286 -2
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +281 -1
- package/dist/react.d.ts +281 -1
- package/dist/react.js +546 -58
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +527 -45
- package/dist/react.mjs.map +1 -1
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -72,6 +72,8 @@ __export(src_exports, {
|
|
|
72
72
|
NOTIFICATION_EVENTS: () => NOTIFICATION_EVENTS,
|
|
73
73
|
NotesError: () => NotesError,
|
|
74
74
|
NotesResource: () => NotesResource,
|
|
75
|
+
NotificationsError: () => NotificationsError,
|
|
76
|
+
NotificationsResource: () => NotificationsResource,
|
|
75
77
|
PROVIDER_EVENTS: () => PROVIDER_EVENTS,
|
|
76
78
|
PatientDetailsError: () => PatientDetailsError,
|
|
77
79
|
PatientDetailsResource: () => PatientDetailsResource,
|
|
@@ -87,7 +89,12 @@ __export(src_exports, {
|
|
|
87
89
|
TranslationError: () => TranslationError,
|
|
88
90
|
TranslationResource: () => TranslationResource,
|
|
89
91
|
TruthClient: () => TruthClient,
|
|
90
|
-
generateUuidV7: () => generateUuidV7
|
|
92
|
+
generateUuidV7: () => generateUuidV7,
|
|
93
|
+
isWebPushSupported: () => isWebPushSupported,
|
|
94
|
+
onServiceWorkerMessage: () => onServiceWorkerMessage,
|
|
95
|
+
registerServiceWorker: () => registerServiceWorker,
|
|
96
|
+
subscribeToPush: () => subscribeToPush,
|
|
97
|
+
subscriptionToJSON: () => subscriptionToJSON
|
|
91
98
|
});
|
|
92
99
|
module.exports = __toCommonJS(src_exports);
|
|
93
100
|
|
|
@@ -627,6 +634,188 @@ var NotesResource = class {
|
|
|
627
634
|
}
|
|
628
635
|
};
|
|
629
636
|
|
|
637
|
+
// src/resources/notifications.ts
|
|
638
|
+
var NotificationsError = class extends Error {
|
|
639
|
+
constructor(operation, status, message) {
|
|
640
|
+
super(message != null ? message : `Notifications ${operation} failed (HTTP ${status})`);
|
|
641
|
+
this.name = "NotificationsError";
|
|
642
|
+
this.status = status;
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
var NotificationsResource = class {
|
|
646
|
+
constructor(apiBaseUrl, apiKey) {
|
|
647
|
+
this.baseUrl = apiBaseUrl;
|
|
648
|
+
this.apiKey = apiKey;
|
|
649
|
+
}
|
|
650
|
+
post(path, body) {
|
|
651
|
+
return __async(this, null, function* () {
|
|
652
|
+
const res = yield fetch(`${this.baseUrl}/api${path}`, {
|
|
653
|
+
method: "POST",
|
|
654
|
+
headers: {
|
|
655
|
+
"Content-Type": "application/json",
|
|
656
|
+
Accept: "application/json",
|
|
657
|
+
"X-API-Key": this.apiKey
|
|
658
|
+
},
|
|
659
|
+
body: JSON.stringify(body)
|
|
660
|
+
});
|
|
661
|
+
if (!res.ok) {
|
|
662
|
+
const text = yield res.text().catch(() => "");
|
|
663
|
+
throw new NotificationsError(path, res.status, text.slice(0, 200));
|
|
664
|
+
}
|
|
665
|
+
return yield res.json();
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
get(path, params) {
|
|
669
|
+
return __async(this, null, function* () {
|
|
670
|
+
const url = new URL(`${this.baseUrl}/api${path}`);
|
|
671
|
+
for (const [k, v] of Object.entries(params)) {
|
|
672
|
+
url.searchParams.set(k, v);
|
|
673
|
+
}
|
|
674
|
+
const res = yield fetch(url.toString(), {
|
|
675
|
+
method: "GET",
|
|
676
|
+
headers: {
|
|
677
|
+
Accept: "application/json",
|
|
678
|
+
"X-API-Key": this.apiKey
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
if (!res.ok) {
|
|
682
|
+
const text = yield res.text().catch(() => "");
|
|
683
|
+
throw new NotificationsError(path, res.status, text.slice(0, 200));
|
|
684
|
+
}
|
|
685
|
+
return yield res.json();
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
delete(path) {
|
|
689
|
+
return __async(this, null, function* () {
|
|
690
|
+
const res = yield fetch(`${this.baseUrl}/api${path}`, {
|
|
691
|
+
method: "DELETE",
|
|
692
|
+
headers: {
|
|
693
|
+
Accept: "application/json",
|
|
694
|
+
"X-API-Key": this.apiKey
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
if (!res.ok) {
|
|
698
|
+
const text = yield res.text().catch(() => "");
|
|
699
|
+
throw new NotificationsError(path, res.status, text.slice(0, 200));
|
|
700
|
+
}
|
|
701
|
+
return yield res.json();
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Register a device (or refresh its metadata) for push delivery.
|
|
706
|
+
* Safe to call repeatedly — the server dedupes by native token.
|
|
707
|
+
*/
|
|
708
|
+
registerDevice(input) {
|
|
709
|
+
return __async(this, null, function* () {
|
|
710
|
+
return this.post("/notifications/devices/register", input);
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
/** Revoke a device — on sign-out or when the OS reports an invalid token. */
|
|
714
|
+
unregisterDevice(input) {
|
|
715
|
+
return __async(this, null, function* () {
|
|
716
|
+
return this.post("/notifications/devices/unregister", input);
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Send a push notification to every active device belonging to
|
|
721
|
+
* `userId`. Honors the user's notificationPreferences (quiet hours,
|
|
722
|
+
* DND, channel off) before publishing.
|
|
723
|
+
*/
|
|
724
|
+
send(input) {
|
|
725
|
+
return __async(this, null, function* () {
|
|
726
|
+
return this.post("/notifications/send", input);
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
/** Read a user's notification preferences. Returns defaults when no row exists. */
|
|
730
|
+
getPreferences(userId) {
|
|
731
|
+
return __async(this, null, function* () {
|
|
732
|
+
return this.get("/notifications/preferences", { userId });
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
updatePreferences(input) {
|
|
736
|
+
return __async(this, null, function* () {
|
|
737
|
+
return this.post("/notifications/preferences", input);
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Schedule a future push notification. Convex's native scheduler
|
|
742
|
+
* fires the send at `scheduledAt` and runs the same delivery
|
|
743
|
+
* pipeline as `send()` (preferences, devices, history audit).
|
|
744
|
+
*
|
|
745
|
+
* Throws `NotificationsError` with status 400 if `scheduledAt` is
|
|
746
|
+
* not strictly in the future.
|
|
747
|
+
*/
|
|
748
|
+
schedule(input) {
|
|
749
|
+
return __async(this, null, function* () {
|
|
750
|
+
return this.post("/notifications/schedule", input);
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Cancel a pending scheduled notification. Returns `cancelled: false`
|
|
755
|
+
* (no error) if the job has already executed, was previously
|
|
756
|
+
* cancelled, or no longer exists — `reason` describes which case.
|
|
757
|
+
*/
|
|
758
|
+
cancelScheduled(jobId) {
|
|
759
|
+
return __async(this, null, function* () {
|
|
760
|
+
return this.delete(`/notifications/schedule/${encodeURIComponent(jobId)}`);
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* List scheduled notifications for a user — pending, executed,
|
|
765
|
+
* cancelled, or failed. Most-recent first. Default limit 100.
|
|
766
|
+
*/
|
|
767
|
+
listScheduled(userId, options) {
|
|
768
|
+
return __async(this, null, function* () {
|
|
769
|
+
const params = { userId };
|
|
770
|
+
if ((options == null ? void 0 : options.limit) !== void 0) {
|
|
771
|
+
params.limit = String(options.limit);
|
|
772
|
+
}
|
|
773
|
+
return this.get("/notifications/schedule", params);
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
getVapidKey() {
|
|
777
|
+
return __async(this, null, function* () {
|
|
778
|
+
try {
|
|
779
|
+
const result = yield this.get(
|
|
780
|
+
"/notifications/vapid-key",
|
|
781
|
+
{}
|
|
782
|
+
);
|
|
783
|
+
return result.vapidPublicKey;
|
|
784
|
+
} catch (e) {
|
|
785
|
+
return null;
|
|
786
|
+
}
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
onPushReceived(callback) {
|
|
790
|
+
if (typeof navigator === "undefined" || !("serviceWorker" in navigator)) {
|
|
791
|
+
return () => {
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
const handler = (event) => {
|
|
795
|
+
var _a;
|
|
796
|
+
if (((_a = event.data) == null ? void 0 : _a.type) === "TRUTH_PUSH_RECEIVED") {
|
|
797
|
+
callback(event.data.payload);
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
navigator.serviceWorker.addEventListener("message", handler);
|
|
801
|
+
return () => navigator.serviceWorker.removeEventListener("message", handler);
|
|
802
|
+
}
|
|
803
|
+
onPushTapped(callback) {
|
|
804
|
+
if (typeof navigator === "undefined" || !("serviceWorker" in navigator)) {
|
|
805
|
+
return () => {
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
const handler = (event) => {
|
|
809
|
+
var _a;
|
|
810
|
+
if (((_a = event.data) == null ? void 0 : _a.type) === "TRUTH_PUSH_TAPPED") {
|
|
811
|
+
callback(event.data.payload);
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
navigator.serviceWorker.addEventListener("message", handler);
|
|
815
|
+
return () => navigator.serviceWorker.removeEventListener("message", handler);
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
|
|
630
819
|
// src/resources/patient-details.ts
|
|
631
820
|
var PatientDetailsError = class extends Error {
|
|
632
821
|
constructor(operation, status, message) {
|
|
@@ -1192,6 +1381,65 @@ function sleep(ms) {
|
|
|
1192
1381
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1193
1382
|
}
|
|
1194
1383
|
|
|
1384
|
+
// src/web-push.ts
|
|
1385
|
+
function isWebPushSupported() {
|
|
1386
|
+
return typeof window !== "undefined" && "serviceWorker" in navigator && "PushManager" in window;
|
|
1387
|
+
}
|
|
1388
|
+
function registerServiceWorker(path = "/truth-sw.js") {
|
|
1389
|
+
return __async(this, null, function* () {
|
|
1390
|
+
return navigator.serviceWorker.register(path);
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
function subscribeToPush(registration, vapidPublicKey) {
|
|
1394
|
+
return __async(this, null, function* () {
|
|
1395
|
+
const existing = yield registration.pushManager.getSubscription();
|
|
1396
|
+
if (existing) {
|
|
1397
|
+
return existing;
|
|
1398
|
+
}
|
|
1399
|
+
return registration.pushManager.subscribe({
|
|
1400
|
+
userVisibleOnly: true,
|
|
1401
|
+
applicationServerKey: urlBase64ToUint8Array(
|
|
1402
|
+
vapidPublicKey
|
|
1403
|
+
)
|
|
1404
|
+
});
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
function subscriptionToJSON(sub) {
|
|
1408
|
+
var _a, _b, _c, _d;
|
|
1409
|
+
const json = sub.toJSON();
|
|
1410
|
+
return {
|
|
1411
|
+
endpoint: sub.endpoint,
|
|
1412
|
+
keys: {
|
|
1413
|
+
p256dh: (_b = (_a = json.keys) == null ? void 0 : _a.p256dh) != null ? _b : "",
|
|
1414
|
+
auth: (_d = (_c = json.keys) == null ? void 0 : _c.auth) != null ? _d : ""
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
function urlBase64ToUint8Array(base64String) {
|
|
1419
|
+
const padding = "=".repeat((4 - base64String.length % 4) % 4);
|
|
1420
|
+
const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
|
|
1421
|
+
const rawData = atob(base64);
|
|
1422
|
+
const outputArray = new Uint8Array(rawData.length);
|
|
1423
|
+
for (let i = 0; i < rawData.length; ++i) {
|
|
1424
|
+
outputArray[i] = rawData.charCodeAt(i);
|
|
1425
|
+
}
|
|
1426
|
+
return outputArray;
|
|
1427
|
+
}
|
|
1428
|
+
function onServiceWorkerMessage(type, callback) {
|
|
1429
|
+
if (typeof navigator === "undefined" || !("serviceWorker" in navigator)) {
|
|
1430
|
+
return () => {
|
|
1431
|
+
};
|
|
1432
|
+
}
|
|
1433
|
+
const handler = (event) => {
|
|
1434
|
+
var _a;
|
|
1435
|
+
if (((_a = event.data) == null ? void 0 : _a.type) === type) {
|
|
1436
|
+
callback(event.data.payload);
|
|
1437
|
+
}
|
|
1438
|
+
};
|
|
1439
|
+
navigator.serviceWorker.addEventListener("message", handler);
|
|
1440
|
+
return () => navigator.serviceWorker.removeEventListener("message", handler);
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1195
1443
|
// src/client.ts
|
|
1196
1444
|
var CONVEX_URLS = {
|
|
1197
1445
|
local: "https://courteous-duck-623.convex.cloud",
|
|
@@ -1203,7 +1451,9 @@ var CONVEX_URLS = {
|
|
|
1203
1451
|
};
|
|
1204
1452
|
var TruthClient = class {
|
|
1205
1453
|
constructor(config) {
|
|
1206
|
-
|
|
1454
|
+
this._vapidPublicKey = null;
|
|
1455
|
+
this._webPushReady = null;
|
|
1456
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1207
1457
|
const convexUrl = (_b = (_a = config.convexUrl) != null ? _a : CONVEX_URLS[config.environment]) != null ? _b : CONVEX_URLS.local;
|
|
1208
1458
|
this.convex = new import_browser.ConvexHttpClient(convexUrl);
|
|
1209
1459
|
this.tracker = new Tracker({
|
|
@@ -1232,6 +1482,40 @@ var TruthClient = class {
|
|
|
1232
1482
|
);
|
|
1233
1483
|
this.notes = new NotesResource(apiUrl, config.apiKey);
|
|
1234
1484
|
this.physicians = new PhysiciansResource(this.convex);
|
|
1485
|
+
this.notifications = new NotificationsResource(apiUrl, config.apiKey);
|
|
1486
|
+
this._serviceWorkerPath = (_h = config.serviceWorkerPath) != null ? _h : "/truth-sw.js";
|
|
1487
|
+
if (typeof window !== "undefined" && isWebPushSupported() && config.autoInitServiceWorker !== false) {
|
|
1488
|
+
this._webPushReady = this.initWebPush();
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
get vapidPublicKey() {
|
|
1492
|
+
return this._vapidPublicKey;
|
|
1493
|
+
}
|
|
1494
|
+
get webPushReady() {
|
|
1495
|
+
return this._webPushReady;
|
|
1496
|
+
}
|
|
1497
|
+
initWebPush() {
|
|
1498
|
+
return __async(this, null, function* () {
|
|
1499
|
+
try {
|
|
1500
|
+
const key = yield this.notifications.getVapidKey();
|
|
1501
|
+
if (!key) {
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1504
|
+
this._vapidPublicKey = key;
|
|
1505
|
+
const registration = yield registerServiceWorker(this._serviceWorkerPath);
|
|
1506
|
+
yield navigator.serviceWorker.ready;
|
|
1507
|
+
const subscription = yield subscribeToPush(registration, key);
|
|
1508
|
+
const subJSON = subscriptionToJSON(subscription);
|
|
1509
|
+
yield this.notifications.registerDevice({
|
|
1510
|
+
userId: "__pending__",
|
|
1511
|
+
platform: "web",
|
|
1512
|
+
webPushSubscription: subJSON,
|
|
1513
|
+
locale: navigator.language,
|
|
1514
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
1515
|
+
});
|
|
1516
|
+
} catch (e) {
|
|
1517
|
+
}
|
|
1518
|
+
});
|
|
1235
1519
|
}
|
|
1236
1520
|
/**
|
|
1237
1521
|
* The resolved Truth API base URL for this environment.
|
|
@@ -1389,6 +1673,8 @@ var ENVIRONMENTS = {
|
|
|
1389
1673
|
NOTIFICATION_EVENTS,
|
|
1390
1674
|
NotesError,
|
|
1391
1675
|
NotesResource,
|
|
1676
|
+
NotificationsError,
|
|
1677
|
+
NotificationsResource,
|
|
1392
1678
|
PROVIDER_EVENTS,
|
|
1393
1679
|
PatientDetailsError,
|
|
1394
1680
|
PatientDetailsResource,
|
|
@@ -1404,6 +1690,11 @@ var ENVIRONMENTS = {
|
|
|
1404
1690
|
TranslationError,
|
|
1405
1691
|
TranslationResource,
|
|
1406
1692
|
TruthClient,
|
|
1407
|
-
generateUuidV7
|
|
1693
|
+
generateUuidV7,
|
|
1694
|
+
isWebPushSupported,
|
|
1695
|
+
onServiceWorkerMessage,
|
|
1696
|
+
registerServiceWorker,
|
|
1697
|
+
subscribeToPush,
|
|
1698
|
+
subscriptionToJSON
|
|
1408
1699
|
});
|
|
1409
1700
|
//# sourceMappingURL=index.js.map
|