flagmint-js-sdk 1.2.4 → 1.2.6

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,16 +1,53 @@
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
 
7
18
  ```bash
8
- npm install flagmint-sdk
19
+ npm install flagmint-js-sdk
9
20
  # or
10
- yarn add flagmint-sdk
21
+ yarn add flagmint-js-sdk
22
+ ```
23
+
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
+ kind: "multi | user | organisation",
34
+ user: { kind: "user", key: '', email: '' },
35
+ organization: { kind: "organization", key: '', plan: '' }
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' });
11
48
  ```
12
49
 
13
- ## 🛠️ FlagClientOptions
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,292 @@ 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: {
176
+ kind: "multi | user | organisation",
177
+ user: { kind: "user", key: '', email: '' },
178
+ organization: { kind: "organization", key: '', plan: '' }
179
+ }
118
180
  });
119
181
 
120
- // wait until connected
121
- await client.ready();
182
+ export function App() {
183
+ const [flags, setFlags] = useState({});
184
+
185
+ useEffect(() => {
186
+ client.ready().then(() => {
187
+ setFlags({
188
+ showBeta: client.getFlag('show_beta', false),
189
+ theme: client.getFlag('theme', 'light')
190
+ });
191
+ });
192
+ }, []);
193
+
194
+ return (
195
+ <div className={`theme-${flags.theme}`}>
196
+ {flags.showBeta && <BetaFeature />}
197
+ </div>
198
+ );
199
+ }
200
+ ```
122
201
 
123
- // get flag
124
- const showBanner = client.getFlag('show_banner', false);
202
+ ### Node.js / Express
203
+
204
+ ```ts
205
+ import { FlagClient } from 'flagmint-sdk';
206
+ import * as asyncCache from 'flagmint-sdk/core/cacheHelper.async';
207
+
208
+ const client = new FlagClient({
209
+ apiKey: 'ff_...',
210
+ cacheAdapter: {
211
+ loadFlags: asyncCache.loadCachedFlags,
212
+ saveFlags: asyncCache.saveCachedFlags,
213
+ loadContext: asyncCache.loadCachedContext,
214
+ saveContext: asyncCache.saveCachedContext
215
+ }
216
+ });
217
+
218
+ app.get('/api/feature', async (req, res) => {
219
+ const userContext = { userId: req.user.id, plan: req.user.plan };
220
+ const isEnabled = client.getFlag('new_api', false, userContext);
221
+
222
+ res.json({ enabled: isEnabled });
223
+ });
224
+ ```
225
+
226
+ ## 🔄 Context Management
227
+
228
+ ### Updating Context
229
+
230
+ ```ts
231
+ // Initial context
232
+ const client = new FlagClient({
233
+ apiKey: '...',
234
+ context: { user_id: 'user123' }
235
+ });
236
+
237
+ // Update context later
238
+ client.updateContext({
239
+ user_id: 'user123',
240
+ plan: 'premium',
241
+ country: 'CA'
242
+ });
243
+ ```
244
+
245
+ ### Persisting Context
246
+
247
+ ```ts
248
+ const client = new FlagClient({
249
+ apiKey: '...',
250
+ persistContext: true, // Saves to localStorage/AsyncStorage
251
+ context: { user_id: 'user123' }
252
+ });
253
+ ```
254
+
255
+ ## 🔌 Deferred Initialization
256
+
257
+ For scenarios where you need to set up the client before context is available:
258
+
259
+ ```ts
260
+ const client = new FlagClient({
261
+ apiKey: '...',
262
+ deferInitialization: true
263
+ });
264
+
265
+ // Later, when context is ready:
266
+ client.updateContext({ user_id: 'user123' });
267
+ await client.init();
268
+ ```
269
+
270
+ ## 🌍 Advanced Usage
271
+
272
+ ### Error Handling
273
+
274
+ ```ts
275
+ const client = new FlagClient({
276
+ apiKey: '...',
277
+ onError: (error) => {
278
+ console.error('Flag client error:', error);
279
+ // Report to monitoring service
280
+ sentry.captureException(error);
281
+ }
282
+ });
283
+ ```
284
+
285
+ ### Preview Mode
286
+
287
+ For testing or preview environments where you want to bypass remote flag fetching:
288
+
289
+ ```ts
290
+ const client = new FlagClient({
291
+ apiKey: '...',
292
+ previewMode: true,
293
+ rawFlags: {
294
+ new_checkout: true,
295
+ discount_percent: 20,
296
+ ui_variant: 'experimental'
297
+ }
298
+ });
299
+
300
+ // All getFlag calls will use rawFlags
301
+ const checkout = client.getFlag('new_checkout', false); // true
302
+ ```
303
+
304
+ ### Custom Cache Implementations
305
+
306
+ ```ts
307
+ import { FlagClient } from 'flagmint-sdk';
308
+ import redis from 'redis';
309
+
310
+ const redisClient = redis.createClient();
311
+
312
+ const client = new FlagClient({
313
+ apiKey: '...',
314
+ cacheAdapter: {
315
+ loadFlags: async (apiKey) => {
316
+ const cached = await redisClient.get(`flags:${apiKey}`);
317
+ return cached ? JSON.parse(cached) : null;
318
+ },
319
+ saveFlags: async (apiKey, flags) => {
320
+ await redisClient.setex(
321
+ `flags:${apiKey}`,
322
+ 600, // 10 min TTL
323
+ JSON.stringify(flags)
324
+ );
325
+ },
326
+ loadContext: async (apiKey) => {
327
+ const cached = await redisClient.get(`context:${apiKey}`);
328
+ return cached ? JSON.parse(cached) : null;
329
+ },
330
+ saveContext: async (apiKey, context) => {
331
+ await redisClient.setex(
332
+ `context:${apiKey}`,
333
+ 3600, // 1 hour TTL
334
+ JSON.stringify(context)
335
+ );
336
+ }
337
+ }
338
+ });
125
339
  ```
126
340
 
341
+ ## 📋 API Reference
342
+
343
+ ### `FlagClient`
344
+
345
+ **Methods:**
346
+ - `ready(): Promise<void>` - Wait for initial connection
347
+ - `getFlag<T>(key: string, defaultValue: T, context?: Record<string, any>): T` - Get flag value
348
+ - `updateContext(context: Record<string, any>): void` - Update evaluation context
349
+ - `init(): Promise<void>` - Initialize client (if deferred)
350
+ - `disconnect(): void` - Close transport connection
351
+
352
+ **Events:**
353
+ - `flagsUpdated` - Fired when flags change
354
+ - `contextUpdated` - Fired when context changes
355
+ - `connected` - Fired when transport connects
356
+ - `disconnected` - Fired when transport disconnects
357
+
358
+ ### Cache Adapter Interface
359
+
360
+ ```ts
361
+ interface CacheAdapter {
362
+ loadFlags(apiKey: string): Promise<Record<string, any>> | Record<string, any>;
363
+ saveFlags(apiKey: string, flags: Record<string, any>): Promise<void> | void;
364
+ loadContext(apiKey: string): Promise<Record<string, any> | null> | Record<string, any> | null;
365
+ saveContext(apiKey: string, context: Record<string, any>): Promise<void> | void;
366
+ }
367
+ ```
368
+
369
+ ## 🛠️ Development & Contributing
370
+
371
+ ### Build
372
+
373
+ ```bash
374
+ npm run build
375
+ ```
376
+
377
+ ### Test
378
+
379
+ ```bash
380
+ npm test
381
+ ```
382
+
383
+ ### Project Structure
384
+
385
+ ```
386
+ sdk/
387
+ ├── core/
388
+ │ ├── client.ts # Main FlagClient
389
+ │ ├── types.ts # Type definitions
390
+ │ ├── evaluation/ # Flag evaluation logic
391
+ │ ├── helpers/ # Cache helpers (sync & async)
392
+ │ └── transports/ # Transport implementations
393
+ ```
394
+
395
+ ## 🐛 Troubleshooting
396
+
397
+ ### Client not connecting
398
+
399
+ - Verify your API key is correct
400
+ - Check network connectivity
401
+ - Review browser console for errors
402
+ - Ensure CORS is properly configured if using from browser
403
+
404
+ ### Flags not updating
405
+
406
+ - Confirm `enableOfflineCache: false` or cache is working correctly
407
+ - Check transport mode (WebSocket vs long-polling)
408
+ - Verify context is properly set with `updateContext()`
409
+
410
+ ### Performance issues
411
+
412
+ - Consider using long-polling instead of WebSocket for high-traffic scenarios
413
+ - Implement proper cache TTLs
414
+ - Monitor transport connection status
415
+
416
+ ## 📞 Support & Resources
417
+
418
+ - **Documentation**: See [Flagmint Docs](https://docs.flagmint.io)
419
+ - **Issues**: Report on [GitHub](https://github.com/flagmint/js-sdk/issues)
420
+ - **Email**: support@flagmint.io
421
+
422
+ ## 🚀 Changelog
423
+
424
+ ### v1.2.5
425
+ - Enhanced async cache helper for better server-side support
426
+ - Improved WebSocket connection stability
427
+ - Better error reporting and handling
428
+ - Added support for context persistence
429
+ - Performance optimizations for large flag sets
430
+
127
431
  ## 📖 References
128
432
 
129
- * Core client: `@/core/client.ts`
130
- * Cache helpers: `@/core/helpers/cacheHelper.ts`, `asyncCacheHelper.ts`
131
- * Transports: `WebsocketTransport`, `LongPollingTransport`
132
- * Evaluation: `evaluateFlagValue`, `evaluateRollout`, `rolloutUtils`
433
+ * Core client: [sdk/core/client.ts](sdk/core/client.ts)
434
+ * Type definitions: [sdk/core/types.ts](sdk/core/types.ts)
435
+ * Cache helpers: [sdk/core/helpers/cacheHelper.ts](sdk/core/helpers/cacheHelper.ts), [cacheHelper.async.ts](sdk/core/helpers/cacheHelper.async.ts)
436
+ * Transports: [WebsocketTransport](sdk/core/transports/WebsocketTransport.ts), [LongPollingTransport](sdk/core/transports/LongPollingTransport.ts)
437
+ * Evaluation: [evaluateFlagValue](sdk/core/evaluation/evaluateFlagValue.ts), [evaluateRollout](sdk/core/evaluation/evaluateRollout.ts), [rolloutUtils](sdk/core/evaluation/rolloutUtils.ts)
133
438
 
134
439
  ---
135
440
 
136
- *MIT © Flagmint Team*
441
+ **License**: MIT © Flagmint Team
442
+
443
+ **Maintained with ❤️ by the Flagmint Team**