@togglely/sdk 1.1.2 → 1.2.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/README.md +211 -37
- package/dist/index.umd.js +151 -58
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/package.json +35 -35
package/README.md
CHANGED
|
@@ -1,63 +1,64 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Togglely Vanilla JavaScript SDK
|
|
2
2
|
|
|
3
|
-
Vanilla JavaScript SDK for Togglely
|
|
3
|
+
Vanilla JavaScript SDK for [Togglely](https://togglely.io) feature flag management. Works in browsers and Node.js without any framework.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🌍 **Universal** - Works in browser and Node.js
|
|
8
|
+
- 📦 **Zero dependencies** - Lightweight and fast
|
|
9
|
+
- 💾 **Offline support** - JSON file, environment variables, or window object
|
|
10
|
+
- 🎯 **Simple API** - Easy to use with global instance
|
|
11
|
+
- 🔒 **TypeScript** - Full type support
|
|
4
12
|
|
|
5
13
|
## Installation
|
|
6
14
|
|
|
15
|
+
### NPM
|
|
16
|
+
|
|
7
17
|
```bash
|
|
8
18
|
npm install @togglely/sdk
|
|
9
19
|
```
|
|
10
20
|
|
|
11
|
-
|
|
21
|
+
### CDN
|
|
12
22
|
|
|
13
23
|
```html
|
|
14
24
|
<script src="https://unpkg.com/@togglely/sdk/dist/index.umd.min.js"></script>
|
|
15
25
|
```
|
|
16
26
|
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
### ES Modules
|
|
20
|
-
|
|
21
|
-
```javascript
|
|
22
|
-
import { TogglelyClient } from '@togglely/sdk';
|
|
23
|
-
|
|
24
|
-
const client = new TogglelyClient({
|
|
25
|
-
apiKey: 'your-api-key',
|
|
26
|
-
environment: 'production',
|
|
27
|
-
baseUrl: 'https://your-togglely-instance.com'
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const isEnabled = await client.isEnabled('new-feature', false);
|
|
31
|
-
```
|
|
27
|
+
## Quick Start
|
|
32
28
|
|
|
33
|
-
###
|
|
29
|
+
### Browser (Module)
|
|
34
30
|
|
|
35
31
|
```javascript
|
|
36
32
|
import { initTogglely, isEnabled } from '@togglely/sdk';
|
|
37
33
|
|
|
38
|
-
// Initialize
|
|
34
|
+
// Initialize
|
|
39
35
|
initTogglely({
|
|
40
36
|
apiKey: 'your-api-key',
|
|
37
|
+
project: 'my-project',
|
|
41
38
|
environment: 'production',
|
|
42
|
-
baseUrl: 'https://
|
|
39
|
+
baseUrl: 'https://togglely.io',
|
|
43
40
|
});
|
|
44
41
|
|
|
45
42
|
// Use global helpers
|
|
46
|
-
const
|
|
43
|
+
const newFeature = await isEnabled('new-feature', false);
|
|
44
|
+
if (newFeature) {
|
|
45
|
+
document.getElementById('new-feature').style.display = 'block';
|
|
46
|
+
}
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
### CDN
|
|
49
|
+
### Browser (CDN)
|
|
50
50
|
|
|
51
51
|
```html
|
|
52
52
|
<script src="https://unpkg.com/@togglely/sdk/dist/index.umd.min.js"></script>
|
|
53
53
|
<script>
|
|
54
|
-
|
|
54
|
+
Togglely.initTogglely({
|
|
55
55
|
apiKey: 'your-api-key',
|
|
56
|
+
project: 'my-project',
|
|
56
57
|
environment: 'production',
|
|
57
|
-
baseUrl: 'https://
|
|
58
|
+
baseUrl: 'https://togglely.io',
|
|
58
59
|
});
|
|
59
60
|
|
|
60
|
-
|
|
61
|
+
Togglely.isEnabled('new-feature').then(function(enabled) {
|
|
61
62
|
if (enabled) {
|
|
62
63
|
document.getElementById('new-feature').style.display = 'block';
|
|
63
64
|
}
|
|
@@ -65,26 +66,199 @@ const enabled = await isEnabled('new-feature', false);
|
|
|
65
66
|
</script>
|
|
66
67
|
```
|
|
67
68
|
|
|
68
|
-
###
|
|
69
|
+
### Node.js
|
|
69
70
|
|
|
70
71
|
```javascript
|
|
71
|
-
|
|
72
|
+
const { TogglelyClient } = require('@togglely/sdk');
|
|
73
|
+
|
|
74
|
+
const client = new TogglelyClient({
|
|
75
|
+
apiKey: 'your-api-key',
|
|
76
|
+
project: 'my-project',
|
|
77
|
+
environment: 'production',
|
|
78
|
+
baseUrl: 'https://togglely.io',
|
|
79
|
+
});
|
|
72
80
|
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
const isEnabled = await client.isEnabled('new-feature', false);
|
|
82
|
+
console.log('New feature:', isEnabled);
|
|
83
|
+
```
|
|
75
84
|
|
|
76
|
-
|
|
77
|
-
|
|
85
|
+
## Configuration
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
initTogglely({
|
|
89
|
+
apiKey: 'your-api-key',
|
|
90
|
+
project: 'my-project',
|
|
91
|
+
environment: 'production',
|
|
92
|
+
baseUrl: 'https://togglely.io',
|
|
93
|
+
tenantId: 'brand-a', // For multi-brand projects
|
|
94
|
+
offlineJsonPath: '/toggles.json', // Offline fallback
|
|
95
|
+
timeout: 5000, // Request timeout
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Global Helpers
|
|
100
|
+
|
|
101
|
+
After calling `initTogglely()`, you can use these global helpers:
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
import { isEnabled, getString, getNumber, getJSON } from '@togglely/sdk';
|
|
105
|
+
|
|
106
|
+
// Boolean toggle
|
|
107
|
+
const enabled = await isEnabled('new-feature', false);
|
|
108
|
+
|
|
109
|
+
// String toggle
|
|
110
|
+
const message = await getString('welcome-message', 'Hello!');
|
|
111
|
+
|
|
112
|
+
// Number toggle
|
|
113
|
+
const limit = await getNumber('max-items', 10);
|
|
114
|
+
|
|
115
|
+
// JSON toggle
|
|
116
|
+
const config = await getJSON('app-config', { theme: 'dark' });
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## DOM Helpers
|
|
120
|
+
|
|
121
|
+
### togglelyToggle
|
|
122
|
+
|
|
123
|
+
Show/hide elements based on a toggle:
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
import { togglelyToggle } from '@togglely/sdk';
|
|
127
|
+
|
|
128
|
+
// Show element when toggle is enabled
|
|
129
|
+
await togglelyToggle('#new-feature', 'new-feature');
|
|
130
|
+
|
|
131
|
+
// Hide element when toggle is disabled (invert)
|
|
132
|
+
await togglelyToggle('#old-feature', 'new-feature', { invert: true });
|
|
133
|
+
|
|
134
|
+
// With default value
|
|
135
|
+
await togglelyToggle('#beta', 'beta-feature', { defaultValue: true });
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### togglelyInit
|
|
139
|
+
|
|
140
|
+
Initialize multiple elements:
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
import { togglelyInit } from '@togglely/sdk';
|
|
144
|
+
|
|
145
|
+
const unsubscribe = togglelyInit({
|
|
146
|
+
// Simple selectors
|
|
78
147
|
'new-feature': ['.new-feature', '.new-banner'],
|
|
79
|
-
|
|
148
|
+
|
|
149
|
+
// With options
|
|
80
150
|
'premium': {
|
|
81
151
|
selector: '.premium-content',
|
|
82
|
-
defaultValue: false
|
|
83
|
-
|
|
152
|
+
defaultValue: false
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
// Invert (hide when enabled)
|
|
156
|
+
'new-ui': {
|
|
157
|
+
selector: '.old-ui',
|
|
158
|
+
invert: true
|
|
84
159
|
}
|
|
85
160
|
});
|
|
161
|
+
|
|
162
|
+
// Cleanup
|
|
163
|
+
unsubscribe();
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Offline Fallback
|
|
167
|
+
|
|
168
|
+
### Environment Variables (Node.js)
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
TOGGLELY_NEW_FEATURE=true
|
|
172
|
+
TOGGLELY_MAX_ITEMS=100
|
|
173
|
+
TOGGLELY_WELCOME_MESSAGE="Hello World"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
const client = new TogglelyClient({
|
|
178
|
+
apiKey: 'your-api-key',
|
|
179
|
+
project: 'my-project',
|
|
180
|
+
environment: 'production',
|
|
181
|
+
baseUrl: 'https://togglely.io',
|
|
182
|
+
envPrefix: 'TOGGLELY_', // Default
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Window Object (Browser)
|
|
187
|
+
|
|
188
|
+
```html
|
|
189
|
+
<script>
|
|
190
|
+
window.__TOGGLELY_TOGGLES = {
|
|
191
|
+
'new-feature': { value: true, enabled: true },
|
|
192
|
+
'max-items': { value: 100, enabled: true },
|
|
193
|
+
'welcome-message': { value: 'Hello World', enabled: true }
|
|
194
|
+
};
|
|
195
|
+
</script>
|
|
196
|
+
<script src="https://unpkg.com/@togglely/sdk/dist/index.umd.min.js"></script>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### JSON File
|
|
200
|
+
|
|
201
|
+
Generate offline JSON:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
togglely-pull --apiKey=xxx --project=my-project --environment=production --output=./toggles.json
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Use in your app:
|
|
208
|
+
|
|
209
|
+
```javascript
|
|
210
|
+
initTogglely({
|
|
211
|
+
apiKey: 'your-api-key',
|
|
212
|
+
project: 'my-project',
|
|
213
|
+
environment: 'production',
|
|
214
|
+
baseUrl: 'https://togglely.io',
|
|
215
|
+
offlineJsonPath: '/toggles.json',
|
|
216
|
+
});
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Direct Client Usage
|
|
220
|
+
|
|
221
|
+
For more control, use the client directly:
|
|
222
|
+
|
|
223
|
+
```javascript
|
|
224
|
+
import { TogglelyClient } from '@togglely/sdk';
|
|
225
|
+
|
|
226
|
+
const client = new TogglelyClient({
|
|
227
|
+
apiKey: 'your-api-key',
|
|
228
|
+
project: 'my-project',
|
|
229
|
+
environment: 'production',
|
|
230
|
+
baseUrl: 'https://togglely.io',
|
|
231
|
+
tenantId: 'brand-a',
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// Set targeting context
|
|
235
|
+
client.setContext({ userId: '123', country: 'DE' });
|
|
236
|
+
|
|
237
|
+
// Check toggle
|
|
238
|
+
const enabled = await client.isEnabled('new-feature', false);
|
|
239
|
+
|
|
240
|
+
// Listen to events
|
|
241
|
+
client.on('ready', () => console.log('Ready!'));
|
|
242
|
+
client.on('offline', () => console.log('Offline mode'));
|
|
243
|
+
client.on('update', () => console.log('Toggles updated'));
|
|
244
|
+
|
|
245
|
+
// Get all toggles
|
|
246
|
+
const all = client.getAllToggles();
|
|
247
|
+
|
|
248
|
+
// Cleanup
|
|
249
|
+
client.destroy();
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Build-Time JSON Generation
|
|
253
|
+
|
|
254
|
+
```json
|
|
255
|
+
{
|
|
256
|
+
"scripts": {
|
|
257
|
+
"build": "togglely-pull --apiKey=$TOGGLELY_APIKEY --project=my-project --environment=production --output=./toggles.json"
|
|
258
|
+
}
|
|
259
|
+
}
|
|
86
260
|
```
|
|
87
261
|
|
|
88
|
-
##
|
|
262
|
+
## License
|
|
89
263
|
|
|
90
|
-
|
|
264
|
+
MIT
|
package/dist/index.umd.js
CHANGED
|
@@ -5,13 +5,16 @@
|
|
|
5
5
|
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Togglely Core SDK - Framework agnostic
|
|
8
|
+
* Togglely Core SDK - Framework agnostic feature flag management
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - Real-time feature flag evaluation
|
|
12
|
+
* - Offline fallback via JSON file, environment variables, or window object
|
|
13
|
+
* - Multi-brand/tenant support
|
|
14
|
+
* - Type-safe flag access
|
|
15
|
+
* - Build-time JSON generation for offline-first deployment
|
|
14
16
|
*/
|
|
17
|
+
// ==================== Togglely Client ====================
|
|
15
18
|
class TogglelyClient {
|
|
16
19
|
constructor(config) {
|
|
17
20
|
this.toggles = new Map();
|
|
@@ -25,10 +28,11 @@
|
|
|
25
28
|
this.eventHandlers = new Map();
|
|
26
29
|
this.offlineTogglesLoaded = false;
|
|
27
30
|
this.config = {
|
|
28
|
-
refreshInterval: 60000,
|
|
29
31
|
timeout: 5000,
|
|
30
32
|
offlineFallback: true,
|
|
31
33
|
envPrefix: 'TOGGLELY_',
|
|
34
|
+
autoFetch: true,
|
|
35
|
+
offlineJsonPath: undefined,
|
|
32
36
|
...config
|
|
33
37
|
};
|
|
34
38
|
// Initialize event handlers
|
|
@@ -37,12 +41,21 @@
|
|
|
37
41
|
this.eventHandlers.set('error', new Set());
|
|
38
42
|
this.eventHandlers.set('offline', new Set());
|
|
39
43
|
this.eventHandlers.set('online', new Set());
|
|
44
|
+
// Set initial context if provided (including brandKey/tenantId)
|
|
45
|
+
const initialContext = { ...config.context };
|
|
46
|
+
if (config.brandKey)
|
|
47
|
+
initialContext.brandKey = config.brandKey;
|
|
48
|
+
if (config.tenantId)
|
|
49
|
+
initialContext.tenantId = config.tenantId;
|
|
50
|
+
this.context = initialContext;
|
|
40
51
|
// Load offline toggles first (if enabled)
|
|
41
52
|
if (this.config.offlineFallback) {
|
|
42
53
|
this.loadOfflineToggles();
|
|
43
54
|
}
|
|
44
|
-
//
|
|
45
|
-
this.
|
|
55
|
+
// Initial fetch (if enabled)
|
|
56
|
+
if (this.config.autoFetch) {
|
|
57
|
+
this.refresh();
|
|
58
|
+
}
|
|
46
59
|
}
|
|
47
60
|
// ==================== Event Handling ====================
|
|
48
61
|
on(event, handler) {
|
|
@@ -85,24 +98,49 @@
|
|
|
85
98
|
return this.state.isOffline;
|
|
86
99
|
}
|
|
87
100
|
// ==================== Toggle Accessors ====================
|
|
101
|
+
/**
|
|
102
|
+
* Check if a boolean feature flag is enabled
|
|
103
|
+
* @param key - The flag key
|
|
104
|
+
* @param defaultValue - Default value if flag not found
|
|
105
|
+
* @returns Promise<boolean>
|
|
106
|
+
*/
|
|
88
107
|
async isEnabled(key, defaultValue = false) {
|
|
89
108
|
const value = await this.getValue(key);
|
|
90
|
-
if (value === null)
|
|
109
|
+
if (value === null) {
|
|
91
110
|
return defaultValue;
|
|
111
|
+
}
|
|
92
112
|
return value.enabled && value.value === true;
|
|
93
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Get a string feature flag value
|
|
116
|
+
* @param key - The flag key
|
|
117
|
+
* @param defaultValue - Default value if flag not found or disabled
|
|
118
|
+
* @returns Promise<string>
|
|
119
|
+
*/
|
|
94
120
|
async getString(key, defaultValue = '') {
|
|
95
121
|
const value = await this.getValue(key);
|
|
96
122
|
if (value === null || !value.enabled)
|
|
97
123
|
return defaultValue;
|
|
98
124
|
return String(value.value);
|
|
99
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Get a number feature flag value
|
|
128
|
+
* @param key - The flag key
|
|
129
|
+
* @param defaultValue - Default value if flag not found or disabled
|
|
130
|
+
* @returns Promise<number>
|
|
131
|
+
*/
|
|
100
132
|
async getNumber(key, defaultValue = 0) {
|
|
101
133
|
const value = await this.getValue(key);
|
|
102
134
|
if (value === null || !value.enabled)
|
|
103
135
|
return defaultValue;
|
|
104
136
|
return Number(value.value);
|
|
105
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Get a JSON feature flag value
|
|
140
|
+
* @param key - The flag key
|
|
141
|
+
* @param defaultValue - Default value if flag not found or disabled
|
|
142
|
+
* @returns Promise<T>
|
|
143
|
+
*/
|
|
106
144
|
async getJSON(key, defaultValue = {}) {
|
|
107
145
|
const value = await this.getValue(key);
|
|
108
146
|
if (value === null || !value.enabled)
|
|
@@ -117,29 +155,41 @@
|
|
|
117
155
|
}
|
|
118
156
|
return value.value;
|
|
119
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* Get raw toggle value
|
|
160
|
+
* @param key - The flag key
|
|
161
|
+
* @returns Promise<ToggleValue | null>
|
|
162
|
+
*/
|
|
120
163
|
async getValue(key) {
|
|
121
|
-
// Try cache first
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
164
|
+
// Try cache first - but only if no context is set
|
|
165
|
+
if (Object.keys(this.context).length === 0) {
|
|
166
|
+
const cached = this.toggles.get(key);
|
|
167
|
+
if (cached) {
|
|
168
|
+
return cached;
|
|
169
|
+
}
|
|
125
170
|
}
|
|
126
171
|
// Fetch from server
|
|
127
172
|
try {
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
173
|
+
const params = new URLSearchParams();
|
|
174
|
+
if (this.config.apiKey)
|
|
175
|
+
params.set('apiKey', this.config.apiKey);
|
|
176
|
+
const brandKey = this.context.tenantId || this.context.brandKey;
|
|
177
|
+
if (brandKey)
|
|
178
|
+
params.set('tenantId', String(brandKey));
|
|
179
|
+
if (Object.keys(this.context).length > 0) {
|
|
180
|
+
params.set('context', JSON.stringify(this.context));
|
|
181
|
+
}
|
|
182
|
+
const query = params.toString() ? `?${params.toString()}` : '';
|
|
183
|
+
const url = `${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}/${encodeURIComponent(key)}${query}`;
|
|
184
|
+
const response = await this.fetchWithTimeout(url, { headers: { 'Content-Type': 'application/json' } });
|
|
134
185
|
if (!response.ok) {
|
|
135
186
|
if (response.status === 404) {
|
|
136
187
|
return null;
|
|
137
188
|
}
|
|
138
|
-
throw new Error(`HTTP ${response.status}`);
|
|
189
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
139
190
|
}
|
|
140
191
|
const data = await response.json();
|
|
141
192
|
this.toggles.set(key, data);
|
|
142
|
-
// Update state if we were offline
|
|
143
193
|
if (this.state.isOffline) {
|
|
144
194
|
this.state.isOffline = false;
|
|
145
195
|
this.emit('online');
|
|
@@ -148,14 +198,20 @@
|
|
|
148
198
|
}
|
|
149
199
|
catch (error) {
|
|
150
200
|
// Try offline fallback
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
201
|
+
if (this.config.offlineFallback) {
|
|
202
|
+
const offlineValue = this.getOfflineToggle(key);
|
|
203
|
+
if (offlineValue !== null) {
|
|
204
|
+
return offlineValue;
|
|
205
|
+
}
|
|
154
206
|
}
|
|
155
|
-
|
|
156
|
-
return
|
|
207
|
+
// Return safe default
|
|
208
|
+
return { value: false, enabled: false };
|
|
157
209
|
}
|
|
158
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Get all toggles
|
|
213
|
+
* @returns Record<string, ToggleValue>
|
|
214
|
+
*/
|
|
159
215
|
getAllToggles() {
|
|
160
216
|
const result = {};
|
|
161
217
|
this.toggles.forEach((value, key) => {
|
|
@@ -165,12 +221,28 @@
|
|
|
165
221
|
}
|
|
166
222
|
// ==================== Offline Fallback ====================
|
|
167
223
|
/**
|
|
168
|
-
* Load toggles from
|
|
169
|
-
*
|
|
224
|
+
* Load offline toggles from multiple sources (in priority order):
|
|
225
|
+
* 1. Inline offlineToggles from config
|
|
226
|
+
* 2. JSON file (if offlineJsonPath is set)
|
|
227
|
+
* 3. window.__TOGGLELY_TOGGLES (browser)
|
|
228
|
+
* 4. Environment variables (Node.js)
|
|
170
229
|
*/
|
|
171
230
|
loadOfflineToggles() {
|
|
172
231
|
try {
|
|
173
|
-
//
|
|
232
|
+
// Priority 1: Inline offline toggles from config
|
|
233
|
+
if (this.config.offlineToggles && Object.keys(this.config.offlineToggles).length > 0) {
|
|
234
|
+
for (const [key, value] of Object.entries(this.config.offlineToggles)) {
|
|
235
|
+
this.toggles.set(key, value);
|
|
236
|
+
}
|
|
237
|
+
this.offlineTogglesLoaded = true;
|
|
238
|
+
console.log('[Togglely] Loaded offline toggles from config');
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
// Priority 2: JSON file (browser only - fetch synchronously not possible, will try async)
|
|
242
|
+
if (this.config.offlineJsonPath && typeof window !== 'undefined') {
|
|
243
|
+
this.loadOfflineJsonFile(this.config.offlineJsonPath);
|
|
244
|
+
}
|
|
245
|
+
// Priority 3: Browser environment - check window.__TOGGLELY_TOGGLES
|
|
174
246
|
if (typeof window !== 'undefined' && window.__TOGGLELY_TOGGLES) {
|
|
175
247
|
const offlineToggles = window.__TOGGLELY_TOGGLES;
|
|
176
248
|
for (const [key, value] of Object.entries(offlineToggles)) {
|
|
@@ -180,12 +252,11 @@
|
|
|
180
252
|
console.log('[Togglely] Loaded offline toggles from window.__TOGGLELY_TOGGLES');
|
|
181
253
|
return;
|
|
182
254
|
}
|
|
183
|
-
// Node.js / Bun / Deno environment - check process.env
|
|
255
|
+
// Priority 4: Node.js / Bun / Deno environment - check process.env
|
|
184
256
|
if (typeof process !== 'undefined' && process.env) {
|
|
185
257
|
const prefix = this.config.envPrefix;
|
|
186
258
|
for (const [envKey, envValue] of Object.entries(process.env)) {
|
|
187
259
|
if (envKey?.startsWith(prefix) && envValue !== undefined) {
|
|
188
|
-
// Parse toggle key: TOGGLELY_MY_FEATURE -> my-feature
|
|
189
260
|
const toggleKey = envKey
|
|
190
261
|
.slice(prefix.length)
|
|
191
262
|
.toLowerCase()
|
|
@@ -201,13 +272,47 @@
|
|
|
201
272
|
console.warn('[Togglely] Failed to load offline toggles:', error);
|
|
202
273
|
}
|
|
203
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* Load offline toggles from JSON file (async)
|
|
277
|
+
*/
|
|
278
|
+
async loadOfflineJsonFile(path) {
|
|
279
|
+
try {
|
|
280
|
+
if (typeof window !== 'undefined') {
|
|
281
|
+
// Browser - fetch the JSON file
|
|
282
|
+
const response = await fetch(path);
|
|
283
|
+
if (response.ok) {
|
|
284
|
+
const data = await response.json();
|
|
285
|
+
for (const [key, value] of Object.entries(data)) {
|
|
286
|
+
this.toggles.set(key, this.parseOfflineValue(value));
|
|
287
|
+
}
|
|
288
|
+
this.offlineTogglesLoaded = true;
|
|
289
|
+
console.log('[Togglely] Loaded offline toggles from JSON file:', path);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
else if (typeof require !== 'undefined') {
|
|
293
|
+
// Node.js - require the JSON file
|
|
294
|
+
const fs = require('fs');
|
|
295
|
+
const pathModule = require('path');
|
|
296
|
+
const fullPath = pathModule.resolve(path);
|
|
297
|
+
if (fs.existsSync(fullPath)) {
|
|
298
|
+
const data = JSON.parse(fs.readFileSync(fullPath, 'utf-8'));
|
|
299
|
+
for (const [key, value] of Object.entries(data)) {
|
|
300
|
+
this.toggles.set(key, this.parseOfflineValue(value));
|
|
301
|
+
}
|
|
302
|
+
this.offlineTogglesLoaded = true;
|
|
303
|
+
console.log('[Togglely] Loaded offline toggles from JSON file:', fullPath);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
console.warn('[Togglely] Failed to load offline JSON file:', error);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
204
311
|
getOfflineToggle(key) {
|
|
205
312
|
if (!this.config.offlineFallback)
|
|
206
313
|
return null;
|
|
207
|
-
// Try to get from already loaded offline toggles
|
|
208
314
|
const cached = this.toggles.get(key);
|
|
209
315
|
if (cached) {
|
|
210
|
-
// If we haven't emitted offline event yet, do it now
|
|
211
316
|
if (!this.state.isOffline) {
|
|
212
317
|
this.state.isOffline = true;
|
|
213
318
|
this.emit('offline');
|
|
@@ -217,38 +322,41 @@
|
|
|
217
322
|
return null;
|
|
218
323
|
}
|
|
219
324
|
parseOfflineValue(value) {
|
|
220
|
-
// Handle boolean strings
|
|
221
325
|
if (typeof value === 'string') {
|
|
222
326
|
const lower = value.toLowerCase();
|
|
223
327
|
if (lower === 'true')
|
|
224
328
|
return { value: true, enabled: true };
|
|
225
329
|
if (lower === 'false')
|
|
226
330
|
return { value: false, enabled: true };
|
|
227
|
-
// Try to parse as number
|
|
228
331
|
if (!isNaN(Number(value))) {
|
|
229
332
|
return { value: Number(value), enabled: true };
|
|
230
333
|
}
|
|
231
|
-
// Try to parse as JSON
|
|
232
334
|
try {
|
|
233
335
|
const parsed = JSON.parse(value);
|
|
234
336
|
return { value: parsed, enabled: true };
|
|
235
337
|
}
|
|
236
338
|
catch {
|
|
237
|
-
// Return as string
|
|
238
339
|
return { value, enabled: true };
|
|
239
340
|
}
|
|
240
341
|
}
|
|
241
342
|
return { value, enabled: true };
|
|
242
343
|
}
|
|
243
344
|
// ==================== Refresh / Polling ====================
|
|
345
|
+
/**
|
|
346
|
+
* Refresh all toggles from the server
|
|
347
|
+
*/
|
|
244
348
|
async refresh() {
|
|
245
349
|
try {
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
350
|
+
const params = new URLSearchParams();
|
|
351
|
+
if (this.config.apiKey)
|
|
352
|
+
params.set('apiKey', this.config.apiKey);
|
|
353
|
+
const brandKey = this.context.tenantId || this.context.brandKey;
|
|
354
|
+
if (brandKey)
|
|
355
|
+
params.set('tenantId', String(brandKey));
|
|
356
|
+
if (Object.keys(this.context).length > 0) {
|
|
357
|
+
params.set('context', JSON.stringify(this.context));
|
|
358
|
+
}
|
|
359
|
+
const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}?${params.toString()}`, { headers: { 'Content-Type': 'application/json' } });
|
|
252
360
|
if (!response.ok) {
|
|
253
361
|
throw new Error(`HTTP ${response.status}`);
|
|
254
362
|
}
|
|
@@ -263,7 +371,6 @@
|
|
|
263
371
|
this.state.isReady = true;
|
|
264
372
|
this.emit('ready');
|
|
265
373
|
}
|
|
266
|
-
// If we were offline, go online
|
|
267
374
|
if (this.state.isOffline) {
|
|
268
375
|
this.state.isOffline = false;
|
|
269
376
|
this.emit('online');
|
|
@@ -272,7 +379,6 @@
|
|
|
272
379
|
}
|
|
273
380
|
catch (error) {
|
|
274
381
|
this.state.lastError = error;
|
|
275
|
-
// If we have offline toggles, switch to offline mode
|
|
276
382
|
if (this.config.offlineFallback && this.offlineTogglesLoaded) {
|
|
277
383
|
if (!this.state.isOffline) {
|
|
278
384
|
this.state.isOffline = true;
|
|
@@ -294,23 +400,10 @@
|
|
|
294
400
|
}
|
|
295
401
|
// ==================== Cleanup ====================
|
|
296
402
|
destroy() {
|
|
297
|
-
if (this.refreshTimer) {
|
|
298
|
-
clearInterval(this.refreshTimer);
|
|
299
|
-
}
|
|
300
403
|
this.toggles.clear();
|
|
301
404
|
this.eventHandlers.forEach(handlers => handlers.clear());
|
|
302
405
|
}
|
|
303
406
|
// ==================== Private Helpers ====================
|
|
304
|
-
startPolling() {
|
|
305
|
-
// Initial fetch
|
|
306
|
-
this.refresh();
|
|
307
|
-
// Set up polling
|
|
308
|
-
this.refreshTimer = setInterval(() => {
|
|
309
|
-
if (!this.state.isOffline) {
|
|
310
|
-
this.refresh();
|
|
311
|
-
}
|
|
312
|
-
}, this.config.refreshInterval);
|
|
313
|
-
}
|
|
314
407
|
fetchWithTimeout(url, options) {
|
|
315
408
|
return new Promise((resolve, reject) => {
|
|
316
409
|
const timeoutId = setTimeout(() => {
|
package/dist/index.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.js","sources":["../../core/dist/index.esm.js","../src/index.ts"],"sourcesContent":["/**\n * Togglely Core SDK - Framework agnostic\n *\n * Supports offline fallback via environment variables\n */\n/**\n * Core Togglely Client\n */\nclass TogglelyClient {\n constructor(config) {\n this.toggles = new Map();\n this.context = {};\n this.state = {\n isReady: false,\n isOffline: false,\n lastError: null,\n lastFetch: null\n };\n this.eventHandlers = new Map();\n this.offlineTogglesLoaded = false;\n this.config = {\n refreshInterval: 60000,\n timeout: 5000,\n offlineFallback: true,\n envPrefix: 'TOGGLELY_',\n ...config\n };\n // Initialize event handlers\n this.eventHandlers.set('ready', new Set());\n this.eventHandlers.set('update', new Set());\n this.eventHandlers.set('error', new Set());\n this.eventHandlers.set('offline', new Set());\n this.eventHandlers.set('online', new Set());\n // Load offline toggles first (if enabled)\n if (this.config.offlineFallback) {\n this.loadOfflineToggles();\n }\n // Start polling\n this.startPolling();\n }\n // ==================== Event Handling ====================\n on(event, handler) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.add(handler);\n }\n return () => this.off(event, handler);\n }\n off(event, handler) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.delete(handler);\n }\n }\n emit(event) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.forEach(handler => handler({ ...this.state }));\n }\n }\n // ==================== Context ====================\n setContext(context) {\n this.context = { ...this.context, ...context };\n }\n getContext() {\n return { ...this.context };\n }\n clearContext() {\n this.context = {};\n }\n // ==================== State ====================\n getState() {\n return { ...this.state };\n }\n isReady() {\n return this.state.isReady;\n }\n isOffline() {\n return this.state.isOffline;\n }\n // ==================== Toggle Accessors ====================\n async isEnabled(key, defaultValue = false) {\n const value = await this.getValue(key);\n if (value === null)\n return defaultValue;\n return value.enabled && value.value === true;\n }\n async getString(key, defaultValue = '') {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n return String(value.value);\n }\n async getNumber(key, defaultValue = 0) {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n return Number(value.value);\n }\n async getJSON(key, defaultValue = {}) {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n if (typeof value.value === 'string') {\n try {\n return JSON.parse(value.value);\n }\n catch {\n return defaultValue;\n }\n }\n return value.value;\n }\n async getValue(key) {\n // Try cache first\n const cached = this.toggles.get(key);\n if (cached) {\n return cached;\n }\n // Fetch from server\n try {\n const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${this.config.environment}/${key}`, {\n headers: {\n 'Authorization': `Bearer ${this.config.apiKey}`,\n 'Content-Type': 'application/json'\n }\n });\n if (!response.ok) {\n if (response.status === 404) {\n return null;\n }\n throw new Error(`HTTP ${response.status}`);\n }\n const data = await response.json();\n this.toggles.set(key, data);\n // Update state if we were offline\n if (this.state.isOffline) {\n this.state.isOffline = false;\n this.emit('online');\n }\n return data;\n }\n catch (error) {\n // Try offline fallback\n const offlineValue = this.getOfflineToggle(key);\n if (offlineValue !== null) {\n return offlineValue;\n }\n console.error(`[Togglely] Failed to fetch toggle \"${key}\":`, error);\n return null;\n }\n }\n getAllToggles() {\n const result = {};\n this.toggles.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n }\n // ==================== Offline Fallback ====================\n /**\n * Load toggles from environment variables\n * Format: TOGGLELY_<TOGGLE_KEY>=<value> or TOGGLELY_<TOGGLE_KEY>_ENABLED=true\n */\n loadOfflineToggles() {\n try {\n // Browser environment - check window.__TOGGLELY_TOGGLES\n if (typeof window !== 'undefined' && window.__TOGGLELY_TOGGLES) {\n const offlineToggles = window.__TOGGLELY_TOGGLES;\n for (const [key, value] of Object.entries(offlineToggles)) {\n this.toggles.set(key, this.parseOfflineValue(value));\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from window.__TOGGLELY_TOGGLES');\n return;\n }\n // Node.js / Bun / Deno environment - check process.env\n if (typeof process !== 'undefined' && process.env) {\n const prefix = this.config.envPrefix;\n for (const [envKey, envValue] of Object.entries(process.env)) {\n if (envKey?.startsWith(prefix) && envValue !== undefined) {\n // Parse toggle key: TOGGLELY_MY_FEATURE -> my-feature\n const toggleKey = envKey\n .slice(prefix.length)\n .toLowerCase()\n .replace(/_/g, '-');\n this.toggles.set(toggleKey, this.parseOfflineValue(envValue));\n }\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from environment variables');\n }\n }\n catch (error) {\n console.warn('[Togglely] Failed to load offline toggles:', error);\n }\n }\n getOfflineToggle(key) {\n if (!this.config.offlineFallback)\n return null;\n // Try to get from already loaded offline toggles\n const cached = this.toggles.get(key);\n if (cached) {\n // If we haven't emitted offline event yet, do it now\n if (!this.state.isOffline) {\n this.state.isOffline = true;\n this.emit('offline');\n }\n return cached;\n }\n return null;\n }\n parseOfflineValue(value) {\n // Handle boolean strings\n if (typeof value === 'string') {\n const lower = value.toLowerCase();\n if (lower === 'true')\n return { value: true, enabled: true };\n if (lower === 'false')\n return { value: false, enabled: true };\n // Try to parse as number\n if (!isNaN(Number(value))) {\n return { value: Number(value), enabled: true };\n }\n // Try to parse as JSON\n try {\n const parsed = JSON.parse(value);\n return { value: parsed, enabled: true };\n }\n catch {\n // Return as string\n return { value, enabled: true };\n }\n }\n return { value, enabled: true };\n }\n // ==================== Refresh / Polling ====================\n async refresh() {\n try {\n const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${this.config.environment}`, {\n headers: {\n 'Authorization': `Bearer ${this.config.apiKey}`,\n 'Content-Type': 'application/json'\n }\n });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n const data = await response.json();\n this.toggles.clear();\n for (const [key, value] of Object.entries(data)) {\n this.toggles.set(key, value);\n }\n this.state.lastFetch = new Date();\n this.state.lastError = null;\n if (!this.state.isReady) {\n this.state.isReady = true;\n this.emit('ready');\n }\n // If we were offline, go online\n if (this.state.isOffline) {\n this.state.isOffline = false;\n this.emit('online');\n }\n this.emit('update');\n }\n catch (error) {\n this.state.lastError = error;\n // If we have offline toggles, switch to offline mode\n if (this.config.offlineFallback && this.offlineTogglesLoaded) {\n if (!this.state.isOffline) {\n this.state.isOffline = true;\n this.emit('offline');\n }\n }\n this.emit('error');\n console.error('[Togglely] Failed to refresh toggles:', error);\n }\n }\n forceOfflineMode() {\n this.state.isOffline = true;\n this.emit('offline');\n }\n forceOnlineMode() {\n this.state.isOffline = false;\n this.refresh();\n this.emit('online');\n }\n // ==================== Cleanup ====================\n destroy() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n }\n this.toggles.clear();\n this.eventHandlers.forEach(handlers => handlers.clear());\n }\n // ==================== Private Helpers ====================\n startPolling() {\n // Initial fetch\n this.refresh();\n // Set up polling\n this.refreshTimer = setInterval(() => {\n if (!this.state.isOffline) {\n this.refresh();\n }\n }, this.config.refreshInterval);\n }\n fetchWithTimeout(url, options) {\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(new Error('Request timeout'));\n }, this.config.timeout);\n fetch(url, options)\n .then(response => {\n clearTimeout(timeoutId);\n resolve(response);\n })\n .catch(error => {\n clearTimeout(timeoutId);\n reject(error);\n });\n });\n }\n}\n// ==================== Utility Functions ====================\n/**\n * Create a client-side toggle loader script\n * Use this to inject offline toggles into your HTML\n */\nfunction createOfflineTogglesScript(toggles) {\n return `<script>window.__TOGGLELY_TOGGLES = ${JSON.stringify(toggles)};</script>`;\n}\n/**\n * Helper to convert toggles to environment variables\n */\nfunction togglesToEnvVars(toggles, prefix = 'TOGGLELY_') {\n const envVars = {};\n for (const [key, value] of Object.entries(toggles)) {\n const envKey = prefix + key.toUpperCase().replace(/-/g, '_');\n envVars[envKey] = typeof value === 'object' ? JSON.stringify(value) : String(value);\n }\n return envVars;\n}\n\nexport { TogglelyClient, createOfflineTogglesScript, TogglelyClient as default, togglesToEnvVars };\n//# sourceMappingURL=index.esm.js.map\n",null],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../../core/dist/index.esm.js","../src/index.ts"],"sourcesContent":["/**\n * Togglely Core SDK - Framework agnostic feature flag management\n *\n * Features:\n * - Real-time feature flag evaluation\n * - Offline fallback via JSON file, environment variables, or window object\n * - Multi-brand/tenant support\n * - Type-safe flag access\n * - Build-time JSON generation for offline-first deployment\n */\n// ==================== Togglely Client ====================\nclass TogglelyClient {\n constructor(config) {\n this.toggles = new Map();\n this.context = {};\n this.state = {\n isReady: false,\n isOffline: false,\n lastError: null,\n lastFetch: null\n };\n this.eventHandlers = new Map();\n this.offlineTogglesLoaded = false;\n this.config = {\n timeout: 5000,\n offlineFallback: true,\n envPrefix: 'TOGGLELY_',\n autoFetch: true,\n offlineJsonPath: undefined,\n ...config\n };\n // Initialize event handlers\n this.eventHandlers.set('ready', new Set());\n this.eventHandlers.set('update', new Set());\n this.eventHandlers.set('error', new Set());\n this.eventHandlers.set('offline', new Set());\n this.eventHandlers.set('online', new Set());\n // Set initial context if provided (including brandKey/tenantId)\n const initialContext = { ...config.context };\n if (config.brandKey)\n initialContext.brandKey = config.brandKey;\n if (config.tenantId)\n initialContext.tenantId = config.tenantId;\n this.context = initialContext;\n // Load offline toggles first (if enabled)\n if (this.config.offlineFallback) {\n this.loadOfflineToggles();\n }\n // Initial fetch (if enabled)\n if (this.config.autoFetch) {\n this.refresh();\n }\n }\n // ==================== Event Handling ====================\n on(event, handler) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.add(handler);\n }\n return () => this.off(event, handler);\n }\n off(event, handler) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.delete(handler);\n }\n }\n emit(event) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.forEach(handler => handler({ ...this.state }));\n }\n }\n // ==================== Context ====================\n setContext(context) {\n this.context = { ...this.context, ...context };\n }\n getContext() {\n return { ...this.context };\n }\n clearContext() {\n this.context = {};\n }\n // ==================== State ====================\n getState() {\n return { ...this.state };\n }\n isReady() {\n return this.state.isReady;\n }\n isOffline() {\n return this.state.isOffline;\n }\n // ==================== Toggle Accessors ====================\n /**\n * Check if a boolean feature flag is enabled\n * @param key - The flag key\n * @param defaultValue - Default value if flag not found\n * @returns Promise<boolean>\n */\n async isEnabled(key, defaultValue = false) {\n const value = await this.getValue(key);\n if (value === null) {\n return defaultValue;\n }\n return value.enabled && value.value === true;\n }\n /**\n * Get a string feature flag value\n * @param key - The flag key\n * @param defaultValue - Default value if flag not found or disabled\n * @returns Promise<string>\n */\n async getString(key, defaultValue = '') {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n return String(value.value);\n }\n /**\n * Get a number feature flag value\n * @param key - The flag key\n * @param defaultValue - Default value if flag not found or disabled\n * @returns Promise<number>\n */\n async getNumber(key, defaultValue = 0) {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n return Number(value.value);\n }\n /**\n * Get a JSON feature flag value\n * @param key - The flag key\n * @param defaultValue - Default value if flag not found or disabled\n * @returns Promise<T>\n */\n async getJSON(key, defaultValue = {}) {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n if (typeof value.value === 'string') {\n try {\n return JSON.parse(value.value);\n }\n catch {\n return defaultValue;\n }\n }\n return value.value;\n }\n /**\n * Get raw toggle value\n * @param key - The flag key\n * @returns Promise<ToggleValue | null>\n */\n async getValue(key) {\n // Try cache first - but only if no context is set\n if (Object.keys(this.context).length === 0) {\n const cached = this.toggles.get(key);\n if (cached) {\n return cached;\n }\n }\n // Fetch from server\n try {\n const params = new URLSearchParams();\n if (this.config.apiKey)\n params.set('apiKey', this.config.apiKey);\n const brandKey = this.context.tenantId || this.context.brandKey;\n if (brandKey)\n params.set('tenantId', String(brandKey));\n if (Object.keys(this.context).length > 0) {\n params.set('context', JSON.stringify(this.context));\n }\n const query = params.toString() ? `?${params.toString()}` : '';\n const url = `${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}/${encodeURIComponent(key)}${query}`;\n const response = await this.fetchWithTimeout(url, { headers: { 'Content-Type': 'application/json' } });\n if (!response.ok) {\n if (response.status === 404) {\n return null;\n }\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n const data = await response.json();\n this.toggles.set(key, data);\n if (this.state.isOffline) {\n this.state.isOffline = false;\n this.emit('online');\n }\n return data;\n }\n catch (error) {\n // Try offline fallback\n if (this.config.offlineFallback) {\n const offlineValue = this.getOfflineToggle(key);\n if (offlineValue !== null) {\n return offlineValue;\n }\n }\n // Return safe default\n return { value: false, enabled: false };\n }\n }\n /**\n * Get all toggles\n * @returns Record<string, ToggleValue>\n */\n getAllToggles() {\n const result = {};\n this.toggles.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n }\n // ==================== Offline Fallback ====================\n /**\n * Load offline toggles from multiple sources (in priority order):\n * 1. Inline offlineToggles from config\n * 2. JSON file (if offlineJsonPath is set)\n * 3. window.__TOGGLELY_TOGGLES (browser)\n * 4. Environment variables (Node.js)\n */\n loadOfflineToggles() {\n try {\n // Priority 1: Inline offline toggles from config\n if (this.config.offlineToggles && Object.keys(this.config.offlineToggles).length > 0) {\n for (const [key, value] of Object.entries(this.config.offlineToggles)) {\n this.toggles.set(key, value);\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from config');\n return;\n }\n // Priority 2: JSON file (browser only - fetch synchronously not possible, will try async)\n if (this.config.offlineJsonPath && typeof window !== 'undefined') {\n this.loadOfflineJsonFile(this.config.offlineJsonPath);\n }\n // Priority 3: Browser environment - check window.__TOGGLELY_TOGGLES\n if (typeof window !== 'undefined' && window.__TOGGLELY_TOGGLES) {\n const offlineToggles = window.__TOGGLELY_TOGGLES;\n for (const [key, value] of Object.entries(offlineToggles)) {\n this.toggles.set(key, this.parseOfflineValue(value));\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from window.__TOGGLELY_TOGGLES');\n return;\n }\n // Priority 4: Node.js / Bun / Deno environment - check process.env\n if (typeof process !== 'undefined' && process.env) {\n const prefix = this.config.envPrefix;\n for (const [envKey, envValue] of Object.entries(process.env)) {\n if (envKey?.startsWith(prefix) && envValue !== undefined) {\n const toggleKey = envKey\n .slice(prefix.length)\n .toLowerCase()\n .replace(/_/g, '-');\n this.toggles.set(toggleKey, this.parseOfflineValue(envValue));\n }\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from environment variables');\n }\n }\n catch (error) {\n console.warn('[Togglely] Failed to load offline toggles:', error);\n }\n }\n /**\n * Load offline toggles from JSON file (async)\n */\n async loadOfflineJsonFile(path) {\n try {\n if (typeof window !== 'undefined') {\n // Browser - fetch the JSON file\n const response = await fetch(path);\n if (response.ok) {\n const data = await response.json();\n for (const [key, value] of Object.entries(data)) {\n this.toggles.set(key, this.parseOfflineValue(value));\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from JSON file:', path);\n }\n }\n else if (typeof require !== 'undefined') {\n // Node.js - require the JSON file\n const fs = require('fs');\n const pathModule = require('path');\n const fullPath = pathModule.resolve(path);\n if (fs.existsSync(fullPath)) {\n const data = JSON.parse(fs.readFileSync(fullPath, 'utf-8'));\n for (const [key, value] of Object.entries(data)) {\n this.toggles.set(key, this.parseOfflineValue(value));\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from JSON file:', fullPath);\n }\n }\n }\n catch (error) {\n console.warn('[Togglely] Failed to load offline JSON file:', error);\n }\n }\n getOfflineToggle(key) {\n if (!this.config.offlineFallback)\n return null;\n const cached = this.toggles.get(key);\n if (cached) {\n if (!this.state.isOffline) {\n this.state.isOffline = true;\n this.emit('offline');\n }\n return cached;\n }\n return null;\n }\n parseOfflineValue(value) {\n if (typeof value === 'string') {\n const lower = value.toLowerCase();\n if (lower === 'true')\n return { value: true, enabled: true };\n if (lower === 'false')\n return { value: false, enabled: true };\n if (!isNaN(Number(value))) {\n return { value: Number(value), enabled: true };\n }\n try {\n const parsed = JSON.parse(value);\n return { value: parsed, enabled: true };\n }\n catch {\n return { value, enabled: true };\n }\n }\n return { value, enabled: true };\n }\n // ==================== Refresh / Polling ====================\n /**\n * Refresh all toggles from the server\n */\n async refresh() {\n try {\n const params = new URLSearchParams();\n if (this.config.apiKey)\n params.set('apiKey', this.config.apiKey);\n const brandKey = this.context.tenantId || this.context.brandKey;\n if (brandKey)\n params.set('tenantId', String(brandKey));\n if (Object.keys(this.context).length > 0) {\n params.set('context', JSON.stringify(this.context));\n }\n const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}?${params.toString()}`, { headers: { 'Content-Type': 'application/json' } });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n const data = await response.json();\n this.toggles.clear();\n for (const [key, value] of Object.entries(data)) {\n this.toggles.set(key, value);\n }\n this.state.lastFetch = new Date();\n this.state.lastError = null;\n if (!this.state.isReady) {\n this.state.isReady = true;\n this.emit('ready');\n }\n if (this.state.isOffline) {\n this.state.isOffline = false;\n this.emit('online');\n }\n this.emit('update');\n }\n catch (error) {\n this.state.lastError = error;\n if (this.config.offlineFallback && this.offlineTogglesLoaded) {\n if (!this.state.isOffline) {\n this.state.isOffline = true;\n this.emit('offline');\n }\n }\n this.emit('error');\n console.error('[Togglely] Failed to refresh toggles:', error);\n }\n }\n forceOfflineMode() {\n this.state.isOffline = true;\n this.emit('offline');\n }\n forceOnlineMode() {\n this.state.isOffline = false;\n this.refresh();\n this.emit('online');\n }\n // ==================== Cleanup ====================\n destroy() {\n this.toggles.clear();\n this.eventHandlers.forEach(handlers => handlers.clear());\n }\n // ==================== Private Helpers ====================\n fetchWithTimeout(url, options) {\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(new Error('Request timeout'));\n }, this.config.timeout);\n fetch(url, options)\n .then(response => {\n clearTimeout(timeoutId);\n resolve(response);\n })\n .catch(error => {\n clearTimeout(timeoutId);\n reject(error);\n });\n });\n }\n}\n// ==================== Utility Functions ====================\n/**\n * Create a client-side toggle loader script\n * Use this to inject offline toggles into your HTML\n */\nfunction createOfflineTogglesScript(toggles) {\n return `<script>window.__TOGGLELY_TOGGLES = ${JSON.stringify(toggles)};</script>`;\n}\n/**\n * Helper to convert toggles to environment variables\n */\nfunction togglesToEnvVars(toggles, prefix = 'TOGGLELY_') {\n const envVars = {};\n for (const [key, value] of Object.entries(toggles)) {\n const envKey = prefix + key.toUpperCase().replace(/-/g, '_');\n envVars[envKey] = typeof value === 'object' ? JSON.stringify(value) : String(value);\n }\n return envVars;\n}\n\nexport { TogglelyClient, createOfflineTogglesScript, TogglelyClient as default, togglesToEnvVars };\n//# sourceMappingURL=index.esm.js.map\n",null],"names":[],"mappings":"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"}
|
package/dist/index.umd.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Flagify={})}(this,function(e){"use strict";class t{constructor(e){this.toggles=new Map,this.context={},this.state={isReady:!1,isOffline:!1,lastError:null,lastFetch:null},this.eventHandlers=new Map,this.offlineTogglesLoaded=!1,this.config={
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Flagify={})}(this,function(e){"use strict";class t{constructor(e){this.toggles=new Map,this.context={},this.state={isReady:!1,isOffline:!1,lastError:null,lastFetch:null},this.eventHandlers=new Map,this.offlineTogglesLoaded=!1,this.config={timeout:5e3,offlineFallback:!0,envPrefix:"TOGGLELY_",autoFetch:!0,offlineJsonPath:void 0,...e},this.eventHandlers.set("ready",new Set),this.eventHandlers.set("update",new Set),this.eventHandlers.set("error",new Set),this.eventHandlers.set("offline",new Set),this.eventHandlers.set("online",new Set);const t={...e.context};e.brandKey&&(t.brandKey=e.brandKey),e.tenantId&&(t.tenantId=e.tenantId),this.context=t,this.config.offlineFallback&&this.loadOfflineToggles(),this.config.autoFetch&&this.refresh()}on(e,t){const n=this.eventHandlers.get(e);return n&&n.add(t),()=>this.off(e,t)}off(e,t){const n=this.eventHandlers.get(e);n&&n.delete(t)}emit(e){const t=this.eventHandlers.get(e);t&&t.forEach(e=>e({...this.state}))}setContext(e){this.context={...this.context,...e}}getContext(){return{...this.context}}clearContext(){this.context={}}getState(){return{...this.state}}isReady(){return this.state.isReady}isOffline(){return this.state.isOffline}async isEnabled(e,t=!1){const n=await this.getValue(e);return null===n?t:n.enabled&&!0===n.value}async getString(e,t=""){const n=await this.getValue(e);return null!==n&&n.enabled?String(n.value):t}async getNumber(e,t=0){const n=await this.getValue(e);return null!==n&&n.enabled?Number(n.value):t}async getJSON(e,t={}){const n=await this.getValue(e);if(null===n||!n.enabled)return t;if("string"==typeof n.value)try{return JSON.parse(n.value)}catch{return t}return n.value}async getValue(e){if(0===Object.keys(this.context).length){const t=this.toggles.get(e);if(t)return t}try{const t=new URLSearchParams;this.config.apiKey&&t.set("apiKey",this.config.apiKey);const n=this.context.tenantId||this.context.brandKey;n&&t.set("tenantId",String(n)),Object.keys(this.context).length>0&&t.set("context",JSON.stringify(this.context));const o=t.toString()?`?${t.toString()}`:"",s=`${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}/${encodeURIComponent(e)}${o}`,i=await this.fetchWithTimeout(s,{headers:{"Content-Type":"application/json"}});if(!i.ok){if(404===i.status)return null;throw new Error(`HTTP ${i.status}: ${i.statusText}`)}const l=await i.json();return this.toggles.set(e,l),this.state.isOffline&&(this.state.isOffline=!1,this.emit("online")),l}catch(t){if(this.config.offlineFallback){const t=this.getOfflineToggle(e);if(null!==t)return t}return{value:!1,enabled:!1}}}getAllToggles(){const e={};return this.toggles.forEach((t,n)=>{e[n]=t}),e}loadOfflineToggles(){try{if(this.config.offlineToggles&&Object.keys(this.config.offlineToggles).length>0){for(const[e,t]of Object.entries(this.config.offlineToggles))this.toggles.set(e,t);return this.offlineTogglesLoaded=!0,void console.log("[Togglely] Loaded offline toggles from config")}if(this.config.offlineJsonPath&&"undefined"!=typeof window&&this.loadOfflineJsonFile(this.config.offlineJsonPath),"undefined"!=typeof window&&window.__TOGGLELY_TOGGLES){const e=window.__TOGGLELY_TOGGLES;for(const[t,n]of Object.entries(e))this.toggles.set(t,this.parseOfflineValue(n));return this.offlineTogglesLoaded=!0,void console.log("[Togglely] Loaded offline toggles from window.__TOGGLELY_TOGGLES")}if("undefined"!=typeof process&&process.env){const e=this.config.envPrefix;for(const[t,n]of Object.entries(process.env))if(t?.startsWith(e)&&void 0!==n){const o=t.slice(e.length).toLowerCase().replace(/_/g,"-");this.toggles.set(o,this.parseOfflineValue(n))}this.offlineTogglesLoaded=!0,console.log("[Togglely] Loaded offline toggles from environment variables")}}catch(e){console.warn("[Togglely] Failed to load offline toggles:",e)}}async loadOfflineJsonFile(e){try{if("undefined"!=typeof window){const t=await fetch(e);if(t.ok){const n=await t.json();for(const[e,t]of Object.entries(n))this.toggles.set(e,this.parseOfflineValue(t));this.offlineTogglesLoaded=!0,console.log("[Togglely] Loaded offline toggles from JSON file:",e)}}else if("undefined"!=typeof require){const t=require("fs"),n=require("path").resolve(e);if(t.existsSync(n)){const e=JSON.parse(t.readFileSync(n,"utf-8"));for(const[t,n]of Object.entries(e))this.toggles.set(t,this.parseOfflineValue(n));this.offlineTogglesLoaded=!0,console.log("[Togglely] Loaded offline toggles from JSON file:",n)}}}catch(e){console.warn("[Togglely] Failed to load offline JSON file:",e)}}getOfflineToggle(e){if(!this.config.offlineFallback)return null;const t=this.toggles.get(e);return t?(this.state.isOffline||(this.state.isOffline=!0,this.emit("offline")),t):null}parseOfflineValue(e){if("string"==typeof e){const t=e.toLowerCase();if("true"===t)return{value:!0,enabled:!0};if("false"===t)return{value:!1,enabled:!0};if(!isNaN(Number(e)))return{value:Number(e),enabled:!0};try{return{value:JSON.parse(e),enabled:!0}}catch{return{value:e,enabled:!0}}}return{value:e,enabled:!0}}async refresh(){try{const e=new URLSearchParams;this.config.apiKey&&e.set("apiKey",this.config.apiKey);const t=this.context.tenantId||this.context.brandKey;t&&e.set("tenantId",String(t)),Object.keys(this.context).length>0&&e.set("context",JSON.stringify(this.context));const n=await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}?${e.toString()}`,{headers:{"Content-Type":"application/json"}});if(!n.ok)throw new Error(`HTTP ${n.status}`);const o=await n.json();this.toggles.clear();for(const[e,t]of Object.entries(o))this.toggles.set(e,t);this.state.lastFetch=new Date,this.state.lastError=null,this.state.isReady||(this.state.isReady=!0,this.emit("ready")),this.state.isOffline&&(this.state.isOffline=!1,this.emit("online")),this.emit("update")}catch(e){this.state.lastError=e,this.config.offlineFallback&&this.offlineTogglesLoaded&&(this.state.isOffline||(this.state.isOffline=!0,this.emit("offline"))),this.emit("error"),console.error("[Togglely] Failed to refresh toggles:",e)}}forceOfflineMode(){this.state.isOffline=!0,this.emit("offline")}forceOnlineMode(){this.state.isOffline=!1,this.refresh(),this.emit("online")}destroy(){this.toggles.clear(),this.eventHandlers.forEach(e=>e.clear())}fetchWithTimeout(e,t){return new Promise((n,o)=>{const s=setTimeout(()=>{o(new Error("Request timeout"))},this.config.timeout);fetch(e,t).then(e=>{clearTimeout(s),n(e)}).catch(e=>{clearTimeout(s),o(e)})})}}function n(){return"undefined"!=typeof window&&window.togglely||null}e.TogglelyClient=t,e.createOfflineTogglesScript=function(e){return`<script>window.__TOGGLELY_TOGGLES = ${JSON.stringify(e)};<\/script>`},e.default=t,e.getGlobalTogglely=n,e.getJSON=async function(e,t={}){const o=n();return o?o.getJSON(e,t):(console.error("[Togglely] No global instance found. Call initTogglely() first."),t)},e.getNumber=async function(e,t=0){const o=n();return o?o.getNumber(e,t):(console.error("[Togglely] No global instance found. Call initTogglely() first."),t)},e.getString=async function(e,t=""){const o=n();return o?o.getString(e,t):(console.error("[Togglely] No global instance found. Call initTogglely() first."),t)},e.initTogglely=function(e){const n=new t(e);return"undefined"!=typeof window&&(window.togglely=n),n},e.isEnabled=async function(e,t=!1){const o=n();return o?o.isEnabled(e,t):(console.error("[Togglely] No global instance found. Call initTogglely() first."),t)},e.togglelyInit=function(e){const t=n();if(!t)return console.error("[Togglely] No global instance found. Call initTogglely() first."),()=>{};const o=async()=>{for(const[n,o]of Object.entries(e)){let e,s=!1,i=!1;"string"==typeof o?e=[o]:Array.isArray(o)?e=o:(e=[o.selector],s=o.defaultValue??!1,i=o.invert??!1);const l=await t.isEnabled(n,s),r=i?!l:l;e.forEach(e=>{document.querySelectorAll(e).forEach(e=>{e.style.display=r?"":"none"})})}};return o(),t.on("update",o)},e.togglelyToggle=async function(e,t,o={}){const{defaultValue:s=!1,invert:i=!1,hideClass:l="togglely-hidden",showClass:r="togglely-visible"}=o,a=n();if(!a)return void console.error("[Togglely] No global instance found. Call initTogglely() first.");const f=await a.isEnabled(t,s),c=i?!f:f;document.querySelectorAll(e).forEach(e=>{c?(e.classList.remove(l),e.classList.add(r),e.style.display=""):(e.classList.remove(r),e.classList.add(l),e.style.display="none")})},e.togglesToEnvVars=function(e,t="TOGGLELY_"){const n={};for(const[o,s]of Object.entries(e)){n[t+o.toUpperCase().replace(/-/g,"_")]="object"==typeof s?JSON.stringify(s):String(s)}return n},Object.defineProperty(e,"__esModule",{value:!0})});
|
|
2
2
|
//# sourceMappingURL=index.umd.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.min.js","sources":["../../core/dist/index.esm.js","../src/index.ts"],"sourcesContent":["/**\n * Togglely Core SDK - Framework agnostic\n *\n * Supports offline fallback via environment variables\n */\n/**\n * Core Togglely Client\n */\nclass TogglelyClient {\n constructor(config) {\n this.toggles = new Map();\n this.context = {};\n this.state = {\n isReady: false,\n isOffline: false,\n lastError: null,\n lastFetch: null\n };\n this.eventHandlers = new Map();\n this.offlineTogglesLoaded = false;\n this.config = {\n refreshInterval: 60000,\n timeout: 5000,\n offlineFallback: true,\n envPrefix: 'TOGGLELY_',\n ...config\n };\n // Initialize event handlers\n this.eventHandlers.set('ready', new Set());\n this.eventHandlers.set('update', new Set());\n this.eventHandlers.set('error', new Set());\n this.eventHandlers.set('offline', new Set());\n this.eventHandlers.set('online', new Set());\n // Load offline toggles first (if enabled)\n if (this.config.offlineFallback) {\n this.loadOfflineToggles();\n }\n // Start polling\n this.startPolling();\n }\n // ==================== Event Handling ====================\n on(event, handler) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.add(handler);\n }\n return () => this.off(event, handler);\n }\n off(event, handler) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.delete(handler);\n }\n }\n emit(event) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.forEach(handler => handler({ ...this.state }));\n }\n }\n // ==================== Context ====================\n setContext(context) {\n this.context = { ...this.context, ...context };\n }\n getContext() {\n return { ...this.context };\n }\n clearContext() {\n this.context = {};\n }\n // ==================== State ====================\n getState() {\n return { ...this.state };\n }\n isReady() {\n return this.state.isReady;\n }\n isOffline() {\n return this.state.isOffline;\n }\n // ==================== Toggle Accessors ====================\n async isEnabled(key, defaultValue = false) {\n const value = await this.getValue(key);\n if (value === null)\n return defaultValue;\n return value.enabled && value.value === true;\n }\n async getString(key, defaultValue = '') {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n return String(value.value);\n }\n async getNumber(key, defaultValue = 0) {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n return Number(value.value);\n }\n async getJSON(key, defaultValue = {}) {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n if (typeof value.value === 'string') {\n try {\n return JSON.parse(value.value);\n }\n catch {\n return defaultValue;\n }\n }\n return value.value;\n }\n async getValue(key) {\n // Try cache first\n const cached = this.toggles.get(key);\n if (cached) {\n return cached;\n }\n // Fetch from server\n try {\n const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${this.config.environment}/${key}`, {\n headers: {\n 'Authorization': `Bearer ${this.config.apiKey}`,\n 'Content-Type': 'application/json'\n }\n });\n if (!response.ok) {\n if (response.status === 404) {\n return null;\n }\n throw new Error(`HTTP ${response.status}`);\n }\n const data = await response.json();\n this.toggles.set(key, data);\n // Update state if we were offline\n if (this.state.isOffline) {\n this.state.isOffline = false;\n this.emit('online');\n }\n return data;\n }\n catch (error) {\n // Try offline fallback\n const offlineValue = this.getOfflineToggle(key);\n if (offlineValue !== null) {\n return offlineValue;\n }\n console.error(`[Togglely] Failed to fetch toggle \"${key}\":`, error);\n return null;\n }\n }\n getAllToggles() {\n const result = {};\n this.toggles.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n }\n // ==================== Offline Fallback ====================\n /**\n * Load toggles from environment variables\n * Format: TOGGLELY_<TOGGLE_KEY>=<value> or TOGGLELY_<TOGGLE_KEY>_ENABLED=true\n */\n loadOfflineToggles() {\n try {\n // Browser environment - check window.__TOGGLELY_TOGGLES\n if (typeof window !== 'undefined' && window.__TOGGLELY_TOGGLES) {\n const offlineToggles = window.__TOGGLELY_TOGGLES;\n for (const [key, value] of Object.entries(offlineToggles)) {\n this.toggles.set(key, this.parseOfflineValue(value));\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from window.__TOGGLELY_TOGGLES');\n return;\n }\n // Node.js / Bun / Deno environment - check process.env\n if (typeof process !== 'undefined' && process.env) {\n const prefix = this.config.envPrefix;\n for (const [envKey, envValue] of Object.entries(process.env)) {\n if (envKey?.startsWith(prefix) && envValue !== undefined) {\n // Parse toggle key: TOGGLELY_MY_FEATURE -> my-feature\n const toggleKey = envKey\n .slice(prefix.length)\n .toLowerCase()\n .replace(/_/g, '-');\n this.toggles.set(toggleKey, this.parseOfflineValue(envValue));\n }\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from environment variables');\n }\n }\n catch (error) {\n console.warn('[Togglely] Failed to load offline toggles:', error);\n }\n }\n getOfflineToggle(key) {\n if (!this.config.offlineFallback)\n return null;\n // Try to get from already loaded offline toggles\n const cached = this.toggles.get(key);\n if (cached) {\n // If we haven't emitted offline event yet, do it now\n if (!this.state.isOffline) {\n this.state.isOffline = true;\n this.emit('offline');\n }\n return cached;\n }\n return null;\n }\n parseOfflineValue(value) {\n // Handle boolean strings\n if (typeof value === 'string') {\n const lower = value.toLowerCase();\n if (lower === 'true')\n return { value: true, enabled: true };\n if (lower === 'false')\n return { value: false, enabled: true };\n // Try to parse as number\n if (!isNaN(Number(value))) {\n return { value: Number(value), enabled: true };\n }\n // Try to parse as JSON\n try {\n const parsed = JSON.parse(value);\n return { value: parsed, enabled: true };\n }\n catch {\n // Return as string\n return { value, enabled: true };\n }\n }\n return { value, enabled: true };\n }\n // ==================== Refresh / Polling ====================\n async refresh() {\n try {\n const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${this.config.environment}`, {\n headers: {\n 'Authorization': `Bearer ${this.config.apiKey}`,\n 'Content-Type': 'application/json'\n }\n });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n const data = await response.json();\n this.toggles.clear();\n for (const [key, value] of Object.entries(data)) {\n this.toggles.set(key, value);\n }\n this.state.lastFetch = new Date();\n this.state.lastError = null;\n if (!this.state.isReady) {\n this.state.isReady = true;\n this.emit('ready');\n }\n // If we were offline, go online\n if (this.state.isOffline) {\n this.state.isOffline = false;\n this.emit('online');\n }\n this.emit('update');\n }\n catch (error) {\n this.state.lastError = error;\n // If we have offline toggles, switch to offline mode\n if (this.config.offlineFallback && this.offlineTogglesLoaded) {\n if (!this.state.isOffline) {\n this.state.isOffline = true;\n this.emit('offline');\n }\n }\n this.emit('error');\n console.error('[Togglely] Failed to refresh toggles:', error);\n }\n }\n forceOfflineMode() {\n this.state.isOffline = true;\n this.emit('offline');\n }\n forceOnlineMode() {\n this.state.isOffline = false;\n this.refresh();\n this.emit('online');\n }\n // ==================== Cleanup ====================\n destroy() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n }\n this.toggles.clear();\n this.eventHandlers.forEach(handlers => handlers.clear());\n }\n // ==================== Private Helpers ====================\n startPolling() {\n // Initial fetch\n this.refresh();\n // Set up polling\n this.refreshTimer = setInterval(() => {\n if (!this.state.isOffline) {\n this.refresh();\n }\n }, this.config.refreshInterval);\n }\n fetchWithTimeout(url, options) {\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(new Error('Request timeout'));\n }, this.config.timeout);\n fetch(url, options)\n .then(response => {\n clearTimeout(timeoutId);\n resolve(response);\n })\n .catch(error => {\n clearTimeout(timeoutId);\n reject(error);\n });\n });\n }\n}\n// ==================== Utility Functions ====================\n/**\n * Create a client-side toggle loader script\n * Use this to inject offline toggles into your HTML\n */\nfunction createOfflineTogglesScript(toggles) {\n return `<script>window.__TOGGLELY_TOGGLES = ${JSON.stringify(toggles)};</script>`;\n}\n/**\n * Helper to convert toggles to environment variables\n */\nfunction togglesToEnvVars(toggles, prefix = 'TOGGLELY_') {\n const envVars = {};\n for (const [key, value] of Object.entries(toggles)) {\n const envKey = prefix + key.toUpperCase().replace(/-/g, '_');\n envVars[envKey] = typeof value === 'object' ? JSON.stringify(value) : String(value);\n }\n return envVars;\n}\n\nexport { TogglelyClient, createOfflineTogglesScript, TogglelyClient as default, togglesToEnvVars };\n//# sourceMappingURL=index.esm.js.map\n",null],"names":["TogglelyClient","constructor","config","this","toggles","Map","context","state","isReady","isOffline","lastError","lastFetch","eventHandlers","offlineTogglesLoaded","refreshInterval","timeout","offlineFallback","envPrefix","set","Set","loadOfflineToggles","startPolling","on","event","handler","handlers","get","add","off","delete","emit","forEach","setContext","getContext","clearContext","getState","isEnabled","key","defaultValue","value","getValue","enabled","getString","String","getNumber","Number","getJSON","JSON","parse","cached","response","fetchWithTimeout","baseUrl","environment","headers","Authorization","apiKey","ok","status","Error","data","json","error","offlineValue","getOfflineToggle","console","getAllToggles","result","window","__TOGGLELY_TOGGLES","offlineToggles","Object","entries","parseOfflineValue","log","process","env","prefix","envKey","envValue","startsWith","undefined","toggleKey","slice","length","toLowerCase","replace","warn","lower","isNaN","refresh","clear","Date","forceOfflineMode","forceOnlineMode","destroy","refreshTimer","clearInterval","setInterval","url","options","Promise","resolve","reject","timeoutId","setTimeout","fetch","then","clearTimeout","catch","getGlobalTogglely","togglely","stringify","async","client","updateAll","selectors","invert","Array","isArray","selector","isToggleEnabled","shouldShow","document","querySelectorAll","el","style","display","hideClass","showClass","classList","remove","envVars","toUpperCase"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.umd.min.js","sources":["../../core/dist/index.esm.js","../src/index.ts"],"sourcesContent":["/**\n * Togglely Core SDK - Framework agnostic feature flag management\n *\n * Features:\n * - Real-time feature flag evaluation\n * - Offline fallback via JSON file, environment variables, or window object\n * - Multi-brand/tenant support\n * - Type-safe flag access\n * - Build-time JSON generation for offline-first deployment\n */\n// ==================== Togglely Client ====================\nclass TogglelyClient {\n constructor(config) {\n this.toggles = new Map();\n this.context = {};\n this.state = {\n isReady: false,\n isOffline: false,\n lastError: null,\n lastFetch: null\n };\n this.eventHandlers = new Map();\n this.offlineTogglesLoaded = false;\n this.config = {\n timeout: 5000,\n offlineFallback: true,\n envPrefix: 'TOGGLELY_',\n autoFetch: true,\n offlineJsonPath: undefined,\n ...config\n };\n // Initialize event handlers\n this.eventHandlers.set('ready', new Set());\n this.eventHandlers.set('update', new Set());\n this.eventHandlers.set('error', new Set());\n this.eventHandlers.set('offline', new Set());\n this.eventHandlers.set('online', new Set());\n // Set initial context if provided (including brandKey/tenantId)\n const initialContext = { ...config.context };\n if (config.brandKey)\n initialContext.brandKey = config.brandKey;\n if (config.tenantId)\n initialContext.tenantId = config.tenantId;\n this.context = initialContext;\n // Load offline toggles first (if enabled)\n if (this.config.offlineFallback) {\n this.loadOfflineToggles();\n }\n // Initial fetch (if enabled)\n if (this.config.autoFetch) {\n this.refresh();\n }\n }\n // ==================== Event Handling ====================\n on(event, handler) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.add(handler);\n }\n return () => this.off(event, handler);\n }\n off(event, handler) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.delete(handler);\n }\n }\n emit(event) {\n const handlers = this.eventHandlers.get(event);\n if (handlers) {\n handlers.forEach(handler => handler({ ...this.state }));\n }\n }\n // ==================== Context ====================\n setContext(context) {\n this.context = { ...this.context, ...context };\n }\n getContext() {\n return { ...this.context };\n }\n clearContext() {\n this.context = {};\n }\n // ==================== State ====================\n getState() {\n return { ...this.state };\n }\n isReady() {\n return this.state.isReady;\n }\n isOffline() {\n return this.state.isOffline;\n }\n // ==================== Toggle Accessors ====================\n /**\n * Check if a boolean feature flag is enabled\n * @param key - The flag key\n * @param defaultValue - Default value if flag not found\n * @returns Promise<boolean>\n */\n async isEnabled(key, defaultValue = false) {\n const value = await this.getValue(key);\n if (value === null) {\n return defaultValue;\n }\n return value.enabled && value.value === true;\n }\n /**\n * Get a string feature flag value\n * @param key - The flag key\n * @param defaultValue - Default value if flag not found or disabled\n * @returns Promise<string>\n */\n async getString(key, defaultValue = '') {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n return String(value.value);\n }\n /**\n * Get a number feature flag value\n * @param key - The flag key\n * @param defaultValue - Default value if flag not found or disabled\n * @returns Promise<number>\n */\n async getNumber(key, defaultValue = 0) {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n return Number(value.value);\n }\n /**\n * Get a JSON feature flag value\n * @param key - The flag key\n * @param defaultValue - Default value if flag not found or disabled\n * @returns Promise<T>\n */\n async getJSON(key, defaultValue = {}) {\n const value = await this.getValue(key);\n if (value === null || !value.enabled)\n return defaultValue;\n if (typeof value.value === 'string') {\n try {\n return JSON.parse(value.value);\n }\n catch {\n return defaultValue;\n }\n }\n return value.value;\n }\n /**\n * Get raw toggle value\n * @param key - The flag key\n * @returns Promise<ToggleValue | null>\n */\n async getValue(key) {\n // Try cache first - but only if no context is set\n if (Object.keys(this.context).length === 0) {\n const cached = this.toggles.get(key);\n if (cached) {\n return cached;\n }\n }\n // Fetch from server\n try {\n const params = new URLSearchParams();\n if (this.config.apiKey)\n params.set('apiKey', this.config.apiKey);\n const brandKey = this.context.tenantId || this.context.brandKey;\n if (brandKey)\n params.set('tenantId', String(brandKey));\n if (Object.keys(this.context).length > 0) {\n params.set('context', JSON.stringify(this.context));\n }\n const query = params.toString() ? `?${params.toString()}` : '';\n const url = `${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}/${encodeURIComponent(key)}${query}`;\n const response = await this.fetchWithTimeout(url, { headers: { 'Content-Type': 'application/json' } });\n if (!response.ok) {\n if (response.status === 404) {\n return null;\n }\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n const data = await response.json();\n this.toggles.set(key, data);\n if (this.state.isOffline) {\n this.state.isOffline = false;\n this.emit('online');\n }\n return data;\n }\n catch (error) {\n // Try offline fallback\n if (this.config.offlineFallback) {\n const offlineValue = this.getOfflineToggle(key);\n if (offlineValue !== null) {\n return offlineValue;\n }\n }\n // Return safe default\n return { value: false, enabled: false };\n }\n }\n /**\n * Get all toggles\n * @returns Record<string, ToggleValue>\n */\n getAllToggles() {\n const result = {};\n this.toggles.forEach((value, key) => {\n result[key] = value;\n });\n return result;\n }\n // ==================== Offline Fallback ====================\n /**\n * Load offline toggles from multiple sources (in priority order):\n * 1. Inline offlineToggles from config\n * 2. JSON file (if offlineJsonPath is set)\n * 3. window.__TOGGLELY_TOGGLES (browser)\n * 4. Environment variables (Node.js)\n */\n loadOfflineToggles() {\n try {\n // Priority 1: Inline offline toggles from config\n if (this.config.offlineToggles && Object.keys(this.config.offlineToggles).length > 0) {\n for (const [key, value] of Object.entries(this.config.offlineToggles)) {\n this.toggles.set(key, value);\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from config');\n return;\n }\n // Priority 2: JSON file (browser only - fetch synchronously not possible, will try async)\n if (this.config.offlineJsonPath && typeof window !== 'undefined') {\n this.loadOfflineJsonFile(this.config.offlineJsonPath);\n }\n // Priority 3: Browser environment - check window.__TOGGLELY_TOGGLES\n if (typeof window !== 'undefined' && window.__TOGGLELY_TOGGLES) {\n const offlineToggles = window.__TOGGLELY_TOGGLES;\n for (const [key, value] of Object.entries(offlineToggles)) {\n this.toggles.set(key, this.parseOfflineValue(value));\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from window.__TOGGLELY_TOGGLES');\n return;\n }\n // Priority 4: Node.js / Bun / Deno environment - check process.env\n if (typeof process !== 'undefined' && process.env) {\n const prefix = this.config.envPrefix;\n for (const [envKey, envValue] of Object.entries(process.env)) {\n if (envKey?.startsWith(prefix) && envValue !== undefined) {\n const toggleKey = envKey\n .slice(prefix.length)\n .toLowerCase()\n .replace(/_/g, '-');\n this.toggles.set(toggleKey, this.parseOfflineValue(envValue));\n }\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from environment variables');\n }\n }\n catch (error) {\n console.warn('[Togglely] Failed to load offline toggles:', error);\n }\n }\n /**\n * Load offline toggles from JSON file (async)\n */\n async loadOfflineJsonFile(path) {\n try {\n if (typeof window !== 'undefined') {\n // Browser - fetch the JSON file\n const response = await fetch(path);\n if (response.ok) {\n const data = await response.json();\n for (const [key, value] of Object.entries(data)) {\n this.toggles.set(key, this.parseOfflineValue(value));\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from JSON file:', path);\n }\n }\n else if (typeof require !== 'undefined') {\n // Node.js - require the JSON file\n const fs = require('fs');\n const pathModule = require('path');\n const fullPath = pathModule.resolve(path);\n if (fs.existsSync(fullPath)) {\n const data = JSON.parse(fs.readFileSync(fullPath, 'utf-8'));\n for (const [key, value] of Object.entries(data)) {\n this.toggles.set(key, this.parseOfflineValue(value));\n }\n this.offlineTogglesLoaded = true;\n console.log('[Togglely] Loaded offline toggles from JSON file:', fullPath);\n }\n }\n }\n catch (error) {\n console.warn('[Togglely] Failed to load offline JSON file:', error);\n }\n }\n getOfflineToggle(key) {\n if (!this.config.offlineFallback)\n return null;\n const cached = this.toggles.get(key);\n if (cached) {\n if (!this.state.isOffline) {\n this.state.isOffline = true;\n this.emit('offline');\n }\n return cached;\n }\n return null;\n }\n parseOfflineValue(value) {\n if (typeof value === 'string') {\n const lower = value.toLowerCase();\n if (lower === 'true')\n return { value: true, enabled: true };\n if (lower === 'false')\n return { value: false, enabled: true };\n if (!isNaN(Number(value))) {\n return { value: Number(value), enabled: true };\n }\n try {\n const parsed = JSON.parse(value);\n return { value: parsed, enabled: true };\n }\n catch {\n return { value, enabled: true };\n }\n }\n return { value, enabled: true };\n }\n // ==================== Refresh / Polling ====================\n /**\n * Refresh all toggles from the server\n */\n async refresh() {\n try {\n const params = new URLSearchParams();\n if (this.config.apiKey)\n params.set('apiKey', this.config.apiKey);\n const brandKey = this.context.tenantId || this.context.brandKey;\n if (brandKey)\n params.set('tenantId', String(brandKey));\n if (Object.keys(this.context).length > 0) {\n params.set('context', JSON.stringify(this.context));\n }\n const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}?${params.toString()}`, { headers: { 'Content-Type': 'application/json' } });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n const data = await response.json();\n this.toggles.clear();\n for (const [key, value] of Object.entries(data)) {\n this.toggles.set(key, value);\n }\n this.state.lastFetch = new Date();\n this.state.lastError = null;\n if (!this.state.isReady) {\n this.state.isReady = true;\n this.emit('ready');\n }\n if (this.state.isOffline) {\n this.state.isOffline = false;\n this.emit('online');\n }\n this.emit('update');\n }\n catch (error) {\n this.state.lastError = error;\n if (this.config.offlineFallback && this.offlineTogglesLoaded) {\n if (!this.state.isOffline) {\n this.state.isOffline = true;\n this.emit('offline');\n }\n }\n this.emit('error');\n console.error('[Togglely] Failed to refresh toggles:', error);\n }\n }\n forceOfflineMode() {\n this.state.isOffline = true;\n this.emit('offline');\n }\n forceOnlineMode() {\n this.state.isOffline = false;\n this.refresh();\n this.emit('online');\n }\n // ==================== Cleanup ====================\n destroy() {\n this.toggles.clear();\n this.eventHandlers.forEach(handlers => handlers.clear());\n }\n // ==================== Private Helpers ====================\n fetchWithTimeout(url, options) {\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(new Error('Request timeout'));\n }, this.config.timeout);\n fetch(url, options)\n .then(response => {\n clearTimeout(timeoutId);\n resolve(response);\n })\n .catch(error => {\n clearTimeout(timeoutId);\n reject(error);\n });\n });\n }\n}\n// ==================== Utility Functions ====================\n/**\n * Create a client-side toggle loader script\n * Use this to inject offline toggles into your HTML\n */\nfunction createOfflineTogglesScript(toggles) {\n return `<script>window.__TOGGLELY_TOGGLES = ${JSON.stringify(toggles)};</script>`;\n}\n/**\n * Helper to convert toggles to environment variables\n */\nfunction togglesToEnvVars(toggles, prefix = 'TOGGLELY_') {\n const envVars = {};\n for (const [key, value] of Object.entries(toggles)) {\n const envKey = prefix + key.toUpperCase().replace(/-/g, '_');\n envVars[envKey] = typeof value === 'object' ? JSON.stringify(value) : String(value);\n }\n return envVars;\n}\n\nexport { TogglelyClient, createOfflineTogglesScript, TogglelyClient as default, togglesToEnvVars };\n//# sourceMappingURL=index.esm.js.map\n",null],"names":["TogglelyClient","constructor","config","this","toggles","Map","context","state","isReady","isOffline","lastError","lastFetch","eventHandlers","offlineTogglesLoaded","timeout","offlineFallback","envPrefix","autoFetch","offlineJsonPath","undefined","set","Set","initialContext","brandKey","tenantId","loadOfflineToggles","refresh","on","event","handler","handlers","get","add","off","delete","emit","forEach","setContext","getContext","clearContext","getState","isEnabled","key","defaultValue","value","getValue","enabled","getString","String","getNumber","Number","getJSON","JSON","parse","Object","keys","length","cached","params","URLSearchParams","apiKey","stringify","query","toString","url","baseUrl","encodeURIComponent","project","environment","response","fetchWithTimeout","headers","ok","status","Error","statusText","data","json","error","offlineValue","getOfflineToggle","getAllToggles","result","offlineToggles","entries","console","log","window","loadOfflineJsonFile","__TOGGLELY_TOGGLES","parseOfflineValue","process","env","prefix","envKey","envValue","startsWith","toggleKey","slice","toLowerCase","replace","warn","path","fetch","require","fs","fullPath","resolve","existsSync","readFileSync","lower","isNaN","clear","Date","forceOfflineMode","forceOnlineMode","destroy","options","Promise","reject","timeoutId","setTimeout","then","clearTimeout","catch","getGlobalTogglely","togglely","async","client","updateAll","selectors","invert","Array","isArray","selector","isToggleEnabled","shouldShow","document","querySelectorAll","el","style","display","hideClass","showClass","classList","remove","envVars","toUpperCase"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@togglely/sdk",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Vanilla JavaScript SDK for Togglely - Feature toggles for any framework",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.esm.js",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
|
-
"unpkg": "dist/index.umd.js",
|
|
9
|
-
"files": [
|
|
10
|
-
"dist"
|
|
11
|
-
],
|
|
12
|
-
"scripts": {
|
|
13
|
-
"build": "tsc && rollup -c",
|
|
14
|
-
"test": "jest"
|
|
15
|
-
},
|
|
16
|
-
"keywords": [
|
|
17
|
-
"feature-flags",
|
|
18
|
-
"feature-toggles",
|
|
19
|
-
"togglely",
|
|
20
|
-
"vanilla",
|
|
21
|
-
"javascript"
|
|
22
|
-
],
|
|
23
|
-
"author": "Togglely",
|
|
24
|
-
"license": "MIT",
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"@togglely/sdk-core": "^1.0.0"
|
|
27
|
-
},
|
|
28
|
-
"devDependencies": {
|
|
29
|
-
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
30
|
-
"@rollup/plugin-terser": "^0.4.4",
|
|
31
|
-
"@rollup/plugin-typescript": "^11.1.5",
|
|
32
|
-
"rollup": "^4.9.1",
|
|
33
|
-
"tslib": "^2.6.2",
|
|
34
|
-
"typescript": "^5.3.3"
|
|
35
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@togglely/sdk",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Vanilla JavaScript SDK for Togglely - Feature toggles for any framework",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.esm.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"unpkg": "dist/index.umd.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc && rollup -c",
|
|
14
|
+
"test": "jest"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"feature-flags",
|
|
18
|
+
"feature-toggles",
|
|
19
|
+
"togglely",
|
|
20
|
+
"vanilla",
|
|
21
|
+
"javascript"
|
|
22
|
+
],
|
|
23
|
+
"author": "Togglely",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@togglely/sdk-core": "^1.0.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
30
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
31
|
+
"@rollup/plugin-typescript": "^11.1.5",
|
|
32
|
+
"rollup": "^4.9.1",
|
|
33
|
+
"tslib": "^2.6.2",
|
|
34
|
+
"typescript": "^5.3.3"
|
|
35
|
+
}
|
|
36
36
|
}
|