@concavejs/devtools 0.0.1-alpha.4
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.
Potentially problematic release.
This version of @concavejs/devtools might be problematic. Click here for more details.
- package/README.md +263 -0
- package/dist/client-D6NyDOCN.js +2781 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.js +5 -0
- package/dist/extension/page-agent.d.ts +8 -0
- package/dist/extension/panel.d.ts +14 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +380 -0
- package/dist/interceptor/index.d.ts +5 -0
- package/dist/interceptor/websocket-interceptor.d.ts +67 -0
- package/dist/overlay/ActivityPanel.d.ts +10 -0
- package/dist/overlay/ContextMenu.d.ts +23 -0
- package/dist/overlay/DataInspector.d.ts +12 -0
- package/dist/overlay/DevToolbar.d.ts +11 -0
- package/dist/overlay/LogsPanel.d.ts +10 -0
- package/dist/overlay/NetworkPanel.d.ts +9 -0
- package/dist/overlay/PerformancePanel.d.ts +10 -0
- package/dist/overlay/SearchField.d.ts +9 -0
- package/dist/overlay/SettingsPanel.d.ts +9 -0
- package/dist/overlay/SubscriptionsPanel.d.ts +9 -0
- package/dist/overlay/TimelinePanel.d.ts +9 -0
- package/dist/overlay/utils.d.ts +16 -0
- package/dist/standalone.d.ts +11 -0
- package/dist/store/event-store.d.ts +165 -0
- package/dist/store/safe-storage.d.ts +7 -0
- package/dist/types.d.ts +146 -0
- package/dist/version.d.ts +10 -0
- package/dist/vite-plugin/index.d.ts +16 -0
- package/dist/vite-plugin.js +544 -0
- package/package.json +62 -0
package/dist/client.d.ts
ADDED
package/dist/client.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page Agent — Thin IIFE injected into the page context.
|
|
3
|
+
*
|
|
4
|
+
* Intercepts WebSocket traffic using the same WebSocketInterceptor,
|
|
5
|
+
* but instead of a full EventStore it posts events to the content script
|
|
6
|
+
* via window.postMessage. Buffers the last 500 events for late-opening panels.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DevTools Panel Entry — React app rendered inside the Chrome DevTools "Concave" tab.
|
|
3
|
+
*
|
|
4
|
+
* Uses chrome.devtools.inspectedWindow.reload({ injectedScript }) to install a
|
|
5
|
+
* WebSocket interceptor BEFORE any page scripts run. This guarantees full
|
|
6
|
+
* interception without any permissions beyond the devtools_page manifest key.
|
|
7
|
+
*
|
|
8
|
+
* Flow:
|
|
9
|
+
* 1. Panel opens → try eval() injection (catches new WS connections)
|
|
10
|
+
* 2. If page already has a connection → show "Reload" button
|
|
11
|
+
* 3. Reload uses inspectedWindow.reload({ injectedScript }) — runs before page JS
|
|
12
|
+
* 4. On navigation → re-inject via eval()
|
|
13
|
+
*/
|
|
14
|
+
import "../devtools.css";
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Concave DevTools
|
|
3
|
+
*
|
|
4
|
+
* Client-side development tools for Convex/Concave applications
|
|
5
|
+
*/
|
|
6
|
+
export type { DevToolsEvent, QueryEvent, MutationEvent, ActionEvent, SubscriptionEvent, LogEvent, AuthEvent, ActiveSubscription, PerformanceMetrics, EventType, EventStatus, SubscriptionStatus, } from "./types";
|
|
7
|
+
export { EventStore, getGlobalEventStore } from "./store/event-store";
|
|
8
|
+
export type { EventListener, StoreSnapshot, ExportedSession } from "./store/event-store";
|
|
9
|
+
export { WebSocketInterceptor } from "./interceptor/websocket-interceptor";
|
|
10
|
+
export { DevToolbar } from "./overlay/DevToolbar";
|
|
11
|
+
export { SubscriptionsPanel } from "./overlay/SubscriptionsPanel";
|
|
12
|
+
export { PerformancePanel } from "./overlay/PerformancePanel";
|
|
13
|
+
export { LogsPanel } from "./overlay/LogsPanel";
|
|
14
|
+
export { SettingsPanel } from "./overlay/SettingsPanel";
|
|
15
|
+
export { DataInspector } from "./overlay/DataInspector";
|
|
16
|
+
export { initDevTools } from "./client";
|
|
17
|
+
export { default as concaveDevTools } from "./vite-plugin/index";
|
|
18
|
+
export type { DevToolsOptions } from "./vite-plugin/index";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
var m = Object.defineProperty;
|
|
2
|
+
var v = (c, e, t) => e in c ? m(c, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[e] = t;
|
|
3
|
+
var d = (c, e, t) => v(c, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
import { b as w, D as P, E, L as S, P as A, a as L, S as M, g as D, i as $ } from "./client-D6NyDOCN.js";
|
|
5
|
+
import { concaveDevTools as R } from "./vite-plugin.js";
|
|
6
|
+
function T(c) {
|
|
7
|
+
const e = c.split(".");
|
|
8
|
+
if (e.length < 2) return null;
|
|
9
|
+
try {
|
|
10
|
+
const t = e[1].replace(/-/g, "+").replace(/_/g, "/"), n = t + "=".repeat((4 - t.length % 4) % 4), s = JSON.parse(atob(n)), o = ["iss", "sub", "aud", "exp", "iat", "nbf"], i = {};
|
|
11
|
+
for (const a of o) {
|
|
12
|
+
const u = s[a];
|
|
13
|
+
u !== void 0 && (i[a] = u);
|
|
14
|
+
}
|
|
15
|
+
return typeof i.exp == "number" && (i.expIso = new Date(i.exp * 1e3).toISOString()), typeof i.iat == "number" && (i.iatIso = new Date(i.iat * 1e3).toISOString()), Object.keys(i).length > 0 ? i : null;
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
class I {
|
|
21
|
+
constructor(e) {
|
|
22
|
+
d(this, "eventStore");
|
|
23
|
+
d(this, "originalWebSocket");
|
|
24
|
+
d(this, "pendingQueries", /* @__PURE__ */ new Map());
|
|
25
|
+
d(this, "pendingMutations", /* @__PURE__ */ new Map());
|
|
26
|
+
d(this, "pendingActions", /* @__PURE__ */ new Map());
|
|
27
|
+
d(this, "pendingAuthTokenType", null);
|
|
28
|
+
/** Tracks the most recent mutation event ID for causality linking */
|
|
29
|
+
d(this, "lastMutationEventId", null);
|
|
30
|
+
d(this, "lastMutationTimestamp", 0);
|
|
31
|
+
this.eventStore = e, this.originalWebSocket = window.WebSocket;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Install the WebSocket interceptor
|
|
35
|
+
*/
|
|
36
|
+
install() {
|
|
37
|
+
const e = this, t = this.originalWebSocket;
|
|
38
|
+
class n extends t {
|
|
39
|
+
constructor(o, i) {
|
|
40
|
+
super(o, i);
|
|
41
|
+
const a = this.addEventListener.bind(this);
|
|
42
|
+
this.addEventListener = (r, l, h) => {
|
|
43
|
+
r === "message" && typeof l == "function" ? a("message", (p) => {
|
|
44
|
+
try {
|
|
45
|
+
e.handleServerMessage(p.data);
|
|
46
|
+
} catch (f) {
|
|
47
|
+
console.warn("[DevTools] Error parsing server message:", f);
|
|
48
|
+
}
|
|
49
|
+
l(p);
|
|
50
|
+
}, h) : a(r, l, h);
|
|
51
|
+
};
|
|
52
|
+
let u = null;
|
|
53
|
+
Object.defineProperty(this, "onmessage", {
|
|
54
|
+
get: () => u,
|
|
55
|
+
set: (r) => {
|
|
56
|
+
u = r, r && a("message", (h) => {
|
|
57
|
+
try {
|
|
58
|
+
e.handleServerMessage(h.data);
|
|
59
|
+
} catch (g) {
|
|
60
|
+
console.warn("[DevTools] Error parsing server message:", g);
|
|
61
|
+
}
|
|
62
|
+
r.call(this, h);
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
configurable: !0,
|
|
66
|
+
enumerable: !0
|
|
67
|
+
});
|
|
68
|
+
const y = this.send.bind(this);
|
|
69
|
+
this.send = (r) => {
|
|
70
|
+
try {
|
|
71
|
+
typeof r == "string" && e.handleClientMessage(r);
|
|
72
|
+
} catch (l) {
|
|
73
|
+
console.warn("[DevTools] Error parsing client message:", l);
|
|
74
|
+
}
|
|
75
|
+
y(r);
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
window.WebSocket = n, console.log("[DevTools] WebSocket interceptor installed");
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Uninstall the interceptor
|
|
83
|
+
*/
|
|
84
|
+
uninstall() {
|
|
85
|
+
window.WebSocket = this.originalWebSocket;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Handle client → server messages
|
|
89
|
+
*/
|
|
90
|
+
handleClientMessage(e) {
|
|
91
|
+
try {
|
|
92
|
+
const t = JSON.parse(e);
|
|
93
|
+
switch (console.log("[DevTools] Client message:", t.type, t), t.type) {
|
|
94
|
+
case "ModifyQuerySet":
|
|
95
|
+
this.handleModifyQuerySet(t.modifications);
|
|
96
|
+
break;
|
|
97
|
+
case "Mutation":
|
|
98
|
+
this.handleMutationRequest(t);
|
|
99
|
+
break;
|
|
100
|
+
case "Action":
|
|
101
|
+
this.handleActionRequest(t);
|
|
102
|
+
break;
|
|
103
|
+
case "Connect":
|
|
104
|
+
this.handleConnectMessage(t);
|
|
105
|
+
break;
|
|
106
|
+
case "Authenticate":
|
|
107
|
+
this.handleAuthenticateMessage(t);
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
} catch (t) {
|
|
111
|
+
console.warn("[DevTools] Failed to parse client message:", t);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Handle server → client messages
|
|
116
|
+
*/
|
|
117
|
+
handleServerMessage(e) {
|
|
118
|
+
try {
|
|
119
|
+
const t = JSON.parse(e);
|
|
120
|
+
switch (console.log("[DevTools] Server message:", t.type, t), t.type) {
|
|
121
|
+
case "Transition":
|
|
122
|
+
this.handleTransition(t);
|
|
123
|
+
break;
|
|
124
|
+
case "MutationResponse":
|
|
125
|
+
this.handleMutationResponse(t);
|
|
126
|
+
break;
|
|
127
|
+
case "ActionResponse":
|
|
128
|
+
this.handleActionResponse(t);
|
|
129
|
+
break;
|
|
130
|
+
case "AuthError":
|
|
131
|
+
this.handleAuthErrorResponse(t);
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
} catch (t) {
|
|
135
|
+
console.warn("[DevTools] Failed to parse server message:", t);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Handle query set modifications (subscriptions)
|
|
140
|
+
*/
|
|
141
|
+
handleModifyQuerySet(e) {
|
|
142
|
+
const t = Date.now();
|
|
143
|
+
for (const n of e)
|
|
144
|
+
if (n.type === "Add") {
|
|
145
|
+
this.pendingQueries.set(n.queryId, {
|
|
146
|
+
queryId: n.queryId,
|
|
147
|
+
udfPath: n.udfPath,
|
|
148
|
+
args: n.args,
|
|
149
|
+
componentPath: n.componentPath,
|
|
150
|
+
startTime: t
|
|
151
|
+
});
|
|
152
|
+
const s = {
|
|
153
|
+
id: `sub-${n.queryId}-${t}`,
|
|
154
|
+
timestamp: t,
|
|
155
|
+
type: "subscription",
|
|
156
|
+
queryId: n.queryId,
|
|
157
|
+
udfPath: n.udfPath,
|
|
158
|
+
args: n.args,
|
|
159
|
+
componentPath: n.componentPath,
|
|
160
|
+
status: "added"
|
|
161
|
+
};
|
|
162
|
+
this.eventStore.addEvent(s);
|
|
163
|
+
} else if (n.type === "Remove") {
|
|
164
|
+
const s = this.pendingQueries.get(n.queryId);
|
|
165
|
+
if (this.pendingQueries.delete(n.queryId), s) {
|
|
166
|
+
const o = {
|
|
167
|
+
id: `sub-${n.queryId}-${t}`,
|
|
168
|
+
timestamp: t,
|
|
169
|
+
type: "subscription",
|
|
170
|
+
queryId: n.queryId,
|
|
171
|
+
udfPath: s.udfPath,
|
|
172
|
+
args: s.args,
|
|
173
|
+
componentPath: s.componentPath,
|
|
174
|
+
status: "removed"
|
|
175
|
+
};
|
|
176
|
+
this.eventStore.addEvent(o);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Handle mutation requests
|
|
182
|
+
*/
|
|
183
|
+
handleMutationRequest(e) {
|
|
184
|
+
const t = Date.now();
|
|
185
|
+
this.pendingMutations.set(e.requestId, {
|
|
186
|
+
requestId: e.requestId,
|
|
187
|
+
udfPath: e.udfPath,
|
|
188
|
+
args: e.args,
|
|
189
|
+
componentPath: e.componentPath,
|
|
190
|
+
startTime: t
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Handle action requests
|
|
195
|
+
*/
|
|
196
|
+
handleActionRequest(e) {
|
|
197
|
+
const t = Date.now();
|
|
198
|
+
this.pendingActions.set(e.requestId, {
|
|
199
|
+
requestId: e.requestId,
|
|
200
|
+
udfPath: e.udfPath,
|
|
201
|
+
args: e.args,
|
|
202
|
+
componentPath: e.componentPath,
|
|
203
|
+
startTime: t
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
handleConnectMessage(e) {
|
|
207
|
+
const t = {};
|
|
208
|
+
typeof e.connectionCount == "number" && (t.connectionCount = e.connectionCount), typeof e.lastCloseReason == "string" && (t.lastCloseReason = e.lastCloseReason), typeof e.clientTs == "number" && (t.clientTs = e.clientTs), typeof e.sessionId == "string" && (t.sessionId = e.sessionId), this.emitAuthEvent({
|
|
209
|
+
direction: "client",
|
|
210
|
+
messageType: "Connect",
|
|
211
|
+
status: "success",
|
|
212
|
+
details: t
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
handleAuthenticateMessage(e) {
|
|
216
|
+
const t = {};
|
|
217
|
+
if (typeof e.baseVersion == "number" && (t.baseVersion = e.baseVersion), typeof e.tokenType == "string" && (t.tokenType = e.tokenType), typeof e.value == "string" && e.value.length > 0) {
|
|
218
|
+
const n = e.value;
|
|
219
|
+
t.tokenLength = n.length, t.tokenPreview = n.length > 24 ? `${n.slice(0, 12)}…${n.slice(-10)}` : n;
|
|
220
|
+
const s = T(n);
|
|
221
|
+
s && (t.jwtClaims = s);
|
|
222
|
+
}
|
|
223
|
+
this.pendingAuthTokenType = e.tokenType ?? "Unknown", this.emitAuthEvent({
|
|
224
|
+
direction: "client",
|
|
225
|
+
messageType: "Authenticate",
|
|
226
|
+
status: "success",
|
|
227
|
+
tokenType: e.tokenType,
|
|
228
|
+
details: t
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Handle state transitions (query updates)
|
|
233
|
+
*/
|
|
234
|
+
handleTransition(e) {
|
|
235
|
+
const t = Date.now();
|
|
236
|
+
this.pendingAuthTokenType && (this.emitAuthEvent({
|
|
237
|
+
direction: "server",
|
|
238
|
+
messageType: "Authenticated",
|
|
239
|
+
status: "success",
|
|
240
|
+
tokenType: this.pendingAuthTokenType,
|
|
241
|
+
details: { modificationCount: e.modifications.length }
|
|
242
|
+
}), this.pendingAuthTokenType = null);
|
|
243
|
+
for (const n of e.modifications)
|
|
244
|
+
if (n.type === "QueryUpdated") {
|
|
245
|
+
const s = this.pendingQueries.get(n.queryId);
|
|
246
|
+
if (!s) continue;
|
|
247
|
+
const o = t - s.startTime, i = this.lastMutationEventId && t - this.lastMutationTimestamp < 2e3 ? this.lastMutationEventId : void 0, a = {
|
|
248
|
+
id: `query-${n.queryId}-${t}`,
|
|
249
|
+
timestamp: t,
|
|
250
|
+
type: "query",
|
|
251
|
+
queryId: n.queryId,
|
|
252
|
+
udfPath: s.udfPath,
|
|
253
|
+
args: s.args,
|
|
254
|
+
componentPath: s.componentPath,
|
|
255
|
+
status: "success",
|
|
256
|
+
result: n.value,
|
|
257
|
+
logLines: n.logLines,
|
|
258
|
+
duration: o,
|
|
259
|
+
triggeredBy: i
|
|
260
|
+
};
|
|
261
|
+
this.eventStore.addEvent(a), Array.isArray(n.logLines) && n.logLines.length > 0 && this.emitLogEvents(n.logLines, a.id);
|
|
262
|
+
} else if (n.type === "QueryFailed") {
|
|
263
|
+
const s = this.pendingQueries.get(n.queryId);
|
|
264
|
+
if (!s) continue;
|
|
265
|
+
const o = t - s.startTime, i = {
|
|
266
|
+
id: `query-${n.queryId}-${t}`,
|
|
267
|
+
timestamp: t,
|
|
268
|
+
type: "query",
|
|
269
|
+
queryId: n.queryId,
|
|
270
|
+
udfPath: s.udfPath,
|
|
271
|
+
args: s.args,
|
|
272
|
+
componentPath: s.componentPath,
|
|
273
|
+
status: "error",
|
|
274
|
+
error: n.errorMessage,
|
|
275
|
+
logLines: n.logLines,
|
|
276
|
+
duration: o
|
|
277
|
+
};
|
|
278
|
+
this.eventStore.addEvent(i), Array.isArray(n.logLines) && n.logLines.length > 0 && this.emitLogEvents(n.logLines, i.id);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Handle mutation responses
|
|
283
|
+
*/
|
|
284
|
+
handleMutationResponse(e) {
|
|
285
|
+
const t = this.pendingMutations.get(e.requestId);
|
|
286
|
+
if (!t) return;
|
|
287
|
+
const n = Date.now(), s = n - t.startTime, o = {
|
|
288
|
+
id: `mutation-${e.requestId}-${n}`,
|
|
289
|
+
timestamp: n,
|
|
290
|
+
type: "mutation",
|
|
291
|
+
requestId: e.requestId,
|
|
292
|
+
udfPath: t.udfPath,
|
|
293
|
+
args: t.args,
|
|
294
|
+
componentPath: t.componentPath,
|
|
295
|
+
status: e.success ? "success" : "error",
|
|
296
|
+
result: e.success ? e.result : void 0,
|
|
297
|
+
error: e.success ? void 0 : e.result,
|
|
298
|
+
logLines: e.logLines,
|
|
299
|
+
duration: s
|
|
300
|
+
};
|
|
301
|
+
this.eventStore.addEvent(o), this.lastMutationEventId = o.id, this.lastMutationTimestamp = n, e.logLines && e.logLines.length > 0 && this.emitLogEvents(e.logLines, o.id), this.pendingMutations.delete(e.requestId);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Handle action responses
|
|
305
|
+
*/
|
|
306
|
+
handleActionResponse(e) {
|
|
307
|
+
const t = this.pendingActions.get(e.requestId);
|
|
308
|
+
if (!t) return;
|
|
309
|
+
const n = Date.now(), s = n - t.startTime, o = {
|
|
310
|
+
id: `action-${e.requestId}-${n}`,
|
|
311
|
+
timestamp: n,
|
|
312
|
+
type: "action",
|
|
313
|
+
requestId: e.requestId,
|
|
314
|
+
udfPath: t.udfPath,
|
|
315
|
+
args: t.args,
|
|
316
|
+
componentPath: t.componentPath,
|
|
317
|
+
status: e.success ? "success" : "error",
|
|
318
|
+
result: e.success ? e.result : void 0,
|
|
319
|
+
error: e.success ? void 0 : e.result,
|
|
320
|
+
logLines: e.logLines,
|
|
321
|
+
duration: s
|
|
322
|
+
};
|
|
323
|
+
this.eventStore.addEvent(o), e.logLines && e.logLines.length > 0 && this.emitLogEvents(e.logLines, o.id), this.pendingActions.delete(e.requestId);
|
|
324
|
+
}
|
|
325
|
+
handleAuthErrorResponse(e) {
|
|
326
|
+
const t = {};
|
|
327
|
+
typeof e.baseVersion == "number" && (t.baseVersion = e.baseVersion), typeof e.authUpdateAttempted == "boolean" && (t.authUpdateAttempted = e.authUpdateAttempted), this.emitAuthEvent({
|
|
328
|
+
direction: "server",
|
|
329
|
+
messageType: "AuthError",
|
|
330
|
+
status: "error",
|
|
331
|
+
tokenType: this.pendingAuthTokenType ?? void 0,
|
|
332
|
+
error: e.error ?? "Authentication failed",
|
|
333
|
+
details: t
|
|
334
|
+
}), this.pendingAuthTokenType = null;
|
|
335
|
+
}
|
|
336
|
+
emitAuthEvent(e) {
|
|
337
|
+
const t = Date.now(), n = {
|
|
338
|
+
id: `auth-${e.direction}-${e.messageType}-${t}-${Math.random().toString(36).slice(2, 8)}`,
|
|
339
|
+
timestamp: t,
|
|
340
|
+
type: "auth",
|
|
341
|
+
direction: e.direction,
|
|
342
|
+
messageType: e.messageType,
|
|
343
|
+
status: e.status,
|
|
344
|
+
tokenType: e.tokenType,
|
|
345
|
+
error: e.error,
|
|
346
|
+
details: e.details
|
|
347
|
+
};
|
|
348
|
+
this.eventStore.addEvent(n);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Extract and emit log events from logLines
|
|
352
|
+
*/
|
|
353
|
+
emitLogEvents(e, t) {
|
|
354
|
+
const n = Date.now();
|
|
355
|
+
for (const s of e) {
|
|
356
|
+
const o = s.match(/^\[(log|info|warn|error)\]\s+(.+)$/i), i = o ? o[1].toLowerCase() : "log", a = o ? o[2] : s, u = {
|
|
357
|
+
id: `log-${n}-${Math.random()}`,
|
|
358
|
+
timestamp: n,
|
|
359
|
+
type: "log",
|
|
360
|
+
level: i,
|
|
361
|
+
message: a,
|
|
362
|
+
relatedEventId: t
|
|
363
|
+
};
|
|
364
|
+
this.eventStore.addEvent(u);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
export {
|
|
369
|
+
w as DataInspector,
|
|
370
|
+
P as DevToolbar,
|
|
371
|
+
E as EventStore,
|
|
372
|
+
S as LogsPanel,
|
|
373
|
+
A as PerformancePanel,
|
|
374
|
+
L as SettingsPanel,
|
|
375
|
+
M as SubscriptionsPanel,
|
|
376
|
+
I as WebSocketInterceptor,
|
|
377
|
+
R as concaveDevTools,
|
|
378
|
+
D as getGlobalEventStore,
|
|
379
|
+
$ as initDevTools
|
|
380
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket Interceptor for Convex Sync Protocol
|
|
3
|
+
*
|
|
4
|
+
* Intercepts WebSocket messages to capture queries, mutations, actions, subscriptions,
|
|
5
|
+
* and authentication protocol events.
|
|
6
|
+
*/
|
|
7
|
+
import type { EventStore } from "../store/event-store";
|
|
8
|
+
export declare class WebSocketInterceptor {
|
|
9
|
+
private eventStore;
|
|
10
|
+
private originalWebSocket;
|
|
11
|
+
private pendingQueries;
|
|
12
|
+
private pendingMutations;
|
|
13
|
+
private pendingActions;
|
|
14
|
+
private pendingAuthTokenType;
|
|
15
|
+
/** Tracks the most recent mutation event ID for causality linking */
|
|
16
|
+
private lastMutationEventId;
|
|
17
|
+
private lastMutationTimestamp;
|
|
18
|
+
constructor(eventStore: EventStore);
|
|
19
|
+
/**
|
|
20
|
+
* Install the WebSocket interceptor
|
|
21
|
+
*/
|
|
22
|
+
install(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Uninstall the interceptor
|
|
25
|
+
*/
|
|
26
|
+
uninstall(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Handle client → server messages
|
|
29
|
+
*/
|
|
30
|
+
private handleClientMessage;
|
|
31
|
+
/**
|
|
32
|
+
* Handle server → client messages
|
|
33
|
+
*/
|
|
34
|
+
private handleServerMessage;
|
|
35
|
+
/**
|
|
36
|
+
* Handle query set modifications (subscriptions)
|
|
37
|
+
*/
|
|
38
|
+
private handleModifyQuerySet;
|
|
39
|
+
/**
|
|
40
|
+
* Handle mutation requests
|
|
41
|
+
*/
|
|
42
|
+
private handleMutationRequest;
|
|
43
|
+
/**
|
|
44
|
+
* Handle action requests
|
|
45
|
+
*/
|
|
46
|
+
private handleActionRequest;
|
|
47
|
+
private handleConnectMessage;
|
|
48
|
+
private handleAuthenticateMessage;
|
|
49
|
+
/**
|
|
50
|
+
* Handle state transitions (query updates)
|
|
51
|
+
*/
|
|
52
|
+
private handleTransition;
|
|
53
|
+
/**
|
|
54
|
+
* Handle mutation responses
|
|
55
|
+
*/
|
|
56
|
+
private handleMutationResponse;
|
|
57
|
+
/**
|
|
58
|
+
* Handle action responses
|
|
59
|
+
*/
|
|
60
|
+
private handleActionResponse;
|
|
61
|
+
private handleAuthErrorResponse;
|
|
62
|
+
private emitAuthEvent;
|
|
63
|
+
/**
|
|
64
|
+
* Extract and emit log events from logLines
|
|
65
|
+
*/
|
|
66
|
+
private emitLogEvents;
|
|
67
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activity Panel - Unified view of queries, mutations, and actions
|
|
3
|
+
* with focused list-first debugging UX
|
|
4
|
+
*/
|
|
5
|
+
import type { EventStore } from "../store/event-store";
|
|
6
|
+
interface ActivityPanelProps {
|
|
7
|
+
eventStore: EventStore;
|
|
8
|
+
}
|
|
9
|
+
export declare function ActivityPanel({ eventStore }: ActivityPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ContextMenu - Native-style right-click context menu for DevTools panels
|
|
3
|
+
*/
|
|
4
|
+
export interface MenuItem {
|
|
5
|
+
label: string;
|
|
6
|
+
action: () => void;
|
|
7
|
+
shortcut?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
separator?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface ContextMenuProps {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
items: MenuItem[];
|
|
15
|
+
onClose: () => void;
|
|
16
|
+
}
|
|
17
|
+
export declare function ContextMenu({ x, y, items, onClose }: ContextMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
18
|
+
/** State type for panels using context menus */
|
|
19
|
+
export interface ContextMenuState {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
items: MenuItem[];
|
|
23
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data Inspector - Advanced JSON viewer with syntax highlighting, search, and diff
|
|
3
|
+
*/
|
|
4
|
+
import type { JSONValue } from "../types";
|
|
5
|
+
interface DataInspectorProps {
|
|
6
|
+
data: JSONValue;
|
|
7
|
+
label?: string;
|
|
8
|
+
onCopy?: () => void;
|
|
9
|
+
maxHeight?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function DataInspector({ data, label, onCopy, maxHeight, }: DataInspectorProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main DevTools Overlay Component
|
|
3
|
+
*/
|
|
4
|
+
import type { EventStore } from "../store/event-store";
|
|
5
|
+
interface DevToolbarProps {
|
|
6
|
+
eventStore: EventStore;
|
|
7
|
+
position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
|
|
8
|
+
mode?: "overlay" | "panel";
|
|
9
|
+
}
|
|
10
|
+
export declare function DevToolbar({ eventStore, position, mode }: DevToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logs Panel - Shows console logs from function executions
|
|
3
|
+
*/
|
|
4
|
+
import type { EventStore } from "../store/event-store";
|
|
5
|
+
interface LogsPanelProps {
|
|
6
|
+
eventStore: EventStore;
|
|
7
|
+
onNavigate?: (tab: "activity" | "subscriptions" | "performance" | "logs" | "settings") => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function LogsPanel({ eventStore, onNavigate }: LogsPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Network Panel - Shows all client-server communication
|
|
3
|
+
*/
|
|
4
|
+
import type { EventStore } from "../store/event-store";
|
|
5
|
+
interface NetworkPanelProps {
|
|
6
|
+
eventStore: EventStore;
|
|
7
|
+
}
|
|
8
|
+
export declare function NetworkPanel({ eventStore }: NetworkPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Performance Panel - Shows performance metrics with sparkline trends
|
|
3
|
+
*/
|
|
4
|
+
import type { EventStore } from "../store/event-store";
|
|
5
|
+
interface PerformancePanelProps {
|
|
6
|
+
eventStore: EventStore;
|
|
7
|
+
onNavigate?: (tab: "activity" | "subscriptions" | "performance" | "logs" | "settings") => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function PerformancePanel({ eventStore, onNavigate }: PerformancePanelProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
interface SearchFieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "value" | "onChange"> {
|
|
3
|
+
value: string;
|
|
4
|
+
onValueChange: (value: string) => void;
|
|
5
|
+
onClear?: () => void;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const SearchField: React.ForwardRefExoticComponent<SearchFieldProps & React.RefAttributes<HTMLInputElement>>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings Panel - Configure devtools behavior
|
|
3
|
+
*/
|
|
4
|
+
import type { EventStore } from "../store/event-store";
|
|
5
|
+
interface SettingsPanelProps {
|
|
6
|
+
eventStore: EventStore;
|
|
7
|
+
}
|
|
8
|
+
export declare function SettingsPanel({ eventStore }: SettingsPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscriptions Panel - Shows active query subscriptions
|
|
3
|
+
*/
|
|
4
|
+
import type { EventStore } from "../store/event-store";
|
|
5
|
+
interface SubscriptionsPanelProps {
|
|
6
|
+
eventStore: EventStore;
|
|
7
|
+
}
|
|
8
|
+
export declare function SubscriptionsPanel({ eventStore }: SubscriptionsPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timeline Panel - Visual timeline of all events
|
|
3
|
+
*/
|
|
4
|
+
import type { EventStore } from "../store/event-store";
|
|
5
|
+
interface TimelinePanelProps {
|
|
6
|
+
eventStore: EventStore;
|
|
7
|
+
}
|
|
8
|
+
export declare function TimelinePanel({ eventStore }: TimelinePanelProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copy text to clipboard with fallback for restricted contexts (e.g. Chrome
|
|
3
|
+
* DevTools panels where the Clipboard API is blocked by permissions policy).
|
|
4
|
+
* Shows a brief "Copied!" toast on success.
|
|
5
|
+
*/
|
|
6
|
+
export declare function copyToClipboard(text: string): void;
|
|
7
|
+
export declare function unwrapArgs<T>(args: T): T;
|
|
8
|
+
export type InlinePreviewOptions = {
|
|
9
|
+
maxStringLength?: number;
|
|
10
|
+
stringTailLength?: number;
|
|
11
|
+
maxArrayItems?: number;
|
|
12
|
+
maxObjectEntries?: number;
|
|
13
|
+
maxDepth?: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function formatInlinePreview(value: any, options?: InlinePreviewOptions, depth?: number): string;
|
|
16
|
+
export declare function formatJsonSnippet(value: any, maxLength?: number): string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standalone DevTools Entry Point
|
|
3
|
+
*
|
|
4
|
+
* Self-contained bundle that can be loaded via <script> on any page.
|
|
5
|
+
* Renders inside a Shadow DOM for complete CSS/DOM isolation from the host page.
|
|
6
|
+
*
|
|
7
|
+
* When the Chrome extension's page-agent is already intercepting WebSockets,
|
|
8
|
+
* this skips installing its own interceptor and instead consumes events from
|
|
9
|
+
* page-agent via postMessage. This enables overlay + panel coexistence.
|
|
10
|
+
*/
|
|
11
|
+
export {};
|