@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,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DecisionTrackingPlugin - Automatically tracks decision events.
|
|
3
|
+
*
|
|
4
|
+
* This plugin hooks into the SDK's decision lifecycle and sends a DecisionEvent
|
|
5
|
+
* to the control plane whenever decide() is called. This enables:
|
|
6
|
+
* - Intent-to-treat analysis: tracking all assignments, not just exposures
|
|
7
|
+
* - Debugging: understanding why specific values were computed
|
|
8
|
+
* - Audit trail: tracking all decisions made by the SDK
|
|
9
|
+
*
|
|
10
|
+
* Decision events are deduplicated: the same user seeing the same assignment
|
|
11
|
+
* will only trigger one event within the deduplication TTL.
|
|
12
|
+
*/
|
|
13
|
+
import type { TrafficalPlugin } from "./types.js";
|
|
14
|
+
import type { DecisionEvent } from "@traffical/core";
|
|
15
|
+
/**
|
|
16
|
+
* Options for the DecisionTrackingPlugin.
|
|
17
|
+
*/
|
|
18
|
+
export interface DecisionTrackingPluginOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Disable decision tracking entirely.
|
|
21
|
+
* Default: false (tracking enabled)
|
|
22
|
+
*/
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Time-to-live for deduplication in milliseconds.
|
|
26
|
+
* Same user+assignment combination won't be tracked again within this window.
|
|
27
|
+
* Default: 1 hour (3600000 ms)
|
|
28
|
+
*/
|
|
29
|
+
deduplicationTtlMs?: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Dependencies injected by the SDK client.
|
|
33
|
+
*/
|
|
34
|
+
export interface DecisionTrackingPluginDeps {
|
|
35
|
+
/** Organization ID */
|
|
36
|
+
orgId: string;
|
|
37
|
+
/** Project ID */
|
|
38
|
+
projectId: string;
|
|
39
|
+
/** Environment */
|
|
40
|
+
env: string;
|
|
41
|
+
/**
|
|
42
|
+
* Function to log a decision event.
|
|
43
|
+
* This is typically the EventLogger.log() method.
|
|
44
|
+
*/
|
|
45
|
+
log: (event: DecisionEvent) => void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates a DecisionTrackingPlugin instance.
|
|
49
|
+
*
|
|
50
|
+
* @param options - Plugin configuration options
|
|
51
|
+
* @param deps - Dependencies injected by the SDK client
|
|
52
|
+
* @returns A TrafficalPlugin that tracks decision events
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const plugin = createDecisionTrackingPlugin(
|
|
57
|
+
* { disabled: false },
|
|
58
|
+
* {
|
|
59
|
+
* orgId: "org_123",
|
|
60
|
+
* projectId: "proj_456",
|
|
61
|
+
* env: "production",
|
|
62
|
+
* log: (event) => eventLogger.log(event),
|
|
63
|
+
* }
|
|
64
|
+
* );
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare function createDecisionTrackingPlugin(options: DecisionTrackingPluginOptions, deps: DecisionTrackingPluginDeps): TrafficalPlugin;
|
|
68
|
+
//# sourceMappingURL=decision-tracking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-tracking.d.ts","sourceRoot":"","sources":["../../src/plugins/decision-tracking.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAkB,aAAa,EAAkB,MAAM,iBAAiB,CAAC;AAMrF;;GAEG;AACH,MAAM,WAAW,6BAA6B;IAC5C;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,GAAG,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,EACtC,IAAI,EAAE,0BAA0B,GAC/B,eAAe,CAwDjB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DecisionTrackingPlugin - Automatically tracks decision events.
|
|
3
|
+
*
|
|
4
|
+
* This plugin hooks into the SDK's decision lifecycle and sends a DecisionEvent
|
|
5
|
+
* to the control plane whenever decide() is called. This enables:
|
|
6
|
+
* - Intent-to-treat analysis: tracking all assignments, not just exposures
|
|
7
|
+
* - Debugging: understanding why specific values were computed
|
|
8
|
+
* - Audit trail: tracking all decisions made by the SDK
|
|
9
|
+
*
|
|
10
|
+
* Decision events are deduplicated: the same user seeing the same assignment
|
|
11
|
+
* will only trigger one event within the deduplication TTL.
|
|
12
|
+
*/
|
|
13
|
+
import { DecisionDeduplicator } from "@traffical/core";
|
|
14
|
+
const SDK_NAME = "js-client";
|
|
15
|
+
const SDK_VERSION = "0.1.0"; // Should match package.json version
|
|
16
|
+
/**
|
|
17
|
+
* Creates a DecisionTrackingPlugin instance.
|
|
18
|
+
*
|
|
19
|
+
* @param options - Plugin configuration options
|
|
20
|
+
* @param deps - Dependencies injected by the SDK client
|
|
21
|
+
* @returns A TrafficalPlugin that tracks decision events
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const plugin = createDecisionTrackingPlugin(
|
|
26
|
+
* { disabled: false },
|
|
27
|
+
* {
|
|
28
|
+
* orgId: "org_123",
|
|
29
|
+
* projectId: "proj_456",
|
|
30
|
+
* env: "production",
|
|
31
|
+
* log: (event) => eventLogger.log(event),
|
|
32
|
+
* }
|
|
33
|
+
* );
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function createDecisionTrackingPlugin(options, deps) {
|
|
37
|
+
const dedup = new DecisionDeduplicator({
|
|
38
|
+
ttlMs: options.deduplicationTtlMs,
|
|
39
|
+
});
|
|
40
|
+
return {
|
|
41
|
+
name: "decision-tracking",
|
|
42
|
+
onDecision(decision) {
|
|
43
|
+
// Skip if disabled
|
|
44
|
+
if (options.disabled) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Skip if no unit key (can't attribute)
|
|
48
|
+
const unitKey = decision.metadata.unitKeyValue;
|
|
49
|
+
if (!unitKey) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Hash assignments for deduplication
|
|
53
|
+
const hash = DecisionDeduplicator.hashAssignments(decision.assignments);
|
|
54
|
+
// Check deduplication
|
|
55
|
+
if (!dedup.checkAndMark(unitKey, hash)) {
|
|
56
|
+
return; // Duplicate, skip
|
|
57
|
+
}
|
|
58
|
+
// Build the decision event
|
|
59
|
+
const event = {
|
|
60
|
+
type: "decision",
|
|
61
|
+
id: decision.decisionId,
|
|
62
|
+
orgId: deps.orgId,
|
|
63
|
+
projectId: deps.projectId,
|
|
64
|
+
env: deps.env,
|
|
65
|
+
unitKey,
|
|
66
|
+
timestamp: decision.metadata.timestamp,
|
|
67
|
+
assignments: decision.assignments,
|
|
68
|
+
layers: decision.metadata.layers,
|
|
69
|
+
// Include filtered context if available (for contextual bandit training)
|
|
70
|
+
context: decision.metadata.filteredContext,
|
|
71
|
+
sdkName: SDK_NAME,
|
|
72
|
+
sdkVersion: SDK_VERSION,
|
|
73
|
+
};
|
|
74
|
+
// Log the event
|
|
75
|
+
deps.log(event);
|
|
76
|
+
},
|
|
77
|
+
onDestroy() {
|
|
78
|
+
// Clear the deduplication cache
|
|
79
|
+
dedup.clear();
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=decision-tracking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-tracking.js","sourceRoot":"","sources":["../../src/plugins/decision-tracking.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,MAAM,QAAQ,GAAG,WAAW,CAAC;AAC7B,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,oCAAoC;AAqCjE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,4BAA4B,CAC1C,OAAsC,EACtC,IAAgC;IAEhC,MAAM,KAAK,GAAG,IAAI,oBAAoB,CAAC;QACrC,KAAK,EAAE,OAAO,CAAC,kBAAkB;KAClC,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,mBAAmB;QAEzB,UAAU,CAAC,QAAwB;YACjC,mBAAmB;YACnB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACrB,OAAO;YACT,CAAC;YAED,wCAAwC;YACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC;YAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO;YACT,CAAC;YAED,qCAAqC;YACrC,MAAM,IAAI,GAAG,oBAAoB,CAAC,eAAe,CAC/C,QAAQ,CAAC,WAA6C,CACvD,CAAC;YAEF,sBAAsB;YACtB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;gBACvC,OAAO,CAAC,kBAAkB;YAC5B,CAAC;YAED,2BAA2B;YAC3B,MAAM,KAAK,GAAkB;gBAC3B,IAAI,EAAE,UAAU;gBAChB,EAAE,EAAE,QAAQ,CAAC,UAAU;gBACvB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,OAAO;gBACP,SAAS,EAAE,QAAQ,CAAC,QAAQ,CAAC,SAAS;gBACtC,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM;gBAChC,yEAAyE;gBACzE,OAAO,EAAE,QAAQ,CAAC,QAAQ,CAAC,eAAe;gBAC1C,OAAO,EAAE,QAAQ;gBACjB,UAAU,EAAE,WAAW;aACxB,CAAC;YAEF,gBAAgB;YAChB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClB,CAAC;QAED,SAAS;YACP,gCAAgC;YAChC,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM Binding Plugin
|
|
3
|
+
*
|
|
4
|
+
* Automatically applies parameter values to DOM elements based on bindings
|
|
5
|
+
* configured in Traffical via the visual editor.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - URL pattern matching to apply bindings only on matching pages
|
|
9
|
+
* - MutationObserver for dynamic content (SPA support)
|
|
10
|
+
* - Supports multiple property types: innerHTML, textContent, src, href, style.*
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { createTrafficalClient, createDOMBindingPlugin } from '@traffical/js-client';
|
|
15
|
+
*
|
|
16
|
+
* const client = await createTrafficalClient({
|
|
17
|
+
* // ... config
|
|
18
|
+
* plugins: [createDOMBindingPlugin()],
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import type { BundleDOMBinding } from "@traffical/core";
|
|
23
|
+
import type { TrafficalPlugin } from "./types.js";
|
|
24
|
+
export interface DOMBindingPluginOptions {
|
|
25
|
+
/**
|
|
26
|
+
* Whether to start observing DOM mutations automatically.
|
|
27
|
+
* Useful for SPAs where content is dynamically loaded.
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
30
|
+
observeMutations?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Debounce time in ms for mutation-triggered reapplication.
|
|
33
|
+
* @default 100
|
|
34
|
+
*/
|
|
35
|
+
debounceMs?: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Creates a DOM binding plugin instance.
|
|
39
|
+
*
|
|
40
|
+
* This plugin applies parameter values to DOM elements based on bindings
|
|
41
|
+
* defined via the visual editor.
|
|
42
|
+
*/
|
|
43
|
+
export declare function createDOMBindingPlugin(options?: DOMBindingPluginOptions): TrafficalPlugin & {
|
|
44
|
+
applyBindings: (params?: Record<string, unknown>) => void;
|
|
45
|
+
getBindings: () => BundleDOMBinding[];
|
|
46
|
+
};
|
|
47
|
+
export type DOMBindingPlugin = ReturnType<typeof createDOMBindingPlugin>;
|
|
48
|
+
//# sourceMappingURL=dom-binding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-binding.d.ts","sourceRoot":"","sources":["../../src/plugins/dom-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAgB,gBAAgB,EAAkB,MAAM,iBAAiB,CAAC;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAMlD,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,GAAE,uBAA4B,GACpC,eAAe,GAAG;IAAE,aAAa,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,gBAAgB,EAAE,CAAA;CAAE,CA2MxH;AAGD,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM Binding Plugin
|
|
3
|
+
*
|
|
4
|
+
* Automatically applies parameter values to DOM elements based on bindings
|
|
5
|
+
* configured in Traffical via the visual editor.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - URL pattern matching to apply bindings only on matching pages
|
|
9
|
+
* - MutationObserver for dynamic content (SPA support)
|
|
10
|
+
* - Supports multiple property types: innerHTML, textContent, src, href, style.*
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { createTrafficalClient, createDOMBindingPlugin } from '@traffical/js-client';
|
|
15
|
+
*
|
|
16
|
+
* const client = await createTrafficalClient({
|
|
17
|
+
* // ... config
|
|
18
|
+
* plugins: [createDOMBindingPlugin()],
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
// =============================================================================
|
|
23
|
+
// DOM Binding Plugin
|
|
24
|
+
// =============================================================================
|
|
25
|
+
/**
|
|
26
|
+
* Creates a DOM binding plugin instance.
|
|
27
|
+
*
|
|
28
|
+
* This plugin applies parameter values to DOM elements based on bindings
|
|
29
|
+
* defined via the visual editor.
|
|
30
|
+
*/
|
|
31
|
+
export function createDOMBindingPlugin(options = {}) {
|
|
32
|
+
const config = {
|
|
33
|
+
observeMutations: options.observeMutations ?? true,
|
|
34
|
+
debounceMs: options.debounceMs ?? 100,
|
|
35
|
+
};
|
|
36
|
+
// Internal state
|
|
37
|
+
let bindings = [];
|
|
38
|
+
let lastParams = {};
|
|
39
|
+
let observer = null;
|
|
40
|
+
let debounceTimer = null;
|
|
41
|
+
// ==========================================================================
|
|
42
|
+
// Core binding logic
|
|
43
|
+
// ==========================================================================
|
|
44
|
+
/**
|
|
45
|
+
* Check if URL matches the binding's pattern.
|
|
46
|
+
*/
|
|
47
|
+
function matchesUrlPattern(pattern, path) {
|
|
48
|
+
try {
|
|
49
|
+
const regex = new RegExp(pattern);
|
|
50
|
+
return regex.test(path);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Invalid regex - fall back to exact match
|
|
54
|
+
return path === pattern;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Set a property on an element.
|
|
59
|
+
* Supports: innerHTML, textContent, src, href, style.*
|
|
60
|
+
*/
|
|
61
|
+
function setProperty(element, property, value) {
|
|
62
|
+
if (property === "innerHTML") {
|
|
63
|
+
element.innerHTML = value;
|
|
64
|
+
}
|
|
65
|
+
else if (property === "textContent") {
|
|
66
|
+
element.textContent = value;
|
|
67
|
+
}
|
|
68
|
+
else if (property === "src" && "src" in element) {
|
|
69
|
+
element.src = value;
|
|
70
|
+
}
|
|
71
|
+
else if (property === "href" && "href" in element) {
|
|
72
|
+
element.href = value;
|
|
73
|
+
}
|
|
74
|
+
else if (property.startsWith("style.")) {
|
|
75
|
+
const styleProp = property.slice(6); // Remove "style." prefix
|
|
76
|
+
element.style[styleProp] = value;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Generic attribute setter for other properties
|
|
80
|
+
element.setAttribute(property, value);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Apply a single binding to matching elements.
|
|
85
|
+
*/
|
|
86
|
+
function applyBinding(binding, value) {
|
|
87
|
+
const stringValue = String(value);
|
|
88
|
+
try {
|
|
89
|
+
const elements = document.querySelectorAll(binding.selector);
|
|
90
|
+
for (const element of elements) {
|
|
91
|
+
setProperty(element, binding.property, stringValue);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
// Invalid selector or other DOM error - silently warn
|
|
96
|
+
console.warn(`[Traffical DOM Binding] Failed to apply binding for ${binding.parameterKey}:`, error);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Apply parameter values to matching DOM elements.
|
|
101
|
+
*/
|
|
102
|
+
function apply(params, forceAll = false) {
|
|
103
|
+
lastParams = params;
|
|
104
|
+
const currentPath = typeof window !== "undefined" ? window.location.pathname : "";
|
|
105
|
+
for (const binding of bindings) {
|
|
106
|
+
// Check URL pattern match
|
|
107
|
+
if (!forceAll && !matchesUrlPattern(binding.urlPattern, currentPath)) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
// Get parameter value
|
|
111
|
+
const value = params[binding.parameterKey];
|
|
112
|
+
if (value === undefined) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
// Apply to matching elements
|
|
116
|
+
applyBinding(binding, value);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Debounced reapplication of bindings after DOM mutations.
|
|
121
|
+
*/
|
|
122
|
+
function debouncedApply() {
|
|
123
|
+
if (debounceTimer) {
|
|
124
|
+
clearTimeout(debounceTimer);
|
|
125
|
+
}
|
|
126
|
+
debounceTimer = setTimeout(() => {
|
|
127
|
+
apply(lastParams);
|
|
128
|
+
}, config.debounceMs);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Start observing DOM mutations.
|
|
132
|
+
*/
|
|
133
|
+
function startObserving() {
|
|
134
|
+
if (observer || typeof MutationObserver === "undefined" || typeof document === "undefined") {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
observer = new MutationObserver(() => {
|
|
138
|
+
debouncedApply();
|
|
139
|
+
});
|
|
140
|
+
observer.observe(document.body, {
|
|
141
|
+
childList: true,
|
|
142
|
+
subtree: true,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Stop observing DOM mutations.
|
|
147
|
+
*/
|
|
148
|
+
function stopObserving() {
|
|
149
|
+
if (observer) {
|
|
150
|
+
observer.disconnect();
|
|
151
|
+
observer = null;
|
|
152
|
+
}
|
|
153
|
+
if (debounceTimer) {
|
|
154
|
+
clearTimeout(debounceTimer);
|
|
155
|
+
debounceTimer = null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// ==========================================================================
|
|
159
|
+
// Plugin implementation
|
|
160
|
+
// ==========================================================================
|
|
161
|
+
return {
|
|
162
|
+
name: "dom-binding",
|
|
163
|
+
onInitialize() {
|
|
164
|
+
// Start observing if enabled
|
|
165
|
+
if (config.observeMutations) {
|
|
166
|
+
startObserving();
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
onConfigUpdate(bundle) {
|
|
170
|
+
// Update bindings from bundle
|
|
171
|
+
bindings = bundle.domBindings ?? [];
|
|
172
|
+
},
|
|
173
|
+
onResolve(params) {
|
|
174
|
+
// Apply bindings after parameters are resolved
|
|
175
|
+
apply(params);
|
|
176
|
+
},
|
|
177
|
+
onDecision(decision) {
|
|
178
|
+
// Also apply after decide() calls
|
|
179
|
+
apply(decision.assignments);
|
|
180
|
+
},
|
|
181
|
+
onDestroy() {
|
|
182
|
+
stopObserving();
|
|
183
|
+
bindings = [];
|
|
184
|
+
lastParams = {};
|
|
185
|
+
},
|
|
186
|
+
// ==========================================================================
|
|
187
|
+
// Public API (exposed on plugin instance)
|
|
188
|
+
// ==========================================================================
|
|
189
|
+
/**
|
|
190
|
+
* Manually apply DOM bindings with the given parameter values.
|
|
191
|
+
* Use this to re-trigger bindings after dynamic content changes.
|
|
192
|
+
*
|
|
193
|
+
* @param params - Parameter values to apply. If omitted, uses last known params.
|
|
194
|
+
*/
|
|
195
|
+
applyBindings(params) {
|
|
196
|
+
if (params) {
|
|
197
|
+
apply(params);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
apply(lastParams);
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
/**
|
|
204
|
+
* Get the current DOM bindings from the config bundle.
|
|
205
|
+
*/
|
|
206
|
+
getBindings() {
|
|
207
|
+
return bindings;
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=dom-binding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-binding.js","sourceRoot":"","sources":["../../src/plugins/dom-binding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PluginManager - Manages plugin lifecycle and hook execution.
|
|
3
|
+
*
|
|
4
|
+
* Provides a minimal hook-based system for extending SDK functionality.
|
|
5
|
+
*/
|
|
6
|
+
import type { ConfigBundle, DecisionResult, ExposureEvent, TrackEvent, Context, ParameterValue } from "@traffical/core";
|
|
7
|
+
import type { TrafficalPlugin, PluginOptions } from "./types.js";
|
|
8
|
+
export declare class PluginManager {
|
|
9
|
+
private _plugins;
|
|
10
|
+
/**
|
|
11
|
+
* Register a plugin.
|
|
12
|
+
*/
|
|
13
|
+
register(options: PluginOptions | TrafficalPlugin): void;
|
|
14
|
+
/**
|
|
15
|
+
* Unregister a plugin by name.
|
|
16
|
+
*/
|
|
17
|
+
unregister(name: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Get a registered plugin by name.
|
|
20
|
+
*/
|
|
21
|
+
get(name: string): TrafficalPlugin | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Get all registered plugins.
|
|
24
|
+
*/
|
|
25
|
+
getAll(): TrafficalPlugin[];
|
|
26
|
+
/**
|
|
27
|
+
* Run onInitialize hooks.
|
|
28
|
+
*/
|
|
29
|
+
runInitialize(): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Run onConfigUpdate hooks.
|
|
32
|
+
* Called when config bundle is fetched or refreshed.
|
|
33
|
+
*/
|
|
34
|
+
runConfigUpdate(bundle: ConfigBundle): void;
|
|
35
|
+
/**
|
|
36
|
+
* Run onBeforeDecision hooks.
|
|
37
|
+
* Returns potentially modified context.
|
|
38
|
+
*/
|
|
39
|
+
runBeforeDecision(context: Context): Context;
|
|
40
|
+
/**
|
|
41
|
+
* Run onDecision hooks.
|
|
42
|
+
*/
|
|
43
|
+
runDecision(decision: DecisionResult): void;
|
|
44
|
+
/**
|
|
45
|
+
* Run onResolve hooks.
|
|
46
|
+
* Called after getParams() resolves parameters.
|
|
47
|
+
*/
|
|
48
|
+
runResolve(params: Record<string, ParameterValue>): void;
|
|
49
|
+
/**
|
|
50
|
+
* Run onExposure hooks.
|
|
51
|
+
* Returns false if any plugin cancels the exposure.
|
|
52
|
+
*/
|
|
53
|
+
runExposure(event: ExposureEvent): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Run onTrack hooks.
|
|
56
|
+
* Returns false if any plugin cancels the track event.
|
|
57
|
+
*/
|
|
58
|
+
runTrack(event: TrackEvent): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Run onDestroy hooks.
|
|
61
|
+
*/
|
|
62
|
+
runDestroy(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Clear all plugins.
|
|
65
|
+
*/
|
|
66
|
+
clear(): void;
|
|
67
|
+
}
|
|
68
|
+
export type { TrafficalPlugin, PluginOptions } from "./types.js";
|
|
69
|
+
export { createDecisionTrackingPlugin, type DecisionTrackingPluginOptions, type DecisionTrackingPluginDeps, } from "./decision-tracking.js";
|
|
70
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,EACV,OAAO,EACP,cAAc,EACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAOjE,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAA0B;IAE1C;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,eAAe,GAAG,IAAI;IAgBxD;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAQjC;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAI9C;;OAEG;IACH,MAAM,IAAI,eAAe,EAAE;IAI3B;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAYpC;;;OAGG;IACH,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAY3C;;;OAGG;IACH,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IAmB5C;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAY3C;;;OAGG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,IAAI;IAYxD;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO;IAiB1C;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO;IAiBpC;;OAEG;IACH,UAAU,IAAI,IAAI;IAYlB;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd;AAGD,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGjE,OAAO,EACL,4BAA4B,EAC5B,KAAK,6BAA6B,EAClC,KAAK,0BAA0B,GAChC,MAAM,wBAAwB,CAAC"}
|