@traffical/js-client 0.1.2
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 +209 -0
- package/dist/client.d.ts +167 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +429 -0
- package/dist/client.js.map +1 -0
- package/dist/error-boundary.d.ts +47 -0
- package/dist/error-boundary.d.ts.map +1 -0
- package/dist/error-boundary.js +118 -0
- package/dist/error-boundary.js.map +1 -0
- package/dist/event-logger.d.ts +75 -0
- package/dist/event-logger.d.ts.map +1 -0
- package/dist/event-logger.js +186 -0
- package/dist/event-logger.js.map +1 -0
- package/dist/exposure-dedup.d.ts +49 -0
- package/dist/exposure-dedup.d.ts.map +1 -0
- package/dist/exposure-dedup.js +94 -0
- package/dist/exposure-dedup.js.map +1 -0
- package/dist/global.d.ts +38 -0
- package/dist/global.d.ts.map +1 -0
- package/dist/global.js +67 -0
- package/dist/global.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/decision-tracking.d.ts +68 -0
- package/dist/plugins/decision-tracking.d.ts.map +1 -0
- package/dist/plugins/decision-tracking.js +83 -0
- package/dist/plugins/decision-tracking.js.map +1 -0
- package/dist/plugins/dom-binding.d.ts +48 -0
- package/dist/plugins/dom-binding.d.ts.map +1 -0
- package/dist/plugins/dom-binding.js +211 -0
- package/dist/plugins/dom-binding.js.map +1 -0
- package/dist/plugins/index.d.ts +70 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +194 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/types.d.ts +62 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +7 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/stable-id.d.ts +44 -0
- package/dist/stable-id.d.ts.map +1 -0
- package/dist/stable-id.js +129 -0
- package/dist/stable-id.js.map +1 -0
- package/dist/storage.d.ts +41 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +144 -0
- package/dist/storage.js.map +1 -0
- package/dist/traffical.min.js +3 -0
- package/dist/traffical.min.js.map +7 -0
- package/package.json +51 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PluginManager - Manages plugin lifecycle and hook execution.
|
|
3
|
+
*
|
|
4
|
+
* Provides a minimal hook-based system for extending SDK functionality.
|
|
5
|
+
*/
|
|
6
|
+
export class PluginManager {
|
|
7
|
+
constructor() {
|
|
8
|
+
this._plugins = [];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Register a plugin.
|
|
12
|
+
*/
|
|
13
|
+
register(options) {
|
|
14
|
+
const plugin = "plugin" in options ? options.plugin : options;
|
|
15
|
+
const priority = "priority" in options ? (options.priority ?? 0) : 0;
|
|
16
|
+
// Check for duplicate names
|
|
17
|
+
if (this._plugins.some((p) => p.plugin.name === plugin.name)) {
|
|
18
|
+
console.warn(`[Traffical] Plugin "${plugin.name}" already registered, skipping.`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
this._plugins.push({ plugin, priority });
|
|
22
|
+
// Sort by priority (descending - higher priority first)
|
|
23
|
+
this._plugins.sort((a, b) => b.priority - a.priority);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Unregister a plugin by name.
|
|
27
|
+
*/
|
|
28
|
+
unregister(name) {
|
|
29
|
+
const index = this._plugins.findIndex((p) => p.plugin.name === name);
|
|
30
|
+
if (index === -1)
|
|
31
|
+
return false;
|
|
32
|
+
this._plugins.splice(index, 1);
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get a registered plugin by name.
|
|
37
|
+
*/
|
|
38
|
+
get(name) {
|
|
39
|
+
return this._plugins.find((p) => p.plugin.name === name)?.plugin;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get all registered plugins.
|
|
43
|
+
*/
|
|
44
|
+
getAll() {
|
|
45
|
+
return this._plugins.map((p) => p.plugin);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Run onInitialize hooks.
|
|
49
|
+
*/
|
|
50
|
+
async runInitialize() {
|
|
51
|
+
for (const { plugin } of this._plugins) {
|
|
52
|
+
if (plugin.onInitialize) {
|
|
53
|
+
try {
|
|
54
|
+
await plugin.onInitialize();
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
console.warn(`[Traffical] Plugin "${plugin.name}" onInitialize error:`, error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Run onConfigUpdate hooks.
|
|
64
|
+
* Called when config bundle is fetched or refreshed.
|
|
65
|
+
*/
|
|
66
|
+
runConfigUpdate(bundle) {
|
|
67
|
+
for (const { plugin } of this._plugins) {
|
|
68
|
+
if (plugin.onConfigUpdate) {
|
|
69
|
+
try {
|
|
70
|
+
plugin.onConfigUpdate(bundle);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.warn(`[Traffical] Plugin "${plugin.name}" onConfigUpdate error:`, error);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Run onBeforeDecision hooks.
|
|
80
|
+
* Returns potentially modified context.
|
|
81
|
+
*/
|
|
82
|
+
runBeforeDecision(context) {
|
|
83
|
+
let result = context;
|
|
84
|
+
for (const { plugin } of this._plugins) {
|
|
85
|
+
if (plugin.onBeforeDecision) {
|
|
86
|
+
try {
|
|
87
|
+
const modified = plugin.onBeforeDecision(result);
|
|
88
|
+
if (modified) {
|
|
89
|
+
result = modified;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.warn(`[Traffical] Plugin "${plugin.name}" onBeforeDecision error:`, error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Run onDecision hooks.
|
|
101
|
+
*/
|
|
102
|
+
runDecision(decision) {
|
|
103
|
+
for (const { plugin } of this._plugins) {
|
|
104
|
+
if (plugin.onDecision) {
|
|
105
|
+
try {
|
|
106
|
+
plugin.onDecision(decision);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.warn(`[Traffical] Plugin "${plugin.name}" onDecision error:`, error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Run onResolve hooks.
|
|
116
|
+
* Called after getParams() resolves parameters.
|
|
117
|
+
*/
|
|
118
|
+
runResolve(params) {
|
|
119
|
+
for (const { plugin } of this._plugins) {
|
|
120
|
+
if (plugin.onResolve) {
|
|
121
|
+
try {
|
|
122
|
+
plugin.onResolve(params);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
console.warn(`[Traffical] Plugin "${plugin.name}" onResolve error:`, error);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Run onExposure hooks.
|
|
132
|
+
* Returns false if any plugin cancels the exposure.
|
|
133
|
+
*/
|
|
134
|
+
runExposure(event) {
|
|
135
|
+
for (const { plugin } of this._plugins) {
|
|
136
|
+
if (plugin.onExposure) {
|
|
137
|
+
try {
|
|
138
|
+
const result = plugin.onExposure(event);
|
|
139
|
+
if (result === false) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.warn(`[Traffical] Plugin "${plugin.name}" onExposure error:`, error);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Run onTrack hooks.
|
|
152
|
+
* Returns false if any plugin cancels the track event.
|
|
153
|
+
*/
|
|
154
|
+
runTrack(event) {
|
|
155
|
+
for (const { plugin } of this._plugins) {
|
|
156
|
+
if (plugin.onTrack) {
|
|
157
|
+
try {
|
|
158
|
+
const result = plugin.onTrack(event);
|
|
159
|
+
if (result === false) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
console.warn(`[Traffical] Plugin "${plugin.name}" onTrack error:`, error);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Run onDestroy hooks.
|
|
172
|
+
*/
|
|
173
|
+
runDestroy() {
|
|
174
|
+
for (const { plugin } of this._plugins) {
|
|
175
|
+
if (plugin.onDestroy) {
|
|
176
|
+
try {
|
|
177
|
+
plugin.onDestroy();
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
console.warn(`[Traffical] Plugin "${plugin.name}" onDestroy error:`, error);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Clear all plugins.
|
|
187
|
+
*/
|
|
188
|
+
clear() {
|
|
189
|
+
this._plugins = [];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// Re-export plugins
|
|
193
|
+
export { createDecisionTrackingPlugin, } from "./decision-tracking.js";
|
|
194
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin types for Traffical JS Client SDK.
|
|
3
|
+
*
|
|
4
|
+
* Plugins can hook into various SDK lifecycle events.
|
|
5
|
+
*/
|
|
6
|
+
import type { ConfigBundle, DecisionResult, ExposureEvent, TrackEvent, Context, ParameterValue } from "@traffical/core";
|
|
7
|
+
/**
|
|
8
|
+
* Plugin interface - implement any subset of hooks.
|
|
9
|
+
*/
|
|
10
|
+
export interface TrafficalPlugin {
|
|
11
|
+
/** Unique plugin name */
|
|
12
|
+
name: string;
|
|
13
|
+
/**
|
|
14
|
+
* Called after client initialization completes.
|
|
15
|
+
*/
|
|
16
|
+
onInitialize?: () => void | Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Called when the config bundle is fetched or refreshed.
|
|
19
|
+
* Useful for plugins that need access to bundle data (e.g., DOM bindings).
|
|
20
|
+
*/
|
|
21
|
+
onConfigUpdate?: (bundle: ConfigBundle) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Called before a decision is made.
|
|
24
|
+
* Can modify context before resolution.
|
|
25
|
+
*/
|
|
26
|
+
onBeforeDecision?: (context: Context) => Context | void;
|
|
27
|
+
/**
|
|
28
|
+
* Called after a decision is made.
|
|
29
|
+
* Useful for logging, analytics, etc.
|
|
30
|
+
*/
|
|
31
|
+
onDecision?: (decision: DecisionResult) => void;
|
|
32
|
+
/**
|
|
33
|
+
* Called after parameters are resolved via getParams().
|
|
34
|
+
* Useful for plugins that need to react to parameter values (e.g., DOM bindings).
|
|
35
|
+
*/
|
|
36
|
+
onResolve?: (params: Record<string, ParameterValue>) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Called before an exposure is tracked.
|
|
39
|
+
* Return false to prevent tracking.
|
|
40
|
+
*/
|
|
41
|
+
onExposure?: (event: ExposureEvent) => boolean | void;
|
|
42
|
+
/**
|
|
43
|
+
* Called before an event is tracked.
|
|
44
|
+
* Return false to prevent tracking.
|
|
45
|
+
*/
|
|
46
|
+
onTrack?: (event: TrackEvent) => boolean | void;
|
|
47
|
+
/**
|
|
48
|
+
* Called when client is destroyed.
|
|
49
|
+
* Cleanup resources here.
|
|
50
|
+
*/
|
|
51
|
+
onDestroy?: () => void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Plugin registration options.
|
|
55
|
+
*/
|
|
56
|
+
export interface PluginOptions {
|
|
57
|
+
/** Plugin instance */
|
|
58
|
+
plugin: TrafficalPlugin;
|
|
59
|
+
/** Priority (higher = runs first, default: 0) */
|
|
60
|
+
priority?: number;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,EACV,OAAO,EACP,cAAc,EACf,MAAM,iBAAiB,CAAC;AAEzB;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1C;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,CAAC;IAEhD;;;OAGG;IACH,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAG,IAAI,CAAC;IAExD;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;IAEhD;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,IAAI,CAAC;IAE7D;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,GAAG,IAAI,CAAC;IAEtD;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,GAAG,IAAI,CAAC;IAEhD;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sBAAsB;IACtB,MAAM,EAAE,eAAe,CAAC;IACxB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StableIdProvider - Anonymous user identification for experimentation.
|
|
3
|
+
*
|
|
4
|
+
* Generates a stable ID on first visit and persists it across sessions.
|
|
5
|
+
* Uses localStorage as primary storage with cookie fallback.
|
|
6
|
+
*/
|
|
7
|
+
import type { StorageProvider } from "./storage.js";
|
|
8
|
+
export interface StableIdProviderOptions {
|
|
9
|
+
/** Storage provider (localStorage) */
|
|
10
|
+
storage: StorageProvider;
|
|
11
|
+
/** Whether to use cookie fallback (default: true) */
|
|
12
|
+
useCookieFallback?: boolean;
|
|
13
|
+
/** Custom cookie name (default: traffical_sid) */
|
|
14
|
+
cookieName?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class StableIdProvider {
|
|
17
|
+
private _storage;
|
|
18
|
+
private _useCookieFallback;
|
|
19
|
+
private _cookieName;
|
|
20
|
+
private _cachedId;
|
|
21
|
+
constructor(options: StableIdProviderOptions);
|
|
22
|
+
/**
|
|
23
|
+
* Get the stable ID, creating one if it doesn't exist.
|
|
24
|
+
*/
|
|
25
|
+
getId(): string;
|
|
26
|
+
/**
|
|
27
|
+
* Set a custom stable ID (e.g., when user logs in).
|
|
28
|
+
*/
|
|
29
|
+
setId(id: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Clear the stable ID (e.g., on logout).
|
|
32
|
+
*/
|
|
33
|
+
clear(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Check if a stable ID exists.
|
|
36
|
+
*/
|
|
37
|
+
hasId(): boolean;
|
|
38
|
+
private _persist;
|
|
39
|
+
private _generateId;
|
|
40
|
+
private _getCookie;
|
|
41
|
+
private _setCookie;
|
|
42
|
+
private _deleteCookie;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=stable-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stable-id.d.ts","sourceRoot":"","sources":["../src/stable-id.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAMpD,MAAM,WAAW,uBAAuB;IACtC,sCAAsC;IACtC,OAAO,EAAE,eAAe,CAAC;IACzB,qDAAqD;IACrD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,kBAAkB,CAAU;IACpC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAuB;gBAE5B,OAAO,EAAE,uBAAuB;IAM5C;;OAEG;IACH,KAAK,IAAI,MAAM;IAgCf;;OAEG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAKvB;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,KAAK,IAAI,OAAO;IAIhB,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,aAAa;CAStB"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StableIdProvider - Anonymous user identification for experimentation.
|
|
3
|
+
*
|
|
4
|
+
* Generates a stable ID on first visit and persists it across sessions.
|
|
5
|
+
* Uses localStorage as primary storage with cookie fallback.
|
|
6
|
+
*/
|
|
7
|
+
const STORAGE_KEY = "stable_id";
|
|
8
|
+
const COOKIE_NAME = "traffical_sid";
|
|
9
|
+
const COOKIE_MAX_AGE_DAYS = 365;
|
|
10
|
+
export class StableIdProvider {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this._cachedId = null;
|
|
13
|
+
this._storage = options.storage;
|
|
14
|
+
this._useCookieFallback = options.useCookieFallback ?? true;
|
|
15
|
+
this._cookieName = options.cookieName ?? COOKIE_NAME;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get the stable ID, creating one if it doesn't exist.
|
|
19
|
+
*/
|
|
20
|
+
getId() {
|
|
21
|
+
// Check cache first
|
|
22
|
+
if (this._cachedId) {
|
|
23
|
+
return this._cachedId;
|
|
24
|
+
}
|
|
25
|
+
// Try localStorage
|
|
26
|
+
let id = this._storage.get(STORAGE_KEY);
|
|
27
|
+
if (id) {
|
|
28
|
+
this._cachedId = id;
|
|
29
|
+
return id;
|
|
30
|
+
}
|
|
31
|
+
// Try cookie fallback
|
|
32
|
+
if (this._useCookieFallback) {
|
|
33
|
+
id = this._getCookie();
|
|
34
|
+
if (id) {
|
|
35
|
+
// Sync back to localStorage
|
|
36
|
+
this._storage.set(STORAGE_KEY, id);
|
|
37
|
+
this._cachedId = id;
|
|
38
|
+
return id;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Generate new ID
|
|
42
|
+
id = this._generateId();
|
|
43
|
+
this._persist(id);
|
|
44
|
+
this._cachedId = id;
|
|
45
|
+
return id;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Set a custom stable ID (e.g., when user logs in).
|
|
49
|
+
*/
|
|
50
|
+
setId(id) {
|
|
51
|
+
this._persist(id);
|
|
52
|
+
this._cachedId = id;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Clear the stable ID (e.g., on logout).
|
|
56
|
+
*/
|
|
57
|
+
clear() {
|
|
58
|
+
this._storage.remove(STORAGE_KEY);
|
|
59
|
+
if (this._useCookieFallback) {
|
|
60
|
+
this._deleteCookie();
|
|
61
|
+
}
|
|
62
|
+
this._cachedId = null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check if a stable ID exists.
|
|
66
|
+
*/
|
|
67
|
+
hasId() {
|
|
68
|
+
return this._storage.get(STORAGE_KEY) !== null || this._getCookie() !== null;
|
|
69
|
+
}
|
|
70
|
+
_persist(id) {
|
|
71
|
+
// Save to localStorage (no TTL - permanent)
|
|
72
|
+
this._storage.set(STORAGE_KEY, id);
|
|
73
|
+
// Save to cookie as fallback
|
|
74
|
+
if (this._useCookieFallback) {
|
|
75
|
+
this._setCookie(id);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
_generateId() {
|
|
79
|
+
// Use crypto.randomUUID if available (modern browsers)
|
|
80
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
81
|
+
return crypto.randomUUID();
|
|
82
|
+
}
|
|
83
|
+
// Fallback to manual UUID v4 generation
|
|
84
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
85
|
+
const r = (Math.random() * 16) | 0;
|
|
86
|
+
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
|
87
|
+
return v.toString(16);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
_getCookie() {
|
|
91
|
+
if (typeof document === "undefined")
|
|
92
|
+
return null;
|
|
93
|
+
try {
|
|
94
|
+
const cookies = document.cookie.split(";");
|
|
95
|
+
for (const cookie of cookies) {
|
|
96
|
+
const [name, value] = cookie.trim().split("=");
|
|
97
|
+
if (name === this._cookieName && value) {
|
|
98
|
+
return decodeURIComponent(value);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Cookie access failed (e.g., cross-origin iframe)
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
_setCookie(value) {
|
|
108
|
+
if (typeof document === "undefined")
|
|
109
|
+
return;
|
|
110
|
+
try {
|
|
111
|
+
const maxAge = COOKIE_MAX_AGE_DAYS * 24 * 60 * 60;
|
|
112
|
+
document.cookie = `${this._cookieName}=${encodeURIComponent(value)}; max-age=${maxAge}; path=/; SameSite=Lax`;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Cookie access failed
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
_deleteCookie() {
|
|
119
|
+
if (typeof document === "undefined")
|
|
120
|
+
return;
|
|
121
|
+
try {
|
|
122
|
+
document.cookie = `${this._cookieName}=; max-age=0; path=/`;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Cookie access failed
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=stable-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stable-id.js","sourceRoot":"","sources":["../src/stable-id.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage abstraction for browser environments.
|
|
3
|
+
*
|
|
4
|
+
* Provides a safe wrapper around localStorage with:
|
|
5
|
+
* - Automatic JSON serialization/deserialization
|
|
6
|
+
* - Graceful fallback when localStorage is unavailable
|
|
7
|
+
* - TTL support for expiring entries
|
|
8
|
+
*/
|
|
9
|
+
export interface StorageProvider {
|
|
10
|
+
get<T>(key: string): T | null;
|
|
11
|
+
set<T>(key: string, value: T, ttlMs?: number): void;
|
|
12
|
+
remove(key: string): void;
|
|
13
|
+
clear(): void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* localStorage-based storage provider.
|
|
17
|
+
*/
|
|
18
|
+
export declare class LocalStorageProvider implements StorageProvider {
|
|
19
|
+
private _available;
|
|
20
|
+
constructor();
|
|
21
|
+
get<T>(key: string): T | null;
|
|
22
|
+
set<T>(key: string, value: T, ttlMs?: number): void;
|
|
23
|
+
remove(key: string): void;
|
|
24
|
+
clear(): void;
|
|
25
|
+
private _checkAvailability;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* In-memory storage fallback when localStorage is unavailable.
|
|
29
|
+
*/
|
|
30
|
+
export declare class MemoryStorageProvider implements StorageProvider {
|
|
31
|
+
private _store;
|
|
32
|
+
get<T>(key: string): T | null;
|
|
33
|
+
set<T>(key: string, value: T, ttlMs?: number): void;
|
|
34
|
+
remove(key: string): void;
|
|
35
|
+
clear(): void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Creates the appropriate storage provider for the current environment.
|
|
39
|
+
*/
|
|
40
|
+
export declare function createStorageProvider(): StorageProvider;
|
|
41
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC;IAC9B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,IAAI,IAAI,CAAC;CACf;AASD;;GAEG;AACH,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,OAAO,CAAC,UAAU,CAAU;;IAM5B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAqB7B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAcnD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAUzB,KAAK,IAAI,IAAI;IAkBb,OAAO,CAAC,kBAAkB;CAU3B;AAED;;GAEG;AACH,qBAAa,qBAAsB,YAAW,eAAe;IAC3D,OAAO,CAAC,MAAM,CAA2C;IAEzD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAa7B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAOnD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIzB,KAAK,IAAI,IAAI;CAGd;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CAQvD"}
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage abstraction for browser environments.
|
|
3
|
+
*
|
|
4
|
+
* Provides a safe wrapper around localStorage with:
|
|
5
|
+
* - Automatic JSON serialization/deserialization
|
|
6
|
+
* - Graceful fallback when localStorage is unavailable
|
|
7
|
+
* - TTL support for expiring entries
|
|
8
|
+
*/
|
|
9
|
+
const STORAGE_PREFIX = "traffical:";
|
|
10
|
+
/**
|
|
11
|
+
* localStorage-based storage provider.
|
|
12
|
+
*/
|
|
13
|
+
export class LocalStorageProvider {
|
|
14
|
+
constructor() {
|
|
15
|
+
this._available = this._checkAvailability();
|
|
16
|
+
}
|
|
17
|
+
get(key) {
|
|
18
|
+
if (!this._available)
|
|
19
|
+
return null;
|
|
20
|
+
try {
|
|
21
|
+
const raw = localStorage.getItem(STORAGE_PREFIX + key);
|
|
22
|
+
if (!raw)
|
|
23
|
+
return null;
|
|
24
|
+
const stored = JSON.parse(raw);
|
|
25
|
+
// Check TTL
|
|
26
|
+
if (stored.expiresAt && Date.now() > stored.expiresAt) {
|
|
27
|
+
this.remove(key);
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return stored.value;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
set(key, value, ttlMs) {
|
|
37
|
+
if (!this._available)
|
|
38
|
+
return;
|
|
39
|
+
try {
|
|
40
|
+
const stored = {
|
|
41
|
+
value,
|
|
42
|
+
...(ttlMs && { expiresAt: Date.now() + ttlMs }),
|
|
43
|
+
};
|
|
44
|
+
localStorage.setItem(STORAGE_PREFIX + key, JSON.stringify(stored));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Storage full or unavailable - silently fail
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
remove(key) {
|
|
51
|
+
if (!this._available)
|
|
52
|
+
return;
|
|
53
|
+
try {
|
|
54
|
+
localStorage.removeItem(STORAGE_PREFIX + key);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Silently fail
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
clear() {
|
|
61
|
+
if (!this._available)
|
|
62
|
+
return;
|
|
63
|
+
try {
|
|
64
|
+
// Only clear traffical-prefixed keys
|
|
65
|
+
const keysToRemove = [];
|
|
66
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
67
|
+
const key = localStorage.key(i);
|
|
68
|
+
if (key?.startsWith(STORAGE_PREFIX)) {
|
|
69
|
+
keysToRemove.push(key);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
keysToRemove.forEach((key) => localStorage.removeItem(key));
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Silently fail
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
_checkAvailability() {
|
|
79
|
+
try {
|
|
80
|
+
const testKey = STORAGE_PREFIX + "__test__";
|
|
81
|
+
localStorage.setItem(testKey, "test");
|
|
82
|
+
localStorage.removeItem(testKey);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* In-memory storage fallback when localStorage is unavailable.
|
|
92
|
+
*/
|
|
93
|
+
export class MemoryStorageProvider {
|
|
94
|
+
constructor() {
|
|
95
|
+
this._store = new Map();
|
|
96
|
+
}
|
|
97
|
+
get(key) {
|
|
98
|
+
const stored = this._store.get(key);
|
|
99
|
+
if (!stored)
|
|
100
|
+
return null;
|
|
101
|
+
// Check TTL
|
|
102
|
+
if (stored.expiresAt && Date.now() > stored.expiresAt) {
|
|
103
|
+
this.remove(key);
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
return stored.value;
|
|
107
|
+
}
|
|
108
|
+
set(key, value, ttlMs) {
|
|
109
|
+
this._store.set(key, {
|
|
110
|
+
value,
|
|
111
|
+
...(ttlMs && { expiresAt: Date.now() + ttlMs }),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
remove(key) {
|
|
115
|
+
this._store.delete(key);
|
|
116
|
+
}
|
|
117
|
+
clear() {
|
|
118
|
+
this._store.clear();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Creates the appropriate storage provider for the current environment.
|
|
123
|
+
*/
|
|
124
|
+
export function createStorageProvider() {
|
|
125
|
+
// Try localStorage first
|
|
126
|
+
const localProvider = new LocalStorageProvider();
|
|
127
|
+
if (localProvider.get("__check__") !== null || localStorageAvailable()) {
|
|
128
|
+
return localProvider;
|
|
129
|
+
}
|
|
130
|
+
// Fall back to in-memory
|
|
131
|
+
return new MemoryStorageProvider();
|
|
132
|
+
}
|
|
133
|
+
function localStorageAvailable() {
|
|
134
|
+
try {
|
|
135
|
+
const testKey = "__traffical_storage_test__";
|
|
136
|
+
localStorage.setItem(testKey, "test");
|
|
137
|
+
localStorage.removeItem(testKey);
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
|