flagmint-js-sdk 1.0.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 +21 -0
- package/README.md +136 -0
- package/dist/client.d.ts +59 -0
- package/dist/evaluation/evaluateFlagValue.d.ts +4 -0
- package/dist/evaluation/evaluateRollout.d.ts +2 -0
- package/dist/evaluation/isInSegment.d.ts +3 -0
- package/dist/evaluation/rolloutUtils.d.ts +3 -0
- package/dist/evaluation/types.d.ts +42 -0
- package/dist/flagmint.cjs.js +13 -0
- package/dist/flagmint.es.js +19214 -0
- package/dist/flagmint.umd.js +13 -0
- package/dist/helpers/cacheHelper.async.d.ts +11 -0
- package/dist/helpers/cacheHelper.d.ts +11 -0
- package/dist/helpers/types.d.ts +7 -0
- package/dist/index.d.ts +1 -0
- package/dist/transports/LongPollingTransport.d.ts +11 -0
- package/dist/transports/Transport.d.ts +7 -0
- package/dist/transports/WebsocketTransport.d.ts +24 -0
- package/package.json +45 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Israel Edet
|
|
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,136 @@
|
|
|
1
|
+
# Flagmint JavaScript SDK
|
|
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).
|
|
4
|
+
|
|
5
|
+
## 📦 Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install flagmint-sdk
|
|
9
|
+
# or
|
|
10
|
+
yarn add flagmint-sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 🛠️ FlagClientOptions
|
|
14
|
+
|
|
15
|
+
| Option | Type | Default | Description |
|
|
16
|
+
| --------------------- | ----------------------------------------- | ------------------ | --------------------------------------------------------------------- |
|
|
17
|
+
| `apiKey` | `string` | **Required** | Your environment API key. |
|
|
18
|
+
| `context` | `Record<string, any>` | `{}` | Initial evaluation context (e.g. user attributes). |
|
|
19
|
+
| `enableOfflineCache` | `boolean` | `false` | Enable caching of flags locally. |
|
|
20
|
+
| `persistContext` | `boolean` | `false` | Persist evaluation context across sessions. | |
|
|
21
|
+
| `cacheAdapter` | `CacheAdapter<C>` | Sync `cacheHelper` | Custom cache implementation (see examples). |
|
|
22
|
+
| `transportMode` | `'auto' \| 'websocket' \| 'long-polling'` | `'auto'` | How to fetch flags: prefer WebSocket, or use long-polling transport. |
|
|
23
|
+
| `onError` | `(error: Error) => void` | — | Callback for transport or initialization errors. |
|
|
24
|
+
| `previewMode` | `boolean` | `false` | Evaluate using `rawFlags` only, bypassing remote fetch. |
|
|
25
|
+
| `rawFlags` | `Record<string, FlagValue>` | — | Local-only flag definitions used when `previewMode: true`. |
|
|
26
|
+
| `deferInitialization` | `boolean` | `false` | If `true`, client initialization is deferred until you call `init()`. |
|
|
27
|
+
|
|
28
|
+
## 🔧 Cache Adapters
|
|
29
|
+
|
|
30
|
+
### Sync (Browser / In-Memory)
|
|
31
|
+
|
|
32
|
+
By default, the SDK uses a **sync** `localStorage`-based helper in browsers or a `Map` in Node.js:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { FlagClient } from 'flagmint-sdk';
|
|
36
|
+
// No setup needed for browser; for Node you can override:
|
|
37
|
+
import { setCacheStorage } from 'flagmint-sdk/core/cacheHelper';
|
|
38
|
+
setCacheStorage({
|
|
39
|
+
getItem: key => myMap.get(key) ?? null,
|
|
40
|
+
setItem: (key, val) => myMap.set(key, val),
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Async (Redis / File System)
|
|
45
|
+
|
|
46
|
+
Use the **async** helper for server-side or React Native:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { FlagClient } from 'flagmint-sdk';
|
|
50
|
+
import * as asyncCache from 'flagmint-sdk/core/cacheHelper.async';
|
|
51
|
+
|
|
52
|
+
const client = new FlagClient({
|
|
53
|
+
apiKey: '...',
|
|
54
|
+
cacheAdapter: {
|
|
55
|
+
loadFlags: asyncCache.loadCachedFlags,
|
|
56
|
+
saveFlags: asyncCache.saveCachedFlags,
|
|
57
|
+
loadContext: asyncCache.loadCachedContext,
|
|
58
|
+
saveContext: asyncCache.saveCachedContext
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 🌐 Transport Modes
|
|
64
|
+
|
|
65
|
+
* **`'websocket'`**: Persistent WebSocket connection for live updates.
|
|
66
|
+
* **`'long-polling'`**: HTTP requests held open by server until flags change.
|
|
67
|
+
* **`'auto'`** (default): Try WebSocket, fallback to long-polling.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
const client = new FlagClient({
|
|
71
|
+
apiKey: '...',
|
|
72
|
+
transportMode: 'long-polling'
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## ⚙️ Evaluation Helpers
|
|
77
|
+
|
|
78
|
+
The SDK includes utilities to evaluate flag targeting rules and rollouts:
|
|
79
|
+
|
|
80
|
+
### `evaluateFlagValue(flag, context)`
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import { evaluateFlagValue } from 'flagmint-sdk/core/evaluation';
|
|
84
|
+
|
|
85
|
+
const result = evaluateFlagValue(flagValue, userContext);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
* Applies targeting rules (`segment` or attribute rules).
|
|
89
|
+
* If matched, applies rollout (percentage or variant).
|
|
90
|
+
* Returns flag’s value or `null` if not enabled.
|
|
91
|
+
|
|
92
|
+
### `evaluateRollout(rollout, context)`
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { evaluateRollout } from 'flagmint-sdk/core/evaluation';
|
|
96
|
+
|
|
97
|
+
const rolloutValue = evaluateRollout(rolloutConfig, userContext);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
* Supports **percentage** rollouts using consistent hashing.
|
|
101
|
+
* Supports **variant** distributions (A/B tests).
|
|
102
|
+
|
|
103
|
+
### `rolloutUtils`
|
|
104
|
+
|
|
105
|
+
* `hashToPercentage(value: string): number`
|
|
106
|
+
* `pickVariant(value: string, variants: VariantRollout): T | null`
|
|
107
|
+
|
|
108
|
+
These helpers underpin reliable, deterministic assignment of users to flag variants.
|
|
109
|
+
|
|
110
|
+
## 🚀 Quick Start
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { FlagClient } from 'flagmint-sdk';
|
|
114
|
+
|
|
115
|
+
const client = new FlagClient({
|
|
116
|
+
apiKey: 'ff_XXXX',
|
|
117
|
+
context: { user_id: 'user123', country: 'US' }
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// wait until connected
|
|
121
|
+
await client.ready();
|
|
122
|
+
|
|
123
|
+
// get flag
|
|
124
|
+
const showBanner = client.getFlag('show_banner', false);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 📖 References
|
|
128
|
+
|
|
129
|
+
* Core client: `@/core/client.ts`
|
|
130
|
+
* Cache helpers: `@/core/helpers/cacheHelper.ts`, `asyncCacheHelper.ts`
|
|
131
|
+
* Transports: `WebsocketTransport`, `LongPollingTransport`
|
|
132
|
+
* Evaluation: `evaluateFlagValue`, `evaluateRollout`, `rolloutUtils`
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
*MIT © Flagmint Team*
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { CacheAdapter, FeatureFlags } from '../core/helpers/types';
|
|
2
|
+
import type { Transport } from '../core/transports/Transport';
|
|
3
|
+
import { FlagValue } from '../core/evaluation/types';
|
|
4
|
+
type TransportMode = 'auto' | 'websocket' | 'long-polling';
|
|
5
|
+
export interface FlagClientOptions<C extends Record<string, any> = Record<string, any>> {
|
|
6
|
+
apiKey: string;
|
|
7
|
+
context?: C;
|
|
8
|
+
enableOfflineCache?: boolean;
|
|
9
|
+
persistContext?: boolean;
|
|
10
|
+
transport?: Transport<C, any>;
|
|
11
|
+
transportMode?: TransportMode;
|
|
12
|
+
onError?: (error: Error) => void;
|
|
13
|
+
previewMode?: boolean;
|
|
14
|
+
rawFlags?: Record<string, FlagValue>;
|
|
15
|
+
deferInitialization?: boolean;
|
|
16
|
+
cacheAdapter?: CacheAdapter<C>;
|
|
17
|
+
}
|
|
18
|
+
export declare class FlagClient<T = unknown, C extends Record<string, any> = Record<string, any>> {
|
|
19
|
+
private apiKey;
|
|
20
|
+
private context;
|
|
21
|
+
private flags;
|
|
22
|
+
private refreshIntervalId;
|
|
23
|
+
private enableOfflineCache;
|
|
24
|
+
private persistContext;
|
|
25
|
+
private cacheTTL;
|
|
26
|
+
private transport;
|
|
27
|
+
private readyPromise;
|
|
28
|
+
private resolveReady;
|
|
29
|
+
private rejectReady;
|
|
30
|
+
private onError?;
|
|
31
|
+
private previewMode;
|
|
32
|
+
private rawFlags;
|
|
33
|
+
private cacheAdapter;
|
|
34
|
+
/**
|
|
35
|
+
* Creates a new FlagClient instance.
|
|
36
|
+
* @param options - Configuration options for the client.
|
|
37
|
+
*/
|
|
38
|
+
constructor(options: FlagClientOptions<C>);
|
|
39
|
+
/**
|
|
40
|
+
* Initializes the client by loading cached flags and context, setting up the transport layer, and starting the auto-refresh timer if enabled.
|
|
41
|
+
* @param options - The options for initializing the client.
|
|
42
|
+
*
|
|
43
|
+
* @throws Will throw an error if initialization fails.
|
|
44
|
+
* @returns {Promise<void>} A promise that resolves when the client is ready.
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
private initialize;
|
|
48
|
+
/**
|
|
49
|
+
* Sets up the transport layer for the client.
|
|
50
|
+
* @param options - The options for the transport setup.
|
|
51
|
+
*/
|
|
52
|
+
private setupTransport;
|
|
53
|
+
getFlag<K extends keyof FeatureFlags<T>>(key: K, fallback?: FeatureFlags<T>[K]): FeatureFlags<T>[K];
|
|
54
|
+
updateContext(context: C): void;
|
|
55
|
+
destroy(): void;
|
|
56
|
+
ready(): Promise<void>;
|
|
57
|
+
private evaluateLocally;
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type Operator = 'eq' | 'neq' | 'in' | 'nin' | 'gt' | 'lt' | 'exists' | 'not_exists';
|
|
2
|
+
export interface Rule {
|
|
3
|
+
type: 'rule';
|
|
4
|
+
attribute: string;
|
|
5
|
+
operator: Operator;
|
|
6
|
+
value: string | string[];
|
|
7
|
+
}
|
|
8
|
+
export interface SegmentReference {
|
|
9
|
+
type: 'segment';
|
|
10
|
+
segment_id: string;
|
|
11
|
+
}
|
|
12
|
+
export type TargetingRule = Rule | SegmentReference;
|
|
13
|
+
export interface PercentageRollout {
|
|
14
|
+
strategy: 'percentage';
|
|
15
|
+
percentage: number;
|
|
16
|
+
salt: string;
|
|
17
|
+
}
|
|
18
|
+
export interface VariantOption {
|
|
19
|
+
value: string | number | boolean;
|
|
20
|
+
weight: number;
|
|
21
|
+
}
|
|
22
|
+
export interface VariantRollout {
|
|
23
|
+
strategy: 'variant';
|
|
24
|
+
salt: string;
|
|
25
|
+
variants: VariantOption[];
|
|
26
|
+
}
|
|
27
|
+
export type EmptyRollout = Record<string, any>;
|
|
28
|
+
export type Rollout = PercentageRollout | VariantRollout | EmptyRollout;
|
|
29
|
+
export interface FlagValue<T = unknown> {
|
|
30
|
+
key?: string;
|
|
31
|
+
value: T;
|
|
32
|
+
type: 'boolean' | 'string' | 'number' | 'object';
|
|
33
|
+
targeting_rules?: TargetingRule[];
|
|
34
|
+
rollout?: Rollout;
|
|
35
|
+
}
|
|
36
|
+
export type EvaluationContext = Record<string, unknown>;
|
|
37
|
+
export interface Segment {
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
rules: TargetingRule[];
|
|
42
|
+
}
|