@traffical/core 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.
Files changed (68) hide show
  1. package/dist/dedup/decision-dedup.d.ts +74 -0
  2. package/dist/dedup/decision-dedup.d.ts.map +1 -0
  3. package/dist/dedup/decision-dedup.js +132 -0
  4. package/dist/dedup/decision-dedup.js.map +1 -0
  5. package/dist/dedup/index.d.ts +5 -0
  6. package/dist/dedup/index.d.ts.map +1 -0
  7. package/dist/dedup/index.js +5 -0
  8. package/dist/dedup/index.js.map +1 -0
  9. package/dist/edge/client.d.ts +109 -0
  10. package/dist/edge/client.d.ts.map +1 -0
  11. package/dist/edge/client.js +154 -0
  12. package/dist/edge/client.js.map +1 -0
  13. package/dist/edge/index.d.ts +7 -0
  14. package/dist/edge/index.d.ts.map +1 -0
  15. package/dist/edge/index.js +7 -0
  16. package/dist/edge/index.js.map +1 -0
  17. package/dist/hashing/bucket.d.ts +56 -0
  18. package/dist/hashing/bucket.d.ts.map +1 -0
  19. package/dist/hashing/bucket.js +89 -0
  20. package/dist/hashing/bucket.js.map +1 -0
  21. package/dist/hashing/fnv1a.d.ts +17 -0
  22. package/dist/hashing/fnv1a.d.ts.map +1 -0
  23. package/dist/hashing/fnv1a.js +27 -0
  24. package/dist/hashing/fnv1a.js.map +1 -0
  25. package/dist/hashing/index.d.ts +8 -0
  26. package/dist/hashing/index.d.ts.map +1 -0
  27. package/dist/hashing/index.js +8 -0
  28. package/dist/hashing/index.js.map +1 -0
  29. package/dist/ids/index.d.ts +83 -0
  30. package/dist/ids/index.d.ts.map +1 -0
  31. package/dist/ids/index.js +165 -0
  32. package/dist/ids/index.js.map +1 -0
  33. package/dist/index.d.ts +20 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +32 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/resolution/conditions.d.ts +81 -0
  38. package/dist/resolution/conditions.d.ts.map +1 -0
  39. package/dist/resolution/conditions.js +197 -0
  40. package/dist/resolution/conditions.js.map +1 -0
  41. package/dist/resolution/engine.d.ts +54 -0
  42. package/dist/resolution/engine.d.ts.map +1 -0
  43. package/dist/resolution/engine.js +382 -0
  44. package/dist/resolution/engine.js.map +1 -0
  45. package/dist/resolution/index.d.ts +8 -0
  46. package/dist/resolution/index.d.ts.map +1 -0
  47. package/dist/resolution/index.js +10 -0
  48. package/dist/resolution/index.js.map +1 -0
  49. package/dist/types/index.d.ts +440 -0
  50. package/dist/types/index.d.ts.map +1 -0
  51. package/dist/types/index.js +8 -0
  52. package/dist/types/index.js.map +1 -0
  53. package/package.json +51 -0
  54. package/src/dedup/decision-dedup.ts +175 -0
  55. package/src/dedup/index.ts +6 -0
  56. package/src/edge/client.ts +256 -0
  57. package/src/edge/index.ts +16 -0
  58. package/src/hashing/bucket.ts +115 -0
  59. package/src/hashing/fnv1a.test.ts +87 -0
  60. package/src/hashing/fnv1a.ts +31 -0
  61. package/src/hashing/index.ts +15 -0
  62. package/src/ids/index.ts +221 -0
  63. package/src/index.ts +136 -0
  64. package/src/resolution/conditions.ts +253 -0
  65. package/src/resolution/engine.test.ts +242 -0
  66. package/src/resolution/engine.ts +480 -0
  67. package/src/resolution/index.ts +32 -0
  68. package/src/types/index.ts +508 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * DecisionDeduplicator - Pure decision deduplication logic.
3
+ *
4
+ * Tracks which user+assignment combinations have been seen to avoid
5
+ * sending duplicate decision events. This enables efficient decision
6
+ * tracking without overwhelming the event pipeline.
7
+ *
8
+ * Key differences from ExposureDeduplicator:
9
+ * - Pure in-memory (no I/O, no storage dependency)
10
+ * - Deduplicates on unitKey + assignment hash (not policy/variant)
11
+ * - Suitable for use in any JavaScript environment
12
+ */
13
+ import type { ParameterValue } from "../types/index.js";
14
+ export interface DecisionDeduplicatorOptions {
15
+ /**
16
+ * Time-to-live for deduplication entries in milliseconds.
17
+ * After this time, the same decision can be tracked again.
18
+ * Default: 1 hour (3600000 ms)
19
+ */
20
+ ttlMs?: number;
21
+ /**
22
+ * Maximum number of entries to store.
23
+ * When exceeded, oldest entries are removed.
24
+ * Default: 10000
25
+ */
26
+ maxEntries?: number;
27
+ }
28
+ export declare class DecisionDeduplicator {
29
+ private _seen;
30
+ private readonly _ttlMs;
31
+ private readonly _maxEntries;
32
+ private _lastCleanup;
33
+ constructor(options?: DecisionDeduplicatorOptions);
34
+ /**
35
+ * Generate a stable hash for assignment values.
36
+ * Used to create a deduplication key from assignments.
37
+ */
38
+ static hashAssignments(assignments: Record<string, ParameterValue>): string;
39
+ /**
40
+ * Create a deduplication key from unitKey and assignment hash.
41
+ */
42
+ static createKey(unitKey: string, assignmentHash: string): string;
43
+ /**
44
+ * Check if this decision is new (not seen before within TTL).
45
+ * If new, marks it as seen.
46
+ *
47
+ * @param unitKey - The unit key (user identifier)
48
+ * @param assignmentHash - Hash of the assignments (from hashAssignments)
49
+ * @returns true if this is a new decision, false if duplicate
50
+ */
51
+ checkAndMark(unitKey: string, assignmentHash: string): boolean;
52
+ /**
53
+ * Check if a decision would be considered new (without marking it).
54
+ */
55
+ wouldBeNew(unitKey: string, assignmentHash: string): boolean;
56
+ /**
57
+ * Clear all seen decisions.
58
+ */
59
+ clear(): void;
60
+ /**
61
+ * Get the number of entries in the deduplication cache.
62
+ */
63
+ get size(): number;
64
+ /**
65
+ * Perform cleanup of expired entries.
66
+ * Called periodically based on CLEANUP_THRESHOLD.
67
+ */
68
+ private _maybeCleanup;
69
+ /**
70
+ * Remove expired entries and enforce max size.
71
+ */
72
+ private _cleanup;
73
+ }
74
+ //# sourceMappingURL=decision-dedup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-dedup.d.ts","sourceRoot":"","sources":["../../src/dedup/decision-dedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMxD,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,YAAY,CAAc;gBAEtB,OAAO,GAAE,2BAAgC;IAKrD;;;OAGG;IACH,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,MAAM;IAe3E;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM;IAIjE;;;;;;;OAOG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO;IAmB9D;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO;IAY5D;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;OAGG;IACH,OAAO,CAAC,aAAa;IAcrB;;OAEG;IACH,OAAO,CAAC,QAAQ;CAyBjB"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * DecisionDeduplicator - Pure decision deduplication logic.
3
+ *
4
+ * Tracks which user+assignment combinations have been seen to avoid
5
+ * sending duplicate decision events. This enables efficient decision
6
+ * tracking without overwhelming the event pipeline.
7
+ *
8
+ * Key differences from ExposureDeduplicator:
9
+ * - Pure in-memory (no I/O, no storage dependency)
10
+ * - Deduplicates on unitKey + assignment hash (not policy/variant)
11
+ * - Suitable for use in any JavaScript environment
12
+ */
13
+ const DEFAULT_TTL_MS = 3600_000; // 1 hour
14
+ const DEFAULT_MAX_ENTRIES = 10_000;
15
+ const CLEANUP_THRESHOLD = 0.2; // Clean when 20% of entries are expired
16
+ export class DecisionDeduplicator {
17
+ _seen = new Map(); // key -> timestamp
18
+ _ttlMs;
19
+ _maxEntries;
20
+ _lastCleanup = Date.now();
21
+ constructor(options = {}) {
22
+ this._ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
23
+ this._maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;
24
+ }
25
+ /**
26
+ * Generate a stable hash for assignment values.
27
+ * Used to create a deduplication key from assignments.
28
+ */
29
+ static hashAssignments(assignments) {
30
+ // Sort keys for deterministic ordering
31
+ const sortedKeys = Object.keys(assignments).sort();
32
+ const parts = [];
33
+ for (const key of sortedKeys) {
34
+ const value = assignments[key];
35
+ // Simple string representation that's stable
36
+ const valueStr = typeof value === "object" ? JSON.stringify(value) : String(value);
37
+ parts.push(`${key}=${valueStr}`);
38
+ }
39
+ return parts.join("|");
40
+ }
41
+ /**
42
+ * Create a deduplication key from unitKey and assignment hash.
43
+ */
44
+ static createKey(unitKey, assignmentHash) {
45
+ return `${unitKey}:${assignmentHash}`;
46
+ }
47
+ /**
48
+ * Check if this decision is new (not seen before within TTL).
49
+ * If new, marks it as seen.
50
+ *
51
+ * @param unitKey - The unit key (user identifier)
52
+ * @param assignmentHash - Hash of the assignments (from hashAssignments)
53
+ * @returns true if this is a new decision, false if duplicate
54
+ */
55
+ checkAndMark(unitKey, assignmentHash) {
56
+ const key = DecisionDeduplicator.createKey(unitKey, assignmentHash);
57
+ const now = Date.now();
58
+ const lastSeen = this._seen.get(key);
59
+ // Check if we've seen this within TTL
60
+ if (lastSeen !== undefined && now - lastSeen < this._ttlMs) {
61
+ return false; // Duplicate
62
+ }
63
+ // Mark as seen
64
+ this._seen.set(key, now);
65
+ // Periodic cleanup
66
+ this._maybeCleanup(now);
67
+ return true; // New decision
68
+ }
69
+ /**
70
+ * Check if a decision would be considered new (without marking it).
71
+ */
72
+ wouldBeNew(unitKey, assignmentHash) {
73
+ const key = DecisionDeduplicator.createKey(unitKey, assignmentHash);
74
+ const now = Date.now();
75
+ const lastSeen = this._seen.get(key);
76
+ if (lastSeen === undefined) {
77
+ return true;
78
+ }
79
+ return now - lastSeen >= this._ttlMs;
80
+ }
81
+ /**
82
+ * Clear all seen decisions.
83
+ */
84
+ clear() {
85
+ this._seen.clear();
86
+ }
87
+ /**
88
+ * Get the number of entries in the deduplication cache.
89
+ */
90
+ get size() {
91
+ return this._seen.size;
92
+ }
93
+ /**
94
+ * Perform cleanup of expired entries.
95
+ * Called periodically based on CLEANUP_THRESHOLD.
96
+ */
97
+ _maybeCleanup(now) {
98
+ // Only cleanup periodically, not on every call
99
+ const timeSinceCleanup = now - this._lastCleanup;
100
+ const shouldCleanup = timeSinceCleanup > this._ttlMs * CLEANUP_THRESHOLD || this._seen.size > this._maxEntries;
101
+ if (!shouldCleanup) {
102
+ return;
103
+ }
104
+ this._lastCleanup = now;
105
+ this._cleanup(now);
106
+ }
107
+ /**
108
+ * Remove expired entries and enforce max size.
109
+ */
110
+ _cleanup(now) {
111
+ const expiredKeys = [];
112
+ // Find expired entries
113
+ for (const [key, timestamp] of this._seen.entries()) {
114
+ if (now - timestamp >= this._ttlMs) {
115
+ expiredKeys.push(key);
116
+ }
117
+ }
118
+ // Remove expired entries
119
+ for (const key of expiredKeys) {
120
+ this._seen.delete(key);
121
+ }
122
+ // If still over max, remove oldest entries
123
+ if (this._seen.size > this._maxEntries) {
124
+ const entries = Array.from(this._seen.entries()).sort((a, b) => a[1] - b[1]); // Sort by timestamp
125
+ const toRemove = entries.slice(0, this._seen.size - this._maxEntries);
126
+ for (const [key] of toRemove) {
127
+ this._seen.delete(key);
128
+ }
129
+ }
130
+ }
131
+ }
132
+ //# sourceMappingURL=decision-dedup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-dedup.js","sourceRoot":"","sources":["../../src/dedup/decision-dedup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Deduplication utilities for event tracking.
3
+ */
4
+ export { DecisionDeduplicator, type DecisionDeduplicatorOptions } from "./decision-dedup.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dedup/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,oBAAoB,EAAE,KAAK,2BAA2B,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Deduplication utilities for event tracking.
3
+ */
4
+ export { DecisionDeduplicator } from "./decision-dedup.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dedup/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,oBAAoB,EAAoC,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Edge Client
3
+ *
4
+ * Client for making per-entity decisions via the edge worker API.
5
+ * Used when policies have entityConfig.resolutionMode = "edge".
6
+ *
7
+ * The edge client provides:
8
+ * - Real-time entity state resolution (vs batched bundle updates)
9
+ * - Timeout handling with fallback to bundle
10
+ * - Request batching for multiple entities
11
+ */
12
+ import type { Id, Context } from "../types/index.js";
13
+ /**
14
+ * Request to the edge /decide endpoint.
15
+ */
16
+ export interface EdgeDecideRequest {
17
+ /** Policy ID */
18
+ policyId: Id;
19
+ /** Entity ID (composite from entityKeys) */
20
+ entityId: string;
21
+ /** Unit key value for deterministic selection */
22
+ unitKeyValue: string;
23
+ /** Number of allocations (for dynamic allocations) */
24
+ allocationCount?: number;
25
+ /** Full context (for logging/debugging) */
26
+ context?: Context;
27
+ }
28
+ /**
29
+ * Response from the edge /decide endpoint.
30
+ */
31
+ export interface EdgeDecideResponse {
32
+ /** Selected allocation index */
33
+ allocationIndex: number;
34
+ /** Selected allocation name */
35
+ allocationName: string;
36
+ /** Weights used for selection */
37
+ weights: number[];
38
+ /** Whether this was a cold start (no entity state) */
39
+ coldStart: boolean;
40
+ /** Entity state version */
41
+ stateVersion?: string;
42
+ }
43
+ /**
44
+ * Batch request for multiple entity decisions.
45
+ */
46
+ export interface EdgeBatchDecideRequest {
47
+ /** Array of individual decide requests */
48
+ requests: EdgeDecideRequest[];
49
+ }
50
+ /**
51
+ * Batch response for multiple entity decisions.
52
+ */
53
+ export interface EdgeBatchDecideResponse {
54
+ /** Array of individual decide responses (same order as requests) */
55
+ responses: EdgeDecideResponse[];
56
+ }
57
+ /**
58
+ * Edge client configuration.
59
+ */
60
+ export interface EdgeClientConfig {
61
+ /** Base URL for the edge worker (e.g., "https://edge.traffical.io") */
62
+ baseUrl: string;
63
+ /** Organization ID */
64
+ orgId: Id;
65
+ /** Project ID */
66
+ projectId: Id;
67
+ /** Environment */
68
+ env: string;
69
+ /** API key for authentication */
70
+ apiKey: string;
71
+ /** Default timeout in milliseconds */
72
+ defaultTimeoutMs?: number;
73
+ }
74
+ /**
75
+ * EdgeClient - makes per-entity decisions via the edge worker API.
76
+ */
77
+ export declare class EdgeClient {
78
+ private config;
79
+ private defaultTimeout;
80
+ constructor(config: EdgeClientConfig);
81
+ /**
82
+ * Makes a single entity decision via the edge API.
83
+ *
84
+ * @param request - The decide request
85
+ * @param timeoutMs - Optional timeout override
86
+ * @returns The decide response, or null if request failed/timed out
87
+ */
88
+ decide(request: EdgeDecideRequest, timeoutMs?: number): Promise<EdgeDecideResponse | null>;
89
+ /**
90
+ * Makes multiple entity decisions in a single batch request.
91
+ *
92
+ * @param requests - Array of decide requests
93
+ * @param timeoutMs - Optional timeout override
94
+ * @returns Array of responses (null for failed requests)
95
+ */
96
+ decideBatch(requests: EdgeDecideRequest[], timeoutMs?: number): Promise<(EdgeDecideResponse | null)[]>;
97
+ }
98
+ /**
99
+ * Creates an edge decide request from policy and context.
100
+ *
101
+ * @param policyId - The policy ID
102
+ * @param entityKeys - Array of context keys that identify the entity
103
+ * @param context - The evaluation context
104
+ * @param unitKeyValue - The unit key value
105
+ * @param allocationCount - Number of allocations (for dynamic)
106
+ * @returns The decide request, or null if entity ID cannot be built
107
+ */
108
+ export declare function createEdgeDecideRequest(policyId: Id, entityKeys: string[], context: Context, unitKeyValue: string, allocationCount?: number): EdgeDecideRequest | null;
109
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/edge/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAMrD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB;IAChB,QAAQ,EAAE,EAAE,CAAC;IACb,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,gCAAgC;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,+BAA+B;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sDAAsD;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,2BAA2B;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,0CAA0C;IAC1C,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,SAAS,EAAE,kBAAkB,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,KAAK,EAAE,EAAE,CAAC;IACV,iBAAiB;IACjB,SAAS,EAAE,EAAE,CAAC;IACd,kBAAkB;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAMD;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,cAAc,CAAS;gBAEnB,MAAM,EAAE,gBAAgB;IAKpC;;;;;;OAMG;IACG,MAAM,CACV,OAAO,EAAE,iBAAiB,EAC1B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IA8CrC;;;;;;OAMG;IACG,WAAW,CACf,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,kBAAkB,GAAG,IAAI,CAAC,EAAE,CAAC;CA+C1C;AAMD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,EAAE,EACZ,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,MAAM,GACvB,iBAAiB,GAAG,IAAI,CAmB1B"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Edge Client
3
+ *
4
+ * Client for making per-entity decisions via the edge worker API.
5
+ * Used when policies have entityConfig.resolutionMode = "edge".
6
+ *
7
+ * The edge client provides:
8
+ * - Real-time entity state resolution (vs batched bundle updates)
9
+ * - Timeout handling with fallback to bundle
10
+ * - Request batching for multiple entities
11
+ */
12
+ // =============================================================================
13
+ // Edge Client
14
+ // =============================================================================
15
+ /**
16
+ * EdgeClient - makes per-entity decisions via the edge worker API.
17
+ */
18
+ export class EdgeClient {
19
+ config;
20
+ defaultTimeout;
21
+ constructor(config) {
22
+ this.config = config;
23
+ this.defaultTimeout = config.defaultTimeoutMs ?? 100;
24
+ }
25
+ /**
26
+ * Makes a single entity decision via the edge API.
27
+ *
28
+ * @param request - The decide request
29
+ * @param timeoutMs - Optional timeout override
30
+ * @returns The decide response, or null if request failed/timed out
31
+ */
32
+ async decide(request, timeoutMs) {
33
+ const timeout = timeoutMs ?? this.defaultTimeout;
34
+ try {
35
+ const controller = new AbortController();
36
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
37
+ const url = `${this.config.baseUrl}/v1/decide/${request.policyId}`;
38
+ const response = await fetch(url, {
39
+ method: "POST",
40
+ headers: {
41
+ "Content-Type": "application/json",
42
+ Authorization: `Bearer ${this.config.apiKey}`,
43
+ "X-Org-Id": this.config.orgId,
44
+ "X-Project-Id": this.config.projectId,
45
+ "X-Env": this.config.env,
46
+ },
47
+ body: JSON.stringify({
48
+ entityId: request.entityId,
49
+ unitKeyValue: request.unitKeyValue,
50
+ allocationCount: request.allocationCount,
51
+ context: request.context,
52
+ }),
53
+ signal: controller.signal,
54
+ });
55
+ clearTimeout(timeoutId);
56
+ if (!response.ok) {
57
+ console.warn(`[Traffical] Edge decide failed: ${response.status} ${response.statusText}`);
58
+ return null;
59
+ }
60
+ return (await response.json());
61
+ }
62
+ catch (error) {
63
+ if (error instanceof Error && error.name === "AbortError") {
64
+ console.warn(`[Traffical] Edge decide timed out after ${timeout}ms`);
65
+ }
66
+ else {
67
+ console.warn(`[Traffical] Edge decide error:`, error);
68
+ }
69
+ return null;
70
+ }
71
+ }
72
+ /**
73
+ * Makes multiple entity decisions in a single batch request.
74
+ *
75
+ * @param requests - Array of decide requests
76
+ * @param timeoutMs - Optional timeout override
77
+ * @returns Array of responses (null for failed requests)
78
+ */
79
+ async decideBatch(requests, timeoutMs) {
80
+ if (requests.length === 0)
81
+ return [];
82
+ if (requests.length === 1) {
83
+ const result = await this.decide(requests[0], timeoutMs);
84
+ return [result];
85
+ }
86
+ const timeout = timeoutMs ?? this.defaultTimeout;
87
+ try {
88
+ const controller = new AbortController();
89
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
90
+ const url = `${this.config.baseUrl}/v1/decide/batch`;
91
+ const response = await fetch(url, {
92
+ method: "POST",
93
+ headers: {
94
+ "Content-Type": "application/json",
95
+ Authorization: `Bearer ${this.config.apiKey}`,
96
+ "X-Org-Id": this.config.orgId,
97
+ "X-Project-Id": this.config.projectId,
98
+ "X-Env": this.config.env,
99
+ },
100
+ body: JSON.stringify({ requests }),
101
+ signal: controller.signal,
102
+ });
103
+ clearTimeout(timeoutId);
104
+ if (!response.ok) {
105
+ console.warn(`[Traffical] Edge batch decide failed: ${response.status} ${response.statusText}`);
106
+ return requests.map(() => null);
107
+ }
108
+ const data = (await response.json());
109
+ return data.responses;
110
+ }
111
+ catch (error) {
112
+ if (error instanceof Error && error.name === "AbortError") {
113
+ console.warn(`[Traffical] Edge batch decide timed out after ${timeout}ms`);
114
+ }
115
+ else {
116
+ console.warn(`[Traffical] Edge batch decide error:`, error);
117
+ }
118
+ return requests.map(() => null);
119
+ }
120
+ }
121
+ }
122
+ // =============================================================================
123
+ // Utility Functions
124
+ // =============================================================================
125
+ /**
126
+ * Creates an edge decide request from policy and context.
127
+ *
128
+ * @param policyId - The policy ID
129
+ * @param entityKeys - Array of context keys that identify the entity
130
+ * @param context - The evaluation context
131
+ * @param unitKeyValue - The unit key value
132
+ * @param allocationCount - Number of allocations (for dynamic)
133
+ * @returns The decide request, or null if entity ID cannot be built
134
+ */
135
+ export function createEdgeDecideRequest(policyId, entityKeys, context, unitKeyValue, allocationCount) {
136
+ // Build entity ID from context
137
+ const parts = [];
138
+ for (const key of entityKeys) {
139
+ const value = context[key];
140
+ if (value === undefined || value === null) {
141
+ return null;
142
+ }
143
+ parts.push(String(value));
144
+ }
145
+ const entityId = parts.join("_");
146
+ return {
147
+ policyId,
148
+ entityId,
149
+ unitKeyValue,
150
+ allocationCount,
151
+ context,
152
+ };
153
+ }
154
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/edge/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA0EH,gFAAgF;AAChF,cAAc;AACd,gFAAgF;AAEhF;;GAEG;AACH,MAAM,OAAO,UAAU;IACb,MAAM,CAAmB;IACzB,cAAc,CAAS;IAE/B,YAAY,MAAwB;QAClC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,gBAAgB,IAAI,GAAG,CAAC;IACvD,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,CACV,OAA0B,EAC1B,SAAkB;QAElB,MAAM,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,cAAc,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;YAEhE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,cAAc,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;oBAC7C,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK;oBAC7B,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;oBACrC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG;iBACzB;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,eAAe,EAAE,OAAO,CAAC,eAAe;oBACxC,OAAO,EAAE,OAAO,CAAC,OAAO;iBACzB,CAAC;gBACF,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,CAAC,IAAI,CACV,mCAAmC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAC5E,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAuB,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC1D,OAAO,CAAC,IAAI,CAAC,2CAA2C,OAAO,IAAI,CAAC,CAAC;YACvE,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;YACxD,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,WAAW,CACf,QAA6B,EAC7B,SAAkB;QAElB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACrC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YACzD,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,cAAc,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;YAEhE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,kBAAkB,CAAC;YACrD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;oBAC7C,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK;oBAC7B,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;oBACrC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG;iBACzB;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;gBAClC,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,CAAC,IAAI,CACV,yCAAyC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAClF,CAAC;gBACF,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;YAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA4B,CAAC;YAChE,OAAO,IAAI,CAAC,SAAS,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC1D,OAAO,CAAC,IAAI,CAAC,iDAAiD,OAAO,IAAI,CAAC,CAAC;YAC7E,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,IAAI,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;YAC9D,CAAC;YACD,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;CACF;AAED,gFAAgF;AAChF,oBAAoB;AACpB,gFAAgF;AAEhF;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACrC,QAAY,EACZ,UAAoB,EACpB,OAAgB,EAChB,YAAoB,EACpB,eAAwB;IAExB,+BAA+B;IAC/B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5B,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEjC,OAAO;QACL,QAAQ;QACR,QAAQ;QACR,YAAY;QACZ,eAAe;QACf,OAAO;KACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Edge Client Module
3
+ *
4
+ * Exports for making per-entity decisions via the edge worker API.
5
+ */
6
+ export { EdgeClient, createEdgeDecideRequest, type EdgeClientConfig, type EdgeDecideRequest, type EdgeDecideResponse, type EdgeBatchDecideRequest, type EdgeBatchDecideResponse, } from "./client.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/edge/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,UAAU,EACV,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,aAAa,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Edge Client Module
3
+ *
4
+ * Exports for making per-entity decisions via the edge worker API.
5
+ */
6
+ export { EdgeClient, createEdgeDecideRequest, } from "./client.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/edge/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,UAAU,EACV,uBAAuB,GAMxB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Bucket Computation
3
+ *
4
+ * Deterministic bucket assignment for traffic splitting.
5
+ * The bucket is computed as: hash(unitKeyValue + ":" + layerId) % bucketCount
6
+ *
7
+ * This ensures:
8
+ * - Same user always gets same bucket for a given layer
9
+ * - Different layers can have independent bucketing (orthogonality)
10
+ * - Deterministic results across SDK and server
11
+ */
12
+ /**
13
+ * Computes the bucket for a given unit and layer.
14
+ *
15
+ * @param unitKeyValue - The value of the unit key (e.g., userId value)
16
+ * @param layerId - The layer ID for orthogonal bucketing
17
+ * @param bucketCount - Total number of buckets (e.g., 1000)
18
+ * @returns Bucket number in range [0, bucketCount - 1]
19
+ */
20
+ export declare function computeBucket(unitKeyValue: string, layerId: string, bucketCount: number): number;
21
+ /**
22
+ * Checks if a bucket falls within a range.
23
+ *
24
+ * @param bucket - The computed bucket
25
+ * @param range - [start, end] inclusive range
26
+ * @returns True if bucket is in range
27
+ */
28
+ export declare function isInBucketRange(bucket: number, range: [number, number]): boolean;
29
+ /**
30
+ * Finds which allocation matches a given bucket.
31
+ *
32
+ * @param bucket - The computed bucket
33
+ * @param allocations - Array of allocations with bucket ranges
34
+ * @returns The matching allocation, or null if none match
35
+ */
36
+ export declare function findMatchingAllocation<T extends {
37
+ bucketRange: [number, number];
38
+ }>(bucket: number, allocations: T[]): T | null;
39
+ /**
40
+ * Converts a percentage to a bucket range.
41
+ *
42
+ * @param percentage - Traffic percentage (0-100)
43
+ * @param bucketCount - Total buckets
44
+ * @param startBucket - Starting bucket (default 0)
45
+ * @returns [start, end] bucket range
46
+ */
47
+ export declare function percentageToBucketRange(percentage: number, bucketCount: number, startBucket?: number): [number, number];
48
+ /**
49
+ * Creates non-overlapping bucket ranges for multiple variants.
50
+ *
51
+ * @param percentages - Array of percentages that should sum to <= 100
52
+ * @param bucketCount - Total buckets
53
+ * @returns Array of [start, end] bucket ranges
54
+ */
55
+ export declare function createBucketRanges(percentages: number[], bucketCount: number): [number, number][];
56
+ //# sourceMappingURL=bucket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bucket.d.ts","sourceRoot":"","sources":["../../src/hashing/bucket.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,GAClB,MAAM,CASR;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,OAAO,CAET;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,CAAC,SAAS;IAAE,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,EAC3C,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,IAAI,CAO5C;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,WAAW,SAAI,GACd,CAAC,MAAM,EAAE,MAAM,CAAC,CAIlB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,EAAE,EACrB,WAAW,EAAE,MAAM,GAClB,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAgBpB"}