@brainfish-ai/web-tracker 0.0.4-alpha.9 → 0.0.4-beta.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/index.cjs.js +30 -0
- package/dist/index.cjs.js.gz +0 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3816 -0
- package/dist/index.js.gz +0 -0
- package/dist/index.js.map +1 -0
- package/dist/src/common/isLocal.d.ts +1 -0
- package/dist/src/index.d.ts +24 -0
- package/dist/src/record/eventBuffer.d.ts +7 -0
- package/dist/src/record/index.d.ts +16 -0
- package/dist/src/record/recorder.d.ts +41 -0
- package/dist/src/record/recordingManager.d.ts +17 -0
- package/dist/src/record/sender.d.ts +11 -0
- package/dist/src/record/stasher.d.ts +23 -0
- package/dist/src/record/timer.d.ts +11 -0
- package/dist/src/redact/built-ins/NameRedactor.d.ts +6 -0
- package/dist/src/redact/built-ins/SimpleRegexpRedactor.d.ts +10 -0
- package/dist/src/redact/built-ins/simple-regexp-patterns.d.ts +12 -0
- package/dist/src/redact/built-ins/well-known-names.d.ts +2 -0
- package/dist/src/redact/composition.d.ts +2 -0
- package/dist/src/redact/index.d.ts +10 -0
- package/dist/src/redact/types.d.ts +27 -0
- package/dist/src/redact/utils.d.ts +4 -0
- package/dist/src/screenshot/capture.d.ts +2 -0
- package/dist/src/screenshot/redact.d.ts +3 -0
- package/dist/src/screenshot/snapshot.d.ts +2 -0
- package/dist/src/setupTests.d.ts +0 -0
- package/dist/src/tracker.d.ts +9 -0
- package/dist/tracker.cjs.js +2 -0
- package/dist/tracker.cjs.js.map +1 -0
- package/dist/tracker.d.ts +1 -0
- package/dist/tracker.js +15 -0
- package/dist/tracker.js.map +1 -0
- package/package.json +14 -11
- package/index.ts +0 -2
- package/postcss.config.cjs +0 -6
- package/src/index.ts +0 -193
- package/src/setupTests.ts +0 -1
- package/src/tracker.ts +0 -31
- package/src/types.d.ts +0 -31
- package/src/utils/capture.test.ts +0 -83
- package/src/utils/capture.ts +0 -51
- package/src/utils/redact.test.ts +0 -74
- package/src/utils/redact.ts +0 -57
- package/src/utils/snapshot.ts +0 -35
- package/src/vite-env.d.ts +0 -7
- package/tailwind.config.cjs +0 -9
- package/tsconfig.json +0 -15
- package/vite.config.ts +0 -50
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function isLocal(): boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { TrackerSdkOptions, TrackProperties, TrackerSdk } from '@brainfish-ai/tracker-sdk';
|
|
2
|
+
export type * from '@brainfish-ai/tracker-sdk';
|
|
3
|
+
export type TrackerOptions = TrackerSdkOptions & {
|
|
4
|
+
trackOutgoingLinks?: boolean;
|
|
5
|
+
trackScreenViews?: boolean;
|
|
6
|
+
trackAttributes?: boolean;
|
|
7
|
+
trackHashChanges?: boolean;
|
|
8
|
+
enableRecording?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare const VERSION: string;
|
|
11
|
+
export declare class Tracker extends TrackerSdk {
|
|
12
|
+
options: TrackerOptions;
|
|
13
|
+
private lastPath;
|
|
14
|
+
private debounceTimer;
|
|
15
|
+
constructor(options: TrackerOptions);
|
|
16
|
+
private debounce;
|
|
17
|
+
private isServer;
|
|
18
|
+
trackOutgoingLinks(): void;
|
|
19
|
+
trackScreenViews(): void;
|
|
20
|
+
trackAttributes(): void;
|
|
21
|
+
startRecording(): void;
|
|
22
|
+
screenView(properties?: TrackProperties): Promise<void>;
|
|
23
|
+
screenView(path: string, properties?: TrackProperties): Promise<void>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { default as Sender } from './sender';
|
|
2
|
+
import { default as RecordingManager } from './recordingManager';
|
|
3
|
+
import { default as Timer } from './timer';
|
|
4
|
+
export default class Agent {
|
|
5
|
+
recordingManager: RecordingManager;
|
|
6
|
+
sender: Sender;
|
|
7
|
+
endpoint: string | undefined;
|
|
8
|
+
MAX_IDLE_TIME: any;
|
|
9
|
+
timer: Timer | undefined;
|
|
10
|
+
constructor();
|
|
11
|
+
start({ endpoint, }: {
|
|
12
|
+
endpoint: string;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
handleTimeout(): void;
|
|
15
|
+
static handleCustomEvent(customEventType: string): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
declare class Recorder {
|
|
2
|
+
static mockImplementation(arg0: () => any): void;
|
|
3
|
+
options: {
|
|
4
|
+
emit: {
|
|
5
|
+
(event: any): void;
|
|
6
|
+
(event: any): void;
|
|
7
|
+
};
|
|
8
|
+
plugins: import('@rrweb/types').RecordPlugin[];
|
|
9
|
+
recordOptions: {
|
|
10
|
+
blockClass: string;
|
|
11
|
+
blockSelector: null;
|
|
12
|
+
ignoreClass: string;
|
|
13
|
+
ignoreCSSAttributes: null;
|
|
14
|
+
maskTextClass: string;
|
|
15
|
+
maskTextSelector: null;
|
|
16
|
+
maskAllInputs: boolean;
|
|
17
|
+
maskInputOptions: {
|
|
18
|
+
password: boolean;
|
|
19
|
+
};
|
|
20
|
+
maskInputFn: undefined;
|
|
21
|
+
maskTextFn: undefined;
|
|
22
|
+
};
|
|
23
|
+
recordConsolePlugin: {
|
|
24
|
+
level: string[];
|
|
25
|
+
lengthThreshold: number;
|
|
26
|
+
stringifyOptions: {
|
|
27
|
+
stringLengthLimit: number;
|
|
28
|
+
numOfKeysLimit: number;
|
|
29
|
+
depthOfLimit: number;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
stop: (() => void) | null;
|
|
34
|
+
constructor(handleEvent: {
|
|
35
|
+
(event: any): void;
|
|
36
|
+
(event: any): void;
|
|
37
|
+
});
|
|
38
|
+
start(): void;
|
|
39
|
+
getMirror(): import('rrweb-snapshot').Mirror;
|
|
40
|
+
}
|
|
41
|
+
export default Recorder;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { default as Agent } from '.';
|
|
2
|
+
import { default as Recorder } from './recorder';
|
|
3
|
+
import { default as Stasher } from './stasher';
|
|
4
|
+
declare class RecordingManager {
|
|
5
|
+
agent: Agent;
|
|
6
|
+
recorder: Recorder;
|
|
7
|
+
stasher: Stasher;
|
|
8
|
+
constructor(agent: Agent);
|
|
9
|
+
start(): void;
|
|
10
|
+
handleEvent(event: any): void;
|
|
11
|
+
publishEvent(event: any): void;
|
|
12
|
+
startRecorderWithStasher(): void;
|
|
13
|
+
private isClick;
|
|
14
|
+
private nodeIsInteresting;
|
|
15
|
+
private isCustom;
|
|
16
|
+
}
|
|
17
|
+
export default RecordingManager;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { default as Agent } from '.';
|
|
2
|
+
import { default as EventBuffer } from './eventBuffer';
|
|
3
|
+
declare class Sender {
|
|
4
|
+
agent: Agent;
|
|
5
|
+
eventBuffer: EventBuffer;
|
|
6
|
+
constructor(agent: Agent);
|
|
7
|
+
start(): void;
|
|
8
|
+
handle(event: any): void;
|
|
9
|
+
send(): void;
|
|
10
|
+
}
|
|
11
|
+
export default Sender;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { default as RecordingManager } from './recordingManager';
|
|
2
|
+
declare class Stasher {
|
|
3
|
+
recordingManager: RecordingManager;
|
|
4
|
+
isRunning: boolean;
|
|
5
|
+
events: any[][];
|
|
6
|
+
constructor(recordingManager: RecordingManager);
|
|
7
|
+
start(): void;
|
|
8
|
+
handle(event: any): void;
|
|
9
|
+
isInitializingEvent(event: {
|
|
10
|
+
type: number;
|
|
11
|
+
}): boolean;
|
|
12
|
+
isSelectionEvent(event: {
|
|
13
|
+
type: any;
|
|
14
|
+
data?: any;
|
|
15
|
+
}): boolean;
|
|
16
|
+
isConsoleEvent(event: {
|
|
17
|
+
type: any;
|
|
18
|
+
}): boolean;
|
|
19
|
+
stop(event: any): void;
|
|
20
|
+
stamp(events: any[], timestamp: number): void;
|
|
21
|
+
publish(...events: any[][][]): void;
|
|
22
|
+
}
|
|
23
|
+
export default Stasher;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ISyncRedactor } from '../types';
|
|
2
|
+
export declare class SimpleRegexpRedactor implements ISyncRedactor {
|
|
3
|
+
regexpMatcher: RegExp;
|
|
4
|
+
replaceWith: string;
|
|
5
|
+
constructor({ replaceWith, regexpPattern: regexpMatcher, }: {
|
|
6
|
+
replaceWith: string;
|
|
7
|
+
regexpPattern: RegExp;
|
|
8
|
+
});
|
|
9
|
+
redact(textToRedact: string): string;
|
|
10
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const creditCardNumber: RegExp;
|
|
2
|
+
export declare const streetAddress: RegExp;
|
|
3
|
+
export declare const zipcode: RegExp;
|
|
4
|
+
export declare const phoneNumber: RegExp;
|
|
5
|
+
export declare const ipAddress: RegExp;
|
|
6
|
+
export declare const usSocialSecurityNumber: RegExp;
|
|
7
|
+
export declare const emailAddress: RegExp;
|
|
8
|
+
export declare const username: RegExp;
|
|
9
|
+
export declare const password: RegExp;
|
|
10
|
+
export declare const credentials: RegExp;
|
|
11
|
+
export declare const digits: RegExp;
|
|
12
|
+
export declare const url: RegExp;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { AsyncCustomRedactorConfig, IAsyncRedactor, CompositeRedactorOptions, SyncCustomRedactorConfig, ISyncRedactor } from './types';
|
|
2
|
+
export declare function composeChildRedactors<T extends AsyncCustomRedactorConfig>(opts?: CompositeRedactorOptions<T>): T extends SyncCustomRedactorConfig ? ISyncRedactor[] : (ISyncRedactor | IAsyncRedactor)[];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CompositeRedactorOptions, ISyncRedactor, SyncCustomRedactorConfig } from './types';
|
|
2
|
+
/** @public */
|
|
3
|
+
export interface SyncCompositeRedactorOptions extends CompositeRedactorOptions<SyncCustomRedactorConfig> {
|
|
4
|
+
}
|
|
5
|
+
/** @public */
|
|
6
|
+
export declare class SyncRedactor implements ISyncRedactor {
|
|
7
|
+
private childRedactors;
|
|
8
|
+
constructor(opts?: SyncCompositeRedactorOptions);
|
|
9
|
+
redact: (textToRedact: string) => string;
|
|
10
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as simpleRegexpBuiltIns from './built-ins/simple-regexp-patterns';
|
|
2
|
+
export interface ISyncRedactor {
|
|
3
|
+
redact(textToRedact: string): string;
|
|
4
|
+
}
|
|
5
|
+
export interface IAsyncRedactor {
|
|
6
|
+
redactAsync(textToRedact: string): Promise<string>;
|
|
7
|
+
}
|
|
8
|
+
export type IRedactor = ISyncRedactor | IAsyncRedactor;
|
|
9
|
+
export interface SimpleRegexpCustomRedactorConfig {
|
|
10
|
+
regexpPattern: RegExp;
|
|
11
|
+
replaceWith: string;
|
|
12
|
+
}
|
|
13
|
+
export type SyncCustomRedactorConfig = SimpleRegexpCustomRedactorConfig | ISyncRedactor;
|
|
14
|
+
export type AsyncCustomRedactorConfig = SyncCustomRedactorConfig | IAsyncRedactor;
|
|
15
|
+
export interface CompositeRedactorOptions<T extends AsyncCustomRedactorConfig> {
|
|
16
|
+
globalReplaceWith?: string;
|
|
17
|
+
builtInRedactors?: {
|
|
18
|
+
[RedactorName in keyof typeof simpleRegexpBuiltIns | 'names']?: {
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
replaceWith?: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
customRedactors?: {
|
|
24
|
+
before?: Array<T>;
|
|
25
|
+
after?: Array<T>;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SimpleRegexpCustomRedactorConfig, AsyncCustomRedactorConfig, ISyncRedactor, IRedactor } from './types';
|
|
2
|
+
export declare function isSimpleRegexpCustomRedactorConfig(redactor: AsyncCustomRedactorConfig): redactor is SimpleRegexpCustomRedactorConfig;
|
|
3
|
+
export declare function isSyncRedactor(redactor: IRedactor): redactor is ISyncRedactor;
|
|
4
|
+
export declare function snakeCase(str: string): string;
|
|
File without changes
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const r=require("./index.cjs.js");(s=>{if(s.BrainfishAnalytics&&"q"in s.BrainfishAnalytics){const t=s.BrainfishAnalytics.q||[],c=t.findIndex(i=>i[0]==="init");if(c===-1)return void console.warn("BrainfishAnalytics has not been initialized.");const[o]=t.splice(c,1),n=new r.Tracker(o[1]);t.forEach(i=>{i[0]in n&&n[i[0]](...i.slice(1))}),s.BrainfishAnalytics=(i,...a)=>{const e=n[i]?n[i].bind(n):void 0;typeof e=="function"?e(...a):console.warn(`Method ${i} does not exist on BrainfishAnalytics`)}}})(window);
|
|
2
|
+
//# sourceMappingURL=tracker.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.cjs.js","sources":["../src/tracker.ts"],"sourcesContent":["import { Tracker } from './index';\n\ndeclare global {\n interface Window {\n BrainfishAnalytics: {\n q?: [string, ...any[]];\n (method: string, ...args: any[]): void;\n };\n }\n}\n\n((window) => {\n if (window.BrainfishAnalytics && 'q' in window.BrainfishAnalytics) {\n const queue = window.BrainfishAnalytics.q || [];\n const initIndex = queue.findIndex((e) => e[0] === 'init');\n if (initIndex === -1) {\n console.warn('BrainfishAnalytics has not been initialized.');\n return;\n }\n\n const [init] = queue.splice(initIndex, 1);\n const tracker = new Tracker(init[1]) as any;\n queue.forEach((item) => {\n if (item[0] in tracker) {\n tracker[item[0]](...item.slice(1));\n }\n });\n\n window.BrainfishAnalytics = (t, ...args) => {\n const fn = tracker[t] ? tracker[t].bind(tracker) : undefined;\n if (typeof fn === 'function') {\n fn(...args);\n } else {\n console.warn(`Method ${t} does not exist on BrainfishAnalytics`);\n }\n };\n }\n})(window);\n"],"names":["window","BrainfishAnalytics","queue","q","initIndex","findIndex","e","console","warn","init","splice","tracker","Tracker","forEach","item","slice","t","args","fn","bind"],"mappings":"6CAAwB,GAWtBA,IACA,GAAIA,EAAOC,oBAAsB,MAAOD,EAAOC,mBAAoB,CACjE,MAAMC,EAAQF,EAAOC,mBAAmBE,GAAK,CAAA,EACvCC,EAAYF,EAAMG,UAAWC,GAAMA,EAAE,CAC3C,IADkD,MAClD,EAAA,GAAIF,IAAJ,GAEE,OAAA,KADAG,QAAQC,KAAK,gDAIf,KAAOC,CAAAA,CAAAA,EAAQP,EAAMQ,OAAON,EAAW,GACjCO,EAAU,IAAIC,EAAAA,QAAQH,EAAK,CAC3BP,CAAAA,EAAAA,EAAAW,QAASC,GACTA,CAAAA,EAAK,KAAMH,GACLA,EAAAG,EAAK,CAAA,CAAA,EAAA,GAAOA,EAAKC,MAAM,CAAA,CAAA,CACjC,GAGFf,EAAOC,mBAAqB,CAACe,KAAMC,IAAAA,CAC3B,MAAAC,EAAKP,EAAQK,CAAKL,EAAAA,EAAQK,GAAGG,KAAKR,CAAAA,EAAAA,OAC7BO,OAAAA,GAAO,WAChBA,EAAMD,GAAAA,CAAAA,EAEEV,QAAAC,KAAK,UAAUQ,yCACzB,CAEJ,CACF,GAAGhB,MAAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/dist/tracker.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Tracker as r } from "./index.js";
|
|
2
|
+
((s) => {
|
|
3
|
+
if (s.BrainfishAnalytics && "q" in s.BrainfishAnalytics) {
|
|
4
|
+
const o = s.BrainfishAnalytics.q || [], a = o.findIndex((i) => i[0] === "init");
|
|
5
|
+
if (a === -1) return void console.warn("BrainfishAnalytics has not been initialized.");
|
|
6
|
+
const [c] = o.splice(a, 1), n = new r(c[1]);
|
|
7
|
+
o.forEach((i) => {
|
|
8
|
+
i[0] in n && n[i[0]](...i.slice(1));
|
|
9
|
+
}), s.BrainfishAnalytics = (i, ...e) => {
|
|
10
|
+
const t = n[i] ? n[i].bind(n) : void 0;
|
|
11
|
+
typeof t == "function" ? t(...e) : console.warn(`Method ${i} does not exist on BrainfishAnalytics`);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
})(window);
|
|
15
|
+
//# sourceMappingURL=tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.js","sources":["../src/tracker.ts"],"sourcesContent":["import { Tracker } from './index';\n\ndeclare global {\n interface Window {\n BrainfishAnalytics: {\n q?: [string, ...any[]];\n (method: string, ...args: any[]): void;\n };\n }\n}\n\n((window) => {\n if (window.BrainfishAnalytics && 'q' in window.BrainfishAnalytics) {\n const queue = window.BrainfishAnalytics.q || [];\n const initIndex = queue.findIndex((e) => e[0] === 'init');\n if (initIndex === -1) {\n console.warn('BrainfishAnalytics has not been initialized.');\n return;\n }\n\n const [init] = queue.splice(initIndex, 1);\n const tracker = new Tracker(init[1]) as any;\n queue.forEach((item) => {\n if (item[0] in tracker) {\n tracker[item[0]](...item.slice(1));\n }\n });\n\n window.BrainfishAnalytics = (t, ...args) => {\n const fn = tracker[t] ? tracker[t].bind(tracker) : undefined;\n if (typeof fn === 'function') {\n fn(...args);\n } else {\n console.warn(`Method ${t} does not exist on BrainfishAnalytics`);\n }\n };\n }\n})(window);\n"],"names":["window","BrainfishAnalytics","queue","q","initIndex","findIndex","e","console","warn","init","splice","tracker","Tracker","forEach","item","slice","t","args","fn","bind"],"mappings":";CAWEA,CAAAA,MAAAA;AACA,MAAIA,EAAOC,sBAAsB,OAAOD,EAAOC,oBAAoB;AACjE,UAAMC,IAAQF,EAAOC,mBAAmBE,KAAK,IACvCC,IAAYF,EAAMG,UAAWC,OAAMA,EAAE,CAAA,MAAO,MAAP;AAC3C,QAAIF,MAAkB,GAEpB,QADAG,KAAAA,QAAQC,KAAK,8CAAA;AAIf,WAAOC,CAAQP,IAAAA,EAAMQ,OAAON,GAAW,CAAA,GACjCO,IAAU,IAAIC,EAAQH,EAAK,CAAA,CAAA;AAC3BP,IAAAA,EAAAW,QAASC,OAAAA;AACTA,QAAK,CAAA,KAAMH,KACLA,EAAAG,EAAK,CAAOA,CAAAA,EAAAA,GAAAA,EAAKC,MAAM,CACjC,CAAA;AAAA,IAAA,CAAA,GAGFf,EAAOC,qBAAqB,CAACe,MAAMC,MAC3B;AAAA,YAAAC,IAAKP,EAAQK,KAAKL,EAAQK,CAAAA,EAAGG,KAAKR,CAAAA,IAAAA;AACtB,MAAPO,OAAAA,KAAO,aAChBA,EAAMD,GAAAA,CAAAA,IAEEV,QAAAC,KAAK,UAAUQ;IACzB;AAAA,EAEJ;AACF,GAAGhB,MAAAA;"}
|
package/package.json
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainfish-ai/web-tracker",
|
|
3
|
-
"version": "0.0.4-
|
|
4
|
-
"
|
|
3
|
+
"version": "0.0.4-beta.1",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
5
|
"description": "Brainfish Tracker for Web",
|
|
6
|
-
"
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
7
9
|
"scripts": {
|
|
8
10
|
"start": "vite",
|
|
9
11
|
"dev": "vite",
|
|
10
|
-
"
|
|
12
|
+
"set-version": "node set-version.js",
|
|
13
|
+
"build": "npm run set-version && vite build",
|
|
11
14
|
"serve": "vite preview --port 6006",
|
|
12
|
-
"test": "vitest"
|
|
15
|
+
"test": "vitest --watch=false"
|
|
13
16
|
},
|
|
14
17
|
"license": "MIT",
|
|
15
18
|
"devDependencies": {
|
|
19
|
+
"@rrweb/types": "^2.0.0-alpha.17",
|
|
16
20
|
"rollup-plugin-terser": "^7.0.2",
|
|
17
21
|
"rollup-plugin-visualizer": "^5.12.0",
|
|
18
22
|
"typescript": "^5.4.5",
|
|
19
23
|
"vite": "^5.2.12",
|
|
20
24
|
"vite-plugin-compression": "^0.5.1",
|
|
21
25
|
"vite-plugin-dts": "^4.0.3",
|
|
22
|
-
"vite-tsconfig-paths": "^4.2.0"
|
|
26
|
+
"vite-tsconfig-paths": "^4.2.0",
|
|
27
|
+
"vitest": "^2.1.4"
|
|
23
28
|
},
|
|
24
29
|
"dependencies": {
|
|
25
|
-
"@brainfish-ai/tracker-sdk": "0.0.1-alpha.
|
|
30
|
+
"@brainfish-ai/tracker-sdk": "0.0.1-alpha.5",
|
|
26
31
|
"html-to-image": "^1.11.11",
|
|
27
|
-
"
|
|
28
|
-
"rrweb": "^2.0.0-alpha.4",
|
|
29
|
-
"vite-plugin-replace": "^0.1.1"
|
|
32
|
+
"rrweb": "^2.0.0-alpha.4"
|
|
30
33
|
},
|
|
31
34
|
"keywords": [
|
|
32
35
|
"typescript",
|
|
@@ -35,4 +38,4 @@
|
|
|
35
38
|
"in-app",
|
|
36
39
|
"tracker"
|
|
37
40
|
]
|
|
38
|
-
}
|
|
41
|
+
}
|
package/index.ts
DELETED
package/postcss.config.cjs
DELETED
package/src/index.ts
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/unbound-method */
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
TrackerSdkOptions,
|
|
5
|
-
TrackProperties,
|
|
6
|
-
} from '@brainfish-ai/tracker-sdk';
|
|
7
|
-
import { TrackerSdk } from '@brainfish-ai/tracker-sdk';
|
|
8
|
-
import { screenshot } from './utils/snapshot';
|
|
9
|
-
|
|
10
|
-
export type * from '@brainfish-ai/tracker-sdk';
|
|
11
|
-
|
|
12
|
-
export type TrackerOptions = TrackerSdkOptions & {
|
|
13
|
-
trackOutgoingLinks?: boolean;
|
|
14
|
-
trackScreenViews?: boolean;
|
|
15
|
-
trackAttributes?: boolean;
|
|
16
|
-
trackHashChanges?: boolean;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
function toCamelCase(str: string) {
|
|
20
|
-
return str.replace(/([-_][a-z])/gi, ($1) =>
|
|
21
|
-
$1.toUpperCase().replace('-', '').replace('_', ''),
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const VERSION = import.meta.env.PACKAGE_VERSION as string;
|
|
26
|
-
|
|
27
|
-
export class Tracker extends TrackerSdk {
|
|
28
|
-
private lastPath = '';
|
|
29
|
-
private debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
|
30
|
-
static mock: any;
|
|
31
|
-
|
|
32
|
-
constructor(public options: TrackerOptions) {
|
|
33
|
-
super({
|
|
34
|
-
sdk: 'web',
|
|
35
|
-
sdkVersion: VERSION,
|
|
36
|
-
...options,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
if (!this.isServer()) {
|
|
40
|
-
this.setGlobalProperties({
|
|
41
|
-
__referrer: document.referrer,
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
if (this.options.trackOutgoingLinks) {
|
|
45
|
-
this.trackOutgoingLinks();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (this.options.trackScreenViews) {
|
|
49
|
-
this.trackScreenViews();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (this.options.trackAttributes) {
|
|
53
|
-
this.trackAttributes();
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
private debounce(func: () => void, delay: number) {
|
|
59
|
-
this.debounceTimer && clearTimeout(this.debounceTimer);
|
|
60
|
-
this.debounceTimer = setTimeout(func, delay);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
private isServer() {
|
|
64
|
-
return typeof document === 'undefined';
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
public trackOutgoingLinks() {
|
|
68
|
-
if (this.isServer()) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
document.addEventListener('click', (event) => {
|
|
73
|
-
const target = event.target as HTMLElement;
|
|
74
|
-
const link = target.closest('a');
|
|
75
|
-
if (link && target) {
|
|
76
|
-
const href = link.getAttribute('href');
|
|
77
|
-
if (href?.startsWith('http')) {
|
|
78
|
-
super.track('link_out', {
|
|
79
|
-
href,
|
|
80
|
-
text:
|
|
81
|
-
link.innerText ||
|
|
82
|
-
link.getAttribute('title') ||
|
|
83
|
-
target.getAttribute('alt') ||
|
|
84
|
-
target.getAttribute('title'),
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
public trackScreenViews() {
|
|
92
|
-
if (this.isServer()) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
this.screenView();
|
|
97
|
-
|
|
98
|
-
const oldPushState = history.pushState;
|
|
99
|
-
history.pushState = function pushState(...args) {
|
|
100
|
-
const ret = oldPushState.apply(this, args);
|
|
101
|
-
window.dispatchEvent(new Event('pushstate'));
|
|
102
|
-
window.dispatchEvent(new Event('locationchange'));
|
|
103
|
-
return ret;
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const oldReplaceState = history.replaceState;
|
|
107
|
-
history.replaceState = function replaceState(...args) {
|
|
108
|
-
const ret = oldReplaceState.apply(this, args);
|
|
109
|
-
window.dispatchEvent(new Event('replacestate'));
|
|
110
|
-
window.dispatchEvent(new Event('locationchange'));
|
|
111
|
-
return ret;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
window.addEventListener('popstate', function () {
|
|
115
|
-
window.dispatchEvent(new Event('locationchange'));
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
const eventHandler = () => this.debounce(() => this.screenView(), 50);
|
|
119
|
-
|
|
120
|
-
if (this.options.trackHashChanges) {
|
|
121
|
-
window.addEventListener('hashchange', eventHandler);
|
|
122
|
-
} else {
|
|
123
|
-
window.addEventListener('locationchange', eventHandler);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
public trackAttributes() {
|
|
128
|
-
if (this.isServer()) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
document.addEventListener('click', (event) => {
|
|
133
|
-
const target = event.target as HTMLElement;
|
|
134
|
-
const btn = target.closest('button');
|
|
135
|
-
const anchor = target.closest('a');
|
|
136
|
-
const element = btn?.getAttribute('data-track')
|
|
137
|
-
? btn
|
|
138
|
-
: anchor?.getAttribute('data-track')
|
|
139
|
-
? anchor
|
|
140
|
-
: null;
|
|
141
|
-
if (element) {
|
|
142
|
-
const properties: Record<string, unknown> = {};
|
|
143
|
-
for (const attr of element.attributes) {
|
|
144
|
-
if (attr.name.startsWith('data-') && attr.name !== 'data-track') {
|
|
145
|
-
properties[toCamelCase(attr.name.replace(/^data-/, ''))] =
|
|
146
|
-
attr.value;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const name = element.getAttribute('data-track');
|
|
150
|
-
if (name) {
|
|
151
|
-
super.track(name, properties);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
async screenView(properties?: TrackProperties): Promise<void>;
|
|
158
|
-
async screenView(path: string, properties?: TrackProperties): Promise<void>;
|
|
159
|
-
async screenView(
|
|
160
|
-
pathOrProperties?: string | TrackProperties,
|
|
161
|
-
propertiesOrUndefined?: TrackProperties,
|
|
162
|
-
): Promise<void> {
|
|
163
|
-
if (this.isServer()) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
let path: string;
|
|
168
|
-
let properties: TrackProperties | undefined;
|
|
169
|
-
|
|
170
|
-
if (typeof pathOrProperties === 'string') {
|
|
171
|
-
path = pathOrProperties;
|
|
172
|
-
properties = propertiesOrUndefined;
|
|
173
|
-
} else {
|
|
174
|
-
path = window.location.href;
|
|
175
|
-
properties = pathOrProperties;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (this.lastPath === path) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// capture screenshot
|
|
183
|
-
const snapshot = await screenshot();
|
|
184
|
-
|
|
185
|
-
this.lastPath = path;
|
|
186
|
-
super.track('screen_view', {
|
|
187
|
-
...(properties ?? {}),
|
|
188
|
-
screenshot: snapshot,
|
|
189
|
-
__path: path,
|
|
190
|
-
__title: document.title,
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
}
|
package/src/setupTests.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// Setup for Jest tests
|
package/src/tracker.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Tracker } from './index';
|
|
2
|
-
|
|
3
|
-
declare global {
|
|
4
|
-
interface Window {
|
|
5
|
-
tracker: {
|
|
6
|
-
q?: [string, ...any[]];
|
|
7
|
-
(method: string, ...args: any[]): void;
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
((window) => {
|
|
13
|
-
if (window.tracker && 'q' in window.tracker) {
|
|
14
|
-
const queue = window.tracker.q || [];
|
|
15
|
-
const tracker = new Tracker(queue.shift()[1]) as any;
|
|
16
|
-
queue.forEach((item) => {
|
|
17
|
-
if (item[0] in tracker) {
|
|
18
|
-
tracker[item[0]](...item.slice(1));
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
window.tracker = (t, ...args) => {
|
|
23
|
-
const fn = tracker[t] ? tracker[t].bind(tracker) : undefined;
|
|
24
|
-
if (typeof fn === 'function') {
|
|
25
|
-
fn(...args);
|
|
26
|
-
} else {
|
|
27
|
-
console.warn(`tracker.js: ${t} is not a function`);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
})(window);
|
package/src/types.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { Tracker, TrackerOptions, TrackProperties } from "./index";
|
|
2
|
-
|
|
3
|
-
type ExposedMethodsNames =
|
|
4
|
-
| 'track'
|
|
5
|
-
| 'identify'
|
|
6
|
-
| 'setGlobalProperties'
|
|
7
|
-
| 'alias'
|
|
8
|
-
| 'increment'
|
|
9
|
-
| 'decrement'
|
|
10
|
-
| 'clear';
|
|
11
|
-
|
|
12
|
-
export type ExposedMethods = {
|
|
13
|
-
[K in ExposedMethodsNames]: Tracker[K] extends (...args: any[]) => any
|
|
14
|
-
? [K, ...Parameters<Tracker[K]>]
|
|
15
|
-
: never;
|
|
16
|
-
}[ExposedMethodsNames];
|
|
17
|
-
|
|
18
|
-
export type TrackerMethodNames = ExposedMethodsNames | 'init' | 'screenView';
|
|
19
|
-
export type TrackerMethods =
|
|
20
|
-
| ExposedMethods
|
|
21
|
-
| ['init', TrackerOptions]
|
|
22
|
-
| ['screenView', string | TrackProperties, TrackProperties];
|
|
23
|
-
|
|
24
|
-
declare global {
|
|
25
|
-
interface Window {
|
|
26
|
-
BrainfishAnalytics: {
|
|
27
|
-
q?: [string, ...any[]];
|
|
28
|
-
(method: string, ...args: any[]): void;
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
}
|