pulse-updates 1.3.6 → 1.3.8
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/README.md +50 -2
- package/lib/commonjs/config.js.map +1 -1
- package/lib/commonjs/init.js +23 -8
- package/lib/commonjs/init.js.map +1 -1
- package/lib/commonjs/links.js +561 -61
- package/lib/commonjs/links.js.map +1 -1
- package/lib/commonjs/track.js +241 -76
- package/lib/commonjs/track.js.map +1 -1
- package/lib/module/config.js.map +1 -1
- package/lib/module/init.js +24 -9
- package/lib/module/init.js.map +1 -1
- package/lib/module/links.js +561 -61
- package/lib/module/links.js.map +1 -1
- package/lib/module/track.js +240 -76
- package/lib/module/track.js.map +1 -1
- package/lib/typescript/config.d.ts +6 -0
- package/lib/typescript/config.d.ts.map +1 -1
- package/lib/typescript/init.d.ts +15 -6
- package/lib/typescript/init.d.ts.map +1 -1
- package/lib/typescript/links.d.ts +49 -0
- package/lib/typescript/links.d.ts.map +1 -1
- package/lib/typescript/track.d.ts +29 -7
- package/lib/typescript/track.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/config.ts +6 -0
- package/src/init.ts +33 -7
- package/src/links.ts +810 -40
- package/src/track.ts +348 -83
|
@@ -81,6 +81,33 @@ export interface AnonymousFirstOpenContext {
|
|
|
81
81
|
isEmulator?: boolean;
|
|
82
82
|
}
|
|
83
83
|
export type AnonymousFirstOpenResult = 'matched' | 'no_match' | 'ineligible' | 'deterministic_pending' | 'already_completed' | 'backoff' | 'retry_scheduled' | 'terminal_error';
|
|
84
|
+
export type AnonymousFirstOpenTerminalStatus = 'FOUND' | 'NOT_FOUND' | 'FAILURE';
|
|
85
|
+
/** Explicit receiver decision for one terminal-delivery attempt. */
|
|
86
|
+
export type AnonymousFirstOpenTerminalDisposition = 'accepted' | 'retry' | 'drop';
|
|
87
|
+
export type AnonymousFirstOpenTerminalReason = 'matched' | 'unmatched' | 'ambiguous' | 'holdout' | 'low_confidence' | 'shadow_would_route' | 'shadow_attributed' | 'analytics_attributed' | 'target_revoked' | 'disabled' | 'expired_replay' | 'invalid_request' | 'invalid_response' | 'policy_rejected';
|
|
88
|
+
/**
|
|
89
|
+
* Sanitized terminal result of the anonymous first-open rail. It deliberately carries no
|
|
90
|
+
* install-attempt id, token, device signal or raw server error. A 204 is always `no_route` and
|
|
91
|
+
* can never make the client navigate, including when Encore reports a shadow observation.
|
|
92
|
+
*/
|
|
93
|
+
export interface AnonymousFirstOpenTerminalOutcome {
|
|
94
|
+
/** Stable UUIDv4 for receiver-side deduplication of at-least-once delivery. */
|
|
95
|
+
eventId: string;
|
|
96
|
+
status: AnonymousFirstOpenTerminalStatus;
|
|
97
|
+
rail: 'fast_route' | 'no_route';
|
|
98
|
+
routed: boolean;
|
|
99
|
+
retryable: false;
|
|
100
|
+
reason: AnonymousFirstOpenTerminalReason;
|
|
101
|
+
occurredAt: string;
|
|
102
|
+
/** Present only for FOUND and copied from the already-normalized resolver result. */
|
|
103
|
+
matchBasis?: DeferredLinkMatchBasis;
|
|
104
|
+
/** Present only for FOUND, finite and clamped to [0, 1]. */
|
|
105
|
+
confidence?: number;
|
|
106
|
+
/** Optional FOUND-only campaign dimensions; strings are trimmed and bounded to 128 chars. */
|
|
107
|
+
campaignId?: string | null;
|
|
108
|
+
experimentId?: string | null;
|
|
109
|
+
variantId?: string | null;
|
|
110
|
+
}
|
|
84
111
|
export type AndroidInstallReferrerStatus = 'OK' | 'NO_TOKEN' | 'FEATURE_NOT_SUPPORTED' | 'SERVICE_UNAVAILABLE' | 'DEVELOPER_ERROR' | 'SERVICE_DISCONNECTED';
|
|
85
112
|
export interface AndroidInstallReferrerResult {
|
|
86
113
|
status: AndroidInstallReferrerStatus;
|
|
@@ -101,7 +128,13 @@ export interface DeferredLinkClientOptions<Action extends string = DeferredLinkA
|
|
|
101
128
|
allowedActions?: readonly Action[];
|
|
102
129
|
/** Actions that require both a deterministic match and a stable signed-in account. */
|
|
103
130
|
sensitiveActions?: readonly Action[];
|
|
131
|
+
/**
|
|
132
|
+
* Routing callbacks are irreversible commit boundaries: return `false` when no navigation
|
|
133
|
+
* happened. If a newer accepted capture arrives while a successful callback is pending, Pulse
|
|
134
|
+
* persists it but will not auto-route a second journey in the same client lifecycle.
|
|
135
|
+
*/
|
|
104
136
|
onDeepLink: (deepLink: string, link: ResolvedDeferredLink<Action>) => boolean | void | Promise<boolean | void>;
|
|
137
|
+
/** Same commit-boundary contract as `onDeepLink`. */
|
|
105
138
|
onAction?: (link: ResolvedDeferredLink<Action>) => boolean | void | Promise<boolean | void>;
|
|
106
139
|
accountBridge?: DeferredLinkAccountBridge<Action>;
|
|
107
140
|
isAccountReady?: () => boolean;
|
|
@@ -117,11 +150,27 @@ export interface DeferredLinkClientOptions<Action extends string = DeferredLinkA
|
|
|
117
150
|
requestTimeoutMs?: number;
|
|
118
151
|
retryBaseMs?: number;
|
|
119
152
|
retryMaxMs?: number;
|
|
153
|
+
/** Timeout for one terminal-result acknowledgement attempt. Defaults to requestTimeoutMs. */
|
|
154
|
+
terminalDeliveryTimeoutMs?: number;
|
|
120
155
|
tokenMaxAgeMs?: number;
|
|
121
156
|
recentInstallMaxAgeMs?: number;
|
|
122
157
|
autoRetry?: boolean;
|
|
123
158
|
reportResolverOutcomes?: boolean;
|
|
124
159
|
onOutcome?: (event: DeferredLinkOutcomeEvent) => void | Promise<void>;
|
|
160
|
+
/**
|
|
161
|
+
* Synchronous privacy gate evaluated before a terminal record or eventId is created. A false
|
|
162
|
+
* result or throw completes first-open matching without retaining terminal metadata.
|
|
163
|
+
*/
|
|
164
|
+
shouldQueueFirstOpenResult?: () => boolean;
|
|
165
|
+
/**
|
|
166
|
+
* Durable at-least-once terminal delivery. Return `accepted` (or legacy `true`) only after the
|
|
167
|
+
* stable eventId is durably accepted, `retry`/false to replay it, or `drop` to deliberately and
|
|
168
|
+
* durably discard it (for example after consent revocation). Throw, rejection and timeout retry
|
|
169
|
+
* the same eventId. `drop` is sticky: failed local deletion retries never re-enter the receiver.
|
|
170
|
+
* Receivers must deduplicate because a crash after acceptance can replay it. When this handler
|
|
171
|
+
* is absent no terminal record is created or retained.
|
|
172
|
+
*/
|
|
173
|
+
onFirstOpenResult?: (outcome: AnonymousFirstOpenTerminalOutcome) => AnonymousFirstOpenTerminalDisposition | boolean | Promise<AnonymousFirstOpenTerminalDisposition | boolean>;
|
|
125
174
|
onStateChange?: (state: DeferredLinkState) => void;
|
|
126
175
|
onError?: (error: unknown) => void;
|
|
127
176
|
now?: () => number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../../src/links.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../../src/links.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,13 +28,24 @@ export interface TrackOptions {
|
|
|
28
28
|
* app's registry and read as an empty metric on both sides.
|
|
29
29
|
*/
|
|
30
30
|
url: string;
|
|
31
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Request context shared with config. `context` identity mode reads deviceId/userId
|
|
33
|
+
* for backwards-compatible experiment metrics; `anonymous_installation` ignores
|
|
34
|
+
* them and reads only platform/appVersion.
|
|
35
|
+
*/
|
|
32
36
|
getContext?: () => ConfigContext;
|
|
37
|
+
/**
|
|
38
|
+
* `context` preserves the original experiment-event contract and sends the context
|
|
39
|
+
* deviceId/userId. `anonymous_installation` is an explicit privacy mode: it ignores
|
|
40
|
+
* both and sends only an SDK-minted app-scoped random UUID under the legacy wire
|
|
41
|
+
* field `deviceId`. Defaults to `context` for backwards compatibility.
|
|
42
|
+
*/
|
|
43
|
+
identityMode?: 'context' | 'anonymous_installation';
|
|
33
44
|
/** How often a non-empty queue is sent. Default 10s. */
|
|
34
45
|
flushIntervalMs?: number;
|
|
35
46
|
/** Events per request. The server refuses more than 100. */
|
|
36
47
|
maxBatch?: number;
|
|
37
|
-
/**
|
|
48
|
+
/** Best-effort events held before the oldest are dropped. Durable idempotent rows are never evicted. Default 500. */
|
|
38
49
|
maxQueue?: number;
|
|
39
50
|
/** Persists the outbox across process death. Use the same storage passed to initPulse. */
|
|
40
51
|
storage?: ConfigStorage;
|
|
@@ -42,9 +53,12 @@ export interface TrackOptions {
|
|
|
42
53
|
storageKey?: string;
|
|
43
54
|
/** Per-request timeout. Default 10s. */
|
|
44
55
|
timeoutMs?: number;
|
|
45
|
-
/** Maximum delivery attempts before
|
|
56
|
+
/** Maximum delivery attempts before a best-effort event is dropped. Durable idempotent events retry until server ACK. Default 10. */
|
|
46
57
|
maxAttempts?: number;
|
|
47
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Return false until analytics consent exists. No event is retained before consent. Consent is
|
|
60
|
+
* sampled at enqueue; an event already durably accepted remains eligible for later delivery.
|
|
61
|
+
*/
|
|
48
62
|
hasConsent?: () => boolean;
|
|
49
63
|
/** Only these property keys may leave the process. */
|
|
50
64
|
propertyAllowlist?: readonly string[];
|
|
@@ -73,12 +87,20 @@ export declare function configureTracking(opts: TrackOptions): void;
|
|
|
73
87
|
* caller has to wrap.
|
|
74
88
|
*/
|
|
75
89
|
export declare function track(event: string, props?: TrackedEventInput['props'], time?: Date): void;
|
|
90
|
+
/**
|
|
91
|
+
* Durably enqueue one logical event with a caller-owned UUID. Replaying the same id is safe:
|
|
92
|
+
* Pulse's server/read model deduplicates it, while the local outbox avoids duplicate rows that
|
|
93
|
+
* are still pending. `true` means the event is present in persistent storage, not delivered yet;
|
|
94
|
+
* once acknowledged, Track keeps it in that outbox through retries and process restarts until a
|
|
95
|
+
* successful server response removes it transactionally.
|
|
96
|
+
*/
|
|
97
|
+
export declare function trackIdempotent(eventId: string, event: string, props?: TrackedEventInput['props'], time?: Date): boolean;
|
|
76
98
|
/**
|
|
77
99
|
* Send what is queued. Returns how many events the server accepted.
|
|
78
100
|
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* after
|
|
101
|
+
* The batch remains in the durable queue while HTTP is in flight and is removed only after a
|
|
102
|
+
* successful response is also persisted locally. This intentionally permits duplicate replay
|
|
103
|
+
* after a crash, while a caller-owned event id lets the server/read model deduplicate it.
|
|
82
104
|
*/
|
|
83
105
|
export declare function flushEvents(): Promise<number>;
|
|
84
106
|
/** How many events are waiting — for a caller that wants to flush before backgrounding. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../../src/track.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ
|
|
1
|
+
{"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../../src/track.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,aAAa,CAAC;IAEjC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,wBAAwB,CAAC;IAEpD,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,qHAAqH;IACrH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,qIAAqI;IACrI,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC;IAE3B,sDAAsD;IACtD,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAEtC,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAErC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE;QAAE,gBAAgB,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,KAAK;YAAE,MAAM,EAAE,MAAM,IAAI,CAAA;SAAE,CAAA;KAAE,CAAC;IAE9G,+DAA+D;IAC/D,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAEvC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,cAAc,GAAG,YAAY,KAAK,IAAI,CAAC;IAE1F,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACrE,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAuCD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAY1D;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAE1F;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,EAClC,IAAI,CAAC,EAAE,IAAI,GACV,OAAO,CAIT;AA2GD;;;;;;GAMG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAiEnD;AAED,2FAA2F;AAC3F,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,eAAe,IAAI;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB,CAEA;AAED,qEAAqE;AACrE,wBAAgB,eAAe,IAAI,IAAI,CAStC;AAED,wBAAgB,YAAY,IAAI,IAAI,CAOnC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pulse-updates",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.8",
|
|
4
4
|
"description": "Pulse app-experience SDK for React Native: updates, config, experiments, events, decisions and first-party links",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
package/src/config.ts
CHANGED
|
@@ -50,6 +50,12 @@ export type ConfigSignatureStatus = 'not-configured' | 'verified' | 'cached-veri
|
|
|
50
50
|
export interface ConfigStorage {
|
|
51
51
|
getString(key: string): string | null | undefined;
|
|
52
52
|
set(key: string, value: string): void;
|
|
53
|
+
/**
|
|
54
|
+
* False when `set` only mirrors a write and schedules asynchronous persistence. Durable
|
|
55
|
+
* acknowledgement APIs must fail closed because process death may still lose that write.
|
|
56
|
+
* Omitted means the historical synchronous-storage contract.
|
|
57
|
+
*/
|
|
58
|
+
readonly supportsDurableSyncWrites?: boolean;
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
/**
|
package/src/init.ts
CHANGED
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
* - the urls, from the base url and the slug, which is what stops the two halves
|
|
15
15
|
* from ever addressing different apps;
|
|
16
16
|
* - platform and OS version, from React Native;
|
|
17
|
-
* - the
|
|
18
|
-
* identifier of its own
|
|
19
|
-
*
|
|
17
|
+
* - the config/experiment id, minted and persisted on first launch — an app that has
|
|
18
|
+
* a stable identifier of its own may pass it. Event tracking keeps the original
|
|
19
|
+
* context identity by default; privacy-sensitive campaign events can explicitly
|
|
20
|
+
* opt into a separate random app-scoped analytics installation UUID.
|
|
20
21
|
*
|
|
21
22
|
* Deliberately not automatic: the app version. Nothing here can read the store build
|
|
22
23
|
* reliably on both platforms, and a version guessed wrong aims a rollout at the wrong
|
|
@@ -44,6 +45,7 @@ import {
|
|
|
44
45
|
flushEvents,
|
|
45
46
|
getTrackingInfo,
|
|
46
47
|
track,
|
|
48
|
+
trackIdempotent,
|
|
47
49
|
type TrackedEventInput,
|
|
48
50
|
} from './track';
|
|
49
51
|
|
|
@@ -92,6 +94,13 @@ export interface InitPulseOptions {
|
|
|
92
94
|
eventPropertyAllowlist?: readonly string[];
|
|
93
95
|
redactEventProperties?: readonly string[];
|
|
94
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Event-envelope identity. Defaults to the backwards-compatible config context.
|
|
99
|
+
* Use `anonymous_installation` for events that carry their own experiment/variant
|
|
100
|
+
* dimensions and must never transmit the app's device or account identifier.
|
|
101
|
+
*/
|
|
102
|
+
eventIdentityMode?: 'context' | 'anonymous_installation';
|
|
103
|
+
|
|
95
104
|
/** Signed config uses the same Ed25519 public key as OTA updates. */
|
|
96
105
|
signingPublicKey?: string;
|
|
97
106
|
signingKeyId?: string;
|
|
@@ -132,6 +141,12 @@ export interface PulseClient {
|
|
|
132
141
|
configUrl: string;
|
|
133
142
|
trackUrl: string;
|
|
134
143
|
track: (event: string, props?: TrackedEventInput['props'], time?: Date) => void;
|
|
144
|
+
trackIdempotent: (
|
|
145
|
+
eventId: string,
|
|
146
|
+
event: string,
|
|
147
|
+
props?: TrackedEventInput['props'],
|
|
148
|
+
time?: Date,
|
|
149
|
+
) => boolean;
|
|
135
150
|
flush: () => Promise<number>;
|
|
136
151
|
setUser: (userId?: string, attributes?: Record<string, string>) => void;
|
|
137
152
|
clearUser: () => void;
|
|
@@ -156,7 +171,7 @@ export interface AsyncPulseStorage {
|
|
|
156
171
|
let activeClient: PulseClient | null = null;
|
|
157
172
|
let stopActiveRefresh: (() => void) | null = null;
|
|
158
173
|
|
|
159
|
-
/** Wires config and events
|
|
174
|
+
/** Wires config and events with an explicit event-envelope identity policy. */
|
|
160
175
|
export function initPulse(opts: InitPulseOptions): PulseClient {
|
|
161
176
|
// Reconfiguration is synchronous. Calling the old async dispose without awaiting
|
|
162
177
|
// it lets its eventual flush tear down the brand-new tracker — exactly the race a
|
|
@@ -216,6 +231,7 @@ export function initPulse(opts: InitPulseOptions): PulseClient {
|
|
|
216
231
|
configureTracking({
|
|
217
232
|
url: trackUrl,
|
|
218
233
|
getContext,
|
|
234
|
+
identityMode: opts.eventIdentityMode,
|
|
219
235
|
flushIntervalMs: opts.flushIntervalMs,
|
|
220
236
|
storage: opts.storage,
|
|
221
237
|
storageKey: `pulse.${slug}.events.v1`,
|
|
@@ -252,6 +268,7 @@ export function initPulse(opts: InitPulseOptions): PulseClient {
|
|
|
252
268
|
configUrl,
|
|
253
269
|
trackUrl,
|
|
254
270
|
track,
|
|
271
|
+
trackIdempotent,
|
|
255
272
|
flush: flushEvents,
|
|
256
273
|
setUser: (nextUserId, attributes) => {
|
|
257
274
|
userId = nextUserId?.trim() || undefined;
|
|
@@ -300,8 +317,9 @@ export function initPulse(opts: InitPulseOptions): PulseClient {
|
|
|
300
317
|
}
|
|
301
318
|
|
|
302
319
|
/**
|
|
303
|
-
* AsyncStorage-friendly one-call setup. It preloads only Pulse's
|
|
304
|
-
* records, then exposes the same
|
|
320
|
+
* AsyncStorage-friendly one-call setup. It preloads only Pulse's app-scoped config,
|
|
321
|
+
* event, analytics-installation and exposure records, then exposes the same
|
|
322
|
+
* synchronous hot-path API as initPulse.
|
|
305
323
|
*/
|
|
306
324
|
export async function initPulseAsync(
|
|
307
325
|
opts: Omit<InitPulseOptions, 'storage'> & { storage: AsyncPulseStorage },
|
|
@@ -311,16 +329,24 @@ export async function initPulseAsync(
|
|
|
311
329
|
`pulse.${slug}.device-id`,
|
|
312
330
|
`pulse.${slug}.config.v1`,
|
|
313
331
|
`pulse.${slug}.events.v1`,
|
|
332
|
+
`pulse.${slug}.events.v1.analytics-installation-id`,
|
|
314
333
|
`pulse.${slug}.exposures.v1`,
|
|
315
334
|
DEVICE_ID_KEY,
|
|
316
335
|
];
|
|
317
336
|
const loaded = await Promise.all(keys.map(async (key) => [key, await opts.storage.getItem(key)] as const));
|
|
318
337
|
const memory = new Map(loaded.filter((entry): entry is readonly [string, string] => entry[1] !== null));
|
|
319
338
|
const storage: ConfigStorage = {
|
|
339
|
+
supportsDurableSyncWrites: false,
|
|
320
340
|
getString: (key) => memory.get(key),
|
|
321
341
|
set: (key, value) => {
|
|
322
342
|
memory.set(key, value);
|
|
323
|
-
|
|
343
|
+
try {
|
|
344
|
+
void Promise.resolve(opts.storage.setItem(key, value)).catch((error) => {
|
|
345
|
+
try { opts.onError?.(error); } catch { /* diagnostics never break persistence */ }
|
|
346
|
+
});
|
|
347
|
+
} catch (error) {
|
|
348
|
+
try { opts.onError?.(error); } catch { /* diagnostics never break persistence */ }
|
|
349
|
+
}
|
|
324
350
|
},
|
|
325
351
|
};
|
|
326
352
|
return initPulse({ ...opts, storage });
|