@getlimelight/sdk 0.7.10 → 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 +138 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +138 -1
- 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) => {
|
|
@@ -2947,6 +2950,119 @@ var createWithLimelight = (sendMessage, getSessionId, getConfig, options) => {
|
|
|
2947
2950
|
};
|
|
2948
2951
|
};
|
|
2949
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
|
+
|
|
2950
3066
|
// src/limelight/LimelightClient.ts
|
|
2951
3067
|
var LimelightClient = class {
|
|
2952
3068
|
ws = null;
|
|
@@ -2958,6 +3074,8 @@ var LimelightClient = class {
|
|
|
2958
3074
|
reconnectTimer = null;
|
|
2959
3075
|
messageQueue = [];
|
|
2960
3076
|
maxQueueSize = 100;
|
|
3077
|
+
sessionStartTime = 0;
|
|
3078
|
+
sessionEventCount = 0;
|
|
2961
3079
|
networkInterceptor;
|
|
2962
3080
|
xhrInterceptor;
|
|
2963
3081
|
httpInterceptor;
|
|
@@ -3061,6 +3179,7 @@ var LimelightClient = class {
|
|
|
3061
3179
|
console.error("[Limelight] Failed to setup interceptors:", error);
|
|
3062
3180
|
}
|
|
3063
3181
|
}
|
|
3182
|
+
telemetry.init(this.config.telemetry ?? true);
|
|
3064
3183
|
}
|
|
3065
3184
|
/**
|
|
3066
3185
|
* Establishes a WebSocket connection to the Limelight server.
|
|
@@ -3125,8 +3244,11 @@ var LimelightClient = class {
|
|
|
3125
3244
|
};
|
|
3126
3245
|
this.ws.onopen = () => {
|
|
3127
3246
|
this.reconnectAttempts = 0;
|
|
3247
|
+
this.sessionStartTime = Date.now();
|
|
3248
|
+
this.sessionEventCount = 0;
|
|
3128
3249
|
this.flushMessageQueue();
|
|
3129
3250
|
this.sendMessage(message);
|
|
3251
|
+
telemetry.sessionStarted();
|
|
3130
3252
|
};
|
|
3131
3253
|
this.ws.onmessage = (event) => {
|
|
3132
3254
|
try {
|
|
@@ -3209,6 +3331,12 @@ var LimelightClient = class {
|
|
|
3209
3331
|
* @returns {void}
|
|
3210
3332
|
*/
|
|
3211
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
|
+
}
|
|
3212
3340
|
if (this.ws?.readyState === 1) {
|
|
3213
3341
|
this.flushMessageQueue();
|
|
3214
3342
|
if (this.ws?.readyState === 1) {
|
|
@@ -3274,7 +3402,15 @@ var LimelightClient = class {
|
|
|
3274
3402
|
this.renderInterceptor.cleanup();
|
|
3275
3403
|
this.stateInterceptor.cleanup();
|
|
3276
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
|
+
}
|
|
3277
3411
|
this.reconnectAttempts = 0;
|
|
3412
|
+
this.sessionStartTime = 0;
|
|
3413
|
+
this.sessionEventCount = 0;
|
|
3278
3414
|
this.messageQueue = [];
|
|
3279
3415
|
}
|
|
3280
3416
|
/**
|
|
@@ -3285,6 +3421,7 @@ var LimelightClient = class {
|
|
|
3285
3421
|
*/
|
|
3286
3422
|
reset() {
|
|
3287
3423
|
this.disconnect();
|
|
3424
|
+
telemetry.shutdown();
|
|
3288
3425
|
this.config = null;
|
|
3289
3426
|
this.sessionId = "";
|
|
3290
3427
|
}
|