@wireai/activation 0.4.0 → 0.8.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/AGENTS.md +1 -1
- package/CHANGELOG.md +92 -0
- package/dist/analytics/index.d.mts +19 -2
- package/dist/analytics/index.d.ts +19 -2
- package/dist/analytics/index.js +258 -18
- package/dist/analytics/index.js.map +1 -1
- package/dist/analytics/index.mjs +256 -19
- package/dist/analytics/index.mjs.map +1 -1
- package/dist/{eventQueue-CA1d8Fmn.d.mts → currentSession-d9CrBxwe.d.mts} +152 -16
- package/dist/{eventQueue-CrNB9gzH.d.ts → currentSession-f7LWcdWG.d.ts} +152 -16
- package/dist/index.d.mts +96 -32
- package/dist/index.d.ts +96 -32
- package/dist/index.js +214 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +201 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/WireOnboarding.tsx +4 -3
- package/src/analytics/analyticsFacade.ts +120 -12
- package/src/analytics/contextEnvelope.ts +13 -7
- package/src/analytics/currentSession.ts +35 -0
- package/src/analytics/index.ts +3 -0
- package/src/context/deviceId.ts +43 -0
- package/src/context/userContext.ts +210 -0
- package/src/device/appVersion.ts +103 -0
- package/src/device/deviceContext.ts +31 -6
- package/src/device/deviceModel.ts +93 -0
- package/src/identity/userIdentity.ts +5 -0
- package/src/index.ts +25 -0
- package/src/session-analytics/reportSessionStart.ts +7 -0
- package/src/session-analytics/useLifecycleEvents.ts +4 -2
- package/src/session-analytics/useSessionStart.ts +2 -1
- package/src/types.ts +6 -5
package/dist/analytics/index.mjs
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { useRef, useEffect } from 'react';
|
|
2
2
|
import { Platform, Dimensions, I18nManager } from 'react-native';
|
|
3
3
|
|
|
4
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
5
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
6
|
+
}) : x)(function(x) {
|
|
7
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
8
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
9
|
+
});
|
|
10
|
+
|
|
4
11
|
// src/reviews/transport.ts
|
|
5
12
|
var reportAppEvent = (target, name, options = {}) => {
|
|
6
13
|
if (!(target == null ? void 0 : target.serverUrl) || !name) return;
|
|
@@ -155,6 +162,98 @@ var toAnalyticsEvent = (event) => {
|
|
|
155
162
|
}
|
|
156
163
|
}
|
|
157
164
|
};
|
|
165
|
+
|
|
166
|
+
// src/device/appVersion.ts
|
|
167
|
+
var coerceVersion = (value) => {
|
|
168
|
+
if (typeof value !== "string") return void 0;
|
|
169
|
+
const trimmed = value.trim();
|
|
170
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
171
|
+
};
|
|
172
|
+
var runtimeRequire = (moduleName) => {
|
|
173
|
+
try {
|
|
174
|
+
if (typeof __require !== "function") return void 0;
|
|
175
|
+
return __require(moduleName);
|
|
176
|
+
} catch {
|
|
177
|
+
return void 0;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
var interop = (mod) => {
|
|
181
|
+
if (!mod || typeof mod !== "object") return void 0;
|
|
182
|
+
const def = mod.default;
|
|
183
|
+
if (def && typeof def === "object") return def;
|
|
184
|
+
return mod;
|
|
185
|
+
};
|
|
186
|
+
var safeInterop = (requireModule, moduleName) => {
|
|
187
|
+
try {
|
|
188
|
+
return interop(requireModule(moduleName));
|
|
189
|
+
} catch {
|
|
190
|
+
return void 0;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
var detectAppVersion = (requireModule = runtimeRequire) => {
|
|
194
|
+
try {
|
|
195
|
+
const constants = safeInterop(requireModule, "expo-constants");
|
|
196
|
+
if (constants) {
|
|
197
|
+
const expoConfig = constants.expoConfig;
|
|
198
|
+
if (expoConfig && typeof expoConfig === "object") {
|
|
199
|
+
const fromExpoConfig = coerceVersion(expoConfig.version);
|
|
200
|
+
if (fromExpoConfig) return fromExpoConfig;
|
|
201
|
+
}
|
|
202
|
+
const fromNative = coerceVersion(constants.nativeAppVersion);
|
|
203
|
+
if (fromNative) return fromNative;
|
|
204
|
+
}
|
|
205
|
+
const application = safeInterop(requireModule, "expo-application");
|
|
206
|
+
if (application) {
|
|
207
|
+
const fromApplication = coerceVersion(application.nativeApplicationVersion);
|
|
208
|
+
if (fromApplication) return fromApplication;
|
|
209
|
+
}
|
|
210
|
+
} catch {
|
|
211
|
+
}
|
|
212
|
+
return void 0;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// src/device/deviceModel.ts
|
|
216
|
+
var coerceModel = (value) => {
|
|
217
|
+
if (typeof value !== "string") return void 0;
|
|
218
|
+
const trimmed = value.trim();
|
|
219
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
220
|
+
};
|
|
221
|
+
var runtimeRequire2 = (moduleName) => {
|
|
222
|
+
try {
|
|
223
|
+
if (typeof __require !== "function") return void 0;
|
|
224
|
+
return __require(moduleName);
|
|
225
|
+
} catch {
|
|
226
|
+
return void 0;
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
var interop2 = (mod) => {
|
|
230
|
+
if (!mod || typeof mod !== "object") return void 0;
|
|
231
|
+
const def = mod.default;
|
|
232
|
+
if (def && typeof def === "object") return def;
|
|
233
|
+
return mod;
|
|
234
|
+
};
|
|
235
|
+
var safeInterop2 = (requireModule, moduleName) => {
|
|
236
|
+
try {
|
|
237
|
+
return interop2(requireModule(moduleName));
|
|
238
|
+
} catch {
|
|
239
|
+
return void 0;
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
var detectNativeModel = (requireModule = runtimeRequire2) => {
|
|
243
|
+
try {
|
|
244
|
+
const device = safeInterop2(requireModule, "expo-device");
|
|
245
|
+
if (device) {
|
|
246
|
+
const modelName = coerceModel(device.modelName);
|
|
247
|
+
if (modelName) return modelName;
|
|
248
|
+
const modelId = coerceModel(device.modelId);
|
|
249
|
+
if (modelId) return modelId;
|
|
250
|
+
}
|
|
251
|
+
} catch {
|
|
252
|
+
}
|
|
253
|
+
return void 0;
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
// src/device/deviceContext.ts
|
|
158
257
|
var deriveFormFactor = (iosIdiom, width, height) => {
|
|
159
258
|
if (iosIdiom === "pad") return "tablet";
|
|
160
259
|
if (iosIdiom === "phone") return "phone";
|
|
@@ -200,6 +299,8 @@ var collectDeviceContext = () => {
|
|
|
200
299
|
ctx.interfaceIdiom = idiom;
|
|
201
300
|
iosIdiom = idiom;
|
|
202
301
|
}
|
|
302
|
+
const iosModel = detectNativeModel();
|
|
303
|
+
if (iosModel) ctx.model = iosModel;
|
|
203
304
|
}
|
|
204
305
|
} catch {
|
|
205
306
|
}
|
|
@@ -224,16 +325,20 @@ var collectDeviceContext = () => {
|
|
|
224
325
|
if (resolved.timeZone) ctx.timeZone = resolved.timeZone;
|
|
225
326
|
} catch {
|
|
226
327
|
}
|
|
328
|
+
const appVersion = detectAppVersion();
|
|
329
|
+
if (appVersion) ctx.appVersion = appVersion;
|
|
227
330
|
return ctx;
|
|
228
331
|
};
|
|
229
332
|
|
|
230
333
|
// src/analytics/contextEnvelope.ts
|
|
231
334
|
var buildContextEnvelope = (input = {}) => {
|
|
335
|
+
var _a;
|
|
232
336
|
const device = { ...collectDeviceContext() };
|
|
233
|
-
if (input.appVersion
|
|
337
|
+
if (input.appVersion) device.appVersion = input.appVersion;
|
|
338
|
+
const effectiveAppVersion = (_a = input.appVersion) != null ? _a : device.appVersion;
|
|
234
339
|
const envelope = { device };
|
|
235
340
|
if (input.sessionId) envelope.sessionId = input.sessionId;
|
|
236
|
-
if (
|
|
341
|
+
if (effectiveAppVersion) envelope.appVersion = effectiveAppVersion;
|
|
237
342
|
if (input.appBuild) envelope.appBuild = input.appBuild;
|
|
238
343
|
if (input.networkType) envelope.networkType = input.networkType;
|
|
239
344
|
return envelope;
|
|
@@ -447,6 +552,16 @@ var createEventQueue = (options) => {
|
|
|
447
552
|
return { enqueue, flush, notifyOnline, size };
|
|
448
553
|
};
|
|
449
554
|
|
|
555
|
+
// src/analytics/currentSession.ts
|
|
556
|
+
var _currentSessionId;
|
|
557
|
+
var setCurrentSessionId = (id) => {
|
|
558
|
+
if (typeof id === "string" && id.length > 0) _currentSessionId = id;
|
|
559
|
+
};
|
|
560
|
+
var getCurrentSessionId = () => _currentSessionId;
|
|
561
|
+
var resetCurrentSessionId = () => {
|
|
562
|
+
_currentSessionId = void 0;
|
|
563
|
+
};
|
|
564
|
+
|
|
450
565
|
// src/identity/userIdentity.ts
|
|
451
566
|
var USER_ID_MAX_LENGTH = 128;
|
|
452
567
|
var sanitizeUserId = (raw) => {
|
|
@@ -456,16 +571,109 @@ var sanitizeUserId = (raw) => {
|
|
|
456
571
|
return trimmed.length > USER_ID_MAX_LENGTH ? trimmed.slice(0, USER_ID_MAX_LENGTH) : trimmed;
|
|
457
572
|
};
|
|
458
573
|
|
|
574
|
+
// src/context/userContext.ts
|
|
575
|
+
var EXTRA_KEY_PREFIX = "custom.";
|
|
576
|
+
var isWireScalar = (value) => {
|
|
577
|
+
const t = typeof value;
|
|
578
|
+
if (t === "string" || t === "boolean") return true;
|
|
579
|
+
if (t === "number") return Number.isFinite(value);
|
|
580
|
+
return false;
|
|
581
|
+
};
|
|
582
|
+
var hashEmailFnv1a = (email) => {
|
|
583
|
+
const normalized = email.trim().toLowerCase();
|
|
584
|
+
let hash = 2166136261;
|
|
585
|
+
for (let i = 0; i < normalized.length; i++) {
|
|
586
|
+
hash ^= normalized.charCodeAt(i);
|
|
587
|
+
hash = Math.imul(hash, 16777619);
|
|
588
|
+
}
|
|
589
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
590
|
+
};
|
|
591
|
+
var cleanString = (value) => {
|
|
592
|
+
if (typeof value !== "string") return void 0;
|
|
593
|
+
const trimmed = value.trim();
|
|
594
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
595
|
+
};
|
|
596
|
+
var namespaceExtra = (extra) => {
|
|
597
|
+
const out = {};
|
|
598
|
+
if (!extra || typeof extra !== "object") return out;
|
|
599
|
+
for (const [key, value] of Object.entries(extra)) {
|
|
600
|
+
const cleanKey = cleanString(key);
|
|
601
|
+
if (!cleanKey) continue;
|
|
602
|
+
if (!isWireScalar(value)) continue;
|
|
603
|
+
out[`${EXTRA_KEY_PREFIX}${cleanKey}`] = value;
|
|
604
|
+
}
|
|
605
|
+
return out;
|
|
606
|
+
};
|
|
607
|
+
var resolveUserContext = (ctx = {}, opts = {}) => {
|
|
608
|
+
var _a;
|
|
609
|
+
const result = {};
|
|
610
|
+
const bucket = {};
|
|
611
|
+
const userId = sanitizeUserId(ctx.userId);
|
|
612
|
+
if (userId) result.userId = userId;
|
|
613
|
+
const deviceKey = cleanString(ctx.deviceKey);
|
|
614
|
+
if (deviceKey) {
|
|
615
|
+
result.deviceKey = deviceKey;
|
|
616
|
+
bucket.device_key = deviceKey;
|
|
617
|
+
}
|
|
618
|
+
const appVersion = (_a = cleanString(ctx.appVersion)) != null ? _a : cleanString(opts.autoAppVersion);
|
|
619
|
+
if (appVersion) {
|
|
620
|
+
result.appVersion = appVersion;
|
|
621
|
+
bucket.app_version = appVersion;
|
|
622
|
+
}
|
|
623
|
+
const email = cleanString(ctx.userEmail);
|
|
624
|
+
if (email) {
|
|
625
|
+
if (ctx.hashEmail) {
|
|
626
|
+
bucket.user_email = hashEmailFnv1a(email);
|
|
627
|
+
bucket.user_email_hashed = true;
|
|
628
|
+
} else {
|
|
629
|
+
bucket.user_email = email;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
Object.assign(bucket, namespaceExtra(ctx.extra));
|
|
633
|
+
if (Object.keys(bucket).length > 0) result.userContext = bucket;
|
|
634
|
+
return result;
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
// src/context/deviceId.ts
|
|
638
|
+
var AUTO_DEVICE_ID_PREFIX = "wdev_";
|
|
639
|
+
var deviceIdStorageKey = (appId) => `wireai:analytics:deviceKey:${appId != null ? appId : "default"}`;
|
|
640
|
+
var randomChunk = () => Math.floor(Math.random() * 4294967296).toString(36).padStart(6, "0");
|
|
641
|
+
var mintDeviceId = () => {
|
|
642
|
+
const time = Date.now().toString(36);
|
|
643
|
+
return `${AUTO_DEVICE_ID_PREFIX}${time}_${randomChunk()}${randomChunk()}`;
|
|
644
|
+
};
|
|
645
|
+
|
|
459
646
|
// src/analytics/analyticsFacade.ts
|
|
460
647
|
var createAnalytics = (config, options = {}) => {
|
|
461
|
-
var _a, _b;
|
|
462
|
-
const
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
648
|
+
var _a, _b, _c, _d, _e;
|
|
649
|
+
const instanceSessionId = (_a = config.sessionId) != null ? _a : makeSessionId();
|
|
650
|
+
const resolveSessionId = () => {
|
|
651
|
+
var _a2, _b2;
|
|
652
|
+
return (_b2 = (_a2 = config.sessionId) != null ? _a2 : getCurrentSessionId()) != null ? _b2 : instanceSessionId;
|
|
653
|
+
};
|
|
654
|
+
let userContext = { ...(_b = config.userContext) != null ? _b : {} };
|
|
655
|
+
const hostDeviceKeyAtInit = typeof ((_c = config.userContext) == null ? void 0 : _c.deviceKey) === "string" && config.userContext.deviceKey.trim() ? config.userContext.deviceKey.trim() : void 0;
|
|
656
|
+
let autoDeviceKey = mintDeviceId();
|
|
657
|
+
if (config.storage && !hostDeviceKeyAtInit) {
|
|
658
|
+
const storage = config.storage;
|
|
659
|
+
const deviceKey = deviceIdStorageKey(config.appId);
|
|
660
|
+
void storage.getItem(deviceKey).then((saved) => {
|
|
661
|
+
const persisted = typeof saved === "string" && saved.trim() ? saved.trim() : void 0;
|
|
662
|
+
if (persisted) autoDeviceKey = persisted;
|
|
663
|
+
else void storage.setItem(deviceKey, autoDeviceKey).catch(() => {
|
|
664
|
+
});
|
|
665
|
+
}).catch(() => {
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
const envelope = () => {
|
|
669
|
+
var _a2;
|
|
670
|
+
return buildContextEnvelope({
|
|
671
|
+
sessionId: resolveSessionId(),
|
|
672
|
+
appVersion: (_a2 = userContext.appVersion) != null ? _a2 : config.appVersion,
|
|
673
|
+
appBuild: config.appBuild,
|
|
674
|
+
networkType: config.networkType
|
|
675
|
+
});
|
|
676
|
+
};
|
|
469
677
|
const queue = createEventQueue({
|
|
470
678
|
target: { serverUrl: config.serverUrl, apiKey: config.apiKey },
|
|
471
679
|
storage: config.storage,
|
|
@@ -473,23 +681,48 @@ var createAnalytics = (config, options = {}) => {
|
|
|
473
681
|
envelope,
|
|
474
682
|
...options
|
|
475
683
|
});
|
|
476
|
-
let boundUserId;
|
|
477
|
-
const storageKey = `wireai:analytics:userId:${(
|
|
684
|
+
let boundUserId = sanitizeUserId((_d = config.userContext) == null ? void 0 : _d.userId);
|
|
685
|
+
const storageKey = `wireai:analytics:userId:${(_e = config.appId) != null ? _e : "default"}`;
|
|
478
686
|
if (config.storage) {
|
|
479
687
|
void config.storage.getItem(storageKey).then((saved) => {
|
|
480
|
-
if (saved) boundUserId = saved;
|
|
688
|
+
if (saved && !boundUserId) boundUserId = saved;
|
|
481
689
|
}).catch(() => {
|
|
482
690
|
});
|
|
483
691
|
}
|
|
692
|
+
const applyContext = (event) => {
|
|
693
|
+
var _a2;
|
|
694
|
+
const hostDeviceKey = typeof userContext.deviceKey === "string" && userContext.deviceKey.trim() ? userContext.deviceKey : void 0;
|
|
695
|
+
const resolved = resolveUserContext(
|
|
696
|
+
{ ...userContext, deviceKey: hostDeviceKey != null ? hostDeviceKey : autoDeviceKey },
|
|
697
|
+
{ autoAppVersion: config.appVersion }
|
|
698
|
+
);
|
|
699
|
+
if (resolved.userContext) {
|
|
700
|
+
event.user_context = { ...resolved.userContext, ...(_a2 = event.user_context) != null ? _a2 : {} };
|
|
701
|
+
}
|
|
702
|
+
if (boundUserId && !event.user_id) event.user_id = boundUserId;
|
|
703
|
+
};
|
|
704
|
+
const setUserContext = (partial) => {
|
|
705
|
+
var _a2, _b2;
|
|
706
|
+
if (!partial || typeof partial !== "object") return;
|
|
707
|
+
const mergedExtra = partial.extra || userContext.extra ? { ...(_a2 = userContext.extra) != null ? _a2 : {}, ...(_b2 = partial.extra) != null ? _b2 : {} } : void 0;
|
|
708
|
+
userContext = { ...userContext, ...partial };
|
|
709
|
+
if (mergedExtra) userContext.extra = mergedExtra;
|
|
710
|
+
const uid = sanitizeUserId(partial.userId);
|
|
711
|
+
if (uid) {
|
|
712
|
+
boundUserId = uid;
|
|
713
|
+
if (config.storage) void config.storage.setItem(storageKey, uid).catch(() => {
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
};
|
|
484
717
|
const track = (event, props) => {
|
|
485
718
|
if (!event) return;
|
|
486
719
|
const clientEvent = {
|
|
487
720
|
event_type: "app_event",
|
|
488
|
-
session_id:
|
|
721
|
+
session_id: resolveSessionId(),
|
|
489
722
|
question_key: event
|
|
490
723
|
};
|
|
491
724
|
if (props && Object.keys(props).length > 0) clientEvent.meta = JSON.stringify(props);
|
|
492
|
-
|
|
725
|
+
applyContext(clientEvent);
|
|
493
726
|
queue.enqueue(clientEvent);
|
|
494
727
|
};
|
|
495
728
|
const screen = (name, props) => {
|
|
@@ -497,11 +730,11 @@ var createAnalytics = (config, options = {}) => {
|
|
|
497
730
|
const meta = { screen: name, ...props != null ? props : {} };
|
|
498
731
|
const clientEvent = {
|
|
499
732
|
event_type: "app_event",
|
|
500
|
-
session_id:
|
|
733
|
+
session_id: resolveSessionId(),
|
|
501
734
|
question_key: "screen",
|
|
502
735
|
meta: JSON.stringify(meta)
|
|
503
736
|
};
|
|
504
|
-
|
|
737
|
+
applyContext(clientEvent);
|
|
505
738
|
queue.enqueue(clientEvent);
|
|
506
739
|
};
|
|
507
740
|
const identify = (userId, traits) => {
|
|
@@ -514,16 +747,20 @@ var createAnalytics = (config, options = {}) => {
|
|
|
514
747
|
}
|
|
515
748
|
const clientEvent = {
|
|
516
749
|
event_type: "identify",
|
|
517
|
-
|
|
750
|
+
// Reuse the LIVE per-open session id (see `resolveSessionId`) so the server binds identity to
|
|
751
|
+
// the session it already saw instead of back-filling a phantom `session_started`.
|
|
752
|
+
session_id: resolveSessionId(),
|
|
518
753
|
user_id: clean
|
|
519
754
|
};
|
|
520
755
|
if (traits && Object.keys(traits).length > 0) clientEvent.meta = JSON.stringify(traits);
|
|
756
|
+
applyContext(clientEvent);
|
|
521
757
|
queue.enqueue(clientEvent);
|
|
522
758
|
};
|
|
523
759
|
return {
|
|
524
760
|
track,
|
|
525
761
|
screen,
|
|
526
762
|
identify,
|
|
763
|
+
setUserContext,
|
|
527
764
|
flush: queue.flush,
|
|
528
765
|
notifyOnline: queue.notifyOnline,
|
|
529
766
|
size: queue.size
|
|
@@ -540,6 +777,6 @@ var useAnalytics = (config, options = {}) => {
|
|
|
540
777
|
return ref.current;
|
|
541
778
|
};
|
|
542
779
|
|
|
543
|
-
export { WIRE_ONBOARDING_EVENTS, buildContextEnvelope, createAnalytics, createEventQueue, createScreenTracker, getActiveRouteName, makeSessionId, reportAppEvent, reportClientEvent, reportClientEvents, screenTrackingHandler, toAnalyticsEvent, useAnalytics, useScreenTracking };
|
|
780
|
+
export { WIRE_ONBOARDING_EVENTS, buildContextEnvelope, createAnalytics, createEventQueue, createScreenTracker, getActiveRouteName, getCurrentSessionId, makeSessionId, reportAppEvent, reportClientEvent, reportClientEvents, resetCurrentSessionId, screenTrackingHandler, setCurrentSessionId, toAnalyticsEvent, useAnalytics, useScreenTracking };
|
|
544
781
|
//# sourceMappingURL=index.mjs.map
|
|
545
782
|
//# sourceMappingURL=index.mjs.map
|