@traffical/svelte 0.1.0

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.
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @traffical/svelte - Hooks
3
+ *
4
+ * Svelte 5 hooks for parameter resolution and decision tracking.
5
+ * Uses runes ($derived, $effect) for reactive, fine-grained updates.
6
+ */
7
+ import type { ParameterValue } from "@traffical/core";
8
+ import type { TrafficalPlugin, TrafficalClient } from "@traffical/js-client";
9
+ import type { UseTrafficalOptions, UseTrafficalResult, TrackRewardOptions, TrackEventOptions } from "./types.js";
10
+ /**
11
+ * Primary hook for Traffical parameter resolution and decision tracking.
12
+ *
13
+ * Returns reactive values that automatically update when the config bundle changes.
14
+ * On first render, returns defaults immediately (no blocking).
15
+ * When the config bundle loads, recomputes and returns resolved values.
16
+ *
17
+ * @example
18
+ * ```svelte
19
+ * <script>
20
+ * import { useTraffical } from '@traffical/svelte';
21
+ *
22
+ * // Full tracking (default) - decision + exposure events
23
+ * const { params, decision, ready } = useTraffical({
24
+ * defaults: { "checkout.ctaText": "Buy Now" },
25
+ * });
26
+ * </script>
27
+ *
28
+ * {#if ready}
29
+ * <button>{params['checkout.ctaText']}</button>
30
+ * {:else}
31
+ * <button disabled>Loading...</button>
32
+ * {/if}
33
+ * ```
34
+ *
35
+ * @example
36
+ * ```svelte
37
+ * <script>
38
+ * // Decision tracking only - manual exposure control
39
+ * const { params, decision, trackExposure } = useTraffical({
40
+ * defaults: { "checkout.ctaText": "Buy Now" },
41
+ * tracking: "decision",
42
+ * });
43
+ *
44
+ * // Track exposure when element becomes visible
45
+ * function handleVisible() {
46
+ * trackExposure();
47
+ * }
48
+ * </script>
49
+ * ```
50
+ *
51
+ * @example
52
+ * ```svelte
53
+ * <script>
54
+ * // No tracking - for SSR, tests, or internal logic
55
+ * const { params, ready } = useTraffical({
56
+ * defaults: { "ui.hero.title": "Welcome" },
57
+ * tracking: "none",
58
+ * });
59
+ * </script>
60
+ * ```
61
+ */
62
+ export declare function useTraffical<T extends Record<string, ParameterValue>>(options: UseTrafficalOptions<T>): UseTrafficalResult<T>;
63
+ /**
64
+ * Hook to track user events.
65
+ *
66
+ * @example
67
+ * ```svelte
68
+ * <script>
69
+ * import { useTrafficalTrack } from '@traffical/svelte';
70
+ *
71
+ * const track = useTrafficalTrack();
72
+ *
73
+ * function handlePurchase(amount: number) {
74
+ * track({
75
+ * event: 'purchase',
76
+ * properties: { value: amount, orderId: 'ord_123' },
77
+ * });
78
+ * }
79
+ * </script>
80
+ * ```
81
+ */
82
+ export declare function useTrafficalTrack(): (options: TrackEventOptions) => void;
83
+ /**
84
+ * @deprecated Use useTrafficalTrack() instead.
85
+ *
86
+ * Hook to track rewards (conversions, revenue, etc.).
87
+ *
88
+ * @example
89
+ * ```svelte
90
+ * <script>
91
+ * import { useTraffical, useTrafficalReward } from '@traffical/svelte';
92
+ *
93
+ * const { params, decision } = useTraffical({
94
+ * defaults: { 'checkout.ctaText': 'Buy Now' },
95
+ * });
96
+ *
97
+ * const trackReward = useTrafficalReward();
98
+ *
99
+ * function handlePurchase(amount: number) {
100
+ * trackReward({
101
+ * reward: amount,
102
+ * rewardType: 'revenue',
103
+ * });
104
+ * }
105
+ * </script>
106
+ * ```
107
+ */
108
+ export declare function useTrafficalReward(): (options: TrackRewardOptions) => void;
109
+ /**
110
+ * Hook to access the Traffical client directly.
111
+ *
112
+ * @example
113
+ * ```svelte
114
+ * <script>
115
+ * import { useTrafficalClient } from '@traffical/svelte';
116
+ *
117
+ * const { client, ready, error } = useTrafficalClient();
118
+ *
119
+ * $effect(() => {
120
+ * if (ready && client) {
121
+ * const version = client.getConfigVersion();
122
+ * const stableId = client.getStableId();
123
+ * console.log('Config version:', version, 'Stable ID:', stableId);
124
+ * }
125
+ * });
126
+ * </script>
127
+ * ```
128
+ */
129
+ export declare function useTrafficalClient(): {
130
+ readonly client: TrafficalClient | null;
131
+ readonly ready: boolean;
132
+ readonly error: Error | null;
133
+ };
134
+ /**
135
+ * Hook to access a registered plugin by name.
136
+ *
137
+ * @example
138
+ * ```svelte
139
+ * <script>
140
+ * import { useTrafficalPlugin } from '@traffical/svelte';
141
+ * import type { DOMBindingPlugin } from '@traffical/js-client';
142
+ *
143
+ * const domPlugin = useTrafficalPlugin<DOMBindingPlugin>('dom-binding');
144
+ *
145
+ * // Re-apply bindings after dynamic content changes
146
+ * $effect(() => {
147
+ * if (contentLoaded) {
148
+ * domPlugin?.applyBindings();
149
+ * }
150
+ * });
151
+ * </script>
152
+ * ```
153
+ */
154
+ export declare function useTrafficalPlugin<T extends TrafficalPlugin = TrafficalPlugin>(name: string): T | undefined;
155
+ //# sourceMappingURL=hooks.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.svelte.d.ts","sourceRoot":"","sources":["../src/hooks.svelte.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAElB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAcpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,EACnE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAC9B,kBAAkB,CAAC,CAAC,CAAC,CAsKvB;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,IAAI,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAiBxE;AAMD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,IAAI,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CA4B1E;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,IAAI;IACpC,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CAC9B,CAcA;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAChC,CAAC,SAAS,eAAe,GAAG,eAAe,EAC3C,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAY7B"}
@@ -0,0 +1,371 @@
1
+ /**
2
+ * @traffical/svelte - Hooks
3
+ *
4
+ * Svelte 5 hooks for parameter resolution and decision tracking.
5
+ * Uses runes ($derived, $effect) for reactive, fine-grained updates.
6
+ */
7
+ import { resolveParameters, decide as coreDecide } from "@traffical/core";
8
+ import { getTrafficalContext } from "./context.svelte.js";
9
+ // =============================================================================
10
+ // Browser Detection
11
+ // =============================================================================
12
+ function isBrowser() {
13
+ return typeof window !== "undefined" && typeof document !== "undefined";
14
+ }
15
+ // =============================================================================
16
+ // useTraffical - Primary Hook
17
+ // =============================================================================
18
+ /**
19
+ * Primary hook for Traffical parameter resolution and decision tracking.
20
+ *
21
+ * Returns reactive values that automatically update when the config bundle changes.
22
+ * On first render, returns defaults immediately (no blocking).
23
+ * When the config bundle loads, recomputes and returns resolved values.
24
+ *
25
+ * @example
26
+ * ```svelte
27
+ * <script>
28
+ * import { useTraffical } from '@traffical/svelte';
29
+ *
30
+ * // Full tracking (default) - decision + exposure events
31
+ * const { params, decision, ready } = useTraffical({
32
+ * defaults: { "checkout.ctaText": "Buy Now" },
33
+ * });
34
+ * </script>
35
+ *
36
+ * {#if ready}
37
+ * <button>{params['checkout.ctaText']}</button>
38
+ * {:else}
39
+ * <button disabled>Loading...</button>
40
+ * {/if}
41
+ * ```
42
+ *
43
+ * @example
44
+ * ```svelte
45
+ * <script>
46
+ * // Decision tracking only - manual exposure control
47
+ * const { params, decision, trackExposure } = useTraffical({
48
+ * defaults: { "checkout.ctaText": "Buy Now" },
49
+ * tracking: "decision",
50
+ * });
51
+ *
52
+ * // Track exposure when element becomes visible
53
+ * function handleVisible() {
54
+ * trackExposure();
55
+ * }
56
+ * </script>
57
+ * ```
58
+ *
59
+ * @example
60
+ * ```svelte
61
+ * <script>
62
+ * // No tracking - for SSR, tests, or internal logic
63
+ * const { params, ready } = useTraffical({
64
+ * defaults: { "ui.hero.title": "Welcome" },
65
+ * tracking: "none",
66
+ * });
67
+ * </script>
68
+ * ```
69
+ */
70
+ export function useTraffical(options) {
71
+ const ctx = getTrafficalContext();
72
+ const trackingMode = options.tracking ?? "full";
73
+ const shouldTrackDecision = trackingMode !== "none";
74
+ const shouldAutoTrackExposure = trackingMode === "full";
75
+ // Track whether we've already tracked exposure for this decision
76
+ let hasTrackedExposure = $state(false);
77
+ let currentDecisionId = $state(null);
78
+ // Derive params reactively using $derived.by
79
+ // This is synchronous and provides fine-grained reactivity
80
+ const params = $derived.by(() => {
81
+ // Priority 1: Resolve from bundle if available
82
+ if (ctx.bundle) {
83
+ const context = {
84
+ ...ctx.getContext(),
85
+ ...options.context,
86
+ };
87
+ return resolveParameters(ctx.bundle, context, options.defaults);
88
+ }
89
+ // Priority 2: Use server-provided initial params
90
+ if (ctx.initialParams) {
91
+ return { ...options.defaults, ...ctx.initialParams };
92
+ }
93
+ // Priority 3: Fall back to defaults
94
+ return options.defaults;
95
+ });
96
+ // Derive decision reactively
97
+ const decision = $derived.by(() => {
98
+ if (!shouldTrackDecision) {
99
+ return null;
100
+ }
101
+ if (!ctx.bundle) {
102
+ return null;
103
+ }
104
+ const context = {
105
+ ...ctx.getContext(),
106
+ ...options.context,
107
+ };
108
+ // Use client's decide if available (handles tracking internally)
109
+ if (ctx.client) {
110
+ return ctx.client.decide({
111
+ context,
112
+ defaults: options.defaults,
113
+ });
114
+ }
115
+ // Fall back to core decide (SSR or no client)
116
+ return coreDecide(ctx.bundle, context, options.defaults);
117
+ });
118
+ // Reset exposure tracking when decision changes
119
+ $effect(() => {
120
+ const decisionId = decision?.decisionId ?? null;
121
+ if (decisionId !== currentDecisionId) {
122
+ currentDecisionId = decisionId;
123
+ hasTrackedExposure = false;
124
+ }
125
+ });
126
+ // Auto-track exposure when tracking is "full" and decision is available
127
+ $effect(() => {
128
+ if (shouldAutoTrackExposure &&
129
+ decision &&
130
+ !hasTrackedExposure &&
131
+ isBrowser()) {
132
+ trackExposureInternal();
133
+ }
134
+ });
135
+ // Internal exposure tracking function
136
+ function trackExposureInternal() {
137
+ if (!isBrowser() || !ctx.client || !decision || hasTrackedExposure) {
138
+ return;
139
+ }
140
+ ctx.client.trackExposure(decision);
141
+ hasTrackedExposure = true;
142
+ }
143
+ // Public exposure tracking function
144
+ function trackExposure() {
145
+ if (trackingMode === "none") {
146
+ return;
147
+ }
148
+ trackExposureInternal();
149
+ }
150
+ // Track user events - decisionId is automatically included
151
+ function track(event, properties) {
152
+ if (!isBrowser() || !ctx.client) {
153
+ if (!isBrowser()) {
154
+ return; // Silent no-op during SSR
155
+ }
156
+ console.warn("[Traffical] Client not initialized, cannot track event");
157
+ return;
158
+ }
159
+ // Access the reactive decision value
160
+ const currentDecision = decision;
161
+ if (!currentDecision) {
162
+ console.warn("[Traffical] No decision available, cannot track event. Did you use tracking: 'none'?");
163
+ return;
164
+ }
165
+ ctx.client.track(event, properties, {
166
+ decisionId: currentDecision.decisionId,
167
+ unitKey: ctx.getUnitKey(),
168
+ });
169
+ }
170
+ // Deprecated: Bound reward tracking - decisionId is automatically included
171
+ function trackReward(options) {
172
+ if (!isBrowser() || !ctx.client) {
173
+ if (!isBrowser()) {
174
+ return; // Silent no-op during SSR
175
+ }
176
+ console.warn("[Traffical] Client not initialized, cannot track reward");
177
+ return;
178
+ }
179
+ // Access the reactive decision value
180
+ const currentDecision = decision;
181
+ if (!currentDecision) {
182
+ console.warn("[Traffical] No decision available, cannot track reward. Did you use tracking: 'none'?");
183
+ return;
184
+ }
185
+ // Map old API to new track() API
186
+ track(options.rewardType || "reward", {
187
+ value: options.reward,
188
+ ...(options.rewards ? { rewards: options.rewards } : {}),
189
+ });
190
+ }
191
+ return {
192
+ get params() {
193
+ return params;
194
+ },
195
+ get decision() {
196
+ return decision;
197
+ },
198
+ get ready() {
199
+ return ctx.ready;
200
+ },
201
+ get error() {
202
+ return ctx.error;
203
+ },
204
+ trackExposure,
205
+ track,
206
+ trackReward,
207
+ };
208
+ }
209
+ // =============================================================================
210
+ // useTrafficalTrack
211
+ // =============================================================================
212
+ /**
213
+ * Hook to track user events.
214
+ *
215
+ * @example
216
+ * ```svelte
217
+ * <script>
218
+ * import { useTrafficalTrack } from '@traffical/svelte';
219
+ *
220
+ * const track = useTrafficalTrack();
221
+ *
222
+ * function handlePurchase(amount: number) {
223
+ * track({
224
+ * event: 'purchase',
225
+ * properties: { value: amount, orderId: 'ord_123' },
226
+ * });
227
+ * }
228
+ * </script>
229
+ * ```
230
+ */
231
+ export function useTrafficalTrack() {
232
+ const ctx = getTrafficalContext();
233
+ return function track(options) {
234
+ if (!isBrowser() || !ctx.client) {
235
+ if (!isBrowser()) {
236
+ return; // Silent no-op during SSR
237
+ }
238
+ console.warn("[Traffical] Client not initialized, cannot track event");
239
+ return;
240
+ }
241
+ ctx.client.track(options.event, options.properties, {
242
+ decisionId: options.decisionId,
243
+ unitKey: ctx.getUnitKey(),
244
+ });
245
+ };
246
+ }
247
+ // =============================================================================
248
+ // useTrafficalReward (deprecated)
249
+ // =============================================================================
250
+ /**
251
+ * @deprecated Use useTrafficalTrack() instead.
252
+ *
253
+ * Hook to track rewards (conversions, revenue, etc.).
254
+ *
255
+ * @example
256
+ * ```svelte
257
+ * <script>
258
+ * import { useTraffical, useTrafficalReward } from '@traffical/svelte';
259
+ *
260
+ * const { params, decision } = useTraffical({
261
+ * defaults: { 'checkout.ctaText': 'Buy Now' },
262
+ * });
263
+ *
264
+ * const trackReward = useTrafficalReward();
265
+ *
266
+ * function handlePurchase(amount: number) {
267
+ * trackReward({
268
+ * reward: amount,
269
+ * rewardType: 'revenue',
270
+ * });
271
+ * }
272
+ * </script>
273
+ * ```
274
+ */
275
+ export function useTrafficalReward() {
276
+ const ctx = getTrafficalContext();
277
+ return function trackReward(options) {
278
+ if (!isBrowser() || !ctx.client) {
279
+ if (!isBrowser()) {
280
+ return; // Silent no-op during SSR
281
+ }
282
+ console.warn("[Traffical] Client not initialized, cannot track reward");
283
+ return;
284
+ }
285
+ // We need to ensure decisionId is provided for the core TrackRewardOptions
286
+ // If not provided, we skip tracking (can't attribute without decision)
287
+ if (!options.decisionId) {
288
+ console.warn("[Traffical] trackReward called without decisionId, skipping");
289
+ return;
290
+ }
291
+ // Map old API to new track() API
292
+ ctx.client.track(options.rewardType || "reward", {
293
+ value: options.reward,
294
+ ...(options.rewards ? { rewards: options.rewards } : {}),
295
+ }, {
296
+ decisionId: options.decisionId,
297
+ unitKey: ctx.getUnitKey(),
298
+ });
299
+ };
300
+ }
301
+ // =============================================================================
302
+ // useTrafficalClient
303
+ // =============================================================================
304
+ /**
305
+ * Hook to access the Traffical client directly.
306
+ *
307
+ * @example
308
+ * ```svelte
309
+ * <script>
310
+ * import { useTrafficalClient } from '@traffical/svelte';
311
+ *
312
+ * const { client, ready, error } = useTrafficalClient();
313
+ *
314
+ * $effect(() => {
315
+ * if (ready && client) {
316
+ * const version = client.getConfigVersion();
317
+ * const stableId = client.getStableId();
318
+ * console.log('Config version:', version, 'Stable ID:', stableId);
319
+ * }
320
+ * });
321
+ * </script>
322
+ * ```
323
+ */
324
+ export function useTrafficalClient() {
325
+ const ctx = getTrafficalContext();
326
+ return {
327
+ get client() {
328
+ return ctx.client;
329
+ },
330
+ get ready() {
331
+ return ctx.ready;
332
+ },
333
+ get error() {
334
+ return ctx.error;
335
+ },
336
+ };
337
+ }
338
+ // =============================================================================
339
+ // useTrafficalPlugin
340
+ // =============================================================================
341
+ /**
342
+ * Hook to access a registered plugin by name.
343
+ *
344
+ * @example
345
+ * ```svelte
346
+ * <script>
347
+ * import { useTrafficalPlugin } from '@traffical/svelte';
348
+ * import type { DOMBindingPlugin } from '@traffical/js-client';
349
+ *
350
+ * const domPlugin = useTrafficalPlugin<DOMBindingPlugin>('dom-binding');
351
+ *
352
+ * // Re-apply bindings after dynamic content changes
353
+ * $effect(() => {
354
+ * if (contentLoaded) {
355
+ * domPlugin?.applyBindings();
356
+ * }
357
+ * });
358
+ * </script>
359
+ * ```
360
+ */
361
+ export function useTrafficalPlugin(name) {
362
+ const ctx = getTrafficalContext();
363
+ // Derive plugin access reactively
364
+ const plugin = $derived.by(() => {
365
+ if (!ctx.client || !ctx.ready) {
366
+ return undefined;
367
+ }
368
+ return ctx.client.getPlugin(name);
369
+ });
370
+ return plugin;
371
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @traffical/svelte
3
+ *
4
+ * Traffical SDK for Svelte 5 applications.
5
+ * Provides Provider component and hooks for parameter resolution and decision tracking.
6
+ *
7
+ * Features:
8
+ * - Full SSR/hydration support for SvelteKit
9
+ * - Svelte 5 runes for reactive, fine-grained updates
10
+ * - Browser-optimized with sendBeacon, localStorage persistence
11
+ * - Automatic stable ID for anonymous users
12
+ * - Plugin system support (DecisionTrackingPlugin enabled by default)
13
+ * - Decision and exposure deduplication
14
+ *
15
+ * @example
16
+ * ```svelte
17
+ * <!-- +layout.svelte -->
18
+ * <script>
19
+ * import { TrafficalProvider } from '@traffical/svelte';
20
+ *
21
+ * let { data, children } = $props();
22
+ * </script>
23
+ *
24
+ * <TrafficalProvider
25
+ * config={{
26
+ * orgId: 'org_123',
27
+ * projectId: 'proj_456',
28
+ * env: 'production',
29
+ * apiKey: 'pk_...',
30
+ * initialBundle: data.traffical?.bundle,
31
+ * }}
32
+ * >
33
+ * {@render children()}
34
+ * </TrafficalProvider>
35
+ * ```
36
+ *
37
+ * @example
38
+ * ```svelte
39
+ * <!-- MyComponent.svelte -->
40
+ * <script>
41
+ * import { useTraffical } from '@traffical/svelte';
42
+ *
43
+ * const { params, ready } = useTraffical({
44
+ * defaults: { 'ui.hero.title': 'Welcome' },
45
+ * });
46
+ * </script>
47
+ *
48
+ * {#if ready}
49
+ * <h1>{params['ui.hero.title']}</h1>
50
+ * {:else}
51
+ * <h1>Loading...</h1>
52
+ * {/if}
53
+ * ```
54
+ */
55
+ export { resolveParameters, decide, evaluateCondition, evaluateConditions, fnv1a, computeBucket, isInBucketRange, generateEventId, generateDecisionId, generateExposureId, generateRewardId, } from "@traffical/core";
56
+ export { TrafficalClient, createTrafficalClient, createTrafficalClientSync, LocalStorageProvider, MemoryStorageProvider, createStorageProvider, createDOMBindingPlugin, } from "@traffical/js-client";
57
+ export { initTraffical, getTrafficalContext, hasTrafficalContext, } from "./context.svelte.js";
58
+ export { useTraffical, useTrafficalTrack, useTrafficalReward, useTrafficalClient, useTrafficalPlugin, } from "./hooks.svelte.js";
59
+ export { default as TrafficalProvider } from "./TrafficalProvider.svelte";
60
+ export type { TrafficalProviderConfig, TrafficalContextValue, UseTrafficalOptions, UseTrafficalResult, BoundTrackOptions, TrackEventOptions, BoundTrackRewardOptions, TrackRewardOptions, LoadTrafficalBundleOptions, LoadTrafficalBundleResult, ConfigBundle, Context, DecisionResult, ParameterValue, TrafficalClient as TrafficalClientType, TrafficalPlugin, } from "./types.js";
61
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAMH,OAAO,EAEL,iBAAiB,EACjB,MAAM,EACN,iBAAiB,EACjB,kBAAkB,EAElB,KAAK,EACL,aAAa,EACb,eAAe,EAEf,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EAEL,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EAEzB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EAErB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAM1E,YAAY,EAEV,uBAAuB,EACvB,qBAAqB,EAErB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EAEjB,uBAAuB,EACvB,kBAAkB,EAElB,0BAA0B,EAC1B,yBAAyB,EAEzB,YAAY,EACZ,OAAO,EACP,cAAc,EACd,cAAc,EACd,eAAe,IAAI,mBAAmB,EACtC,eAAe,GAChB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @traffical/svelte
3
+ *
4
+ * Traffical SDK for Svelte 5 applications.
5
+ * Provides Provider component and hooks for parameter resolution and decision tracking.
6
+ *
7
+ * Features:
8
+ * - Full SSR/hydration support for SvelteKit
9
+ * - Svelte 5 runes for reactive, fine-grained updates
10
+ * - Browser-optimized with sendBeacon, localStorage persistence
11
+ * - Automatic stable ID for anonymous users
12
+ * - Plugin system support (DecisionTrackingPlugin enabled by default)
13
+ * - Decision and exposure deduplication
14
+ *
15
+ * @example
16
+ * ```svelte
17
+ * <!-- +layout.svelte -->
18
+ * <script>
19
+ * import { TrafficalProvider } from '@traffical/svelte';
20
+ *
21
+ * let { data, children } = $props();
22
+ * </script>
23
+ *
24
+ * <TrafficalProvider
25
+ * config={{
26
+ * orgId: 'org_123',
27
+ * projectId: 'proj_456',
28
+ * env: 'production',
29
+ * apiKey: 'pk_...',
30
+ * initialBundle: data.traffical?.bundle,
31
+ * }}
32
+ * >
33
+ * {@render children()}
34
+ * </TrafficalProvider>
35
+ * ```
36
+ *
37
+ * @example
38
+ * ```svelte
39
+ * <!-- MyComponent.svelte -->
40
+ * <script>
41
+ * import { useTraffical } from '@traffical/svelte';
42
+ *
43
+ * const { params, ready } = useTraffical({
44
+ * defaults: { 'ui.hero.title': 'Welcome' },
45
+ * });
46
+ * </script>
47
+ *
48
+ * {#if ready}
49
+ * <h1>{params['ui.hero.title']}</h1>
50
+ * {:else}
51
+ * <h1>Loading...</h1>
52
+ * {/if}
53
+ * ```
54
+ */
55
+ // =============================================================================
56
+ // Re-export from @traffical/core
57
+ // =============================================================================
58
+ export {
59
+ // Resolution functions
60
+ resolveParameters, decide, evaluateCondition, evaluateConditions,
61
+ // Hashing utilities
62
+ fnv1a, computeBucket, isInBucketRange,
63
+ // ID generation
64
+ generateEventId, generateDecisionId, generateExposureId, generateRewardId, } from "@traffical/core";
65
+ // =============================================================================
66
+ // Re-export from @traffical/js-client
67
+ // =============================================================================
68
+ export {
69
+ // Client
70
+ TrafficalClient, createTrafficalClient, createTrafficalClientSync,
71
+ // Storage providers
72
+ LocalStorageProvider, MemoryStorageProvider, createStorageProvider,
73
+ // Plugins
74
+ createDOMBindingPlugin, } from "@traffical/js-client";
75
+ // =============================================================================
76
+ // Svelte-specific exports
77
+ // =============================================================================
78
+ // Context
79
+ export { initTraffical, getTrafficalContext, hasTrafficalContext, } from "./context.svelte.js";
80
+ // Hooks
81
+ export { useTraffical, useTrafficalTrack, useTrafficalReward, useTrafficalClient, useTrafficalPlugin, } from "./hooks.svelte.js";
82
+ // Provider component
83
+ export { default as TrafficalProvider } from "./TrafficalProvider.svelte";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @traffical/svelte - Unit Tests
3
+ *
4
+ * Tests for the Svelte 5 SDK hooks and utilities.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}