@traffical/react 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1011 -0
- package/dist/context.d.ts +90 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +23 -0
- package/dist/context.js.map +1 -0
- package/dist/hooks.d.ts +273 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +424 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/provider.d.ts +48 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +144 -0
- package/dist/provider.js.map +1 -0
- package/package.json +55 -0
- package/src/context.ts +144 -0
- package/src/hooks.ts +656 -0
- package/src/index.ts +93 -0
- package/src/provider.tsx +194 -0
package/dist/provider.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Traffical React Provider
|
|
4
|
+
*
|
|
5
|
+
* Initializes the Traffical client (browser-optimized) and provides it to child components.
|
|
6
|
+
* Supports plugins, automatic stable ID, and decision tracking out of the box.
|
|
7
|
+
*/
|
|
8
|
+
import { useEffect, useState, useCallback, useMemo, useRef, } from "react";
|
|
9
|
+
import { createTrafficalClientSync, } from "@traffical/js-client";
|
|
10
|
+
import { TrafficalContext, } from "./context.js";
|
|
11
|
+
/**
|
|
12
|
+
* TrafficalProvider - initializes and provides the Traffical client to React components.
|
|
13
|
+
*
|
|
14
|
+
* Features:
|
|
15
|
+
* - Browser-optimized with sendBeacon, localStorage persistence
|
|
16
|
+
* - Automatic stable ID for anonymous users (unless unitKeyFn provided)
|
|
17
|
+
* - Plugin system support (DecisionTrackingPlugin enabled by default)
|
|
18
|
+
* - Decision and exposure deduplication
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* <TrafficalProvider
|
|
23
|
+
* config={{
|
|
24
|
+
* orgId: "org_123",
|
|
25
|
+
* projectId: "proj_456",
|
|
26
|
+
* env: "production",
|
|
27
|
+
* apiKey: "pk_...",
|
|
28
|
+
* // Optional: provide unitKeyFn for logged-in users
|
|
29
|
+
* unitKeyFn: () => getUserId(),
|
|
30
|
+
* // Optional: add context
|
|
31
|
+
* contextFn: () => ({ locale: "en-US" }),
|
|
32
|
+
* // Optional: add custom plugins
|
|
33
|
+
* plugins: [createDOMBindingPlugin()],
|
|
34
|
+
* }}
|
|
35
|
+
* >
|
|
36
|
+
* <App />
|
|
37
|
+
* </TrafficalProvider>
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function TrafficalProvider({ config, children, }) {
|
|
41
|
+
const [client, setClient] = useState(null);
|
|
42
|
+
const [ready, setReady] = useState(false);
|
|
43
|
+
const [error, setError] = useState(null);
|
|
44
|
+
// Keep a ref to the client for cleanup
|
|
45
|
+
const clientRef = useRef(null);
|
|
46
|
+
// Memoize the unit key function
|
|
47
|
+
// If no unitKeyFn is provided, use the client's stable ID
|
|
48
|
+
const getUnitKey = useCallback(() => {
|
|
49
|
+
if (config.unitKeyFn) {
|
|
50
|
+
return config.unitKeyFn();
|
|
51
|
+
}
|
|
52
|
+
// Fall back to the client's auto-generated stable ID
|
|
53
|
+
return clientRef.current?.getStableId() ?? "";
|
|
54
|
+
}, [config.unitKeyFn]);
|
|
55
|
+
const getContext = useCallback(() => {
|
|
56
|
+
const unitKey = getUnitKey();
|
|
57
|
+
const additionalContext = config.contextFn?.() ?? {};
|
|
58
|
+
// The unit key field name comes from the bundle's hashing config
|
|
59
|
+
// For now, we use common conventions and let the SDK handle it
|
|
60
|
+
return {
|
|
61
|
+
...additionalContext,
|
|
62
|
+
// Include common unit key field names
|
|
63
|
+
userId: unitKey,
|
|
64
|
+
deviceId: unitKey,
|
|
65
|
+
anonymousId: unitKey,
|
|
66
|
+
};
|
|
67
|
+
}, [getUnitKey, config.contextFn]);
|
|
68
|
+
// Initialize client on mount
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
let mounted = true;
|
|
71
|
+
const initClient = async () => {
|
|
72
|
+
try {
|
|
73
|
+
// Create client synchronously so it's available immediately
|
|
74
|
+
const newClient = createTrafficalClientSync({
|
|
75
|
+
orgId: config.orgId,
|
|
76
|
+
projectId: config.projectId,
|
|
77
|
+
env: config.env,
|
|
78
|
+
apiKey: config.apiKey,
|
|
79
|
+
baseUrl: config.baseUrl,
|
|
80
|
+
localConfig: config.localConfig,
|
|
81
|
+
refreshIntervalMs: config.refreshIntervalMs,
|
|
82
|
+
trackDecisions: config.trackDecisions,
|
|
83
|
+
decisionDeduplicationTtlMs: config.decisionDeduplicationTtlMs,
|
|
84
|
+
exposureSessionTtlMs: config.exposureSessionTtlMs,
|
|
85
|
+
eventBatchSize: config.eventBatchSize,
|
|
86
|
+
eventFlushIntervalMs: config.eventFlushIntervalMs,
|
|
87
|
+
plugins: config.plugins,
|
|
88
|
+
});
|
|
89
|
+
clientRef.current = newClient;
|
|
90
|
+
if (mounted) {
|
|
91
|
+
setClient(newClient);
|
|
92
|
+
// If localConfig was provided, mark as ready immediately
|
|
93
|
+
if (config.localConfig) {
|
|
94
|
+
setReady(true);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Initialize asynchronously (fetches/refreshes config bundle)
|
|
98
|
+
await newClient.initialize();
|
|
99
|
+
if (mounted) {
|
|
100
|
+
setReady(true);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
if (mounted) {
|
|
105
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
106
|
+
// Still mark as ready - we'll use defaults
|
|
107
|
+
setReady(true);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
initClient();
|
|
112
|
+
return () => {
|
|
113
|
+
mounted = false;
|
|
114
|
+
clientRef.current?.destroy();
|
|
115
|
+
clientRef.current = null;
|
|
116
|
+
};
|
|
117
|
+
}, [
|
|
118
|
+
config.orgId,
|
|
119
|
+
config.projectId,
|
|
120
|
+
config.env,
|
|
121
|
+
config.apiKey,
|
|
122
|
+
config.baseUrl,
|
|
123
|
+
config.localConfig,
|
|
124
|
+
config.refreshIntervalMs,
|
|
125
|
+
config.trackDecisions,
|
|
126
|
+
config.decisionDeduplicationTtlMs,
|
|
127
|
+
config.exposureSessionTtlMs,
|
|
128
|
+
config.eventBatchSize,
|
|
129
|
+
config.eventFlushIntervalMs,
|
|
130
|
+
config.plugins,
|
|
131
|
+
]);
|
|
132
|
+
// Memoize context value
|
|
133
|
+
const contextValue = useMemo(() => ({
|
|
134
|
+
client,
|
|
135
|
+
ready,
|
|
136
|
+
error,
|
|
137
|
+
getUnitKey,
|
|
138
|
+
getContext,
|
|
139
|
+
initialParams: config.initialParams,
|
|
140
|
+
localConfig: config.localConfig,
|
|
141
|
+
}), [client, ready, error, getUnitKey, getContext, config.initialParams, config.localConfig]);
|
|
142
|
+
return (_jsx(TrafficalContext.Provider, { value: contextValue, children: children }));
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@traffical/react",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Traffical SDK for React - Provider and hooks for parameter resolution",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.ts",
|
|
7
|
+
"module": "./src/index.ts",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"bun": "./src/index.ts",
|
|
13
|
+
"import": "./src/index.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"src"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"dev": "tsc --watch",
|
|
23
|
+
"test": "bun test",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"release": "bun scripts/release.ts"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@traffical/core": "workspace:^",
|
|
29
|
+
"@traffical/js-client": "workspace:^"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/bun": "latest",
|
|
33
|
+
"@types/react": "^18.2.0",
|
|
34
|
+
"typescript": "^5.3.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"traffical",
|
|
41
|
+
"feature-flags",
|
|
42
|
+
"experimentation",
|
|
43
|
+
"a/b-testing",
|
|
44
|
+
"react",
|
|
45
|
+
"hooks"
|
|
46
|
+
],
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "https://github.com/traffical/js-sdk"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Traffical React Context
|
|
3
|
+
*
|
|
4
|
+
* Provides the Traffical client instance to React components.
|
|
5
|
+
* Uses the browser-optimized JS Client for full feature support.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createContext, useContext } from "react";
|
|
9
|
+
import type { TrafficalClient, TrafficalPlugin } from "@traffical/js-client";
|
|
10
|
+
import type { ConfigBundle, Context } from "@traffical/core";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for the Traffical provider.
|
|
14
|
+
*/
|
|
15
|
+
export interface TrafficalProviderConfig {
|
|
16
|
+
// ==========================================================================
|
|
17
|
+
// Required
|
|
18
|
+
// ==========================================================================
|
|
19
|
+
|
|
20
|
+
/** Organization ID */
|
|
21
|
+
orgId: string;
|
|
22
|
+
/** Project ID */
|
|
23
|
+
projectId: string;
|
|
24
|
+
/** Environment (e.g., "production", "staging") */
|
|
25
|
+
env: string;
|
|
26
|
+
/** API key for authentication */
|
|
27
|
+
apiKey: string;
|
|
28
|
+
|
|
29
|
+
// ==========================================================================
|
|
30
|
+
// Optional - Connection
|
|
31
|
+
// ==========================================================================
|
|
32
|
+
|
|
33
|
+
/** Base URL for the control plane API (optional) */
|
|
34
|
+
baseUrl?: string;
|
|
35
|
+
/** Local config bundle for offline fallback */
|
|
36
|
+
localConfig?: ConfigBundle;
|
|
37
|
+
/** Refresh interval in milliseconds (default: 60000) */
|
|
38
|
+
refreshIntervalMs?: number;
|
|
39
|
+
|
|
40
|
+
// ==========================================================================
|
|
41
|
+
// Optional - Identity
|
|
42
|
+
// ==========================================================================
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Function to get the unit key value.
|
|
46
|
+
* If not provided, the SDK will use automatic stable ID generation.
|
|
47
|
+
*/
|
|
48
|
+
unitKeyFn?: () => string;
|
|
49
|
+
/** Function to get additional context (optional) */
|
|
50
|
+
contextFn?: () => Context;
|
|
51
|
+
|
|
52
|
+
// ==========================================================================
|
|
53
|
+
// Optional - Decision Tracking
|
|
54
|
+
// ==========================================================================
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Whether to automatically track decision events (default: true).
|
|
58
|
+
* When enabled, every call to decide() automatically sends a DecisionEvent
|
|
59
|
+
* to the control plane, enabling intent-to-treat analysis.
|
|
60
|
+
*/
|
|
61
|
+
trackDecisions?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Decision deduplication TTL in milliseconds (default: 1 hour).
|
|
64
|
+
* Same user+assignment combination won't be tracked again within this window.
|
|
65
|
+
*/
|
|
66
|
+
decisionDeduplicationTtlMs?: number;
|
|
67
|
+
|
|
68
|
+
// ==========================================================================
|
|
69
|
+
// Optional - Exposure Tracking
|
|
70
|
+
// ==========================================================================
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Exposure deduplication session TTL in milliseconds (default: 30 minutes).
|
|
74
|
+
* Same user seeing same variant won't trigger multiple exposure events.
|
|
75
|
+
*/
|
|
76
|
+
exposureSessionTtlMs?: number;
|
|
77
|
+
|
|
78
|
+
// ==========================================================================
|
|
79
|
+
// Optional - Plugins
|
|
80
|
+
// ==========================================================================
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Plugins to register with the client.
|
|
84
|
+
* The DecisionTrackingPlugin is included by default unless trackDecisions is false.
|
|
85
|
+
*/
|
|
86
|
+
plugins?: TrafficalPlugin[];
|
|
87
|
+
|
|
88
|
+
// ==========================================================================
|
|
89
|
+
// Optional - Event Batching
|
|
90
|
+
// ==========================================================================
|
|
91
|
+
|
|
92
|
+
/** Max events before auto-flush (default: 10) */
|
|
93
|
+
eventBatchSize?: number;
|
|
94
|
+
/** Auto-flush interval in ms (default: 30000) */
|
|
95
|
+
eventFlushIntervalMs?: number;
|
|
96
|
+
|
|
97
|
+
// ==========================================================================
|
|
98
|
+
// Optional - SSR
|
|
99
|
+
// ==========================================================================
|
|
100
|
+
|
|
101
|
+
/** Initial params from SSR (optional) */
|
|
102
|
+
initialParams?: Record<string, unknown>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Internal context value.
|
|
107
|
+
*/
|
|
108
|
+
export interface TrafficalContextValue {
|
|
109
|
+
/** The Traffical client instance */
|
|
110
|
+
client: TrafficalClient | null;
|
|
111
|
+
/** Whether the client is ready (config loaded) */
|
|
112
|
+
ready: boolean;
|
|
113
|
+
/** Any initialization error */
|
|
114
|
+
error: Error | null;
|
|
115
|
+
/** Function to get the unit key */
|
|
116
|
+
getUnitKey: () => string;
|
|
117
|
+
/** Function to get the full context */
|
|
118
|
+
getContext: () => Context;
|
|
119
|
+
/** Initial params from SSR */
|
|
120
|
+
initialParams?: Record<string, unknown>;
|
|
121
|
+
/** Local config bundle for synchronous resolution during initial render */
|
|
122
|
+
localConfig?: ConfigBundle;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* React context for Traffical.
|
|
127
|
+
*/
|
|
128
|
+
export const TrafficalContext = createContext<TrafficalContextValue | null>(
|
|
129
|
+
null
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Hook to access the Traffical context.
|
|
134
|
+
* Throws if used outside of TrafficalProvider.
|
|
135
|
+
*/
|
|
136
|
+
export function useTrafficalContext(): TrafficalContextValue {
|
|
137
|
+
const context = useContext(TrafficalContext);
|
|
138
|
+
if (!context) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
"useTrafficalContext must be used within a TrafficalProvider"
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
return context;
|
|
144
|
+
}
|