@hipnation-truth/sdk 0.6.0 → 0.7.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/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.js +539 -62
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +511 -49
- package/dist/react.mjs.map +1 -1
- package/package.json +6 -3
- package/dist/react.d.mts +0 -655
- package/dist/react.d.ts +0 -655
package/dist/react.mjs
CHANGED
|
@@ -21,79 +21,136 @@ var __async = (__this, __arguments, generator) => {
|
|
|
21
21
|
});
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
// src/react/
|
|
24
|
+
// src/react/conversations.ts
|
|
25
25
|
import { useQuery } from "convex/react";
|
|
26
|
-
import { useEffect } from "react";
|
|
27
26
|
import { makeFunctionReference } from "convex/server";
|
|
28
|
-
var
|
|
29
|
-
var
|
|
30
|
-
var
|
|
31
|
-
var
|
|
32
|
-
var
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
var conversationsListForUserRef = makeFunctionReference("conversations:listForUser");
|
|
28
|
+
var conversationsGetUnreadTotalForUserRef = makeFunctionReference("conversations:getUnreadTotalForUser");
|
|
29
|
+
var conversationsGetByPhonePairRef = makeFunctionReference("conversations:getByPhonePair");
|
|
30
|
+
var conversationMessagesGetByConversationIdRef = makeFunctionReference("conversationMessages:getByConversationId");
|
|
31
|
+
var SKIP = "skip";
|
|
32
|
+
function toResult(value, skipped) {
|
|
33
|
+
if (skipped) {
|
|
34
|
+
return { data: void 0, loading: false, error: void 0 };
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
data: value,
|
|
38
|
+
loading: value === void 0,
|
|
39
|
+
error: void 0
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function useConversations(filters) {
|
|
43
|
+
const skipped = !filters.userId;
|
|
44
|
+
const result = useQuery(
|
|
45
|
+
conversationsListForUserRef,
|
|
46
|
+
skipped ? SKIP : {
|
|
47
|
+
userId: filters.userId,
|
|
48
|
+
limit: filters.limit
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
return toResult(result, skipped);
|
|
52
|
+
}
|
|
53
|
+
function useConversationByPhonePair(phonePair) {
|
|
54
|
+
const skipped = !phonePair;
|
|
55
|
+
const result = useQuery(
|
|
56
|
+
conversationsGetByPhonePairRef,
|
|
57
|
+
skipped ? SKIP : { phonePair }
|
|
58
|
+
);
|
|
59
|
+
return toResult(result, skipped);
|
|
60
|
+
}
|
|
61
|
+
function useMessages(conversationId, options) {
|
|
62
|
+
const skipped = !conversationId;
|
|
63
|
+
const result = useQuery(
|
|
64
|
+
conversationMessagesGetByConversationIdRef,
|
|
65
|
+
skipped ? SKIP : {
|
|
66
|
+
conversationId,
|
|
67
|
+
limit: options == null ? void 0 : options.limit
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
return toResult(result, skipped);
|
|
71
|
+
}
|
|
72
|
+
function useUnreadCount(userId) {
|
|
73
|
+
const skipped = !userId;
|
|
74
|
+
const result = useQuery(
|
|
75
|
+
conversationsGetUnreadTotalForUserRef,
|
|
76
|
+
skipped ? SKIP : { userId }
|
|
77
|
+
);
|
|
78
|
+
return toResult(result, skipped);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/react/hooks.ts
|
|
82
|
+
import { useQuery as useQuery2 } from "convex/react";
|
|
83
|
+
import { useEffect } from "react";
|
|
84
|
+
import { makeFunctionReference as makeFunctionReference2 } from "convex/server";
|
|
85
|
+
var patientsListRef = makeFunctionReference2("patients:list");
|
|
86
|
+
var patientsGetRef = makeFunctionReference2("patients:get");
|
|
87
|
+
var patientsByElationIdRef = makeFunctionReference2("patients:getByElationId");
|
|
88
|
+
var patientsByHintIdRef = makeFunctionReference2("patients:getByHintId");
|
|
89
|
+
var appointmentsListRef = makeFunctionReference2("appointments:list");
|
|
90
|
+
var appointmentsGetRef = makeFunctionReference2("appointments:get");
|
|
91
|
+
var appointmentsByElationIdRef = makeFunctionReference2("appointments:getByElationId");
|
|
35
92
|
function usePatients(options) {
|
|
36
|
-
return
|
|
93
|
+
return useQuery2(patientsListRef, options != null ? options : {});
|
|
37
94
|
}
|
|
38
95
|
function usePatient(id) {
|
|
39
|
-
return
|
|
96
|
+
return useQuery2(patientsGetRef, { id });
|
|
40
97
|
}
|
|
41
98
|
function usePatientByElationId(elationId) {
|
|
42
|
-
return
|
|
99
|
+
return useQuery2(patientsByElationIdRef, {
|
|
43
100
|
elationId
|
|
44
101
|
});
|
|
45
102
|
}
|
|
46
103
|
function usePatientByHintId(hintId) {
|
|
47
|
-
return
|
|
104
|
+
return useQuery2(patientsByHintIdRef, {
|
|
48
105
|
hintId
|
|
49
106
|
});
|
|
50
107
|
}
|
|
51
108
|
function useAppointments(options) {
|
|
52
|
-
return
|
|
109
|
+
return useQuery2(
|
|
53
110
|
appointmentsListRef,
|
|
54
111
|
options != null ? options : {}
|
|
55
112
|
);
|
|
56
113
|
}
|
|
57
114
|
function useAppointment(id) {
|
|
58
|
-
return
|
|
115
|
+
return useQuery2(appointmentsGetRef, { id });
|
|
59
116
|
}
|
|
60
117
|
function useAppointmentByElationId(elationId) {
|
|
61
|
-
return
|
|
118
|
+
return useQuery2(appointmentsByElationIdRef, {
|
|
62
119
|
elationId
|
|
63
120
|
});
|
|
64
121
|
}
|
|
65
|
-
var physiciansGetByElationIdsRef =
|
|
66
|
-
var physiciansGetByElationIdRef =
|
|
122
|
+
var physiciansGetByElationIdsRef = makeFunctionReference2("physicians:getByElationIds");
|
|
123
|
+
var physiciansGetByElationIdRef = makeFunctionReference2("physicians:getByElationId");
|
|
67
124
|
function usePhysiciansByElationIds(ids) {
|
|
68
|
-
return
|
|
125
|
+
return useQuery2(
|
|
69
126
|
physiciansGetByElationIdsRef,
|
|
70
127
|
ids && ids.length > 0 ? { ids } : "skip"
|
|
71
128
|
);
|
|
72
129
|
}
|
|
73
130
|
function usePhysicianByElationId(id) {
|
|
74
|
-
return
|
|
131
|
+
return useQuery2(
|
|
75
132
|
physiciansGetByElationIdRef,
|
|
76
133
|
id !== void 0 ? { id } : "skip"
|
|
77
134
|
);
|
|
78
135
|
}
|
|
79
|
-
var medicationsByPatientRef =
|
|
80
|
-
var problemsByPatientRef =
|
|
81
|
-
var allergiesByPatientRef =
|
|
82
|
-
var appointmentsByPatientRef =
|
|
136
|
+
var medicationsByPatientRef = makeFunctionReference2("medicalRecords:getMedicationsByElationPatient");
|
|
137
|
+
var problemsByPatientRef = makeFunctionReference2("medicalRecords:getProblemsByElationPatient");
|
|
138
|
+
var allergiesByPatientRef = makeFunctionReference2("medicalRecords:getAllergiesByElationPatient");
|
|
139
|
+
var appointmentsByPatientRef = makeFunctionReference2("medicalRecords:getAppointmentsByElationPatient");
|
|
83
140
|
function usePatientMedical(elationId, options) {
|
|
84
|
-
const medications =
|
|
141
|
+
const medications = useQuery2(
|
|
85
142
|
medicationsByPatientRef,
|
|
86
143
|
elationId !== void 0 ? { elationPatientId: elationId } : "skip"
|
|
87
144
|
);
|
|
88
|
-
const problems =
|
|
145
|
+
const problems = useQuery2(
|
|
89
146
|
problemsByPatientRef,
|
|
90
147
|
elationId !== void 0 ? { elationPatientId: elationId } : "skip"
|
|
91
148
|
);
|
|
92
|
-
const allergies =
|
|
149
|
+
const allergies = useQuery2(
|
|
93
150
|
allergiesByPatientRef,
|
|
94
151
|
elationId !== void 0 ? { elationPatientId: elationId } : "skip"
|
|
95
152
|
);
|
|
96
|
-
const appointments =
|
|
153
|
+
const appointments = useQuery2(
|
|
97
154
|
appointmentsByPatientRef,
|
|
98
155
|
elationId !== void 0 ? { elationPatientId: elationId } : "skip"
|
|
99
156
|
);
|
|
@@ -121,26 +178,32 @@ function usePatientMedical(elationId, options) {
|
|
|
121
178
|
}, [elationId, options == null ? void 0 : options.apiBaseUrl, options == null ? void 0 : options.apiKey, options == null ? void 0 : options.skipRefresh]);
|
|
122
179
|
return { medications, problems, allergies, appointments };
|
|
123
180
|
}
|
|
124
|
-
var elationPatientByIdRef =
|
|
125
|
-
var hintPatientByIdRef =
|
|
126
|
-
var pharmacyByNcpdpRef =
|
|
127
|
-
var patientPhotoByIdRef =
|
|
181
|
+
var elationPatientByIdRef = makeFunctionReference2("elationPatients:getByElationId");
|
|
182
|
+
var hintPatientByIdRef = makeFunctionReference2("hintPatients:getByHintId");
|
|
183
|
+
var pharmacyByNcpdpRef = makeFunctionReference2("elationPharmacies:getByNcpdpId");
|
|
184
|
+
var patientPhotoByIdRef = makeFunctionReference2("elationPatientPhotos:getByElationPatientId");
|
|
128
185
|
function usePatientBasic(input, options) {
|
|
129
186
|
var _a, _b;
|
|
130
|
-
const elationRow =
|
|
187
|
+
const elationRow = useQuery2(
|
|
131
188
|
elationPatientByIdRef,
|
|
132
189
|
input.elationId !== void 0 ? { elationId: input.elationId } : "skip"
|
|
133
190
|
);
|
|
134
|
-
const hintRow =
|
|
191
|
+
const hintRow = useQuery2(
|
|
135
192
|
hintPatientByIdRef,
|
|
136
193
|
input.hintId !== void 0 ? { hintId: input.hintId } : "skip"
|
|
137
194
|
);
|
|
138
195
|
useEffect(() => {
|
|
139
|
-
if (options == null ? void 0 : options.skipRefresh)
|
|
140
|
-
|
|
196
|
+
if (options == null ? void 0 : options.skipRefresh) {
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (!input.hintId && input.elationId === void 0) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
141
202
|
const apiBaseUrl = options == null ? void 0 : options.apiBaseUrl;
|
|
142
203
|
const apiKey = options == null ? void 0 : options.apiKey;
|
|
143
|
-
if (!apiBaseUrl || !apiKey)
|
|
204
|
+
if (!apiBaseUrl || !apiKey) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
144
207
|
const controller = new AbortController();
|
|
145
208
|
void fetch(`${apiBaseUrl}/api/patients/basic/refresh`, {
|
|
146
209
|
method: "POST",
|
|
@@ -176,22 +239,28 @@ function usePatientBasic(input, options) {
|
|
|
176
239
|
};
|
|
177
240
|
}
|
|
178
241
|
function usePharmacyByNcpdpId(ncpdpId) {
|
|
179
|
-
return
|
|
242
|
+
return useQuery2(
|
|
180
243
|
pharmacyByNcpdpRef,
|
|
181
244
|
ncpdpId ? { ncpdpId } : "skip"
|
|
182
245
|
);
|
|
183
246
|
}
|
|
184
247
|
function usePatientPhoto(elationId, options) {
|
|
185
|
-
const photo =
|
|
248
|
+
const photo = useQuery2(
|
|
186
249
|
patientPhotoByIdRef,
|
|
187
250
|
elationId !== void 0 ? { elationPatientId: elationId } : "skip"
|
|
188
251
|
);
|
|
189
252
|
useEffect(() => {
|
|
190
|
-
if (options == null ? void 0 : options.skipRefresh)
|
|
191
|
-
|
|
253
|
+
if (options == null ? void 0 : options.skipRefresh) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (elationId === void 0) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
192
259
|
const apiBaseUrl = options == null ? void 0 : options.apiBaseUrl;
|
|
193
260
|
const apiKey = options == null ? void 0 : options.apiKey;
|
|
194
|
-
if (!apiBaseUrl || !apiKey)
|
|
261
|
+
if (!apiBaseUrl || !apiKey) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
195
264
|
const controller = new AbortController();
|
|
196
265
|
void fetch(`${apiBaseUrl}/api/patients/photo/refresh`, {
|
|
197
266
|
method: "POST",
|
|
@@ -207,11 +276,11 @@ function usePatientPhoto(elationId, options) {
|
|
|
207
276
|
}, [elationId, options == null ? void 0 : options.apiBaseUrl, options == null ? void 0 : options.apiKey, options == null ? void 0 : options.skipRefresh]);
|
|
208
277
|
return photo;
|
|
209
278
|
}
|
|
210
|
-
var messagesByPhonesRef =
|
|
211
|
-
var messagesByConversationIdRef =
|
|
279
|
+
var messagesByPhonesRef = makeFunctionReference2("conversationMessages:getByPhones");
|
|
280
|
+
var messagesByConversationIdRef = makeFunctionReference2("conversationMessages:getByConversationId");
|
|
212
281
|
function useConversationMessages(input, options) {
|
|
213
282
|
const hasPair = !!input.phoneA && !!input.phoneB;
|
|
214
|
-
const byPair =
|
|
283
|
+
const byPair = useQuery2(
|
|
215
284
|
messagesByPhonesRef,
|
|
216
285
|
hasPair ? {
|
|
217
286
|
phoneA: input.phoneA,
|
|
@@ -219,13 +288,394 @@ function useConversationMessages(input, options) {
|
|
|
219
288
|
limit: options == null ? void 0 : options.limit
|
|
220
289
|
} : "skip"
|
|
221
290
|
);
|
|
222
|
-
const byConvo =
|
|
291
|
+
const byConvo = useQuery2(
|
|
223
292
|
messagesByConversationIdRef,
|
|
224
293
|
!hasPair && input.conversationId ? { conversationId: input.conversationId, limit: options == null ? void 0 : options.limit } : "skip"
|
|
225
294
|
);
|
|
226
295
|
return hasPair ? byPair : byConvo;
|
|
227
296
|
}
|
|
228
297
|
|
|
298
|
+
// src/react/notifications.ts
|
|
299
|
+
import { useCallback, useEffect as useEffect2, useRef, useState } from "react";
|
|
300
|
+
|
|
301
|
+
// src/web-push.ts
|
|
302
|
+
function isWebPushSupported() {
|
|
303
|
+
return typeof window !== "undefined" && "serviceWorker" in navigator && "PushManager" in window;
|
|
304
|
+
}
|
|
305
|
+
function registerServiceWorker(path = "/truth-sw.js") {
|
|
306
|
+
return __async(this, null, function* () {
|
|
307
|
+
return navigator.serviceWorker.register(path);
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
function subscribeToPush(registration, vapidPublicKey) {
|
|
311
|
+
return __async(this, null, function* () {
|
|
312
|
+
const existing = yield registration.pushManager.getSubscription();
|
|
313
|
+
if (existing) {
|
|
314
|
+
return existing;
|
|
315
|
+
}
|
|
316
|
+
return registration.pushManager.subscribe({
|
|
317
|
+
userVisibleOnly: true,
|
|
318
|
+
applicationServerKey: urlBase64ToUint8Array(
|
|
319
|
+
vapidPublicKey
|
|
320
|
+
)
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
function subscriptionToJSON(sub) {
|
|
325
|
+
var _a, _b, _c, _d;
|
|
326
|
+
const json = sub.toJSON();
|
|
327
|
+
return {
|
|
328
|
+
endpoint: sub.endpoint,
|
|
329
|
+
keys: {
|
|
330
|
+
p256dh: (_b = (_a = json.keys) == null ? void 0 : _a.p256dh) != null ? _b : "",
|
|
331
|
+
auth: (_d = (_c = json.keys) == null ? void 0 : _c.auth) != null ? _d : ""
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function urlBase64ToUint8Array(base64String) {
|
|
336
|
+
const padding = "=".repeat((4 - base64String.length % 4) % 4);
|
|
337
|
+
const base64 = (base64String + padding).replace(/-/g, "+").replace(/_/g, "/");
|
|
338
|
+
const rawData = atob(base64);
|
|
339
|
+
const outputArray = new Uint8Array(rawData.length);
|
|
340
|
+
for (let i = 0; i < rawData.length; ++i) {
|
|
341
|
+
outputArray[i] = rawData.charCodeAt(i);
|
|
342
|
+
}
|
|
343
|
+
return outputArray;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// src/react/notifications.ts
|
|
347
|
+
function loadExpo() {
|
|
348
|
+
return __async(this, null, function* () {
|
|
349
|
+
try {
|
|
350
|
+
return yield import(
|
|
351
|
+
/* @vite-ignore */
|
|
352
|
+
/* webpackIgnore: true */
|
|
353
|
+
"expo-notifications"
|
|
354
|
+
);
|
|
355
|
+
} catch (e) {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
function useNotifications(options) {
|
|
361
|
+
var _a;
|
|
362
|
+
const [permissionStatus, setPermissionStatus] = useState("unknown");
|
|
363
|
+
const [devicePushToken, setDevicePushToken] = useState(null);
|
|
364
|
+
const expoRef = useRef(null);
|
|
365
|
+
const isWebRef = useRef(false);
|
|
366
|
+
const vapidKeyRef = useRef((_a = options.vapidPublicKey) != null ? _a : null);
|
|
367
|
+
useEffect2(() => {
|
|
368
|
+
let mounted = true;
|
|
369
|
+
void (() => __async(null, null, function* () {
|
|
370
|
+
var _a2;
|
|
371
|
+
const expo = yield loadExpo();
|
|
372
|
+
if (!mounted) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
expoRef.current = expo;
|
|
376
|
+
if (expo) {
|
|
377
|
+
try {
|
|
378
|
+
const perm = yield expo.getPermissionsAsync();
|
|
379
|
+
if (!mounted) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
setPermissionStatus(mapStatus(perm == null ? void 0 : perm.status));
|
|
383
|
+
} catch (e) {
|
|
384
|
+
setPermissionStatus("unknown");
|
|
385
|
+
}
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
if (isWebPushSupported()) {
|
|
389
|
+
isWebRef.current = true;
|
|
390
|
+
if (!vapidKeyRef.current) {
|
|
391
|
+
try {
|
|
392
|
+
const res = yield fetch(
|
|
393
|
+
`${options.apiBaseUrl}/api/notifications/vapid-key`,
|
|
394
|
+
{
|
|
395
|
+
headers: {
|
|
396
|
+
Accept: "application/json",
|
|
397
|
+
"X-API-Key": options.apiKey
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
);
|
|
401
|
+
if (res.ok) {
|
|
402
|
+
const data = yield res.json();
|
|
403
|
+
vapidKeyRef.current = (_a2 = data.vapidPublicKey) != null ? _a2 : null;
|
|
404
|
+
}
|
|
405
|
+
} catch (e) {
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
if (!mounted) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
const webPerm = typeof Notification !== "undefined" ? Notification.permission : "default";
|
|
412
|
+
setPermissionStatus(
|
|
413
|
+
webPerm === "granted" ? "granted" : webPerm === "denied" ? "denied" : "undetermined"
|
|
414
|
+
);
|
|
415
|
+
} else {
|
|
416
|
+
setPermissionStatus("unknown");
|
|
417
|
+
}
|
|
418
|
+
}))();
|
|
419
|
+
return () => {
|
|
420
|
+
mounted = false;
|
|
421
|
+
};
|
|
422
|
+
}, [options.apiBaseUrl, options.apiKey]);
|
|
423
|
+
const register = useCallback(() => __async(null, null, function* () {
|
|
424
|
+
var _a2, _b;
|
|
425
|
+
if (!options.userId) {
|
|
426
|
+
return { ok: false, reason: "missing_userId" };
|
|
427
|
+
}
|
|
428
|
+
if (isWebRef.current) {
|
|
429
|
+
const vapidKey = vapidKeyRef.current;
|
|
430
|
+
if (!vapidKey) {
|
|
431
|
+
return { ok: false, reason: "no_vapid_key" };
|
|
432
|
+
}
|
|
433
|
+
const webPerm = yield Notification.requestPermission();
|
|
434
|
+
setPermissionStatus(
|
|
435
|
+
webPerm === "granted" ? "granted" : webPerm === "denied" ? "denied" : "undetermined"
|
|
436
|
+
);
|
|
437
|
+
if (webPerm !== "granted") {
|
|
438
|
+
return { ok: false, reason: "permission_denied" };
|
|
439
|
+
}
|
|
440
|
+
try {
|
|
441
|
+
const swPath = (_a2 = options.serviceWorkerPath) != null ? _a2 : "/truth-sw.js";
|
|
442
|
+
const registration = yield registerServiceWorker(swPath);
|
|
443
|
+
yield navigator.serviceWorker.ready;
|
|
444
|
+
const subscription = yield subscribeToPush(registration, vapidKey);
|
|
445
|
+
const subJSON = subscriptionToJSON(subscription);
|
|
446
|
+
setDevicePushToken(subscription.endpoint);
|
|
447
|
+
const res2 = yield fetch(
|
|
448
|
+
`${options.apiBaseUrl}/api/notifications/devices/register`,
|
|
449
|
+
{
|
|
450
|
+
method: "POST",
|
|
451
|
+
headers: {
|
|
452
|
+
"Content-Type": "application/json",
|
|
453
|
+
"X-API-Key": options.apiKey
|
|
454
|
+
},
|
|
455
|
+
body: JSON.stringify({
|
|
456
|
+
userId: options.userId,
|
|
457
|
+
platform: "web",
|
|
458
|
+
webPushSubscription: subJSON,
|
|
459
|
+
appVersion: options.appVersion,
|
|
460
|
+
locale: navigator.language,
|
|
461
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
462
|
+
})
|
|
463
|
+
}
|
|
464
|
+
);
|
|
465
|
+
if (!res2.ok) {
|
|
466
|
+
const text = yield res2.text().catch(() => "");
|
|
467
|
+
return {
|
|
468
|
+
ok: false,
|
|
469
|
+
reason: `register_failed_${res2.status}: ${text.slice(0, 120)}`
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
return { ok: true };
|
|
473
|
+
} catch (err) {
|
|
474
|
+
return {
|
|
475
|
+
ok: false,
|
|
476
|
+
reason: `web_push_error: ${err instanceof Error ? err.message : String(err)}`
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
const expo = (_b = expoRef.current) != null ? _b : yield loadExpo();
|
|
481
|
+
expoRef.current = expo;
|
|
482
|
+
if (!expo) {
|
|
483
|
+
return { ok: false, reason: "expo_notifications_missing" };
|
|
484
|
+
}
|
|
485
|
+
let perm = yield expo.getPermissionsAsync();
|
|
486
|
+
if ((perm == null ? void 0 : perm.status) !== "granted") {
|
|
487
|
+
perm = yield expo.requestPermissionsAsync();
|
|
488
|
+
}
|
|
489
|
+
setPermissionStatus(mapStatus(perm == null ? void 0 : perm.status));
|
|
490
|
+
if ((perm == null ? void 0 : perm.status) !== "granted") {
|
|
491
|
+
return { ok: false, reason: "permission_denied" };
|
|
492
|
+
}
|
|
493
|
+
const tokenResp = yield expo.getDevicePushTokenAsync();
|
|
494
|
+
const nativeToken = tokenResp == null ? void 0 : tokenResp.data;
|
|
495
|
+
const platform = detectPlatform(tokenResp == null ? void 0 : tokenResp.type);
|
|
496
|
+
if (!nativeToken || platform !== "ios" && platform !== "android") {
|
|
497
|
+
return { ok: false, reason: "no_native_token" };
|
|
498
|
+
}
|
|
499
|
+
setDevicePushToken(nativeToken);
|
|
500
|
+
const res = yield fetch(
|
|
501
|
+
`${options.apiBaseUrl}/api/notifications/devices/register`,
|
|
502
|
+
{
|
|
503
|
+
method: "POST",
|
|
504
|
+
headers: {
|
|
505
|
+
"Content-Type": "application/json",
|
|
506
|
+
"X-API-Key": options.apiKey
|
|
507
|
+
},
|
|
508
|
+
body: JSON.stringify({
|
|
509
|
+
userId: options.userId,
|
|
510
|
+
platform,
|
|
511
|
+
nativeToken,
|
|
512
|
+
appVersion: options.appVersion,
|
|
513
|
+
locale: typeof navigator !== "undefined" ? navigator.language : void 0,
|
|
514
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
515
|
+
})
|
|
516
|
+
}
|
|
517
|
+
);
|
|
518
|
+
if (!res.ok) {
|
|
519
|
+
const text = yield res.text().catch(() => "");
|
|
520
|
+
return {
|
|
521
|
+
ok: false,
|
|
522
|
+
reason: `register_failed_${res.status}: ${text.slice(0, 120)}`
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
return { ok: true };
|
|
526
|
+
}), [
|
|
527
|
+
options.apiBaseUrl,
|
|
528
|
+
options.apiKey,
|
|
529
|
+
options.userId,
|
|
530
|
+
options.appVersion,
|
|
531
|
+
options.serviceWorkerPath
|
|
532
|
+
]);
|
|
533
|
+
const unregister = useCallback(() => __async(null, null, function* () {
|
|
534
|
+
if (!devicePushToken) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
yield fetch(`${options.apiBaseUrl}/api/notifications/devices/unregister`, {
|
|
538
|
+
method: "POST",
|
|
539
|
+
headers: {
|
|
540
|
+
"Content-Type": "application/json",
|
|
541
|
+
"X-API-Key": options.apiKey
|
|
542
|
+
},
|
|
543
|
+
body: JSON.stringify({ nativeToken: devicePushToken })
|
|
544
|
+
}).catch(() => {
|
|
545
|
+
});
|
|
546
|
+
setDevicePushToken(null);
|
|
547
|
+
}), [options.apiBaseUrl, options.apiKey, devicePushToken]);
|
|
548
|
+
const addReceivedListener = useCallback(
|
|
549
|
+
(listener) => {
|
|
550
|
+
if (isWebRef.current) {
|
|
551
|
+
if (typeof navigator === "undefined" || !("serviceWorker" in navigator)) {
|
|
552
|
+
return () => {
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
const handler = (event) => {
|
|
556
|
+
var _a2;
|
|
557
|
+
if (((_a2 = event.data) == null ? void 0 : _a2.type) === "TRUTH_PUSH_RECEIVED") {
|
|
558
|
+
listener(event.data.payload);
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
navigator.serviceWorker.addEventListener("message", handler);
|
|
562
|
+
return () => navigator.serviceWorker.removeEventListener("message", handler);
|
|
563
|
+
}
|
|
564
|
+
const expo = expoRef.current;
|
|
565
|
+
if (!(expo == null ? void 0 : expo.addNotificationReceivedListener)) {
|
|
566
|
+
return () => {
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
const sub = expo.addNotificationReceivedListener(listener);
|
|
570
|
+
return () => {
|
|
571
|
+
var _a2;
|
|
572
|
+
return (_a2 = sub.remove) == null ? void 0 : _a2.call(sub);
|
|
573
|
+
};
|
|
574
|
+
},
|
|
575
|
+
[]
|
|
576
|
+
);
|
|
577
|
+
const addResponseListener = useCallback(
|
|
578
|
+
(listener) => {
|
|
579
|
+
if (isWebRef.current) {
|
|
580
|
+
if (typeof navigator === "undefined" || !("serviceWorker" in navigator)) {
|
|
581
|
+
return () => {
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
const handler = (event) => {
|
|
585
|
+
var _a2;
|
|
586
|
+
if (((_a2 = event.data) == null ? void 0 : _a2.type) === "TRUTH_PUSH_TAPPED") {
|
|
587
|
+
listener(event.data.payload);
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
navigator.serviceWorker.addEventListener("message", handler);
|
|
591
|
+
return () => navigator.serviceWorker.removeEventListener("message", handler);
|
|
592
|
+
}
|
|
593
|
+
const expo = expoRef.current;
|
|
594
|
+
if (!(expo == null ? void 0 : expo.addNotificationResponseReceivedListener)) {
|
|
595
|
+
return () => {
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
const sub = expo.addNotificationResponseReceivedListener(listener);
|
|
599
|
+
return () => {
|
|
600
|
+
var _a2;
|
|
601
|
+
return (_a2 = sub.remove) == null ? void 0 : _a2.call(sub);
|
|
602
|
+
};
|
|
603
|
+
},
|
|
604
|
+
[]
|
|
605
|
+
);
|
|
606
|
+
const getBadgeCount = useCallback(() => __async(null, null, function* () {
|
|
607
|
+
var _a2;
|
|
608
|
+
const expo = expoRef.current;
|
|
609
|
+
if (!(expo == null ? void 0 : expo.getBadgeCountAsync)) {
|
|
610
|
+
return 0;
|
|
611
|
+
}
|
|
612
|
+
return (_a2 = yield expo.getBadgeCountAsync()) != null ? _a2 : 0;
|
|
613
|
+
}), []);
|
|
614
|
+
const setBadgeCount = useCallback((count) => __async(null, null, function* () {
|
|
615
|
+
const expo = expoRef.current;
|
|
616
|
+
if (!(expo == null ? void 0 : expo.setBadgeCountAsync)) {
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
yield expo.setBadgeCountAsync(count);
|
|
620
|
+
}), []);
|
|
621
|
+
const autoRegister = options.autoRegister !== false;
|
|
622
|
+
useEffect2(() => {
|
|
623
|
+
if (!autoRegister) {
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
if (permissionStatus !== "granted") {
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
if (devicePushToken) {
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
if (!options.userId) {
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
void register();
|
|
636
|
+
}, [
|
|
637
|
+
autoRegister,
|
|
638
|
+
permissionStatus,
|
|
639
|
+
devicePushToken,
|
|
640
|
+
options.userId,
|
|
641
|
+
register
|
|
642
|
+
]);
|
|
643
|
+
return {
|
|
644
|
+
permissionStatus,
|
|
645
|
+
devicePushToken,
|
|
646
|
+
register,
|
|
647
|
+
unregister,
|
|
648
|
+
addReceivedListener,
|
|
649
|
+
addResponseListener,
|
|
650
|
+
getBadgeCount,
|
|
651
|
+
setBadgeCount
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
function mapStatus(status) {
|
|
655
|
+
if (status === "granted") {
|
|
656
|
+
return "granted";
|
|
657
|
+
}
|
|
658
|
+
if (status === "denied") {
|
|
659
|
+
return "denied";
|
|
660
|
+
}
|
|
661
|
+
if (status === "undetermined") {
|
|
662
|
+
return "undetermined";
|
|
663
|
+
}
|
|
664
|
+
return "unknown";
|
|
665
|
+
}
|
|
666
|
+
function detectPlatform(tokenType) {
|
|
667
|
+
if (tokenType === "apns") {
|
|
668
|
+
return "ios";
|
|
669
|
+
}
|
|
670
|
+
if (tokenType === "fcm") {
|
|
671
|
+
return "android";
|
|
672
|
+
}
|
|
673
|
+
if (tokenType === "web") {
|
|
674
|
+
return "web";
|
|
675
|
+
}
|
|
676
|
+
return "unknown";
|
|
677
|
+
}
|
|
678
|
+
|
|
229
679
|
// src/react/provider.ts
|
|
230
680
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
|
231
681
|
import { createElement, useMemo } from "react";
|
|
@@ -237,13 +687,20 @@ var CONVEX_URLS = {
|
|
|
237
687
|
uat: "https://gallant-gecko-217.convex.cloud",
|
|
238
688
|
production: "https://gallant-gecko-217.convex.cloud"
|
|
239
689
|
};
|
|
690
|
+
function resolveConvexUrl(environment, override) {
|
|
691
|
+
var _a;
|
|
692
|
+
if (override) {
|
|
693
|
+
return override;
|
|
694
|
+
}
|
|
695
|
+
const env = environment != null ? environment : "sandbox";
|
|
696
|
+
return (_a = CONVEX_URLS[env]) != null ? _a : CONVEX_URLS.sandbox;
|
|
697
|
+
}
|
|
240
698
|
function TruthProvider({
|
|
241
699
|
environment = "sandbox",
|
|
242
700
|
convexUrl,
|
|
243
701
|
children
|
|
244
702
|
}) {
|
|
245
|
-
|
|
246
|
-
const url = (_a = convexUrl != null ? convexUrl : CONVEX_URLS[environment]) != null ? _a : CONVEX_URLS.sandbox;
|
|
703
|
+
const url = resolveConvexUrl(environment, convexUrl);
|
|
247
704
|
const client = useMemo(() => new ConvexReactClient(url), [url]);
|
|
248
705
|
return createElement(ConvexProvider, { client }, children);
|
|
249
706
|
}
|
|
@@ -489,7 +946,11 @@ export {
|
|
|
489
946
|
useAppointment,
|
|
490
947
|
useAppointmentByElationId,
|
|
491
948
|
useAppointments,
|
|
949
|
+
useConversationByPhonePair,
|
|
492
950
|
useConversationMessages,
|
|
951
|
+
useConversations,
|
|
952
|
+
useMessages,
|
|
953
|
+
useNotifications,
|
|
493
954
|
usePatient,
|
|
494
955
|
usePatientBasic,
|
|
495
956
|
usePatientByElationId,
|
|
@@ -500,6 +961,7 @@ export {
|
|
|
500
961
|
usePharmacyByNcpdpId,
|
|
501
962
|
usePhysicianByElationId,
|
|
502
963
|
usePhysiciansByElationIds,
|
|
503
|
-
useTruth
|
|
964
|
+
useTruth,
|
|
965
|
+
useUnreadCount
|
|
504
966
|
};
|
|
505
967
|
//# sourceMappingURL=react.mjs.map
|