@interfere/next 0.0.0-alpha.10 → 0.0.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/README.md +1 -0
- package/dist/__tests__/build/with-interfere-coverage.test.d.ts +2 -0
- package/dist/__tests__/build/with-interfere-coverage.test.d.ts.map +1 -0
- package/dist/__tests__/build/with-interfere-coverage.test.js +338 -0
- package/dist/__tests__/build/with-interfere-coverage.test.js.map +1 -0
- package/dist/__tests__/build/with-interfere.test.d.ts +2 -0
- package/dist/__tests__/build/with-interfere.test.d.ts.map +1 -0
- package/dist/__tests__/build/with-interfere.test.js +466 -0
- package/dist/__tests__/build/with-interfere.test.js.map +1 -0
- package/dist/__tests__/core/client.test.d.ts.map +1 -0
- package/dist/__tests__/core/client.test.js +373 -0
- package/dist/__tests__/core/client.test.js.map +1 -0
- package/dist/__tests__/core/encoders.test.d.ts.map +1 -0
- package/dist/{core → __tests__/core}/encoders.test.js +20 -19
- package/dist/__tests__/core/encoders.test.js.map +1 -0
- package/dist/__tests__/core/rage-click.test.d.ts +2 -0
- package/dist/__tests__/core/rage-click.test.d.ts.map +1 -0
- package/dist/__tests__/core/rage-click.test.js +121 -0
- package/dist/__tests__/core/rage-click.test.js.map +1 -0
- package/dist/__tests__/core/session-manager.test.d.ts +2 -0
- package/dist/__tests__/core/session-manager.test.d.ts.map +1 -0
- package/dist/__tests__/core/session-manager.test.js +1132 -0
- package/dist/__tests__/core/session-manager.test.js.map +1 -0
- package/dist/__tests__/integration/release-upload.test.d.ts +2 -0
- package/dist/__tests__/integration/release-upload.test.d.ts.map +1 -0
- package/dist/__tests__/integration/release-upload.test.js +173 -0
- package/dist/__tests__/integration/release-upload.test.js.map +1 -0
- package/dist/__tests__/session/persistence.test.d.ts +2 -0
- package/dist/__tests__/session/persistence.test.d.ts.map +1 -0
- package/dist/__tests__/session/persistence.test.js +129 -0
- package/dist/__tests__/session/persistence.test.js.map +1 -0
- package/dist/__tests__/session/session-summary.test.d.ts +2 -0
- package/dist/__tests__/session/session-summary.test.d.ts.map +1 -0
- package/dist/__tests__/session/session-summary.test.js +763 -0
- package/dist/__tests__/session/session-summary.test.js.map +1 -0
- package/dist/build/index.d.ts +3 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +2 -0
- package/dist/build/index.js.map +1 -0
- package/dist/build/with-interfere.d.ts +54 -0
- package/dist/build/with-interfere.d.ts.map +1 -0
- package/dist/build/with-interfere.js +267 -0
- package/dist/build/with-interfere.js.map +1 -0
- package/dist/core/client-core.d.ts +27 -0
- package/dist/core/client-core.d.ts.map +1 -0
- package/dist/core/client-core.js +164 -0
- package/dist/core/client-core.js.map +1 -0
- package/dist/core/client.d.ts +70 -18
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +112 -104
- package/dist/core/client.js.map +1 -1
- package/dist/core/constants.d.ts +12 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/constants.js +17 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/debug.d.ts +47 -0
- package/dist/core/debug.d.ts.map +1 -0
- package/dist/core/debug.js +79 -0
- package/dist/core/debug.js.map +1 -0
- package/dist/core/error-handlers.d.ts.map +1 -1
- package/dist/core/error-handlers.js +42 -41
- package/dist/core/error-handlers.js.map +1 -1
- package/dist/core/runtime.d.ts +7 -0
- package/dist/core/runtime.d.ts.map +1 -0
- package/dist/core/runtime.js +16 -0
- package/dist/core/runtime.js.map +1 -0
- package/dist/index.d.ts +10 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -7
- package/dist/index.js.map +1 -1
- package/dist/next/middleware.d.ts +1 -1
- package/dist/next/middleware.js +13 -13
- package/dist/persistence/storage.d.ts +5 -0
- package/dist/persistence/storage.d.ts.map +1 -0
- package/dist/persistence/storage.js +67 -0
- package/dist/persistence/storage.js.map +1 -0
- package/dist/react/provider.d.ts +9 -5
- package/dist/react/provider.d.ts.map +1 -1
- package/dist/react/provider.jsx +33 -10
- package/dist/react/provider.jsx.map +1 -1
- package/dist/session/constants.d.ts +19 -0
- package/dist/session/constants.d.ts.map +1 -0
- package/dist/session/constants.js +34 -0
- package/dist/session/constants.js.map +1 -0
- package/dist/session/persistence.d.ts +58 -0
- package/dist/session/persistence.d.ts.map +1 -0
- package/dist/session/persistence.js +180 -0
- package/dist/session/persistence.js.map +1 -0
- package/dist/session/rage-click.d.ts +17 -0
- package/dist/session/rage-click.d.ts.map +1 -0
- package/dist/session/rage-click.js +104 -0
- package/dist/session/rage-click.js.map +1 -0
- package/dist/session/replay.d.ts +2 -2
- package/dist/session/replay.d.ts.map +1 -1
- package/dist/session/replay.js +57 -24
- package/dist/session/replay.js.map +1 -1
- package/dist/session/session-manager.d.ts +126 -0
- package/dist/session/session-manager.d.ts.map +1 -0
- package/dist/session/session-manager.js +635 -0
- package/dist/session/session-manager.js.map +1 -0
- package/dist/session/session-summary.d.ts +2 -2
- package/dist/session/session-summary.d.ts.map +1 -1
- package/dist/session/session-summary.js +94 -47
- package/dist/session/session-summary.js.map +1 -1
- package/dist/types/storage.d.ts +7 -0
- package/dist/types/storage.d.ts.map +1 -0
- package/dist/types/storage.js +2 -0
- package/dist/types/storage.js.map +1 -0
- package/package.json +24 -7
- package/dist/core/client.test.d.ts.map +0 -1
- package/dist/core/client.test.js +0 -238
- package/dist/core/client.test.js.map +0 -1
- package/dist/core/encoders.test.d.ts.map +0 -1
- package/dist/core/encoders.test.js.map +0 -1
- package/dist/next/error-boundary.d.ts +0 -17
- package/dist/next/error-boundary.d.ts.map +0 -1
- package/dist/next/error-boundary.jsx +0 -32
- package/dist/next/error-boundary.jsx.map +0 -1
- /package/dist/{core → __tests__/core}/client.test.d.ts +0 -0
- /package/dist/{core → __tests__/core}/encoders.test.d.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/session/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;AACxC,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAC;AAEtC,kDAAkD;AAClD,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAC7B,MAAM,eAAe,GAAG,EAAE,CAAC;AAC3B,MAAM,sBAAsB,GAAG,IAAI,CAAC;AACpC,MAAM,eAAe,GAAG,eAAe,GAAG,iBAAiB,CAAC;AAC5D,MAAM,oBAAoB,GAAG,eAAe,GAAG,sBAAsB,CAAC;AAEtE,yBAAyB;AACzB,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,OAAe,EAAU,EAAE,CAC9C,OAAO,GAAG,sBAAsB,CAAC;AACnC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,YAAoB,EAAU,EAAE,CACxD,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,sBAAsB,CAAC,CAAC;AAEpD,2EAA2E;AAC3E,MAAM,4BAA4B,GAAG,EAAE,CAAC;AACxC,MAAM,CAAC,MAAM,oCAAoC,GAC/C,4BAA4B,GAAG,iBAAiB,CAAC,CAAC,aAAa;AACjE,MAAM,CAAC,MAAM,gCAAgC,GAAG,EAAE,GAAG,eAAe,CAAC,CAAC,WAAW;AACjF,MAAM,CAAC,MAAM,gCAAgC,GAAG,iBAAiB,CAAC,CAAC,WAAW;AAE9E,yCAAyC;AACzC,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,GAAG,oBAAoB,CAAC,CAAC,WAAW;AAEvF,kCAAkC;AAClC,qDAAqD;AAErD,kBAAkB;AAClB,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC,CAAC,iBAAiB;AAC9D,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,CAAC,aAAa;AAC9D,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAC9C,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC,iBAAiB;AACjB,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,CAAC,iBAAiB;AACrD,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,CAAC,aAAa;AAEpD,uBAAuB;AACvB,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,CAAC,iBAAiB;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC,CAAC,WAAW;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,CAAC,oCAAoC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Config } from "@interfere/schemas/config";
|
|
2
|
+
import type { PersistentStore } from "../types/storage.js";
|
|
3
|
+
export type Properties = {
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
};
|
|
6
|
+
export type PersistenceOptions = {
|
|
7
|
+
/** Use deep equality check for register method (slower but more accurate for objects) */
|
|
8
|
+
useDeepEquality?: boolean;
|
|
9
|
+
/** Custom storage implementation for testing */
|
|
10
|
+
customStorage?: PersistentStore;
|
|
11
|
+
};
|
|
12
|
+
export declare class InterferePersistence {
|
|
13
|
+
private readonly _config;
|
|
14
|
+
private _props;
|
|
15
|
+
private readonly _storage;
|
|
16
|
+
private readonly _name;
|
|
17
|
+
private _disabled;
|
|
18
|
+
private readonly _useDeepEquality;
|
|
19
|
+
constructor(config: Partial<Config>, surface: string, isDisabled?: boolean, options?: PersistenceOptions);
|
|
20
|
+
private _parseName;
|
|
21
|
+
private _buildStorage;
|
|
22
|
+
isDisabled(): boolean;
|
|
23
|
+
load(): void;
|
|
24
|
+
save(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Deep equality helper for objects and arrays
|
|
27
|
+
*/
|
|
28
|
+
private _deepEqual;
|
|
29
|
+
register(props: Properties): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Remove a single property from persistence
|
|
32
|
+
*/
|
|
33
|
+
removeProp(prop: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get a property value with optional generic typing
|
|
36
|
+
*/
|
|
37
|
+
getProperty<T = unknown>(prop: string): T | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Set a property value
|
|
40
|
+
*/
|
|
41
|
+
setProperty<T = unknown>(prop: string, value: T): void;
|
|
42
|
+
/**
|
|
43
|
+
* Get all properties (immutable copy)
|
|
44
|
+
*/
|
|
45
|
+
getAllProperties(): Readonly<Properties>;
|
|
46
|
+
/**
|
|
47
|
+
* Remove all data from storage and memory
|
|
48
|
+
*/
|
|
49
|
+
removeAll(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Clear both storage and in-memory props (alias for removeAll)
|
|
52
|
+
*/
|
|
53
|
+
clear(): void;
|
|
54
|
+
setDisabled(disabled: boolean): void;
|
|
55
|
+
/** @deprecated Use removeProp instead */
|
|
56
|
+
unregister(prop: string): void;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=persistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../../src/session/persistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAmB,MAAM,2BAA2B,CAAC;AAQzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,MAAM,UAAU,GAAG;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,yFAAyF;IACzF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gDAAgD;IAChD,aAAa,CAAC,EAAE,eAAe,CAAC;CACjC,CAAC;AAEF,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAClD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAU;gBAGzC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,EACvB,OAAO,EAAE,MAAM,EACf,UAAU,UAAQ,EAClB,OAAO,GAAE,kBAAuB;IAelC,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,aAAa;IAiBrB,UAAU,IAAI,OAAO;IAIrB,IAAI,IAAI,IAAI;IAgBZ,IAAI,IAAI,IAAI;IAaZ;;OAEG;IACH,OAAO,CAAC,UAAU;IAsBlB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO;IA0BpC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAO9B;;OAEG;IACH,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAIrD;;OAEG;IACH,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAKtD;;OAEG;IACH,gBAAgB,IAAI,QAAQ,CAAC,UAAU,CAAC;IAIxC;;OAEG;IACH,SAAS,IAAI,IAAI;IAcjB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAWpC,yCAAyC;IACzC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;CAG/B"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { localStore, memoryStore, sessionStore, } from "../persistence/storage.js";
|
|
2
|
+
export class InterferePersistence {
|
|
3
|
+
_config;
|
|
4
|
+
_props = {};
|
|
5
|
+
_storage;
|
|
6
|
+
_name;
|
|
7
|
+
_disabled;
|
|
8
|
+
_useDeepEquality;
|
|
9
|
+
constructor(config, surface, isDisabled = false, options = {}) {
|
|
10
|
+
this._config = config;
|
|
11
|
+
this._name = this._parseName(surface);
|
|
12
|
+
this._disabled = isDisabled;
|
|
13
|
+
this._useDeepEquality = options.useDeepEquality ?? false;
|
|
14
|
+
// Short-circuit storage building if disabled
|
|
15
|
+
this._storage = this._disabled
|
|
16
|
+
? null
|
|
17
|
+
: (options.customStorage ?? this._buildStorage());
|
|
18
|
+
this.load();
|
|
19
|
+
}
|
|
20
|
+
_parseName(surface) {
|
|
21
|
+
// Normalize consecutive non-alphanumerics to single underscore
|
|
22
|
+
const cleanSurface = surface.replace(/[^a-zA-Z0-9]+/g, "_");
|
|
23
|
+
return `interfere_${cleanSurface}`;
|
|
24
|
+
}
|
|
25
|
+
_buildStorage() {
|
|
26
|
+
const persistenceType = this._config.persistence || "localStorage";
|
|
27
|
+
switch (persistenceType) {
|
|
28
|
+
case "localStorage":
|
|
29
|
+
return localStore._is_supported() ? localStore : memoryStore;
|
|
30
|
+
case "sessionStorage":
|
|
31
|
+
return sessionStore._is_supported() ? sessionStore : memoryStore;
|
|
32
|
+
case "memory":
|
|
33
|
+
return memoryStore;
|
|
34
|
+
default:
|
|
35
|
+
// TypeScript ensures exhaustiveness, but keep default for safety
|
|
36
|
+
return localStore._is_supported() ? localStore : memoryStore;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
isDisabled() {
|
|
40
|
+
return this._disabled;
|
|
41
|
+
}
|
|
42
|
+
load() {
|
|
43
|
+
if (this._disabled || !this._storage) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const entry = this._storage._parse(this._name);
|
|
48
|
+
if (entry && typeof entry === "object" && entry !== null) {
|
|
49
|
+
this._props = { ...entry };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Gracefully handle parse errors, keep existing props
|
|
54
|
+
// In production, we silently fail to avoid console noise
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
save() {
|
|
58
|
+
if (this._disabled || !this._storage) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
this._storage._set(this._name, this._props);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Gracefully handle storage errors (e.g., quota exceeded)
|
|
66
|
+
// In production, we silently fail to avoid console noise
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Deep equality helper for objects and arrays
|
|
71
|
+
*/
|
|
72
|
+
_deepEqual(a, b) {
|
|
73
|
+
if (a === b) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
if (a == null || b == null) {
|
|
77
|
+
return a === b;
|
|
78
|
+
}
|
|
79
|
+
if (typeof a !== typeof b) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
if (typeof a !== "object" || typeof b !== "object") {
|
|
83
|
+
return a === b;
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Fallback to shallow comparison for non-serializable objects
|
|
90
|
+
return a === b;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
register(props) {
|
|
94
|
+
if (!props || typeof props !== "object") {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
let hasChanges = false;
|
|
98
|
+
for (const [prop, val] of Object.entries(props)) {
|
|
99
|
+
const currentVal = this._props[prop];
|
|
100
|
+
const isEqual = this._useDeepEquality
|
|
101
|
+
? this._deepEqual(currentVal, val)
|
|
102
|
+
: currentVal === val;
|
|
103
|
+
if (!isEqual) {
|
|
104
|
+
this._props[prop] = val;
|
|
105
|
+
hasChanges = true;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// biome-ignore lint/nursery/noUnnecessaryConditions: false positive, hasChanges can be true
|
|
109
|
+
if (hasChanges) {
|
|
110
|
+
this.save();
|
|
111
|
+
}
|
|
112
|
+
return hasChanges;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Remove a single property from persistence
|
|
116
|
+
*/
|
|
117
|
+
removeProp(prop) {
|
|
118
|
+
if (prop in this._props) {
|
|
119
|
+
delete this._props[prop];
|
|
120
|
+
this.save();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get a property value with optional generic typing
|
|
125
|
+
*/
|
|
126
|
+
getProperty(prop) {
|
|
127
|
+
return this._props[prop];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Set a property value
|
|
131
|
+
*/
|
|
132
|
+
setProperty(prop, value) {
|
|
133
|
+
this._props[prop] = value;
|
|
134
|
+
this.save();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get all properties (immutable copy)
|
|
138
|
+
*/
|
|
139
|
+
getAllProperties() {
|
|
140
|
+
return { ...this._props };
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Remove all data from storage and memory
|
|
144
|
+
*/
|
|
145
|
+
removeAll() {
|
|
146
|
+
this._props = {};
|
|
147
|
+
if (!this._storage) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
this._storage._remove(this._name);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// Gracefully handle removal errors
|
|
155
|
+
// In production, we silently fail to avoid console noise
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Clear both storage and in-memory props (alias for removeAll)
|
|
160
|
+
*/
|
|
161
|
+
clear() {
|
|
162
|
+
this.removeAll();
|
|
163
|
+
}
|
|
164
|
+
setDisabled(disabled) {
|
|
165
|
+
this._disabled = disabled;
|
|
166
|
+
if (this._disabled) {
|
|
167
|
+
this.removeAll();
|
|
168
|
+
}
|
|
169
|
+
else if (Object.keys(this._props).length > 0) {
|
|
170
|
+
// Only save if we have properties to persist
|
|
171
|
+
this.save();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Deprecated methods for backward compatibility
|
|
175
|
+
/** @deprecated Use removeProp instead */
|
|
176
|
+
unregister(prop) {
|
|
177
|
+
this.removeProp(prop);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=persistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence.js","sourceRoot":"","sources":["../../src/session/persistence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export default class RageClick {
|
|
2
|
+
private clicks;
|
|
3
|
+
private readonly radiusPx;
|
|
4
|
+
private readonly timeoutMs;
|
|
5
|
+
private readonly clickCount;
|
|
6
|
+
constructor();
|
|
7
|
+
isRageClick(x: number, y: number, timestamp: number): boolean;
|
|
8
|
+
getElementInfo(target: HTMLElement | null): {
|
|
9
|
+
tagName?: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
id?: string;
|
|
12
|
+
text?: string;
|
|
13
|
+
ariaLabel?: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export declare function setupRageClick(): void;
|
|
17
|
+
//# sourceMappingURL=rage-click.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rage-click.d.ts","sourceRoot":"","sources":["../../src/session/rage-click.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,OAAO,OAAO,SAAS;IAC5B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;;IASpC,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAkC7D,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG;QAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;CAaF;AASD,wBAAgB,cAAc,IAAI,IAAI,CA0DrC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/* Rage click detection for identifying user frustration patterns */
|
|
2
|
+
"use client";
|
|
3
|
+
import { RAGE_CLICK_COUNT, RAGE_CLICK_ENABLED, RAGE_CLICK_RADIUS_PX, RAGE_CLICK_TIMEOUT_MS, } from "./constants.js";
|
|
4
|
+
const MAX_TEXT_LENGTH = 100;
|
|
5
|
+
export default class RageClick {
|
|
6
|
+
clicks = [];
|
|
7
|
+
radiusPx;
|
|
8
|
+
timeoutMs;
|
|
9
|
+
clickCount;
|
|
10
|
+
constructor() {
|
|
11
|
+
// Use static values - config options no longer used
|
|
12
|
+
this.radiusPx = RAGE_CLICK_RADIUS_PX;
|
|
13
|
+
this.timeoutMs = RAGE_CLICK_TIMEOUT_MS;
|
|
14
|
+
this.clickCount = RAGE_CLICK_COUNT;
|
|
15
|
+
}
|
|
16
|
+
isRageClick(x, y, timestamp) {
|
|
17
|
+
const current = { x, y, timestamp };
|
|
18
|
+
// Keep only recent clicks within timeout window
|
|
19
|
+
this.clicks = this.clicks.filter((c) => timestamp - c.timestamp <= this.timeoutMs);
|
|
20
|
+
this.clicks.push(current);
|
|
21
|
+
// Check if enough clicks happened in close proximity
|
|
22
|
+
if (this.clicks.length >= this.clickCount) {
|
|
23
|
+
const first = this.clicks[0];
|
|
24
|
+
const last = this.clicks.at(-1);
|
|
25
|
+
// Check time window - both first and last should exist due to length check
|
|
26
|
+
if (first && last && last.timestamp - first.timestamp <= this.timeoutMs) {
|
|
27
|
+
// Ensure all clicks are within radius of the first
|
|
28
|
+
const allWithinRadius = this.clicks.every((c) => {
|
|
29
|
+
const dx = c.x - first.x;
|
|
30
|
+
const dy = c.y - first.y;
|
|
31
|
+
return Math.sqrt(dx * dx + dy * dy) <= this.radiusPx;
|
|
32
|
+
});
|
|
33
|
+
if (allWithinRadius) {
|
|
34
|
+
this.clicks = []; // reset after detection
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
// Get the element information for the rage click event
|
|
42
|
+
getElementInfo(target) {
|
|
43
|
+
if (!target) {
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
tagName: target.tagName?.toLowerCase(),
|
|
48
|
+
className: target.className || undefined,
|
|
49
|
+
id: target.id || undefined,
|
|
50
|
+
text: target.innerText?.slice(0, MAX_TEXT_LENGTH) || undefined,
|
|
51
|
+
ariaLabel: target.getAttribute("aria-label") || undefined,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
let rageClickDetector = null;
|
|
56
|
+
let initialized = false;
|
|
57
|
+
function isBrowser() {
|
|
58
|
+
return typeof window !== "undefined";
|
|
59
|
+
}
|
|
60
|
+
export function setupRageClick() {
|
|
61
|
+
if (initialized) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (!isBrowser()) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (!RAGE_CLICK_ENABLED) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
initialized = true;
|
|
71
|
+
rageClickDetector = new RageClick();
|
|
72
|
+
// Import capture function dynamically to avoid circular dependencies
|
|
73
|
+
import("../core/client.js")
|
|
74
|
+
.then(({ capture }) => {
|
|
75
|
+
document.addEventListener("click", (e) => {
|
|
76
|
+
if (!rageClickDetector) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const mouseEvent = e;
|
|
80
|
+
const timestamp = Date.now();
|
|
81
|
+
if (rageClickDetector.isRageClick(mouseEvent.clientX, mouseEvent.clientY, timestamp)) {
|
|
82
|
+
const target = mouseEvent.target;
|
|
83
|
+
const elementInfo = rageClickDetector.getElementInfo(target);
|
|
84
|
+
try {
|
|
85
|
+
capture("rage_click", {
|
|
86
|
+
timestamp,
|
|
87
|
+
x: mouseEvent.clientX,
|
|
88
|
+
y: mouseEvent.clientY,
|
|
89
|
+
element: elementInfo,
|
|
90
|
+
url: window.location.href,
|
|
91
|
+
userAgent: navigator.userAgent,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Swallow errors to avoid impacting the host app
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}, { capture: true });
|
|
99
|
+
})
|
|
100
|
+
.catch(() => {
|
|
101
|
+
// Swallow import errors
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=rage-click.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rage-click.js","sourceRoot":"","sources":["../../src/session/rage-click.ts"],"names":[],"mappings":"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"}
|
package/dist/session/replay.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export declare function
|
|
1
|
+
export declare function setupReplay(): void;
|
|
2
|
+
export declare function stopReplay(): void;
|
|
3
3
|
//# sourceMappingURL=replay.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/session/replay.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/session/replay.ts"],"names":[],"mappings":"AAUA,wBAAgB,WAAW,SAuG1B;AAED,wBAAgB,UAAU,SAEzB"}
|
package/dist/session/replay.js
CHANGED
|
@@ -1,37 +1,40 @@
|
|
|
1
1
|
/* Session replay capture using rrweb, chunked streaming to ingest */
|
|
2
|
-
|
|
3
|
-
import { capture, flush } from
|
|
2
|
+
"use client";
|
|
3
|
+
import { capture, flush } from "../core/client.js";
|
|
4
|
+
import { REPLAY_CHUNK_MS, REPLAY_ENABLED } from "./constants.js";
|
|
4
5
|
let started = false;
|
|
5
|
-
|
|
6
|
+
let stopFn = null;
|
|
7
|
+
export function setupReplay() {
|
|
6
8
|
if (started) {
|
|
7
9
|
return;
|
|
8
10
|
}
|
|
9
|
-
if (typeof window ===
|
|
11
|
+
if (typeof window === "undefined") {
|
|
10
12
|
return;
|
|
11
13
|
}
|
|
12
|
-
|
|
13
|
-
if (!enable) {
|
|
14
|
+
if (!REPLAY_ENABLED) {
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
17
|
started = true;
|
|
17
|
-
import(
|
|
18
|
-
.then((
|
|
18
|
+
Promise.all([import("rrweb"), import("@rrweb/packer")])
|
|
19
|
+
.then(([rrwebModule, packerModule]) => {
|
|
19
20
|
// Handle different module export patterns
|
|
20
|
-
const
|
|
21
|
-
const record =
|
|
21
|
+
const rrweb = rrwebModule.default || rrwebModule;
|
|
22
|
+
const record = rrweb.record || rrweb;
|
|
23
|
+
const { pack } = packerModule;
|
|
22
24
|
const events = [];
|
|
23
|
-
const chunkMs = options?.replayChunkMs ?? 10_000;
|
|
24
25
|
// Check if record is a function
|
|
25
|
-
if (typeof record !==
|
|
26
|
+
if (typeof record !== "function") {
|
|
26
27
|
// biome-ignore lint/suspicious/noConsole: error logging needed
|
|
27
|
-
console.error(
|
|
28
|
+
console.error("rrweb.record is not available");
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
30
|
-
record({
|
|
31
|
+
const stopRecord = record({
|
|
31
32
|
emit(event) {
|
|
32
|
-
|
|
33
|
+
// Compress the event before storing it
|
|
34
|
+
const packedEvent = pack(event);
|
|
35
|
+
events.push(packedEvent);
|
|
33
36
|
},
|
|
34
|
-
maskAllInputs:
|
|
37
|
+
maskAllInputs: true, // Privacy: mask all text inputs by default
|
|
35
38
|
});
|
|
36
39
|
const sendChunk = () => {
|
|
37
40
|
if (events.length === 0) {
|
|
@@ -39,11 +42,11 @@ export function setupReplay(options) {
|
|
|
39
42
|
}
|
|
40
43
|
const chunk = events.splice(0, events.length);
|
|
41
44
|
try {
|
|
42
|
-
capture(
|
|
45
|
+
capture("replay_chunk", {
|
|
43
46
|
version: 1,
|
|
44
47
|
chunkTs: Date.now(),
|
|
45
48
|
count: chunk.length,
|
|
46
|
-
// rrweb events are
|
|
49
|
+
// rrweb events are pre-compressed with @rrweb/packer
|
|
47
50
|
events: chunk,
|
|
48
51
|
});
|
|
49
52
|
flush();
|
|
@@ -52,7 +55,7 @@ export function setupReplay(options) {
|
|
|
52
55
|
// swallow
|
|
53
56
|
}
|
|
54
57
|
};
|
|
55
|
-
window.setInterval(sendChunk,
|
|
58
|
+
const intervalId = window.setInterval(sendChunk, REPLAY_CHUNK_MS);
|
|
56
59
|
const flushNow = () => {
|
|
57
60
|
try {
|
|
58
61
|
sendChunk();
|
|
@@ -61,16 +64,46 @@ export function setupReplay(options) {
|
|
|
61
64
|
// swallow
|
|
62
65
|
}
|
|
63
66
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (document.visibilityState ===
|
|
67
|
+
const beforeUnload = () => flushNow();
|
|
68
|
+
const visibility = () => {
|
|
69
|
+
if (document.visibilityState === "hidden") {
|
|
67
70
|
flushNow();
|
|
68
71
|
}
|
|
69
|
-
}
|
|
72
|
+
};
|
|
73
|
+
window.addEventListener("beforeunload", beforeUnload);
|
|
74
|
+
document.addEventListener("visibilitychange", visibility);
|
|
75
|
+
stopFn = () => {
|
|
76
|
+
try {
|
|
77
|
+
if (typeof stopRecord === "function") {
|
|
78
|
+
stopRecord();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
/* no-op */
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
window.clearInterval(intervalId);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
/* no-op */
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
window.removeEventListener("beforeunload", beforeUnload);
|
|
92
|
+
document.removeEventListener("visibilitychange", visibility);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
/* no-op */
|
|
96
|
+
}
|
|
97
|
+
started = false;
|
|
98
|
+
stopFn = null;
|
|
99
|
+
};
|
|
70
100
|
})
|
|
71
101
|
.catch((error) => {
|
|
72
102
|
// biome-ignore lint/suspicious/noConsole: Just for testing
|
|
73
|
-
console.error(
|
|
103
|
+
console.error("Failed to load rrweb:", error);
|
|
74
104
|
});
|
|
75
105
|
}
|
|
106
|
+
export function stopReplay() {
|
|
107
|
+
stopFn?.();
|
|
108
|
+
}
|
|
76
109
|
//# sourceMappingURL=replay.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/session/replay.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,YAAY,CAAC;AAGb,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/session/replay.ts"],"names":[],"mappings":"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"}
|