@getlimelight/sdk 0.7.9 → 0.7.11
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 +19 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +142 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +142 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -137,6 +137,25 @@ Client (fetch) → Your Server (middleware) → Downstream Service (http interce
|
|
|
137
137
|
|
|
138
138
|
No additional setup is required — just connect the SDK and add the middleware.
|
|
139
139
|
|
|
140
|
+
## Telemetry
|
|
141
|
+
|
|
142
|
+
The SDK collects **anonymous** usage telemetry to help us understand adoption and improve the product. **No runtime data, user code, network request bodies, state values, or anything from your app is ever sent.** Only:
|
|
143
|
+
|
|
144
|
+
- Framework type (react, react-native, next, node)
|
|
145
|
+
- SDK version
|
|
146
|
+
- Event counts and session durations
|
|
147
|
+
- A random anonymous device ID (not tied to any user identity)
|
|
148
|
+
|
|
149
|
+
Telemetry is **enabled by default**. To opt out:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
Limelight.connect({
|
|
153
|
+
telemetry: false,
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
When `telemetry` is `false`, no events are sent and no anonymous ID is generated or stored.
|
|
158
|
+
|
|
140
159
|
## Learn More
|
|
141
160
|
|
|
142
161
|
- [Quick Start Guide](https://docs.getlimelight.io/quickstart)
|
package/dist/index.d.mts
CHANGED
|
@@ -461,6 +461,12 @@ interface LimelightConfig {
|
|
|
461
461
|
* Limelight.connect({ webSocketImpl: WebSocket });
|
|
462
462
|
*/
|
|
463
463
|
webSocketImpl?: new (url: string, protocols?: string | string[]) => WebSocket;
|
|
464
|
+
/**
|
|
465
|
+
* Enable anonymous usage telemetry. Only sends event counts, durations,
|
|
466
|
+
* and framework type — never any runtime data, user code, or request content.
|
|
467
|
+
* @default true
|
|
468
|
+
*/
|
|
469
|
+
telemetry?: boolean;
|
|
464
470
|
}
|
|
465
471
|
/**
|
|
466
472
|
* Represents a connection or disconnection event in the Limelight SDK.
|
|
@@ -571,6 +577,8 @@ declare class LimelightClient {
|
|
|
571
577
|
private reconnectTimer;
|
|
572
578
|
private messageQueue;
|
|
573
579
|
private maxQueueSize;
|
|
580
|
+
private sessionStartTime;
|
|
581
|
+
private sessionEventCount;
|
|
574
582
|
private networkInterceptor;
|
|
575
583
|
private xhrInterceptor;
|
|
576
584
|
private httpInterceptor;
|
package/dist/index.d.ts
CHANGED
|
@@ -461,6 +461,12 @@ interface LimelightConfig {
|
|
|
461
461
|
* Limelight.connect({ webSocketImpl: WebSocket });
|
|
462
462
|
*/
|
|
463
463
|
webSocketImpl?: new (url: string, protocols?: string | string[]) => WebSocket;
|
|
464
|
+
/**
|
|
465
|
+
* Enable anonymous usage telemetry. Only sends event counts, durations,
|
|
466
|
+
* and framework type — never any runtime data, user code, or request content.
|
|
467
|
+
* @default true
|
|
468
|
+
*/
|
|
469
|
+
telemetry?: boolean;
|
|
464
470
|
}
|
|
465
471
|
/**
|
|
466
472
|
* Represents a connection or disconnection event in the Limelight SDK.
|
|
@@ -571,6 +577,8 @@ declare class LimelightClient {
|
|
|
571
577
|
private reconnectTimer;
|
|
572
578
|
private messageQueue;
|
|
573
579
|
private maxQueueSize;
|
|
580
|
+
private sessionStartTime;
|
|
581
|
+
private sessionEventCount;
|
|
574
582
|
private networkInterceptor;
|
|
575
583
|
private xhrInterceptor;
|
|
576
584
|
private httpInterceptor;
|
package/dist/index.js
CHANGED
|
@@ -292,7 +292,7 @@ var LIMELIGHT_WEB_WSS_URL = "wss://api.getlimelight.io";
|
|
|
292
292
|
var LIMELIGHT_DESKTOP_WSS_URL = "ws://localhost:8484";
|
|
293
293
|
var LIMELIGHT_MCP_WS_URL = "ws://localhost:9229";
|
|
294
294
|
var WS_PATH = "/limelight";
|
|
295
|
-
var SDK_VERSION = true ? "0.7.
|
|
295
|
+
var SDK_VERSION = true ? "0.7.11" : "test-version";
|
|
296
296
|
var RENDER_THRESHOLDS = {
|
|
297
297
|
HOT_VELOCITY: 5,
|
|
298
298
|
HIGH_RENDER_COUNT: 50,
|
|
@@ -316,6 +316,9 @@ var BINARY_CONTENT_TYPES = [
|
|
|
316
316
|
"application/gzip"
|
|
317
317
|
];
|
|
318
318
|
var MAX_BODY_SIZE = 1024 * 1024;
|
|
319
|
+
var POSTHOG_API_KEY = true ? "phc_I4dF0Du3McRPRCdSiJfvTBMWrbsapXoTP83uaHTA1ry" : "";
|
|
320
|
+
var POSTHOG_HOST = true ? "https://us.i.posthog.com" : "";
|
|
321
|
+
var STORAGE_KEY = "limelight_anon_id";
|
|
319
322
|
|
|
320
323
|
// src/helpers/safety/redactSensitiveHeaders.ts
|
|
321
324
|
var redactSensitiveHeaders = (headers) => {
|
|
@@ -558,6 +561,7 @@ var formatRequestName = (url) => {
|
|
|
558
561
|
|
|
559
562
|
// src/helpers/utils/environment.ts
|
|
560
563
|
var hasDOM = () => typeof window !== "undefined" && typeof document !== "undefined";
|
|
564
|
+
var isServer = () => !hasDOM() && typeof process !== "undefined" && typeof process.versions !== "undefined" && typeof process.versions.node !== "undefined";
|
|
561
565
|
|
|
562
566
|
// src/helpers/render/generateRenderId.ts
|
|
563
567
|
var counter = 0;
|
|
@@ -2946,6 +2950,119 @@ var createWithLimelight = (sendMessage, getSessionId, getConfig, options) => {
|
|
|
2946
2950
|
};
|
|
2947
2951
|
};
|
|
2948
2952
|
|
|
2953
|
+
// src/limelight/telemetry.ts
|
|
2954
|
+
var anonymousId = null;
|
|
2955
|
+
var enabled = false;
|
|
2956
|
+
var framework = "unknown";
|
|
2957
|
+
var detectFramework = () => {
|
|
2958
|
+
try {
|
|
2959
|
+
if (typeof navigator !== "undefined" && "ReactNative" in navigator)
|
|
2960
|
+
return "react-native";
|
|
2961
|
+
if (typeof process !== "undefined" && (process.env?.__NEXT_RUNTIME__ || process.env?.NEXT_RUNTIME))
|
|
2962
|
+
return "next";
|
|
2963
|
+
if (typeof window !== "undefined" && window.__NEXT_DATA__)
|
|
2964
|
+
return "next";
|
|
2965
|
+
if (hasDOM()) return "react";
|
|
2966
|
+
if (isServer()) return "node";
|
|
2967
|
+
} catch {
|
|
2968
|
+
}
|
|
2969
|
+
return "unknown";
|
|
2970
|
+
};
|
|
2971
|
+
var generateId = () => {
|
|
2972
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
2973
|
+
const r = Math.random() * 16 | 0;
|
|
2974
|
+
return (c === "x" ? r : r & 3 | 8).toString(16);
|
|
2975
|
+
});
|
|
2976
|
+
};
|
|
2977
|
+
var getOrCreateAnonymousId = () => {
|
|
2978
|
+
if (anonymousId) return anonymousId;
|
|
2979
|
+
try {
|
|
2980
|
+
if (typeof localStorage !== "undefined") {
|
|
2981
|
+
const stored = localStorage.getItem(STORAGE_KEY);
|
|
2982
|
+
if (stored) {
|
|
2983
|
+
anonymousId = stored;
|
|
2984
|
+
return anonymousId;
|
|
2985
|
+
}
|
|
2986
|
+
anonymousId = generateId();
|
|
2987
|
+
localStorage.setItem(STORAGE_KEY, anonymousId);
|
|
2988
|
+
return anonymousId;
|
|
2989
|
+
}
|
|
2990
|
+
} catch {
|
|
2991
|
+
}
|
|
2992
|
+
try {
|
|
2993
|
+
const _require = globalThis["require"];
|
|
2994
|
+
if (_require) {
|
|
2995
|
+
const fs = _require("fs");
|
|
2996
|
+
const os = _require("os");
|
|
2997
|
+
const path = _require("path");
|
|
2998
|
+
const filePath = path.join(os.homedir(), ".limelight_telemetry_id");
|
|
2999
|
+
try {
|
|
3000
|
+
anonymousId = fs.readFileSync(filePath, "utf-8").trim();
|
|
3001
|
+
if (anonymousId) return anonymousId;
|
|
3002
|
+
} catch {
|
|
3003
|
+
}
|
|
3004
|
+
anonymousId = generateId();
|
|
3005
|
+
fs.writeFileSync(filePath, anonymousId, "utf-8");
|
|
3006
|
+
return anonymousId;
|
|
3007
|
+
}
|
|
3008
|
+
} catch {
|
|
3009
|
+
}
|
|
3010
|
+
anonymousId = generateId();
|
|
3011
|
+
return anonymousId;
|
|
3012
|
+
};
|
|
3013
|
+
var capture = (event, properties = {}) => {
|
|
3014
|
+
if (!enabled) return;
|
|
3015
|
+
try {
|
|
3016
|
+
const payload = {
|
|
3017
|
+
api_key: POSTHOG_API_KEY,
|
|
3018
|
+
event,
|
|
3019
|
+
distinct_id: getOrCreateAnonymousId(),
|
|
3020
|
+
properties: {
|
|
3021
|
+
...properties,
|
|
3022
|
+
sdk_version: SDK_VERSION,
|
|
3023
|
+
framework
|
|
3024
|
+
}
|
|
3025
|
+
};
|
|
3026
|
+
fetch(`${POSTHOG_HOST}/capture/`, {
|
|
3027
|
+
method: "POST",
|
|
3028
|
+
headers: { "Content-Type": "application/json" },
|
|
3029
|
+
body: JSON.stringify(payload)
|
|
3030
|
+
}).catch(() => {
|
|
3031
|
+
});
|
|
3032
|
+
} catch {
|
|
3033
|
+
}
|
|
3034
|
+
};
|
|
3035
|
+
var telemetry = {
|
|
3036
|
+
init(telemetryEnabled) {
|
|
3037
|
+
enabled = telemetryEnabled;
|
|
3038
|
+
if (!enabled) return;
|
|
3039
|
+
framework = detectFramework();
|
|
3040
|
+
capture("sdk_initialized", {
|
|
3041
|
+
framework,
|
|
3042
|
+
device_id: getOrCreateAnonymousId()
|
|
3043
|
+
});
|
|
3044
|
+
},
|
|
3045
|
+
sessionStarted() {
|
|
3046
|
+
capture("session_started");
|
|
3047
|
+
},
|
|
3048
|
+
sessionEnded(durationSeconds, eventCount) {
|
|
3049
|
+
capture("session_ended", {
|
|
3050
|
+
duration_seconds: durationSeconds,
|
|
3051
|
+
event_count: eventCount
|
|
3052
|
+
});
|
|
3053
|
+
},
|
|
3054
|
+
timelineGenerated(eventsCorrelated) {
|
|
3055
|
+
capture("timeline_generated", {
|
|
3056
|
+
events_correlated: eventsCorrelated,
|
|
3057
|
+
framework
|
|
3058
|
+
});
|
|
3059
|
+
},
|
|
3060
|
+
shutdown() {
|
|
3061
|
+
enabled = false;
|
|
3062
|
+
anonymousId = null;
|
|
3063
|
+
}
|
|
3064
|
+
};
|
|
3065
|
+
|
|
2949
3066
|
// src/limelight/LimelightClient.ts
|
|
2950
3067
|
var LimelightClient = class {
|
|
2951
3068
|
ws = null;
|
|
@@ -2957,6 +3074,8 @@ var LimelightClient = class {
|
|
|
2957
3074
|
reconnectTimer = null;
|
|
2958
3075
|
messageQueue = [];
|
|
2959
3076
|
maxQueueSize = 100;
|
|
3077
|
+
sessionStartTime = 0;
|
|
3078
|
+
sessionEventCount = 0;
|
|
2960
3079
|
networkInterceptor;
|
|
2961
3080
|
xhrInterceptor;
|
|
2962
3081
|
httpInterceptor;
|
|
@@ -3039,17 +3158,17 @@ var LimelightClient = class {
|
|
|
3039
3158
|
if (typeof XMLHttpRequest !== "undefined") {
|
|
3040
3159
|
this.xhrInterceptor.setup(this.config);
|
|
3041
3160
|
}
|
|
3042
|
-
if (
|
|
3161
|
+
if (isServer()) {
|
|
3043
3162
|
this.httpInterceptor.setup(this.config);
|
|
3044
3163
|
}
|
|
3045
3164
|
}
|
|
3046
3165
|
if (this.config.enableConsole) {
|
|
3047
3166
|
this.consoleInterceptor.setup(this.config);
|
|
3048
|
-
if (
|
|
3167
|
+
if (isServer()) {
|
|
3049
3168
|
this.errorInterceptor.setup(this.config);
|
|
3050
3169
|
}
|
|
3051
3170
|
}
|
|
3052
|
-
if (this.config.enableRenderInspector &&
|
|
3171
|
+
if (this.config.enableRenderInspector && !isServer()) {
|
|
3053
3172
|
this.renderInterceptor.setup(this.config);
|
|
3054
3173
|
}
|
|
3055
3174
|
if (this.config.stores && this.config.enableStateInspector) {
|
|
@@ -3060,6 +3179,7 @@ var LimelightClient = class {
|
|
|
3060
3179
|
console.error("[Limelight] Failed to setup interceptors:", error);
|
|
3061
3180
|
}
|
|
3062
3181
|
}
|
|
3182
|
+
telemetry.init(this.config.telemetry ?? true);
|
|
3063
3183
|
}
|
|
3064
3184
|
/**
|
|
3065
3185
|
* Establishes a WebSocket connection to the Limelight server.
|
|
@@ -3124,8 +3244,11 @@ var LimelightClient = class {
|
|
|
3124
3244
|
};
|
|
3125
3245
|
this.ws.onopen = () => {
|
|
3126
3246
|
this.reconnectAttempts = 0;
|
|
3247
|
+
this.sessionStartTime = Date.now();
|
|
3248
|
+
this.sessionEventCount = 0;
|
|
3127
3249
|
this.flushMessageQueue();
|
|
3128
3250
|
this.sendMessage(message);
|
|
3251
|
+
telemetry.sessionStarted();
|
|
3129
3252
|
};
|
|
3130
3253
|
this.ws.onmessage = (event) => {
|
|
3131
3254
|
try {
|
|
@@ -3208,6 +3331,12 @@ var LimelightClient = class {
|
|
|
3208
3331
|
* @returns {void}
|
|
3209
3332
|
*/
|
|
3210
3333
|
sendMessage(message) {
|
|
3334
|
+
this.sessionEventCount++;
|
|
3335
|
+
if ("phase" in message && message.phase === "RENDER_SNAPSHOT" && "profiles" in message) {
|
|
3336
|
+
telemetry.timelineGenerated(
|
|
3337
|
+
message.profiles?.length ?? 0
|
|
3338
|
+
);
|
|
3339
|
+
}
|
|
3211
3340
|
if (this.ws?.readyState === 1) {
|
|
3212
3341
|
this.flushMessageQueue();
|
|
3213
3342
|
if (this.ws?.readyState === 1) {
|
|
@@ -3273,7 +3402,15 @@ var LimelightClient = class {
|
|
|
3273
3402
|
this.renderInterceptor.cleanup();
|
|
3274
3403
|
this.stateInterceptor.cleanup();
|
|
3275
3404
|
this.requestBridge.cleanup();
|
|
3405
|
+
if (this.sessionStartTime > 0) {
|
|
3406
|
+
const durationSeconds = Math.round(
|
|
3407
|
+
(Date.now() - this.sessionStartTime) / 1e3
|
|
3408
|
+
);
|
|
3409
|
+
telemetry.sessionEnded(durationSeconds, this.sessionEventCount);
|
|
3410
|
+
}
|
|
3276
3411
|
this.reconnectAttempts = 0;
|
|
3412
|
+
this.sessionStartTime = 0;
|
|
3413
|
+
this.sessionEventCount = 0;
|
|
3277
3414
|
this.messageQueue = [];
|
|
3278
3415
|
}
|
|
3279
3416
|
/**
|
|
@@ -3284,6 +3421,7 @@ var LimelightClient = class {
|
|
|
3284
3421
|
*/
|
|
3285
3422
|
reset() {
|
|
3286
3423
|
this.disconnect();
|
|
3424
|
+
telemetry.shutdown();
|
|
3287
3425
|
this.config = null;
|
|
3288
3426
|
this.sessionId = "";
|
|
3289
3427
|
}
|