pulse-updates 1.1.1 → 1.2.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/README.md +50 -10
- package/SECURITY.md +42 -0
- package/android/src/main/java/app/pulse/updates/PulseController.kt +6 -2
- package/android/src/main/java/app/pulse/updates/PulseUpdatesModule.kt +25 -0
- package/app.plugin.js +47 -0
- package/ios/PulseUpdates/PulseController.swift +7 -2
- package/ios/PulseUpdates/PulseUpdates.m +7 -0
- package/ios/PulseUpdates/PulseUpdates.swift +22 -0
- package/lib/commonjs/NativePulseUpdates.js.map +1 -1
- package/lib/commonjs/PulseUpdates.js +36 -0
- package/lib/commonjs/PulseUpdates.js.map +1 -1
- package/lib/commonjs/config.js +175 -21
- package/lib/commonjs/config.js.map +1 -1
- package/lib/commonjs/decisions.js +128 -0
- package/lib/commonjs/decisions.js.map +1 -0
- package/lib/commonjs/index.js +12 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/init.js +153 -13
- package/lib/commonjs/init.js.map +1 -1
- package/lib/commonjs/track.js +154 -12
- package/lib/commonjs/track.js.map +1 -1
- package/lib/commonjs/usePulseUpdates.js +21 -16
- package/lib/commonjs/usePulseUpdates.js.map +1 -1
- package/lib/module/NativePulseUpdates.js.map +1 -1
- package/lib/module/PulseUpdates.js +33 -0
- package/lib/module/PulseUpdates.js.map +1 -1
- package/lib/module/config.js +174 -21
- package/lib/module/config.js.map +1 -1
- package/lib/module/decisions.js +122 -0
- package/lib/module/decisions.js.map +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/init.js +154 -15
- package/lib/module/init.js.map +1 -1
- package/lib/module/track.js +152 -12
- package/lib/module/track.js.map +1 -1
- package/lib/module/usePulseUpdates.js +21 -16
- package/lib/module/usePulseUpdates.js.map +1 -1
- package/lib/typescript/NativePulseUpdates.d.ts +1 -0
- package/lib/typescript/NativePulseUpdates.d.ts.map +1 -1
- package/lib/typescript/PulseUpdates.d.ts +20 -0
- package/lib/typescript/PulseUpdates.d.ts.map +1 -1
- package/lib/typescript/config.d.ts +22 -0
- package/lib/typescript/config.d.ts.map +1 -1
- package/lib/typescript/decisions.d.ts +55 -0
- package/lib/typescript/decisions.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/init.d.ts +51 -4
- package/lib/typescript/init.d.ts.map +1 -1
- package/lib/typescript/track.d.ts +29 -1
- package/lib/typescript/track.d.ts.map +1 -1
- package/lib/typescript/usePulseUpdates.d.ts.map +1 -1
- package/logo.png +0 -0
- package/package.json +14 -3
- package/scripts/publish.mjs +68 -3
- package/src/NativePulseUpdates.ts +1 -0
- package/src/PulseUpdates.ts +54 -0
- package/src/config.ts +234 -21
- package/src/decisions.ts +179 -0
- package/src/index.ts +1 -0
- package/src/init.ts +227 -12
- package/src/track.ts +191 -13
- package/src/usePulseUpdates.ts +21 -16
package/lib/commonjs/init.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.initPulse = initPulse;
|
|
7
|
+
exports.initPulseAsync = initPulseAsync;
|
|
7
8
|
var _config = require("./config");
|
|
8
9
|
var _track = require("./track");
|
|
9
10
|
/**
|
|
@@ -32,36 +33,65 @@ var _track = require("./track");
|
|
|
32
33
|
*/
|
|
33
34
|
|
|
34
35
|
const DEVICE_ID_KEY = 'pulse.device-id';
|
|
36
|
+
let activeClient = null;
|
|
37
|
+
let stopActiveRefresh = null;
|
|
35
38
|
|
|
36
39
|
/** Wires config and events, and returns the context the two share. */
|
|
37
40
|
function initPulse(opts) {
|
|
41
|
+
// Reconfiguration is synchronous. Calling the old async dispose without awaiting
|
|
42
|
+
// it lets its eventual flush tear down the brand-new tracker — exactly the race a
|
|
43
|
+
// fast app switch or test setup triggers. Persist the old outbox, stop its refresh,
|
|
44
|
+
// then configure the new app in one uninterrupted turn.
|
|
45
|
+
stopActiveRefresh?.();
|
|
46
|
+
(0, _track.disposeTracking)();
|
|
47
|
+
activeClient = null;
|
|
48
|
+
stopActiveRefresh = null;
|
|
38
49
|
const base = opts.apiUrl.replace(/\/+$/, '');
|
|
39
50
|
const slug = opts.appSlug.trim();
|
|
40
51
|
const configUrl = `${base}/pulse/config/${slug}`;
|
|
41
52
|
const trackUrl = `${base}/pulse/track/${slug}`;
|
|
42
|
-
const
|
|
53
|
+
const deviceStorageKey = `pulse.${slug}.device-id`;
|
|
54
|
+
let deviceId = opts.deviceId?.trim() || resolveDeviceId(opts.storage, deviceStorageKey);
|
|
43
55
|
const platform = detectPlatform();
|
|
44
56
|
const osVersion = detectOsVersion();
|
|
57
|
+
const appVersion = opts.appVersion ?? detectAppVersion();
|
|
58
|
+
const language = opts.language ?? detectLanguage();
|
|
59
|
+
let userId;
|
|
60
|
+
let userAttributes;
|
|
61
|
+
let consentOverride = typeof opts.analyticsConsent === 'boolean' ? opts.analyticsConsent : undefined;
|
|
62
|
+
const hasConsent = () => consentOverride ?? (typeof opts.analyticsConsent === 'function' ? opts.analyticsConsent() : true);
|
|
45
63
|
const getContext = () => ({
|
|
46
64
|
platform,
|
|
47
65
|
osVersion,
|
|
48
|
-
appVersion
|
|
66
|
+
appVersion,
|
|
67
|
+
language,
|
|
49
68
|
deviceId,
|
|
50
|
-
userId: opts.getUserId?.(),
|
|
51
|
-
userAttributes: opts.getUserAttributes?.()
|
|
69
|
+
userId: userId ?? opts.getUserId?.(),
|
|
70
|
+
userAttributes: userAttributes ?? opts.getUserAttributes?.()
|
|
52
71
|
});
|
|
53
72
|
(0, _config.configureConfig)({
|
|
54
73
|
url: configUrl,
|
|
55
74
|
defaults: opts.defaults,
|
|
56
75
|
storage: opts.storage,
|
|
76
|
+
storageKey: `pulse.${slug}.config.v1`,
|
|
57
77
|
getContext,
|
|
58
78
|
pollIntervalMs: opts.pollIntervalMs,
|
|
59
|
-
onError: opts.onError
|
|
79
|
+
onError: opts.onError,
|
|
80
|
+
signingPublicKey: opts.signingPublicKey,
|
|
81
|
+
signingKeyId: opts.signingKeyId,
|
|
82
|
+
requireSignature: opts.requireConfigSignature,
|
|
83
|
+
verifySignature: opts.verifyConfigSignature ?? (opts.requireConfigSignature && !opts.signingPublicKey ? verifyWithNativeKey : undefined)
|
|
60
84
|
});
|
|
61
85
|
(0, _track.configureTracking)({
|
|
62
86
|
url: trackUrl,
|
|
63
87
|
getContext,
|
|
64
88
|
flushIntervalMs: opts.flushIntervalMs,
|
|
89
|
+
storage: opts.storage,
|
|
90
|
+
storageKey: `pulse.${slug}.events.v1`,
|
|
91
|
+
hasConsent,
|
|
92
|
+
propertyAllowlist: opts.eventPropertyAllowlist,
|
|
93
|
+
redactProperties: opts.redactEventProperties,
|
|
94
|
+
appState: opts.appState,
|
|
65
95
|
onIgnored: opts.onIgnoredEvents,
|
|
66
96
|
onError: opts.onError
|
|
67
97
|
});
|
|
@@ -71,7 +101,7 @@ function initPulse(opts) {
|
|
|
71
101
|
// simply does not match this install — which reads as "the rollout did nothing".
|
|
72
102
|
// Without storage the id is new on every launch, so the arm is re-dealt each time
|
|
73
103
|
// and no experiment can mean anything.
|
|
74
|
-
if (!
|
|
104
|
+
if (!appVersion) {
|
|
75
105
|
opts.onError?.(new Error('Pulse: no appVersion given — version targeting and version slices will not match this install'));
|
|
76
106
|
}
|
|
77
107
|
if (!opts.storage && !opts.deviceId) {
|
|
@@ -82,12 +112,84 @@ function initPulse(opts) {
|
|
|
82
112
|
// the first response is the launch that runs on defaults, and defaults are the
|
|
83
113
|
// off position of every flag.
|
|
84
114
|
void (0, _config.fetchConfig)();
|
|
85
|
-
(0, _config.startConfigAutoRefresh)(opts.appState);
|
|
86
|
-
|
|
87
|
-
deviceId
|
|
115
|
+
const stopRefresh = (0, _config.startConfigAutoRefresh)(opts.appState);
|
|
116
|
+
const client = {
|
|
117
|
+
get deviceId() {
|
|
118
|
+
return deviceId;
|
|
119
|
+
},
|
|
88
120
|
configUrl,
|
|
89
|
-
trackUrl
|
|
121
|
+
trackUrl,
|
|
122
|
+
track: _track.track,
|
|
123
|
+
flush: _track.flushEvents,
|
|
124
|
+
setUser: (nextUserId, attributes) => {
|
|
125
|
+
userId = nextUserId?.trim() || undefined;
|
|
126
|
+
userAttributes = sanitizeAttributes(attributes);
|
|
127
|
+
},
|
|
128
|
+
clearUser: () => {
|
|
129
|
+
userId = undefined;
|
|
130
|
+
userAttributes = undefined;
|
|
131
|
+
},
|
|
132
|
+
setAnalyticsConsent: granted => {
|
|
133
|
+
consentOverride = granted;
|
|
134
|
+
},
|
|
135
|
+
resetInstallId: () => {
|
|
136
|
+
deviceId = randomId();
|
|
137
|
+
try {
|
|
138
|
+
opts.storage?.set(deviceStorageKey, deviceId);
|
|
139
|
+
} catch {/* memory-only fallback */}
|
|
140
|
+
return deviceId;
|
|
141
|
+
},
|
|
142
|
+
health: () => ({
|
|
143
|
+
appSlug: slug,
|
|
144
|
+
deviceId,
|
|
145
|
+
config: (0, _config.getConfigInfo)(),
|
|
146
|
+
events: (0, _track.getTrackingInfo)(),
|
|
147
|
+
analyticsConsent: hasConsent()
|
|
148
|
+
}),
|
|
149
|
+
config: {
|
|
150
|
+
boolean: _config.getConfigBoolean,
|
|
151
|
+
number: _config.getConfigNumber,
|
|
152
|
+
string: _config.getConfigString,
|
|
153
|
+
json: _config.getConfigJson,
|
|
154
|
+
refresh: _config.fetchConfig
|
|
155
|
+
},
|
|
156
|
+
dispose: async () => {
|
|
157
|
+
stopRefresh();
|
|
158
|
+
if (activeClient !== client) return;
|
|
159
|
+
await (0, _track.flushEvents)();
|
|
160
|
+
// Another init may have taken ownership while this network flush was pending.
|
|
161
|
+
if (activeClient === client) {
|
|
162
|
+
(0, _track.disposeTracking)();
|
|
163
|
+
activeClient = null;
|
|
164
|
+
stopActiveRefresh = null;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
activeClient = client;
|
|
169
|
+
stopActiveRefresh = stopRefresh;
|
|
170
|
+
return client;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* AsyncStorage-friendly one-call setup. It preloads only Pulse's three app-scoped
|
|
175
|
+
* records, then exposes the same synchronous hot-path API as initPulse.
|
|
176
|
+
*/
|
|
177
|
+
async function initPulseAsync(opts) {
|
|
178
|
+
const slug = opts.appSlug.trim();
|
|
179
|
+
const keys = [`pulse.${slug}.device-id`, `pulse.${slug}.config.v1`, `pulse.${slug}.events.v1`, DEVICE_ID_KEY];
|
|
180
|
+
const loaded = await Promise.all(keys.map(async key => [key, await opts.storage.getItem(key)]));
|
|
181
|
+
const memory = new Map(loaded.filter(entry => entry[1] !== null));
|
|
182
|
+
const storage = {
|
|
183
|
+
getString: key => memory.get(key),
|
|
184
|
+
set: (key, value) => {
|
|
185
|
+
memory.set(key, value);
|
|
186
|
+
void opts.storage.setItem(key, value);
|
|
187
|
+
}
|
|
90
188
|
};
|
|
189
|
+
return initPulse({
|
|
190
|
+
...opts,
|
|
191
|
+
storage
|
|
192
|
+
});
|
|
91
193
|
}
|
|
92
194
|
|
|
93
195
|
/**
|
|
@@ -97,18 +199,23 @@ function initPulse(opts) {
|
|
|
97
199
|
* arm is a hash of it, so every launch would be a fresh coin toss and no experiment
|
|
98
200
|
* could mean anything. Said out loud through onError rather than hidden.
|
|
99
201
|
*/
|
|
100
|
-
function resolveDeviceId(storage) {
|
|
202
|
+
function resolveDeviceId(storage, key = DEVICE_ID_KEY) {
|
|
101
203
|
if (!storage) return randomId();
|
|
102
204
|
try {
|
|
103
|
-
const existing = storage.getString(DEVICE_ID_KEY);
|
|
205
|
+
const existing = storage.getString(key) ?? storage.getString(DEVICE_ID_KEY);
|
|
104
206
|
if (existing) return existing;
|
|
105
207
|
const minted = randomId();
|
|
106
|
-
storage.set(
|
|
208
|
+
storage.set(key, minted);
|
|
107
209
|
return minted;
|
|
108
210
|
} catch {
|
|
109
211
|
return randomId();
|
|
110
212
|
}
|
|
111
213
|
}
|
|
214
|
+
function sanitizeAttributes(attributes) {
|
|
215
|
+
if (!attributes) return undefined;
|
|
216
|
+
const clean = Object.fromEntries(Object.entries(attributes).filter(([key, value]) => key.trim() !== '' && typeof value === 'string').slice(0, 50));
|
|
217
|
+
return Object.keys(clean).length > 0 ? clean : undefined;
|
|
218
|
+
}
|
|
112
219
|
function randomId() {
|
|
113
220
|
const bytes = new Uint8Array(16);
|
|
114
221
|
const crypto = globalThis.crypto;
|
|
@@ -147,4 +254,37 @@ function detectOsVersion() {
|
|
|
147
254
|
return undefined;
|
|
148
255
|
}
|
|
149
256
|
}
|
|
257
|
+
function detectAppVersion() {
|
|
258
|
+
try {
|
|
259
|
+
// Optional by design: most RN apps already carry this package, plain JS hosts do not.
|
|
260
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
261
|
+
const loaded = require('react-native-device-info');
|
|
262
|
+
return loaded.default?.getVersion?.() ?? loaded.getVersion?.();
|
|
263
|
+
} catch {
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
async function verifyWithNativeKey(canonicalPayload, signature) {
|
|
268
|
+
try {
|
|
269
|
+
// Kept lazy so init/config remain usable in Node, web and test hosts without RN.
|
|
270
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
271
|
+
const updates = require('./PulseUpdates');
|
|
272
|
+
return (await updates.verifyConfigSignatureAsync?.(canonicalPayload, signature)) ?? false;
|
|
273
|
+
} catch {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function detectLanguage() {
|
|
278
|
+
try {
|
|
279
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
280
|
+
const localize = require('react-native-localize');
|
|
281
|
+
return localize.getLocales?.()[0]?.languageTag;
|
|
282
|
+
} catch {
|
|
283
|
+
try {
|
|
284
|
+
return Intl.DateTimeFormat().resolvedOptions().locale;
|
|
285
|
+
} catch {
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
150
290
|
//# sourceMappingURL=init.js.map
|
package/lib/commonjs/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_config","require","_track","DEVICE_ID_KEY","initPulse","opts","base","apiUrl","replace","slug","appSlug","trim","configUrl","trackUrl","deviceId","resolveDeviceId","storage","platform","detectPlatform","osVersion","detectOsVersion","
|
|
1
|
+
{"version":3,"names":["_config","require","_track","DEVICE_ID_KEY","activeClient","stopActiveRefresh","initPulse","opts","disposeTracking","base","apiUrl","replace","slug","appSlug","trim","configUrl","trackUrl","deviceStorageKey","deviceId","resolveDeviceId","storage","platform","detectPlatform","osVersion","detectOsVersion","appVersion","detectAppVersion","language","detectLanguage","userId","userAttributes","consentOverride","analyticsConsent","undefined","hasConsent","getContext","getUserId","getUserAttributes","configureConfig","url","defaults","storageKey","pollIntervalMs","onError","signingPublicKey","signingKeyId","requireSignature","requireConfigSignature","verifySignature","verifyConfigSignature","verifyWithNativeKey","configureTracking","flushIntervalMs","propertyAllowlist","eventPropertyAllowlist","redactProperties","redactEventProperties","appState","onIgnored","onIgnoredEvents","Error","fetchConfig","stopRefresh","startConfigAutoRefresh","client","track","flush","flushEvents","setUser","nextUserId","attributes","sanitizeAttributes","clearUser","setAnalyticsConsent","granted","resetInstallId","randomId","set","health","config","getConfigInfo","events","getTrackingInfo","boolean","getConfigBoolean","number","getConfigNumber","string","getConfigString","json","getConfigJson","refresh","dispose","initPulseAsync","keys","loaded","Promise","all","map","key","getItem","memory","Map","filter","entry","getString","get","value","setItem","existing","minted","clean","Object","fromEntries","entries","slice","length","bytes","Uint8Array","crypto","globalThis","getRandomValues","i","Math","floor","random","hex","Array","from","b","toString","padStart","join","rn","Platform","OS","version","Version","String","default","getVersion","canonicalPayload","signature","updates","verifyConfigSignatureAsync","localize","getLocales","languageTag","Intl","DateTimeFormat","resolvedOptions","locale"],"sourceRoot":"../../src","sources":["init.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/commonjs/track.js
CHANGED
|
@@ -4,7 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.configureTracking = configureTracking;
|
|
7
|
+
exports.disposeTracking = disposeTracking;
|
|
7
8
|
exports.flushEvents = flushEvents;
|
|
9
|
+
exports.getTrackingInfo = getTrackingInfo;
|
|
8
10
|
exports.pendingEventCount = pendingEventCount;
|
|
9
11
|
exports.stopTracking = stopTracking;
|
|
10
12
|
exports.track = track;
|
|
@@ -33,10 +35,16 @@ exports.track = track;
|
|
|
33
35
|
const DEFAULT_FLUSH_MS = 10_000;
|
|
34
36
|
const DEFAULT_MAX_BATCH = 100;
|
|
35
37
|
const DEFAULT_MAX_QUEUE = 500;
|
|
38
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
39
|
+
const DEFAULT_MAX_ATTEMPTS = 10;
|
|
40
|
+
const DEFAULT_STORAGE_KEY = 'pulse.events.v1';
|
|
36
41
|
let options = null;
|
|
37
42
|
let queue = [];
|
|
38
43
|
let timer = null;
|
|
39
44
|
let sending = false;
|
|
45
|
+
let nextAttemptAt = 0;
|
|
46
|
+
let lifecycleSubscription = null;
|
|
47
|
+
let trackingGeneration = 0;
|
|
40
48
|
|
|
41
49
|
/** Turns a config url into the track url; leaves an explicit track url alone. */
|
|
42
50
|
function trackUrl(url) {
|
|
@@ -44,8 +52,14 @@ function trackUrl(url) {
|
|
|
44
52
|
return trimmed.includes('/pulse/config/') ? trimmed.replace('/pulse/config/', '/pulse/track/') : trimmed;
|
|
45
53
|
}
|
|
46
54
|
function configureTracking(opts) {
|
|
55
|
+
disposeTracking();
|
|
47
56
|
options = opts;
|
|
57
|
+
queue = readQueue(opts);
|
|
58
|
+
nextAttemptAt = 0;
|
|
48
59
|
startTimer();
|
|
60
|
+
lifecycleSubscription = opts.appState?.addEventListener('change', state => {
|
|
61
|
+
if (state !== 'active') void flushEvents();
|
|
62
|
+
}) ?? null;
|
|
49
63
|
}
|
|
50
64
|
|
|
51
65
|
/**
|
|
@@ -55,18 +69,32 @@ function configureTracking(opts) {
|
|
|
55
69
|
*/
|
|
56
70
|
function track(event, props, time) {
|
|
57
71
|
if (!options || !event) return;
|
|
72
|
+
if (options.hasConsent?.() === false) {
|
|
73
|
+
options.onDropped?.(1, 'no-consent');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
58
76
|
const flat = {};
|
|
77
|
+
const allow = options.propertyAllowlist ? new Set(options.propertyAllowlist) : null;
|
|
78
|
+
const redact = new Set(options.redactProperties ?? []);
|
|
59
79
|
for (const [key, value] of Object.entries(props ?? {})) {
|
|
60
80
|
if (value === null || value === undefined) continue;
|
|
61
|
-
|
|
81
|
+
if (allow && !allow.has(key)) continue;
|
|
82
|
+
flat[key] = redact.has(key) ? '[REDACTED]' : typeof value === 'string' ? value : String(value);
|
|
62
83
|
}
|
|
63
84
|
queue.push({
|
|
85
|
+
id: randomEventId(),
|
|
64
86
|
event,
|
|
65
87
|
time: (time ?? new Date()).toISOString(),
|
|
66
|
-
props: flat
|
|
88
|
+
props: flat,
|
|
89
|
+
attempts: 0
|
|
67
90
|
});
|
|
68
91
|
const maxQueue = options.maxQueue ?? DEFAULT_MAX_QUEUE;
|
|
69
|
-
if (queue.length > maxQueue)
|
|
92
|
+
if (queue.length > maxQueue) {
|
|
93
|
+
const dropped = queue.length - maxQueue;
|
|
94
|
+
queue = queue.slice(dropped);
|
|
95
|
+
options.onDropped?.(dropped, 'queue-full');
|
|
96
|
+
}
|
|
97
|
+
persistQueue();
|
|
70
98
|
if (queue.length >= (options.maxBatch ?? DEFAULT_MAX_BATCH)) void flushEvents();
|
|
71
99
|
}
|
|
72
100
|
|
|
@@ -78,8 +106,9 @@ function track(event, props, time) {
|
|
|
78
106
|
* after launch, when the first events of a session are the ones a funnel needs most.
|
|
79
107
|
*/
|
|
80
108
|
async function flushEvents() {
|
|
81
|
-
if (!options || sending || queue.length === 0) return 0;
|
|
109
|
+
if (!options || sending || queue.length === 0 || Date.now() < nextAttemptAt) return 0;
|
|
82
110
|
const opts = options;
|
|
111
|
+
const requestGeneration = trackingGeneration;
|
|
83
112
|
const ctx = opts.getContext?.() ?? {};
|
|
84
113
|
|
|
85
114
|
// Without a device id the server cannot put the event in an arm, and an empty id
|
|
@@ -88,7 +117,10 @@ async function flushEvents() {
|
|
|
88
117
|
if (!ctx.deviceId) return 0;
|
|
89
118
|
const batch = queue.slice(0, opts.maxBatch ?? DEFAULT_MAX_BATCH);
|
|
90
119
|
queue = queue.slice(batch.length);
|
|
120
|
+
persistQueue();
|
|
91
121
|
sending = true;
|
|
122
|
+
const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
|
123
|
+
const timeout = controller ? setTimeout(() => controller.abort(), opts.timeoutMs ?? DEFAULT_TIMEOUT_MS) : null;
|
|
92
124
|
try {
|
|
93
125
|
const response = await fetch(trackUrl(opts.url), {
|
|
94
126
|
method: 'POST',
|
|
@@ -101,27 +133,37 @@ async function flushEvents() {
|
|
|
101
133
|
platform: ctx.platform,
|
|
102
134
|
appVersion: ctx.appVersion,
|
|
103
135
|
events: batch.map(e => ({
|
|
136
|
+
id: e.id,
|
|
104
137
|
event: e.event,
|
|
105
138
|
time: e.time,
|
|
106
139
|
props: e.props
|
|
107
140
|
}))
|
|
108
|
-
})
|
|
141
|
+
}),
|
|
142
|
+
signal: controller?.signal
|
|
109
143
|
});
|
|
110
144
|
if (!response.ok) {
|
|
111
145
|
// Rate limited or briefly down: keep the events, try on the next tick.
|
|
112
|
-
|
|
146
|
+
if (requestGeneration === trackingGeneration && options === opts) {
|
|
147
|
+
requeueWithBackoff(batch, response.status);
|
|
148
|
+
} else {
|
|
149
|
+
restoreStaleBatch(opts, batch, response.status);
|
|
150
|
+
}
|
|
113
151
|
if (response.status !== 429) opts.onError?.(new Error(`Pulse track failed: ${response.status}`));
|
|
114
152
|
return 0;
|
|
115
153
|
}
|
|
116
154
|
const body = await response.json();
|
|
155
|
+
if (requestGeneration !== trackingGeneration || options !== opts) return body.accepted ?? 0;
|
|
117
156
|
if (body.ignored && body.ignored.length > 0) opts.onIgnored?.(body.ignored);
|
|
157
|
+
nextAttemptAt = 0;
|
|
158
|
+
persistQueue();
|
|
118
159
|
return body.accepted ?? 0;
|
|
119
160
|
} catch (error) {
|
|
120
|
-
|
|
161
|
+
if (requestGeneration === trackingGeneration && options === opts) requeueWithBackoff(batch);else restoreStaleBatch(opts, batch);
|
|
121
162
|
opts.onError?.(error);
|
|
122
163
|
return 0;
|
|
123
164
|
} finally {
|
|
124
|
-
|
|
165
|
+
if (timeout) clearTimeout(timeout);
|
|
166
|
+
if (requestGeneration === trackingGeneration) sending = false;
|
|
125
167
|
}
|
|
126
168
|
}
|
|
127
169
|
|
|
@@ -129,14 +171,31 @@ async function flushEvents() {
|
|
|
129
171
|
function pendingEventCount() {
|
|
130
172
|
return queue.length;
|
|
131
173
|
}
|
|
174
|
+
function getTrackingInfo() {
|
|
175
|
+
return {
|
|
176
|
+
queueDepth: queue.length,
|
|
177
|
+
sending,
|
|
178
|
+
nextAttemptAt
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Stop timers and listeners while preserving the durable outbox. */
|
|
183
|
+
function disposeTracking() {
|
|
184
|
+
trackingGeneration += 1;
|
|
185
|
+
if (timer) clearInterval(timer);
|
|
186
|
+
timer = null;
|
|
187
|
+
lifecycleSubscription?.remove();
|
|
188
|
+
lifecycleSubscription = null;
|
|
189
|
+
persistQueue();
|
|
190
|
+
options = null;
|
|
191
|
+
sending = false;
|
|
192
|
+
}
|
|
132
193
|
function stopTracking() {
|
|
133
|
-
|
|
134
|
-
clearInterval(timer);
|
|
135
|
-
timer = null;
|
|
136
|
-
}
|
|
194
|
+
disposeTracking();
|
|
137
195
|
options = null;
|
|
138
196
|
queue = [];
|
|
139
197
|
sending = false;
|
|
198
|
+
nextAttemptAt = 0;
|
|
140
199
|
}
|
|
141
200
|
function startTimer() {
|
|
142
201
|
if (timer) clearInterval(timer);
|
|
@@ -146,4 +205,87 @@ function startTimer() {
|
|
|
146
205
|
// and a CLI importing this should still be able to exit.
|
|
147
206
|
timer.unref?.();
|
|
148
207
|
}
|
|
208
|
+
function requeueWithBackoff(batch, status) {
|
|
209
|
+
if (!options) return;
|
|
210
|
+
const maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
211
|
+
const retryable = [];
|
|
212
|
+
let dropped = 0;
|
|
213
|
+
for (const event of batch) {
|
|
214
|
+
const next = {
|
|
215
|
+
...event,
|
|
216
|
+
attempts: event.attempts + 1
|
|
217
|
+
};
|
|
218
|
+
if (next.attempts >= maxAttempts && status !== 429) dropped++;else retryable.push(next);
|
|
219
|
+
}
|
|
220
|
+
queue = [...retryable, ...queue];
|
|
221
|
+
if (dropped > 0) options.onDropped?.(dropped, 'max-attempts');
|
|
222
|
+
const attempts = retryable.reduce((max, event) => Math.max(max, event.attempts), 1);
|
|
223
|
+
const base = Math.min(60_000, 1_000 * 2 ** Math.min(attempts - 1, 6));
|
|
224
|
+
nextAttemptAt = Date.now() + base + Math.floor(Math.random() * Math.max(1, base / 4));
|
|
225
|
+
persistQueue();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* An old request may fail after another app has been configured. Its rows belong in
|
|
230
|
+
* the old app's outbox, never in the new app's in-memory queue. When the same app was
|
|
231
|
+
* merely reconfigured, merge them back into the live queue so it need not restart to
|
|
232
|
+
* see them; otherwise persist directly under the captured app-scoped key.
|
|
233
|
+
*/
|
|
234
|
+
function restoreStaleBatch(opts, batch, status) {
|
|
235
|
+
const maxAttempts = opts.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
236
|
+
const retryable = [];
|
|
237
|
+
let dropped = 0;
|
|
238
|
+
for (const event of batch) {
|
|
239
|
+
const next = {
|
|
240
|
+
...event,
|
|
241
|
+
attempts: event.attempts + 1
|
|
242
|
+
};
|
|
243
|
+
if (next.attempts >= maxAttempts && status !== 429) dropped++;else retryable.push(next);
|
|
244
|
+
}
|
|
245
|
+
if (dropped > 0) opts.onDropped?.(dropped, 'max-attempts');
|
|
246
|
+
if (retryable.length === 0) return;
|
|
247
|
+
const currentOptions = options;
|
|
248
|
+
const sameOutbox = currentOptions?.storage === opts.storage && currentOptions !== null && storageKey(currentOptions) === storageKey(opts);
|
|
249
|
+
if (sameOutbox) {
|
|
250
|
+
queue = [...retryable, ...queue].slice(-(options?.maxQueue ?? DEFAULT_MAX_QUEUE));
|
|
251
|
+
persistQueue();
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (!opts.storage) return;
|
|
255
|
+
try {
|
|
256
|
+
const stored = readQueue(opts);
|
|
257
|
+
const restored = [...retryable, ...stored].slice(-(opts.maxQueue ?? DEFAULT_MAX_QUEUE));
|
|
258
|
+
opts.storage.set(storageKey(opts), JSON.stringify(restored));
|
|
259
|
+
} catch {
|
|
260
|
+
// Best effort only; a telemetry recovery must not affect the new app session.
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
function storageKey(opts) {
|
|
264
|
+
return opts.storageKey?.trim() || DEFAULT_STORAGE_KEY;
|
|
265
|
+
}
|
|
266
|
+
function readQueue(opts) {
|
|
267
|
+
if (!opts.storage) return [];
|
|
268
|
+
try {
|
|
269
|
+
const raw = opts.storage.getString(storageKey(opts));
|
|
270
|
+
if (!raw) return [];
|
|
271
|
+
const parsed = JSON.parse(raw);
|
|
272
|
+
if (!Array.isArray(parsed)) return [];
|
|
273
|
+
return parsed.filter(item => Boolean(item && typeof item === 'object' && typeof item.id === 'string' && typeof item.event === 'string' && typeof item.time === 'string' && typeof item.props === 'object' && typeof item.attempts === 'number')).slice(-(opts.maxQueue ?? DEFAULT_MAX_QUEUE));
|
|
274
|
+
} catch {
|
|
275
|
+
return [];
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
function persistQueue() {
|
|
279
|
+
if (!options?.storage) return;
|
|
280
|
+
try {
|
|
281
|
+
options.storage.set(storageKey(options), JSON.stringify(queue));
|
|
282
|
+
} catch {
|
|
283
|
+
// Telemetry persistence must never become an app failure.
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function randomEventId() {
|
|
287
|
+
const cryptoLike = globalThis.crypto;
|
|
288
|
+
if (typeof cryptoLike?.randomUUID === 'function') return cryptoLike.randomUUID();
|
|
289
|
+
return `evt-${Date.now()}-${Math.random().toString(36).slice(2, 14)}`;
|
|
290
|
+
}
|
|
149
291
|
//# sourceMappingURL=track.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["DEFAULT_FLUSH_MS","DEFAULT_MAX_BATCH","DEFAULT_MAX_QUEUE","options","queue","timer","sending","trackUrl","url","trimmed","replace","includes","configureTracking","opts","startTimer","track","event","props","time","flat","key","value","Object","entries","undefined","String","push","Date","toISOString","maxQueue","length","slice","maxBatch","flushEvents","ctx","getContext","deviceId","batch","response","fetch","method","headers","body","JSON","stringify","userId","platform","appVersion","events","map","e","ok","status","onError","Error","json","ignored","onIgnored","accepted","error","pendingEventCount","stopTracking","clearInterval","every","flushIntervalMs","setInterval","unref"],"sourceRoot":"../../src","sources":["track.ts"],"mappings":";;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AA2CA,MAAMA,gBAAgB,GAAG,MAAM;AAC/B,MAAMC,iBAAiB,GAAG,GAAG;AAC7B,MAAMC,iBAAiB,GAAG,GAAG;AAE7B,IAAIC,OAA4B,GAAG,IAAI;AACvC,IAAIC,KAAoB,GAAG,EAAE;AAC7B,IAAIC,KAA4C,GAAG,IAAI;AACvD,IAAIC,OAAO,GAAG,KAAK;;AAEnB;AACA,SAASC,QAAQA,CAACC,GAAW,EAAU;EACrC,MAAMC,OAAO,GAAGD,GAAG,CAACE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;EACvC,OAAOD,OAAO,CAACE,QAAQ,CAAC,gBAAgB,CAAC,GACrCF,OAAO,CAACC,OAAO,CAAC,gBAAgB,EAAE,eAAe,CAAC,GAClDD,OAAO;AACb;AAEO,SAASG,iBAAiBA,CAACC,IAAkB,EAAQ;EAC1DV,OAAO,GAAGU,IAAI;EACdC,UAAU,CAAC,CAAC;AACd;;AAEA;AACA;AACA;AACA;AACA;AACO,SAASC,KAAKA,CAACC,KAAa,EAAEC,KAAkC,EAAEC,IAAW,EAAQ;EAC1F,IAAI,CAACf,OAAO,IAAI,CAACa,KAAK,EAAE;EAExB,MAAMG,IAA4B,GAAG,CAAC,CAAC;EACvC,KAAK,MAAM,CAACC,GAAG,EAAEC,KAAK,CAAC,IAAIC,MAAM,CAACC,OAAO,CAACN,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE;IACtD,IAAII,KAAK,KAAK,IAAI,IAAIA,KAAK,KAAKG,SAAS,EAAE;IAC3CL,IAAI,CAACC,GAAG,CAAC,GAAG,OAAOC,KAAK,KAAK,QAAQ,GAAGA,KAAK,GAAGI,MAAM,CAACJ,KAAK,CAAC;EAC/D;EAEAjB,KAAK,CAACsB,IAAI,CAAC;IAAEV,KAAK;IAAEE,IAAI,EAAE,CAACA,IAAI,IAAI,IAAIS,IAAI,CAAC,CAAC,EAAEC,WAAW,CAAC,CAAC;IAAEX,KAAK,EAAEE;EAAK,CAAC,CAAC;EAE5E,MAAMU,QAAQ,GAAG1B,OAAO,CAAC0B,QAAQ,IAAI3B,iBAAiB;EACtD,IAAIE,KAAK,CAAC0B,MAAM,GAAGD,QAAQ,EAAEzB,KAAK,GAAGA,KAAK,CAAC2B,KAAK,CAAC3B,KAAK,CAAC0B,MAAM,GAAGD,QAAQ,CAAC;EAEzE,IAAIzB,KAAK,CAAC0B,MAAM,KAAK3B,OAAO,CAAC6B,QAAQ,IAAI/B,iBAAiB,CAAC,EAAE,KAAKgC,WAAW,CAAC,CAAC;AACjF;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAeA,WAAWA,CAAA,EAAoB;EACnD,IAAI,CAAC9B,OAAO,IAAIG,OAAO,IAAIF,KAAK,CAAC0B,MAAM,KAAK,CAAC,EAAE,OAAO,CAAC;EAEvD,MAAMjB,IAAI,GAAGV,OAAO;EACpB,MAAM+B,GAAG,GAAGrB,IAAI,CAACsB,UAAU,GAAG,CAAC,IAAI,CAAC,CAAC;;EAErC;EACA;EACA;EACA,IAAI,CAACD,GAAG,CAACE,QAAQ,EAAE,OAAO,CAAC;EAE3B,MAAMC,KAAK,GAAGjC,KAAK,CAAC2B,KAAK,CAAC,CAAC,EAAElB,IAAI,CAACmB,QAAQ,IAAI/B,iBAAiB,CAAC;EAChEG,KAAK,GAAGA,KAAK,CAAC2B,KAAK,CAACM,KAAK,CAACP,MAAM,CAAC;EACjCxB,OAAO,GAAG,IAAI;EAEd,IAAI;IACF,MAAMgC,QAAQ,GAAG,MAAMC,KAAK,CAAChC,QAAQ,CAACM,IAAI,CAACL,GAAG,CAAC,EAAE;MAC/CgC,MAAM,EAAE,MAAM;MACdC,OAAO,EAAE;QAAE,cAAc,EAAE;MAAmB,CAAC;MAC/CC,IAAI,EAAEC,IAAI,CAACC,SAAS,CAAC;QACnBR,QAAQ,EAAEF,GAAG,CAACE,QAAQ;QACtBS,MAAM,EAAEX,GAAG,CAACW,MAAM;QAClBC,QAAQ,EAAEZ,GAAG,CAACY,QAAQ;QACtBC,UAAU,EAAEb,GAAG,CAACa,UAAU;QAC1BC,MAAM,EAAEX,KAAK,CAACY,GAAG,CAAEC,CAAC,KAAM;UAAElC,KAAK,EAAEkC,CAAC,CAAClC,KAAK;UAAEE,IAAI,EAAEgC,CAAC,CAAChC,IAAI;UAAED,KAAK,EAAEiC,CAAC,CAACjC;QAAM,CAAC,CAAC;MAC7E,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,CAACqB,QAAQ,CAACa,EAAE,EAAE;MAChB;MACA/C,KAAK,GAAG,CAAC,GAAGiC,KAAK,EAAE,GAAGjC,KAAK,CAAC;MAC5B,IAAIkC,QAAQ,CAACc,MAAM,KAAK,GAAG,EAAEvC,IAAI,CAACwC,OAAO,GAAG,IAAIC,KAAK,CAAC,uBAAuBhB,QAAQ,CAACc,MAAM,EAAE,CAAC,CAAC;MAChG,OAAO,CAAC;IACV;IAEA,MAAMV,IAAI,GAAI,MAAMJ,QAAQ,CAACiB,IAAI,CAAC,CAA+C;IACjF,IAAIb,IAAI,CAACc,OAAO,IAAId,IAAI,CAACc,OAAO,CAAC1B,MAAM,GAAG,CAAC,EAAEjB,IAAI,CAAC4C,SAAS,GAAGf,IAAI,CAACc,OAAO,CAAC;IAC3E,OAAOd,IAAI,CAACgB,QAAQ,IAAI,CAAC;EAC3B,CAAC,CAAC,OAAOC,KAAK,EAAE;IACdvD,KAAK,GAAG,CAAC,GAAGiC,KAAK,EAAE,GAAGjC,KAAK,CAAC;IAC5BS,IAAI,CAACwC,OAAO,GAAGM,KAAK,CAAC;IACrB,OAAO,CAAC;EACV,CAAC,SAAS;IACRrD,OAAO,GAAG,KAAK;EACjB;AACF;;AAEA;AACO,SAASsD,iBAAiBA,CAAA,EAAW;EAC1C,OAAOxD,KAAK,CAAC0B,MAAM;AACrB;AAEO,SAAS+B,YAAYA,CAAA,EAAS;EACnC,IAAIxD,KAAK,EAAE;IACTyD,aAAa,CAACzD,KAAK,CAAC;IACpBA,KAAK,GAAG,IAAI;EACd;EACAF,OAAO,GAAG,IAAI;EACdC,KAAK,GAAG,EAAE;EACVE,OAAO,GAAG,KAAK;AACjB;AAEA,SAASQ,UAAUA,CAAA,EAAS;EAC1B,IAAIT,KAAK,EAAEyD,aAAa,CAACzD,KAAK,CAAC;EAC/B,MAAM0D,KAAK,GAAG5D,OAAO,EAAE6D,eAAe,IAAIhE,gBAAgB;EAC1DK,KAAK,GAAG4D,WAAW,CAAC,MAAM,KAAKhC,WAAW,CAAC,CAAC,EAAE8B,KAAK,CAAC;EACpD;EACA;EACC1D,KAAK,CAAuC6D,KAAK,GAAG,CAAC;AACxD","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["DEFAULT_FLUSH_MS","DEFAULT_MAX_BATCH","DEFAULT_MAX_QUEUE","DEFAULT_TIMEOUT_MS","DEFAULT_MAX_ATTEMPTS","DEFAULT_STORAGE_KEY","options","queue","timer","sending","nextAttemptAt","lifecycleSubscription","trackingGeneration","trackUrl","url","trimmed","replace","includes","configureTracking","opts","disposeTracking","readQueue","startTimer","appState","addEventListener","state","flushEvents","track","event","props","time","hasConsent","onDropped","flat","allow","propertyAllowlist","Set","redact","redactProperties","key","value","Object","entries","undefined","has","String","push","id","randomEventId","Date","toISOString","attempts","maxQueue","length","dropped","slice","persistQueue","maxBatch","now","requestGeneration","ctx","getContext","deviceId","batch","controller","AbortController","timeout","setTimeout","abort","timeoutMs","response","fetch","method","headers","body","JSON","stringify","userId","platform","appVersion","events","map","e","signal","ok","requeueWithBackoff","status","restoreStaleBatch","onError","Error","json","accepted","ignored","onIgnored","error","clearTimeout","pendingEventCount","getTrackingInfo","queueDepth","clearInterval","remove","stopTracking","every","flushIntervalMs","setInterval","unref","maxAttempts","retryable","next","reduce","max","Math","base","min","floor","random","currentOptions","sameOutbox","storage","storageKey","stored","restored","set","trim","raw","getString","parsed","parse","Array","isArray","filter","item","Boolean","cryptoLike","globalThis","crypto","randomUUID","toString"],"sourceRoot":"../../src","sources":["track.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -8,6 +8,7 @@ var _react = require("react");
|
|
|
8
8
|
var PulseUpdates = _interopRequireWildcard(require("./PulseUpdates"));
|
|
9
9
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
10
10
|
function usePulseUpdates() {
|
|
11
|
+
const [nativeState, setNativeState] = (0, _react.useState)(PulseUpdates.getUpdatesState);
|
|
11
12
|
const [isChecking, setIsChecking] = (0, _react.useState)(false);
|
|
12
13
|
const [isDownloading, setIsDownloading] = (0, _react.useState)(false);
|
|
13
14
|
const [availableUpdate, setAvailableUpdate] = (0, _react.useState)(null);
|
|
@@ -16,10 +17,14 @@ function usePulseUpdates() {
|
|
|
16
17
|
|
|
17
18
|
// Refresh state on mount to get latest values after configure
|
|
18
19
|
(0, _react.useEffect)(() => {
|
|
19
|
-
PulseUpdates.
|
|
20
|
+
const unsubscribe = PulseUpdates.onUpdatesStateChange(() => {
|
|
21
|
+
setNativeState(PulseUpdates.getUpdatesState());
|
|
22
|
+
});
|
|
23
|
+
void PulseUpdates.refreshStateAsync();
|
|
24
|
+
return unsubscribe;
|
|
20
25
|
}, []);
|
|
21
26
|
(0, _react.useEffect)(() => {
|
|
22
|
-
if (!
|
|
27
|
+
if (!nativeState.isEnabled) return;
|
|
23
28
|
const subscription = PulseUpdates.addUpdateListener(event => {
|
|
24
29
|
switch (event.type) {
|
|
25
30
|
case 'updateAvailable':
|
|
@@ -37,9 +42,9 @@ function usePulseUpdates() {
|
|
|
37
42
|
}
|
|
38
43
|
});
|
|
39
44
|
return () => subscription.remove();
|
|
40
|
-
}, []);
|
|
45
|
+
}, [nativeState.isEnabled]);
|
|
41
46
|
const checkForUpdate = (0, _react.useCallback)(async () => {
|
|
42
|
-
if (!
|
|
47
|
+
if (!nativeState.isEnabled) {
|
|
43
48
|
return {
|
|
44
49
|
isAvailable: false
|
|
45
50
|
};
|
|
@@ -64,9 +69,9 @@ function usePulseUpdates() {
|
|
|
64
69
|
} finally {
|
|
65
70
|
setIsChecking(false);
|
|
66
71
|
}
|
|
67
|
-
}, []);
|
|
72
|
+
}, [nativeState.isEnabled]);
|
|
68
73
|
const downloadUpdate = (0, _react.useCallback)(async () => {
|
|
69
|
-
if (!
|
|
74
|
+
if (!nativeState.isEnabled) {
|
|
70
75
|
return {
|
|
71
76
|
isNew: false
|
|
72
77
|
};
|
|
@@ -88,21 +93,21 @@ function usePulseUpdates() {
|
|
|
88
93
|
} finally {
|
|
89
94
|
setIsDownloading(false);
|
|
90
95
|
}
|
|
91
|
-
}, []);
|
|
96
|
+
}, [nativeState.isEnabled]);
|
|
92
97
|
const reload = (0, _react.useCallback)(async () => {
|
|
93
|
-
if (!
|
|
98
|
+
if (!nativeState.isEnabled) return;
|
|
94
99
|
await PulseUpdates.reloadAsync();
|
|
95
|
-
}, []);
|
|
100
|
+
}, [nativeState.isEnabled]);
|
|
96
101
|
return {
|
|
97
|
-
isEnabled:
|
|
102
|
+
isEnabled: nativeState.isEnabled,
|
|
98
103
|
isChecking,
|
|
99
104
|
isDownloading,
|
|
100
|
-
updateId:
|
|
101
|
-
runtimeVersion:
|
|
102
|
-
channel:
|
|
103
|
-
manifest:
|
|
104
|
-
isEmbeddedLaunch:
|
|
105
|
-
createdAt:
|
|
105
|
+
updateId: nativeState.updateId,
|
|
106
|
+
runtimeVersion: nativeState.runtimeVersion,
|
|
107
|
+
channel: nativeState.channel,
|
|
108
|
+
manifest: nativeState.manifest,
|
|
109
|
+
isEmbeddedLaunch: nativeState.isEmbeddedLaunch,
|
|
110
|
+
createdAt: nativeState.createdAt,
|
|
106
111
|
build: PulseUpdates.getUpdateBuild(),
|
|
107
112
|
availableUpdate,
|
|
108
113
|
downloadedUpdate,
|