@concavejs/devtools 0.0.1-alpha.10
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 +263 -0
- package/dist/client-CRYWrjNv.js +3590 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.js +6 -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 +486 -0
- package/dist/interceptor/index.d.ts +5 -0
- package/dist/interceptor/websocket-interceptor.d.ts +68 -0
- package/dist/overlay/ActivityPanel.d.ts +18 -0
- package/dist/overlay/ContextMenu.d.ts +23 -0
- package/dist/overlay/DataInspector.d.ts +12 -0
- package/dist/overlay/DevToolbar.d.ts +19 -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/TraceViewer.d.ts +7 -0
- package/dist/overlay/utils.d.ts +30 -0
- package/dist/standalone.d.ts +11 -0
- package/dist/store/event-store.d.ts +191 -0
- package/dist/store/safe-storage.d.ts +7 -0
- package/dist/types.d.ts +211 -0
- package/dist/version.d.ts +10 -0
- package/dist/vite-plugin/index.d.ts +16 -0
- package/dist/vite-plugin.js +668 -0
- package/package.json +62 -0
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
function c(o = {}) {
|
|
2
|
+
const { enabled: s = !0, position: a = "bottom-right" } = o;
|
|
3
|
+
let t = !1;
|
|
4
|
+
return {
|
|
5
|
+
name: "concave-devtools",
|
|
6
|
+
configResolved(e) {
|
|
7
|
+
t = e.mode === "development";
|
|
8
|
+
},
|
|
9
|
+
transformIndexHtml: {
|
|
10
|
+
order: "pre",
|
|
11
|
+
handler(e) {
|
|
12
|
+
if (!t || !s)
|
|
13
|
+
return e;
|
|
14
|
+
const i = `
|
|
15
|
+
<script>
|
|
16
|
+
// Initialize event store immediately
|
|
17
|
+
(function() {
|
|
18
|
+
if (window.__concaveDevTools) return;
|
|
19
|
+
|
|
20
|
+
console.log('[DevTools] Installing WebSocket interceptor...');
|
|
21
|
+
|
|
22
|
+
// Minimal event store for capturing events
|
|
23
|
+
window.__concaveDevToolsEvents = [];
|
|
24
|
+
window.__concaveDevToolsPendingQueries = new Map();
|
|
25
|
+
window.__concaveDevToolsPendingMutations = new Map();
|
|
26
|
+
window.__concaveDevToolsPendingActions = new Map();
|
|
27
|
+
window.__concaveDevToolsPendingAuthTokenType = null;
|
|
28
|
+
|
|
29
|
+
// Latency simulation config (mutated by devtools settings panel)
|
|
30
|
+
if (!window.__concaveDevToolsLatencyConfig) {
|
|
31
|
+
window.__concaveDevToolsLatencyConfig = { latencyMs: 0, jitterMs: 0 };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var __concaveSanitizeLatency = function(value) {
|
|
35
|
+
var parsed = Number(value);
|
|
36
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return 0;
|
|
37
|
+
return Math.min(parsed, 5000);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
var __concaveGetLatencyDelay = function() {
|
|
41
|
+
var cfg = window.__concaveDevToolsLatencyConfig;
|
|
42
|
+
if (!cfg) return 0;
|
|
43
|
+
var base = __concaveSanitizeLatency(cfg.latencyMs);
|
|
44
|
+
var jitter = __concaveSanitizeLatency(cfg.jitterMs);
|
|
45
|
+
if (base <= 0 && jitter <= 0) return 0;
|
|
46
|
+
if (base > 0 && jitter > base) jitter = base;
|
|
47
|
+
return Math.max(0, base + (jitter > 0 ? (Math.random() * 2 - 1) * jitter : 0));
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
var __concaveInternalMessageListener = Symbol.for('__concaveDevToolsInternalWsListener');
|
|
51
|
+
var __concaveLatencyDelaySymbol = Symbol.for('__concaveDevToolsWsDelayMs');
|
|
52
|
+
var __concaveGetDelayForEvent = function(event) {
|
|
53
|
+
if (!event || typeof event !== 'object') return __concaveGetLatencyDelay();
|
|
54
|
+
var existing = event[__concaveLatencyDelaySymbol];
|
|
55
|
+
if (typeof existing === 'number' && isFinite(existing) && existing >= 0) {
|
|
56
|
+
return existing;
|
|
57
|
+
}
|
|
58
|
+
var sampled = __concaveGetLatencyDelay();
|
|
59
|
+
try {
|
|
60
|
+
Object.defineProperty(event, __concaveLatencyDelaySymbol, {
|
|
61
|
+
value: sampled,
|
|
62
|
+
configurable: true
|
|
63
|
+
});
|
|
64
|
+
} catch (e) {
|
|
65
|
+
event[__concaveLatencyDelaySymbol] = sampled;
|
|
66
|
+
}
|
|
67
|
+
return sampled;
|
|
68
|
+
};
|
|
69
|
+
var __concaveInvokeWithLatency = function(listener, target, event) {
|
|
70
|
+
if (typeof listener !== 'function') return;
|
|
71
|
+
if (listener[__concaveInternalMessageListener]) {
|
|
72
|
+
listener.call(target, event);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
var delay = 0;
|
|
76
|
+
try {
|
|
77
|
+
delay = __concaveGetDelayForEvent(event);
|
|
78
|
+
} catch (e) {
|
|
79
|
+
delay = 0;
|
|
80
|
+
}
|
|
81
|
+
if (delay > 0) {
|
|
82
|
+
setTimeout(function() {
|
|
83
|
+
listener.call(target, event);
|
|
84
|
+
}, delay);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
listener.call(target, event);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const OriginalWebSocket = window.WebSocket;
|
|
91
|
+
|
|
92
|
+
const emitAuthEvent = (direction, messageType, status, details, error, tokenType) => {
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
window.__concaveDevToolsEvents.push({
|
|
95
|
+
id: 'auth-' + direction + '-' + messageType + '-' + now + '-' + Math.random().toString(36).slice(2, 8),
|
|
96
|
+
timestamp: now,
|
|
97
|
+
type: 'auth',
|
|
98
|
+
direction,
|
|
99
|
+
messageType,
|
|
100
|
+
status,
|
|
101
|
+
tokenType,
|
|
102
|
+
error,
|
|
103
|
+
details,
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const decodeJwtClaims = (token) => {
|
|
108
|
+
const parts = token.split('.');
|
|
109
|
+
if (parts.length < 2) return null;
|
|
110
|
+
try {
|
|
111
|
+
const normalized = parts[1].replace(/-/g, '+').replace(/_/g, '/');
|
|
112
|
+
const padded = normalized + '='.repeat((4 - (normalized.length % 4)) % 4);
|
|
113
|
+
const payload = JSON.parse(atob(padded));
|
|
114
|
+
const keys = ['iss', 'sub', 'aud', 'exp', 'iat', 'nbf'];
|
|
115
|
+
const claims = {};
|
|
116
|
+
keys.forEach((key) => {
|
|
117
|
+
if (payload[key] !== undefined) claims[key] = payload[key];
|
|
118
|
+
});
|
|
119
|
+
if (typeof claims.exp === 'number') claims.expIso = new Date(claims.exp * 1000).toISOString();
|
|
120
|
+
if (typeof claims.iat === 'number') claims.iatIso = new Date(claims.iat * 1000).toISOString();
|
|
121
|
+
return Object.keys(claims).length > 0 ? claims : null;
|
|
122
|
+
} catch (e) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Create intercepted WebSocket constructor
|
|
128
|
+
window.WebSocket = function(url, protocols) {
|
|
129
|
+
const ws = new OriginalWebSocket(url, protocols);
|
|
130
|
+
|
|
131
|
+
// Intercept send
|
|
132
|
+
const originalSend = ws.send.bind(ws);
|
|
133
|
+
ws.send = function(data) {
|
|
134
|
+
if (typeof data === 'string') {
|
|
135
|
+
try {
|
|
136
|
+
const msg = JSON.parse(data);
|
|
137
|
+
const now = Date.now();
|
|
138
|
+
|
|
139
|
+
if (msg.type === 'Connect') {
|
|
140
|
+
const connectDetails = {};
|
|
141
|
+
if (typeof msg.connectionCount === 'number') connectDetails.connectionCount = msg.connectionCount;
|
|
142
|
+
if (typeof msg.lastCloseReason === 'string') connectDetails.lastCloseReason = msg.lastCloseReason;
|
|
143
|
+
if (typeof msg.clientTs === 'number') connectDetails.clientTs = msg.clientTs;
|
|
144
|
+
if (typeof msg.sessionId === 'string') connectDetails.sessionId = msg.sessionId;
|
|
145
|
+
emitAuthEvent('client', 'Connect', 'success', connectDetails, undefined, undefined);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (msg.type === 'Authenticate') {
|
|
149
|
+
const authDetails = {};
|
|
150
|
+
if (typeof msg.baseVersion === 'number') authDetails.baseVersion = msg.baseVersion;
|
|
151
|
+
if (typeof msg.tokenType === 'string') authDetails.tokenType = msg.tokenType;
|
|
152
|
+
if (typeof msg.value === 'string' && msg.value.length > 0) {
|
|
153
|
+
authDetails.tokenLength = msg.value.length;
|
|
154
|
+
authDetails.tokenPreview = msg.value.length > 24
|
|
155
|
+
? msg.value.slice(0, 12) + '…' + msg.value.slice(-10)
|
|
156
|
+
: msg.value;
|
|
157
|
+
const claims = decodeJwtClaims(msg.value);
|
|
158
|
+
if (claims) authDetails.jwtClaims = claims;
|
|
159
|
+
}
|
|
160
|
+
window.__concaveDevToolsPendingAuthTokenType = msg.tokenType || 'Unknown';
|
|
161
|
+
emitAuthEvent('client', 'Authenticate', 'success', authDetails, undefined, msg.tokenType);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Track queries
|
|
165
|
+
if (msg.type === 'ModifyQuerySet' && msg.modifications) {
|
|
166
|
+
msg.modifications.forEach(mod => {
|
|
167
|
+
if (mod.type === 'Add') {
|
|
168
|
+
window.__concaveDevToolsPendingQueries.set(mod.queryId, {
|
|
169
|
+
queryId: mod.queryId,
|
|
170
|
+
udfPath: mod.udfPath,
|
|
171
|
+
args: mod.args,
|
|
172
|
+
componentPath: mod.componentPath,
|
|
173
|
+
startTime: now
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
window.__concaveDevToolsEvents.push({
|
|
177
|
+
id: 'sub-' + mod.queryId + '-' + now,
|
|
178
|
+
timestamp: now,
|
|
179
|
+
type: 'subscription',
|
|
180
|
+
queryId: mod.queryId,
|
|
181
|
+
udfPath: mod.udfPath,
|
|
182
|
+
args: mod.args,
|
|
183
|
+
componentPath: mod.componentPath,
|
|
184
|
+
status: 'added'
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
window.__concaveDevToolsEvents.push({
|
|
188
|
+
id: 'query-pending-' + mod.queryId + '-' + now,
|
|
189
|
+
timestamp: now,
|
|
190
|
+
type: 'query',
|
|
191
|
+
queryId: mod.queryId,
|
|
192
|
+
udfPath: mod.udfPath,
|
|
193
|
+
args: mod.args,
|
|
194
|
+
componentPath: mod.componentPath,
|
|
195
|
+
status: 'pending'
|
|
196
|
+
});
|
|
197
|
+
} else if (mod.type === 'Remove') {
|
|
198
|
+
const pending = window.__concaveDevToolsPendingQueries.get(mod.queryId);
|
|
199
|
+
window.__concaveDevToolsPendingQueries.delete(mod.queryId);
|
|
200
|
+
// Emit removed subscription if we have context
|
|
201
|
+
window.__concaveDevToolsEvents.push({
|
|
202
|
+
id: 'sub-' + mod.queryId + '-' + now,
|
|
203
|
+
timestamp: now,
|
|
204
|
+
type: 'subscription',
|
|
205
|
+
queryId: mod.queryId,
|
|
206
|
+
udfPath: pending ? pending.udfPath : 'unknown',
|
|
207
|
+
args: pending ? pending.args : [],
|
|
208
|
+
componentPath: pending ? pending.componentPath : undefined,
|
|
209
|
+
status: 'removed'
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Track mutations
|
|
216
|
+
if (msg.type === 'Mutation') {
|
|
217
|
+
window.__concaveDevToolsPendingMutations.set(msg.requestId, {
|
|
218
|
+
requestId: msg.requestId,
|
|
219
|
+
udfPath: msg.udfPath,
|
|
220
|
+
args: msg.args,
|
|
221
|
+
componentPath: msg.componentPath,
|
|
222
|
+
startTime: now
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
window.__concaveDevToolsEvents.push({
|
|
226
|
+
id: 'mutation-pending-' + msg.requestId + '-' + now,
|
|
227
|
+
timestamp: now,
|
|
228
|
+
type: 'mutation',
|
|
229
|
+
requestId: msg.requestId,
|
|
230
|
+
udfPath: msg.udfPath,
|
|
231
|
+
args: msg.args,
|
|
232
|
+
componentPath: msg.componentPath,
|
|
233
|
+
status: 'pending'
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Track actions
|
|
238
|
+
if (msg.type === 'Action') {
|
|
239
|
+
window.__concaveDevToolsPendingActions.set(msg.requestId, {
|
|
240
|
+
requestId: msg.requestId,
|
|
241
|
+
udfPath: msg.udfPath,
|
|
242
|
+
args: msg.args,
|
|
243
|
+
componentPath: msg.componentPath,
|
|
244
|
+
startTime: now
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
window.__concaveDevToolsEvents.push({
|
|
248
|
+
id: 'action-pending-' + msg.requestId + '-' + now,
|
|
249
|
+
timestamp: now,
|
|
250
|
+
type: 'action',
|
|
251
|
+
requestId: msg.requestId,
|
|
252
|
+
udfPath: msg.udfPath,
|
|
253
|
+
args: msg.args,
|
|
254
|
+
componentPath: msg.componentPath,
|
|
255
|
+
status: 'pending'
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
} catch (e) {
|
|
259
|
+
console.warn('[DevTools] Error parsing client message:', e);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return originalSend(data);
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// Intercept message handlers and keep listener identity stable so removeEventListener works.
|
|
266
|
+
const originalAddEventListener = ws.addEventListener.bind(ws);
|
|
267
|
+
const originalRemoveEventListener = ws.removeEventListener.bind(ws);
|
|
268
|
+
const messageListenerWrappers = new WeakMap();
|
|
269
|
+
ws.addEventListener = function(type, listener, options) {
|
|
270
|
+
if (type === 'message' && typeof listener === 'function') {
|
|
271
|
+
let wrappedListener = messageListenerWrappers.get(listener);
|
|
272
|
+
if (!wrappedListener) {
|
|
273
|
+
wrappedListener = function(event) {
|
|
274
|
+
try {
|
|
275
|
+
const msg = JSON.parse(event.data);
|
|
276
|
+
const now = Date.now();
|
|
277
|
+
const delayMs = __concaveGetDelayForEvent(event);
|
|
278
|
+
|
|
279
|
+
if (msg.type === 'AuthError') {
|
|
280
|
+
const errorDetails = {};
|
|
281
|
+
if (typeof msg.baseVersion === 'number') errorDetails.baseVersion = msg.baseVersion;
|
|
282
|
+
if (typeof msg.authUpdateAttempted === 'boolean') errorDetails.authUpdateAttempted = msg.authUpdateAttempted;
|
|
283
|
+
emitAuthEvent('server', 'AuthError', 'error', errorDetails, msg.error || 'Authentication failed', window.__concaveDevToolsPendingAuthTokenType || undefined);
|
|
284
|
+
window.__concaveDevToolsPendingAuthTokenType = null;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Handle transitions (query updates)
|
|
288
|
+
if (msg.type === 'Transition' && msg.modifications) {
|
|
289
|
+
if (window.__concaveDevToolsPendingAuthTokenType) {
|
|
290
|
+
emitAuthEvent(
|
|
291
|
+
'server',
|
|
292
|
+
'Authenticated',
|
|
293
|
+
'success',
|
|
294
|
+
{ modificationCount: msg.modifications.length },
|
|
295
|
+
undefined,
|
|
296
|
+
window.__concaveDevToolsPendingAuthTokenType
|
|
297
|
+
);
|
|
298
|
+
window.__concaveDevToolsPendingAuthTokenType = null;
|
|
299
|
+
}
|
|
300
|
+
msg.modifications.forEach(mod => {
|
|
301
|
+
if (mod.type === 'QueryUpdated' || mod.type === 'QueryFailed') {
|
|
302
|
+
const pending = window.__concaveDevToolsPendingQueries.get(mod.queryId);
|
|
303
|
+
if (pending) {
|
|
304
|
+
const duration = now - pending.startTime;
|
|
305
|
+
window.__concaveDevToolsEvents.push({
|
|
306
|
+
id: 'query-' + mod.queryId + '-' + now,
|
|
307
|
+
timestamp: now,
|
|
308
|
+
type: 'query',
|
|
309
|
+
queryId: mod.queryId,
|
|
310
|
+
udfPath: pending.udfPath,
|
|
311
|
+
args: pending.args,
|
|
312
|
+
componentPath: pending.componentPath,
|
|
313
|
+
status: mod.type === 'QueryUpdated' ? 'success' : 'error',
|
|
314
|
+
result: mod.type === 'QueryUpdated' ? mod.value : undefined,
|
|
315
|
+
error: mod.type === 'QueryFailed' ? mod.errorMessage : undefined,
|
|
316
|
+
trace: mod.type === 'QueryUpdated' ? mod.trace : undefined,
|
|
317
|
+
logLines: mod.logLines,
|
|
318
|
+
duration: duration,
|
|
319
|
+
simulatedDelayMs: delayMs,
|
|
320
|
+
endToEndDurationMs: duration + delayMs
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// Extract log events
|
|
324
|
+
if (mod.logLines && mod.logLines.length > 0) {
|
|
325
|
+
mod.logLines.forEach(logLine => {
|
|
326
|
+
const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
|
|
327
|
+
const level = match ? match[1].toLowerCase() : 'log';
|
|
328
|
+
const message = match ? match[2] : logLine;
|
|
329
|
+
window.__concaveDevToolsEvents.push({
|
|
330
|
+
id: 'log-' + now + '-' + Math.random(),
|
|
331
|
+
timestamp: now,
|
|
332
|
+
type: 'log',
|
|
333
|
+
level: level,
|
|
334
|
+
message: message,
|
|
335
|
+
relatedEventId: 'query-' + mod.queryId + '-' + now
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Handle mutation responses
|
|
345
|
+
if (msg.type === 'MutationResponse') {
|
|
346
|
+
const pending = window.__concaveDevToolsPendingMutations.get(msg.requestId);
|
|
347
|
+
if (pending) {
|
|
348
|
+
const duration = now - pending.startTime;
|
|
349
|
+
window.__concaveDevToolsEvents.push({
|
|
350
|
+
id: 'mutation-' + msg.requestId + '-' + now,
|
|
351
|
+
timestamp: now,
|
|
352
|
+
type: 'mutation',
|
|
353
|
+
requestId: msg.requestId,
|
|
354
|
+
udfPath: pending.udfPath,
|
|
355
|
+
args: pending.args,
|
|
356
|
+
componentPath: pending.componentPath,
|
|
357
|
+
status: msg.success ? 'success' : 'error',
|
|
358
|
+
result: msg.success ? msg.result : undefined,
|
|
359
|
+
error: !msg.success ? msg.result : undefined,
|
|
360
|
+
trace: msg.trace,
|
|
361
|
+
logLines: msg.logLines,
|
|
362
|
+
duration: duration,
|
|
363
|
+
simulatedDelayMs: delayMs,
|
|
364
|
+
endToEndDurationMs: duration + delayMs
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
// Extract log events
|
|
368
|
+
if (msg.logLines && msg.logLines.length > 0) {
|
|
369
|
+
msg.logLines.forEach(logLine => {
|
|
370
|
+
const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
|
|
371
|
+
const level = match ? match[1].toLowerCase() : 'log';
|
|
372
|
+
const message = match ? match[2] : logLine;
|
|
373
|
+
window.__concaveDevToolsEvents.push({
|
|
374
|
+
id: 'log-' + now + '-' + Math.random(),
|
|
375
|
+
timestamp: now,
|
|
376
|
+
type: 'log',
|
|
377
|
+
level: level,
|
|
378
|
+
message: message,
|
|
379
|
+
relatedEventId: 'mutation-' + msg.requestId + '-' + now
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
window.__concaveDevToolsPendingMutations.delete(msg.requestId);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Handle action responses
|
|
389
|
+
if (msg.type === 'ActionResponse') {
|
|
390
|
+
const pending = window.__concaveDevToolsPendingActions.get(msg.requestId);
|
|
391
|
+
if (pending) {
|
|
392
|
+
const duration = now - pending.startTime;
|
|
393
|
+
window.__concaveDevToolsEvents.push({
|
|
394
|
+
id: 'action-' + msg.requestId + '-' + now,
|
|
395
|
+
timestamp: now,
|
|
396
|
+
type: 'action',
|
|
397
|
+
requestId: msg.requestId,
|
|
398
|
+
udfPath: pending.udfPath,
|
|
399
|
+
args: pending.args,
|
|
400
|
+
componentPath: pending.componentPath,
|
|
401
|
+
status: msg.success ? 'success' : 'error',
|
|
402
|
+
result: msg.success ? msg.result : undefined,
|
|
403
|
+
error: !msg.success ? msg.result : undefined,
|
|
404
|
+
trace: msg.trace,
|
|
405
|
+
logLines: msg.logLines,
|
|
406
|
+
duration: duration,
|
|
407
|
+
simulatedDelayMs: delayMs,
|
|
408
|
+
endToEndDurationMs: duration + delayMs
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
// Extract log events
|
|
412
|
+
if (msg.logLines && msg.logLines.length > 0) {
|
|
413
|
+
msg.logLines.forEach(logLine => {
|
|
414
|
+
const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
|
|
415
|
+
const level = match ? match[1].toLowerCase() : 'log';
|
|
416
|
+
const message = match ? match[2] : logLine;
|
|
417
|
+
window.__concaveDevToolsEvents.push({
|
|
418
|
+
id: 'log-' + now + '-' + Math.random(),
|
|
419
|
+
timestamp: now,
|
|
420
|
+
type: 'log',
|
|
421
|
+
level: level,
|
|
422
|
+
message: message,
|
|
423
|
+
relatedEventId: 'action-' + msg.requestId + '-' + now
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
window.__concaveDevToolsPendingActions.delete(msg.requestId);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
} catch (e) {
|
|
432
|
+
console.warn('[DevTools] Error parsing server message:', e);
|
|
433
|
+
}
|
|
434
|
+
__concaveInvokeWithLatency(listener, ws, event);
|
|
435
|
+
};
|
|
436
|
+
wrappedListener[__concaveInternalMessageListener] = true;
|
|
437
|
+
messageListenerWrappers.set(listener, wrappedListener);
|
|
438
|
+
}
|
|
439
|
+
return originalAddEventListener('message', wrappedListener, options);
|
|
440
|
+
}
|
|
441
|
+
return originalAddEventListener(type, listener, options);
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
ws.removeEventListener = function(type, listener, options) {
|
|
445
|
+
if (type === 'message' && typeof listener === 'function') {
|
|
446
|
+
const wrappedListener = messageListenerWrappers.get(listener);
|
|
447
|
+
return originalRemoveEventListener('message', wrappedListener || listener, options);
|
|
448
|
+
}
|
|
449
|
+
return originalRemoveEventListener(type, listener, options);
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
// Intercept onmessage assignment as well
|
|
453
|
+
(function(){
|
|
454
|
+
let currentHandler = null;
|
|
455
|
+
let currentOnMessageWrapper = null;
|
|
456
|
+
Object.defineProperty(ws, 'onmessage', {
|
|
457
|
+
configurable: true,
|
|
458
|
+
enumerable: true,
|
|
459
|
+
get() {
|
|
460
|
+
return currentHandler;
|
|
461
|
+
},
|
|
462
|
+
set(handler) {
|
|
463
|
+
// Remove previous wrapper if present
|
|
464
|
+
if (currentOnMessageWrapper) {
|
|
465
|
+
originalRemoveEventListener('message', currentOnMessageWrapper);
|
|
466
|
+
currentOnMessageWrapper = null;
|
|
467
|
+
}
|
|
468
|
+
currentHandler = handler;
|
|
469
|
+
if (typeof handler === 'function') {
|
|
470
|
+
const wrapper = function(event) {
|
|
471
|
+
try {
|
|
472
|
+
const msg = JSON.parse(event.data);
|
|
473
|
+
const now = Date.now();
|
|
474
|
+
const delayMs = __concaveGetDelayForEvent(event);
|
|
475
|
+
|
|
476
|
+
if (msg.type === 'AuthError') {
|
|
477
|
+
const errorDetails = {};
|
|
478
|
+
if (typeof msg.baseVersion === 'number') errorDetails.baseVersion = msg.baseVersion;
|
|
479
|
+
if (typeof msg.authUpdateAttempted === 'boolean') errorDetails.authUpdateAttempted = msg.authUpdateAttempted;
|
|
480
|
+
emitAuthEvent('server', 'AuthError', 'error', errorDetails, msg.error || 'Authentication failed', window.__concaveDevToolsPendingAuthTokenType || undefined);
|
|
481
|
+
window.__concaveDevToolsPendingAuthTokenType = null;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Mirror the same processing as in addEventListener wrapper
|
|
485
|
+
if (msg.type === 'Transition' && msg.modifications) {
|
|
486
|
+
if (window.__concaveDevToolsPendingAuthTokenType) {
|
|
487
|
+
emitAuthEvent(
|
|
488
|
+
'server',
|
|
489
|
+
'Authenticated',
|
|
490
|
+
'success',
|
|
491
|
+
{ modificationCount: msg.modifications.length },
|
|
492
|
+
undefined,
|
|
493
|
+
window.__concaveDevToolsPendingAuthTokenType
|
|
494
|
+
);
|
|
495
|
+
window.__concaveDevToolsPendingAuthTokenType = null;
|
|
496
|
+
}
|
|
497
|
+
msg.modifications.forEach(mod => {
|
|
498
|
+
if (mod.type === 'QueryUpdated' || mod.type === 'QueryFailed') {
|
|
499
|
+
const pending = window.__concaveDevToolsPendingQueries.get(mod.queryId);
|
|
500
|
+
if (pending) {
|
|
501
|
+
const duration = now - pending.startTime;
|
|
502
|
+
window.__concaveDevToolsEvents.push({
|
|
503
|
+
id: 'query-' + mod.queryId + '-' + now,
|
|
504
|
+
timestamp: now,
|
|
505
|
+
type: 'query',
|
|
506
|
+
queryId: mod.queryId,
|
|
507
|
+
udfPath: pending.udfPath,
|
|
508
|
+
args: pending.args,
|
|
509
|
+
componentPath: pending.componentPath,
|
|
510
|
+
status: mod.type === 'QueryUpdated' ? 'success' : 'error',
|
|
511
|
+
result: mod.type === 'QueryUpdated' ? mod.value : undefined,
|
|
512
|
+
error: mod.type === 'QueryFailed' ? mod.errorMessage : undefined,
|
|
513
|
+
trace: mod.type === 'QueryUpdated' ? mod.trace : undefined,
|
|
514
|
+
logLines: mod.logLines,
|
|
515
|
+
duration: duration,
|
|
516
|
+
simulatedDelayMs: delayMs,
|
|
517
|
+
endToEndDurationMs: duration + delayMs
|
|
518
|
+
});
|
|
519
|
+
if (mod.logLines && mod.logLines.length > 0) {
|
|
520
|
+
mod.logLines.forEach(logLine => {
|
|
521
|
+
const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
|
|
522
|
+
const level = match ? match[1].toLowerCase() : 'log';
|
|
523
|
+
const message = match ? match[2] : logLine;
|
|
524
|
+
window.__concaveDevToolsEvents.push({
|
|
525
|
+
id: 'log-' + now + '-' + Math.random(),
|
|
526
|
+
timestamp: now,
|
|
527
|
+
type: 'log',
|
|
528
|
+
level: level,
|
|
529
|
+
message: message,
|
|
530
|
+
relatedEventId: 'query-' + mod.queryId + '-' + now
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
if (msg.type === 'MutationResponse') {
|
|
539
|
+
const pending = window.__concaveDevToolsPendingMutations.get(msg.requestId);
|
|
540
|
+
if (pending) {
|
|
541
|
+
const duration = now - pending.startTime;
|
|
542
|
+
window.__concaveDevToolsEvents.push({
|
|
543
|
+
id: 'mutation-' + msg.requestId + '-' + now,
|
|
544
|
+
timestamp: now,
|
|
545
|
+
type: 'mutation',
|
|
546
|
+
requestId: msg.requestId,
|
|
547
|
+
udfPath: pending.udfPath,
|
|
548
|
+
args: pending.args,
|
|
549
|
+
componentPath: pending.componentPath,
|
|
550
|
+
status: msg.success ? 'success' : 'error',
|
|
551
|
+
result: msg.success ? msg.result : undefined,
|
|
552
|
+
error: !msg.success ? msg.result : undefined,
|
|
553
|
+
trace: msg.trace,
|
|
554
|
+
logLines: msg.logLines,
|
|
555
|
+
duration: duration,
|
|
556
|
+
simulatedDelayMs: delayMs,
|
|
557
|
+
endToEndDurationMs: duration + delayMs
|
|
558
|
+
});
|
|
559
|
+
if (msg.logLines && msg.logLines.length > 0) {
|
|
560
|
+
msg.logLines.forEach(logLine => {
|
|
561
|
+
const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
|
|
562
|
+
const level = match ? match[1].toLowerCase() : 'log';
|
|
563
|
+
const message = match ? match[2] : logLine;
|
|
564
|
+
window.__concaveDevToolsEvents.push({
|
|
565
|
+
id: 'log-' + now + '-' + Math.random(),
|
|
566
|
+
timestamp: now,
|
|
567
|
+
type: 'log',
|
|
568
|
+
level: level,
|
|
569
|
+
message: message,
|
|
570
|
+
relatedEventId: 'mutation-' + msg.requestId + '-' + now
|
|
571
|
+
});
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
window.__concaveDevToolsPendingMutations.delete(msg.requestId);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if (msg.type === 'ActionResponse') {
|
|
578
|
+
const pending = window.__concaveDevToolsPendingActions.get(msg.requestId);
|
|
579
|
+
if (pending) {
|
|
580
|
+
const duration = now - pending.startTime;
|
|
581
|
+
window.__concaveDevToolsEvents.push({
|
|
582
|
+
id: 'action-' + msg.requestId + '-' + now,
|
|
583
|
+
timestamp: now,
|
|
584
|
+
type: 'action',
|
|
585
|
+
requestId: msg.requestId,
|
|
586
|
+
udfPath: pending.udfPath,
|
|
587
|
+
args: pending.args,
|
|
588
|
+
componentPath: pending.componentPath,
|
|
589
|
+
status: msg.success ? 'success' : 'error',
|
|
590
|
+
result: msg.success ? msg.result : undefined,
|
|
591
|
+
error: !msg.success ? msg.result : undefined,
|
|
592
|
+
trace: msg.trace,
|
|
593
|
+
logLines: msg.logLines,
|
|
594
|
+
duration: duration,
|
|
595
|
+
simulatedDelayMs: delayMs,
|
|
596
|
+
endToEndDurationMs: duration + delayMs
|
|
597
|
+
});
|
|
598
|
+
if (msg.logLines && msg.logLines.length > 0) {
|
|
599
|
+
msg.logLines.forEach(logLine => {
|
|
600
|
+
const match = logLine.match(/^\\[(log|info|warn|error)\\]\\s+(.+)$/i);
|
|
601
|
+
const level = match ? match[1].toLowerCase() : 'log';
|
|
602
|
+
const message = match ? match[2] : logLine;
|
|
603
|
+
window.__concaveDevToolsEvents.push({
|
|
604
|
+
id: 'log-' + now + '-' + Math.random(),
|
|
605
|
+
timestamp: now,
|
|
606
|
+
type: 'log',
|
|
607
|
+
level: level,
|
|
608
|
+
message: message,
|
|
609
|
+
relatedEventId: 'action-' + msg.requestId + '-' + now
|
|
610
|
+
});
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
window.__concaveDevToolsPendingActions.delete(msg.requestId);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
} catch (e) {
|
|
617
|
+
console.warn('[DevTools] Error parsing server message (onmessage):', e);
|
|
618
|
+
}
|
|
619
|
+
__concaveInvokeWithLatency(handler, ws, event);
|
|
620
|
+
};
|
|
621
|
+
wrapper[__concaveInternalMessageListener] = true;
|
|
622
|
+
currentOnMessageWrapper = wrapper;
|
|
623
|
+
originalAddEventListener('message', wrapper);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
})();
|
|
628
|
+
|
|
629
|
+
return ws;
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
// Preserve prototype chain
|
|
633
|
+
Object.setPrototypeOf(window.WebSocket, OriginalWebSocket);
|
|
634
|
+
Object.defineProperty(window.WebSocket, 'prototype', {
|
|
635
|
+
value: OriginalWebSocket.prototype,
|
|
636
|
+
writable: false,
|
|
637
|
+
configurable: false
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
console.log('[DevTools] WebSocket interceptor installed');
|
|
641
|
+
})();
|
|
642
|
+
<\/script>
|
|
643
|
+
`, r = `
|
|
644
|
+
<script>
|
|
645
|
+
window.__concaveDevToolsConfig = ${JSON.stringify({ position: a, autoInit: !0 })};
|
|
646
|
+
<\/script>
|
|
647
|
+
`, n = i + r + `
|
|
648
|
+
<script type="module">
|
|
649
|
+
import { initDevTools } from '@concavejs/devtools/client';
|
|
650
|
+
<\/script>
|
|
651
|
+
`;
|
|
652
|
+
return e.includes("</head>") ? e.replace("</head>", `${n}</head>`) : e.includes("</body>") ? e.replace("</body>", `${n}</body>`) : e + n;
|
|
653
|
+
}
|
|
654
|
+
},
|
|
655
|
+
// Ensure devtools dependencies are optimized
|
|
656
|
+
config(e) {
|
|
657
|
+
return {
|
|
658
|
+
optimizeDeps: {
|
|
659
|
+
include: [...e.optimizeDeps?.include || [], "react", "react-dom"]
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
export {
|
|
666
|
+
c as concaveDevTools,
|
|
667
|
+
c as default
|
|
668
|
+
};
|