pulse-updates 1.1.0 → 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 +164 -12
- 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 +165 -14
- 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 +240 -11
- package/src/track.ts +191 -13
- package/src/usePulseUpdates.ts +21 -16
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/** Generic decision protocol. Product-specific action handlers remain in each app. */
|
|
2
|
+
export function createPulseDecisionClient(options) {
|
|
3
|
+
const fetcher = options.fetch ?? globalThis.fetch;
|
|
4
|
+
const base = options.apiUrl.replace(/\/+$/, '');
|
|
5
|
+
const slug = encodeURIComponent(options.appSlug);
|
|
6
|
+
const timeoutMs = Math.max(250, options.timeoutMs ?? 3_000);
|
|
7
|
+
const executionMode = options.executionMode ?? 'shadow-only';
|
|
8
|
+
const reportOutcome = async (decisionId, outcome, metadata) => {
|
|
9
|
+
try {
|
|
10
|
+
const response = await timedFetch(fetcher, `${base}/pulse/decisions/${slug}/${encodeURIComponent(decisionId)}/outcome`, {
|
|
11
|
+
method: 'POST',
|
|
12
|
+
headers: {
|
|
13
|
+
'Content-Type': 'application/json'
|
|
14
|
+
},
|
|
15
|
+
body: JSON.stringify({
|
|
16
|
+
outcome,
|
|
17
|
+
...(metadata ? {
|
|
18
|
+
metadata
|
|
19
|
+
} : {})
|
|
20
|
+
})
|
|
21
|
+
}, timeoutMs);
|
|
22
|
+
return response.ok;
|
|
23
|
+
} catch (error) {
|
|
24
|
+
options.onError?.(error);
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const decide = async (trigger, request = {}) => {
|
|
29
|
+
try {
|
|
30
|
+
const context = await options.getContext();
|
|
31
|
+
const response = await timedFetch(fetcher, `${base}/pulse/decisions/${slug}`, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: {
|
|
34
|
+
'Content-Type': 'application/json'
|
|
35
|
+
},
|
|
36
|
+
body: JSON.stringify({
|
|
37
|
+
...context,
|
|
38
|
+
attributes: {
|
|
39
|
+
...(context.attributes ?? {}),
|
|
40
|
+
...(request.attributes ?? {})
|
|
41
|
+
},
|
|
42
|
+
trigger,
|
|
43
|
+
channel: request.channel ?? 'in_app',
|
|
44
|
+
idempotencyKey: request.idempotencyKey ?? randomKey()
|
|
45
|
+
})
|
|
46
|
+
}, timeoutMs);
|
|
47
|
+
if (!response.ok) throw new Error(`Pulse decision HTTP ${response.status}`);
|
|
48
|
+
const decision = parseDecision(await response.json());
|
|
49
|
+
if (!decision.execute) return decision;
|
|
50
|
+
if (executionMode !== 'allow-live') {
|
|
51
|
+
void reportOutcome(decision.decisionId, 'failed', {
|
|
52
|
+
reason: 'client_executor_not_armed'
|
|
53
|
+
});
|
|
54
|
+
return decision;
|
|
55
|
+
}
|
|
56
|
+
const action = decision.action;
|
|
57
|
+
const handler = action?.kind ? options.handlers?.[action.kind] : undefined;
|
|
58
|
+
if (!action || !handler) {
|
|
59
|
+
void reportOutcome(decision.decisionId, 'failed', {
|
|
60
|
+
reason: 'unknown_action_kind',
|
|
61
|
+
kind: action?.kind ?? null
|
|
62
|
+
});
|
|
63
|
+
return decision;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const result = await handler(action, decision);
|
|
67
|
+
void reportOutcome(decision.decisionId, result?.outcome ?? 'accepted', result?.metadata);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
options.onError?.(error);
|
|
70
|
+
void reportOutcome(decision.decisionId, 'failed', {
|
|
71
|
+
reason: 'handler_failed'
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return decision;
|
|
75
|
+
} catch (error) {
|
|
76
|
+
options.onError?.(error);
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
decide,
|
|
82
|
+
reportOutcome
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function parseDecision(raw) {
|
|
86
|
+
if (!raw || typeof raw !== 'object') throw new Error('Malformed Pulse decision');
|
|
87
|
+
const value = raw;
|
|
88
|
+
if (typeof value.decisionId !== 'string' || typeof value.execute !== 'boolean' || typeof value.mode !== 'string' || typeof value.verdict !== 'string' || typeof value.reasonCode !== 'string') throw new Error('Malformed Pulse decision');
|
|
89
|
+
const action = value.action;
|
|
90
|
+
if (action != null && (typeof action !== 'object' || typeof action.kind !== 'string')) {
|
|
91
|
+
throw new Error('Malformed Pulse action');
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
decisionId: value.decisionId,
|
|
95
|
+
replayed: value.replayed === true,
|
|
96
|
+
execute: value.execute,
|
|
97
|
+
mode: value.mode,
|
|
98
|
+
verdict: value.verdict,
|
|
99
|
+
reasonCode: value.reasonCode,
|
|
100
|
+
policyKey: typeof value.policyKey === 'string' ? value.policyKey : null,
|
|
101
|
+
policyVersion: typeof value.policyVersion === 'number' ? value.policyVersion : null,
|
|
102
|
+
action: action ?? null
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
async function timedFetch(fetcher, url, init, timeoutMs) {
|
|
106
|
+
const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
|
107
|
+
const timer = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
108
|
+
try {
|
|
109
|
+
return await fetcher(url, {
|
|
110
|
+
...init,
|
|
111
|
+
signal: controller?.signal
|
|
112
|
+
});
|
|
113
|
+
} finally {
|
|
114
|
+
if (timer) clearTimeout(timer);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function randomKey() {
|
|
118
|
+
const cryptoLike = globalThis.crypto;
|
|
119
|
+
if (typeof cryptoLike?.randomUUID === 'function') return cryptoLike.randomUUID();
|
|
120
|
+
return `moment-${Date.now()}-${Math.random().toString(36).slice(2, 14)}`;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=decisions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["createPulseDecisionClient","options","fetcher","fetch","globalThis","base","apiUrl","replace","slug","encodeURIComponent","appSlug","timeoutMs","Math","max","executionMode","reportOutcome","decisionId","outcome","metadata","response","timedFetch","method","headers","body","JSON","stringify","ok","error","onError","decide","trigger","request","context","getContext","attributes","channel","idempotencyKey","randomKey","Error","status","decision","parseDecision","json","execute","reason","action","handler","kind","handlers","undefined","result","raw","value","mode","verdict","reasonCode","replayed","policyKey","policyVersion","url","init","controller","AbortController","timer","setTimeout","abort","signal","clearTimeout","cryptoLike","crypto","randomUUID","Date","now","random","toString","slice"],"sourceRoot":"../../src","sources":["decisions.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["usePulseUpdates","initializeAssetResolver","updateLocalAssets"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AAAA,cAAc,gBAAgB;AAC9B,cAAc,SAAS;AACvB,SAASA,eAAe,QAAQ,mBAAmB;AACnD,SAASC,uBAAuB,EAAEC,iBAAiB,QAAQ,iBAAiB;AAC5E,cAAc,UAAU;AACxB,cAAc,SAAS;AACvB,cAAc,QAAQ","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["usePulseUpdates","initializeAssetResolver","updateLocalAssets"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AAAA,cAAc,gBAAgB;AAC9B,cAAc,SAAS;AACvB,SAASA,eAAe,QAAQ,mBAAmB;AACnD,SAASC,uBAAuB,EAAEC,iBAAiB,QAAQ,iBAAiB;AAC5E,cAAc,UAAU;AACxB,cAAc,SAAS;AACvB,cAAc,QAAQ;AACtB,cAAc,aAAa","ignoreList":[]}
|
package/lib/module/init.js
CHANGED
|
@@ -23,53 +23,166 @@
|
|
|
23
23
|
* installs — a targeting bug that looks like a rollout that "did not work".
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import { configureConfig, fetchConfig, startConfigAutoRefresh } from './config';
|
|
27
|
-
import { configureTracking } from './track';
|
|
26
|
+
import { configureConfig, fetchConfig, startConfigAutoRefresh, getConfigInfo, getConfigBoolean, getConfigNumber, getConfigString, getConfigJson } from './config';
|
|
27
|
+
import { configureTracking, disposeTracking, flushEvents, getTrackingInfo, track } from './track';
|
|
28
28
|
const DEVICE_ID_KEY = 'pulse.device-id';
|
|
29
|
+
let activeClient = null;
|
|
30
|
+
let stopActiveRefresh = null;
|
|
29
31
|
|
|
30
32
|
/** Wires config and events, and returns the context the two share. */
|
|
31
33
|
export function initPulse(opts) {
|
|
34
|
+
// Reconfiguration is synchronous. Calling the old async dispose without awaiting
|
|
35
|
+
// it lets its eventual flush tear down the brand-new tracker — exactly the race a
|
|
36
|
+
// fast app switch or test setup triggers. Persist the old outbox, stop its refresh,
|
|
37
|
+
// then configure the new app in one uninterrupted turn.
|
|
38
|
+
stopActiveRefresh?.();
|
|
39
|
+
disposeTracking();
|
|
40
|
+
activeClient = null;
|
|
41
|
+
stopActiveRefresh = null;
|
|
32
42
|
const base = opts.apiUrl.replace(/\/+$/, '');
|
|
33
43
|
const slug = opts.appSlug.trim();
|
|
34
44
|
const configUrl = `${base}/pulse/config/${slug}`;
|
|
35
45
|
const trackUrl = `${base}/pulse/track/${slug}`;
|
|
36
|
-
const
|
|
46
|
+
const deviceStorageKey = `pulse.${slug}.device-id`;
|
|
47
|
+
let deviceId = opts.deviceId?.trim() || resolveDeviceId(opts.storage, deviceStorageKey);
|
|
37
48
|
const platform = detectPlatform();
|
|
38
49
|
const osVersion = detectOsVersion();
|
|
50
|
+
const appVersion = opts.appVersion ?? detectAppVersion();
|
|
51
|
+
const language = opts.language ?? detectLanguage();
|
|
52
|
+
let userId;
|
|
53
|
+
let userAttributes;
|
|
54
|
+
let consentOverride = typeof opts.analyticsConsent === 'boolean' ? opts.analyticsConsent : undefined;
|
|
55
|
+
const hasConsent = () => consentOverride ?? (typeof opts.analyticsConsent === 'function' ? opts.analyticsConsent() : true);
|
|
39
56
|
const getContext = () => ({
|
|
40
57
|
platform,
|
|
41
58
|
osVersion,
|
|
42
|
-
appVersion
|
|
59
|
+
appVersion,
|
|
60
|
+
language,
|
|
43
61
|
deviceId,
|
|
44
|
-
userId: opts.getUserId?.(),
|
|
45
|
-
userAttributes: opts.getUserAttributes?.()
|
|
62
|
+
userId: userId ?? opts.getUserId?.(),
|
|
63
|
+
userAttributes: userAttributes ?? opts.getUserAttributes?.()
|
|
46
64
|
});
|
|
47
65
|
configureConfig({
|
|
48
66
|
url: configUrl,
|
|
49
67
|
defaults: opts.defaults,
|
|
50
68
|
storage: opts.storage,
|
|
69
|
+
storageKey: `pulse.${slug}.config.v1`,
|
|
51
70
|
getContext,
|
|
52
71
|
pollIntervalMs: opts.pollIntervalMs,
|
|
53
|
-
onError: opts.onError
|
|
72
|
+
onError: opts.onError,
|
|
73
|
+
signingPublicKey: opts.signingPublicKey,
|
|
74
|
+
signingKeyId: opts.signingKeyId,
|
|
75
|
+
requireSignature: opts.requireConfigSignature,
|
|
76
|
+
verifySignature: opts.verifyConfigSignature ?? (opts.requireConfigSignature && !opts.signingPublicKey ? verifyWithNativeKey : undefined)
|
|
54
77
|
});
|
|
55
78
|
configureTracking({
|
|
56
79
|
url: trackUrl,
|
|
57
80
|
getContext,
|
|
58
81
|
flushIntervalMs: opts.flushIntervalMs,
|
|
82
|
+
storage: opts.storage,
|
|
83
|
+
storageKey: `pulse.${slug}.events.v1`,
|
|
84
|
+
hasConsent,
|
|
85
|
+
propertyAllowlist: opts.eventPropertyAllowlist,
|
|
86
|
+
redactProperties: opts.redactEventProperties,
|
|
87
|
+
appState: opts.appState,
|
|
59
88
|
onIgnored: opts.onIgnoredEvents,
|
|
60
89
|
onError: opts.onError
|
|
61
90
|
});
|
|
62
91
|
|
|
92
|
+
// The two fields nothing can derive, said out loud when they are missing. Both
|
|
93
|
+
// fail silently and late: without a version, every rule and slice that names one
|
|
94
|
+
// simply does not match this install — which reads as "the rollout did nothing".
|
|
95
|
+
// Without storage the id is new on every launch, so the arm is re-dealt each time
|
|
96
|
+
// and no experiment can mean anything.
|
|
97
|
+
if (!appVersion) {
|
|
98
|
+
opts.onError?.(new Error('Pulse: no appVersion given — version targeting and version slices will not match this install'));
|
|
99
|
+
}
|
|
100
|
+
if (!opts.storage && !opts.deviceId) {
|
|
101
|
+
opts.onError?.(new Error('Pulse: no storage and no deviceId — this install gets a new id every launch, which re-deals its arm'));
|
|
102
|
+
}
|
|
103
|
+
|
|
63
104
|
// Fetch now rather than on the first read: a launch that reads the config before
|
|
64
105
|
// the first response is the launch that runs on defaults, and defaults are the
|
|
65
106
|
// off position of every flag.
|
|
66
107
|
void fetchConfig();
|
|
67
|
-
startConfigAutoRefresh(opts.appState);
|
|
68
|
-
|
|
69
|
-
deviceId
|
|
108
|
+
const stopRefresh = startConfigAutoRefresh(opts.appState);
|
|
109
|
+
const client = {
|
|
110
|
+
get deviceId() {
|
|
111
|
+
return deviceId;
|
|
112
|
+
},
|
|
70
113
|
configUrl,
|
|
71
|
-
trackUrl
|
|
114
|
+
trackUrl,
|
|
115
|
+
track,
|
|
116
|
+
flush: flushEvents,
|
|
117
|
+
setUser: (nextUserId, attributes) => {
|
|
118
|
+
userId = nextUserId?.trim() || undefined;
|
|
119
|
+
userAttributes = sanitizeAttributes(attributes);
|
|
120
|
+
},
|
|
121
|
+
clearUser: () => {
|
|
122
|
+
userId = undefined;
|
|
123
|
+
userAttributes = undefined;
|
|
124
|
+
},
|
|
125
|
+
setAnalyticsConsent: granted => {
|
|
126
|
+
consentOverride = granted;
|
|
127
|
+
},
|
|
128
|
+
resetInstallId: () => {
|
|
129
|
+
deviceId = randomId();
|
|
130
|
+
try {
|
|
131
|
+
opts.storage?.set(deviceStorageKey, deviceId);
|
|
132
|
+
} catch {/* memory-only fallback */}
|
|
133
|
+
return deviceId;
|
|
134
|
+
},
|
|
135
|
+
health: () => ({
|
|
136
|
+
appSlug: slug,
|
|
137
|
+
deviceId,
|
|
138
|
+
config: getConfigInfo(),
|
|
139
|
+
events: getTrackingInfo(),
|
|
140
|
+
analyticsConsent: hasConsent()
|
|
141
|
+
}),
|
|
142
|
+
config: {
|
|
143
|
+
boolean: getConfigBoolean,
|
|
144
|
+
number: getConfigNumber,
|
|
145
|
+
string: getConfigString,
|
|
146
|
+
json: getConfigJson,
|
|
147
|
+
refresh: fetchConfig
|
|
148
|
+
},
|
|
149
|
+
dispose: async () => {
|
|
150
|
+
stopRefresh();
|
|
151
|
+
if (activeClient !== client) return;
|
|
152
|
+
await flushEvents();
|
|
153
|
+
// Another init may have taken ownership while this network flush was pending.
|
|
154
|
+
if (activeClient === client) {
|
|
155
|
+
disposeTracking();
|
|
156
|
+
activeClient = null;
|
|
157
|
+
stopActiveRefresh = null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
72
160
|
};
|
|
161
|
+
activeClient = client;
|
|
162
|
+
stopActiveRefresh = stopRefresh;
|
|
163
|
+
return client;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* AsyncStorage-friendly one-call setup. It preloads only Pulse's three app-scoped
|
|
168
|
+
* records, then exposes the same synchronous hot-path API as initPulse.
|
|
169
|
+
*/
|
|
170
|
+
export async function initPulseAsync(opts) {
|
|
171
|
+
const slug = opts.appSlug.trim();
|
|
172
|
+
const keys = [`pulse.${slug}.device-id`, `pulse.${slug}.config.v1`, `pulse.${slug}.events.v1`, DEVICE_ID_KEY];
|
|
173
|
+
const loaded = await Promise.all(keys.map(async key => [key, await opts.storage.getItem(key)]));
|
|
174
|
+
const memory = new Map(loaded.filter(entry => entry[1] !== null));
|
|
175
|
+
const storage = {
|
|
176
|
+
getString: key => memory.get(key),
|
|
177
|
+
set: (key, value) => {
|
|
178
|
+
memory.set(key, value);
|
|
179
|
+
void opts.storage.setItem(key, value);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
return initPulse({
|
|
183
|
+
...opts,
|
|
184
|
+
storage
|
|
185
|
+
});
|
|
73
186
|
}
|
|
74
187
|
|
|
75
188
|
/**
|
|
@@ -79,18 +192,23 @@ export function initPulse(opts) {
|
|
|
79
192
|
* arm is a hash of it, so every launch would be a fresh coin toss and no experiment
|
|
80
193
|
* could mean anything. Said out loud through onError rather than hidden.
|
|
81
194
|
*/
|
|
82
|
-
function resolveDeviceId(storage) {
|
|
195
|
+
function resolveDeviceId(storage, key = DEVICE_ID_KEY) {
|
|
83
196
|
if (!storage) return randomId();
|
|
84
197
|
try {
|
|
85
|
-
const existing = storage.getString(DEVICE_ID_KEY);
|
|
198
|
+
const existing = storage.getString(key) ?? storage.getString(DEVICE_ID_KEY);
|
|
86
199
|
if (existing) return existing;
|
|
87
200
|
const minted = randomId();
|
|
88
|
-
storage.set(
|
|
201
|
+
storage.set(key, minted);
|
|
89
202
|
return minted;
|
|
90
203
|
} catch {
|
|
91
204
|
return randomId();
|
|
92
205
|
}
|
|
93
206
|
}
|
|
207
|
+
function sanitizeAttributes(attributes) {
|
|
208
|
+
if (!attributes) return undefined;
|
|
209
|
+
const clean = Object.fromEntries(Object.entries(attributes).filter(([key, value]) => key.trim() !== '' && typeof value === 'string').slice(0, 50));
|
|
210
|
+
return Object.keys(clean).length > 0 ? clean : undefined;
|
|
211
|
+
}
|
|
94
212
|
function randomId() {
|
|
95
213
|
const bytes = new Uint8Array(16);
|
|
96
214
|
const crypto = globalThis.crypto;
|
|
@@ -129,4 +247,37 @@ function detectOsVersion() {
|
|
|
129
247
|
return undefined;
|
|
130
248
|
}
|
|
131
249
|
}
|
|
250
|
+
function detectAppVersion() {
|
|
251
|
+
try {
|
|
252
|
+
// Optional by design: most RN apps already carry this package, plain JS hosts do not.
|
|
253
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
254
|
+
const loaded = require('react-native-device-info');
|
|
255
|
+
return loaded.default?.getVersion?.() ?? loaded.getVersion?.();
|
|
256
|
+
} catch {
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
async function verifyWithNativeKey(canonicalPayload, signature) {
|
|
261
|
+
try {
|
|
262
|
+
// Kept lazy so init/config remain usable in Node, web and test hosts without RN.
|
|
263
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
264
|
+
const updates = require('./PulseUpdates');
|
|
265
|
+
return (await updates.verifyConfigSignatureAsync?.(canonicalPayload, signature)) ?? false;
|
|
266
|
+
} catch {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
function detectLanguage() {
|
|
271
|
+
try {
|
|
272
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
273
|
+
const localize = require('react-native-localize');
|
|
274
|
+
return localize.getLocales?.()[0]?.languageTag;
|
|
275
|
+
} catch {
|
|
276
|
+
try {
|
|
277
|
+
return Intl.DateTimeFormat().resolvedOptions().locale;
|
|
278
|
+
} catch {
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
132
283
|
//# sourceMappingURL=init.js.map
|
package/lib/module/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["configureConfig","fetchConfig","startConfigAutoRefresh","configureTracking","DEVICE_ID_KEY","initPulse","opts","base","apiUrl","replace","slug","appSlug","trim","configUrl","trackUrl","deviceId","resolveDeviceId","storage","platform","detectPlatform","osVersion","detectOsVersion","getContext","appVersion","userId","getUserId","userAttributes","getUserAttributes","url","defaults","pollIntervalMs","onError","flushIntervalMs","onIgnored","onIgnoredEvents","appState","randomId","existing","getString","minted","set","bytes","Uint8Array","crypto","globalThis","getRandomValues","i","length","Math","floor","random","hex","Array","from","b","toString","padStart","join","slice","rn","require","Platform","OS","undefined","version","Version","String"],"sourceRoot":"../../src","sources":["init.ts"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["configureConfig","fetchConfig","startConfigAutoRefresh","getConfigInfo","getConfigBoolean","getConfigNumber","getConfigString","getConfigJson","configureTracking","disposeTracking","flushEvents","getTrackingInfo","track","DEVICE_ID_KEY","activeClient","stopActiveRefresh","initPulse","opts","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","url","defaults","storageKey","pollIntervalMs","onError","signingPublicKey","signingKeyId","requireSignature","requireConfigSignature","verifySignature","verifyConfigSignature","verifyWithNativeKey","flushIntervalMs","propertyAllowlist","eventPropertyAllowlist","redactProperties","redactEventProperties","appState","onIgnored","onIgnoredEvents","Error","stopRefresh","client","flush","setUser","nextUserId","attributes","sanitizeAttributes","clearUser","setAnalyticsConsent","granted","resetInstallId","randomId","set","health","config","events","boolean","number","string","json","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","require","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":[]}
|