@journium/js 1.1.1 → 1.2.1
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/dist/JourniumAnalytics.d.ts.map +1 -1
- package/dist/JourniumClient.d.ts +9 -0
- package/dist/JourniumClient.d.ts.map +1 -1
- package/dist/PageviewTracker.d.ts +3 -2
- package/dist/PageviewTracker.d.ts.map +1 -1
- package/dist/index.cjs +136 -111
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.mjs +136 -111
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +136 -111
- package/dist/index.umd.js.map +1 -1
- package/dist/journium.js +136 -111
- package/dist/journium.js.map +1 -1
- package/dist/journium.min.js +1 -1
- package/dist/journium.min.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JourniumAnalytics.d.ts","sourceRoot":"","sources":["../src/JourniumAnalytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAsB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAK1F,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,kBAAkB,CAAkB;IAC5C,OAAO,CAAC,wBAAwB,CAAC,CAAa;gBAElC,MAAM,EAAE,cAAc;IAqBlC,OAAO,CAAC,yBAAyB;IAiBjC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIhE,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIxE,KAAK,IAAI,IAAI;IAIb,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI3D,gBAAgB,IAAI,IAAI;IA4BxB,eAAe,IAAI,IAAI;IAMvB;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAkCjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;
|
|
1
|
+
{"version":3,"file":"JourniumAnalytics.d.ts","sourceRoot":"","sources":["../src/JourniumAnalytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAsB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAK1F,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,kBAAkB,CAAkB;IAC5C,OAAO,CAAC,wBAAwB,CAAC,CAAa;gBAElC,MAAM,EAAE,cAAc;IAqBlC,OAAO,CAAC,yBAAyB;IAiBjC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIhE,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIxE,KAAK,IAAI,IAAI;IAIb,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI3D,gBAAgB,IAAI,IAAI;IA4BxB,eAAe,IAAI,IAAI;IAMvB;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAkCjC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA+BrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,mBAAmB;IAInB;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI;IAI9E,OAAO,IAAI,IAAI;CAQhB;AAED,eAAO,MAAM,IAAI,WAAY,cAAc,KAAG,iBAE7C,CAAC;;mBAF2B,cAAc,KAAG,iBAAiB;;AAI/D,wBAAwB"}
|
package/dist/JourniumClient.d.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { JourniumConfig, JourniumLocalOptions } from '@journium/core';
|
|
2
2
|
export declare class JourniumClient {
|
|
3
|
+
private static readonly REMOTE_OPTIONS_REFRESH_INTERVAL;
|
|
3
4
|
private config;
|
|
4
5
|
private effectiveOptions;
|
|
5
6
|
private queue;
|
|
6
7
|
private stagedEvents;
|
|
7
8
|
private flushTimer;
|
|
9
|
+
private remoteOptionsRefreshTimer;
|
|
10
|
+
private isRefreshing;
|
|
11
|
+
private lastRemoteOptions;
|
|
8
12
|
private initializationComplete;
|
|
9
13
|
private initializationFailed;
|
|
10
14
|
private identityManager;
|
|
@@ -22,6 +26,10 @@ export declare class JourniumClient {
|
|
|
22
26
|
private notifyOptionsChange;
|
|
23
27
|
private processStagedEvents;
|
|
24
28
|
private startFlushTimer;
|
|
29
|
+
private startRemoteOptionsRefreshTimer;
|
|
30
|
+
private refreshRemoteOptions;
|
|
31
|
+
private applyRemoteOptions;
|
|
32
|
+
private buildIdentityProperties;
|
|
25
33
|
private sendEvents;
|
|
26
34
|
identify(distinctId: string, attributes?: Record<string, unknown>): void;
|
|
27
35
|
reset(): void;
|
|
@@ -29,5 +37,6 @@ export declare class JourniumClient {
|
|
|
29
37
|
flush(): Promise<void>;
|
|
30
38
|
destroy(): void;
|
|
31
39
|
getEffectiveOptions(): JourniumLocalOptions;
|
|
40
|
+
private get ingestionPaused();
|
|
32
41
|
}
|
|
33
42
|
//# sourceMappingURL=JourniumClient.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JourniumClient.d.ts","sourceRoot":"","sources":["../src/JourniumClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,cAAc,EAAyB,oBAAoB,EAAyG,MAAM,gBAAgB,CAAC;AAEnN,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,gBAAgB,CAAwB;IAChD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,sBAAsB,CAAkB;IAChD,OAAO,CAAC,oBAAoB,CAAkB;IAC9C,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,sBAAsB,CAA2D;gBAE7E,MAAM,EAAE,cAAc;IAiClC,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,iBAAiB;YAYX,eAAe;
|
|
1
|
+
{"version":3,"file":"JourniumClient.d.ts","sourceRoot":"","sources":["../src/JourniumClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,cAAc,EAAyB,oBAAoB,EAAyG,MAAM,gBAAgB,CAAC;AAEnN,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,+BAA+B,CAAkB;IAEzE,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,gBAAgB,CAAwB;IAChD,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,yBAAyB,CAA+C;IAChF,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,iBAAiB,CAAsC;IAC/D,OAAO,CAAC,sBAAsB,CAAkB;IAChD,OAAO,CAAC,oBAAoB,CAAkB;IAC9C,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,sBAAsB,CAA2D;gBAE7E,MAAM,EAAE,cAAc;IAiClC,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,iBAAiB;YAYX,eAAe;YAoCf,2BAA2B;IAiDzC;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,GAAG,MAAM,IAAI;IAQ9E,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,8BAA8B;YAcxB,oBAAoB;IA6ClC,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,uBAAuB;YAiBjB,UAAU;IA0BxB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAqB5E,KAAK,IAAI,IAAI;IAab,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAsC9D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B,OAAO,IAAI,IAAI;IAYf,mBAAmB,IAAI,oBAAoB;IAI3C,OAAO,KAAK,eAAe,GAE1B;CACF"}
|
|
@@ -9,9 +9,10 @@ export declare class PageviewTracker {
|
|
|
9
9
|
capturePageview(customProperties?: Record<string, unknown>): void;
|
|
10
10
|
/**
|
|
11
11
|
* Start automatic autocapture for pageviews
|
|
12
|
-
* @
|
|
12
|
+
* @param captureInitialPageview - whether to fire a $pageview immediately on start (default: true).
|
|
13
|
+
* Pass false when restarting after a remote options update to avoid a spurious pageview.
|
|
13
14
|
*/
|
|
14
|
-
startAutoPageviewTracking(): void;
|
|
15
|
+
startAutoPageviewTracking(captureInitialPageview?: boolean): void;
|
|
15
16
|
/**
|
|
16
17
|
* Stop automatic autocapture for pageviews
|
|
17
18
|
* @returns void
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageviewTracker.d.ts","sourceRoot":"","sources":["../src/PageviewTracker.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,iBAAiB,CAAgD;IACzE,OAAO,CAAC,oBAAoB,CAAmD;IAC/E,OAAO,CAAC,eAAe,CAA6B;gBAExC,MAAM,EAAE,cAAc;IAIlC,eAAe,CAAC,gBAAgB,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAkBrE
|
|
1
|
+
{"version":3,"file":"PageviewTracker.d.ts","sourceRoot":"","sources":["../src/PageviewTracker.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,iBAAiB,CAAgD;IACzE,OAAO,CAAC,oBAAoB,CAAmD;IAC/E,OAAO,CAAC,eAAe,CAA6B;gBAExC,MAAM,EAAE,cAAc;IAIlC,eAAe,CAAC,gBAAgB,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI;IAkBrE;;;;OAIG;IACH,yBAAyB,CAAC,sBAAsB,GAAE,OAAc,GAAG,IAAI;IA4BvE;;;OAGG;IACH,eAAe,IAAI,IAAI;CAmBxB"}
|
package/dist/index.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* uuidv7: A JavaScript implementation of UUID version 7
|
|
5
5
|
*
|
|
6
|
-
* Copyright 2021-
|
|
6
|
+
* Copyright 2021-2025 LiosK
|
|
7
7
|
*
|
|
8
8
|
* @license Apache-2.0
|
|
9
9
|
* @packageDocumentation
|
|
@@ -232,7 +232,10 @@ class V7Generator {
|
|
|
232
232
|
* number generator should be cryptographically strong and securely seeded.
|
|
233
233
|
*/
|
|
234
234
|
constructor(randomNumberGenerator) {
|
|
235
|
-
|
|
235
|
+
/**
|
|
236
|
+
* Biased by one to distinguish zero (uninitialized) and zero (UNIX epoch).
|
|
237
|
+
*/
|
|
238
|
+
this.timestamp_biased = 0;
|
|
236
239
|
this.counter = 0;
|
|
237
240
|
this.random = randomNumberGenerator !== null && randomNumberGenerator !== void 0 ? randomNumberGenerator : getDefaultRandom();
|
|
238
241
|
}
|
|
@@ -278,13 +281,13 @@ class V7Generator {
|
|
|
278
281
|
*
|
|
279
282
|
* @param rollbackAllowance - The amount of `unixTsMs` rollback that is
|
|
280
283
|
* considered significant. A suggested value is `10_000` (milliseconds).
|
|
281
|
-
* @throws RangeError if `unixTsMs` is not a 48-bit
|
|
284
|
+
* @throws RangeError if `unixTsMs` is not a 48-bit unsigned integer.
|
|
282
285
|
*/
|
|
283
286
|
generateOrResetCore(unixTsMs, rollbackAllowance) {
|
|
284
287
|
let value = this.generateOrAbortCore(unixTsMs, rollbackAllowance);
|
|
285
288
|
if (value === undefined) {
|
|
286
289
|
// reset state and resume
|
|
287
|
-
this.
|
|
290
|
+
this.timestamp_biased = 0;
|
|
288
291
|
value = this.generateOrAbortCore(unixTsMs, rollbackAllowance);
|
|
289
292
|
}
|
|
290
293
|
return value;
|
|
@@ -298,28 +301,29 @@ class V7Generator {
|
|
|
298
301
|
*
|
|
299
302
|
* @param rollbackAllowance - The amount of `unixTsMs` rollback that is
|
|
300
303
|
* considered significant. A suggested value is `10_000` (milliseconds).
|
|
301
|
-
* @throws RangeError if `unixTsMs` is not a 48-bit
|
|
304
|
+
* @throws RangeError if `unixTsMs` is not a 48-bit unsigned integer.
|
|
302
305
|
*/
|
|
303
306
|
generateOrAbortCore(unixTsMs, rollbackAllowance) {
|
|
304
307
|
const MAX_COUNTER = 4398046511103;
|
|
305
308
|
if (!Number.isInteger(unixTsMs) ||
|
|
306
|
-
unixTsMs <
|
|
309
|
+
unixTsMs < 0 ||
|
|
307
310
|
unixTsMs > 281474976710655) {
|
|
308
|
-
throw new RangeError("`unixTsMs` must be a 48-bit
|
|
311
|
+
throw new RangeError("`unixTsMs` must be a 48-bit unsigned integer");
|
|
309
312
|
}
|
|
310
313
|
else if (rollbackAllowance < 0 || rollbackAllowance > 281474976710655) {
|
|
311
314
|
throw new RangeError("`rollbackAllowance` out of reasonable range");
|
|
312
315
|
}
|
|
313
|
-
|
|
314
|
-
|
|
316
|
+
unixTsMs++;
|
|
317
|
+
if (unixTsMs > this.timestamp_biased) {
|
|
318
|
+
this.timestamp_biased = unixTsMs;
|
|
315
319
|
this.resetCounter();
|
|
316
320
|
}
|
|
317
|
-
else if (unixTsMs + rollbackAllowance >= this.
|
|
321
|
+
else if (unixTsMs + rollbackAllowance >= this.timestamp_biased) {
|
|
318
322
|
// go on with previous timestamp if new one is not much smaller
|
|
319
323
|
this.counter++;
|
|
320
324
|
if (this.counter > MAX_COUNTER) {
|
|
321
325
|
// increment timestamp at counter overflow
|
|
322
|
-
this.
|
|
326
|
+
this.timestamp_biased++;
|
|
323
327
|
this.resetCounter();
|
|
324
328
|
}
|
|
325
329
|
}
|
|
@@ -327,7 +331,7 @@ class V7Generator {
|
|
|
327
331
|
// abort if clock went backwards to unbearable extent
|
|
328
332
|
return undefined;
|
|
329
333
|
}
|
|
330
|
-
return UUID.fromFieldsV7(this.
|
|
334
|
+
return UUID.fromFieldsV7(this.timestamp_biased - 1, Math.trunc(this.counter / 2 ** 30), this.counter & (2 ** 30 - 1), this.random.nextUint32());
|
|
331
335
|
}
|
|
332
336
|
/** Initializes the counter at a 42-bit random integer. */
|
|
333
337
|
resetCounter() {
|
|
@@ -703,6 +707,9 @@ class JourniumClient {
|
|
|
703
707
|
this.queue = [];
|
|
704
708
|
this.stagedEvents = [];
|
|
705
709
|
this.flushTimer = null;
|
|
710
|
+
this.remoteOptionsRefreshTimer = null;
|
|
711
|
+
this.isRefreshing = false;
|
|
712
|
+
this.lastRemoteOptions = null;
|
|
706
713
|
this.initializationComplete = false;
|
|
707
714
|
this.initializationFailed = false;
|
|
708
715
|
this.optionsChangeCallbacks = new Set();
|
|
@@ -756,61 +763,24 @@ class JourniumClient {
|
|
|
756
763
|
}
|
|
757
764
|
}
|
|
758
765
|
async initializeAsync() {
|
|
759
|
-
var _a;
|
|
760
766
|
try {
|
|
761
767
|
Logger.log('Journium: Starting initialization - fetching fresh remote config...');
|
|
762
|
-
// Step 1: Try to fetch fresh remote config with timeout and retry
|
|
763
768
|
const remoteOptions = await this.fetchRemoteOptionsWithRetry();
|
|
764
|
-
if (remoteOptions) {
|
|
765
|
-
|
|
766
|
-
this.
|
|
767
|
-
|
|
768
|
-
if (this.config.options) {
|
|
769
|
-
this.effectiveOptions = mergeOptions(this.config.options, remoteOptions);
|
|
770
|
-
Logger.log('Journium: Using fresh remote config merged with local options:', this.effectiveOptions);
|
|
771
|
-
}
|
|
772
|
-
else {
|
|
773
|
-
this.effectiveOptions = remoteOptions;
|
|
774
|
-
Logger.log('Journium: Using fresh remote config:', this.effectiveOptions);
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
else {
|
|
778
|
-
// Step 4: Fallback to cached config if fresh fetch failed
|
|
779
|
-
/* const cachedRemoteOptions = this.loadCachedOptions();
|
|
780
|
-
|
|
781
|
-
if (cachedRemoteOptions) {
|
|
782
|
-
if (this.config.options) {
|
|
783
|
-
this.effectiveOptions = mergeOptions(this.config.options, cachedRemoteOptions);
|
|
784
|
-
Logger.log('Journium: Fresh config failed, using cached remote config merged with local options:', this.effectiveOptions);
|
|
785
|
-
} else {
|
|
786
|
-
this.effectiveOptions = cachedRemoteOptions;
|
|
787
|
-
Logger.log('Journium: Fresh config failed, using cached remote config:', this.effectiveOptions);
|
|
788
|
-
}
|
|
789
|
-
} else {
|
|
790
|
-
// Step 5: No remote config and no cached config - initialization fails
|
|
791
|
-
Logger.error('Journium: Initialization failed - no remote config available and no cached config found');
|
|
792
|
-
this.initializationFailed = true;
|
|
793
|
-
this.initializationComplete = false;
|
|
794
|
-
return;
|
|
795
|
-
} */
|
|
796
|
-
}
|
|
797
|
-
// Step 6: Update identity manager session timeout if provided
|
|
798
|
-
if (this.effectiveOptions.sessionTimeout) {
|
|
799
|
-
this.identityManager.updateSessionTimeout(this.effectiveOptions.sessionTimeout);
|
|
769
|
+
if (!remoteOptions) {
|
|
770
|
+
Logger.error('Journium: Initialization failed - no remote config available');
|
|
771
|
+
this.initializationFailed = true;
|
|
772
|
+
return;
|
|
800
773
|
}
|
|
801
|
-
|
|
802
|
-
Logger.
|
|
803
|
-
// Step 8: Mark initialization as complete
|
|
774
|
+
this.applyRemoteOptions(remoteOptions);
|
|
775
|
+
Logger.log('Journium: Effective options after init:', this.effectiveOptions);
|
|
804
776
|
this.initializationComplete = true;
|
|
805
777
|
this.initializationFailed = false;
|
|
806
|
-
// Step 9: Process any staged events
|
|
807
778
|
this.processStagedEvents();
|
|
808
|
-
// Step 10: Start flush timer
|
|
809
779
|
if (this.effectiveOptions.flushInterval && this.effectiveOptions.flushInterval > 0) {
|
|
810
780
|
this.startFlushTimer();
|
|
811
781
|
}
|
|
812
|
-
|
|
813
|
-
|
|
782
|
+
this.startRemoteOptionsRefreshTimer();
|
|
783
|
+
Logger.log('Journium: Initialization complete');
|
|
814
784
|
this.notifyOptionsChange();
|
|
815
785
|
}
|
|
816
786
|
catch (error) {
|
|
@@ -881,35 +851,21 @@ class JourniumClient {
|
|
|
881
851
|
processStagedEvents() {
|
|
882
852
|
if (this.stagedEvents.length === 0)
|
|
883
853
|
return;
|
|
854
|
+
if (this.ingestionPaused) {
|
|
855
|
+
Logger.warn(`Journium: Ingestion is paused — discarding ${this.stagedEvents.length} staged events`);
|
|
856
|
+
this.stagedEvents = [];
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
884
859
|
Logger.log(`Journium: Processing ${this.stagedEvents.length} staged events`);
|
|
885
|
-
// Move staged events to main queue, adding identity properties now
|
|
886
|
-
const identity = this.identityManager.getIdentity();
|
|
887
|
-
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
888
860
|
for (const stagedEvent of this.stagedEvents) {
|
|
889
|
-
|
|
890
|
-
const eventWithIdentity = {
|
|
861
|
+
this.queue.push({
|
|
891
862
|
...stagedEvent,
|
|
892
|
-
properties:
|
|
893
|
-
|
|
894
|
-
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
895
|
-
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
896
|
-
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
897
|
-
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
898
|
-
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
899
|
-
...userAgentInfo,
|
|
900
|
-
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
901
|
-
$platform: 'web',
|
|
902
|
-
...stagedEvent.properties, // Original properties override system properties
|
|
903
|
-
},
|
|
904
|
-
};
|
|
905
|
-
this.queue.push(eventWithIdentity);
|
|
863
|
+
properties: this.buildIdentityProperties(stagedEvent.properties),
|
|
864
|
+
});
|
|
906
865
|
}
|
|
907
|
-
// Clear staged events
|
|
908
866
|
this.stagedEvents = [];
|
|
909
867
|
Logger.log('Journium: Staged events processed and moved to main queue');
|
|
910
|
-
// Check if we should flush immediately
|
|
911
868
|
if (this.queue.length >= this.effectiveOptions.flushAt) {
|
|
912
|
-
// console.log('1 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
913
869
|
this.flush();
|
|
914
870
|
}
|
|
915
871
|
}
|
|
@@ -917,12 +873,88 @@ class JourniumClient {
|
|
|
917
873
|
if (this.flushTimer) {
|
|
918
874
|
clearInterval(this.flushTimer);
|
|
919
875
|
}
|
|
920
|
-
// Use universal setInterval (works in both browser and Node.js)
|
|
921
876
|
this.flushTimer = setInterval(() => {
|
|
922
|
-
// console.log('2 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
923
877
|
this.flush();
|
|
924
878
|
}, this.effectiveOptions.flushInterval);
|
|
925
879
|
}
|
|
880
|
+
startRemoteOptionsRefreshTimer() {
|
|
881
|
+
// Clear any existing timer to prevent duplicate intervals
|
|
882
|
+
if (this.remoteOptionsRefreshTimer) {
|
|
883
|
+
clearInterval(this.remoteOptionsRefreshTimer);
|
|
884
|
+
this.remoteOptionsRefreshTimer = null;
|
|
885
|
+
}
|
|
886
|
+
this.remoteOptionsRefreshTimer = setInterval(() => {
|
|
887
|
+
this.refreshRemoteOptions();
|
|
888
|
+
}, JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL);
|
|
889
|
+
Logger.log(`Journium: Scheduling remote options refresh every ${JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL}ms`);
|
|
890
|
+
}
|
|
891
|
+
async refreshRemoteOptions() {
|
|
892
|
+
if (this.isRefreshing) {
|
|
893
|
+
Logger.log('Journium: Remote options refresh already in progress, skipping');
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
this.isRefreshing = true;
|
|
897
|
+
Logger.log('Journium: Periodic remote options refresh triggered');
|
|
898
|
+
try {
|
|
899
|
+
const remoteOptions = await this.fetchRemoteOptionsWithRetry();
|
|
900
|
+
if (!remoteOptions) {
|
|
901
|
+
Logger.warn('Journium: Periodic remote options refresh failed, keeping current options');
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
const prevRemoteSnapshot = JSON.stringify(this.lastRemoteOptions);
|
|
905
|
+
const prevFlushInterval = this.effectiveOptions.flushInterval;
|
|
906
|
+
this.applyRemoteOptions(remoteOptions);
|
|
907
|
+
if (prevRemoteSnapshot === JSON.stringify(this.lastRemoteOptions)) {
|
|
908
|
+
Logger.log('Journium: Remote options unchanged after refresh, no update needed');
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
Logger.log('Journium: Remote options updated after refresh:', this.effectiveOptions);
|
|
912
|
+
if (this.effectiveOptions.flushInterval !== prevFlushInterval) {
|
|
913
|
+
if (this.effectiveOptions.flushInterval && this.effectiveOptions.flushInterval > 0) {
|
|
914
|
+
this.startFlushTimer();
|
|
915
|
+
}
|
|
916
|
+
else if (this.flushTimer) {
|
|
917
|
+
clearInterval(this.flushTimer);
|
|
918
|
+
this.flushTimer = null;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
this.notifyOptionsChange();
|
|
922
|
+
}
|
|
923
|
+
catch (error) {
|
|
924
|
+
Logger.error('Journium: Periodic remote options refresh encountered an error:', error);
|
|
925
|
+
}
|
|
926
|
+
finally {
|
|
927
|
+
this.isRefreshing = false;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
applyRemoteOptions(remoteOptions) {
|
|
931
|
+
var _a;
|
|
932
|
+
this.lastRemoteOptions = remoteOptions;
|
|
933
|
+
this.effectiveOptions = this.config.options
|
|
934
|
+
? mergeOptions(this.config.options, remoteOptions)
|
|
935
|
+
: remoteOptions;
|
|
936
|
+
this.saveCachedOptions(remoteOptions);
|
|
937
|
+
if (this.effectiveOptions.sessionTimeout) {
|
|
938
|
+
this.identityManager.updateSessionTimeout(this.effectiveOptions.sessionTimeout);
|
|
939
|
+
}
|
|
940
|
+
Logger.setDebug((_a = this.effectiveOptions.debug) !== null && _a !== void 0 ? _a : false);
|
|
941
|
+
}
|
|
942
|
+
buildIdentityProperties(userProperties = {}) {
|
|
943
|
+
const identity = this.identityManager.getIdentity();
|
|
944
|
+
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
945
|
+
return {
|
|
946
|
+
$device_id: identity === null || identity === void 0 ? void 0 : identity.$device_id,
|
|
947
|
+
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
948
|
+
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
949
|
+
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
950
|
+
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
951
|
+
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
952
|
+
...userAgentInfo,
|
|
953
|
+
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
954
|
+
$platform: 'web',
|
|
955
|
+
...userProperties,
|
|
956
|
+
};
|
|
957
|
+
}
|
|
926
958
|
async sendEvents(events) {
|
|
927
959
|
if (!events.length)
|
|
928
960
|
return;
|
|
@@ -982,9 +1014,7 @@ class JourniumClient {
|
|
|
982
1014
|
event,
|
|
983
1015
|
properties: { ...properties }, // Only user properties for now
|
|
984
1016
|
};
|
|
985
|
-
// Stage events during initialization, add to queue after initialization
|
|
986
1017
|
if (!this.initializationComplete) {
|
|
987
|
-
// If initialization failed, reject events
|
|
988
1018
|
if (this.initializationFailed) {
|
|
989
1019
|
Logger.warn('Journium: track() call rejected - initialization failed');
|
|
990
1020
|
return;
|
|
@@ -993,34 +1023,17 @@ class JourniumClient {
|
|
|
993
1023
|
Logger.log('Journium: Event staged during initialization', journiumEvent);
|
|
994
1024
|
return;
|
|
995
1025
|
}
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
Logger.warn('Journium: track() call rejected - initialization failed');
|
|
1026
|
+
if (this.ingestionPaused) {
|
|
1027
|
+
Logger.warn('Journium: Ingestion is paused — event dropped:', journiumEvent.event);
|
|
999
1028
|
return;
|
|
1000
1029
|
}
|
|
1001
|
-
// Add identity properties for immediate events (after initialization)
|
|
1002
|
-
const identity = this.identityManager.getIdentity();
|
|
1003
|
-
const userAgentInfo = this.identityManager.getUserAgentInfo();
|
|
1004
1030
|
const eventWithIdentity = {
|
|
1005
1031
|
...journiumEvent,
|
|
1006
|
-
properties:
|
|
1007
|
-
$device_id: identity === null || identity === void 0 ? void 0 : identity.$device_id,
|
|
1008
|
-
distinct_id: identity === null || identity === void 0 ? void 0 : identity.distinct_id,
|
|
1009
|
-
$session_id: identity === null || identity === void 0 ? void 0 : identity.$session_id,
|
|
1010
|
-
$is_identified: (identity === null || identity === void 0 ? void 0 : identity.$user_state) === 'identified',
|
|
1011
|
-
$current_url: typeof window !== 'undefined' ? window.location.href : '',
|
|
1012
|
-
$pathname: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
1013
|
-
...userAgentInfo,
|
|
1014
|
-
$lib_version: '0.1.0', // TODO: Get from package.json
|
|
1015
|
-
$platform: 'web',
|
|
1016
|
-
...properties, // User-provided properties override system properties
|
|
1017
|
-
},
|
|
1032
|
+
properties: this.buildIdentityProperties(properties),
|
|
1018
1033
|
};
|
|
1019
1034
|
this.queue.push(eventWithIdentity);
|
|
1020
1035
|
Logger.log('Journium: Event tracked', eventWithIdentity);
|
|
1021
|
-
// Only flush if we have effective options (after initialization)
|
|
1022
1036
|
if (this.effectiveOptions.flushAt && this.queue.length >= this.effectiveOptions.flushAt) {
|
|
1023
|
-
// console.log('3 Journium: Flushing events...'+JSON.stringify(this.effectiveOptions));
|
|
1024
1037
|
this.flush();
|
|
1025
1038
|
}
|
|
1026
1039
|
}
|
|
@@ -1047,12 +1060,20 @@ class JourniumClient {
|
|
|
1047
1060
|
clearInterval(this.flushTimer);
|
|
1048
1061
|
this.flushTimer = null;
|
|
1049
1062
|
}
|
|
1063
|
+
if (this.remoteOptionsRefreshTimer) {
|
|
1064
|
+
clearInterval(this.remoteOptionsRefreshTimer);
|
|
1065
|
+
this.remoteOptionsRefreshTimer = null;
|
|
1066
|
+
}
|
|
1050
1067
|
this.flush();
|
|
1051
1068
|
}
|
|
1052
1069
|
getEffectiveOptions() {
|
|
1053
1070
|
return this.effectiveOptions;
|
|
1054
1071
|
}
|
|
1072
|
+
get ingestionPaused() {
|
|
1073
|
+
return this.effectiveOptions['ingestionPaused'] === true;
|
|
1074
|
+
}
|
|
1055
1075
|
}
|
|
1076
|
+
JourniumClient.REMOTE_OPTIONS_REFRESH_INTERVAL = 15 * 60 * 1000; // 15 minutes
|
|
1056
1077
|
|
|
1057
1078
|
class PageviewTracker {
|
|
1058
1079
|
constructor(client) {
|
|
@@ -1079,10 +1100,13 @@ class PageviewTracker {
|
|
|
1079
1100
|
}
|
|
1080
1101
|
/**
|
|
1081
1102
|
* Start automatic autocapture for pageviews
|
|
1082
|
-
* @
|
|
1103
|
+
* @param captureInitialPageview - whether to fire a $pageview immediately on start (default: true).
|
|
1104
|
+
* Pass false when restarting after a remote options update to avoid a spurious pageview.
|
|
1083
1105
|
*/
|
|
1084
|
-
startAutoPageviewTracking() {
|
|
1085
|
-
|
|
1106
|
+
startAutoPageviewTracking(captureInitialPageview = true) {
|
|
1107
|
+
if (captureInitialPageview) {
|
|
1108
|
+
this.capturePageview();
|
|
1109
|
+
}
|
|
1086
1110
|
if (typeof window !== 'undefined') {
|
|
1087
1111
|
// Store original methods for cleanup
|
|
1088
1112
|
this.originalPushState = window.history.pushState;
|
|
@@ -1601,21 +1625,22 @@ class JourniumAnalytics {
|
|
|
1601
1625
|
* Handle effective options change (e.g., when remote options are fetched)
|
|
1602
1626
|
*/
|
|
1603
1627
|
handleOptionsChange(effectiveOptions) {
|
|
1604
|
-
//
|
|
1628
|
+
// If autocapture was never started before, this is the initial options application
|
|
1629
|
+
// (async init completed) — treat it like a page load and capture a pageview.
|
|
1630
|
+
// If it was already started, this is a periodic remote options update — only
|
|
1631
|
+
// re-register listeners without emitting a spurious pageview.
|
|
1632
|
+
const isFirstStart = !this.autocaptureStarted;
|
|
1605
1633
|
if (this.autocaptureStarted) {
|
|
1606
1634
|
this.pageviewTracker.stopAutocapture();
|
|
1607
1635
|
this.autocaptureTracker.stop();
|
|
1608
1636
|
this.autocaptureStarted = false;
|
|
1609
1637
|
}
|
|
1610
|
-
// Evaluate if autocapture should be enabled with new options
|
|
1611
1638
|
const autoTrackPageviews = effectiveOptions.autoTrackPageviews !== false;
|
|
1612
1639
|
const autocaptureEnabled = effectiveOptions.autocapture !== false;
|
|
1613
|
-
// Update autocapture tracker options
|
|
1614
1640
|
const autocaptureOptions = this.resolveAutocaptureOptions(effectiveOptions.autocapture);
|
|
1615
1641
|
this.autocaptureTracker.updateOptions(autocaptureOptions);
|
|
1616
|
-
// Start autocapture based on new options (even if it wasn't started before)
|
|
1617
1642
|
if (autoTrackPageviews) {
|
|
1618
|
-
this.pageviewTracker.startAutoPageviewTracking();
|
|
1643
|
+
this.pageviewTracker.startAutoPageviewTracking(isFirstStart);
|
|
1619
1644
|
}
|
|
1620
1645
|
if (autocaptureEnabled) {
|
|
1621
1646
|
this.autocaptureTracker.start();
|