flagmint-js-sdk 1.2.3 → 1.2.5

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 CHANGED
@@ -1,6 +1,17 @@
1
1
  # Flagmint JavaScript SDK
2
2
 
3
- This SDK provides a framework-agnostic client for evaluating feature flags, with pluggable caching (sync or async) and transport strategies (WebSocket or long-polling).
3
+ **Version: 1.2.5**
4
+
5
+ This SDK provides a framework-agnostic client for evaluating feature flags, with pluggable caching (sync or async) and transport strategies (WebSocket or long-polling). It's designed for both browser and server-side Node.js environments.
6
+
7
+ ## ✨ Key Features
8
+
9
+ - 🎯 **Framework-Agnostic**: Works with React, Vue, vanilla JS, Node.js, and more
10
+ - 🔄 **Flexible Transport**: WebSocket for real-time updates or long-polling fallback
11
+ - 💾 **Pluggable Caching**: Use built-in sync cache, async cache (Redis/filesystem), or custom implementations
12
+ - 🚀 **Server & Browser Support**: Compatible with browser environments, Node.js, React Native
13
+ - 🔒 **Type-Safe**: Full TypeScript support with comprehensive type definitions
14
+ - ⚡ **Zero-Config Defaults**: Works out of the box with sensible defaults
4
15
 
5
16
  ## 📦 Installation
6
17
 
@@ -10,7 +21,33 @@ npm install flagmint-sdk
10
21
  yarn add flagmint-sdk
11
22
  ```
12
23
 
13
- ## 🛠️ FlagClientOptions
24
+ ## Quick Start
25
+
26
+ ```ts
27
+ import { FlagClient } from 'flagmint-sdk';
28
+
29
+ // Create a client instance
30
+ const client = new FlagClient({
31
+ apiKey: 'ff_your_api_key_here',
32
+ context: {
33
+ user_id: 'user123',
34
+ country: 'US',
35
+ isPremium: true
36
+ }
37
+ });
38
+
39
+ // Wait for initial connection
40
+ await client.ready();
41
+
42
+ // Get flag values
43
+ const showBanner = client.getFlag('show_banner', false);
44
+ const featureVersion = client.getFlag('feature_version', 'v1');
45
+
46
+ // Update context and re-evaluate
47
+ client.updateContext({ user_id: 'user456' });
48
+ ```
49
+
50
+ ## �🛠️ FlagClientOptions
14
51
 
15
52
  | Option | Type | Default | Description |
16
53
  | --------------------- | ----------------------------------------- | ------------------ | --------------------------------------------------------------------- |
@@ -73,6 +110,14 @@ const client = new FlagClient({
73
110
  });
74
111
  ```
75
112
 
113
+ ### Transport Performance
114
+
115
+ | Mode | Latency | Bandwidth | Best For |
116
+ |------|---------|-----------|----------|
117
+ | WebSocket | Lowest (real-time) | Efficient | Real-time dashboards, live updates |
118
+ | Long-Polling | Medium | Higher | Simpler setup, less overhead on server |
119
+ | Auto | Lowest to Medium | Varies | Most applications (recommended) |
120
+
76
121
  ## ⚙️ Evaluation Helpers
77
122
 
78
123
  The SDK includes utilities to evaluate flag targeting rules and rollouts:
@@ -107,30 +152,288 @@ const rolloutValue = evaluateRollout(rolloutConfig, userContext);
107
152
 
108
153
  These helpers underpin reliable, deterministic assignment of users to flag variants.
109
154
 
110
- ## 🚀 Quick Start
155
+ ### `isInSegment(context, segment)`
111
156
 
112
157
  ```ts
158
+ import { isInSegment } from 'flagmint-sdk/core/evaluation';
159
+
160
+ const inBetaSegment = isInSegment(userContext, betaSegment);
161
+ ```
162
+
163
+ Evaluates whether a user context matches a segment's criteria.
164
+
165
+ ## 📖 Framework Integration Examples
166
+
167
+ ### React
168
+
169
+ ```tsx
170
+ import { useEffect, useState } from 'react';
113
171
  import { FlagClient } from 'flagmint-sdk';
114
172
 
115
173
  const client = new FlagClient({
116
- apiKey: 'ff_XXXX',
117
- context: { user_id: 'user123', country: 'US' }
174
+ apiKey: 'ff_...',
175
+ context: { userId: 'user123' }
118
176
  });
119
177
 
120
- // wait until connected
121
- await client.ready();
178
+ export function App() {
179
+ const [flags, setFlags] = useState({});
180
+
181
+ useEffect(() => {
182
+ client.ready().then(() => {
183
+ setFlags({
184
+ showBeta: client.getFlag('show_beta', false),
185
+ theme: client.getFlag('theme', 'light')
186
+ });
187
+ });
188
+ }, []);
189
+
190
+ return (
191
+ <div className={`theme-${flags.theme}`}>
192
+ {flags.showBeta && <BetaFeature />}
193
+ </div>
194
+ );
195
+ }
196
+ ```
122
197
 
123
- // get flag
124
- const showBanner = client.getFlag('show_banner', false);
198
+ ### Node.js / Express
199
+
200
+ ```ts
201
+ import { FlagClient } from 'flagmint-sdk';
202
+ import * as asyncCache from 'flagmint-sdk/core/cacheHelper.async';
203
+
204
+ const client = new FlagClient({
205
+ apiKey: 'ff_...',
206
+ cacheAdapter: {
207
+ loadFlags: asyncCache.loadCachedFlags,
208
+ saveFlags: asyncCache.saveCachedFlags,
209
+ loadContext: asyncCache.loadCachedContext,
210
+ saveContext: asyncCache.saveCachedContext
211
+ }
212
+ });
213
+
214
+ app.get('/api/feature', async (req, res) => {
215
+ const userContext = { userId: req.user.id, plan: req.user.plan };
216
+ const isEnabled = client.getFlag('new_api', false, userContext);
217
+
218
+ res.json({ enabled: isEnabled });
219
+ });
125
220
  ```
126
221
 
222
+ ## 🔄 Context Management
223
+
224
+ ### Updating Context
225
+
226
+ ```ts
227
+ // Initial context
228
+ const client = new FlagClient({
229
+ apiKey: '...',
230
+ context: { user_id: 'user123' }
231
+ });
232
+
233
+ // Update context later
234
+ client.updateContext({
235
+ user_id: 'user123',
236
+ plan: 'premium',
237
+ country: 'CA'
238
+ });
239
+ ```
240
+
241
+ ### Persisting Context
242
+
243
+ ```ts
244
+ const client = new FlagClient({
245
+ apiKey: '...',
246
+ persistContext: true, // Saves to localStorage/AsyncStorage
247
+ context: { user_id: 'user123' }
248
+ });
249
+ ```
250
+
251
+ ## 🔌 Deferred Initialization
252
+
253
+ For scenarios where you need to set up the client before context is available:
254
+
255
+ ```ts
256
+ const client = new FlagClient({
257
+ apiKey: '...',
258
+ deferInitialization: true
259
+ });
260
+
261
+ // Later, when context is ready:
262
+ client.updateContext({ user_id: 'user123' });
263
+ await client.init();
264
+ ```
265
+
266
+ ## 🌍 Advanced Usage
267
+
268
+ ### Error Handling
269
+
270
+ ```ts
271
+ const client = new FlagClient({
272
+ apiKey: '...',
273
+ onError: (error) => {
274
+ console.error('Flag client error:', error);
275
+ // Report to monitoring service
276
+ sentry.captureException(error);
277
+ }
278
+ });
279
+ ```
280
+
281
+ ### Preview Mode
282
+
283
+ For testing or preview environments where you want to bypass remote flag fetching:
284
+
285
+ ```ts
286
+ const client = new FlagClient({
287
+ apiKey: '...',
288
+ previewMode: true,
289
+ rawFlags: {
290
+ new_checkout: true,
291
+ discount_percent: 20,
292
+ ui_variant: 'experimental'
293
+ }
294
+ });
295
+
296
+ // All getFlag calls will use rawFlags
297
+ const checkout = client.getFlag('new_checkout', false); // true
298
+ ```
299
+
300
+ ### Custom Cache Implementations
301
+
302
+ ```ts
303
+ import { FlagClient } from 'flagmint-sdk';
304
+ import redis from 'redis';
305
+
306
+ const redisClient = redis.createClient();
307
+
308
+ const client = new FlagClient({
309
+ apiKey: '...',
310
+ cacheAdapter: {
311
+ loadFlags: async (apiKey) => {
312
+ const cached = await redisClient.get(`flags:${apiKey}`);
313
+ return cached ? JSON.parse(cached) : null;
314
+ },
315
+ saveFlags: async (apiKey, flags) => {
316
+ await redisClient.setex(
317
+ `flags:${apiKey}`,
318
+ 600, // 10 min TTL
319
+ JSON.stringify(flags)
320
+ );
321
+ },
322
+ loadContext: async (apiKey) => {
323
+ const cached = await redisClient.get(`context:${apiKey}`);
324
+ return cached ? JSON.parse(cached) : null;
325
+ },
326
+ saveContext: async (apiKey, context) => {
327
+ await redisClient.setex(
328
+ `context:${apiKey}`,
329
+ 3600, // 1 hour TTL
330
+ JSON.stringify(context)
331
+ );
332
+ }
333
+ }
334
+ });
335
+ ```
336
+
337
+ ## 📋 API Reference
338
+
339
+ ### `FlagClient`
340
+
341
+ **Methods:**
342
+ - `ready(): Promise<void>` - Wait for initial connection
343
+ - `getFlag<T>(key: string, defaultValue: T, context?: Record<string, any>): T` - Get flag value
344
+ - `updateContext(context: Record<string, any>): void` - Update evaluation context
345
+ - `init(): Promise<void>` - Initialize client (if deferred)
346
+ - `disconnect(): void` - Close transport connection
347
+
348
+ **Events:**
349
+ - `flagsUpdated` - Fired when flags change
350
+ - `contextUpdated` - Fired when context changes
351
+ - `connected` - Fired when transport connects
352
+ - `disconnected` - Fired when transport disconnects
353
+
354
+ ### Cache Adapter Interface
355
+
356
+ ```ts
357
+ interface CacheAdapter {
358
+ loadFlags(apiKey: string): Promise<Record<string, any>> | Record<string, any>;
359
+ saveFlags(apiKey: string, flags: Record<string, any>): Promise<void> | void;
360
+ loadContext(apiKey: string): Promise<Record<string, any> | null> | Record<string, any> | null;
361
+ saveContext(apiKey: string, context: Record<string, any>): Promise<void> | void;
362
+ }
363
+ ```
364
+
365
+ ## 🛠️ Development & Contributing
366
+
367
+ ### Build
368
+
369
+ ```bash
370
+ npm run build
371
+ ```
372
+
373
+ ### Test
374
+
375
+ ```bash
376
+ npm test
377
+ ```
378
+
379
+ ### Project Structure
380
+
381
+ ```
382
+ sdk/
383
+ ├── core/
384
+ │ ├── client.ts # Main FlagClient
385
+ │ ├── types.ts # Type definitions
386
+ │ ├── evaluation/ # Flag evaluation logic
387
+ │ ├── helpers/ # Cache helpers (sync & async)
388
+ │ └── transports/ # Transport implementations
389
+ ```
390
+
391
+ ## 🐛 Troubleshooting
392
+
393
+ ### Client not connecting
394
+
395
+ - Verify your API key is correct
396
+ - Check network connectivity
397
+ - Review browser console for errors
398
+ - Ensure CORS is properly configured if using from browser
399
+
400
+ ### Flags not updating
401
+
402
+ - Confirm `enableOfflineCache: false` or cache is working correctly
403
+ - Check transport mode (WebSocket vs long-polling)
404
+ - Verify context is properly set with `updateContext()`
405
+
406
+ ### Performance issues
407
+
408
+ - Consider using long-polling instead of WebSocket for high-traffic scenarios
409
+ - Implement proper cache TTLs
410
+ - Monitor transport connection status
411
+
412
+ ## 📞 Support & Resources
413
+
414
+ - **Documentation**: See [Flagmint Docs](https://docs.flagmint.io)
415
+ - **Issues**: Report on [GitHub](https://github.com/flagmint/js-sdk/issues)
416
+ - **Email**: support@flagmint.io
417
+
418
+ ## 🚀 Changelog
419
+
420
+ ### v1.2.5
421
+ - Enhanced async cache helper for better server-side support
422
+ - Improved WebSocket connection stability
423
+ - Better error reporting and handling
424
+ - Added support for context persistence
425
+ - Performance optimizations for large flag sets
426
+
127
427
  ## 📖 References
128
428
 
129
- * Core client: `@/core/client.ts`
130
- * Cache helpers: `@/core/helpers/cacheHelper.ts`, `asyncCacheHelper.ts`
131
- * Transports: `WebsocketTransport`, `LongPollingTransport`
132
- * Evaluation: `evaluateFlagValue`, `evaluateRollout`, `rolloutUtils`
429
+ * Core client: [sdk/core/client.ts](sdk/core/client.ts)
430
+ * Type definitions: [sdk/core/types.ts](sdk/core/types.ts)
431
+ * Cache helpers: [sdk/core/helpers/cacheHelper.ts](sdk/core/helpers/cacheHelper.ts), [cacheHelper.async.ts](sdk/core/helpers/cacheHelper.async.ts)
432
+ * Transports: [WebsocketTransport](sdk/core/transports/WebsocketTransport.ts), [LongPollingTransport](sdk/core/transports/LongPollingTransport.ts)
433
+ * Evaluation: [evaluateFlagValue](sdk/core/evaluation/evaluateFlagValue.ts), [evaluateRollout](sdk/core/evaluation/evaluateRollout.ts), [rolloutUtils](sdk/core/evaluation/rolloutUtils.ts)
133
434
 
134
435
  ---
135
436
 
136
- *MIT © Flagmint Team*
437
+ **License**: MIT © Flagmint Team
438
+
439
+ **Maintained with ❤️ by the Flagmint Team**