@hipnation-truth/sdk 0.26.4 → 0.26.7
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 +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.ts +15 -18
- package/dist/react.js +76 -44
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/dist/react.d.ts
CHANGED
|
@@ -591,23 +591,6 @@ interface UsePatientMedicalOptions {
|
|
|
591
591
|
*/
|
|
592
592
|
skipRefresh?: boolean;
|
|
593
593
|
}
|
|
594
|
-
/**
|
|
595
|
-
* Composite hook that returns a patient's medical records — medications,
|
|
596
|
-
* problems, allergies, appointments — from the Convex cache.
|
|
597
|
-
*
|
|
598
|
-
* On mount (and when `elationId` changes) fires a background refresh
|
|
599
|
-
* against Truth's `/api/patients/medical/refresh` endpoint so stale data
|
|
600
|
-
* is pulled in without blocking render. Returns cached data immediately;
|
|
601
|
-
* Convex subscription updates the UI when refresh completes.
|
|
602
|
-
*
|
|
603
|
-
* OFFLINE-READS POLICY: these medical-record queries ARE mirrored offline
|
|
604
|
-
* via `usePersistentQuery`, so medications, problems, allergies and
|
|
605
|
-
* appointments render from the at-rest mirror when the device is offline.
|
|
606
|
-
* Full medical records are the most sensitive PHI we hold, so they are
|
|
607
|
-
* only ever written to the encrypted-at-rest store (256-bit MMKV key held
|
|
608
|
-
* in the device keychain), never to any plaintext storage. Keep them on
|
|
609
|
-
* the encrypted mirror only — do not relax the store's encryption.
|
|
610
|
-
*/
|
|
611
594
|
declare function usePatientMedical(elationId: number | undefined, options?: UsePatientMedicalOptions): {
|
|
612
595
|
medications: unknown[] | undefined;
|
|
613
596
|
problems: unknown[] | undefined;
|
|
@@ -1262,8 +1245,15 @@ type Environment = (typeof ENVIRONMENTS)[keyof typeof ENVIRONMENTS];
|
|
|
1262
1245
|
* your identity provider's Clerk JWT template named "convex"
|
|
1263
1246
|
* (e.g. `getToken({ template: "convex" })` from `@clerk/expo`), or
|
|
1264
1247
|
* `null` when no user is signed in.
|
|
1248
|
+
*
|
|
1249
|
+
* Convex invokes this with `{ forceRefreshToken: true }` when the cached
|
|
1250
|
+
* token has expired — forward it to your provider (e.g. Clerk's
|
|
1251
|
+
* `getToken({ template: "convex", skipCache: opts?.forceRefreshToken })`)
|
|
1252
|
+
* so the refresh returns a fresh token rather than a stale cached one.
|
|
1265
1253
|
*/
|
|
1266
|
-
type AuthTokenFetcher = (
|
|
1254
|
+
type AuthTokenFetcher = (opts?: {
|
|
1255
|
+
forceRefreshToken?: boolean;
|
|
1256
|
+
}) => Promise<string | null | undefined>;
|
|
1267
1257
|
/**
|
|
1268
1258
|
* Configuration for initializing a TruthClient.
|
|
1269
1259
|
*/
|
|
@@ -2771,6 +2761,13 @@ interface TruthSdkContextValue {
|
|
|
2771
2761
|
apiKey: string;
|
|
2772
2762
|
environment: string;
|
|
2773
2763
|
client: TruthClient;
|
|
2764
|
+
/**
|
|
2765
|
+
* Clerk token fetcher (template "convex"), if wired. Hooks that make their
|
|
2766
|
+
* own HTTP calls (e.g. the patient `…/refresh` endpoints) use this to attach
|
|
2767
|
+
* `Authorization: Bearer <jwt>` so they work under a publishable `hn_pk_*`
|
|
2768
|
+
* key, which the API gate accepts only with a verified user JWT.
|
|
2769
|
+
*/
|
|
2770
|
+
getAuthToken?: AuthTokenFetcher;
|
|
2774
2771
|
/** Injected offline mirror (or the Noop default on web / flag off). */
|
|
2775
2772
|
offlineStore: OfflineStore;
|
|
2776
2773
|
/** Whether the offline-reads layer is active for this provider. */
|
package/dist/react.js
CHANGED
|
@@ -2296,26 +2296,34 @@ function TruthProvider({
|
|
|
2296
2296
|
getAuthTokenRef.current = getAuthToken;
|
|
2297
2297
|
const hasAuthFetcher = Boolean(getAuthToken);
|
|
2298
2298
|
const stableGetAuthToken = (0, import_react2.useMemo)(
|
|
2299
|
-
() => hasAuthFetcher ? () => __async(null, null, function* () {
|
|
2299
|
+
() => hasAuthFetcher ? (opts) => __async(null, null, function* () {
|
|
2300
2300
|
var _a2, _b2;
|
|
2301
|
-
return (_b2 = yield (_a2 = getAuthTokenRef.current) == null ? void 0 : _a2.call(getAuthTokenRef)) != null ? _b2 : null;
|
|
2301
|
+
return (_b2 = yield (_a2 = getAuthTokenRef.current) == null ? void 0 : _a2.call(getAuthTokenRef, opts)) != null ? _b2 : null;
|
|
2302
2302
|
}) : void 0,
|
|
2303
2303
|
[hasAuthFetcher]
|
|
2304
2304
|
);
|
|
2305
2305
|
const [convexAuthed, setConvexAuthed] = (0, import_react2.useState)(false);
|
|
2306
2306
|
(0, import_react2.useEffect)(() => {
|
|
2307
|
-
if (stableGetAuthToken) {
|
|
2308
|
-
convexClient.setAuth(
|
|
2309
|
-
() => __async(null, null, function* () {
|
|
2310
|
-
var _a2;
|
|
2311
|
-
return (_a2 = yield stableGetAuthToken()) != null ? _a2 : null;
|
|
2312
|
-
}),
|
|
2313
|
-
(isAuthenticated) => setConvexAuthed(isAuthenticated)
|
|
2314
|
-
);
|
|
2315
|
-
} else {
|
|
2307
|
+
if (!stableGetAuthToken) {
|
|
2316
2308
|
convexClient.clearAuth();
|
|
2317
2309
|
setConvexAuthed(false);
|
|
2310
|
+
return;
|
|
2318
2311
|
}
|
|
2312
|
+
const fetchToken = (opts) => __async(null, null, function* () {
|
|
2313
|
+
for (let attempt = 0; attempt < 6; attempt++) {
|
|
2314
|
+
try {
|
|
2315
|
+
const token = yield stableGetAuthToken(opts);
|
|
2316
|
+
if (token) return token;
|
|
2317
|
+
} catch (e) {
|
|
2318
|
+
}
|
|
2319
|
+
yield new Promise((resolve) => setTimeout(resolve, 200 + attempt * 150));
|
|
2320
|
+
}
|
|
2321
|
+
return null;
|
|
2322
|
+
});
|
|
2323
|
+
convexClient.setAuth(
|
|
2324
|
+
fetchToken,
|
|
2325
|
+
(isAuthenticated) => setConvexAuthed(isAuthenticated)
|
|
2326
|
+
);
|
|
2319
2327
|
}, [convexClient, stableGetAuthToken]);
|
|
2320
2328
|
const convexQueryClient = (0, import_react2.useMemo)(
|
|
2321
2329
|
() => new import_react_query.ConvexQueryClient(convexClient),
|
|
@@ -2390,6 +2398,7 @@ function TruthProvider({
|
|
|
2390
2398
|
client: truthClient,
|
|
2391
2399
|
offlineStore,
|
|
2392
2400
|
offlineEnabled,
|
|
2401
|
+
getAuthToken: stableGetAuthToken,
|
|
2393
2402
|
authGated: hasAuthFetcher,
|
|
2394
2403
|
authReady: convexAuthed
|
|
2395
2404
|
}),
|
|
@@ -2400,6 +2409,7 @@ function TruthProvider({
|
|
|
2400
2409
|
truthClient,
|
|
2401
2410
|
offlineStore,
|
|
2402
2411
|
offlineEnabled,
|
|
2412
|
+
stableGetAuthToken,
|
|
2403
2413
|
hasAuthFetcher,
|
|
2404
2414
|
convexAuthed
|
|
2405
2415
|
]
|
|
@@ -2739,11 +2749,33 @@ var medicationsByPatientRef = (0, import_server5.makeFunctionReference)("medical
|
|
|
2739
2749
|
var problemsByPatientRef = (0, import_server5.makeFunctionReference)("medicalRecords:getProblemsByElationPatient");
|
|
2740
2750
|
var allergiesByPatientRef = (0, import_server5.makeFunctionReference)("medicalRecords:getAllergiesByElationPatient");
|
|
2741
2751
|
var appointmentsByPatientRef = (0, import_server5.makeFunctionReference)("medicalRecords:getAppointmentsByElationPatient");
|
|
2752
|
+
function postPatientRefresh(url, apiKey, getAuthToken, body, signal) {
|
|
2753
|
+
return __async(this, null, function* () {
|
|
2754
|
+
const headers = {
|
|
2755
|
+
"Content-Type": "application/json",
|
|
2756
|
+
"X-API-Key": apiKey
|
|
2757
|
+
};
|
|
2758
|
+
try {
|
|
2759
|
+
const token = yield getAuthToken == null ? void 0 : getAuthToken();
|
|
2760
|
+
if (token) {
|
|
2761
|
+
headers.Authorization = `Bearer ${token}`;
|
|
2762
|
+
}
|
|
2763
|
+
} catch (e) {
|
|
2764
|
+
}
|
|
2765
|
+
yield fetch(url, {
|
|
2766
|
+
method: "POST",
|
|
2767
|
+
headers,
|
|
2768
|
+
body: JSON.stringify(body),
|
|
2769
|
+
signal
|
|
2770
|
+
});
|
|
2771
|
+
});
|
|
2772
|
+
}
|
|
2742
2773
|
function usePatientMedical(elationId, options) {
|
|
2743
2774
|
var _a, _b;
|
|
2744
2775
|
const sdkContext = useTruthSdkContext();
|
|
2745
2776
|
const apiBaseUrl = (_a = options == null ? void 0 : options.apiBaseUrl) != null ? _a : sdkContext == null ? void 0 : sdkContext.apiBaseUrl;
|
|
2746
2777
|
const apiKey = (_b = options == null ? void 0 : options.apiKey) != null ? _b : sdkContext == null ? void 0 : sdkContext.apiKey;
|
|
2778
|
+
const getAuthToken = sdkContext == null ? void 0 : sdkContext.getAuthToken;
|
|
2747
2779
|
const medications = usePersistentQuery(
|
|
2748
2780
|
medicationsByPatientRef,
|
|
2749
2781
|
elationId !== void 0 ? { elationPatientId: elationId } : "skip"
|
|
@@ -2768,18 +2800,16 @@ function usePatientMedical(elationId, options) {
|
|
|
2768
2800
|
return;
|
|
2769
2801
|
}
|
|
2770
2802
|
const controller = new AbortController();
|
|
2771
|
-
void
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
signal: controller.signal
|
|
2779
|
-
}).catch(() => {
|
|
2803
|
+
void postPatientRefresh(
|
|
2804
|
+
`${apiBaseUrl}/api/patients/medical/refresh`,
|
|
2805
|
+
apiKey,
|
|
2806
|
+
getAuthToken,
|
|
2807
|
+
{ elationId },
|
|
2808
|
+
controller.signal
|
|
2809
|
+
).catch(() => {
|
|
2780
2810
|
});
|
|
2781
2811
|
return () => controller.abort();
|
|
2782
|
-
}, [elationId, apiBaseUrl, apiKey, options == null ? void 0 : options.skipRefresh]);
|
|
2812
|
+
}, [elationId, apiBaseUrl, apiKey, getAuthToken, options == null ? void 0 : options.skipRefresh]);
|
|
2783
2813
|
return { medications, problems, allergies, appointments };
|
|
2784
2814
|
}
|
|
2785
2815
|
var elationPatientByIdRef = (0, import_server5.makeFunctionReference)("elationPatients:getByElationId");
|
|
@@ -2791,6 +2821,7 @@ function usePatientBasic(input, options) {
|
|
|
2791
2821
|
const sdkContext = useTruthSdkContext();
|
|
2792
2822
|
const apiBaseUrl = (_a = options == null ? void 0 : options.apiBaseUrl) != null ? _a : sdkContext == null ? void 0 : sdkContext.apiBaseUrl;
|
|
2793
2823
|
const apiKey = (_b = options == null ? void 0 : options.apiKey) != null ? _b : sdkContext == null ? void 0 : sdkContext.apiKey;
|
|
2824
|
+
const getAuthToken = sdkContext == null ? void 0 : sdkContext.getAuthToken;
|
|
2794
2825
|
const elationRow = usePersistentQuery(
|
|
2795
2826
|
elationPatientByIdRef,
|
|
2796
2827
|
input.elationId !== void 0 ? { elationId: input.elationId } : "skip"
|
|
@@ -2810,21 +2841,23 @@ function usePatientBasic(input, options) {
|
|
|
2810
2841
|
return;
|
|
2811
2842
|
}
|
|
2812
2843
|
const controller = new AbortController();
|
|
2813
|
-
void
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
hintId: input.hintId,
|
|
2821
|
-
elationId: input.elationId
|
|
2822
|
-
}),
|
|
2823
|
-
signal: controller.signal
|
|
2824
|
-
}).catch(() => {
|
|
2844
|
+
void postPatientRefresh(
|
|
2845
|
+
`${apiBaseUrl}/api/patients/basic/refresh`,
|
|
2846
|
+
apiKey,
|
|
2847
|
+
getAuthToken,
|
|
2848
|
+
{ hintId: input.hintId, elationId: input.elationId },
|
|
2849
|
+
controller.signal
|
|
2850
|
+
).catch(() => {
|
|
2825
2851
|
});
|
|
2826
2852
|
return () => controller.abort();
|
|
2827
|
-
}, [
|
|
2853
|
+
}, [
|
|
2854
|
+
input.hintId,
|
|
2855
|
+
input.elationId,
|
|
2856
|
+
apiBaseUrl,
|
|
2857
|
+
apiKey,
|
|
2858
|
+
getAuthToken,
|
|
2859
|
+
options == null ? void 0 : options.skipRefresh
|
|
2860
|
+
]);
|
|
2828
2861
|
const elationPatient = elationRow === void 0 ? void 0 : elationRow === null ? null : (_c = elationRow.raw) != null ? _c : null;
|
|
2829
2862
|
const hintPatient = hintRow === void 0 ? void 0 : hintRow === null ? null : (_d = hintRow.raw) != null ? _d : null;
|
|
2830
2863
|
const elationLoading = input.elationId !== void 0 && elationRow === void 0;
|
|
@@ -2848,6 +2881,7 @@ function usePatientPhoto(elationId, options) {
|
|
|
2848
2881
|
const sdkContext = useTruthSdkContext();
|
|
2849
2882
|
const apiBaseUrl = (_a = options == null ? void 0 : options.apiBaseUrl) != null ? _a : sdkContext == null ? void 0 : sdkContext.apiBaseUrl;
|
|
2850
2883
|
const apiKey = (_b = options == null ? void 0 : options.apiKey) != null ? _b : sdkContext == null ? void 0 : sdkContext.apiKey;
|
|
2884
|
+
const getAuthToken = sdkContext == null ? void 0 : sdkContext.getAuthToken;
|
|
2851
2885
|
const photo = usePersistentQuery(
|
|
2852
2886
|
patientPhotoByIdRef,
|
|
2853
2887
|
elationId !== void 0 ? { elationPatientId: elationId } : "skip"
|
|
@@ -2863,18 +2897,16 @@ function usePatientPhoto(elationId, options) {
|
|
|
2863
2897
|
return;
|
|
2864
2898
|
}
|
|
2865
2899
|
const controller = new AbortController();
|
|
2866
|
-
void
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
signal: controller.signal
|
|
2874
|
-
}).catch(() => {
|
|
2900
|
+
void postPatientRefresh(
|
|
2901
|
+
`${apiBaseUrl}/api/patients/photo/refresh`,
|
|
2902
|
+
apiKey,
|
|
2903
|
+
getAuthToken,
|
|
2904
|
+
{ elationId },
|
|
2905
|
+
controller.signal
|
|
2906
|
+
).catch(() => {
|
|
2875
2907
|
});
|
|
2876
2908
|
return () => controller.abort();
|
|
2877
|
-
}, [elationId, apiBaseUrl, apiKey, options == null ? void 0 : options.skipRefresh]);
|
|
2909
|
+
}, [elationId, apiBaseUrl, apiKey, getAuthToken, options == null ? void 0 : options.skipRefresh]);
|
|
2878
2910
|
return photo;
|
|
2879
2911
|
}
|
|
2880
2912
|
var messagesByPhonesRef = (0, import_server5.makeFunctionReference)("conversationMessages:getByPhones");
|