@everfur/sdk 0.1.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 +74 -0
- package/LICENSE +21 -0
- package/README.md +161 -0
- package/animations/package.json +8 -0
- package/chat/package.json +8 -0
- package/client/package.json +8 -0
- package/core/package.json +8 -0
- package/dist/CameraPort-Cv31Pz7g.d.cts +29 -0
- package/dist/CameraPort-Cv31Pz7g.d.ts +29 -0
- package/dist/ChatController-CKdBvPj2.d.ts +146 -0
- package/dist/ChatController-CpUMvvZf.d.cts +146 -0
- package/dist/EverfurResult-D92-uL82.d.cts +240 -0
- package/dist/EverfurResult-D92-uL82.d.ts +240 -0
- package/dist/FilePort-BabWrv7I.d.cts +22 -0
- package/dist/FilePort-BabWrv7I.d.ts +22 -0
- package/dist/PhotoController-BItt5M7u.d.cts +43 -0
- package/dist/PhotoController-D8zMTdcW.d.ts +43 -0
- package/dist/TelemetryPort-BDNr00hu.d.cts +12 -0
- package/dist/TelemetryPort-BDNr00hu.d.ts +12 -0
- package/dist/animations/index.cjs +1997 -0
- package/dist/animations/index.d.cts +517 -0
- package/dist/animations/index.d.ts +517 -0
- package/dist/animations/index.js +1972 -0
- package/dist/cacheEpoch-DknKn3S0.d.cts +36 -0
- package/dist/cacheEpoch-DknKn3S0.d.ts +36 -0
- package/dist/chat/index.cjs +1170 -0
- package/dist/chat/index.d.cts +59 -0
- package/dist/chat/index.d.ts +59 -0
- package/dist/chat/index.js +1167 -0
- package/dist/client/index.cjs +2317 -0
- package/dist/client/index.d.cts +65 -0
- package/dist/client/index.d.ts +65 -0
- package/dist/client/index.js +2217 -0
- package/dist/config-BSjBdxrZ.d.cts +501 -0
- package/dist/config-CiJ0PVBB.d.ts +501 -0
- package/dist/core/index.cjs +3175 -0
- package/dist/core/index.d.cts +70 -0
- package/dist/core/index.d.ts +70 -0
- package/dist/core/index.js +3163 -0
- package/dist/identity-Brl-lDd6.d.cts +91 -0
- package/dist/identity-DK9zORrG.d.ts +91 -0
- package/dist/ids-CJ1S6adf.d.cts +46 -0
- package/dist/ids-CJ1S6adf.d.ts +46 -0
- package/dist/index.cjs +4488 -0
- package/dist/index.d.cts +156 -0
- package/dist/index.d.ts +156 -0
- package/dist/index.js +4464 -0
- package/dist/petsRepository-BEGb97M9.d.cts +326 -0
- package/dist/petsRepository-Bu18r2kK.d.ts +326 -0
- package/dist/photo/index.cjs +2189 -0
- package/dist/photo/index.d.cts +43 -0
- package/dist/photo/index.d.ts +43 -0
- package/dist/photo/index.js +2186 -0
- package/dist/projection-CeIUsbSk.d.cts +8 -0
- package/dist/projection-CeIUsbSk.d.ts +8 -0
- package/dist/records/index.cjs +2840 -0
- package/dist/records/index.d.cts +224 -0
- package/dist/records/index.d.ts +224 -0
- package/dist/records/index.js +2834 -0
- package/dist/requestFunnel-DuUH-kAe.d.cts +28 -0
- package/dist/requestFunnel-dio5OmR9.d.ts +28 -0
- package/dist/resolve-Dq_4_agU.d.cts +86 -0
- package/dist/resolve-Dq_4_agU.d.ts +86 -0
- package/dist/runtime-BgQnA594.d.cts +349 -0
- package/dist/runtime-CBA-LvdM.d.ts +349 -0
- package/dist/server/index.cjs +533 -0
- package/dist/server/index.d.cts +48 -0
- package/dist/server/index.d.ts +48 -0
- package/dist/server/index.js +530 -0
- package/dist/testing/index.cjs +825 -0
- package/dist/testing/index.d.cts +113 -0
- package/dist/testing/index.d.ts +113 -0
- package/dist/testing/index.js +822 -0
- package/dist/testing/rn/index.cjs +449 -0
- package/dist/testing/rn/index.d.cts +49 -0
- package/dist/testing/rn/index.d.ts +49 -0
- package/dist/testing/rn/index.js +444 -0
- package/dist/video/index.cjs +1941 -0
- package/dist/video/index.d.cts +66 -0
- package/dist/video/index.d.ts +66 -0
- package/dist/video/index.js +1938 -0
- package/package.json +311 -0
- package/photo/package.json +8 -0
- package/records/package.json +8 -0
- package/server/device-blocked.cjs +15 -0
- package/server/package.json +9 -0
- package/testing/package.json +8 -0
- package/testing/rn/package.json +8 -0
- package/video/package.json +8 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import { E as EntitlementDecision, b as CapabilityName } from './resolve-Dq_4_agU.js';
|
|
2
|
+
import { C as ClientBranding, F as FetchEntitlementsArgs, c as EntitlementResolution, w as PetProfileInput, R as RegisteredPet } from './petsRepository-Bu18r2kK.js';
|
|
3
|
+
import { E as EverfurResult } from './EverfurResult-D92-uL82.js';
|
|
4
|
+
import { A as AuthContext, T as TokenProvider } from './identity-DK9zORrG.js';
|
|
5
|
+
import { U as UserRef, P as PetRef, a as ConversationId } from './ids-CJ1S6adf.js';
|
|
6
|
+
import { T as TransportPort, k as EventSourceFactory } from './config-CiJ0PVBB.js';
|
|
7
|
+
import { I as ImageCachePort, K as KvPort } from './cacheEpoch-DknKn3S0.js';
|
|
8
|
+
import { T as TelemetryPort } from './TelemetryPort-BDNr00hu.js';
|
|
9
|
+
import { E as ErrorPolicyPort, C as ChatController } from './ChatController-CKdBvPj2.js';
|
|
10
|
+
import { F as FileHandle } from './FilePort-BabWrv7I.js';
|
|
11
|
+
import { C as CameraPort } from './CameraPort-Cv31Pz7g.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Opt-in encrypted secret storage. Backed by a Keychain / Keystore native peer through an rn-layer adapter.
|
|
15
|
+
* Absent by default; the SDK never persists a credential unless the host supplies this port.
|
|
16
|
+
*/
|
|
17
|
+
interface SecureStorePort {
|
|
18
|
+
readonly isAvailable: boolean;
|
|
19
|
+
getSecret(key: string): Promise<string | null>;
|
|
20
|
+
setSecret(key: string, value: string): Promise<void>;
|
|
21
|
+
deleteSecret(key: string): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The safe default: NO persistence. `currentToken()` lives only in IdentityProvider memory (cleared on
|
|
25
|
+
* setUser / clear). Attempting to persist without an explicit port fails loud so a partner opts in on
|
|
26
|
+
* purpose rather than silently leaking a token to disk.
|
|
27
|
+
*/
|
|
28
|
+
declare const NULL_SECURE_STORE: SecureStorePort;
|
|
29
|
+
|
|
30
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
31
|
+
/**
|
|
32
|
+
* One structured, correlated log record. `context` is key-allowlisted and value-scrubbed by createLogPort
|
|
33
|
+
* BEFORE it reaches any sink; the raw untrusted `wireMessage` never flows into a rendered node.
|
|
34
|
+
*/
|
|
35
|
+
interface LogRecord {
|
|
36
|
+
readonly level: LogLevel;
|
|
37
|
+
/** Stable machine id, e.g. 'chat.stream.error' | 'transport.retry'. */
|
|
38
|
+
readonly event: string;
|
|
39
|
+
/** One id per request; also sent as X-Everfur-Correlation-Id in debug mode. */
|
|
40
|
+
readonly correlationId?: string;
|
|
41
|
+
readonly code?: string;
|
|
42
|
+
readonly httpStatus?: number;
|
|
43
|
+
readonly attempt?: number;
|
|
44
|
+
readonly latencyMs?: number;
|
|
45
|
+
/** Key-allowlisted + value-scrubbed before ANY sink. */
|
|
46
|
+
readonly context?: Record<string, unknown>;
|
|
47
|
+
}
|
|
48
|
+
/** The sink partners inject. It only ever receives already-redacted records. */
|
|
49
|
+
interface LogSink {
|
|
50
|
+
emit(record: Readonly<LogRecord>): void;
|
|
51
|
+
}
|
|
52
|
+
|
|
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
|
+
/**
|
|
143
|
+
* The public init config the host passes at EverfurProvider mount: the lean client subset
|
|
144
|
+
* (publishableKey / apiBaseUrl / contractVersion / transport / debug) PLUS the host-seam ports. The client
|
|
145
|
+
* layer validates only its own subset; the ports below are consumed here in the core runtime. The rn
|
|
146
|
+
* facade declares a structurally identical `EverfurConfig`, which is assignable to this type.
|
|
147
|
+
*/
|
|
148
|
+
interface EverfurRuntimeConfig {
|
|
149
|
+
readonly publishableKey: string;
|
|
150
|
+
readonly apiBaseUrl?: string;
|
|
151
|
+
readonly contractVersion?: string;
|
|
152
|
+
/** Non-secret durable KV; a token is NEVER written through it. In-memory fallback when absent. */
|
|
153
|
+
readonly storage?: KvPort;
|
|
154
|
+
/** Opt-in encrypted storage, the ONLY port a token may cross to disk. Omit for memory-only tokens. */
|
|
155
|
+
readonly secureStore?: SecureStorePort;
|
|
156
|
+
/** Analytics sink; the SDK never imports PostHog / Sentry. No-op default. */
|
|
157
|
+
readonly telemetry?: TelemetryPort;
|
|
158
|
+
/** Receives ALREADY-redacted structured log records. */
|
|
159
|
+
readonly logSink?: LogSink;
|
|
160
|
+
/** Recovery decisions the host can override; a default policy is applied when absent. */
|
|
161
|
+
readonly errorPolicy?: ErrorPolicyPort;
|
|
162
|
+
/** Test seam; production builds the real transport from apiBaseUrl. */
|
|
163
|
+
readonly transport?: TransportPort;
|
|
164
|
+
/**
|
|
165
|
+
* Native capture seam for video / photo (an rn adapter over the camera peer). Absent =>
|
|
166
|
+
* `unavailableCamera`, so those surfaces render the deliberate capture-unavailable state, never a crash.
|
|
167
|
+
*/
|
|
168
|
+
readonly camera?: CameraPort;
|
|
169
|
+
/**
|
|
170
|
+
* Native presigned-PUT seam for video / photo uploads. Absent => `unavailableUpload` (rejects), so a
|
|
171
|
+
* submit settles to a handled `mediaUploadFailed` rather than silently succeeding.
|
|
172
|
+
*/
|
|
173
|
+
readonly upload?: UploadPort;
|
|
174
|
+
/**
|
|
175
|
+
* Native S3-multipart seam for records document upload. Absent => an unavailable transport (rejects), so
|
|
176
|
+
* records READS still work and only the upload action settles to a handled failure.
|
|
177
|
+
*/
|
|
178
|
+
readonly uploadTransport?: UploadTransport;
|
|
179
|
+
/**
|
|
180
|
+
* Platform image-cache seam for the animations fleet-wide epoch purge (rn: expo-image clear*). Absent =>
|
|
181
|
+
* a no-op cache (the cosmetic purge never fires); every other animations path is unaffected.
|
|
182
|
+
*/
|
|
183
|
+
readonly imageCache?: ImageCachePort;
|
|
184
|
+
/** Structured, redacted LogPort events when true. */
|
|
185
|
+
readonly debug?: boolean;
|
|
186
|
+
}
|
|
187
|
+
/** Identity handed to the runtime: the partner's opaque user id + a lazy token minter (SPEC-00 §4.3). */
|
|
188
|
+
interface RuntimeUser {
|
|
189
|
+
readonly userRef: UserRef;
|
|
190
|
+
readonly getToken: TokenProvider;
|
|
191
|
+
}
|
|
192
|
+
/** Opaque, permissive theme input; server branding merges ON TOP. Sanitized downstream. */
|
|
193
|
+
type RuntimeTheme = Readonly<Record<string, string | number | boolean>>;
|
|
194
|
+
interface CreateEverfurRuntimeInput {
|
|
195
|
+
readonly config: EverfurRuntimeConfig;
|
|
196
|
+
/** null => general (anonymous) mode: pk alone on the wire. */
|
|
197
|
+
readonly user: RuntimeUser | null;
|
|
198
|
+
readonly activePet: PetRef | null;
|
|
199
|
+
readonly theme: RuntimeTheme | null;
|
|
200
|
+
}
|
|
201
|
+
/** Scope key for a chat controller: two hooks with the same scope share ONE ref-counted controller. */
|
|
202
|
+
interface ChatScope {
|
|
203
|
+
readonly userRef: UserRef | null;
|
|
204
|
+
readonly petRef: PetRef | null;
|
|
205
|
+
readonly conversationId: ConversationId | null;
|
|
206
|
+
}
|
|
207
|
+
/** The four optional (tree-shakeable) capabilities that self-register a controller through the registry. */
|
|
208
|
+
type CapabilityKind = 'records' | 'video' | 'photo' | 'animations';
|
|
209
|
+
/**
|
|
210
|
+
* The shared services a capability hook builds its controller from: the device AuthContext, the analytics
|
|
211
|
+
* sink, and the injected native seams. Handing these out (rather than importing every controller here) is what
|
|
212
|
+
* lets the runtime stay tree-shake-clean while every capability is still genuinely wired.
|
|
213
|
+
*/
|
|
214
|
+
interface CapabilityServices {
|
|
215
|
+
/** Build a device AuthContext for a scope (personalized bearer XOR anonymous pk). */
|
|
216
|
+
authFor(userRef: UserRef | null): AuthContext;
|
|
217
|
+
readonly telemetry: TelemetryPort;
|
|
218
|
+
readonly errorPolicy: ErrorPolicyPort | undefined;
|
|
219
|
+
readonly camera: CameraPort;
|
|
220
|
+
readonly upload: UploadPort;
|
|
221
|
+
readonly uploadTransport: UploadTransport;
|
|
222
|
+
readonly imageCache: ImageCachePort;
|
|
223
|
+
readonly kv: KvPort;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* The ONE ref-counted capability registry (SPEC-10 §7.4). Chat (the spine) is acquired by its typed method;
|
|
227
|
+
* every optional capability is acquired through the generic `acquire`, keyed by (kind, scopeKey) under the
|
|
228
|
+
* current epoch, so two hooks with the same scope share ONE controller and the last release disposes it. A
|
|
229
|
+
* user / pet re-scope bumps the epoch, disposing every open controller so a fresh one is keyed to the new
|
|
230
|
+
* scope. The controller type is inferred from `create`, so a capability hook binds BY NAME (its kind + its own
|
|
231
|
+
* factory) with NO cast, while this module never statically names a media capability controller.
|
|
232
|
+
*/
|
|
233
|
+
interface CapabilityRegistry {
|
|
234
|
+
/** The shared services each capability hook builds its controller from (native seams + auth + telemetry). */
|
|
235
|
+
readonly services: CapabilityServices;
|
|
236
|
+
/** Chat is the spine capability; the registry constructs + ref-counts it directly. */
|
|
237
|
+
acquireChat(scope: ChatScope): ChatController;
|
|
238
|
+
releaseChat(controller: ChatController): void;
|
|
239
|
+
/**
|
|
240
|
+
* Ref-counted acquire for the tree-shakeable capabilities. Two calls with the same (kind, scopeKey) under
|
|
241
|
+
* the current epoch share ONE controller; the last release disposes it via `destroy`.
|
|
242
|
+
*/
|
|
243
|
+
acquire<C extends object>(kind: CapabilityKind, scopeKey: string, create: () => C, destroy: (controller: C) => void): C;
|
|
244
|
+
/** Release a controller acquired via `acquire`; the last release disposes it. */
|
|
245
|
+
release(controller: object): void;
|
|
246
|
+
}
|
|
247
|
+
/** @deprecated Pre-capability alias retained for back-compat; the registry is a full CapabilityRegistry. */
|
|
248
|
+
type ChatControllerRegistry = CapabilityRegistry;
|
|
249
|
+
/** The already-resolved server verdict the capability hooks render (never re-folded here). */
|
|
250
|
+
interface EntitlementSnapshot {
|
|
251
|
+
readonly decisions: readonly EntitlementDecision[];
|
|
252
|
+
/** true during the first resolve or while serving a stale value -> skeleton, never a flash of UI. */
|
|
253
|
+
readonly isPending: boolean;
|
|
254
|
+
/**
|
|
255
|
+
* Server-driven theme branding from the SAME entitlements body (orthogonal to decisions). null/absent =>
|
|
256
|
+
* the compiled Everfur default theme. The rn EverfurThemeProvider reads this off the store snapshot and
|
|
257
|
+
* feeds it to resolveTheme; the SERVER stays authoritative for capabilities regardless of branding.
|
|
258
|
+
*/
|
|
259
|
+
readonly branding?: ClientBranding | null;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Framework-free entitlement store bound by `useCapability` through useSyncExternalStore. `getSnapshot`
|
|
263
|
+
* returns a STABLE reference until a real change (tearing-safe). `subscribe`/`getSnapshot` are closures,
|
|
264
|
+
* safe to pass as bare references.
|
|
265
|
+
*/
|
|
266
|
+
interface EntitlementStore {
|
|
267
|
+
subscribe(listener: () => void): () => void;
|
|
268
|
+
getSnapshot(): EntitlementSnapshot;
|
|
269
|
+
}
|
|
270
|
+
interface EverfurRuntime {
|
|
271
|
+
readonly registry: CapabilityRegistry;
|
|
272
|
+
/**
|
|
273
|
+
* True once `dispose()` has run. Every verb early-returns after that, so a host holding a disposed
|
|
274
|
+
* runtime silently gets nothing: the entitlement store never advances and every gate renders its
|
|
275
|
+
* off-state forever. React StrictMode's dev double-mount runs the unmount cleanup once, which makes this
|
|
276
|
+
* reachable in ordinary development, so the provider checks it and rebuilds rather than republishing a
|
|
277
|
+
* dead runtime.
|
|
278
|
+
*/
|
|
279
|
+
readonly isDisposed: boolean;
|
|
280
|
+
readonly entitlements: EntitlementStore;
|
|
281
|
+
/** null => logout: drops the cached bearer and re-scopes every open capability. */
|
|
282
|
+
setUser(user: RuntimeUser | null): void;
|
|
283
|
+
/**
|
|
284
|
+
* Full sign-out: setUser(null) (drop the bearer + re-scope every open capability), and ADDITIONALLY sweep
|
|
285
|
+
* the SDK's genuinely PER-USER non-secret durable KV keys so the next user does not inherit the previous
|
|
286
|
+
* user's cached state. The per-user set is the explicit allowlist `PER_USER_KV_KEYS`, which is EMPTY today:
|
|
287
|
+
* no SDK state persisted through KvPort is per-user yet. Device-global keys (manifest last-known-good,
|
|
288
|
+
* petState cacheEpoch) are deliberately NOT swept. The bearer never enters KV (KvPort privacy invariant),
|
|
289
|
+
* so this touches only non-secret durable state. Returns a promise so a host can await the sweep before
|
|
290
|
+
* calling `setUser(nextUser)`.
|
|
291
|
+
*/
|
|
292
|
+
logout(): Promise<void>;
|
|
293
|
+
/** Re-scopes pet-bound controllers in the same commit. */
|
|
294
|
+
setActivePet(pet: PetRef | null): void;
|
|
295
|
+
/**
|
|
296
|
+
* Register (or update) the widget pet profile the records and consent routes assume already exists.
|
|
297
|
+
*
|
|
298
|
+
* All three consent routes resolve `pet_ref` through the server's `_resolve_pet_id`, which 404s when no
|
|
299
|
+
* widget pet exists — so consent, and therefore records, is UNREACHABLE for any pet the partner has not
|
|
300
|
+
* upserted out of band. `createPetsRepository` exists on the `@everfur/sdk/client` subpath, but that is
|
|
301
|
+
* the advanced-integrator surface and it takes a raw `AuthContext`; a partner using the provider had no
|
|
302
|
+
* way to call it. This is that way. Idempotent: the route is an upsert keyed on `pet_ref`.
|
|
303
|
+
*/
|
|
304
|
+
registerPet(pet: PetRef, profile?: PetProfileInput): Promise<EverfurResult<RegisteredPet>>;
|
|
305
|
+
/**
|
|
306
|
+
* Replace the rendered entitlement verdict (a future poller / a manifest refresh). The SERVER stays
|
|
307
|
+
* authoritative: this only feeds the render store, so the pending/enabled paths become reachable while a
|
|
308
|
+
* 403 on any request still settles the controller to its denied state.
|
|
309
|
+
*/
|
|
310
|
+
updateEntitlements(next: EntitlementSnapshot): void;
|
|
311
|
+
/** Navigate / mount a prebuilt capability screen (host-routed). No-op at the spine. */
|
|
312
|
+
open(capability: CapabilityName): void;
|
|
313
|
+
/**
|
|
314
|
+
* Idempotent teardown: aborts in-flight capability requests, tears down every open SSE stream, and stops
|
|
315
|
+
* the entitlement poller (an in-flight entitlement poll's result is DROPPED, not aborted mid-flight).
|
|
316
|
+
*/
|
|
317
|
+
dispose(): void;
|
|
318
|
+
}
|
|
319
|
+
/** Runtime-construction options, distinct from the partner-facing config (host wiring / test seams). */
|
|
320
|
+
interface CreateRuntimeOptions {
|
|
321
|
+
/**
|
|
322
|
+
* Whether to start the entitlement poller. Default: start ONLY when the transport was NOT injected (a real,
|
|
323
|
+
* base-URL runtime). An injected transport is the test seam, so auto-start stays OFF to keep MockTransport
|
|
324
|
+
* suites network-free; pass `true` to exercise the wired poller against a MockTransport.
|
|
325
|
+
*/
|
|
326
|
+
readonly startEntitlementPolling?: boolean;
|
|
327
|
+
/** Test seam: an injected scheduler so a suite can drive the entitlement re-poll timer deterministically. */
|
|
328
|
+
readonly pollScheduler?: PollScheduler;
|
|
329
|
+
/**
|
|
330
|
+
* Host-wiring seam: the EventSource factory the built HTTP transport falls back to when a streaming
|
|
331
|
+
* `res.body` is unavailable (stock RN fetch). The rn facade injects react-native-sse here so streaming works
|
|
332
|
+
* on stock React Native; core NEVER imports react-native-sse (it stays framework-free and only threads this
|
|
333
|
+
* through). Absent (web/expo, or an injected transport) => the fetch-body streaming path is used.
|
|
334
|
+
*/
|
|
335
|
+
readonly eventSourceFactory?: EventSourceFactory;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Construct the runtime once (EverfurProvider mount). Builds the transport (injected test seam, else the
|
|
339
|
+
* real HTTP transport from the resolved client config), the IdentityProvider when a user is set, the
|
|
340
|
+
* capability registry, the entitlement store, and (for a real runtime) the entitlement poller.
|
|
341
|
+
* A config that cannot be resolved (missing publishableKey, or an unresolvable / non-https base URL when
|
|
342
|
+
* no transport is injected) does NOT throw: it yields a DISABLED runtime whose transport refuses and
|
|
343
|
+
* whose every capability settles to the deliberate off-state at `disabled.level === 'sdk_config'`.
|
|
344
|
+
* @throws {EverfurConfigError} only for a supplied ACTIVE secureStore, which expresses a security
|
|
345
|
+
* intent the SDK cannot yet honour and must not silently discard.
|
|
346
|
+
*/
|
|
347
|
+
declare function createEverfurRuntime(input: CreateEverfurRuntimeInput, opts?: CreateRuntimeOptions): EverfurRuntime;
|
|
348
|
+
|
|
349
|
+
export { type CapabilityKind as C, type EntitlementPoller as E, type LogLevel as L, MIN_POLL_INTERVAL_SECONDS as M, NULL_SECURE_STORE as N, type PollScheduler as P, type RuntimeTheme as R, type SecureStorePort as S, type TimerHandle as T, type UploadPort as U, type CapabilityRegistry as a, type CapabilityServices as b, type ChatControllerRegistry as c, type ChatScope as d, type CreateEverfurRuntimeInput as e, type CreateRuntimeOptions as f, type EntitlementPollerDeps as g, type EntitlementSnapshot as h, type EntitlementStore as i, type EverfurRuntime as j, type EverfurRuntimeConfig as k, type LogRecord as l, type LogSink as m, type RuntimeUser as n, createEntitlementPoller as o, createEverfurRuntime as p, type UploadTransport as q, type PresignedPolicy as r, type UploadPolicyWire as s };
|