@flaggly/sdk 0.0.5 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.js +32 -11
- package/dist/index.mjs +32 -11
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -35,6 +35,14 @@ type EvaluatedFlags<FD extends FlagSchema = FlagSchema> = {
|
|
|
35
35
|
result: FlagValue<FD[K]>;
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* Defines a custom storage interface for handling backup identifiers.
|
|
40
|
+
* This allows for persistence in environments where localStorage is not available (e.g., server-side).
|
|
41
|
+
*/
|
|
42
|
+
type CustomStorage = {
|
|
43
|
+
getItem(key: string): string | null;
|
|
44
|
+
setItem(key: string, value: string): void;
|
|
45
|
+
};
|
|
38
46
|
type FlagglyOptions<TFlags extends FlagSchema = FlagSchema> = {
|
|
39
47
|
/**
|
|
40
48
|
* The base URL of your Flaggly worker.
|
|
@@ -86,6 +94,21 @@ type FlagglyOptions<TFlags extends FlagSchema = FlagSchema> = {
|
|
|
86
94
|
* @see https://developers.cloudflare.com/workers/observability/errors/#illegal-invocation-errors
|
|
87
95
|
*/
|
|
88
96
|
workerFetch?: typeof fetch;
|
|
97
|
+
/**
|
|
98
|
+
* Optional custom storage implementation for backup IDs, for anonymous users.
|
|
99
|
+
* By default, it will use localStorage in browser environments.
|
|
100
|
+
* If localStorage is not available, a new ID will be generated on each request.
|
|
101
|
+
*/
|
|
102
|
+
customStorage?: CustomStorage;
|
|
103
|
+
/**
|
|
104
|
+
* Optional method to provide the current route/URL in non-browser environments.
|
|
105
|
+
* By default, it uses `window.location.href`.
|
|
106
|
+
*/
|
|
107
|
+
getCurrentRoute?: () => string | null;
|
|
108
|
+
/**
|
|
109
|
+
* Optional method to stub for `crypo.randomUUID` method in non-browser environments.
|
|
110
|
+
*/
|
|
111
|
+
getRandomId?: () => string;
|
|
89
112
|
};
|
|
90
113
|
declare class Flaggly<TFlags extends FlagSchema = FlagSchema> {
|
|
91
114
|
#private;
|
|
@@ -93,11 +116,14 @@ declare class Flaggly<TFlags extends FlagSchema = FlagSchema> {
|
|
|
93
116
|
private apiKey;
|
|
94
117
|
private app;
|
|
95
118
|
private env;
|
|
119
|
+
private storage;
|
|
120
|
+
private getCurrentRoute?;
|
|
96
121
|
user?: unknown;
|
|
97
122
|
id?: string;
|
|
98
123
|
workerFetch: typeof fetch;
|
|
99
124
|
getBackupId?: () => string;
|
|
100
|
-
|
|
125
|
+
getRandomId: () => string;
|
|
126
|
+
constructor({ url, apiKey, app, env, lazy, bootstrap, getBackupId, workerFetch, customStorage, getCurrentRoute, getRandomId, }: FlagglyOptions<TFlags>);
|
|
101
127
|
/**
|
|
102
128
|
* Method to identify a user and persist the ID and details for evaluations.
|
|
103
129
|
* Calling this method will evaluate the flags and reset the state.
|
|
@@ -165,4 +191,4 @@ declare class Flaggly<TFlags extends FlagSchema = FlagSchema> {
|
|
|
165
191
|
get store(): MapStore<EvaluatedFlags<TFlags>>;
|
|
166
192
|
}
|
|
167
193
|
|
|
168
|
-
export { type EvaluatedFlags, type FlagConfig, type FlagInput, type FlagSchema, type FlagValue, type FlagValues, Flaggly, type FlagglyOptions };
|
|
194
|
+
export { type CustomStorage, type EvaluatedFlags, type FlagConfig, type FlagInput, type FlagSchema, type FlagValue, type FlagValues, Flaggly, type FlagglyOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -35,6 +35,14 @@ type EvaluatedFlags<FD extends FlagSchema = FlagSchema> = {
|
|
|
35
35
|
result: FlagValue<FD[K]>;
|
|
36
36
|
};
|
|
37
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* Defines a custom storage interface for handling backup identifiers.
|
|
40
|
+
* This allows for persistence in environments where localStorage is not available (e.g., server-side).
|
|
41
|
+
*/
|
|
42
|
+
type CustomStorage = {
|
|
43
|
+
getItem(key: string): string | null;
|
|
44
|
+
setItem(key: string, value: string): void;
|
|
45
|
+
};
|
|
38
46
|
type FlagglyOptions<TFlags extends FlagSchema = FlagSchema> = {
|
|
39
47
|
/**
|
|
40
48
|
* The base URL of your Flaggly worker.
|
|
@@ -86,6 +94,21 @@ type FlagglyOptions<TFlags extends FlagSchema = FlagSchema> = {
|
|
|
86
94
|
* @see https://developers.cloudflare.com/workers/observability/errors/#illegal-invocation-errors
|
|
87
95
|
*/
|
|
88
96
|
workerFetch?: typeof fetch;
|
|
97
|
+
/**
|
|
98
|
+
* Optional custom storage implementation for backup IDs, for anonymous users.
|
|
99
|
+
* By default, it will use localStorage in browser environments.
|
|
100
|
+
* If localStorage is not available, a new ID will be generated on each request.
|
|
101
|
+
*/
|
|
102
|
+
customStorage?: CustomStorage;
|
|
103
|
+
/**
|
|
104
|
+
* Optional method to provide the current route/URL in non-browser environments.
|
|
105
|
+
* By default, it uses `window.location.href`.
|
|
106
|
+
*/
|
|
107
|
+
getCurrentRoute?: () => string | null;
|
|
108
|
+
/**
|
|
109
|
+
* Optional method to stub for `crypo.randomUUID` method in non-browser environments.
|
|
110
|
+
*/
|
|
111
|
+
getRandomId?: () => string;
|
|
89
112
|
};
|
|
90
113
|
declare class Flaggly<TFlags extends FlagSchema = FlagSchema> {
|
|
91
114
|
#private;
|
|
@@ -93,11 +116,14 @@ declare class Flaggly<TFlags extends FlagSchema = FlagSchema> {
|
|
|
93
116
|
private apiKey;
|
|
94
117
|
private app;
|
|
95
118
|
private env;
|
|
119
|
+
private storage;
|
|
120
|
+
private getCurrentRoute?;
|
|
96
121
|
user?: unknown;
|
|
97
122
|
id?: string;
|
|
98
123
|
workerFetch: typeof fetch;
|
|
99
124
|
getBackupId?: () => string;
|
|
100
|
-
|
|
125
|
+
getRandomId: () => string;
|
|
126
|
+
constructor({ url, apiKey, app, env, lazy, bootstrap, getBackupId, workerFetch, customStorage, getCurrentRoute, getRandomId, }: FlagglyOptions<TFlags>);
|
|
101
127
|
/**
|
|
102
128
|
* Method to identify a user and persist the ID and details for evaluations.
|
|
103
129
|
* Calling this method will evaluate the flags and reset the state.
|
|
@@ -165,4 +191,4 @@ declare class Flaggly<TFlags extends FlagSchema = FlagSchema> {
|
|
|
165
191
|
get store(): MapStore<EvaluatedFlags<TFlags>>;
|
|
166
192
|
}
|
|
167
193
|
|
|
168
|
-
export { type EvaluatedFlags, type FlagConfig, type FlagInput, type FlagSchema, type FlagValue, type FlagValues, Flaggly, type FlagglyOptions };
|
|
194
|
+
export { type CustomStorage, type EvaluatedFlags, type FlagConfig, type FlagInput, type FlagSchema, type FlagValue, type FlagValues, Flaggly, type FlagglyOptions };
|
package/dist/index.js
CHANGED
|
@@ -131,10 +131,13 @@ var Flaggly = class {
|
|
|
131
131
|
apiKey;
|
|
132
132
|
app;
|
|
133
133
|
env;
|
|
134
|
+
storage;
|
|
135
|
+
getCurrentRoute;
|
|
134
136
|
user;
|
|
135
137
|
id;
|
|
136
138
|
workerFetch;
|
|
137
139
|
getBackupId;
|
|
140
|
+
getRandomId;
|
|
138
141
|
#flags = map();
|
|
139
142
|
constructor({
|
|
140
143
|
url,
|
|
@@ -144,14 +147,32 @@ var Flaggly = class {
|
|
|
144
147
|
lazy = false,
|
|
145
148
|
bootstrap,
|
|
146
149
|
getBackupId,
|
|
147
|
-
workerFetch
|
|
150
|
+
workerFetch,
|
|
151
|
+
customStorage,
|
|
152
|
+
getCurrentRoute,
|
|
153
|
+
getRandomId
|
|
148
154
|
}) {
|
|
149
155
|
this.url = url;
|
|
150
156
|
this.apiKey = apiKey;
|
|
151
157
|
this.app = app;
|
|
152
158
|
this.env = env;
|
|
153
159
|
this.getBackupId = getBackupId;
|
|
160
|
+
this.getCurrentRoute = getCurrentRoute;
|
|
154
161
|
this.workerFetch = workerFetch ?? fetch;
|
|
162
|
+
this.getRandomId = getRandomId ?? globalThis.crypto.randomUUID;
|
|
163
|
+
this.storage = customStorage ?? {
|
|
164
|
+
getItem: (key) => {
|
|
165
|
+
if ("localStorage" in globalThis) {
|
|
166
|
+
return globalThis.localStorage.getItem(key);
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
},
|
|
170
|
+
setItem: (key, value) => {
|
|
171
|
+
if ("localStorage" in globalThis) {
|
|
172
|
+
globalThis.localStorage.setItem(key, value);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
155
176
|
const defValues = bootstrap ? Object.entries(bootstrap).reduce(
|
|
156
177
|
(acc, [flagKey, flagValue]) => {
|
|
157
178
|
const type = typeof flagValue === "boolean" ? "boolean" : typeof flagValue === "string" ? "variant" : "payload";
|
|
@@ -183,6 +204,9 @@ var Flaggly = class {
|
|
|
183
204
|
return await this.fetchFlags({ id, user });
|
|
184
205
|
}
|
|
185
206
|
#getPageUrl() {
|
|
207
|
+
if (this.getCurrentRoute) {
|
|
208
|
+
return this.getCurrentRoute();
|
|
209
|
+
}
|
|
186
210
|
if ("window" in globalThis) {
|
|
187
211
|
return globalThis.window.location.href;
|
|
188
212
|
}
|
|
@@ -192,17 +216,14 @@ var Flaggly = class {
|
|
|
192
216
|
if (this.getBackupId) {
|
|
193
217
|
return this.getBackupId();
|
|
194
218
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
return id;
|
|
202
|
-
}
|
|
203
|
-
return storage;
|
|
219
|
+
const key = `__flaggly_id.${this.app}.${this.env}`;
|
|
220
|
+
const storedId = this.storage.getItem(key);
|
|
221
|
+
if (!storedId) {
|
|
222
|
+
const newId = this.getRandomId();
|
|
223
|
+
this.storage.setItem(key, newId);
|
|
224
|
+
return newId;
|
|
204
225
|
}
|
|
205
|
-
return
|
|
226
|
+
return storedId;
|
|
206
227
|
}
|
|
207
228
|
async #request(path, options = {}) {
|
|
208
229
|
const { method = "POST", body } = options;
|
package/dist/index.mjs
CHANGED
|
@@ -105,10 +105,13 @@ var Flaggly = class {
|
|
|
105
105
|
apiKey;
|
|
106
106
|
app;
|
|
107
107
|
env;
|
|
108
|
+
storage;
|
|
109
|
+
getCurrentRoute;
|
|
108
110
|
user;
|
|
109
111
|
id;
|
|
110
112
|
workerFetch;
|
|
111
113
|
getBackupId;
|
|
114
|
+
getRandomId;
|
|
112
115
|
#flags = map();
|
|
113
116
|
constructor({
|
|
114
117
|
url,
|
|
@@ -118,14 +121,32 @@ var Flaggly = class {
|
|
|
118
121
|
lazy = false,
|
|
119
122
|
bootstrap,
|
|
120
123
|
getBackupId,
|
|
121
|
-
workerFetch
|
|
124
|
+
workerFetch,
|
|
125
|
+
customStorage,
|
|
126
|
+
getCurrentRoute,
|
|
127
|
+
getRandomId
|
|
122
128
|
}) {
|
|
123
129
|
this.url = url;
|
|
124
130
|
this.apiKey = apiKey;
|
|
125
131
|
this.app = app;
|
|
126
132
|
this.env = env;
|
|
127
133
|
this.getBackupId = getBackupId;
|
|
134
|
+
this.getCurrentRoute = getCurrentRoute;
|
|
128
135
|
this.workerFetch = workerFetch ?? fetch;
|
|
136
|
+
this.getRandomId = getRandomId ?? globalThis.crypto.randomUUID;
|
|
137
|
+
this.storage = customStorage ?? {
|
|
138
|
+
getItem: (key) => {
|
|
139
|
+
if ("localStorage" in globalThis) {
|
|
140
|
+
return globalThis.localStorage.getItem(key);
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
},
|
|
144
|
+
setItem: (key, value) => {
|
|
145
|
+
if ("localStorage" in globalThis) {
|
|
146
|
+
globalThis.localStorage.setItem(key, value);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
129
150
|
const defValues = bootstrap ? Object.entries(bootstrap).reduce(
|
|
130
151
|
(acc, [flagKey, flagValue]) => {
|
|
131
152
|
const type = typeof flagValue === "boolean" ? "boolean" : typeof flagValue === "string" ? "variant" : "payload";
|
|
@@ -157,6 +178,9 @@ var Flaggly = class {
|
|
|
157
178
|
return await this.fetchFlags({ id, user });
|
|
158
179
|
}
|
|
159
180
|
#getPageUrl() {
|
|
181
|
+
if (this.getCurrentRoute) {
|
|
182
|
+
return this.getCurrentRoute();
|
|
183
|
+
}
|
|
160
184
|
if ("window" in globalThis) {
|
|
161
185
|
return globalThis.window.location.href;
|
|
162
186
|
}
|
|
@@ -166,17 +190,14 @@ var Flaggly = class {
|
|
|
166
190
|
if (this.getBackupId) {
|
|
167
191
|
return this.getBackupId();
|
|
168
192
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return id;
|
|
176
|
-
}
|
|
177
|
-
return storage;
|
|
193
|
+
const key = `__flaggly_id.${this.app}.${this.env}`;
|
|
194
|
+
const storedId = this.storage.getItem(key);
|
|
195
|
+
if (!storedId) {
|
|
196
|
+
const newId = this.getRandomId();
|
|
197
|
+
this.storage.setItem(key, newId);
|
|
198
|
+
return newId;
|
|
178
199
|
}
|
|
179
|
-
return
|
|
200
|
+
return storedId;
|
|
180
201
|
}
|
|
181
202
|
async #request(path, options = {}) {
|
|
182
203
|
const { method = "POST", body } = options;
|