@togglely/sdk-core 1.0.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +95 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +346 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +353 -0
- package/dist/index.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Togglely Core SDK - Framework agnostic
|
|
3
|
+
*
|
|
4
|
+
* Supports offline fallback via environment variables
|
|
5
|
+
*/
|
|
6
|
+
export interface TogglelyConfig {
|
|
7
|
+
/** API Key from your Togglely dashboard */
|
|
8
|
+
apiKey: string;
|
|
9
|
+
/** Environment key (e.g., 'development', 'production') */
|
|
10
|
+
environment: string;
|
|
11
|
+
/** Base URL of your Togglely instance */
|
|
12
|
+
baseUrl: string;
|
|
13
|
+
/** Refresh interval in milliseconds (default: 60000) */
|
|
14
|
+
refreshInterval?: number;
|
|
15
|
+
/** Request timeout in milliseconds (default: 5000) */
|
|
16
|
+
timeout?: number;
|
|
17
|
+
/** Enable offline mode fallback via environment variables (default: true) */
|
|
18
|
+
offlineFallback?: boolean;
|
|
19
|
+
/** Prefix for environment variables (default: 'TOGGLELY_') */
|
|
20
|
+
envPrefix?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ToggleContext {
|
|
23
|
+
userId?: string;
|
|
24
|
+
email?: string;
|
|
25
|
+
country?: string;
|
|
26
|
+
region?: string;
|
|
27
|
+
[key: string]: any;
|
|
28
|
+
}
|
|
29
|
+
export interface ToggleValue {
|
|
30
|
+
value: any;
|
|
31
|
+
enabled: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface AllTogglesResponse {
|
|
34
|
+
[key: string]: ToggleValue;
|
|
35
|
+
}
|
|
36
|
+
export interface TogglelyState {
|
|
37
|
+
isReady: boolean;
|
|
38
|
+
isOffline: boolean;
|
|
39
|
+
lastError: Error | null;
|
|
40
|
+
lastFetch: Date | null;
|
|
41
|
+
}
|
|
42
|
+
export type TogglelyEventType = 'ready' | 'update' | 'error' | 'offline' | 'online';
|
|
43
|
+
export type TogglelyEventHandler = (state: TogglelyState) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Core Togglely Client
|
|
46
|
+
*/
|
|
47
|
+
export declare class TogglelyClient {
|
|
48
|
+
private config;
|
|
49
|
+
private toggles;
|
|
50
|
+
private refreshTimer?;
|
|
51
|
+
private context;
|
|
52
|
+
private state;
|
|
53
|
+
private eventHandlers;
|
|
54
|
+
private offlineTogglesLoaded;
|
|
55
|
+
constructor(config: TogglelyConfig);
|
|
56
|
+
on(event: TogglelyEventType, handler: TogglelyEventHandler): () => void;
|
|
57
|
+
off(event: TogglelyEventType, handler: TogglelyEventHandler): void;
|
|
58
|
+
private emit;
|
|
59
|
+
setContext(context: ToggleContext): void;
|
|
60
|
+
getContext(): ToggleContext;
|
|
61
|
+
clearContext(): void;
|
|
62
|
+
getState(): TogglelyState;
|
|
63
|
+
isReady(): boolean;
|
|
64
|
+
isOffline(): boolean;
|
|
65
|
+
isEnabled(key: string, defaultValue?: boolean): Promise<boolean>;
|
|
66
|
+
getString(key: string, defaultValue?: string): Promise<string>;
|
|
67
|
+
getNumber(key: string, defaultValue?: number): Promise<number>;
|
|
68
|
+
getJSON<T = any>(key: string, defaultValue?: T): Promise<T>;
|
|
69
|
+
getValue(key: string): Promise<ToggleValue | null>;
|
|
70
|
+
getAllToggles(): Record<string, ToggleValue>;
|
|
71
|
+
/**
|
|
72
|
+
* Load toggles from environment variables
|
|
73
|
+
* Format: TOGGLELY_<TOGGLE_KEY>=<value> or TOGGLELY_<TOGGLE_KEY>_ENABLED=true
|
|
74
|
+
*/
|
|
75
|
+
private loadOfflineToggles;
|
|
76
|
+
private getOfflineToggle;
|
|
77
|
+
private parseOfflineValue;
|
|
78
|
+
refresh(): Promise<void>;
|
|
79
|
+
forceOfflineMode(): void;
|
|
80
|
+
forceOnlineMode(): void;
|
|
81
|
+
destroy(): void;
|
|
82
|
+
private startPolling;
|
|
83
|
+
private fetchWithTimeout;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Create a client-side toggle loader script
|
|
87
|
+
* Use this to inject offline toggles into your HTML
|
|
88
|
+
*/
|
|
89
|
+
export declare function createOfflineTogglesScript(toggles: Record<string, any>): string;
|
|
90
|
+
/**
|
|
91
|
+
* Helper to convert toggles to environment variables
|
|
92
|
+
*/
|
|
93
|
+
export declare function togglesToEnvVars(toggles: Record<string, any>, prefix?: string): Record<string, string>;
|
|
94
|
+
export default TogglelyClient;
|
|
95
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB;AAGD,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AACpF,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;AAElE;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,YAAY,CAAC,CAAiC;IACtD,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,KAAK,CAKX;IACF,OAAO,CAAC,aAAa,CAAgE;IACrF,OAAO,CAAC,oBAAoB,CAAkB;gBAElC,MAAM,EAAE,cAAc;IA2BlC,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,oBAAoB,GAAG,MAAM,IAAI;IAQvE,GAAG,CAAC,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAOlE,OAAO,CAAC,IAAI;IASZ,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAIxC,UAAU,IAAI,aAAa;IAI3B,YAAY,IAAI,IAAI;IAMpB,QAAQ,IAAI,aAAa;IAIzB,OAAO,IAAI,OAAO;IAIlB,SAAS,IAAI,OAAO;IAMd,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,GAAE,OAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IAMvE,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,GAAE,MAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAMlE,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,GAAE,MAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAMjE,OAAO,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,GAAE,CAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAepE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAgDxD,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;IAU5C;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAmC1B,OAAO,CAAC,gBAAgB;IAiBxB,OAAO,CAAC,iBAAiB;IA2BnB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAuD9B,gBAAgB,IAAI,IAAI;IAKxB,eAAe,IAAI,IAAI;IAQvB,OAAO,IAAI,IAAI;IAUf,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,gBAAgB;CAiBzB;AAID;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAE/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5B,MAAM,GAAE,MAAoB,GAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB;AAGD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Togglely Core SDK - Framework agnostic
|
|
3
|
+
*
|
|
4
|
+
* Supports offline fallback via environment variables
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Core Togglely Client
|
|
8
|
+
*/
|
|
9
|
+
class TogglelyClient {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.toggles = new Map();
|
|
12
|
+
this.context = {};
|
|
13
|
+
this.state = {
|
|
14
|
+
isReady: false,
|
|
15
|
+
isOffline: false,
|
|
16
|
+
lastError: null,
|
|
17
|
+
lastFetch: null
|
|
18
|
+
};
|
|
19
|
+
this.eventHandlers = new Map();
|
|
20
|
+
this.offlineTogglesLoaded = false;
|
|
21
|
+
this.config = {
|
|
22
|
+
refreshInterval: 60000,
|
|
23
|
+
timeout: 5000,
|
|
24
|
+
offlineFallback: true,
|
|
25
|
+
envPrefix: 'TOGGLELY_',
|
|
26
|
+
...config
|
|
27
|
+
};
|
|
28
|
+
// Initialize event handlers
|
|
29
|
+
this.eventHandlers.set('ready', new Set());
|
|
30
|
+
this.eventHandlers.set('update', new Set());
|
|
31
|
+
this.eventHandlers.set('error', new Set());
|
|
32
|
+
this.eventHandlers.set('offline', new Set());
|
|
33
|
+
this.eventHandlers.set('online', new Set());
|
|
34
|
+
// Load offline toggles first (if enabled)
|
|
35
|
+
if (this.config.offlineFallback) {
|
|
36
|
+
this.loadOfflineToggles();
|
|
37
|
+
}
|
|
38
|
+
// Start polling
|
|
39
|
+
this.startPolling();
|
|
40
|
+
}
|
|
41
|
+
// ==================== Event Handling ====================
|
|
42
|
+
on(event, handler) {
|
|
43
|
+
const handlers = this.eventHandlers.get(event);
|
|
44
|
+
if (handlers) {
|
|
45
|
+
handlers.add(handler);
|
|
46
|
+
}
|
|
47
|
+
return () => this.off(event, handler);
|
|
48
|
+
}
|
|
49
|
+
off(event, handler) {
|
|
50
|
+
const handlers = this.eventHandlers.get(event);
|
|
51
|
+
if (handlers) {
|
|
52
|
+
handlers.delete(handler);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
emit(event) {
|
|
56
|
+
const handlers = this.eventHandlers.get(event);
|
|
57
|
+
if (handlers) {
|
|
58
|
+
handlers.forEach(handler => handler({ ...this.state }));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// ==================== Context ====================
|
|
62
|
+
setContext(context) {
|
|
63
|
+
this.context = { ...this.context, ...context };
|
|
64
|
+
}
|
|
65
|
+
getContext() {
|
|
66
|
+
return { ...this.context };
|
|
67
|
+
}
|
|
68
|
+
clearContext() {
|
|
69
|
+
this.context = {};
|
|
70
|
+
}
|
|
71
|
+
// ==================== State ====================
|
|
72
|
+
getState() {
|
|
73
|
+
return { ...this.state };
|
|
74
|
+
}
|
|
75
|
+
isReady() {
|
|
76
|
+
return this.state.isReady;
|
|
77
|
+
}
|
|
78
|
+
isOffline() {
|
|
79
|
+
return this.state.isOffline;
|
|
80
|
+
}
|
|
81
|
+
// ==================== Toggle Accessors ====================
|
|
82
|
+
async isEnabled(key, defaultValue = false) {
|
|
83
|
+
const value = await this.getValue(key);
|
|
84
|
+
if (value === null)
|
|
85
|
+
return defaultValue;
|
|
86
|
+
return value.enabled && value.value === true;
|
|
87
|
+
}
|
|
88
|
+
async getString(key, defaultValue = '') {
|
|
89
|
+
const value = await this.getValue(key);
|
|
90
|
+
if (value === null || !value.enabled)
|
|
91
|
+
return defaultValue;
|
|
92
|
+
return String(value.value);
|
|
93
|
+
}
|
|
94
|
+
async getNumber(key, defaultValue = 0) {
|
|
95
|
+
const value = await this.getValue(key);
|
|
96
|
+
if (value === null || !value.enabled)
|
|
97
|
+
return defaultValue;
|
|
98
|
+
return Number(value.value);
|
|
99
|
+
}
|
|
100
|
+
async getJSON(key, defaultValue = {}) {
|
|
101
|
+
const value = await this.getValue(key);
|
|
102
|
+
if (value === null || !value.enabled)
|
|
103
|
+
return defaultValue;
|
|
104
|
+
if (typeof value.value === 'string') {
|
|
105
|
+
try {
|
|
106
|
+
return JSON.parse(value.value);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return defaultValue;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return value.value;
|
|
113
|
+
}
|
|
114
|
+
async getValue(key) {
|
|
115
|
+
// Try cache first
|
|
116
|
+
const cached = this.toggles.get(key);
|
|
117
|
+
if (cached) {
|
|
118
|
+
return cached;
|
|
119
|
+
}
|
|
120
|
+
// Fetch from server
|
|
121
|
+
try {
|
|
122
|
+
const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${this.config.environment}/${key}`, {
|
|
123
|
+
headers: {
|
|
124
|
+
'Authorization': `Bearer ${this.config.apiKey}`,
|
|
125
|
+
'Content-Type': 'application/json'
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
if (!response.ok) {
|
|
129
|
+
if (response.status === 404) {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
throw new Error(`HTTP ${response.status}`);
|
|
133
|
+
}
|
|
134
|
+
const data = await response.json();
|
|
135
|
+
this.toggles.set(key, data);
|
|
136
|
+
// Update state if we were offline
|
|
137
|
+
if (this.state.isOffline) {
|
|
138
|
+
this.state.isOffline = false;
|
|
139
|
+
this.emit('online');
|
|
140
|
+
}
|
|
141
|
+
return data;
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
// Try offline fallback
|
|
145
|
+
const offlineValue = this.getOfflineToggle(key);
|
|
146
|
+
if (offlineValue !== null) {
|
|
147
|
+
return offlineValue;
|
|
148
|
+
}
|
|
149
|
+
console.error(`[Togglely] Failed to fetch toggle "${key}":`, error);
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
getAllToggles() {
|
|
154
|
+
const result = {};
|
|
155
|
+
this.toggles.forEach((value, key) => {
|
|
156
|
+
result[key] = value;
|
|
157
|
+
});
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
// ==================== Offline Fallback ====================
|
|
161
|
+
/**
|
|
162
|
+
* Load toggles from environment variables
|
|
163
|
+
* Format: TOGGLELY_<TOGGLE_KEY>=<value> or TOGGLELY_<TOGGLE_KEY>_ENABLED=true
|
|
164
|
+
*/
|
|
165
|
+
loadOfflineToggles() {
|
|
166
|
+
try {
|
|
167
|
+
// Browser environment - check window.__TOGGLELY_TOGGLES
|
|
168
|
+
if (typeof window !== 'undefined' && window.__TOGGLELY_TOGGLES) {
|
|
169
|
+
const offlineToggles = window.__TOGGLELY_TOGGLES;
|
|
170
|
+
for (const [key, value] of Object.entries(offlineToggles)) {
|
|
171
|
+
this.toggles.set(key, this.parseOfflineValue(value));
|
|
172
|
+
}
|
|
173
|
+
this.offlineTogglesLoaded = true;
|
|
174
|
+
console.log('[Togglely] Loaded offline toggles from window.__TOGGLELY_TOGGLES');
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
// Node.js / Bun / Deno environment - check process.env
|
|
178
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
179
|
+
const prefix = this.config.envPrefix;
|
|
180
|
+
for (const [envKey, envValue] of Object.entries(process.env)) {
|
|
181
|
+
if (envKey?.startsWith(prefix) && envValue !== undefined) {
|
|
182
|
+
// Parse toggle key: TOGGLELY_MY_FEATURE -> my-feature
|
|
183
|
+
const toggleKey = envKey
|
|
184
|
+
.slice(prefix.length)
|
|
185
|
+
.toLowerCase()
|
|
186
|
+
.replace(/_/g, '-');
|
|
187
|
+
this.toggles.set(toggleKey, this.parseOfflineValue(envValue));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
this.offlineTogglesLoaded = true;
|
|
191
|
+
console.log('[Togglely] Loaded offline toggles from environment variables');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
console.warn('[Togglely] Failed to load offline toggles:', error);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
getOfflineToggle(key) {
|
|
199
|
+
if (!this.config.offlineFallback)
|
|
200
|
+
return null;
|
|
201
|
+
// Try to get from already loaded offline toggles
|
|
202
|
+
const cached = this.toggles.get(key);
|
|
203
|
+
if (cached) {
|
|
204
|
+
// If we haven't emitted offline event yet, do it now
|
|
205
|
+
if (!this.state.isOffline) {
|
|
206
|
+
this.state.isOffline = true;
|
|
207
|
+
this.emit('offline');
|
|
208
|
+
}
|
|
209
|
+
return cached;
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
parseOfflineValue(value) {
|
|
214
|
+
// Handle boolean strings
|
|
215
|
+
if (typeof value === 'string') {
|
|
216
|
+
const lower = value.toLowerCase();
|
|
217
|
+
if (lower === 'true')
|
|
218
|
+
return { value: true, enabled: true };
|
|
219
|
+
if (lower === 'false')
|
|
220
|
+
return { value: false, enabled: true };
|
|
221
|
+
// Try to parse as number
|
|
222
|
+
if (!isNaN(Number(value))) {
|
|
223
|
+
return { value: Number(value), enabled: true };
|
|
224
|
+
}
|
|
225
|
+
// Try to parse as JSON
|
|
226
|
+
try {
|
|
227
|
+
const parsed = JSON.parse(value);
|
|
228
|
+
return { value: parsed, enabled: true };
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
// Return as string
|
|
232
|
+
return { value, enabled: true };
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return { value, enabled: true };
|
|
236
|
+
}
|
|
237
|
+
// ==================== Refresh / Polling ====================
|
|
238
|
+
async refresh() {
|
|
239
|
+
try {
|
|
240
|
+
const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/toggles/${this.config.environment}`, {
|
|
241
|
+
headers: {
|
|
242
|
+
'Authorization': `Bearer ${this.config.apiKey}`,
|
|
243
|
+
'Content-Type': 'application/json'
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
if (!response.ok) {
|
|
247
|
+
throw new Error(`HTTP ${response.status}`);
|
|
248
|
+
}
|
|
249
|
+
const data = await response.json();
|
|
250
|
+
this.toggles.clear();
|
|
251
|
+
for (const [key, value] of Object.entries(data)) {
|
|
252
|
+
this.toggles.set(key, value);
|
|
253
|
+
}
|
|
254
|
+
this.state.lastFetch = new Date();
|
|
255
|
+
this.state.lastError = null;
|
|
256
|
+
if (!this.state.isReady) {
|
|
257
|
+
this.state.isReady = true;
|
|
258
|
+
this.emit('ready');
|
|
259
|
+
}
|
|
260
|
+
// If we were offline, go online
|
|
261
|
+
if (this.state.isOffline) {
|
|
262
|
+
this.state.isOffline = false;
|
|
263
|
+
this.emit('online');
|
|
264
|
+
}
|
|
265
|
+
this.emit('update');
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
this.state.lastError = error;
|
|
269
|
+
// If we have offline toggles, switch to offline mode
|
|
270
|
+
if (this.config.offlineFallback && this.offlineTogglesLoaded) {
|
|
271
|
+
if (!this.state.isOffline) {
|
|
272
|
+
this.state.isOffline = true;
|
|
273
|
+
this.emit('offline');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
this.emit('error');
|
|
277
|
+
console.error('[Togglely] Failed to refresh toggles:', error);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
forceOfflineMode() {
|
|
281
|
+
this.state.isOffline = true;
|
|
282
|
+
this.emit('offline');
|
|
283
|
+
}
|
|
284
|
+
forceOnlineMode() {
|
|
285
|
+
this.state.isOffline = false;
|
|
286
|
+
this.refresh();
|
|
287
|
+
this.emit('online');
|
|
288
|
+
}
|
|
289
|
+
// ==================== Cleanup ====================
|
|
290
|
+
destroy() {
|
|
291
|
+
if (this.refreshTimer) {
|
|
292
|
+
clearInterval(this.refreshTimer);
|
|
293
|
+
}
|
|
294
|
+
this.toggles.clear();
|
|
295
|
+
this.eventHandlers.forEach(handlers => handlers.clear());
|
|
296
|
+
}
|
|
297
|
+
// ==================== Private Helpers ====================
|
|
298
|
+
startPolling() {
|
|
299
|
+
// Initial fetch
|
|
300
|
+
this.refresh();
|
|
301
|
+
// Set up polling
|
|
302
|
+
this.refreshTimer = setInterval(() => {
|
|
303
|
+
if (!this.state.isOffline) {
|
|
304
|
+
this.refresh();
|
|
305
|
+
}
|
|
306
|
+
}, this.config.refreshInterval);
|
|
307
|
+
}
|
|
308
|
+
fetchWithTimeout(url, options) {
|
|
309
|
+
return new Promise((resolve, reject) => {
|
|
310
|
+
const timeoutId = setTimeout(() => {
|
|
311
|
+
reject(new Error('Request timeout'));
|
|
312
|
+
}, this.config.timeout);
|
|
313
|
+
fetch(url, options)
|
|
314
|
+
.then(response => {
|
|
315
|
+
clearTimeout(timeoutId);
|
|
316
|
+
resolve(response);
|
|
317
|
+
})
|
|
318
|
+
.catch(error => {
|
|
319
|
+
clearTimeout(timeoutId);
|
|
320
|
+
reject(error);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// ==================== Utility Functions ====================
|
|
326
|
+
/**
|
|
327
|
+
* Create a client-side toggle loader script
|
|
328
|
+
* Use this to inject offline toggles into your HTML
|
|
329
|
+
*/
|
|
330
|
+
function createOfflineTogglesScript(toggles) {
|
|
331
|
+
return `<script>window.__TOGGLELY_TOGGLES = ${JSON.stringify(toggles)};</script>`;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Helper to convert toggles to environment variables
|
|
335
|
+
*/
|
|
336
|
+
function togglesToEnvVars(toggles, prefix = 'TOGGLELY_') {
|
|
337
|
+
const envVars = {};
|
|
338
|
+
for (const [key, value] of Object.entries(toggles)) {
|
|
339
|
+
const envKey = prefix + key.toUpperCase().replace(/-/g, '_');
|
|
340
|
+
envVars[envKey] = typeof value === 'object' ? JSON.stringify(value) : String(value);
|
|
341
|
+
}
|
|
342
|
+
return envVars;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export { TogglelyClient, createOfflineTogglesScript, TogglelyClient as default, togglesToEnvVars };
|
|
346
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/index.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Togglely Core SDK - Framework agnostic
|
|
7
|
+
*
|
|
8
|
+
* Supports offline fallback via environment variables
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Core Togglely Client
|
|
12
|
+
*/
|
|
13
|
+
class TogglelyClient {
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.toggles = new Map();
|
|
16
|
+
this.context = {};
|
|
17
|
+
this.state = {
|
|
18
|
+
isReady: false,
|
|
19
|
+
isOffline: false,
|
|
20
|
+
lastError: null,
|
|
21
|
+
lastFetch: null
|
|
22
|
+
};
|
|
23
|
+
this.eventHandlers = new Map();
|
|
24
|
+
this.offlineTogglesLoaded = false;
|
|
25
|
+
this.config = {
|
|
26
|
+
refreshInterval: 60000,
|
|
27
|
+
timeout: 5000,
|
|
28
|
+
offlineFallback: true,
|
|
29
|
+
envPrefix: 'TOGGLELY_',
|
|
30
|
+
...config
|
|
31
|
+
};
|
|
32
|
+
// Initialize event handlers
|
|
33
|
+
this.eventHandlers.set('ready', new Set());
|
|
34
|
+
this.eventHandlers.set('update', new Set());
|
|
35
|
+
this.eventHandlers.set('error', new Set());
|
|
36
|
+
this.eventHandlers.set('offline', new Set());
|
|
37
|
+
this.eventHandlers.set('online', new Set());
|
|
38
|
+
// Load offline toggles first (if enabled)
|
|
39
|
+
if (this.config.offlineFallback) {
|
|
40
|
+
this.loadOfflineToggles();
|
|
41
|
+
}
|
|
42
|
+
// Start polling
|
|
43
|
+
this.startPolling();
|
|
44
|
+
}
|
|
45
|
+
// ==================== Event Handling ====================
|
|
46
|
+
on(event, handler) {
|
|
47
|
+
const handlers = this.eventHandlers.get(event);
|
|
48
|
+
if (handlers) {
|
|
49
|
+
handlers.add(handler);
|
|
50
|
+
}
|
|
51
|
+
return () => this.off(event, handler);
|
|
52
|
+
}
|
|
53
|
+
off(event, handler) {
|
|
54
|
+
const handlers = this.eventHandlers.get(event);
|
|
55
|
+
if (handlers) {
|
|
56
|
+
handlers.delete(handler);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
emit(event) {
|
|
60
|
+
const handlers = this.eventHandlers.get(event);
|
|
61
|
+
if (handlers) {
|
|
62
|
+
handlers.forEach(handler => handler({ ...this.state }));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// ==================== Context ====================
|
|
66
|
+
setContext(context) {
|
|
67
|
+
this.context = { ...this.context, ...context };
|
|
68
|
+
}
|
|
69
|
+
getContext() {
|
|
70
|
+
return { ...this.context };
|
|
71
|
+
}
|
|
72
|
+
clearContext() {
|
|
73
|
+
this.context = {};
|
|
74
|
+
}
|
|
75
|
+
// ==================== State ====================
|
|
76
|
+
getState() {
|
|
77
|
+
return { ...this.state };
|
|
78
|
+
}
|
|
79
|
+
isReady() {
|
|
80
|
+
return this.state.isReady;
|
|
81
|
+
}
|
|
82
|
+
isOffline() {
|
|
83
|
+
return this.state.isOffline;
|
|
84
|
+
}
|
|
85
|
+
// ==================== Toggle Accessors ====================
|
|
86
|
+
async isEnabled(key, defaultValue = false) {
|
|
87
|
+
const value = await this.getValue(key);
|
|
88
|
+
if (value === null)
|
|
89
|
+
return defaultValue;
|
|
90
|
+
return value.enabled && value.value === true;
|
|
91
|
+
}
|
|
92
|
+
async getString(key, defaultValue = '') {
|
|
93
|
+
const value = await this.getValue(key);
|
|
94
|
+
if (value === null || !value.enabled)
|
|
95
|
+
return defaultValue;
|
|
96
|
+
return String(value.value);
|
|
97
|
+
}
|
|
98
|
+
async getNumber(key, defaultValue = 0) {
|
|
99
|
+
const value = await this.getValue(key);
|
|
100
|
+
if (value === null || !value.enabled)
|
|
101
|
+
return defaultValue;
|
|
102
|
+
return Number(value.value);
|
|
103
|
+
}
|
|
104
|
+
async getJSON(key, defaultValue = {}) {
|
|
105
|
+
const value = await this.getValue(key);
|
|
106
|
+
if (value === null || !value.enabled)
|
|
107
|
+
return defaultValue;
|
|
108
|
+
if (typeof value.value === 'string') {
|
|
109
|
+
try {
|
|
110
|
+
return JSON.parse(value.value);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return defaultValue;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return value.value;
|
|
117
|
+
}
|
|
118
|
+
async getValue(key) {
|
|
119
|
+
// Try cache first
|
|
120
|
+
const cached = this.toggles.get(key);
|
|
121
|
+
if (cached) {
|
|
122
|
+
return cached;
|
|
123
|
+
}
|
|
124
|
+
// Fetch from server
|
|
125
|
+
try {
|
|
126
|
+
const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/flags/${this.config.environment}/${key}`, {
|
|
127
|
+
headers: {
|
|
128
|
+
'Authorization': `Bearer ${this.config.apiKey}`,
|
|
129
|
+
'Content-Type': 'application/json'
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
if (response.status === 404) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
throw new Error(`HTTP ${response.status}`);
|
|
137
|
+
}
|
|
138
|
+
const data = await response.json();
|
|
139
|
+
this.toggles.set(key, data);
|
|
140
|
+
// Update state if we were offline
|
|
141
|
+
if (this.state.isOffline) {
|
|
142
|
+
this.state.isOffline = false;
|
|
143
|
+
this.emit('online');
|
|
144
|
+
}
|
|
145
|
+
return data;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
// Try offline fallback
|
|
149
|
+
const offlineValue = this.getOfflineToggle(key);
|
|
150
|
+
if (offlineValue !== null) {
|
|
151
|
+
return offlineValue;
|
|
152
|
+
}
|
|
153
|
+
console.error(`[Togglely] Failed to fetch toggle "${key}":`, error);
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
getAllToggles() {
|
|
158
|
+
const result = {};
|
|
159
|
+
this.toggles.forEach((value, key) => {
|
|
160
|
+
result[key] = value;
|
|
161
|
+
});
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
// ==================== Offline Fallback ====================
|
|
165
|
+
/**
|
|
166
|
+
* Load toggles from environment variables
|
|
167
|
+
* Format: TOGGLELY_<TOGGLE_KEY>=<value> or TOGGLELY_<TOGGLE_KEY>_ENABLED=true
|
|
168
|
+
*/
|
|
169
|
+
loadOfflineToggles() {
|
|
170
|
+
try {
|
|
171
|
+
// Browser environment - check window.__TOGGLELY_TOGGLES
|
|
172
|
+
if (typeof window !== 'undefined' && window.__TOGGLELY_TOGGLES) {
|
|
173
|
+
const offlineToggles = window.__TOGGLELY_TOGGLES;
|
|
174
|
+
for (const [key, value] of Object.entries(offlineToggles)) {
|
|
175
|
+
this.toggles.set(key, this.parseOfflineValue(value));
|
|
176
|
+
}
|
|
177
|
+
this.offlineTogglesLoaded = true;
|
|
178
|
+
console.log('[Togglely] Loaded offline toggles from window.__TOGGLELY_TOGGLES');
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// Node.js / Bun / Deno environment - check process.env
|
|
182
|
+
if (typeof process !== 'undefined' && process.env) {
|
|
183
|
+
const prefix = this.config.envPrefix;
|
|
184
|
+
for (const [envKey, envValue] of Object.entries(process.env)) {
|
|
185
|
+
if (envKey?.startsWith(prefix) && envValue !== undefined) {
|
|
186
|
+
// Parse toggle key: TOGGLELY_MY_FEATURE -> my-feature
|
|
187
|
+
const toggleKey = envKey
|
|
188
|
+
.slice(prefix.length)
|
|
189
|
+
.toLowerCase()
|
|
190
|
+
.replace(/_/g, '-');
|
|
191
|
+
this.toggles.set(toggleKey, this.parseOfflineValue(envValue));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
this.offlineTogglesLoaded = true;
|
|
195
|
+
console.log('[Togglely] Loaded offline toggles from environment variables');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
console.warn('[Togglely] Failed to load offline toggles:', error);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
getOfflineToggle(key) {
|
|
203
|
+
if (!this.config.offlineFallback)
|
|
204
|
+
return null;
|
|
205
|
+
// Try to get from already loaded offline toggles
|
|
206
|
+
const cached = this.toggles.get(key);
|
|
207
|
+
if (cached) {
|
|
208
|
+
// If we haven't emitted offline event yet, do it now
|
|
209
|
+
if (!this.state.isOffline) {
|
|
210
|
+
this.state.isOffline = true;
|
|
211
|
+
this.emit('offline');
|
|
212
|
+
}
|
|
213
|
+
return cached;
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
parseOfflineValue(value) {
|
|
218
|
+
// Handle boolean strings
|
|
219
|
+
if (typeof value === 'string') {
|
|
220
|
+
const lower = value.toLowerCase();
|
|
221
|
+
if (lower === 'true')
|
|
222
|
+
return { value: true, enabled: true };
|
|
223
|
+
if (lower === 'false')
|
|
224
|
+
return { value: false, enabled: true };
|
|
225
|
+
// Try to parse as number
|
|
226
|
+
if (!isNaN(Number(value))) {
|
|
227
|
+
return { value: Number(value), enabled: true };
|
|
228
|
+
}
|
|
229
|
+
// Try to parse as JSON
|
|
230
|
+
try {
|
|
231
|
+
const parsed = JSON.parse(value);
|
|
232
|
+
return { value: parsed, enabled: true };
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
// Return as string
|
|
236
|
+
return { value, enabled: true };
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return { value, enabled: true };
|
|
240
|
+
}
|
|
241
|
+
// ==================== Refresh / Polling ====================
|
|
242
|
+
async refresh() {
|
|
243
|
+
try {
|
|
244
|
+
const response = await this.fetchWithTimeout(`${this.config.baseUrl}/sdk/toggles/${this.config.environment}`, {
|
|
245
|
+
headers: {
|
|
246
|
+
'Authorization': `Bearer ${this.config.apiKey}`,
|
|
247
|
+
'Content-Type': 'application/json'
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
if (!response.ok) {
|
|
251
|
+
throw new Error(`HTTP ${response.status}`);
|
|
252
|
+
}
|
|
253
|
+
const data = await response.json();
|
|
254
|
+
this.toggles.clear();
|
|
255
|
+
for (const [key, value] of Object.entries(data)) {
|
|
256
|
+
this.toggles.set(key, value);
|
|
257
|
+
}
|
|
258
|
+
this.state.lastFetch = new Date();
|
|
259
|
+
this.state.lastError = null;
|
|
260
|
+
if (!this.state.isReady) {
|
|
261
|
+
this.state.isReady = true;
|
|
262
|
+
this.emit('ready');
|
|
263
|
+
}
|
|
264
|
+
// If we were offline, go online
|
|
265
|
+
if (this.state.isOffline) {
|
|
266
|
+
this.state.isOffline = false;
|
|
267
|
+
this.emit('online');
|
|
268
|
+
}
|
|
269
|
+
this.emit('update');
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
this.state.lastError = error;
|
|
273
|
+
// If we have offline toggles, switch to offline mode
|
|
274
|
+
if (this.config.offlineFallback && this.offlineTogglesLoaded) {
|
|
275
|
+
if (!this.state.isOffline) {
|
|
276
|
+
this.state.isOffline = true;
|
|
277
|
+
this.emit('offline');
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
this.emit('error');
|
|
281
|
+
console.error('[Togglely] Failed to refresh toggles:', error);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
forceOfflineMode() {
|
|
285
|
+
this.state.isOffline = true;
|
|
286
|
+
this.emit('offline');
|
|
287
|
+
}
|
|
288
|
+
forceOnlineMode() {
|
|
289
|
+
this.state.isOffline = false;
|
|
290
|
+
this.refresh();
|
|
291
|
+
this.emit('online');
|
|
292
|
+
}
|
|
293
|
+
// ==================== Cleanup ====================
|
|
294
|
+
destroy() {
|
|
295
|
+
if (this.refreshTimer) {
|
|
296
|
+
clearInterval(this.refreshTimer);
|
|
297
|
+
}
|
|
298
|
+
this.toggles.clear();
|
|
299
|
+
this.eventHandlers.forEach(handlers => handlers.clear());
|
|
300
|
+
}
|
|
301
|
+
// ==================== Private Helpers ====================
|
|
302
|
+
startPolling() {
|
|
303
|
+
// Initial fetch
|
|
304
|
+
this.refresh();
|
|
305
|
+
// Set up polling
|
|
306
|
+
this.refreshTimer = setInterval(() => {
|
|
307
|
+
if (!this.state.isOffline) {
|
|
308
|
+
this.refresh();
|
|
309
|
+
}
|
|
310
|
+
}, this.config.refreshInterval);
|
|
311
|
+
}
|
|
312
|
+
fetchWithTimeout(url, options) {
|
|
313
|
+
return new Promise((resolve, reject) => {
|
|
314
|
+
const timeoutId = setTimeout(() => {
|
|
315
|
+
reject(new Error('Request timeout'));
|
|
316
|
+
}, this.config.timeout);
|
|
317
|
+
fetch(url, options)
|
|
318
|
+
.then(response => {
|
|
319
|
+
clearTimeout(timeoutId);
|
|
320
|
+
resolve(response);
|
|
321
|
+
})
|
|
322
|
+
.catch(error => {
|
|
323
|
+
clearTimeout(timeoutId);
|
|
324
|
+
reject(error);
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
// ==================== Utility Functions ====================
|
|
330
|
+
/**
|
|
331
|
+
* Create a client-side toggle loader script
|
|
332
|
+
* Use this to inject offline toggles into your HTML
|
|
333
|
+
*/
|
|
334
|
+
function createOfflineTogglesScript(toggles) {
|
|
335
|
+
return `<script>window.__TOGGLELY_TOGGLES = ${JSON.stringify(toggles)};</script>`;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Helper to convert toggles to environment variables
|
|
339
|
+
*/
|
|
340
|
+
function togglesToEnvVars(toggles, prefix = 'TOGGLELY_') {
|
|
341
|
+
const envVars = {};
|
|
342
|
+
for (const [key, value] of Object.entries(toggles)) {
|
|
343
|
+
const envKey = prefix + key.toUpperCase().replace(/-/g, '_');
|
|
344
|
+
envVars[envKey] = typeof value === 'object' ? JSON.stringify(value) : String(value);
|
|
345
|
+
}
|
|
346
|
+
return envVars;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
exports.TogglelyClient = TogglelyClient;
|
|
350
|
+
exports.createOfflineTogglesScript = createOfflineTogglesScript;
|
|
351
|
+
exports.default = TogglelyClient;
|
|
352
|
+
exports.togglesToEnvVars = togglesToEnvVars;
|
|
353
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|