flagmint-js-sdk 1.2.24 โ†’ 1.2.25

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 CHANGED
@@ -1,21 +1,29 @@
1
- MIT License
1
+ BSD 3-Clause License
2
2
 
3
- Copyright (c) 2025 Israel Edet
3
+ Copyright (c) 2024, Flagmint
4
+ All rights reserved.
4
5
 
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:
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
11
8
 
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
14
11
 
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.
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md CHANGED
@@ -1,11 +1,20 @@
1
1
  # Flagmint JavaScript SDK
2
2
 
3
- **Version: v1.2.24**
3
+ **Version: v1.2.25**
4
4
 
5
5
  This SDK provides a javascript 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
6
 
7
7
  ## ๐Ÿ“‹ Release Notes
8
8
 
9
+ ### v1.2.25
10
+ - ๐Ÿ”‡ **Controllable debug logging** โ€” SDK logs are now silent by default; opt in with `logger.setup({ debugLog: true })`. In production, only connection/disconnection messages are ever emitted regardless of the setting.
11
+ - ๐Ÿ”Œ **Configurable endpoints** โ€” `restEndpoint` and `wsEndpoint` can now be passed directly in `FlagClientOptions`, overriding the environment-derived defaults. Useful for proxies, staging overrides, or self-hosted deployments.
12
+ - ๐Ÿ“ก **`subscribe()` delivers current flags immediately** โ€” the callback is now called synchronously with the current flag state at subscription time, so you never miss the initial value.
13
+ - ๐Ÿงน **`destroy()` clears all subscribers** โ€” calling `destroy()` now also clears the subscriber set, preventing stale callbacks from holding references after teardown.
14
+ - ๐Ÿ›ก๏ธ **WebSocket auth vs rate-limit error discrimination** โ€” close code `1008`/`4001` now inspects the close reason to distinguish `ERR_AUTH` (invalid API key) from `ERR_RATE_LIMITED` errors. Rate-limit errors include a `resetTime` field parsed from the close reason.
15
+ - ๐Ÿ”— **`initialFlagsReject` on WebSocket transport** โ€” a post-`onopen` close with a terminal code now correctly rejects the `waitForInitialFlags()` promise (and therefore `init()`), so the error surfaces reliably through `client.ready()` even when the connection opened before the server sent the close frame.
16
+ - ๐Ÿ”” **`onConnectionStateChanged()` exposed** โ€” consumers can now register a callback to observe WebSocket connection state transitions (`connecting`, `connected`, `disconnected`, `reconnecting`, `failed`).
17
+
9
18
  ### v1.2.24
10
19
  - โœจ Add `env` parameter to SDK configuration for explicit environment specification
11
20
  - Allows users to pass environment as a variable when NODE_ENV or NEXT_PUBLIC_NODE_ENV cannot be reliably detected
@@ -64,14 +73,38 @@ await client.updateContext({
64
73
  | `apiKey` | `string` | **Required** | Your environment API key. |
65
74
  | `context` | `Record<string, any>` | `{}` | Initial evaluation context (e.g. user attributes). |
66
75
  | `enableOfflineCache` | `boolean` | `true` | Enable caching of flags locally. |
67
- | `persistContext` | `boolean` | `false` | Persist evaluation context across sessions. | |
76
+ | `persistContext` | `boolean` | `false` | Persist evaluation context across sessions. |
68
77
  | `cacheAdapter` | `CacheAdapter<C>` | Sync `cacheHelper` | Custom cache implementation (see examples). |
69
78
  | `transportMode` | `'auto' \| 'websocket' \| 'long-polling'` | `'auto'` | How to fetch flags: prefer WebSocket, or use long-polling transport. |
79
+ | `restEndpoint` | `string` | env-derived | Override the REST endpoint (useful for proxies or self-hosted setups).|
80
+ | `wsEndpoint` | `string` | env-derived | Override the WebSocket endpoint. |
70
81
  | `onError` | `(error: Error) => void` | โ€” | Callback for transport or initialization errors. Called when operating in degraded mode with cached flags. |
71
82
  | `previewMode` | `boolean` | `false` | Evaluate using `rawFlags` only, bypassing remote fetch. |
72
83
  | `rawFlags` | `Record<string, FlagValue>` | โ€” | Local-only flag definitions used when `previewMode: true`. |
73
84
  | `deferInitialization` | `boolean` | `false` | If `true`, client initialization is deferred until you call `ready()`. |
74
85
 
86
+ ## ๐Ÿชต Debug Logging
87
+
88
+ By default the SDK is **silent** โ€” no console output in any environment. To enable verbose logging during development, call `logger.setup()` before creating your client:
89
+
90
+ ```ts
91
+ import { logger } from 'flagmint-js-sdk';
92
+
93
+ logger.setup({ debugLog: true });
94
+
95
+ const client = new FlagClient({ apiKey: '...' });
96
+ ```
97
+
98
+ In **production** (`NODE_ENV=production`), only connection and disconnection messages are emitted regardless of the `debugLog` setting โ€” all other internal logs are suppressed.
99
+
100
+ ```ts
101
+ // These messages always appear in production:
102
+ // "[WebSocketTransport] Connected"
103
+ // "[WebSocketTransport] Connection closed: 1000"
104
+
105
+ // All other internal logs require debugLog: true in non-production environments
106
+ ```
107
+
75
108
  ## ๐Ÿ”ง Cache Adapters
76
109
 
77
110
  ### Sync (Browser / In-Memory)
@@ -118,6 +151,32 @@ const client = new FlagClient({
118
151
  });
119
152
  ```
120
153
 
154
+ ### Custom Endpoints
155
+
156
+ Override the default environment-derived endpoints โ€” useful for proxies, staging overrides, or self-hosted deployments:
157
+
158
+ ```ts
159
+ const client = new FlagClient({
160
+ apiKey: '...',
161
+ restEndpoint: 'https://my-proxy.example.com/evaluator/evaluate',
162
+ wsEndpoint: 'wss://my-proxy.example.com/ws/sdk',
163
+ });
164
+ ```
165
+
166
+ ### WebSocket Connection State
167
+
168
+ Monitor connection state transitions by accessing the underlying WebSocket transport directly:
169
+
170
+ ```ts
171
+ import { WebSocketTransport } from 'flagmint-js-sdk';
172
+
173
+ const ws = new WebSocketTransport(wsUrl, apiKey);
174
+ ws.onConnectionStateChanged((state) => {
175
+ // state: 'connecting' | 'connected' | 'disconnected' | 'reconnecting' | 'failed'
176
+ console.log('WS state:', state);
177
+ });
178
+ ```
179
+
121
180
  ### Transport Performance
122
181
 
123
182
  | Mode | Latency | Bandwidth | Best For |
@@ -342,7 +401,7 @@ The SDK gracefully handles connection failures using cached flags as a fallback:
342
401
 
343
402
  | Scenario | `ready()` Promise | Behavior |
344
403
  |----------|-------------------|----------|
345
- | โœ… Cached flags available | Resolves | Operates in degraded mode with cached flags |
404
+ | โœ… Cached flags available | Resolves | Operates in degraded mode with cached flags; `onError` is called |
346
405
  | โŒ No cached flags | Rejects | Initialization fails |
347
406
  | โœ… Connected successfully | Resolves | Normal operation with live updates |
348
407
 
@@ -435,17 +494,17 @@ const client = new FlagClient({
435
494
  - `getFlag<K>(key: K, fallback?: T): T` - Get flag value with optional fallback
436
495
  - `getFlags(): FeatureFlags<T>` - Get all flags as an object
437
496
  - `updateContext(context: Record<string, any>): Promise<void>` - Update evaluation context (async)
438
- - `subscribe(callback: (flags) => void): () => void` - Subscribe to flag updates, returns unsubscribe function
439
- - `destroy(): void` - Close transport connection and cleanup resources
497
+ - `subscribe(callback: (flags) => void): () => void` - Subscribe to flag updates; fires immediately with current flags, returns unsubscribe function
498
+ - `destroy(): void` - Close transport connection, clear all subscribers, and release resources
440
499
 
441
500
  ### Subscribing to Flag Updates
442
501
 
443
- Instead of event listeners, use the `subscribe()` method:
502
+ Instead of event listeners, use the `subscribe()` method. The callback is called **immediately** with the current flag state at subscription time, then again on every subsequent update:
444
503
 
445
504
  ```ts
446
505
  const unsubscribe = client.subscribe((flags) => {
447
506
  console.log('Flags updated:', flags);
448
- // Handle flag updates
507
+ // Also fires immediately with current flags โ€” no need to call getFlags() separately
449
508
  });
450
509
 
451
510
  // Later, to unsubscribe:
@@ -509,11 +568,9 @@ sdk/
509
568
 
510
569
  **Important**: When `enableOfflineCache: true` (default):
511
570
  - Cached flags are loaded even if the server is unreachable
512
- - `ready()` will still throw an error on connection failure
513
- - You can still access cached flags via `getFlag()` after catching the error
514
- - Consider wrapping `ready()` in try/catch and continuing with cached data
515
-
516
- See the "Error Handling with Cache" section above for examples.
571
+ - `ready()` **resolves** (does not throw) if cached flags are available โ€” the `onError` callback is invoked instead to signal degraded mode
572
+ - `ready()` only rejects if **no cached flags exist** and the server is unreachable
573
+ - You can safely call `getFlag()` after `ready()` resolves, regardless of whether the connection succeeded
517
574
 
518
575
  ### Performance issues
519
576
 
@@ -541,6 +598,6 @@ See [GitHub Releases](https://github.com/flagmint/js-sdk/releases) for the compl
541
598
 
542
599
  ---
543
600
 
544
- **License**: MIT ยฉ Flagmint Team
601
+ **License**: BSD 3-Clause License ยฉ Flagmint Team
545
602
 
546
603
  **Maintained with โค๏ธ by the Flagmint Team**