@emit-vision/sdk-js 0.4.2 → 0.4.3
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 +4 -0
- package/dist/index.js +33 -8
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -218,3 +218,7 @@ init({
|
|
|
218
218
|
- Do not use `email` or `username` as the `evaluationKey` — use an opaque user ID or session ID.
|
|
219
219
|
- Use the helper packages when they reduce boilerplate, but keep direct browser
|
|
220
220
|
SDK usage for the simplest client-side apps.
|
|
221
|
+
|
|
222
|
+
## License
|
|
223
|
+
|
|
224
|
+
MIT — see [LICENSE](./LICENSE).
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
// src/flag-eval.ts
|
|
2
|
+
function cacheKeyFor(env, opts) {
|
|
3
|
+
const keys = opts.flagKeys?.length ? [...opts.flagKeys].sort().join(",") : "*";
|
|
4
|
+
return `${env}:${opts.evaluationKey}:${keys}`;
|
|
5
|
+
}
|
|
2
6
|
var FlagEvaluator = class {
|
|
3
7
|
constructor(cfg, onFlagsLoaded, captureExposure2, debug) {
|
|
4
8
|
this.cfg = cfg;
|
|
@@ -14,7 +18,7 @@ var FlagEvaluator = class {
|
|
|
14
18
|
async evaluateFlags(opts) {
|
|
15
19
|
const env = opts.environment ?? "";
|
|
16
20
|
const ttl = opts.ttlMs ?? this.cfg.ttlMs;
|
|
17
|
-
const key =
|
|
21
|
+
const key = cacheKeyFor(env, opts);
|
|
18
22
|
const cached = this.cache.get(key);
|
|
19
23
|
if (cached && Date.now() < cached.expiresAt) {
|
|
20
24
|
this.debug("flag eval cache hit", { key });
|
|
@@ -24,7 +28,9 @@ var FlagEvaluator = class {
|
|
|
24
28
|
}
|
|
25
29
|
async getFlag(flagKey, fallback, opts) {
|
|
26
30
|
try {
|
|
27
|
-
const flags = await this.evaluateFlags(
|
|
31
|
+
const flags = await this.evaluateFlags(
|
|
32
|
+
opts.flagKeys?.length ? opts : { ...opts, flagKeys: [flagKey] }
|
|
33
|
+
);
|
|
28
34
|
const value = flags[flagKey];
|
|
29
35
|
return value !== void 0 ? value : fallback;
|
|
30
36
|
} catch {
|
|
@@ -34,7 +40,7 @@ var FlagEvaluator = class {
|
|
|
34
40
|
async refreshFlags(opts) {
|
|
35
41
|
const env = opts.environment ?? "";
|
|
36
42
|
const ttl = opts.ttlMs ?? this.cfg.ttlMs;
|
|
37
|
-
const key =
|
|
43
|
+
const key = cacheKeyFor(env, opts);
|
|
38
44
|
this.cache.delete(key);
|
|
39
45
|
return this.fetchAndCacheFlags(opts, env, ttl, key);
|
|
40
46
|
}
|
|
@@ -157,6 +163,15 @@ function resolveAutoCapture(options) {
|
|
|
157
163
|
};
|
|
158
164
|
}
|
|
159
165
|
|
|
166
|
+
// src/compress.ts
|
|
167
|
+
var COMPRESS_THRESHOLD_BYTES = 8 * 1024;
|
|
168
|
+
async function gzipBatchBody(body) {
|
|
169
|
+
if (typeof CompressionStream !== "function") return null;
|
|
170
|
+
const stream = new Blob([body]).stream().pipeThrough(new CompressionStream("gzip"));
|
|
171
|
+
const buffer = await new Response(stream).arrayBuffer();
|
|
172
|
+
return new Uint8Array(buffer);
|
|
173
|
+
}
|
|
174
|
+
|
|
160
175
|
// src/client-helpers.ts
|
|
161
176
|
var SDK_NAME = "emit-vision-js";
|
|
162
177
|
var SDK_VERSION = "0.4.0";
|
|
@@ -292,18 +307,28 @@ var FlushHttpError = class extends Error {
|
|
|
292
307
|
serverMessage;
|
|
293
308
|
};
|
|
294
309
|
async function executeHttpSend(chunk, endpoint, apiKey, fetchImpl) {
|
|
310
|
+
const body = buildBatchBody(chunk);
|
|
311
|
+
const compressed = byteLength(body) >= COMPRESS_THRESHOLD_BYTES ? await gzipBatchBody(body) : null;
|
|
295
312
|
const response = await fetchImpl(`${endpoint}/v1/batch`, {
|
|
296
313
|
method: "POST",
|
|
297
|
-
headers: {
|
|
298
|
-
|
|
299
|
-
|
|
314
|
+
headers: {
|
|
315
|
+
"content-type": "application/json",
|
|
316
|
+
"x-emit-api-key": apiKey,
|
|
317
|
+
...compressed ? { "content-encoding": "gzip" } : {}
|
|
318
|
+
},
|
|
319
|
+
body: compressed ?? body,
|
|
320
|
+
// keepalive lets a flush survive page unload, but browsers cap keepalive
|
|
321
|
+
// request bytes at ~64 KB total per page — a compressed send can be far
|
|
322
|
+
// bigger than that, so it skips keepalive and relies on the queue/retry
|
|
323
|
+
// path instead. Only the small, uncompressed path keeps the guarantee.
|
|
324
|
+
...compressed ? {} : { keepalive: true }
|
|
300
325
|
});
|
|
301
326
|
if (!response.ok) {
|
|
302
327
|
const retryAfter = Number(response.headers?.get?.("retry-after"));
|
|
303
328
|
let serverMessage;
|
|
304
329
|
try {
|
|
305
|
-
const
|
|
306
|
-
if (
|
|
330
|
+
const body2 = await response.json();
|
|
331
|
+
if (body2 && typeof body2.message === "string") serverMessage = body2.message;
|
|
307
332
|
} catch {
|
|
308
333
|
}
|
|
309
334
|
throw new FlushHttpError(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@emit-vision/sdk-js",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Browser SDK for self-hosted emit-vision analytics and error tracking.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,6 +33,11 @@
|
|
|
33
33
|
"default": "./dist/index.js"
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsup --config tsup.config.ts",
|
|
38
|
+
"size": "size-limit",
|
|
39
|
+
"prepack": "pnpm run build"
|
|
40
|
+
},
|
|
36
41
|
"size-limit": [
|
|
37
42
|
{
|
|
38
43
|
"name": "@emit-vision/sdk-js (gzip)",
|
|
@@ -43,9 +48,5 @@
|
|
|
43
48
|
"devDependencies": {
|
|
44
49
|
"@size-limit/file": "^11.1.6",
|
|
45
50
|
"size-limit": "^11.1.6"
|
|
46
|
-
},
|
|
47
|
-
"scripts": {
|
|
48
|
-
"build": "tsup --config tsup.config.ts",
|
|
49
|
-
"size": "size-limit"
|
|
50
51
|
}
|
|
51
|
-
}
|
|
52
|
+
}
|