@getlimelight/sdk 0.4.6 → 0.5.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.mts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +174 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +174 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -210,6 +210,17 @@ declare enum GraphqlOprtation {
|
|
|
210
210
|
SUB = "SUBSCRIPTION"
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
declare enum CommandType {
|
|
214
|
+
CLEAR_RENDERS = "CLEAR_RENDERS",
|
|
215
|
+
ACK = "ACK"
|
|
216
|
+
}
|
|
217
|
+
interface CommandAckEvent {
|
|
218
|
+
phase: CommandType.ACK;
|
|
219
|
+
commandId: string;
|
|
220
|
+
type: CommandType;
|
|
221
|
+
success: boolean;
|
|
222
|
+
}
|
|
223
|
+
|
|
213
224
|
/**
|
|
214
225
|
* Render lifecycle phases
|
|
215
226
|
*/
|
|
@@ -450,7 +461,7 @@ interface ConnectionEvent {
|
|
|
450
461
|
/**
|
|
451
462
|
* Union type representing all possible Limelight messages.
|
|
452
463
|
*/
|
|
453
|
-
type LimelightMessage = NetworkRequest | NetworkResponse | NetworkErrorEvent | ConsoleEvent | ConnectionEvent | RenderSnapshot | TransactionEvent | StateInitEvent | StateUpdateEvent;
|
|
464
|
+
type LimelightMessage = NetworkRequest | NetworkResponse | NetworkErrorEvent | ConsoleEvent | ConnectionEvent | RenderSnapshot | TransactionEvent | StateInitEvent | StateUpdateEvent | CommandAckEvent;
|
|
454
465
|
|
|
455
466
|
/**
|
|
456
467
|
* Represents a single frame in a stack trace.
|
|
@@ -512,6 +523,7 @@ declare class LimelightClient {
|
|
|
512
523
|
private renderInterceptor;
|
|
513
524
|
private stateInterceptor;
|
|
514
525
|
private requestBridge;
|
|
526
|
+
private commandHandler;
|
|
515
527
|
constructor();
|
|
516
528
|
/**
|
|
517
529
|
* Configures the Limelight client with the provided settings.
|
package/dist/index.d.ts
CHANGED
|
@@ -210,6 +210,17 @@ declare enum GraphqlOprtation {
|
|
|
210
210
|
SUB = "SUBSCRIPTION"
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
+
declare enum CommandType {
|
|
214
|
+
CLEAR_RENDERS = "CLEAR_RENDERS",
|
|
215
|
+
ACK = "ACK"
|
|
216
|
+
}
|
|
217
|
+
interface CommandAckEvent {
|
|
218
|
+
phase: CommandType.ACK;
|
|
219
|
+
commandId: string;
|
|
220
|
+
type: CommandType;
|
|
221
|
+
success: boolean;
|
|
222
|
+
}
|
|
223
|
+
|
|
213
224
|
/**
|
|
214
225
|
* Render lifecycle phases
|
|
215
226
|
*/
|
|
@@ -450,7 +461,7 @@ interface ConnectionEvent {
|
|
|
450
461
|
/**
|
|
451
462
|
* Union type representing all possible Limelight messages.
|
|
452
463
|
*/
|
|
453
|
-
type LimelightMessage = NetworkRequest | NetworkResponse | NetworkErrorEvent | ConsoleEvent | ConnectionEvent | RenderSnapshot | TransactionEvent | StateInitEvent | StateUpdateEvent;
|
|
464
|
+
type LimelightMessage = NetworkRequest | NetworkResponse | NetworkErrorEvent | ConsoleEvent | ConnectionEvent | RenderSnapshot | TransactionEvent | StateInitEvent | StateUpdateEvent | CommandAckEvent;
|
|
454
465
|
|
|
455
466
|
/**
|
|
456
467
|
* Represents a single frame in a stack trace.
|
|
@@ -512,6 +523,7 @@ declare class LimelightClient {
|
|
|
512
523
|
private renderInterceptor;
|
|
513
524
|
private stateInterceptor;
|
|
514
525
|
private requestBridge;
|
|
526
|
+
private commandHandler;
|
|
515
527
|
constructor();
|
|
516
528
|
/**
|
|
517
529
|
* Configures the Limelight client with the provided settings.
|
package/dist/index.js
CHANGED
|
@@ -267,7 +267,7 @@ var SENSITIVE_HEADERS = [
|
|
|
267
267
|
var LIMELIGHT_WEB_WSS_URL = "wss://api.getlimelight.io";
|
|
268
268
|
var LIMELIGHT_DESKTOP_WSS_URL = "ws://localhost:8484";
|
|
269
269
|
var WS_PATH = "/limelight";
|
|
270
|
-
var SDK_VERSION = true ? "0.
|
|
270
|
+
var SDK_VERSION = true ? "0.5.1" : "test-version";
|
|
271
271
|
var RENDER_THRESHOLDS = {
|
|
272
272
|
HOT_VELOCITY: 5,
|
|
273
273
|
HIGH_RENDER_COUNT: 50,
|
|
@@ -1162,12 +1162,10 @@ var RenderInterceptor = class {
|
|
|
1162
1162
|
}, RENDER_THRESHOLDS.SNAPSHOT_INTERVAL_MS);
|
|
1163
1163
|
this.isSetup = true;
|
|
1164
1164
|
}
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
this.componentIdCounter = 0;
|
|
1170
|
-
}
|
|
1165
|
+
/**
|
|
1166
|
+
* Installs or wraps the React DevTools global hook.
|
|
1167
|
+
* Returns true if successful, false otherwise.
|
|
1168
|
+
*/
|
|
1171
1169
|
installHook() {
|
|
1172
1170
|
const globalObj = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : null;
|
|
1173
1171
|
if (!globalObj) return false;
|
|
@@ -1180,6 +1178,11 @@ var RenderInterceptor = class {
|
|
|
1180
1178
|
}
|
|
1181
1179
|
return true;
|
|
1182
1180
|
}
|
|
1181
|
+
/**
|
|
1182
|
+
* Wraps an existing React DevTools hook to intercept render events.
|
|
1183
|
+
* Preserves original functionality.
|
|
1184
|
+
* @param hook - The existing React DevTools hook
|
|
1185
|
+
*/
|
|
1183
1186
|
wrapExistingHook(hook) {
|
|
1184
1187
|
this.originalHook = hook;
|
|
1185
1188
|
this.originalOnCommitFiberRoot = hook.onCommitFiberRoot?.bind(hook);
|
|
@@ -1193,6 +1196,11 @@ var RenderInterceptor = class {
|
|
|
1193
1196
|
this.handleCommitFiberUnmount(rendererID, fiber);
|
|
1194
1197
|
};
|
|
1195
1198
|
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Creates a new React DevTools hook to intercept render events.
|
|
1201
|
+
* @param globalObj - The global object (window or global)
|
|
1202
|
+
* @param hookKey - The key for the React DevTools hook
|
|
1203
|
+
*/
|
|
1196
1204
|
createHook(globalObj, hookKey) {
|
|
1197
1205
|
const renderers = /* @__PURE__ */ new Map();
|
|
1198
1206
|
let rendererIdCounter = 0;
|
|
@@ -1215,6 +1223,8 @@ var RenderInterceptor = class {
|
|
|
1215
1223
|
/**
|
|
1216
1224
|
* Handles a fiber root commit - walks tree and ACCUMULATES into profiles.
|
|
1217
1225
|
* Two-pass: first count components, then accumulate with distributed cost.
|
|
1226
|
+
* @param rendererID - The renderer ID
|
|
1227
|
+
* @param root - The fiber root
|
|
1218
1228
|
*/
|
|
1219
1229
|
handleCommitFiberRoot(_rendererID, root) {
|
|
1220
1230
|
this.currentCommitComponents.clear();
|
|
@@ -1230,6 +1240,7 @@ var RenderInterceptor = class {
|
|
|
1230
1240
|
}
|
|
1231
1241
|
/**
|
|
1232
1242
|
* First pass: count rendered components for cost distribution.
|
|
1243
|
+
* @param fiber - The current fiber node
|
|
1233
1244
|
*/
|
|
1234
1245
|
countRenderedComponents(fiber) {
|
|
1235
1246
|
if (!fiber) return;
|
|
@@ -1239,6 +1250,11 @@ var RenderInterceptor = class {
|
|
|
1239
1250
|
this.countRenderedComponents(fiber.child);
|
|
1240
1251
|
this.countRenderedComponents(fiber.sibling);
|
|
1241
1252
|
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Handles a fiber unmount - marks component as unmounted.
|
|
1255
|
+
* @param rendererID - The renderer ID
|
|
1256
|
+
* @param fiber - The fiber being unmounted
|
|
1257
|
+
*/
|
|
1242
1258
|
handleCommitFiberUnmount(_rendererID, fiber) {
|
|
1243
1259
|
if (!this.isUserComponent(fiber)) return;
|
|
1244
1260
|
const componentId = this.fiberToComponentId.get(fiber);
|
|
@@ -1252,6 +1268,9 @@ var RenderInterceptor = class {
|
|
|
1252
1268
|
}
|
|
1253
1269
|
/**
|
|
1254
1270
|
* Walks fiber tree and accumulates render stats into profiles.
|
|
1271
|
+
* @param fiber - The current fiber node
|
|
1272
|
+
* @param parentComponentId - The parent component ID
|
|
1273
|
+
* @param depth - The current depth in the tree
|
|
1255
1274
|
*/
|
|
1256
1275
|
walkFiberTree(fiber, parentComponentId, depth) {
|
|
1257
1276
|
if (!fiber) return;
|
|
@@ -1266,6 +1285,10 @@ var RenderInterceptor = class {
|
|
|
1266
1285
|
}
|
|
1267
1286
|
/**
|
|
1268
1287
|
* Core accumulation logic - this is where we build up the profile.
|
|
1288
|
+
* @param fiber - The current fiber node
|
|
1289
|
+
* @param componentId - The component ID
|
|
1290
|
+
* @param parentComponentId - The parent component ID
|
|
1291
|
+
* @param depth - The current depth in the tree
|
|
1269
1292
|
*/
|
|
1270
1293
|
accumulateRender(fiber, componentId, parentComponentId, depth) {
|
|
1271
1294
|
const now = Date.now();
|
|
@@ -1326,7 +1349,9 @@ var RenderInterceptor = class {
|
|
|
1326
1349
|
this.updateSuspiciousFlag(profile);
|
|
1327
1350
|
}
|
|
1328
1351
|
/**
|
|
1329
|
-
*
|
|
1352
|
+
* Accumulate prop change details into the profile.
|
|
1353
|
+
* @param profile - The component profile
|
|
1354
|
+
* @param changes - The list of prop change details
|
|
1330
1355
|
*/
|
|
1331
1356
|
accumulatePropChanges(profile, changes) {
|
|
1332
1357
|
const stats = profile.propChangeStats;
|
|
@@ -1355,7 +1380,9 @@ var RenderInterceptor = class {
|
|
|
1355
1380
|
}
|
|
1356
1381
|
}
|
|
1357
1382
|
/**
|
|
1358
|
-
*
|
|
1383
|
+
* Build prop change snapshot for emission.
|
|
1384
|
+
* @param profile - The component profile
|
|
1385
|
+
* @returns The prop change snapshot or undefined
|
|
1359
1386
|
*/
|
|
1360
1387
|
buildPropChangeSnapshot(profile) {
|
|
1361
1388
|
const stats = profile.propChangeStats;
|
|
@@ -1373,6 +1400,10 @@ var RenderInterceptor = class {
|
|
|
1373
1400
|
});
|
|
1374
1401
|
return { topChangedProps };
|
|
1375
1402
|
}
|
|
1403
|
+
/**
|
|
1404
|
+
* Updates the suspicious flag based on render velocity and count.
|
|
1405
|
+
* @param profile - The component profile
|
|
1406
|
+
*/
|
|
1376
1407
|
updateSuspiciousFlag(profile) {
|
|
1377
1408
|
const velocity = this.calculateVelocity(profile);
|
|
1378
1409
|
if (velocity > RENDER_THRESHOLDS.HOT_VELOCITY) {
|
|
@@ -1391,6 +1422,8 @@ var RenderInterceptor = class {
|
|
|
1391
1422
|
/**
|
|
1392
1423
|
* Calculates renders per second from velocity window.
|
|
1393
1424
|
* Cheap: just count / window duration, no array operations.
|
|
1425
|
+
* @param profile - The component profile
|
|
1426
|
+
* @returns The calculated velocity
|
|
1394
1427
|
*/
|
|
1395
1428
|
calculateVelocity(profile) {
|
|
1396
1429
|
const now = Date.now();
|
|
@@ -1403,6 +1436,8 @@ var RenderInterceptor = class {
|
|
|
1403
1436
|
}
|
|
1404
1437
|
/**
|
|
1405
1438
|
* Emits a snapshot of all profiles with deltas.
|
|
1439
|
+
* Only emits profiles that have significant changes since last emit.
|
|
1440
|
+
* Also emits unmounts.
|
|
1406
1441
|
*/
|
|
1407
1442
|
emitSnapshot() {
|
|
1408
1443
|
const now = Date.now();
|
|
@@ -1486,7 +1521,11 @@ var RenderInterceptor = class {
|
|
|
1486
1521
|
this.sendMessage(message);
|
|
1487
1522
|
}
|
|
1488
1523
|
/**
|
|
1489
|
-
*
|
|
1524
|
+
* Now returns prop change details when applicable.
|
|
1525
|
+
* Infers the cause of the render by comparing current and previous fiber states.
|
|
1526
|
+
* @param fiber - The current fiber node
|
|
1527
|
+
* @param parentComponentId - The parent component ID
|
|
1528
|
+
* @returns The inferred render cause
|
|
1490
1529
|
*/
|
|
1491
1530
|
inferRenderCause(fiber, parentComponentId) {
|
|
1492
1531
|
const alternate = fiber.alternate;
|
|
@@ -1535,6 +1574,9 @@ var RenderInterceptor = class {
|
|
|
1535
1574
|
/**
|
|
1536
1575
|
* Diff props to find which keys changed and whether it's reference-only.
|
|
1537
1576
|
* This is the key insight generator.
|
|
1577
|
+
* @param prevProps - The previous props
|
|
1578
|
+
* @param nextProps - The next props
|
|
1579
|
+
* @returns List of prop change details
|
|
1538
1580
|
*/
|
|
1539
1581
|
diffProps(prevProps, nextProps) {
|
|
1540
1582
|
if (!prevProps || !nextProps) {
|
|
@@ -1562,8 +1604,11 @@ var RenderInterceptor = class {
|
|
|
1562
1604
|
return changes;
|
|
1563
1605
|
}
|
|
1564
1606
|
/**
|
|
1565
|
-
*
|
|
1607
|
+
* Shallow equality check to determine if a prop is reference-only change.
|
|
1566
1608
|
* We only go one level deep to keep it fast.
|
|
1609
|
+
* @param a - The first value
|
|
1610
|
+
* @param b - The second value
|
|
1611
|
+
* @returns True if shallow equal, false otherwise
|
|
1567
1612
|
*/
|
|
1568
1613
|
isShallowEqual(a, b) {
|
|
1569
1614
|
if (a === b) return true;
|
|
@@ -1590,13 +1635,28 @@ var RenderInterceptor = class {
|
|
|
1590
1635
|
}
|
|
1591
1636
|
return a === b;
|
|
1592
1637
|
}
|
|
1638
|
+
/**
|
|
1639
|
+
* Determines if a fiber represents a user-defined component.
|
|
1640
|
+
* @param fiber - The fiber node
|
|
1641
|
+
* @returns True if user component, false otherwise
|
|
1642
|
+
*/
|
|
1593
1643
|
isUserComponent(fiber) {
|
|
1594
1644
|
const tag = fiber.tag;
|
|
1595
1645
|
return tag === 0 /* FunctionComponent */ || tag === 1 /* ClassComponent */ || tag === 11 /* ForwardRef */ || tag === 14 /* MemoComponent */ || tag === 15 /* SimpleMemoComponent */;
|
|
1596
1646
|
}
|
|
1647
|
+
/**
|
|
1648
|
+
* Determines if a fiber performed work during the commit.
|
|
1649
|
+
* @param fiber - The fiber node
|
|
1650
|
+
* @returns True if performed work, false otherwise
|
|
1651
|
+
*/
|
|
1597
1652
|
didFiberRender(fiber) {
|
|
1598
1653
|
return (fiber.flags & 1 /* PerformedWork */) !== 0;
|
|
1599
1654
|
}
|
|
1655
|
+
/**
|
|
1656
|
+
* Gets or creates a unique component ID for a fiber.
|
|
1657
|
+
* @param fiber - The fiber node
|
|
1658
|
+
* @returns The unique component ID
|
|
1659
|
+
*/
|
|
1600
1660
|
getOrCreateComponentId(fiber) {
|
|
1601
1661
|
let id = this.fiberToComponentId.get(fiber);
|
|
1602
1662
|
if (id) return id;
|
|
@@ -1611,6 +1671,11 @@ var RenderInterceptor = class {
|
|
|
1611
1671
|
this.fiberToComponentId.set(fiber, id);
|
|
1612
1672
|
return id;
|
|
1613
1673
|
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Gets the display name of a component from a fiber.
|
|
1676
|
+
* @param fiber - The fiber node
|
|
1677
|
+
* @returns The component name
|
|
1678
|
+
*/
|
|
1614
1679
|
getComponentName(fiber) {
|
|
1615
1680
|
const type = fiber.type;
|
|
1616
1681
|
if (!type) return "Unknown";
|
|
@@ -1628,6 +1693,11 @@ var RenderInterceptor = class {
|
|
|
1628
1693
|
}
|
|
1629
1694
|
return "Unknown";
|
|
1630
1695
|
}
|
|
1696
|
+
/**
|
|
1697
|
+
* Gets the component type from a fiber.
|
|
1698
|
+
* @param fiber - The fiber node
|
|
1699
|
+
* @returns The component type
|
|
1700
|
+
*/
|
|
1631
1701
|
getComponentType(fiber) {
|
|
1632
1702
|
switch (fiber.tag) {
|
|
1633
1703
|
case 0 /* FunctionComponent */:
|
|
@@ -1661,6 +1731,9 @@ var RenderInterceptor = class {
|
|
|
1661
1731
|
getSuspiciousComponents() {
|
|
1662
1732
|
return Array.from(this.profiles.values()).filter((p) => p.isSuspicious);
|
|
1663
1733
|
}
|
|
1734
|
+
/**
|
|
1735
|
+
* Cleans up and restores original hook behavior.
|
|
1736
|
+
*/
|
|
1664
1737
|
cleanup() {
|
|
1665
1738
|
if (!this.isSetup) return;
|
|
1666
1739
|
this.emitSnapshot();
|
|
@@ -1686,6 +1759,16 @@ var RenderInterceptor = class {
|
|
|
1686
1759
|
this.config = null;
|
|
1687
1760
|
this.isSetup = false;
|
|
1688
1761
|
}
|
|
1762
|
+
/**
|
|
1763
|
+
* Resets all collected profiles
|
|
1764
|
+
*/
|
|
1765
|
+
resetProfiles() {
|
|
1766
|
+
this.profiles.clear();
|
|
1767
|
+
this.fiberToComponentId = /* @__PURE__ */ new WeakMap();
|
|
1768
|
+
this.pendingUnmounts = [];
|
|
1769
|
+
this.currentCommitComponents.clear();
|
|
1770
|
+
this.componentIdCounter = 0;
|
|
1771
|
+
}
|
|
1689
1772
|
};
|
|
1690
1773
|
|
|
1691
1774
|
// src/limelight/interceptors/StateInterceptor.ts
|
|
@@ -1724,7 +1807,7 @@ var StateInterceptor = class {
|
|
|
1724
1807
|
);
|
|
1725
1808
|
return;
|
|
1726
1809
|
}
|
|
1727
|
-
const state = this.getState(store
|
|
1810
|
+
const state = this.getState(store);
|
|
1728
1811
|
const initEvent = {
|
|
1729
1812
|
phase: "STATE:INIT" /* INIT */,
|
|
1730
1813
|
sessionId: this.getSessionId(),
|
|
@@ -1741,6 +1824,8 @@ var StateInterceptor = class {
|
|
|
1741
1824
|
}
|
|
1742
1825
|
/**
|
|
1743
1826
|
* Unregister a store and stop listening to changes.
|
|
1827
|
+
* Can be called manually via Limelight.removeStore().
|
|
1828
|
+
* @param name The name of the store to unregister
|
|
1744
1829
|
*/
|
|
1745
1830
|
unregisterStore(name) {
|
|
1746
1831
|
const store = this.stores.get(name);
|
|
@@ -1751,6 +1836,7 @@ var StateInterceptor = class {
|
|
|
1751
1836
|
}
|
|
1752
1837
|
/**
|
|
1753
1838
|
* Emit an event, applying beforeSend hook if configured
|
|
1839
|
+
* @param event The event to emit
|
|
1754
1840
|
*/
|
|
1755
1841
|
emitEvent(event) {
|
|
1756
1842
|
if (this.config?.beforeSend) {
|
|
@@ -1769,6 +1855,8 @@ var StateInterceptor = class {
|
|
|
1769
1855
|
}
|
|
1770
1856
|
/**
|
|
1771
1857
|
* Detect whether a store is Zustand or Redux
|
|
1858
|
+
* @param store The store to inspect
|
|
1859
|
+
* @return StateLibrary or null if unknown
|
|
1772
1860
|
*/
|
|
1773
1861
|
detectLibrary(store) {
|
|
1774
1862
|
if (!store || typeof store !== "function" && typeof store !== "object") {
|
|
@@ -1787,13 +1875,19 @@ var StateInterceptor = class {
|
|
|
1787
1875
|
}
|
|
1788
1876
|
/**
|
|
1789
1877
|
* Get current state from a store
|
|
1878
|
+
* @param store The store to get state from
|
|
1879
|
+
* @return The current state
|
|
1790
1880
|
*/
|
|
1791
|
-
getState(store
|
|
1881
|
+
getState(store) {
|
|
1792
1882
|
const storeAny = store;
|
|
1793
1883
|
return storeAny.getState();
|
|
1794
1884
|
}
|
|
1795
1885
|
/**
|
|
1796
1886
|
* Subscribe to store changes
|
|
1887
|
+
* @param store The store to subscribe to
|
|
1888
|
+
* @param library The detected state library
|
|
1889
|
+
* @param storeName The name of the store
|
|
1890
|
+
* @return Unsubscribe function
|
|
1797
1891
|
*/
|
|
1798
1892
|
subscribe(store, library, storeName) {
|
|
1799
1893
|
const storeAny = store;
|
|
@@ -1805,6 +1899,9 @@ var StateInterceptor = class {
|
|
|
1805
1899
|
}
|
|
1806
1900
|
/**
|
|
1807
1901
|
* Subscribe to Zustand store changes
|
|
1902
|
+
* @param store The Zustand store
|
|
1903
|
+
* @param storeName The name of the store
|
|
1904
|
+
* @return Unsubscribe function
|
|
1808
1905
|
*/
|
|
1809
1906
|
subscribeZustand(store, storeName) {
|
|
1810
1907
|
return store.subscribe((state, prevState) => {
|
|
@@ -1827,6 +1924,9 @@ var StateInterceptor = class {
|
|
|
1827
1924
|
}
|
|
1828
1925
|
/**
|
|
1829
1926
|
* Subscribe to Redux store changes
|
|
1927
|
+
* @param store The Redux store
|
|
1928
|
+
* @param storeName The name of the store
|
|
1929
|
+
* @return Unsubscribe function
|
|
1830
1930
|
*/
|
|
1831
1931
|
subscribeRedux(store, storeName) {
|
|
1832
1932
|
let lastAction = { type: "@@INIT" };
|
|
@@ -1862,6 +1962,9 @@ var StateInterceptor = class {
|
|
|
1862
1962
|
}
|
|
1863
1963
|
/**
|
|
1864
1964
|
* Infer action name from stack trace for Zustand
|
|
1965
|
+
* @param state The new state
|
|
1966
|
+
* @param prevState The previous state
|
|
1967
|
+
* @return Inferred StateAction
|
|
1865
1968
|
*/
|
|
1866
1969
|
inferZustandAction(state, prevState) {
|
|
1867
1970
|
const actionType = this.parseActionFromStack(this.captureStackTrace());
|
|
@@ -1873,6 +1976,8 @@ var StateInterceptor = class {
|
|
|
1873
1976
|
}
|
|
1874
1977
|
/**
|
|
1875
1978
|
* Parse function name from stack trace
|
|
1979
|
+
* @param stack The stack trace string
|
|
1980
|
+
* @return The inferred action name
|
|
1876
1981
|
*/
|
|
1877
1982
|
parseActionFromStack(stack) {
|
|
1878
1983
|
if (!stack) return "set";
|
|
@@ -1903,6 +2008,9 @@ var StateInterceptor = class {
|
|
|
1903
2008
|
}
|
|
1904
2009
|
/**
|
|
1905
2010
|
* Compute what keys changed between states (shallow)
|
|
2011
|
+
* @param state The new state
|
|
2012
|
+
* @param prevState The previous state
|
|
2013
|
+
* @return Partial state with only changed keys
|
|
1906
2014
|
*/
|
|
1907
2015
|
computePartialState(state, prevState) {
|
|
1908
2016
|
if (typeof state !== "object" || state === null || typeof prevState !== "object" || prevState === null) {
|
|
@@ -1943,7 +2051,7 @@ var StateInterceptor = class {
|
|
|
1943
2051
|
}
|
|
1944
2052
|
};
|
|
1945
2053
|
|
|
1946
|
-
// src/limelight/
|
|
2054
|
+
// src/limelight/bridges/RequestBridge.ts
|
|
1947
2055
|
var RequestBridge = class {
|
|
1948
2056
|
constructor(sendMessage, getSessionId) {
|
|
1949
2057
|
this.sendMessage = sendMessage;
|
|
@@ -2110,6 +2218,42 @@ var RequestBridge = class {
|
|
|
2110
2218
|
}
|
|
2111
2219
|
};
|
|
2112
2220
|
|
|
2221
|
+
// src/limelight/handlers/CommandHandler.ts
|
|
2222
|
+
var CommandHandler = class {
|
|
2223
|
+
constructor(interceptors, sendMessage, getConfig) {
|
|
2224
|
+
this.interceptors = interceptors;
|
|
2225
|
+
this.sendMessage = sendMessage;
|
|
2226
|
+
this.getConfig = getConfig;
|
|
2227
|
+
}
|
|
2228
|
+
/**
|
|
2229
|
+
* Handles an incoming command.
|
|
2230
|
+
* @param command - The command to handle
|
|
2231
|
+
*/
|
|
2232
|
+
handle(command) {
|
|
2233
|
+
const config = this.getConfig();
|
|
2234
|
+
if (config?.enableInternalLogging) {
|
|
2235
|
+
console.log("[Limelight] Received command:", command.type);
|
|
2236
|
+
}
|
|
2237
|
+
switch (command.type) {
|
|
2238
|
+
case "CLEAR_RENDERS" /* CLEAR_RENDERS */:
|
|
2239
|
+
this.interceptors.render.resetProfiles();
|
|
2240
|
+
break;
|
|
2241
|
+
default:
|
|
2242
|
+
if (config?.enableInternalLogging) {
|
|
2243
|
+
console.warn("[Limelight] Unknown command:", command.type);
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
if (command.id) {
|
|
2247
|
+
this.sendMessage({
|
|
2248
|
+
phase: "ACK" /* ACK */,
|
|
2249
|
+
commandId: command.id,
|
|
2250
|
+
type: command.type,
|
|
2251
|
+
success: true
|
|
2252
|
+
});
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
};
|
|
2256
|
+
|
|
2113
2257
|
// src/limelight/LimelightClient.ts
|
|
2114
2258
|
var LimelightClient = class {
|
|
2115
2259
|
ws = null;
|
|
@@ -2127,6 +2271,7 @@ var LimelightClient = class {
|
|
|
2127
2271
|
renderInterceptor;
|
|
2128
2272
|
stateInterceptor;
|
|
2129
2273
|
requestBridge;
|
|
2274
|
+
commandHandler = null;
|
|
2130
2275
|
constructor() {
|
|
2131
2276
|
this.networkInterceptor = new NetworkInterceptor(
|
|
2132
2277
|
this.sendMessage.bind(this),
|
|
@@ -2152,6 +2297,11 @@ var LimelightClient = class {
|
|
|
2152
2297
|
this.sendMessage.bind(this),
|
|
2153
2298
|
() => this.sessionId
|
|
2154
2299
|
);
|
|
2300
|
+
this.commandHandler = new CommandHandler(
|
|
2301
|
+
{ render: this.renderInterceptor },
|
|
2302
|
+
this.sendMessage.bind(this),
|
|
2303
|
+
() => this.config
|
|
2304
|
+
);
|
|
2155
2305
|
}
|
|
2156
2306
|
/**
|
|
2157
2307
|
* Configures the Limelight client with the provided settings.
|
|
@@ -2258,6 +2408,16 @@ var LimelightClient = class {
|
|
|
2258
2408
|
this.flushMessageQueue();
|
|
2259
2409
|
this.sendMessage(message);
|
|
2260
2410
|
};
|
|
2411
|
+
this.ws.onmessage = (event) => {
|
|
2412
|
+
try {
|
|
2413
|
+
const command = JSON.parse(event.data);
|
|
2414
|
+
this.commandHandler?.handle(command);
|
|
2415
|
+
} catch (error) {
|
|
2416
|
+
if (this.config?.enableInternalLogging) {
|
|
2417
|
+
console.error("[Limelight] Failed to parse command:", error);
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
};
|
|
2261
2421
|
this.ws.onerror = (error) => {
|
|
2262
2422
|
if (this.config?.enableInternalLogging) {
|
|
2263
2423
|
console.error("[Limelight] WebSocket error:", error);
|