@everfur/sdk 0.1.1 → 0.4.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/CHANGELOG.md +703 -4
- package/README.md +63 -23
- package/consent/package.json +8 -0
- package/dist/Chat-BZZ-Py5l.d.ts +128 -0
- package/dist/Chat-Dq4fffIO.d.cts +128 -0
- package/dist/DepthViews-BG3E25MD.d.ts +16 -0
- package/dist/DepthViews-B_hIypI6.d.cts +19 -0
- package/dist/DepthViews-CL75jyRA.d.cts +16 -0
- package/dist/DepthViews-CkYri51q.d.ts +19 -0
- package/dist/ErrorPolicyPort-CNf4uQZP.d.cts +22 -0
- package/dist/ErrorPolicyPort-CwbfmxzJ.d.ts +22 -0
- package/dist/{EverfurResult-D92-uL82.d.cts → EverfurResult-DN9pL2Ab.d.cts} +11 -10
- package/dist/{EverfurResult-D92-uL82.d.ts → EverfurResult-DN9pL2Ab.d.ts} +11 -10
- package/dist/{PhotoController-BItt5M7u.d.cts → PhotoController-3l7MT9jA.d.cts} +1 -1
- package/dist/{PhotoController-D8zMTdcW.d.ts → PhotoController-vzY5bfY_.d.ts} +1 -1
- package/dist/animations/index.cjs +1 -1997
- package/dist/animations/index.d.cts +35 -35
- package/dist/animations/index.d.ts +35 -35
- package/dist/animations/index.js +1 -1972
- package/dist/attachments-BorG422I.d.cts +146 -0
- package/dist/attachments-BrUWQYNK.d.ts +257 -0
- package/dist/attachments-D_SECjr1.d.cts +257 -0
- package/dist/attachments-DpldrvIW.d.ts +146 -0
- package/dist/bookingCopy-CqtDYvCR.d.ts +732 -0
- package/dist/bookingCopy-SREvkG19.d.cts +732 -0
- package/dist/branding-CsRdeNwK.d.cts +566 -0
- package/dist/branding-CsRdeNwK.d.ts +566 -0
- package/dist/callCopy-DoQKG3-L.d.cts +40 -0
- package/dist/callCopy-DoQKG3-L.d.ts +40 -0
- package/dist/casesRepository-DwtZVsbj.d.cts +51 -0
- package/dist/casesRepository-v6QczS9N.d.ts +51 -0
- package/dist/chat/index.cjs +1 -1170
- package/dist/chat/index.d.cts +32 -53
- package/dist/chat/index.d.ts +32 -53
- package/dist/chat/index.js +1 -1167
- package/dist/client/index.cjs +9 -2315
- package/dist/client/index.d.cts +80 -16
- package/dist/client/index.d.ts +80 -16
- package/dist/client/index.js +9 -2215
- package/dist/{config-CiJ0PVBB.d.ts → config--Wu1Umhd.d.cts} +64 -26
- package/dist/{config-BSjBdxrZ.d.cts → config-C7eb_IMD.d.ts} +64 -26
- package/dist/consent/index.cjs +1 -0
- package/dist/consent/index.d.cts +33 -0
- package/dist/consent/index.d.ts +33 -0
- package/dist/consent/index.js +1 -0
- package/dist/context-CL3lyuy1.d.cts +159 -0
- package/dist/context-CahAEha8.d.ts +159 -0
- package/dist/copy-DdVFDL01.d.ts +198 -0
- package/dist/copy-UeUJVk8X.d.cts +198 -0
- package/dist/core/index.cjs +13 -3178
- package/dist/core/index.d.cts +164 -29
- package/dist/core/index.d.ts +164 -29
- package/dist/core/index.js +13 -3166
- package/dist/depth-D5HwcvKC.d.cts +533 -0
- package/dist/depth-DvPwPuT_.d.ts +533 -0
- package/dist/entitlementRepository-B7egEdW6.d.ts +43 -0
- package/dist/entitlementRepository-BpJ7tiwl.d.cts +43 -0
- package/dist/{identity-Brl-lDd6.d.cts → identity-C2-08BZW.d.cts} +20 -7
- package/dist/{identity-DK9zORrG.d.ts → identity-CEi9GRFZ.d.ts} +20 -7
- package/dist/{ids-CJ1S6adf.d.cts → ids-B2GAAifq.d.cts} +1 -1
- package/dist/{ids-CJ1S6adf.d.ts → ids-B2GAAifq.d.ts} +1 -1
- package/dist/index.cjs +12 -4494
- package/dist/index.d.cts +30 -121
- package/dist/index.d.ts +30 -121
- package/dist/index.js +12 -4470
- package/dist/models-B-Uh2LTf.d.ts +214 -0
- package/dist/models-D2EUxPZY.d.cts +214 -0
- package/dist/notifications/index.cjs +2 -0
- package/dist/notifications/index.d.cts +17 -0
- package/dist/notifications/index.d.ts +17 -0
- package/dist/notifications/index.js +2 -0
- package/dist/optionalModule-DbJmsq5f.d.cts +21 -0
- package/dist/optionalModule-DbJmsq5f.d.ts +21 -0
- package/dist/pets-DJv2sj2H.d.ts +92 -0
- package/dist/pets-JVCXgRgR.d.cts +92 -0
- package/dist/petsRepository-B_gKbAzJ.d.cts +142 -0
- package/dist/petsRepository-Bk6GDwLs.d.ts +142 -0
- package/dist/photo/index.cjs +1 -2189
- package/dist/photo/index.d.cts +6 -6
- package/dist/photo/index.d.ts +6 -6
- package/dist/photo/index.js +1 -2186
- package/dist/ports-BN6RHF9W.d.cts +48 -0
- package/dist/ports-BN6RHF9W.d.ts +48 -0
- package/dist/ports-BY2ph0_y.d.cts +376 -0
- package/dist/ports-D7YW8qz9.d.ts +376 -0
- package/dist/profile-CSs1wlXT.d.cts +93 -0
- package/dist/profile-CSs1wlXT.d.ts +93 -0
- package/dist/records/depth/index.cjs +2 -0
- package/dist/records/depth/index.d.cts +13 -0
- package/dist/records/depth/index.d.ts +13 -0
- package/dist/records/depth/index.js +2 -0
- package/dist/records/index.cjs +3 -2839
- package/dist/records/index.d.cts +137 -203
- package/dist/records/index.d.ts +137 -203
- package/dist/records/index.js +3 -2833
- package/dist/requestFunnel-BjDpqqvm.d.cts +110 -0
- package/dist/requestFunnel-DFMGcluw.d.ts +110 -0
- package/dist/{resolve-Dq_4_agU.d.ts → resolve-D4Ywz5OS.d.cts} +10 -4
- package/dist/{resolve-Dq_4_agU.d.cts → resolve-D4Ywz5OS.d.ts} +10 -4
- package/dist/{runtime-Bvr8yqXm.d.cts → runtimeTypes-gZEJu-da.d.cts} +104 -132
- package/dist/{runtime-BIYzf9cK.d.ts → runtimeTypes-w5KqBMcs.d.ts} +104 -132
- package/dist/server/events/index.cjs +2 -0
- package/dist/server/events/index.d.cts +550 -0
- package/dist/server/events/index.d.ts +550 -0
- package/dist/server/events/index.js +2 -0
- package/dist/server/index.cjs +2 -533
- package/dist/server/index.d.cts +73 -18
- package/dist/server/index.d.ts +73 -18
- package/dist/server/index.js +2 -530
- package/dist/species-BXAIMh7I.d.cts +9 -0
- package/dist/species-BXAIMh7I.d.ts +9 -0
- package/dist/televet/booking/index.cjs +1 -0
- package/dist/televet/booking/index.d.cts +294 -0
- package/dist/televet/booking/index.d.ts +294 -0
- package/dist/televet/booking/index.js +1 -0
- package/dist/televet/call/index.cjs +1 -0
- package/dist/televet/call/index.d.cts +141 -0
- package/dist/televet/call/index.d.ts +141 -0
- package/dist/televet/call/index.js +1 -0
- package/dist/televet/index.cjs +1 -0
- package/dist/televet/index.d.cts +142 -0
- package/dist/televet/index.d.ts +142 -0
- package/dist/televet/index.js +1 -0
- package/dist/testing/index.cjs +5 -823
- package/dist/testing/index.d.cts +18 -4
- package/dist/testing/index.d.ts +18 -4
- package/dist/testing/index.js +5 -820
- package/dist/testing/rn/index.cjs +1 -449
- package/dist/testing/rn/index.d.cts +18 -29
- package/dist/testing/rn/index.d.ts +18 -29
- package/dist/testing/rn/index.js +1 -444
- package/dist/testing/web/index.cjs +1 -0
- package/dist/testing/web/index.d.cts +132 -0
- package/dist/testing/web/index.d.ts +132 -0
- package/dist/testing/web/index.js +1 -0
- package/dist/timelineRows-C15jxFFH.d.ts +19 -0
- package/dist/timelineRows-odO8g9r2.d.cts +19 -0
- package/dist/typeStyle-CKqVYD6L.d.cts +111 -0
- package/dist/typeStyle-DmoyacDG.d.ts +111 -0
- package/dist/uploadTransport-D0M0T4hN.d.ts +38 -0
- package/dist/uploadTransport-DKJHs3Yj.d.cts +38 -0
- package/dist/useRecordsDepth-C6rjEaLn.d.cts +237 -0
- package/dist/useRecordsDepth-crhBllQK.d.ts +237 -0
- package/dist/useVetVisit-Bc84hWUU.d.cts +187 -0
- package/dist/useVetVisit-CjmMa896.d.ts +187 -0
- package/dist/video/index.cjs +1 -1941
- package/dist/video/index.d.cts +4 -4
- package/dist/video/index.d.ts +4 -4
- package/dist/video/index.js +1 -1938
- package/dist/view-Bxwxp4xD.d.ts +310 -0
- package/dist/view-DyitEO0m.d.cts +310 -0
- package/dist/visitIntent-D7_yVp1I.d.cts +8 -0
- package/dist/visitIntent-D7_yVp1I.d.ts +8 -0
- package/dist/web/consent/index.cjs +1 -0
- package/dist/web/consent/index.d.cts +34 -0
- package/dist/web/consent/index.d.ts +34 -0
- package/dist/web/consent/index.js +1 -0
- package/dist/web/index.cjs +14 -0
- package/dist/web/index.d.cts +218 -0
- package/dist/web/index.d.ts +218 -0
- package/dist/web/index.js +14 -0
- package/dist/web/notifications/index.cjs +2 -0
- package/dist/web/notifications/index.d.cts +213 -0
- package/dist/web/notifications/index.d.ts +213 -0
- package/dist/web/notifications/index.js +2 -0
- package/dist/web/records/depth/index.cjs +2 -0
- package/dist/web/records/depth/index.d.cts +12 -0
- package/dist/web/records/depth/index.d.ts +12 -0
- package/dist/web/records/depth/index.js +2 -0
- package/dist/web/records/index.cjs +4 -0
- package/dist/web/records/index.d.cts +285 -0
- package/dist/web/records/index.d.ts +285 -0
- package/dist/web/records/index.js +4 -0
- package/dist/web/televet/booking/index.cjs +1 -0
- package/dist/web/televet/booking/index.d.cts +349 -0
- package/dist/web/televet/booking/index.d.ts +349 -0
- package/dist/web/televet/booking/index.js +1 -0
- package/dist/web/televet/call/index.cjs +1 -0
- package/dist/web/televet/call/index.d.cts +142 -0
- package/dist/web/televet/call/index.d.ts +142 -0
- package/dist/web/televet/call/index.js +1 -0
- package/dist/web/televet/index.cjs +1 -0
- package/dist/web/televet/index.d.cts +136 -0
- package/dist/web/televet/index.d.ts +136 -0
- package/dist/web/televet/index.js +1 -0
- package/notifications/package.json +8 -0
- package/package.json +266 -10
- package/records/depth/package.json +8 -0
- package/server/events/device-blocked.cjs +15 -0
- package/server/events/package.json +9 -0
- package/televet/booking/package.json +8 -0
- package/televet/call/package.json +8 -0
- package/televet/package.json +8 -0
- package/testing/web/native-blocked.cjs +12 -0
- package/testing/web/package.json +8 -0
- package/web/consent/native-blocked.cjs +12 -0
- package/web/consent/package.json +8 -0
- package/web/native-blocked.cjs +12 -0
- package/web/notifications/native-blocked.cjs +12 -0
- package/web/notifications/package.json +8 -0
- package/web/package.json +8 -0
- package/web/records/depth/native-blocked.cjs +12 -0
- package/web/records/depth/package.json +8 -0
- package/web/records/native-blocked.cjs +12 -0
- package/web/records/package.json +8 -0
- package/web/televet/booking/native-blocked.cjs +12 -0
- package/web/televet/booking/package.json +8 -0
- package/web/televet/call/native-blocked.cjs +12 -0
- package/web/televet/call/package.json +8 -0
- package/web/televet/native-blocked.cjs +12 -0
- package/web/televet/package.json +8 -0
- package/dist/ChatController-CKdBvPj2.d.ts +0 -146
- package/dist/ChatController-CpUMvvZf.d.cts +0 -146
- package/dist/FilePort-BabWrv7I.d.cts +0 -22
- package/dist/FilePort-BabWrv7I.d.ts +0 -22
- package/dist/petsRepository-BEGb97M9.d.cts +0 -326
- package/dist/petsRepository-Bu18r2kK.d.ts +0 -326
- package/dist/requestFunnel-DuUH-kAe.d.cts +0 -28
- package/dist/requestFunnel-dio5OmR9.d.ts +0 -28
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { E as EntitlementDecision,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { E as EntitlementDecision, C as CapabilityName } from './resolve-D4Ywz5OS.js';
|
|
2
|
+
import { P as PetProfileInput, R as RegisteredPet, a as PetProfilePatch } from './petsRepository-Bk6GDwLs.js';
|
|
3
|
+
import { c as EverfurResult } from './EverfurResult-DN9pL2Ab.js';
|
|
4
|
+
import { E as EverfurThemeInput, C as ClientBranding } from './branding-CsRdeNwK.js';
|
|
5
|
+
import { A as AuthContext, T as TokenProvider } from './identity-CEi9GRFZ.js';
|
|
6
|
+
import { U as UserRef, P as PetRef, C as ConversationId } from './ids-B2GAAifq.js';
|
|
7
|
+
import { T as TransportPort } from './config-C7eb_IMD.js';
|
|
7
8
|
import { I as ImageCachePort, K as KvPort } from './cacheEpoch-DknKn3S0.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { F as FileHandle } from './FilePort-BabWrv7I.js';
|
|
9
|
+
import { E as ErrorPolicyPort } from './ErrorPolicyPort-CwbfmxzJ.js';
|
|
10
|
+
import { U as UploadPort, l as ChatController } from './ports-D7YW8qz9.js';
|
|
11
11
|
import { C as CameraPort } from './CameraPort-Cv31Pz7g.js';
|
|
12
|
+
import { T as TelemetryPort } from './TelemetryPort-BDNr00hu.js';
|
|
13
|
+
import { U as UploadTransport } from './ports-BN6RHF9W.js';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Opt-in encrypted secret storage. Backed by a Keychain / Keystore native peer through an rn-layer adapter.
|
|
@@ -50,95 +52,6 @@ interface LogSink {
|
|
|
50
52
|
emit(record: Readonly<LogRecord>): void;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
/** Minimum re-poll interval; a server ttl below this is clamped so we never hot-loop the endpoint. */
|
|
54
|
-
declare const MIN_POLL_INTERVAL_SECONDS = 30;
|
|
55
|
-
/** Injectable timer seam so a suite drives the re-poll clock deterministically (default: global timers). */
|
|
56
|
-
type TimerHandle = ReturnType<typeof setTimeout>;
|
|
57
|
-
interface PollScheduler {
|
|
58
|
-
set(callback: () => void, ms: number): TimerHandle;
|
|
59
|
-
clear(handle: TimerHandle): void;
|
|
60
|
-
}
|
|
61
|
-
interface EntitlementPollerDeps {
|
|
62
|
-
/** Re-derived every poll so a token refresh / user re-scope is reflected on the next hop. */
|
|
63
|
-
readonly authFor: () => AuthContext;
|
|
64
|
-
/**
|
|
65
|
-
* Push a fresh verdict into the runtime store. Called ONLY on a 200 'updated'. Carries the server-driven
|
|
66
|
-
* branding parsed from the SAME body (null when absent/unparseable -> the compiled default theme); branding
|
|
67
|
-
* is additive and orthogonal to the decisions.
|
|
68
|
-
*/
|
|
69
|
-
readonly update: (decisions: readonly EntitlementDecision[], branding: ClientBranding | null) => void;
|
|
70
|
-
/** Optional region hint forwarded to the endpoint. */
|
|
71
|
-
readonly region?: string;
|
|
72
|
-
readonly telemetry?: TelemetryPort;
|
|
73
|
-
/** Test seam; defaults to global timers (unref'd so a live poll never pins a Node event loop). */
|
|
74
|
-
readonly scheduler?: PollScheduler;
|
|
75
|
-
/** Test seam; defaults to the real repository call. */
|
|
76
|
-
readonly resolve?: (auth: AuthContext, args: FetchEntitlementsArgs) => Promise<EntitlementResolution>;
|
|
77
|
-
/** Floor override for tests; defaults to MIN_POLL_INTERVAL_SECONDS. */
|
|
78
|
-
readonly floorSeconds?: number;
|
|
79
|
-
/** Test seam for deterministic failure-retry jitter; defaults to Math.random. */
|
|
80
|
-
readonly rng?: () => number;
|
|
81
|
-
}
|
|
82
|
-
interface EntitlementPoller {
|
|
83
|
-
/** Idempotent. Kicks an immediate first poll, then self-schedules on the returned cadence. */
|
|
84
|
-
start(): void;
|
|
85
|
-
/** Idempotent. Clears the pending timer and prevents any post-stop update (dispose calls this). */
|
|
86
|
-
stop(): void;
|
|
87
|
-
/**
|
|
88
|
-
* Drop the cached revision and re-poll immediately. A user / pet re-scope invalidates the cached verdict, so
|
|
89
|
-
* the next request must be UNCONDITIONAL (no If-None-Match) to force a fresh 200 for the new scope.
|
|
90
|
-
*/
|
|
91
|
-
refresh(): void;
|
|
92
|
-
}
|
|
93
|
-
declare function createEntitlementPoller(deps: EntitlementPollerDeps): EntitlementPoller;
|
|
94
|
-
|
|
95
|
-
/** The presigned POST/PUT policy returned by `/uploads/initiate` (SPEC-11b §2.1). */
|
|
96
|
-
interface PresignedPolicy {
|
|
97
|
-
/** Absolute S3 endpoint URL to POST/PUT the bytes at. */
|
|
98
|
-
readonly url: string;
|
|
99
|
-
/** POST-policy form fields to include with the upload (empty for a plain PUT). */
|
|
100
|
-
readonly fields: Readonly<Record<string, string>>;
|
|
101
|
-
/** The owned-uploads-prefixed key the analyze call then references. */
|
|
102
|
-
readonly s3Key: string;
|
|
103
|
-
/** epoch seconds the policy expires; telemetry only. */
|
|
104
|
-
readonly expiresAt: number | null;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* The native upload seam. It PUTs `file` at the presigned `target` (SPEC-11b §2.1). `idempotencyKey` is reused
|
|
108
|
-
* on every retry so a re-uploaded identical file dedupes server-side. A network failure REJECTS; the controller
|
|
109
|
-
* normalizes that to a `mediaUploadFailed` and exposes a retake affordance (never auto-retried, SPEC-00 §3.2).
|
|
110
|
-
*
|
|
111
|
-
* NOTE: the spine `FilePort.presignedPut(file, { idempotencyKey, signal })` has no slot for the presigned
|
|
112
|
-
* target; this richer port is the shape it must grow to. See the manifest gap note.
|
|
113
|
-
*/
|
|
114
|
-
interface UploadPort {
|
|
115
|
-
presignedPut(file: FileHandle, opts: {
|
|
116
|
-
readonly target: PresignedPolicy;
|
|
117
|
-
readonly idempotencyKey: string;
|
|
118
|
-
readonly signal?: AbortSignal;
|
|
119
|
-
}): Promise<void>;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
interface UploadPolicyWire {
|
|
123
|
-
readonly upload_id: string;
|
|
124
|
-
readonly upload_url: string;
|
|
125
|
-
readonly upload_fields: Readonly<Record<string, string>>;
|
|
126
|
-
readonly expires_in_seconds: number;
|
|
127
|
-
readonly max_content_length: number;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Platform-specific: the rn adapter binds `expo-file-system` (uploadAsync) behind `optionalModule`; the
|
|
131
|
-
* controller stays platform-neutral and never sees a native module. Resolves on S3's 204; rejects on a
|
|
132
|
-
* policy 403 / stream failure, which the controller normalizes to a typed `mediaUploadFailed` (never a throw
|
|
133
|
-
* that escapes the controller).
|
|
134
|
-
*/
|
|
135
|
-
interface UploadTransport {
|
|
136
|
-
postMultipart(policy: UploadPolicyWire, file: FileHandle, opts: {
|
|
137
|
-
readonly onProgress?: (fraction: number) => void;
|
|
138
|
-
readonly signal?: AbortSignal;
|
|
139
|
-
}): Promise<void>;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
55
|
/**
|
|
143
56
|
* The public init config the host passes at EverfurProvider mount: the lean client subset
|
|
144
57
|
* (publishableKey / apiBaseUrl / contractVersion / transport / debug) PLUS the host-seam ports. The client
|
|
@@ -189,8 +102,8 @@ interface RuntimeUser {
|
|
|
189
102
|
readonly userRef: UserRef;
|
|
190
103
|
readonly getToken: TokenProvider;
|
|
191
104
|
}
|
|
192
|
-
/**
|
|
193
|
-
type RuntimeTheme =
|
|
105
|
+
/** The client `theme` prop as the provider hands it over (tolerant shape; sanitized by the theme provider). */
|
|
106
|
+
type RuntimeTheme = EverfurThemeInput;
|
|
194
107
|
interface CreateEverfurRuntimeInput {
|
|
195
108
|
readonly config: EverfurRuntimeConfig;
|
|
196
109
|
/** null => general (anonymous) mode: pk alone on the wire. */
|
|
@@ -221,6 +134,12 @@ interface CapabilityServices {
|
|
|
221
134
|
readonly uploadTransport: UploadTransport;
|
|
222
135
|
readonly imageCache: ImageCachePort;
|
|
223
136
|
readonly kv: KvPort;
|
|
137
|
+
/**
|
|
138
|
+
* The API base URL the transport was built for (the config's, or the environment's), or null with an
|
|
139
|
+
* injected transport and no base URL. A relative link the server returns (a share link's path) is
|
|
140
|
+
* resolved against this origin, never opened raw.
|
|
141
|
+
*/
|
|
142
|
+
readonly apiBaseUrl: string | null;
|
|
224
143
|
}
|
|
225
144
|
/**
|
|
226
145
|
* The ONE ref-counted capability registry (SPEC-10 §7.4). Chat (the spine) is acquired by its typed method;
|
|
@@ -236,6 +155,12 @@ interface CapabilityRegistry {
|
|
|
236
155
|
/** Chat is the spine capability; the registry constructs + ref-counts it directly. */
|
|
237
156
|
acquireChat(scope: ChatScope): ChatController;
|
|
238
157
|
releaseChat(controller: ChatController): void;
|
|
158
|
+
/**
|
|
159
|
+
* The live controller for a scope WITHOUT taking a hold, or null. A mount reads it synchronously on its
|
|
160
|
+
* first render so a scope `prepare()` primed renders its settled snapshot at once (no bootstrapping frame),
|
|
161
|
+
* then takes its hold through `acquireChat` in the commit effect as before.
|
|
162
|
+
*/
|
|
163
|
+
peekChat(scope: ChatScope): ChatController | null;
|
|
239
164
|
/**
|
|
240
165
|
* Ref-counted acquire for the tree-shakeable capabilities. Two calls with the same (kind, scopeKey) under
|
|
241
166
|
* the current epoch share ONE controller; the last release disposes it via `destroy`.
|
|
@@ -249,7 +174,12 @@ type ChatControllerRegistry = CapabilityRegistry;
|
|
|
249
174
|
/** The already-resolved server verdict the capability hooks render (never re-folded here). */
|
|
250
175
|
interface EntitlementSnapshot {
|
|
251
176
|
readonly decisions: readonly EntitlementDecision[];
|
|
252
|
-
/**
|
|
177
|
+
/**
|
|
178
|
+
* The first verdict of the current scope is still being fetched. `decideCapability` pends only what the
|
|
179
|
+
* decisions leave undecided: a key absent from the compiled floor (records) shows its skeleton, a key the
|
|
180
|
+
* floor grants (chat) renders at once. false once that fetch settles, whatever it settled to (a failure keeps
|
|
181
|
+
* the floor: fail-closed, never a skeleton left up), and always on a runtime that never fetched.
|
|
182
|
+
*/
|
|
253
183
|
readonly isPending: boolean;
|
|
254
184
|
/**
|
|
255
185
|
* Server-driven theme branding from the SAME entitlements body (orthogonal to decisions). null/absent =>
|
|
@@ -267,6 +197,48 @@ interface EntitlementStore {
|
|
|
267
197
|
subscribe(listener: () => void): () => void;
|
|
268
198
|
getSnapshot(): EntitlementSnapshot;
|
|
269
199
|
}
|
|
200
|
+
interface PrepareOptions {
|
|
201
|
+
/**
|
|
202
|
+
* The pet the first chat mount will be scoped to. Names it and the warm-up ALSO primes that scope's chat
|
|
203
|
+
* bootstrap (conversation + suggested prompts), held for the first mount. It registers nothing: a pet the
|
|
204
|
+
* partner has not upserted is registered with `registerPet`, not here.
|
|
205
|
+
*/
|
|
206
|
+
readonly petRef?: PetRef;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* `ready`: token minted (when a user is set), verdict resolved, chat primed (when a pet was named).
|
|
210
|
+
* `partial`: the token is ready but the verdict fetch or the chat prime settled to an error; surfaces still
|
|
211
|
+
* mount and self-heal (the poller re-polls, the first send recreates the conversation).
|
|
212
|
+
* `failed`: nothing authenticated can proceed: the mint failed, or the runtime is disposed / not configured.
|
|
213
|
+
*/
|
|
214
|
+
type PrepareStatus = 'ready' | 'partial' | 'failed';
|
|
215
|
+
/** The settled warm-up. Each step carries the same `EverfurError` the surfaces settle to; nothing throws. */
|
|
216
|
+
interface PrepareResult {
|
|
217
|
+
readonly status: PrepareStatus;
|
|
218
|
+
/** Milliseconds from the `prepare()` call to settlement: the login-to-ready number, also on telemetry. */
|
|
219
|
+
readonly durationMs: number;
|
|
220
|
+
/** The session-token mint. `ok` without a user (anonymous mode mints nothing). */
|
|
221
|
+
readonly session: EverfurResult<void>;
|
|
222
|
+
/** The entitlement verdict fetch into the store every gate reads. */
|
|
223
|
+
readonly entitlements: EverfurResult<void>;
|
|
224
|
+
/** The chat prime for `petRef`; absent when no pet was named. */
|
|
225
|
+
readonly chat?: EverfurResult<void>;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* What a before-logout hook receives: who is leaving, and an auth context that keeps signing requests for the
|
|
229
|
+
* length of the hook budget even though the runtime drops the live identity synchronously right after the hooks
|
|
230
|
+
* start. The bearer is read from the identity's cache at that instant (or minted then, if none was cached), so a
|
|
231
|
+
* request the hook issues after an `await` still goes out under the signed-out user, never re-minted afterwards.
|
|
232
|
+
*/
|
|
233
|
+
interface BeforeLogoutContext {
|
|
234
|
+
readonly userRef: UserRef;
|
|
235
|
+
readonly auth: AuthContext;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* A hook that runs when a signed-in user is about to leave (`logout()`, `setUser(null)`, a switch to another
|
|
239
|
+
* user). It may return a promise; `logout()` waits for it up to `LOGOUT_HOOK_BUDGET_MS` and never fails on it.
|
|
240
|
+
*/
|
|
241
|
+
type BeforeLogoutHook = (context: BeforeLogoutContext) => unknown;
|
|
270
242
|
interface EverfurRuntime {
|
|
271
243
|
readonly registry: CapabilityRegistry;
|
|
272
244
|
/**
|
|
@@ -303,18 +275,39 @@ interface EverfurRuntime {
|
|
|
303
275
|
* calling `setUser(nextUser)`.
|
|
304
276
|
*/
|
|
305
277
|
logout(): Promise<void>;
|
|
278
|
+
/**
|
|
279
|
+
* Run `hook` BEFORE a signed-in user leaves: on `logout()`, on `setUser(null)` and on a switch to another user,
|
|
280
|
+
* with the leaving user's `userRef` and a grace auth that still signs requests. Started synchronously, before
|
|
281
|
+
* the bearer drops and the capabilities re-scope; `logout()` additionally awaits it, bounded by
|
|
282
|
+
* `LOGOUT_HOOK_BUDGET_MS`, and a hook that throws, rejects or hangs never fails or delays sign-out beyond that.
|
|
283
|
+
* The per-user KV sweep runs after the hooks. Returns the unsubscribe. Nothing runs for an anonymous runtime.
|
|
284
|
+
*/
|
|
285
|
+
onBeforeLogout(hook: BeforeLogoutHook): () => void;
|
|
306
286
|
/** Re-scopes pet-bound controllers in the same commit. */
|
|
307
287
|
setActivePet(pet: PetRef | null): void;
|
|
308
288
|
/**
|
|
309
289
|
* Register (or update) the widget pet profile the records and consent routes assume already exists.
|
|
310
290
|
*
|
|
311
291
|
* All three consent routes resolve `pet_ref` through the server's `_resolve_pet_id`, which 404s when no
|
|
312
|
-
* widget pet exists
|
|
292
|
+
* widget pet exists, so consent, and therefore records, is UNREACHABLE for any pet the partner has not
|
|
313
293
|
* upserted out of band. `createPetsRepository` exists on the `@everfur/sdk/client` subpath, but that is
|
|
314
294
|
* the advanced-integrator surface and it takes a raw `AuthContext`; a partner using the provider had no
|
|
315
295
|
* way to call it. This is that way. Idempotent: the route is an upsert keyed on `pet_ref`.
|
|
316
296
|
*/
|
|
317
297
|
registerPet(pet: PetRef, profile?: PetProfileInput): Promise<EverfurResult<RegisteredPet>>;
|
|
298
|
+
/**
|
|
299
|
+
* Change part of a registered pet's profile (`PATCH /widget/v1/pets/{pet_ref}`). An omitted field is unchanged,
|
|
300
|
+
* `null` clears it. An unknown pet settles to the not-found error.
|
|
301
|
+
*/
|
|
302
|
+
updatePet(pet: PetRef, patch: PetProfilePatch): Promise<EverfurResult<RegisteredPet>>;
|
|
303
|
+
/** Delete a pet profile (`DELETE /widget/v1/pets/{pet_ref}`); the server also retires its Records data. */
|
|
304
|
+
deletePet(pet: PetRef): Promise<EverfurResult<void>>;
|
|
305
|
+
/**
|
|
306
|
+
* Permanently erase everything Everfur holds for the current user (`DELETE /widget/v1/me`). A failure is
|
|
307
|
+
* retryable and a repeat call resumes the erasure. It does not sign the user out: call `logout()` or
|
|
308
|
+
* `setUser(null)` afterwards so mounted surfaces stop showing the erased data.
|
|
309
|
+
*/
|
|
310
|
+
eraseUserData(): Promise<EverfurResult<void>>;
|
|
318
311
|
/**
|
|
319
312
|
* Replace the rendered entitlement verdict (a future poller / a manifest refresh). The SERVER stays
|
|
320
313
|
* authoritative: this only feeds the render store, so the pending/enabled paths become reachable while a
|
|
@@ -323,40 +316,19 @@ interface EverfurRuntime {
|
|
|
323
316
|
updateEntitlements(next: EntitlementSnapshot): void;
|
|
324
317
|
/** Navigate / mount a prebuilt capability screen (host-routed). No-op at the spine. */
|
|
325
318
|
open(capability: CapabilityName): void;
|
|
319
|
+
/**
|
|
320
|
+
* Warm up during the partner's OWN login so no Everfur surface adds a loading step of its own: mint the
|
|
321
|
+
* session token, resolve the entitlement verdict into the gate store and, when a pet is named, prime its
|
|
322
|
+
* chat bootstrap. Concurrent calls coalesce onto one run; a settled `ready` is returned again without I/O
|
|
323
|
+
* until the identity or pet re-scopes; a `partial` / `failed` run is retried on the next call. Never
|
|
324
|
+
* throws. Emits `sdk.prepare.timing` (`durationMs`, `status`) on the host telemetry sink once per run.
|
|
325
|
+
*/
|
|
326
|
+
prepare(opts?: PrepareOptions): Promise<PrepareResult>;
|
|
326
327
|
/**
|
|
327
328
|
* Idempotent teardown: aborts in-flight capability requests, tears down every open SSE stream, and stops
|
|
328
329
|
* the entitlement poller (an in-flight entitlement poll's result is DROPPED, not aborted mid-flight).
|
|
329
330
|
*/
|
|
330
331
|
dispose(): void;
|
|
331
332
|
}
|
|
332
|
-
/** Runtime-construction options, distinct from the partner-facing config (host wiring / test seams). */
|
|
333
|
-
interface CreateRuntimeOptions {
|
|
334
|
-
/**
|
|
335
|
-
* Whether to start the entitlement poller. Default: start ONLY when the transport was NOT injected (a real,
|
|
336
|
-
* base-URL runtime). An injected transport is the test seam, so auto-start stays OFF to keep MockTransport
|
|
337
|
-
* suites network-free; pass `true` to exercise the wired poller against a MockTransport.
|
|
338
|
-
*/
|
|
339
|
-
readonly startEntitlementPolling?: boolean;
|
|
340
|
-
/** Test seam: an injected scheduler so a suite can drive the entitlement re-poll timer deterministically. */
|
|
341
|
-
readonly pollScheduler?: PollScheduler;
|
|
342
|
-
/**
|
|
343
|
-
* Host-wiring seam: the EventSource factory the built HTTP transport falls back to when a streaming
|
|
344
|
-
* `res.body` is unavailable (stock RN fetch). The rn facade injects react-native-sse here so streaming works
|
|
345
|
-
* on stock React Native; core NEVER imports react-native-sse (it stays framework-free and only threads this
|
|
346
|
-
* through). Absent (web/expo, or an injected transport) => the fetch-body streaming path is used.
|
|
347
|
-
*/
|
|
348
|
-
readonly eventSourceFactory?: EventSourceFactory;
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Construct the runtime once (EverfurProvider mount). Builds the transport (injected test seam, else the
|
|
352
|
-
* real HTTP transport from the resolved client config), the IdentityProvider when a user is set, the
|
|
353
|
-
* capability registry, the entitlement store, and (for a real runtime) the entitlement poller.
|
|
354
|
-
* A config that cannot be resolved (missing publishableKey, or an unresolvable / non-https base URL when
|
|
355
|
-
* no transport is injected) does NOT throw: it yields a DISABLED runtime whose transport refuses and
|
|
356
|
-
* whose every capability settles to the deliberate off-state at `disabled.level === 'sdk_config'`.
|
|
357
|
-
* @throws {EverfurConfigError} only for a supplied ACTIVE secureStore, which expresses a security
|
|
358
|
-
* intent the SDK cannot yet honour and must not silently discard.
|
|
359
|
-
*/
|
|
360
|
-
declare function createEverfurRuntime(input: CreateEverfurRuntimeInput, opts?: CreateRuntimeOptions): EverfurRuntime;
|
|
361
333
|
|
|
362
|
-
export { type
|
|
334
|
+
export { type BeforeLogoutContext as B, type CreateEverfurRuntimeInput as C, type EntitlementSnapshot as E, type LogLevel as L, NULL_SECURE_STORE as N, type PrepareOptions as P, type RuntimeTheme as R, type SecureStorePort as S, type LogRecord as a, type LogSink as b, type PrepareResult as c, type PrepareStatus as d, type EverfurRuntime as e, type BeforeLogoutHook as f, type CapabilityKind as g, type CapabilityRegistry as h, type CapabilityServices as i, type ChatControllerRegistry as j, type ChatScope as k, type EntitlementStore as l, type EverfurRuntimeConfig as m, type RuntimeUser as n };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var crypto=require('crypto');var we=Object.defineProperty;var n=(e,t)=>we(e,"name",{value:t,configurable:true});function k(e,t){return Object.freeze(t===void 0?{ok:true,value:e}:{ok:true,value:e,warning:t})}n(k,"ok");function _(e){return Object.freeze({ok:false,error:e})}n(_,"err");var E=class E extends Error{constructor(t,r){super(r),this.name="EverfurConfigError",this.kind=t,Object.setPrototypeOf(this,E.prototype);}};n(E,"EverfurConfigError");var s=E;var ke="Everfur-Signature",N=300,j="v1",Oe=4096,Te=64,xe=/^[0-9]+$/,R=class R extends Error{constructor(t){super(`Everfur webhook verification failed: ${t}`),this.name="EverfurWebhookVerificationError",this.code=t,Object.setPrototypeOf(this,R.prototype);}};n(R,"EverfurWebhookVerificationError");var p=R;function Ie(e,t,r,o={}){let i=L(e),a=M(r),l=o.toleranceSeconds??N;if(!Number.isInteger(l)||l<0)throw new s("invalid-argument","toleranceSeconds must be a non-negative integer");let d=De(t),u=o.nowSeconds??Math.floor(Date.now()/1e3);if(Math.abs(u-d.timestamp)>l)throw new p("timestamp_outside_tolerance");let c=false;for(let f of a){let y=Buffer.from(U(f,d.timestamp,i),"ascii");for(let m of d.signatures){if(m.length!==Te)continue;let g=Buffer.from(m,"utf8");g.length===y.length&&crypto.timingSafeEqual(y,g)&&(c=true);}}if(!c)throw new p("no_matching_signature");return Fe(i)}n(Ie,"constructEvent");function Ae(e){let t=L(e.payload),r=M(e.secrets),o=e.timestamp??Math.floor(Date.now()/1e3);if(!Number.isSafeInteger(o)||o<0)throw new s("invalid-argument","timestamp must be a non-negative integer (unix seconds)");return [`t=${o}`,...r.map(i=>`${j}=${U(i,o,t)}`)].join(",")}n(Ae,"generateTestSignatureHeader");function U(e,t,r){return crypto.createHmac("sha256",Buffer.from(e,"utf8")).update(`${t}.`,"ascii").update(r).digest("hex")}n(U,"computeSignature");function L(e){if(typeof e=="string")return Buffer.from(e,"utf8");if(e instanceof Uint8Array)return e;throw new s("invalid-argument","constructEvent needs the raw request body (a string or a Buffer), not parsed JSON: re-serialised JSON does not reproduce the signed bytes.")}n(L,"rawBodyBytes");function M(e){let t=typeof e=="string"?[e]:Array.isArray(e)?e:[];if(t.length===0||t.some(r=>typeof r!="string"||r.length===0))throw new s("invalid-argument","at least one non-empty webhook signing secret is required");return t}n(M,"requireSecrets");function De(e){if(typeof e!="string"||e.length===0||e.length>Oe)throw new p("malformed_header");let t=null,r=[];for(let o of e.split(",")){let i=o.trim(),a=i.indexOf("=");if(a<0)throw new p("malformed_header");let l=i.slice(0,a),d=i.slice(a+1);if(l==="t"){if(t!==null||!xe.test(d))throw new p("malformed_header");let u=Number(d);if(!Number.isSafeInteger(u))throw new p("malformed_header");t=u;}else l===j&&r.push(d);}if(t===null||r.length===0)throw new p("malformed_header");return {timestamp:t,signatures:r}}n(De,"parseSignatureHeader");function Fe(e){let t;try{t=JSON.parse(Buffer.from(e.buffer,e.byteOffset,e.byteLength).toString("utf8"));}catch{throw new p("malformed_payload")}if(!O(t))throw new p("malformed_payload");let{id:r,object:o,type:i,api_version:a,created:l,livemode:d,data:u}=t;if(typeof r!="string"||r.length===0||o!=="event"||typeof i!="string"||i.length===0||typeof a!="string"||typeof l!="number"||typeof d!="boolean"||!O(u)||!O(u.object))throw new p("malformed_payload");return t}n(Fe,"parseEnvelope");function O(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}n(O,"isRecord");var V="0.4.0",B="react-native",q="2026-09-19",z="EVERFUR_API_BASE_URL";function h(e,t){return Object.freeze({ok:false,failure:Object.freeze({reason:e,message:t})})}n(h,"configFailure");function Ne(e){let t=e?.trim(),r=t&&t.length>0?t:qe(z);return r?Ve(r):h("missing-api-base-url",`apiBaseUrl is required: pass config.apiBaseUrl or set ${z}. The SDK never ships a hardcoded host.`)}n(Ne,"tryResolveApiBaseUrl");function W(e){let t=Ne(e);if(!t.ok)throw new s("invalid-argument",t.failure.message);return t.value}n(W,"resolveApiBaseUrl");function H(e){return {"X-Everfur-SDK-Version":e.sdkVersion,"X-Everfur-SDK-Platform":e.platform,"X-Everfur-Contract":e.contractVersion}}n(H,"buildBaseHeaders");var je=/^([A-Za-z][A-Za-z0-9+.-]*):\/\/([^/?#]*)/;function Ue(e){return e.slice(e.lastIndexOf("@")+1).replace(/:\d+$/,"").toLowerCase()}n(Ue,"hostOf");function Le(e){return e.length===0||e.includes("@")?false:e.startsWith("[")&&e.endsWith("]")?true:!e.includes(":")}n(Le,"isPrintableHost");function Me(e,t){let r=e.indexOf("://");return r<0||e.slice(r+3).includes("@")?false:Le(t)}n(Me,"canEchoOrigin");function ze(e,t){return `${e}://${t}`}n(ze,"safeOrigin");function Ve(e){let t=e.trim(),r=je.exec(t);if(r===null||r[2]===void 0||r[2].length===0)return h("malformed-api-base-url","apiBaseUrl is not a valid absolute URL");let o=(r[1]??"").toLowerCase(),i=Ue(r[2]);if(i.length===0)return h("malformed-api-base-url","apiBaseUrl is not a valid absolute URL");let a=Me(t,i)?`: ${ze(o,i)}`:"";if(o!=="https"){if(!(o==="http"&&Be(i)))return o==="http"?h("insecure-api-base-url",`apiBaseUrl must use https (cleartext http is only allowed for localhost)${a}`):h("unsupported-api-base-url-scheme",`apiBaseUrl must be http(s)${a}`)}let l=t.endsWith("/")?t.slice(0,-1):t;return Object.freeze({ok:true,value:l})}n(Ve,"normalizeBaseUrl");function Be(e){let t=e.toLowerCase();return t==="localhost"||t==="127.0.0.1"||t==="[::1]"||t==="::1"}n(Be,"isLoopbackHost");function qe(e){let r=globalThis.process?.env?.[e];return typeof r=="string"&&r.trim().length>0?r.trim():void 0}n(qe,"readEnv");var T=Object.freeze([Object.freeze({wireCode:"AccessDeniedException",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"AuthorizationException",envelope:"http_envelope",httpStatus:401,retryable:false}),Object.freeze({wireCode:"ConflictException",envelope:"http_envelope",httpStatus:409,retryable:true}),Object.freeze({wireCode:"DAILY_QUOTA_EXCEEDED",envelope:"http_envelope",httpStatus:429,retryable:true}),Object.freeze({wireCode:"FILE_TOO_LARGE",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"IDEMPOTENCY_KEY_IN_FLIGHT",envelope:"http_envelope",httpStatus:409,retryable:true}),Object.freeze({wireCode:"IDEMPOTENCY_KEY_REUSED_DIFFERENT_REQUEST",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"INVALID_CONTENT_TYPE",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"InternalFailureException",envelope:"http_envelope",httpStatus:500,retryable:true}),Object.freeze({wireCode:"MethodNotAllowedException",envelope:"http_envelope",httpStatus:405,retryable:false}),Object.freeze({wireCode:"NotImplementedException",envelope:"http_envelope",httpStatus:501,retryable:false}),Object.freeze({wireCode:"PaymentRequiredException",envelope:"http_envelope",httpStatus:402,retryable:false}),Object.freeze({wireCode:"ResourceNotFoundException",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"ServiceUnavailableException",envelope:"http_envelope",httpStatus:503,retryable:true}),Object.freeze({wireCode:"TIER_UPGRADE_REQUIRED",envelope:"http_envelope",httpStatus:402,retryable:false}),Object.freeze({wireCode:"ThrottlingException",envelope:"http_envelope",httpStatus:429,retryable:true}),Object.freeze({wireCode:"ValidationException",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"accessDenied",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"access_denied",envelope:"oauth_error",httpStatus:302,retryable:false}),Object.freeze({wireCode:"attachment_unreadable",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"authExpired",envelope:"http_envelope",httpStatus:401,retryable:true}),Object.freeze({wireCode:"authRejected",envelope:"http_envelope",httpStatus:401,retryable:false}),Object.freeze({wireCode:"consent_invalid",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"consent_required",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"consent_scope_wrong_route",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"device_cipher_unavailable",envelope:"http_envelope",httpStatus:503,retryable:true}),Object.freeze({wireCode:"email_invalid",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"event_cursor_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"event_filter_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"event_payload_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"event_type_not_available",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"event_type_unknown",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"idempotency_key_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"idempotency_key_required",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"idempotency_key_reused",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"insufficientCapability",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"insufficient_scope",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"internal_error",envelope:"sse_frame",httpStatus:200,retryable:false}),Object.freeze({wireCode:"invalidRequest",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_client",envelope:"oauth_error",httpStatus:401,retryable:false}),Object.freeze({wireCode:"invalid_client_metadata",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_grant",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_redirect_uri",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_request",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_scope",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_target",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"mcp_connection_not_found",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"mcp_request_conflict",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"mcp_request_gone",envelope:"http_envelope",httpStatus:410,retryable:false}),Object.freeze({wireCode:"mcp_request_not_found",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"not_found",envelope:"sse_frame",httpStatus:200,retryable:false}),Object.freeze({wireCode:"partner_visit_link_conflict",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"partner_visit_owner_only",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"partner_visit_pet_already_mapped",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"payload_too_large",envelope:"http_envelope",httpStatus:413,retryable:false}),Object.freeze({wireCode:"petRefInUse",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"pet_health_list_removals_unconfirmed",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"pet_health_species_unsupported",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"pet_not_registered",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"provider_unsupported",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"rateLimited",envelope:"http_envelope",httpStatus:429,retryable:true}),Object.freeze({wireCode:"record_species_unsupported",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"record_subject_not_found",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"record_upload_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"records_consent_required",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"sandbox_only",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"session_required",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"share_limit_reached",envelope:"http_envelope",httpStatus:429,retryable:false}),Object.freeze({wireCode:"slow_down",envelope:"oauth_error",httpStatus:429,retryable:true}),Object.freeze({wireCode:"species_unsupported",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"tenant_filter_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"tenant_has_no_capabilities",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"tenant_resource_not_found",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"tenant_surface_not_enabled",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"timeout",envelope:"sse_frame",httpStatus:200,retryable:true}),Object.freeze({wireCode:"token_invalid",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"unavailable",envelope:"sse_frame",httpStatus:200,retryable:true}),Object.freeze({wireCode:"unavailable",envelope:"http_envelope",httpStatus:503,retryable:true}),Object.freeze({wireCode:"unsupported_grant_type",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"unsupported_response_type",envelope:"oauth_error",httpStatus:302,retryable:false}),Object.freeze({wireCode:"verify_mint_rate_limited",envelope:"http_envelope",httpStatus:429,retryable:true}),Object.freeze({wireCode:"verify_mint_refused",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"verify_mint_unavailable",envelope:"http_envelope",httpStatus:503,retryable:true}),Object.freeze({wireCode:"verify_user_ref_invalid",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"webhook_endpoint_update_empty",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"webhook_endpoint_update_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"webhook_url_rejected",envelope:"http_envelope",httpStatus:400,retryable:false})]);Object.freeze(T.map(e=>e.wireCode));var We=Object.freeze({ValidationException:"validationFailed",AuthorizationException:"authRejected",PaymentRequiredException:"paymentRequired",AccessDeniedException:"accessDenied",ResourceNotFoundException:"resourceNotFound",ConflictException:"conflict",ThrottlingException:"rateLimited",InternalFailureException:"internalError",NotImplementedException:"notImplemented",ServiceUnavailableException:"serviceUnavailable",MethodNotAllowedException:"validationFailed",authExpired:"authExpired",unavailable:"serviceUnavailable",session_required:"sessionRequired",accessDenied:"accessDenied",invalidRequest:"sdkUpdateRequired",authRejected:"authRejected",rateLimited:"rateLimited",insufficientCapability:"accessDenied",event_cursor_invalid:"validationFailed",event_filter_invalid:"validationFailed",event_payload_invalid:"validationFailed",event_type_unknown:"validationFailed",idempotency_key_invalid:"validationFailed",idempotency_key_required:"validationFailed",idempotency_key_reused:"idempotencyConflict",payload_too_large:"validationFailed",webhook_url_rejected:"validationFailed",webhook_endpoint_update_empty:"validationFailed",webhook_endpoint_update_invalid:"validationFailed",event_type_not_available:"conflict",record_subject_not_found:"resourceNotFound",records_consent_required:"conflict",record_species_unsupported:"validationFailed",record_upload_invalid:"validationFailed",FILE_TOO_LARGE:"validationFailed",INVALID_CONTENT_TYPE:"validationFailed",attachment_unreadable:"validationFailed",provider_unsupported:"validationFailed",token_invalid:"validationFailed",device_cipher_unavailable:"serviceUnavailable",email_invalid:"validationFailed",consent_required:"validationFailed",consent_invalid:"validationFailed",consent_scope_wrong_route:"validationFailed",IDEMPOTENCY_KEY_IN_FLIGHT:"idempotencyInFlight",IDEMPOTENCY_KEY_REUSED_DIFFERENT_REQUEST:"idempotencyConflict",DAILY_QUOTA_EXCEEDED:"quotaExceeded",TIER_UPGRADE_REQUIRED:"paymentRequired",not_found:"conversationNotFound",timeout:"streamTimeout",internal_error:"internalError",invalid_request:"validationFailed",invalid_client:"authRejected",invalid_grant:"authRejected",unsupported_grant_type:"validationFailed",invalid_scope:"validationFailed",invalid_target:"validationFailed",invalid_redirect_uri:"validationFailed",invalid_client_metadata:"validationFailed",unsupported_response_type:"validationFailed",access_denied:"accessDenied",slow_down:"rateLimited",mcp_request_not_found:"resourceNotFound",mcp_request_gone:"resourceNotFound",mcp_connection_not_found:"resourceNotFound",mcp_request_conflict:"conflict",sandbox_only:"accessDenied",tenant_has_no_capabilities:"conflict",verify_mint_refused:"accessDenied",verify_mint_rate_limited:"rateLimited",verify_mint_unavailable:"serviceUnavailable",verify_user_ref_invalid:"validationFailed",insufficient_scope:"accessDenied",tenant_filter_invalid:"validationFailed",tenant_resource_not_found:"resourceNotFound",tenant_surface_not_enabled:"conflict",pet_health_species_unsupported:"validationFailed",pet_health_list_removals_unconfirmed:"validationFailed",petRefInUse:"conflict",share_limit_reached:"conflict",pet_not_registered:"resourceNotFound",species_unsupported:"validationFailed",partner_visit_owner_only:"accessDenied",partner_visit_link_conflict:"conflict",partner_visit_pet_already_mapped:"conflict"}),K=Object.freeze(T.map(e=>Object.freeze({wireCode:e.wireCode,envelope:e.envelope,retryable:e.retryable,normalized:We[e.wireCode]}))),He=new Map(K.map(e=>[e.envelope+e.wireCode.toUpperCase(),e])),$e=Object.freeze(["http_envelope",...[...new Set(K.map(e=>e.envelope))].filter(e=>e!=="http_envelope").sort()]);function P(e,t){if(typeof e!="string")return;let r=e.trim().toUpperCase();if(r.length!==0)for(let o of [t??"http_envelope",...$e]){let i=He.get(o+r);if(i)return i}}n(P,"contractErrorFor");function Ke(e){return e.envelope==="sse_frame"?`/errors#sse-${e.wireCode}`:e.envelope==="oauth_error"?`/errors#oauth-${e.wireCode}`:`/errors#${e.wireCode}`}n(Ke,"contractDocUrl");function Y(e){return null}n(Y,"publishedDocUrl");var Ye=Object.freeze({authExpired:"authentication",authRejected:"authentication",sessionRequired:"authentication",accessDenied:"authorization",paymentRequired:"entitlement",quotaExceeded:"rateLimit",rateLimited:"rateLimit",validationFailed:"invalidRequest",sdkUpdateRequired:"invalidRequest",conversationNotFound:"notFound",petNotFound:"notFound",resourceNotFound:"notFound",conflict:"conflict",idempotencyConflict:"conflict",idempotencyInFlight:"conflict",streamTimeout:"connection",streamIncomplete:"connection",upstreamLlmTimeout:"connection",serviceUnavailable:"connection",internalError:"server",notImplemented:"server",mediaUploadFailed:"media",moderationBlocked:"policy",unknown:"unknown"});function G(e){return Ye[e]}n(G,"categoryFor");function X(e){let t=P(e);if(t)return t.normalized;let r=(e??"").trim().toUpperCase(),o=r.replace(/[^A-Z0-9]/g,"");if(o==="AUTHREJECTED")return "authRejected";if(r.startsWith("AUTH"))return "authExpired";switch(o){case "DAILYQUOTAEXCEEDED":case "QUOTAEXCEEDED":return "quotaExceeded";case "RATELIMITED":case "TOOMANYREQUESTS":return "rateLimited";case "IDEMPOTENCYKEYCONFLICT":case "IDEMPOTENCYCONFLICT":return "idempotencyConflict";case "ACCESSDENIED":case "FORBIDDEN":return "accessDenied";case "NOTFOUND":case "CONVERSATIONNOTFOUND":return "conversationNotFound";case "PETNOTFOUND":return "petNotFound";case "TIMEOUT":case "STREAMTIMEOUT":return "streamTimeout";case "MEDIAUPLOADFAILED":case "UNRECOGNIZEDVIDEOFORMAT":case "FILETOOSMALL":return "mediaUploadFailed";case "MODERATIONBLOCKED":return "moderationBlocked";case "UPSTREAMLLMTIMEOUT":return "upstreamLlmTimeout";case "INTERNALERROR":case "INTERNALSERVERERROR":return "internalError";case "STREAMINCOMPLETE":case "CHATSTREAMINCOMPLETE":return "streamIncomplete";case "INVALIDANALYSISTYPE":case "INVALIDUPLOADPURPOSE":return "unknown";default:return "unknown"}}n(X,"fromWire");function J(e){return e===401?"authExpired":e===403?"accessDenied":e===404?"conversationNotFound":e===409?"idempotencyConflict":e===421?"unknown":e===429?"rateLimited":e===400||e===422?"unknown":e>=500?"internalError":"unknown"}n(J,"fromHttpStatus");var Ge=new Set(["streamTimeout","rateLimited","internalError","upstreamLlmTimeout","streamIncomplete"]);function Q(e){return Ge.has(e)}n(Q,"isAutoRetryable");var Xe=new Set(["serviceUnavailable","conflict","idempotencyInFlight"]);function Z(e){return Q(e)||Xe.has(e)}n(Z,"isRetryableCode");var Je=Object.freeze({authExpired:"Please sign in again to continue.",authRejected:"Please sign in again to continue.",sessionRequired:"This app needs to be updated to keep using Everfur.",accessDenied:"This feature isn't available on your account right now.",paymentRequired:"This is part of a paid plan.",quotaExceeded:"You have used today's messages. This resets tomorrow.",rateLimited:"You are sending messages quickly. Try again in a few seconds.",validationFailed:"Something in that request was not right. Check the details and try again.",sdkUpdateRequired:"This app needs to be updated to keep using Everfur.",conflict:"That is already running. Wait for it to finish, then try again.",idempotencyConflict:"That message was already delivered.",idempotencyInFlight:"That is still processing. Give it a moment.",conversationNotFound:"This conversation is no longer available.",petNotFound:"We could not find that pet. Please pick a pet and try again.",resourceNotFound:"We could not find that.",streamTimeout:"The response timed out. Tap retry to try again.",mediaUploadFailed:"We could not upload that photo. Please attach it again.",moderationBlocked:"This request cannot be answered here.",upstreamLlmTimeout:"The response timed out. Tap retry to try again.",internalError:"We hit a snag on our end. Please try again.",notImplemented:"That is not available yet.",serviceUnavailable:"That service is briefly unavailable. Try again shortly.",streamIncomplete:"The connection dropped mid-answer. Tap retry to continue.",unknown:"Something went wrong. Please try again."});function Qe(e){return Je[e]}n(Qe,"userFacingError");function ee(e,t,r){Object.defineProperty(e,t,{value:r,enumerable:false,writable:false,configurable:false});}n(ee,"defineHidden");var Ze=/^[a-z][a-z0-9_]{0,63}$/;function x(e,t){let r=P(t?.wireCode,t?.wireEnvelope),o={code:e,category:G(e),retryable:t?.retryable??Z(e),displayMessage:Qe(e)};if(t?.httpStatus!==void 0&&(o.httpStatus=t.httpStatus),t?.requestId&&(o.requestId=t.requestId),typeof t?.reasonCode=="string"&&Ze.test(t.reasonCode)&&(o.reasonCode=t.reasonCode),r);return t?.wireMessage&&ee(o,"wireMessage",t.wireMessage),t?.raw!==void 0&&t.raw!==null&&ee(o,"raw",t.raw),Object.freeze(o)}n(x,"makeEverfurError");var et="x-request-id";function I(e,t,r){let o=tt(t),i=o?X(o):J(e),a=rt(t);return x(i,{httpStatus:e,...nt(t)?{retryable:true}:{},...r?{requestId:r}:{},...o?{wireCode:o}:{},...te(t)?{reasonCode:te(t)}:{},...a?{wireMessage:a}:{},...t!=null?{raw:t}:{}})}n(I,"errorFromResponse");function re(e){return x("internalError",{retryable:true,wireMessage:ot(e)})}n(re,"networkError");function ne(e){let t=e.headers.get(et);return typeof t=="string"&&t.length>0?t:null}n(ne,"requestIdOf");function oe(){let e=globalThis.fetch;if(typeof e!="function")throw new s("missing-peer-dependency","global fetch is unavailable; provide config.transport or an injected fetch implementation");return e}n(oe,"getGlobalFetch");function te(e){let t=e,r=t?.error?.reason_code??t?.reason_code;return typeof r=="string"&&r.length>0?r:null}n(te,"extractReasonCode");function tt(e){let t=e,r=t?.error?.code??t?.code;return typeof r=="string"&&r.length>0?r:null}n(tt,"extractWireCode");function rt(e){let t=e,r=t?.error?.message??t?.message;return typeof r=="string"&&r.length>0?r:null}n(rt,"extractWireMessage");function nt(e){let t=e;return t?.error?.retryable===true||t?.retryable===true}n(nt,"extractRetryable");function ot(e){return e instanceof Error?e.message:typeof e=="string"?e:"network request failed"}n(ot,"describeCause");var ie=Object.freeze(["member.linked","member.unlinked","visit.booked","visit.cancelled","visit.completed","visit.no_show","record_request.updated","record.ready","webhook_endpoint.test","chat.follow_up_due","chat.urgency.flagged","pet.vaccination.due","visit.rescheduled","visit.reminder","visit.followup_sent","chat.reminder_due","record.activation","visit.message_received","visit.ended"]),it=Object.freeze(["member.linked","member.unlinked","chat.urgency.flagged","webhook_endpoint.test"]);function ae(e){return typeof e=="string"&&ie.includes(e)}n(ae,"isEverfurWebhookEventType");function at(e){return ae(e.type)}n(at,"isEverfurWebhookEvent");var w=Object.freeze(["pet.profile.updated","pet.incident.reported","pet.behavior_note.added","pet.service_score.recorded","pet.deleted","member.status_changed","member.deleted"]);var se=128;function S(e){let t=typeof e=="string"?[...e].length:0;if(typeof e!="string"||t<1||t>se)throw new s("invalid-argument",`user_ref must be 1..${se} characters`);if(e.trim().length===0)throw new s("invalid-argument","user_ref must not be blank: the server strips surrounding whitespace before validating, so a whitespace-only value arrives empty and is rejected as required.");if(e!==e.trim())throw new s("invalid-argument","user_ref must not have leading or trailing whitespace: the server strips it, so padded and unpadded forms of the same id resolve to ONE user. Pass the exact id you want to key on.");if(e.includes("@"))throw new s("invalid-argument","user_ref must not contain '@'");if(!st(e))throw new s("invalid-argument","user_ref must be printable (no control characters)");return e}n(S,"assertValidUserRef");function st(e){return !lt.test(e)}n(st,"isPrintable");var lt=/[\p{Cc}\p{Cf}\p{Cs}\p{Co}\p{Cn}\p{Zl}\p{Zp}]|(?!\u0020)[\p{Zs}]/u;function le(e){for(let t=0;t<e.length;t+=1){let r=e.charCodeAt(t);if(r>=55296&&r<=56319){let o=e.charCodeAt(t+1);if(!(o>=56320&&o<=57343))return true;t+=1;}else if(r>=56320&&r<=57343)return true}return false}n(le,"hasLoneSurrogate");function de(e){return [...e].length}n(de,"serverLength");var ue=Object.freeze({dog:"dog",canine:"dog",k9:"dog",puppy:"dog",cat:"cat",feline:"cat",kitten:"cat"});function ce(e){if(typeof e!="string")return null;let t=e.trim().toLowerCase();return Object.prototype.hasOwnProperty.call(ue,t)?ue[t]:null}n(ce,"canonicalPetSpecies");var pe=50,dt=128,A=120,fe=120,ut=2e3,ye=120,ct=80,pt=new Set(["male","female","unknown"]),ft=new Set(["day","month","year"]),yt=new Set(["low","medium","high","athletic"]),mt=new Set(["indoor","outdoor","both"]),vt=new Set(["mild","moderate","severe"]),gt=/^(\d{4})-(\d{2})-(\d{2})$/,ve=[["sex","sex"],["spayedNeutered","spayed_neutered"],["birthDate","birth_date"],["birthDatePrecision","birth_date_precision"],["activityLevel","activity_level"],["indoorOutdoor","indoor_outdoor"],["foodBrand","food_brand"],["foodType","food_type"],["microchipId","microchip_id"]],ge=[["allergies","allergies"],["medications","medications"],["supplements","supplements"],["conditions","conditions"]];Object.freeze([...ve,...ge].map(([e])=>e));function _t(e){let t=gt.exec(e);if(t===null)return false;let[r,o,i]=[Number(t[1]),Number(t[2]),Number(t[3])],a=new Date(Date.UTC(r,o-1,i));return a.getUTCFullYear()===r&&a.getUTCMonth()===o-1&&a.getUTCDate()===i}n(_t,"isRealDate");var b=n(e=>(t,r)=>typeof r=="string"&&e.has(r)?null:`${t} must be one of ${[...e].join(", ")}`,"oneOf"),ht=n((e,t)=>typeof t=="boolean"?null:`${e} must be true or false`,"boolean"),C=n((e,t)=>typeof t=="string"&&_t(t)?null:`${e} must be a real date written YYYY-MM-DD`,"date"),v=n((e,t={})=>(r,o)=>{if(typeof o!="string")return `${r} must be a string`;if(le(o))return `${r} contains an unpaired surrogate and cannot be encoded`;let i=t.trimmed?o.trim():o;if(t.required&&i.length===0)return `${r} is required and must not be blank`;let a=de(i);return a<=e?null:`${r} is ${a} characters; the server accepts at most ${e}`},"text"),bt={sex:b(pt),spayedNeutered:ht,birthDate:C,birthDatePrecision:b(ft),activityLevel:b(yt),indoorOutdoor:b(mt),foodBrand:v(ye),foodType:v(ye),microchipId:v(ct)},D=["ref","ref",false,v(dt,{required:true,trimmed:true})],F=["notes","notes",false,v(ut,{trimmed:true})],me=[D,["name","name",true,v(A,{required:true,trimmed:true})],["dose","dose",false,v(fe,{trimmed:true})],["frequency","frequency",false,v(fe,{trimmed:true})],["startDate","start_date",false,C],["endDate","end_date",false,C],F],Et={allergies:[D,["allergen","allergen",true,v(A,{required:true,trimmed:true})],["severity","severity",false,b(vt)],F],medications:me,supplements:me,conditions:[D,["conditionName","condition_name",true,v(A,{required:true,trimmed:true})],["diagnosedDate","diagnosed_date",false,C],F]};function Rt(e,t,r){let o=`${e}[${t}]`;if(typeof r!="object"||r===null||Array.isArray(r))return {error:`${o} must be an object`};let i=r,a={};for(let[u,c,f,y]of Et[e]){let m=i[u];if(m==null){if(f)return {error:`${o}.${u} is required`};m===null&&(a[c]=null);continue}let g=y(`${o}.${u}`,m);if(g!==null)return {error:g};a[c]=m;}let l=a.start_date,d=a.end_date;return typeof l=="string"&&typeof d=="string"&&d<l?{error:`${o}.endDate must not be before startDate`}:{item:a}}n(Rt,"itemToWire");function Pt(e,t){if(!Array.isArray(t))return {error:`${e} must be an array (send [] to clear it)`};if(t.length>pe)return {error:`${e} has ${t.length} items; the server accepts at most ${pe}`};let r=[],o=new Set;for(let i=0;i<t.length;i+=1){let a=Rt(e,i,t[i]);if("error"in a)return a;let l=a.item.ref;if(typeof l=="string"){let d=l.trim();if(o.has(d))return {error:`${e}: ref ${JSON.stringify(d)} is used twice; a ref names one item`};o.add(d);}r.push(a.item);}return {items:r}}n(Pt,"listToWire");function _e(e,t){let r=e,o={};for(let[l,d]of ve){let u=r[l];if(u!==void 0){if(u!==null){let c=bt[l](l,u);if(c!==null)return {error:c}}o[d]=u;}}let i=r.birthDate!==void 0,a=r.birthDatePrecision!==void 0;if(i!==a||i&&r.birthDate===null!=(r.birthDatePrecision===null))return {error:"birthDate and birthDatePrecision must be sent together, both set or both null"};for(let[l,d]of ge){let u=r[l];if(u===void 0)continue;let c=Pt(l,u);if("error"in c)return c;o[d]=c.items;}return Object.keys(o).length>0&&t!==void 0&&ce(t)===null?{error:"health fields need a pet Everfur reads as a dog or a cat (dog, canine, k9, puppy, cat, feline, kitten)"}:{body:o}}n(_e,"petHealthToWire");var wt=["sk_partner_","rk_partner_"];function he(e,t){if(typeof e!="string"||e.length===0)throw new s("invalid-argument","partnerSecretKey is required");if(e.startsWith("pk_"))throw new s("invalid-argument",`partnerSecretKey is a publishable key (pk_...): ${t} needs your secret key, server side only`);if(!wt.some(r=>e.startsWith(r)))throw new s("invalid-argument","partnerSecretKey must be an sk_partner_ secret key or an rk_partner_ restricted key")}n(he,"assertServerSecretKey");var St=[["name","name"],["species","species"],["breed","breed"],["ageYears","age_years"],["weightKg","weight_kg"],["partnerLabelInstructions","partner_label_instructions"]];function be(e){if(typeof e!="object"||e===null||Array.isArray(e))throw new s("invalid-argument","the pet profile must be an object");let t={};for(let[o,i]of St)e[o]!==void 0&&(t[i]=e[o]);let r=_e(e,e.species);if("error"in r)throw new s("invalid-argument",r.error);return Object.assign(t,r.body)}n(be,"partnerPetProfileBody");var kt=/^[\x21-\x7e]{1,255}$/,Ee=32*1024,Ot=/^\d{4}-\d{2}-\d{2}[Tt ]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:[Zz]|[+-]\d{2}:?\d{2})$/,Tt=3e4,xt=Object.freeze({"pet.profile.updated":{subject:"pet",schemaVersions:[1,2]},"pet.incident.reported":{subject:"pet",schemaVersions:[1]},"pet.behavior_note.added":{subject:"pet",schemaVersions:[1]},"pet.service_score.recorded":{subject:"pet",schemaVersions:[1]},"pet.deleted":{subject:"pet",schemaVersions:[1]},"member.status_changed":{subject:"member",schemaVersions:[1]},"member.deleted":{subject:"member",schemaVersions:[1]}});async function It(e,t,r){let o=r??crypto.randomUUID();if(typeof o!="string"||!kt.test(o))throw new s("invalid-argument","idempotencyKey must be 1 to 255 visible ASCII characters (no spaces, no control or non-ASCII characters)");he(e.partnerSecretKey,"sending events");let i=Nt(At(t)),a=e.fetchImpl??oe(),l=`${W(e.apiBaseUrl)}/partners/events`,d={...H({sdkVersion:V,platform:B,contractVersion:e.contractVersion??q}),accept:"application/json","content-type":"application/json","idempotency-key":o,"x-everfur-partner-secret-key":e.partnerSecretKey},u=new AbortController,c=setTimeout(()=>u.abort(),Tt),f;try{f=await a(l,{method:"POST",headers:d,body:i,signal:u.signal});}catch(Pe){return _(re(Pe))}finally{clearTimeout(c);}let y=null;try{y=await f.json();}catch{y=null;}let m=ne(f);if(!f.ok)return _(I(f.status,y,m));let g=jt(y,o);return g?k(g):_(I(502,{error:{code:"INTERNAL_ERROR"}},m))}n(It,"sendPartnerEvent");function Re(e){return typeof e=="string"&&w.includes(e)}n(Re,"isInboundType");function At(e){if(typeof e!="object"||e===null)throw new s("invalid-argument","event is required");if(!Re(e.type))throw new s("invalid-argument",`event.type must be one of ${w.join(", ")}`);let t=xt[e.type],r=e.schemaVersion??1;if(typeof r!="number"||!t.schemaVersions.includes(r))throw new s("invalid-argument",`event.schemaVersion must be one of ${t.schemaVersions.join(", ")} for ${e.type}`);let o=S(e.userRef);if(t.subject==="pet"&&e.petRef===void 0)throw new s("invalid-argument",`event.petRef is required for ${e.type}`);if(t.subject==="member"&&e.petRef!==void 0)throw new s("invalid-argument",`event.petRef is not accepted on ${e.type}`);let i=e.petRef===void 0?void 0:Dt(e.petRef);if(typeof e.data!="object"||e.data===null||Array.isArray(e.data))throw new s("invalid-argument","event.data must be an object");let a=e.type==="pet.profile.updated"&&r===2?be(e.data):e.data,l={type:e.type,schema_version:r,user_ref:o,occurred_at:Ft(e.occurredAt),data:a};return i!==void 0&&(l.pet_ref=i),l}n(At,"buildBody");function Dt(e){try{return S(e)}catch(t){throw t instanceof s?new s("invalid-argument",`event.petRef follows the user_ref rule: ${t.message}`):t}}n(Dt,"assertValidPetRef");function Ft(e){if(typeof e=="string"&&!Ot.test(e))throw new s("invalid-argument","event.occurredAt must be a Date or an ISO 8601 date-time with an explicit offset (Z or +05:30)");let t=e instanceof Date?e:typeof e=="string"?new Date(e):new Date(Number.NaN);if(Number.isNaN(t.getTime()))throw new s("invalid-argument","event.occurredAt must be a Date or an ISO 8601 date-time with an explicit offset (Z or +05:30)");return t.toISOString()}n(Ft,"occurredAtIso");function Nt(e){let t;try{t=JSON.stringify(e);}catch{throw new s("invalid-argument","event.data must be JSON-serialisable")}let r=new TextEncoder().encode(t).byteLength;if(r>Ee)throw new s("invalid-argument",`the event is ${r} bytes once serialised; Everfur accepts at most ${Ee} (32 KB)`);return t}n(Nt,"serialize");function jt(e,t){if(typeof e!="object"||e===null)return null;let r=e,o=r.id,i=r.type,a=r.schema_version,l=r.user_ref,d=r.pet_ref??null,u=r.occurred_at,c=r.received_at,f=r.status,y=r.livemode;return typeof o!="string"||o.length===0||!Re(i)||typeof a!="number"||typeof l!="string"||d!==null&&typeof d!="string"||typeof u!="string"||typeof c!="string"||typeof f!="string"||typeof y!="boolean"?null:Object.freeze({id:o,type:i,schemaVersion:a,userRef:l,petRef:d,occurredAt:u,receivedAt:c,status:f,livemode:y,idempotencyKey:t})}n(jt,"parseReceipt");
|
|
2
|
+
exports.DEFAULT_WEBHOOK_TOLERANCE_SECONDS=N;exports.EVERFUR_SIGNATURE_HEADER=ke;exports.EVERFUR_WEBHOOK_EVENT_TYPES=ie;exports.EVERFUR_WEBHOOK_ONLY_EVENT_TYPES=it;exports.EverfurWebhookVerificationError=p;exports.PARTNER_INBOUND_EVENT_TYPES=w;exports.constructEvent=Ie;exports.generateTestSignatureHeader=Ae;exports.isEverfurWebhookEvent=at;exports.isEverfurWebhookEventType=ae;exports.sendPartnerEvent=It;
|