@togglely/sdk 1.1.7 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +210 -38
- package/dist/index.umd.js +154 -56
- 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,65 +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
4
|
|
|
5
|
-
|
|
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
|
|
6
12
|
|
|
7
13
|
## Installation
|
|
8
14
|
|
|
15
|
+
### NPM
|
|
16
|
+
|
|
9
17
|
```bash
|
|
10
18
|
npm install @togglely/sdk
|
|
11
19
|
```
|
|
12
20
|
|
|
13
|
-
|
|
21
|
+
### CDN
|
|
14
22
|
|
|
15
23
|
```html
|
|
16
24
|
<script src="https://unpkg.com/@togglely/sdk/dist/index.umd.min.js"></script>
|
|
17
25
|
```
|
|
18
26
|
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
### ES Modules
|
|
22
|
-
|
|
23
|
-
```javascript
|
|
24
|
-
import { TogglelyClient } from '@togglely/sdk';
|
|
25
|
-
|
|
26
|
-
const client = new TogglelyClient({
|
|
27
|
-
apiKey: 'your-api-key',
|
|
28
|
-
environment: 'production',
|
|
29
|
-
baseUrl: 'https://your-togglely-instance.com'
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
const isEnabled = await client.isEnabled('new-feature', false);
|
|
33
|
-
```
|
|
27
|
+
## Quick Start
|
|
34
28
|
|
|
35
|
-
###
|
|
29
|
+
### Browser (Module)
|
|
36
30
|
|
|
37
31
|
```javascript
|
|
38
32
|
import { initTogglely, isEnabled } from '@togglely/sdk';
|
|
39
33
|
|
|
40
|
-
// Initialize
|
|
34
|
+
// Initialize
|
|
41
35
|
initTogglely({
|
|
42
36
|
apiKey: 'your-api-key',
|
|
37
|
+
project: 'my-project',
|
|
43
38
|
environment: 'production',
|
|
44
|
-
baseUrl: 'https://
|
|
39
|
+
baseUrl: 'https://togglely.io',
|
|
45
40
|
});
|
|
46
41
|
|
|
47
42
|
// Use global helpers
|
|
48
|
-
const
|
|
43
|
+
const newFeature = await isEnabled('new-feature', false);
|
|
44
|
+
if (newFeature) {
|
|
45
|
+
document.getElementById('new-feature').style.display = 'block';
|
|
46
|
+
}
|
|
49
47
|
```
|
|
50
48
|
|
|
51
|
-
### CDN
|
|
49
|
+
### Browser (CDN)
|
|
52
50
|
|
|
53
51
|
```html
|
|
54
52
|
<script src="https://unpkg.com/@togglely/sdk/dist/index.umd.min.js"></script>
|
|
55
53
|
<script>
|
|
56
|
-
|
|
54
|
+
Togglely.initTogglely({
|
|
57
55
|
apiKey: 'your-api-key',
|
|
56
|
+
project: 'my-project',
|
|
58
57
|
environment: 'production',
|
|
59
|
-
baseUrl: 'https://
|
|
58
|
+
baseUrl: 'https://togglely.io',
|
|
60
59
|
});
|
|
61
60
|
|
|
62
|
-
|
|
61
|
+
Togglely.isEnabled('new-feature').then(function(enabled) {
|
|
63
62
|
if (enabled) {
|
|
64
63
|
document.getElementById('new-feature').style.display = 'block';
|
|
65
64
|
}
|
|
@@ -67,26 +66,199 @@ const enabled = await isEnabled('new-feature', false);
|
|
|
67
66
|
</script>
|
|
68
67
|
```
|
|
69
68
|
|
|
70
|
-
###
|
|
69
|
+
### Node.js
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
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
|
+
});
|
|
80
|
+
|
|
81
|
+
const isEnabled = await client.isEnabled('new-feature', false);
|
|
82
|
+
console.log('New feature:', isEnabled);
|
|
83
|
+
```
|
|
84
|
+
|
|
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:
|
|
71
102
|
|
|
72
103
|
```javascript
|
|
73
|
-
import {
|
|
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
|
+
```
|
|
74
118
|
|
|
75
|
-
|
|
76
|
-
togglelyToggle('#new-feature', 'new-feature');
|
|
119
|
+
## DOM Helpers
|
|
77
120
|
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
80
147
|
'new-feature': ['.new-feature', '.new-banner'],
|
|
81
|
-
|
|
148
|
+
|
|
149
|
+
// With options
|
|
82
150
|
'premium': {
|
|
83
151
|
selector: '.premium-content',
|
|
84
|
-
defaultValue: false
|
|
85
|
-
|
|
152
|
+
defaultValue: false
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
// Invert (hide when enabled)
|
|
156
|
+
'new-ui': {
|
|
157
|
+
selector: '.old-ui',
|
|
158
|
+
invert: true
|
|
86
159
|
}
|
|
87
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
|
+
}
|
|
88
260
|
```
|
|
89
261
|
|
|
90
|
-
##
|
|
262
|
+
## License
|
|
91
263
|
|
|
92
|
-
|
|
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();
|
|
@@ -29,6 +32,7 @@
|
|
|
29
32
|
offlineFallback: true,
|
|
30
33
|
envPrefix: 'TOGGLELY_',
|
|
31
34
|
autoFetch: true,
|
|
35
|
+
offlineJsonPath: undefined,
|
|
32
36
|
...config
|
|
33
37
|
};
|
|
34
38
|
// Initialize event handlers
|
|
@@ -37,6 +41,13 @@
|
|
|
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();
|
|
@@ -87,24 +98,56 @@
|
|
|
87
98
|
return this.state.isOffline;
|
|
88
99
|
}
|
|
89
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
|
+
*/
|
|
90
107
|
async isEnabled(key, defaultValue = false) {
|
|
91
108
|
const value = await this.getValue(key);
|
|
92
|
-
if (value === null)
|
|
109
|
+
if (value === null) {
|
|
93
110
|
return defaultValue;
|
|
94
|
-
|
|
111
|
+
}
|
|
112
|
+
// enabled is the primary on/off switch for a flag.
|
|
113
|
+
// value.value holds the flag's configured value (used for non-boolean use-cases).
|
|
114
|
+
// For boolean flags: if enabled, return the boolean value itself.
|
|
115
|
+
// If the value is not a boolean (misconfigured), fall back to just enabled.
|
|
116
|
+
if (typeof value.value === 'boolean') {
|
|
117
|
+
return value.enabled && value.value;
|
|
118
|
+
}
|
|
119
|
+
return value.enabled;
|
|
95
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Get a string feature flag value
|
|
123
|
+
* @param key - The flag key
|
|
124
|
+
* @param defaultValue - Default value if flag not found or disabled
|
|
125
|
+
* @returns Promise<string>
|
|
126
|
+
*/
|
|
96
127
|
async getString(key, defaultValue = '') {
|
|
97
128
|
const value = await this.getValue(key);
|
|
98
129
|
if (value === null || !value.enabled)
|
|
99
130
|
return defaultValue;
|
|
100
131
|
return String(value.value);
|
|
101
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Get a number feature flag value
|
|
135
|
+
* @param key - The flag key
|
|
136
|
+
* @param defaultValue - Default value if flag not found or disabled
|
|
137
|
+
* @returns Promise<number>
|
|
138
|
+
*/
|
|
102
139
|
async getNumber(key, defaultValue = 0) {
|
|
103
140
|
const value = await this.getValue(key);
|
|
104
141
|
if (value === null || !value.enabled)
|
|
105
142
|
return defaultValue;
|
|
106
143
|
return Number(value.value);
|
|
107
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Get a JSON feature flag value
|
|
147
|
+
* @param key - The flag key
|
|
148
|
+
* @param defaultValue - Default value if flag not found or disabled
|
|
149
|
+
* @returns Promise<T>
|
|
150
|
+
*/
|
|
108
151
|
async getJSON(key, defaultValue = {}) {
|
|
109
152
|
const value = await this.getValue(key);
|
|
110
153
|
if (value === null || !value.enabled)
|
|
@@ -119,40 +162,43 @@
|
|
|
119
162
|
}
|
|
120
163
|
return value.value;
|
|
121
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Get raw toggle value
|
|
167
|
+
* @param key - The flag key
|
|
168
|
+
* @returns Promise<ToggleValue | null>
|
|
169
|
+
*/
|
|
122
170
|
async getValue(key) {
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (cached) {
|
|
127
|
-
return cached;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
171
|
+
// Note: We intentionally do NOT use cache here to always get fresh values
|
|
172
|
+
// The cache is only used for offline fallback and getAllToggles()
|
|
173
|
+
// If you need cached values, use getAllToggles() instead
|
|
130
174
|
// Fetch from server
|
|
131
175
|
try {
|
|
132
176
|
const params = new URLSearchParams();
|
|
133
|
-
|
|
134
|
-
if (brandKey)
|
|
135
|
-
params.set('brandKey', String(brandKey));
|
|
136
|
-
|
|
177
|
+
// Support both brandKey and tenantId for maximum compatibility
|
|
178
|
+
if (this.context.brandKey)
|
|
179
|
+
params.set('brandKey', String(this.context.brandKey));
|
|
180
|
+
if (this.context.tenantId)
|
|
181
|
+
params.set('tenantId', String(this.context.tenantId));
|
|
137
182
|
if (Object.keys(this.context).length > 0) {
|
|
138
183
|
params.set('context', JSON.stringify(this.context));
|
|
139
184
|
}
|
|
140
185
|
const query = params.toString() ? `?${params.toString()}` : '';
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
186
|
+
const url = `${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}/${encodeURIComponent(key)}${query}`;
|
|
187
|
+
const headers = {
|
|
188
|
+
'Content-Type': 'application/json'
|
|
189
|
+
};
|
|
190
|
+
if (this.config.apiKey) {
|
|
191
|
+
headers['Authorization'] = `Bearer ${this.config.apiKey}`;
|
|
192
|
+
}
|
|
193
|
+
const response = await this.fetchWithTimeout(url, { headers });
|
|
147
194
|
if (!response.ok) {
|
|
148
195
|
if (response.status === 404) {
|
|
149
196
|
return null;
|
|
150
197
|
}
|
|
151
|
-
throw new Error(`HTTP ${response.status}`);
|
|
198
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
152
199
|
}
|
|
153
200
|
const data = await response.json();
|
|
154
201
|
this.toggles.set(key, data);
|
|
155
|
-
// Update state if we were offline
|
|
156
202
|
if (this.state.isOffline) {
|
|
157
203
|
this.state.isOffline = false;
|
|
158
204
|
this.emit('online');
|
|
@@ -161,14 +207,20 @@
|
|
|
161
207
|
}
|
|
162
208
|
catch (error) {
|
|
163
209
|
// Try offline fallback
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
210
|
+
if (this.config.offlineFallback) {
|
|
211
|
+
const offlineValue = this.getOfflineToggle(key);
|
|
212
|
+
if (offlineValue !== null) {
|
|
213
|
+
return offlineValue;
|
|
214
|
+
}
|
|
167
215
|
}
|
|
168
|
-
|
|
169
|
-
return
|
|
216
|
+
// Return safe default
|
|
217
|
+
return { value: false, enabled: false };
|
|
170
218
|
}
|
|
171
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Get all toggles
|
|
222
|
+
* @returns Record<string, ToggleValue>
|
|
223
|
+
*/
|
|
172
224
|
getAllToggles() {
|
|
173
225
|
const result = {};
|
|
174
226
|
this.toggles.forEach((value, key) => {
|
|
@@ -178,12 +230,28 @@
|
|
|
178
230
|
}
|
|
179
231
|
// ==================== Offline Fallback ====================
|
|
180
232
|
/**
|
|
181
|
-
* Load toggles from
|
|
182
|
-
*
|
|
233
|
+
* Load offline toggles from multiple sources (in priority order):
|
|
234
|
+
* 1. Inline offlineToggles from config
|
|
235
|
+
* 2. JSON file (if offlineJsonPath is set)
|
|
236
|
+
* 3. window.__TOGGLELY_TOGGLES (browser)
|
|
237
|
+
* 4. Environment variables (Node.js)
|
|
183
238
|
*/
|
|
184
239
|
loadOfflineToggles() {
|
|
185
240
|
try {
|
|
186
|
-
//
|
|
241
|
+
// Priority 1: Inline offline toggles from config
|
|
242
|
+
if (this.config.offlineToggles && Object.keys(this.config.offlineToggles).length > 0) {
|
|
243
|
+
for (const [key, value] of Object.entries(this.config.offlineToggles)) {
|
|
244
|
+
this.toggles.set(key, value);
|
|
245
|
+
}
|
|
246
|
+
this.offlineTogglesLoaded = true;
|
|
247
|
+
console.log('[Togglely] Loaded offline toggles from config');
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
// Priority 2: JSON file (browser only - fetch synchronously not possible, will try async)
|
|
251
|
+
if (this.config.offlineJsonPath && typeof window !== 'undefined') {
|
|
252
|
+
this.loadOfflineJsonFile(this.config.offlineJsonPath);
|
|
253
|
+
}
|
|
254
|
+
// Priority 3: Browser environment - check window.__TOGGLELY_TOGGLES
|
|
187
255
|
if (typeof window !== 'undefined' && window.__TOGGLELY_TOGGLES) {
|
|
188
256
|
const offlineToggles = window.__TOGGLELY_TOGGLES;
|
|
189
257
|
for (const [key, value] of Object.entries(offlineToggles)) {
|
|
@@ -193,12 +261,11 @@
|
|
|
193
261
|
console.log('[Togglely] Loaded offline toggles from window.__TOGGLELY_TOGGLES');
|
|
194
262
|
return;
|
|
195
263
|
}
|
|
196
|
-
// Node.js / Bun / Deno environment - check process.env
|
|
264
|
+
// Priority 4: Node.js / Bun / Deno environment - check process.env
|
|
197
265
|
if (typeof process !== 'undefined' && process.env) {
|
|
198
266
|
const prefix = this.config.envPrefix;
|
|
199
267
|
for (const [envKey, envValue] of Object.entries(process.env)) {
|
|
200
268
|
if (envKey?.startsWith(prefix) && envValue !== undefined) {
|
|
201
|
-
// Parse toggle key: TOGGLELY_MY_FEATURE -> my-feature
|
|
202
269
|
const toggleKey = envKey
|
|
203
270
|
.slice(prefix.length)
|
|
204
271
|
.toLowerCase()
|
|
@@ -214,13 +281,47 @@
|
|
|
214
281
|
console.warn('[Togglely] Failed to load offline toggles:', error);
|
|
215
282
|
}
|
|
216
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Load offline toggles from JSON file (async)
|
|
286
|
+
*/
|
|
287
|
+
async loadOfflineJsonFile(path) {
|
|
288
|
+
try {
|
|
289
|
+
if (typeof window !== 'undefined') {
|
|
290
|
+
// Browser - fetch the JSON file
|
|
291
|
+
const response = await fetch(path);
|
|
292
|
+
if (response.ok) {
|
|
293
|
+
const data = await response.json();
|
|
294
|
+
for (const [key, value] of Object.entries(data)) {
|
|
295
|
+
this.toggles.set(key, this.parseOfflineValue(value));
|
|
296
|
+
}
|
|
297
|
+
this.offlineTogglesLoaded = true;
|
|
298
|
+
console.log('[Togglely] Loaded offline toggles from JSON file:', path);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else if (typeof require !== 'undefined') {
|
|
302
|
+
// Node.js - require the JSON file
|
|
303
|
+
const fs = require('fs');
|
|
304
|
+
const pathModule = require('path');
|
|
305
|
+
const fullPath = pathModule.resolve(path);
|
|
306
|
+
if (fs.existsSync(fullPath)) {
|
|
307
|
+
const data = JSON.parse(fs.readFileSync(fullPath, 'utf-8'));
|
|
308
|
+
for (const [key, value] of Object.entries(data)) {
|
|
309
|
+
this.toggles.set(key, this.parseOfflineValue(value));
|
|
310
|
+
}
|
|
311
|
+
this.offlineTogglesLoaded = true;
|
|
312
|
+
console.log('[Togglely] Loaded offline toggles from JSON file:', fullPath);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
catch (error) {
|
|
317
|
+
console.warn('[Togglely] Failed to load offline JSON file:', error);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
217
320
|
getOfflineToggle(key) {
|
|
218
321
|
if (!this.config.offlineFallback)
|
|
219
322
|
return null;
|
|
220
|
-
// Try to get from already loaded offline toggles
|
|
221
323
|
const cached = this.toggles.get(key);
|
|
222
324
|
if (cached) {
|
|
223
|
-
// If we haven't emitted offline event yet, do it now
|
|
224
325
|
if (!this.state.isOffline) {
|
|
225
326
|
this.state.isOffline = true;
|
|
226
327
|
this.emit('offline');
|
|
@@ -230,48 +331,47 @@
|
|
|
230
331
|
return null;
|
|
231
332
|
}
|
|
232
333
|
parseOfflineValue(value) {
|
|
233
|
-
// Handle boolean strings
|
|
234
334
|
if (typeof value === 'string') {
|
|
235
335
|
const lower = value.toLowerCase();
|
|
236
336
|
if (lower === 'true')
|
|
237
337
|
return { value: true, enabled: true };
|
|
238
338
|
if (lower === 'false')
|
|
239
339
|
return { value: false, enabled: true };
|
|
240
|
-
// Try to parse as number
|
|
241
340
|
if (!isNaN(Number(value))) {
|
|
242
341
|
return { value: Number(value), enabled: true };
|
|
243
342
|
}
|
|
244
|
-
// Try to parse as JSON
|
|
245
343
|
try {
|
|
246
344
|
const parsed = JSON.parse(value);
|
|
247
345
|
return { value: parsed, enabled: true };
|
|
248
346
|
}
|
|
249
347
|
catch {
|
|
250
|
-
// Return as string
|
|
251
348
|
return { value, enabled: true };
|
|
252
349
|
}
|
|
253
350
|
}
|
|
254
351
|
return { value, enabled: true };
|
|
255
352
|
}
|
|
256
353
|
// ==================== Refresh / Polling ====================
|
|
354
|
+
/**
|
|
355
|
+
* Refresh all toggles from the server
|
|
356
|
+
*/
|
|
257
357
|
async refresh() {
|
|
258
358
|
try {
|
|
259
359
|
const params = new URLSearchParams();
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if (
|
|
264
|
-
params.set('
|
|
265
|
-
// Always send context if available (needed for targeting rules)
|
|
360
|
+
// Support both brandKey and tenantId for maximum compatibility
|
|
361
|
+
if (this.context.brandKey)
|
|
362
|
+
params.set('brandKey', String(this.context.brandKey));
|
|
363
|
+
if (this.context.tenantId)
|
|
364
|
+
params.set('tenantId', String(this.context.tenantId));
|
|
266
365
|
if (Object.keys(this.context).length > 0) {
|
|
267
366
|
params.set('context', JSON.stringify(this.context));
|
|
268
367
|
}
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
}
|
|
368
|
+
const headers = {
|
|
369
|
+
'Content-Type': 'application/json'
|
|
370
|
+
};
|
|
371
|
+
if (this.config.apiKey) {
|
|
372
|
+
headers['Authorization'] = `Bearer ${this.config.apiKey}`;
|
|
373
|
+
}
|
|
374
|
+
const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}?${params.toString()}`, { headers });
|
|
275
375
|
if (!response.ok) {
|
|
276
376
|
throw new Error(`HTTP ${response.status}`);
|
|
277
377
|
}
|
|
@@ -286,7 +386,6 @@
|
|
|
286
386
|
this.state.isReady = true;
|
|
287
387
|
this.emit('ready');
|
|
288
388
|
}
|
|
289
|
-
// If we were offline, go online
|
|
290
389
|
if (this.state.isOffline) {
|
|
291
390
|
this.state.isOffline = false;
|
|
292
391
|
this.emit('online');
|
|
@@ -295,7 +394,6 @@
|
|
|
295
394
|
}
|
|
296
395
|
catch (error) {
|
|
297
396
|
this.state.lastError = error;
|
|
298
|
-
// If we have offline toggles, switch to offline mode
|
|
299
397
|
if (this.config.offlineFallback && this.offlineTogglesLoaded) {
|
|
300
398
|
if (!this.state.isOffline) {
|
|
301
399
|
this.state.isOffline = true;
|
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 timeout: 5000,\n offlineFallback: true,\n envPrefix: 'TOGGLELY_',\n autoFetch: true,\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 // 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 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 - 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 const brandKey = this.context.tenantId || this.context.brandKey;\n if (brandKey)\n params.set('brandKey', String(brandKey));\n // Always send context if available (needed for targeting rules)\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 response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${this.config.project}/${this.config.environment}/${key}${query}`, {\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 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('brandKey', String(brandKey));\n // Always send context if available (needed for targeting rules)\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/${this.config.project}/${this.config.environment}?${params.toString()}`, {\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 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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"}
|
|
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 // enabled is the primary on/off switch for a flag.\n // value.value holds the flag's configured value (used for non-boolean use-cases).\n // For boolean flags: if enabled, return the boolean value itself.\n // If the value is not a boolean (misconfigured), fall back to just enabled.\n if (typeof value.value === 'boolean') {\n return value.enabled && value.value;\n }\n return value.enabled;\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 // Note: We intentionally do NOT use cache here to always get fresh values\n // The cache is only used for offline fallback and getAllToggles()\n // If you need cached values, use getAllToggles() instead\n // Fetch from server\n try {\n const params = new URLSearchParams();\n // Support both brandKey and tenantId for maximum compatibility\n if (this.context.brandKey)\n params.set('brandKey', String(this.context.brandKey));\n if (this.context.tenantId)\n params.set('tenantId', String(this.context.tenantId));\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 headers = {\n 'Content-Type': 'application/json'\n };\n if (this.config.apiKey) {\n headers['Authorization'] = `Bearer ${this.config.apiKey}`;\n }\n const response = await this.fetchWithTimeout(url, { headers });\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 // Support both brandKey and tenantId for maximum compatibility\n if (this.context.brandKey)\n params.set('brandKey', String(this.context.brandKey));\n if (this.context.tenantId)\n params.set('tenantId', String(this.context.tenantId));\n if (Object.keys(this.context).length > 0) {\n params.set('context', JSON.stringify(this.context));\n }\n const headers = {\n 'Content-Type': 'application/json'\n };\n if (this.config.apiKey) {\n headers['Authorization'] = `Bearer ${this.config.apiKey}`;\n }\n const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}?${params.toString()}`, { headers });\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={timeout:5e3,offlineFallback:!0,envPrefix:"TOGGLELY_",autoFetch:!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),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
|
|
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:"boolean"==typeof n.value?n.enabled&&n.value:n.enabled}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){try{const t=new URLSearchParams;this.context.brandKey&&t.set("brandKey",String(this.context.brandKey)),this.context.tenantId&&t.set("tenantId",String(this.context.tenantId)),Object.keys(this.context).length>0&&t.set("context",JSON.stringify(this.context));const n=t.toString()?`?${t.toString()}`:"",o=`${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}/${encodeURIComponent(e)}${n}`,i={"Content-Type":"application/json"};this.config.apiKey&&(i.Authorization=`Bearer ${this.config.apiKey}`);const s=await this.fetchWithTimeout(o,{headers:i});if(!s.ok){if(404===s.status)return null;throw new Error(`HTTP ${s.status}: ${s.statusText}`)}const l=await s.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.context.brandKey&&e.set("brandKey",String(this.context.brandKey)),this.context.tenantId&&e.set("tenantId",String(this.context.tenantId)),Object.keys(this.context).length>0&&e.set("context",JSON.stringify(this.context));const t={"Content-Type":"application/json"};this.config.apiKey&&(t.Authorization=`Bearer ${this.config.apiKey}`);const n=await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}?${e.toString()}`,{headers:t});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 i=setTimeout(()=>{o(new Error("Request timeout"))},this.config.timeout);fetch(e,t).then(e=>{clearTimeout(i),n(e)}).catch(e=>{clearTimeout(i),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,i=!1,s=!1;"string"==typeof o?e=[o]:Array.isArray(o)?e=o:(e=[o.selector],i=o.defaultValue??!1,s=o.invert??!1);const l=await t.isEnabled(n,i),r=s?!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:i=!1,invert:s=!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,i),c=s?!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,i]of Object.entries(e)){n[t+o.toUpperCase().replace(/-/g,"_")]="object"==typeof i?JSON.stringify(i):String(i)}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 timeout: 5000,\n offlineFallback: true,\n envPrefix: 'TOGGLELY_',\n autoFetch: true,\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 // 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 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 - 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 const brandKey = this.context.tenantId || this.context.brandKey;\n if (brandKey)\n params.set('brandKey', String(brandKey));\n // Always send context if available (needed for targeting rules)\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 response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${this.config.project}/${this.config.environment}/${key}${query}`, {\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 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('brandKey', String(brandKey));\n // Always send context if available (needed for targeting rules)\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/${this.config.project}/${this.config.environment}?${params.toString()}`, {\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 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","set","Set","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","brandKey","tenantId","stringify","query","toString","response","fetchWithTimeout","baseUrl","project","environment","headers","Authorization","apiKey","ok","status","Error","data","json","error","offlineValue","getOfflineToggle","console","getAllToggles","result","window","__TOGGLELY_TOGGLES","offlineToggles","entries","parseOfflineValue","log","process","env","prefix","envKey","envValue","startsWith","undefined","toggleKey","slice","toLowerCase","replace","warn","lower","isNaN","clear","Date","forceOfflineMode","forceOnlineMode","destroy","url","options","Promise","resolve","reject","timeoutId","setTimeout","fetch","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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"}
|
|
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 // enabled is the primary on/off switch for a flag.\n // value.value holds the flag's configured value (used for non-boolean use-cases).\n // For boolean flags: if enabled, return the boolean value itself.\n // If the value is not a boolean (misconfigured), fall back to just enabled.\n if (typeof value.value === 'boolean') {\n return value.enabled && value.value;\n }\n return value.enabled;\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 // Note: We intentionally do NOT use cache here to always get fresh values\n // The cache is only used for offline fallback and getAllToggles()\n // If you need cached values, use getAllToggles() instead\n // Fetch from server\n try {\n const params = new URLSearchParams();\n // Support both brandKey and tenantId for maximum compatibility\n if (this.context.brandKey)\n params.set('brandKey', String(this.context.brandKey));\n if (this.context.tenantId)\n params.set('tenantId', String(this.context.tenantId));\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 headers = {\n 'Content-Type': 'application/json'\n };\n if (this.config.apiKey) {\n headers['Authorization'] = `Bearer ${this.config.apiKey}`;\n }\n const response = await this.fetchWithTimeout(url, { headers });\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 // Support both brandKey and tenantId for maximum compatibility\n if (this.context.brandKey)\n params.set('brandKey', String(this.context.brandKey));\n if (this.context.tenantId)\n params.set('tenantId', String(this.context.tenantId));\n if (Object.keys(this.context).length > 0) {\n params.set('context', JSON.stringify(this.context));\n }\n const headers = {\n 'Content-Type': 'application/json'\n };\n if (this.config.apiKey) {\n headers['Authorization'] = `Bearer ${this.config.apiKey}`;\n }\n const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${encodeURIComponent(this.config.project)}/${encodeURIComponent(this.config.environment)}?${params.toString()}`, { headers });\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","params","URLSearchParams","Object","keys","length","stringify","query","toString","url","baseUrl","encodeURIComponent","project","environment","headers","apiKey","response","fetchWithTimeout","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","cached","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.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.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
|
+
}
|
|
36
36
|
}
|