@flagpool/sdk 0.1.0 → 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.
Files changed (2) hide show
  1. package/README.md +182 -116
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Flagpool SDK - TypeScript / JavaScript
1
+ # Flagpool SDK for TypeScript / JavaScript
2
2
 
3
- Official TypeScript/JavaScript SDK for Flagpool feature flags with local evaluation, deterministic rollouts, and encrypted target lists.
3
+ Official TypeScript/JavaScript SDK for [Flagpool](https://flagpool.io) - the modern feature flag platform for teams who want control without complexity.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@flagpool/sdk.svg)](https://www.npmjs.com/package/@flagpool/sdk)
6
6
  [![npm downloads](https://img.shields.io/npm/dm/@flagpool/sdk.svg)](https://www.npmjs.com/package/@flagpool/sdk)
@@ -17,7 +17,7 @@ npm install @flagpool/sdk
17
17
  import { FlagpoolClient } from '@flagpool/sdk';
18
18
 
19
19
  const client = new FlagpoolClient({
20
- apiKey: 'fp_production_xxx',
20
+ apiKey: 'fp_production_xxx', // Get from Flagpool dashboard
21
21
  environment: 'production',
22
22
  context: {
23
23
  userId: 'user-123',
@@ -35,10 +35,12 @@ if (client.isEnabled('new-dashboard')) {
35
35
  }
36
36
 
37
37
  // String flag (A/B test)
38
- const buttonColor = client.getValue('cta-button-color'); // 'blue' | 'green' | 'orange'
38
+ const buttonColor = client.getValue('cta-button-color');
39
+ // 'blue' | 'green' | 'orange'
39
40
 
40
41
  // Number flag
41
- const maxUpload = client.getValue('max-upload-size-mb'); // 10 | 100 | 1000
42
+ const maxUpload = client.getValue('max-upload-size-mb');
43
+ // 10 | 100 | 1000
42
44
 
43
45
  // JSON flag
44
46
  const config = client.getValue('checkout-config');
@@ -53,45 +55,85 @@ client.close();
53
55
  - ✅ **Local evaluation** - No server roundtrip per flag check
54
56
  - ✅ **Deterministic rollouts** - Same user always gets same variation
55
57
  - ✅ **Multiple flag types** - Boolean, string, number, JSON
56
- - ✅ **8 targeting operators** - eq, neq, in, nin, contains, startsWith, inTargetList, notInTargetList
57
- - ✅ **Priority-based rules** - First matching rule wins
58
- - ✅ **Encrypted target lists** - Optional client-side decryption
59
- - ✅ **Real-time updates** - Polling for flag changes
60
- - ✅ **Zero dependencies** - Core SDK has no external dependencies
61
-
62
- ## API Reference
63
-
64
- ### `FlagpoolClient`
58
+ - ✅ **Advanced targeting** - 8 operators including target lists
59
+ - ✅ **Real-time updates** - Automatic polling for flag changes
60
+ - ✅ **Offline support** - Works with cached flags when offline
61
+ - ✅ **Zero dependencies** - Lightweight, no external dependencies
65
62
 
66
- #### Constructor Options
63
+ ## Configuration
67
64
 
68
65
  ```typescript
69
- interface FlagpoolClientOptions {
70
- apiKey: string; // Environment-specific API key
71
- environment: string; // Environment name (required)
72
- context?: Record<string, any>; // User context for targeting
73
- pollingInterval?: number; // Polling interval in ms (default: 30000)
74
- streaming?: boolean; // Enable real-time updates (default: false)
75
- urlOverride?: string; // Override API endpoint
76
- decryptionKey?: string; // Key for client-side target list decryption
77
- clientSideTargetLists?: boolean; // Enable client-side target list evaluation
78
- }
66
+ const client = new FlagpoolClient({
67
+ // Required
68
+ apiKey: 'fp_production_xxx', // Your environment API key
69
+ environment: 'production', // Environment name
70
+
71
+ // Optional
72
+ context: { // User context for targeting
73
+ userId: 'user-123',
74
+ email: 'user@example.com',
75
+ plan: 'pro',
76
+ // Add any attributes for targeting
77
+ },
78
+ pollingInterval: 30000, // Auto-refresh interval (ms), default: 30000
79
+ urlOverride: undefined, // Override API endpoint (for self-hosted)
80
+ });
79
81
  ```
80
82
 
81
- #### Methods
83
+ ## API Reference
84
+
85
+ ### Methods
82
86
 
83
87
  | Method | Description |
84
88
  |--------|-------------|
85
- | `init()` | Initialize client and fetch flags |
86
- | `isEnabled(key)` | Check if boolean flag is enabled |
89
+ | `init()` | Initialize client and fetch flags (required before evaluation) |
90
+ | `isEnabled(key)` | Check if a boolean flag is enabled |
87
91
  | `getValue(key)` | Get flag value (any type) |
88
92
  | `getVariation(key)` | Alias for getValue |
89
- | `getAllFlags()` | Get all evaluated flag values |
90
- | `updateContext(context)` | Update user context and re-evaluate |
91
- | `onChange(callback)` | Subscribe to flag changes |
92
- | `close()` | Clean up timers and connections |
93
+ | `updateContext(ctx)` | Update user context and re-evaluate flags |
94
+ | `onChange(callback)` | Subscribe to flag value changes |
95
+ | `close()` | Clean up resources (stop polling) |
96
+
97
+ ### Flag Types
98
+
99
+ #### Boolean Flags
100
+
101
+ ```typescript
102
+ if (client.isEnabled('feature-flag')) {
103
+ // Feature is enabled for this user
104
+ }
105
+ ```
106
+
107
+ #### String Flags
108
+
109
+ Perfect for A/B tests and feature variants:
110
+
111
+ ```typescript
112
+ const variant = client.getValue('button-color');
113
+ // Returns: 'blue' | 'green' | 'orange'
114
+ ```
115
+
116
+ #### Number Flags
93
117
 
94
- ## Targeting Operators
118
+ Great for limits, thresholds, and configurations:
119
+
120
+ ```typescript
121
+ const limit = client.getValue('rate-limit');
122
+ // Returns: 100 | 1000 | 10000
123
+ ```
124
+
125
+ #### JSON Flags
126
+
127
+ For complex configurations:
128
+
129
+ ```typescript
130
+ const config = client.getValue('checkout-config');
131
+ // Returns: { showCoupons: true, maxItems: 50, ... }
132
+ ```
133
+
134
+ ## Targeting Rules
135
+
136
+ Flagpool supports powerful targeting with 8 operators:
95
137
 
96
138
  | Operator | Description | Example |
97
139
  |----------|-------------|---------|
@@ -106,8 +148,9 @@ interface FlagpoolClientOptions {
106
148
 
107
149
  ## Dynamic Context Updates
108
150
 
151
+ Update user context on the fly - flags re-evaluate automatically:
152
+
109
153
  ```typescript
110
- // Initial context
111
154
  const client = new FlagpoolClient({
112
155
  apiKey: 'fp_prod_xxx',
113
156
  environment: 'production',
@@ -116,143 +159,166 @@ const client = new FlagpoolClient({
116
159
 
117
160
  await client.init();
118
161
 
162
+ // User on free plan
119
163
  console.log(client.getValue('max-upload-size-mb')); // 10
120
164
 
121
165
  // User upgrades to pro
122
166
  client.updateContext({ plan: 'pro' });
123
167
 
168
+ // Instantly gets pro limits
124
169
  console.log(client.getValue('max-upload-size-mb')); // 100
125
170
  ```
126
171
 
127
- ## Encrypted Target Lists
128
-
129
- For offline/edge scenarios, you can decrypt and evaluate target lists client-side.
130
-
131
- > **Note:** The SDK has NO crypto dependencies. You provide the adapter.
172
+ ## Real-time Updates
132
173
 
133
- ### Step 1: Create a Crypto Adapter
174
+ Flags automatically refresh in the background:
134
175
 
135
176
  ```typescript
136
- // crypto-adapter.ts (YOUR CODE)
137
- import type { CryptoAdapter } from 'flagpool-sdk';
177
+ const client = new FlagpoolClient({
178
+ apiKey: 'fp_prod_xxx',
179
+ environment: 'production',
180
+ context: { userId: 'user-1' },
181
+ pollingInterval: 30000 // Refresh every 30 seconds
182
+ });
183
+
184
+ await client.init();
138
185
 
139
- export async function createNodeCryptoAdapter(): Promise<CryptoAdapter> {
140
- const crypto = await import('crypto');
186
+ // Listen for flag changes
187
+ client.onChange((flagKey, newValue) => {
188
+ console.log(`Flag ${flagKey} changed to:`, newValue);
141
189
 
142
- return {
143
- async decrypt(ciphertext, key, iv, tag) {
144
- // Your AES-256-GCM decryption implementation
145
- // See examples/src/crypto-adapter.ts for full implementation
146
- }
147
- };
148
- }
190
+ // React to changes (e.g., update UI)
191
+ if (flagKey === 'maintenance-mode' && newValue === true) {
192
+ showMaintenanceBanner();
193
+ }
194
+ });
149
195
  ```
150
196
 
151
- ### Step 2: Register and Use
197
+ ## Offline Support
152
198
 
153
- ```typescript
154
- import { FlagpoolClient, setCryptoAdapter } from 'flagpool-sdk';
155
- import { createNodeCryptoAdapter } from './crypto-adapter';
156
-
157
- // 1. Create and register your adapter
158
- const adapter = await createNodeCryptoAdapter();
159
- setCryptoAdapter(adapter);
199
+ The SDK caches flags locally. If the network is unavailable, it uses cached values:
160
200
 
161
- // 2. Create client with decryption enabled
201
+ ```typescript
162
202
  const client = new FlagpoolClient({
163
- apiKey: 'fp_staging_xxx',
164
- environment: 'staging',
165
- context: { userId: 'beta-user-1' },
166
- decryptionKey: 'your-secret-key',
167
- clientSideTargetLists: true,
203
+ apiKey: 'fp_prod_xxx',
204
+ environment: 'production',
205
+ context: { userId: 'user-1' }
168
206
  });
169
207
 
208
+ // Works even if network fails (uses cache from last successful fetch)
170
209
  await client.init();
171
210
 
172
- // Target list rules are now evaluated locally
173
- client.isEnabled('beta-feature'); // true if userId is in beta-testers
211
+ // Always returns a value (from cache if offline)
212
+ const feature = client.isEnabled('my-feature');
174
213
  ```
175
214
 
176
- ## Real-time Updates
215
+ ## Framework Examples
216
+
217
+ ### React
177
218
 
178
219
  ```typescript
220
+ import { useEffect, useState } from 'react';
221
+ import { FlagpoolClient } from '@flagpool/sdk';
222
+
179
223
  const client = new FlagpoolClient({
180
224
  apiKey: 'fp_prod_xxx',
181
225
  environment: 'production',
182
- context: { userId: 'user-1' },
183
- streaming: true,
184
- pollingInterval: 30000 // Poll every 30 seconds
185
226
  });
186
227
 
187
- await client.init();
228
+ export function useFeatureFlag(key: string) {
229
+ const [value, setValue] = useState<any>(null);
188
230
 
189
- // Listen to flag changes
190
- client.onChange((flagKey, newValue) => {
191
- console.log(`Flag ${flagKey} changed to:`, newValue);
192
- });
193
- ```
231
+ useEffect(() => {
232
+ client.init().then(() => {
233
+ setValue(client.getValue(key));
234
+ });
194
235
 
195
- ## Examples
236
+ const unsubscribe = client.onChange((changedKey, newValue) => {
237
+ if (changedKey === key) setValue(newValue);
238
+ });
196
239
 
197
- See the `examples/` directory for working examples:
240
+ return () => unsubscribe?.();
241
+ }, [key]);
198
242
 
199
- ```bash
200
- cd examples
201
- npm install
202
-
203
- # Start mock server (uses shared server from test-harness)
204
- npm run server
243
+ return value;
244
+ }
205
245
 
206
- # Run tests
207
- npm run test:dev # Development environment
208
- npm run test:staging # Staging environment
209
- npm run test:evaluator # Comprehensive evaluator tests
210
- npm run test:client-side # Client-side target list evaluation
246
+ // Usage
247
+ function MyComponent() {
248
+ const showNewFeature = useFeatureFlag('new-feature');
249
+
250
+ if (showNewFeature) {
251
+ return <NewFeature />;
252
+ }
253
+ return <OldFeature />;
254
+ }
211
255
  ```
212
256
 
213
- ## Flag Types
214
-
215
- ### Boolean Flags
257
+ ### Next.js
216
258
 
217
259
  ```typescript
218
- if (client.isEnabled('feature-flag')) {
219
- // Feature is enabled
260
+ // lib/flagpool.ts
261
+ import { FlagpoolClient } from '@flagpool/sdk';
262
+
263
+ let client: FlagpoolClient | null = null;
264
+
265
+ export async function getFlags(userId: string) {
266
+ if (!client) {
267
+ client = new FlagpoolClient({
268
+ apiKey: process.env.FLAGPOOL_API_KEY!,
269
+ environment: process.env.NODE_ENV,
270
+ context: { userId }
271
+ });
272
+ await client.init();
273
+ }
274
+
275
+ return {
276
+ newDashboard: client.isEnabled('new-dashboard'),
277
+ buttonColor: client.getValue('button-color'),
278
+ };
220
279
  }
221
280
  ```
222
281
 
223
- ### String Flags (A/B Tests)
282
+ ### Node.js / Express
224
283
 
225
284
  ```typescript
226
- const variant = client.getValue('button-color');
227
- // 'blue' | 'green' | 'orange'
228
- ```
285
+ import express from 'express';
286
+ import { FlagpoolClient } from '@flagpool/sdk';
229
287
 
230
- ### Number Flags
288
+ const app = express();
231
289
 
232
- ```typescript
233
- const limit = client.getValue('rate-limit');
234
- // 100 | 1000 | 10000
235
- ```
290
+ const flagpool = new FlagpoolClient({
291
+ apiKey: process.env.FLAGPOOL_API_KEY!,
292
+ environment: 'production',
293
+ });
236
294
 
237
- ### JSON Flags
295
+ // Initialize on startup
296
+ await flagpool.init();
238
297
 
239
- ```typescript
240
- const config = client.getValue('checkout-config');
241
- // { showCoupons: true, maxItems: 50, ... }
298
+ app.get('/api/data', (req, res) => {
299
+ // Update context per-request
300
+ flagpool.updateContext({ userId: req.user.id });
301
+
302
+ if (flagpool.isEnabled('new-api-response')) {
303
+ return res.json({ version: 'v2', data: newData });
304
+ }
305
+ return res.json({ version: 'v1', data: legacyData });
306
+ });
242
307
  ```
243
308
 
244
- ## Conformance
309
+ ## Documentation
245
310
 
246
- This SDK passes all 60 conformance tests defined in `/spec/test-vectors.json`.
311
+ For complete documentation, guides, and best practices, visit:
247
312
 
248
- Run conformance tests:
313
+ 📚 **[flagpool.io/docs](https://flagpool.io/docs)**
249
314
 
250
- ```bash
251
- cd ../../test-harness
252
- npm run test:typescript
253
- ```
315
+ ## Support
316
+
317
+ - 📖 [Documentation](https://flagpool.io/docs)
318
+ - 🐛 [Report Issues](https://github.com/flagpool/flagpool-sdk/issues)
319
+ - ✉️ [Email Support](mailto:support@flagpool.io)
254
320
 
255
321
  ## License
256
322
 
257
- MIT
323
+ MIT © [Flagpool](https://flagpool.io)
258
324
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flagpool/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Official Flagpool SDK for TypeScript/JavaScript - feature flags with local evaluation, deterministic rollouts, and encrypted target lists",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -25,7 +25,7 @@
25
25
  "url": "git+https://github.com/flagpool/flagpool-sdk.git",
26
26
  "directory": "sdks/typescript"
27
27
  },
28
- "homepage": "https://github.com/flagpool/flagpool-sdk/tree/main/sdks/typescript#readme",
28
+ "homepage": "https://flagpool.io/docs/sdks/typescript",
29
29
  "bugs": {
30
30
  "url": "https://github.com/flagpool/flagpool-sdk/issues"
31
31
  },