@fluxcontrolsdk/js-sdk 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FluxControl Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,260 @@
1
+ # FluxControl JavaScript SDK
2
+
3
+ High-performance JavaScript/TypeScript SDK for feature flags and experimentation in web applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @fluxcontrol/js-sdk
9
+ # or
10
+ yarn add @fluxcontrol/js-sdk
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ### Vanilla JavaScript/TypeScript
16
+
17
+ ```typescript
18
+ import { FluxClient } from '@fluxcontrol/js-sdk';
19
+
20
+ // Initialize client
21
+ const client = new FluxClient('your-sdk-key', {
22
+ edgeUrl: 'https://edge.fluxcontrol.io',
23
+ enableAnalytics: true
24
+ });
25
+
26
+ // Create context
27
+ const context = {
28
+ userId: 'user-123',
29
+ attributes: {
30
+ plan: 'premium',
31
+ country: 'US'
32
+ }
33
+ };
34
+
35
+ // Evaluate boolean flag
36
+ const enabled = await client.boolVariation('new-feature', context, false);
37
+ if (enabled) {
38
+ // New feature code
39
+ }
40
+
41
+ // Evaluate string flag
42
+ const theme = await client.stringVariation('ui-theme', context, 'light');
43
+
44
+ // Track custom event
45
+ await client.track('button_clicked', context, {
46
+ buttonId: 'checkout',
47
+ page: 'cart'
48
+ });
49
+
50
+ // Cleanup
51
+ client.close();
52
+ ```
53
+
54
+ ### React
55
+
56
+ ```tsx
57
+ import { FluxProvider, useFeature, useTrack } from '@fluxcontrol/js-sdk';
58
+
59
+ // Wrap your app
60
+ function App() {
61
+ return (
62
+ <FluxProvider
63
+ sdkKey="your-sdk-key"
64
+ context={{ userId: 'user-123' }}
65
+ >
66
+ <MyComponent />
67
+ </FluxProvider>
68
+ );
69
+ }
70
+
71
+ // Use in components
72
+ function MyComponent() {
73
+ // Evaluate flag
74
+ const checkoutFlow = useFeature('checkout-flow', 'standard');
75
+
76
+ // Track events
77
+ const track = useTrack();
78
+
79
+ const handleClick = () => {
80
+ track('button_clicked', { button: 'checkout' });
81
+ };
82
+
83
+ if (checkoutFlow === 'one-click') {
84
+ return <OneClickCheckout onClick={handleClick} />;
85
+ }
86
+
87
+ return <StandardCheckout onClick={handleClick} />;
88
+ }
89
+ ```
90
+
91
+ ## API Reference
92
+
93
+ ### FluxClient
94
+
95
+ Main client for evaluating feature flags.
96
+
97
+ #### Constructor
98
+
99
+ ```typescript
100
+ new FluxClient(sdkKey: string, config?: Config)
101
+ ```
102
+
103
+ **Config Options:**
104
+ - `edgeUrl` - Edge evaluator URL (default: 'https://edge.fluxcontrol.io')
105
+ - `pollingInterval` - Cache refresh interval in ms (default: 60000)
106
+ - `enableAnalytics` - Enable event tracking (default: true)
107
+ - `localStorage` - Use localStorage for caching (default: true)
108
+
109
+ #### Methods
110
+
111
+ **`boolVariation(flagKey, context, defaultValue)`**
112
+ Evaluate a boolean flag.
113
+
114
+ **`stringVariation(flagKey, context, defaultValue)`**
115
+ Evaluate a string flag.
116
+
117
+ **`numberVariation(flagKey, context, defaultValue)`**
118
+ Evaluate a number flag.
119
+
120
+ **`jsonVariation<T>(flagKey, context, defaultValue)`**
121
+ Evaluate a JSON flag with type safety.
122
+
123
+ **`track(eventName, context, properties?, value?)`**
124
+ Track a custom event.
125
+
126
+ **`close()`**
127
+ Cleanup and stop polling.
128
+
129
+ ### React Hooks
130
+
131
+ #### `FluxProvider`
132
+
133
+ Provider component to wrap your app.
134
+
135
+ ```tsx
136
+ <FluxProvider
137
+ sdkKey="your-key"
138
+ config={{ edgeUrl: 'https://...' }}
139
+ context={{ userId: 'user-123' }}
140
+ >
141
+ {children}
142
+ </FluxProvider>
143
+ ```
144
+
145
+ #### `useFeature(flagKey, defaultValue, contextOverride?)`
146
+
147
+ Hook to evaluate a feature flag.
148
+
149
+ ```tsx
150
+ const theme = useFeature('ui-theme', 'light');
151
+ const enabled = useFeature('new-feature', false);
152
+ const config = useFeature('feature-config', { timeout: 5000 });
153
+ ```
154
+
155
+ #### `useFluxClient()`
156
+
157
+ Get the client instance for advanced usage.
158
+
159
+ ```tsx
160
+ const client = useFluxClient();
161
+ await client.track('custom_event', context);
162
+ ```
163
+
164
+ #### `useTrack()`
165
+
166
+ Hook to track custom events.
167
+
168
+ ```tsx
169
+ const track = useTrack();
170
+ track('purchase', { productId: '123' }, 99.99);
171
+ ```
172
+
173
+ ## Context
174
+
175
+ The context object provides user attributes for targeting:
176
+
177
+ ```typescript
178
+ interface Context {
179
+ userId?: string;
180
+ sessionId?: string;
181
+ attributes?: Record<string, any>;
182
+ }
183
+ ```
184
+
185
+ **Standard attributes:**
186
+ - `userId` - Unique user identifier
187
+ - `sessionId` - Session identifier
188
+ - `attributes` - Custom attributes (plan, country, etc.)
189
+
190
+ ## Features
191
+
192
+ - ✅ **TypeScript Support** - Full type definitions
193
+ - ✅ **React Integration** - Hooks and Provider
194
+ - ✅ **Local Caching** - localStorage for offline support
195
+ - ✅ **Auto-refresh** - Polling for flag updates
196
+ - ✅ **Event Tracking** - Automatic exposure tracking
197
+ - ✅ **Edge Evaluation** - Secure server-side evaluation
198
+ - ✅ **SSR Compatible** - Works with Next.js and other frameworks
199
+
200
+ ## Advanced Usage
201
+
202
+ ### Custom Context per Evaluation
203
+
204
+ ```tsx
205
+ const enabled = useFeature('feature', false, {
206
+ attributes: { experiment: 'variant-a' }
207
+ });
208
+ ```
209
+
210
+ ### Conditional Rendering
211
+
212
+ ```tsx
213
+ function FeatureGate({ flagKey, children }) {
214
+ const enabled = useFeature(flagKey, false);
215
+ return enabled ? <>{children}</> : null;
216
+ }
217
+
218
+ <FeatureGate flagKey="new-ui">
219
+ <NewUI />
220
+ </FeatureGate>
221
+ ```
222
+
223
+ ### A/B Testing
224
+
225
+ ```tsx
226
+ function Experiment() {
227
+ const variant = useFeature('homepage-hero', 'control');
228
+ const track = useTrack();
229
+
230
+ useEffect(() => {
231
+ // Track impression
232
+ track('hero_viewed', { variant });
233
+ }, [variant]);
234
+
235
+ const handleClick = () => {
236
+ track('hero_clicked', { variant });
237
+ };
238
+
239
+ switch (variant) {
240
+ case 'variant-a':
241
+ return <HeroA onClick={handleClick} />;
242
+ case 'variant-b':
243
+ return <HeroB onClick={handleClick} />;
244
+ default:
245
+ return <HeroControl onClick={handleClick} />;
246
+ }
247
+ }
248
+ ```
249
+
250
+ ## Browser Support
251
+
252
+ - Chrome/Edge: Latest 2 versions
253
+ - Firefox: Latest 2 versions
254
+ - Safari: Latest 2 versions
255
+ - iOS Safari: iOS 12+
256
+ - Android Chrome: Latest 2 versions
257
+
258
+ ## License
259
+
260
+ Internal use only.
@@ -0,0 +1,45 @@
1
+ import { Context, Config, EvaluationResult, Ruleset } from './types';
2
+ export { Context, Config, EvaluationResult, Ruleset };
3
+ /**
4
+ * FluxControl JavaScript SDK (Thick Client)
5
+ *
6
+ * Downloads rulesets and evaluates flags locally.
7
+ */
8
+ export declare class FluxClient {
9
+ private sdkKey;
10
+ private config;
11
+ private evaluator;
12
+ private ruleset;
13
+ private pollingInterval;
14
+ constructor(sdkKey: string, config?: Config);
15
+ /**
16
+ * Initialize the SDK (fetch ruleset).
17
+ */
18
+ init(): Promise<void>;
19
+ /**
20
+ * Fetch ruleset from API.
21
+ */
22
+ fetchRuleset(): Promise<void>;
23
+ /**
24
+ * Evaluate a boolean flag.
25
+ * Note: Sync evaluation now possible if ruleset is loaded!
26
+ * But we keep async signature if needed or make it sync?
27
+ * Legacy SDK was async. Let's make it sync but helpful.
28
+ * Actually, if init() is async, we can't guarantee ruleset is there immediately.
29
+ */
30
+ boolVariation(flagKey: string, context: Context, defaultValue: boolean): boolean;
31
+ stringVariation(flagKey: string, context: Context, defaultValue: string): string;
32
+ numberVariation(flagKey: string, context: Context, defaultValue: number): number;
33
+ jsonVariation<T = any>(flagKey: string, context: Context, defaultValue: T): T;
34
+ isEnabled(flagKey: string, contextOrId: Context | string, defaultValue?: boolean): boolean;
35
+ /**
36
+ * Internal evaluation.
37
+ */
38
+ private evaluate;
39
+ /**
40
+ * Track a custom event.
41
+ */
42
+ track(eventName: string, context: Context, properties?: Record<string, any>, value?: number): Promise<void>;
43
+ close(): void;
44
+ }
45
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC;AAEtD;;;;GAIG;AACH,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,eAAe,CAAM;gBAEjB,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,MAAW;IAe/C;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IA+BnC;;;;;;OAMG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO;IAKhF,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAKhF,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAKhF,aAAa,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC;IAI7E,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,MAAM,EAAE,YAAY,GAAE,OAAe,GAAG,OAAO;IAMjG;;OAEG;IACH,OAAO,CAAC,QAAQ;IAahB;;OAEG;IACG,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBjH,KAAK;CAGR"}
@@ -0,0 +1,40 @@
1
+ import { Context, Ruleset, EvaluationResult } from './types';
2
+ /**
3
+ * Evaluates feature flags against targeting rules.
4
+ */
5
+ export declare class Evaluator {
6
+ /**
7
+ * Evaluate a flag.
8
+ */
9
+ evaluate(flagKey: string, context: Context, ruleset: Ruleset, defaultValue: any): EvaluationResult;
10
+ /**
11
+ * Evaluate all conditions in a rule.
12
+ */
13
+ private evaluateConditions;
14
+ /**
15
+ * Evaluate a single condition.
16
+ */
17
+ private evaluateCondition;
18
+ /**
19
+ * Serve a specific variation.
20
+ */
21
+ private serveVariation;
22
+ /**
23
+ * Serve variation based on percentage rollout.
24
+ */
25
+ private servePercentageRollout;
26
+ /**
27
+ * Serve variation based on boolean rollout (simplified format: {on: percentage}).
28
+ * Used for boolean flags where 'on' represents the percentage for 'true'.
29
+ */
30
+ private serveBooleanRollout;
31
+ /**
32
+ * Get consistent bucket (0-9999) for user using MD5 hash.
33
+ */
34
+ /**
35
+ * Get consistent bucket (0-9999) for user using simple hash (DJB2).
36
+ * Format: flagKey:userId (matches Python SDK for cross-SDK consistency)
37
+ */
38
+ private getBucket;
39
+ }
40
+ //# sourceMappingURL=evaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../src/evaluator.ts"],"names":[],"mappings":"AACA,OAAO,EACH,OAAO,EACP,OAAO,EAIP,gBAAgB,EAGnB,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,qBAAa,SAAS;IAClB;;OAEG;IACH,QAAQ,CACJ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,GAAG,GAClB,gBAAgB;IA0CnB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAc1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAqDzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAsBtB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IA8B9B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IA2C3B;;OAEG;IACH;;;OAGG;IACH,OAAO,CAAC,SAAS;CAQpB"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * FluxControl JavaScript SDK
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export * from './types';
7
+ export * from './client';
8
+ export * from './react';
9
+ import { FluxClient } from './client';
10
+ export default FluxClient;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,eAAe,UAAU,CAAC"}