@mugenlabs/logtape-devtools 0.2.0 → 0.3.0
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 +189 -20
- package/assets/panel.png +0 -0
- package/dist/chunk-CYXOBB6A.mjs +247 -0
- package/dist/chunk-CYXOBB6A.mjs.map +1 -0
- package/dist/index.d.ts +38 -67
- package/dist/index.mjs +338 -496
- package/dist/index.mjs.map +1 -1
- package/dist/sink.d.ts +130 -0
- package/dist/sink.mjs +13 -0
- package/dist/sink.mjs.map +1 -0
- package/package.json +23 -5
package/dist/index.mjs
CHANGED
|
@@ -1,48 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
listener();
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
return {
|
|
12
|
-
getSnapshot: () => records,
|
|
13
|
-
addRecord: (record) => {
|
|
14
|
-
records = [...records, record];
|
|
15
|
-
if (records.length > max) {
|
|
16
|
-
records = records.slice(records.length - max);
|
|
17
|
-
}
|
|
18
|
-
notify();
|
|
19
|
-
},
|
|
20
|
-
clear: () => {
|
|
21
|
-
records = [];
|
|
22
|
-
notify();
|
|
23
|
-
},
|
|
24
|
-
subscribe: (listener) => {
|
|
25
|
-
listeners.add(listener);
|
|
26
|
-
return () => {
|
|
27
|
-
listeners.delete(listener);
|
|
28
|
-
};
|
|
29
|
-
},
|
|
30
|
-
setMaxSize: (size) => {
|
|
31
|
-
max = size;
|
|
32
|
-
if (records.length > max) {
|
|
33
|
-
records = records.slice(records.length - max);
|
|
34
|
-
notify();
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
var defaultLogStore = createLogStore();
|
|
1
|
+
import {
|
|
2
|
+
LOG_LEVELS,
|
|
3
|
+
createDevtoolsSink,
|
|
4
|
+
createLogStore,
|
|
5
|
+
defaultLogStore,
|
|
6
|
+
safeStringify
|
|
7
|
+
} from "./chunk-CYXOBB6A.mjs";
|
|
40
8
|
|
|
41
9
|
// src/plugin/logtape-devtools-plugin.tsx
|
|
42
|
-
import { useCallback as
|
|
10
|
+
import { useCallback as useCallback4, useMemo as useMemo2, useState as useState2, useSyncExternalStore } from "react";
|
|
43
11
|
|
|
44
12
|
// src/plugin/components/log-list.tsx
|
|
45
|
-
import {
|
|
13
|
+
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
14
|
+
import { useCallback as useCallback2, useEffect, useRef } from "react";
|
|
46
15
|
|
|
47
16
|
// src/plugin/theme.ts
|
|
48
17
|
var theme = {
|
|
@@ -102,6 +71,17 @@ var theme = {
|
|
|
102
71
|
// src/plugin/components/log-row.tsx
|
|
103
72
|
import { useCallback } from "react";
|
|
104
73
|
|
|
74
|
+
// src/plugin/format.ts
|
|
75
|
+
function formatTime(ts) {
|
|
76
|
+
const d = new Date(ts);
|
|
77
|
+
return d.toLocaleTimeString(void 0, {
|
|
78
|
+
hour12: false,
|
|
79
|
+
hour: "2-digit",
|
|
80
|
+
minute: "2-digit",
|
|
81
|
+
second: "2-digit"
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
105
85
|
// src/plugin/icons.tsx
|
|
106
86
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
107
87
|
var defaults = { size: 14, color: "currentColor" };
|
|
@@ -192,91 +172,120 @@ var LevelBadge = ({ level }) => {
|
|
|
192
172
|
|
|
193
173
|
// src/plugin/components/log-detail.tsx
|
|
194
174
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
var
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
175
|
+
var detailRowStyle = {
|
|
176
|
+
display: "flex",
|
|
177
|
+
gap: theme.spacing.lg,
|
|
178
|
+
marginBottom: theme.spacing.md
|
|
179
|
+
};
|
|
180
|
+
var detailLabelStyle = {
|
|
181
|
+
color: theme.colors.textMuted,
|
|
182
|
+
flexShrink: 0,
|
|
183
|
+
fontSize: theme.fontSize.md,
|
|
184
|
+
minWidth: "72px",
|
|
185
|
+
textAlign: "right"
|
|
186
|
+
};
|
|
187
|
+
var detailValueStyle = {
|
|
188
|
+
fontSize: theme.fontSize.base,
|
|
189
|
+
wordBreak: "break-all"
|
|
190
|
+
};
|
|
191
|
+
var containerStyle = {
|
|
192
|
+
borderTop: `1px solid ${theme.colors.border}`,
|
|
193
|
+
padding: `${theme.spacing.lg} ${theme.spacing.xl}`
|
|
194
|
+
};
|
|
195
|
+
var categoryStyle = {
|
|
196
|
+
color: theme.colors.accent,
|
|
197
|
+
fontFamily: theme.fontFamily.mono
|
|
198
|
+
};
|
|
199
|
+
var callerStyle = {
|
|
200
|
+
color: theme.colors.textSecondary,
|
|
201
|
+
fontFamily: theme.fontFamily.mono
|
|
202
|
+
};
|
|
203
|
+
var messageStyle = { color: theme.colors.textPrimary };
|
|
204
|
+
var propertiesStyle = {
|
|
205
|
+
background: "rgba(0,0,0,0.3)",
|
|
206
|
+
borderRadius: theme.radius.md,
|
|
207
|
+
color: theme.colors.textPrimary,
|
|
208
|
+
fontFamily: theme.fontFamily.mono,
|
|
209
|
+
fontSize: theme.fontSize.md,
|
|
210
|
+
margin: 0,
|
|
211
|
+
maxHeight: "200px",
|
|
212
|
+
overflow: "auto",
|
|
213
|
+
padding: theme.spacing.lg,
|
|
214
|
+
whiteSpace: "pre-wrap",
|
|
215
|
+
wordBreak: "break-all"
|
|
216
|
+
};
|
|
217
|
+
var DetailRow = ({ label, children }) => /* @__PURE__ */ jsxs2("div", { style: detailRowStyle, children: [
|
|
218
|
+
/* @__PURE__ */ jsx3("span", { style: detailLabelStyle, children: label }),
|
|
219
|
+
/* @__PURE__ */ jsx3("span", { style: detailValueStyle, children })
|
|
226
220
|
] });
|
|
227
221
|
var LogDetail = ({ record }) => {
|
|
228
222
|
const levelColors = theme.colors.levels[record.level];
|
|
229
223
|
const hasProperties = Object.keys(record.properties).length > 0;
|
|
230
|
-
return /* @__PURE__ */ jsxs2(
|
|
231
|
-
"
|
|
232
|
-
{
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
},
|
|
239
|
-
children: [
|
|
240
|
-
/* @__PURE__ */ jsx3(DetailRow, { label: "Time", children: formatTimestamp(record.timestamp) }),
|
|
241
|
-
/* @__PURE__ */ jsx3(DetailRow, { label: "Level", children: /* @__PURE__ */ jsx3("span", { style: { color: levelColors.color, fontWeight: 600 }, children: record.level }) }),
|
|
242
|
-
/* @__PURE__ */ jsx3(DetailRow, { label: "Category", children: /* @__PURE__ */ jsx3("span", { style: { color: theme.colors.accent, fontFamily: theme.fontFamily.mono }, children: record.category.join(".") }) }),
|
|
243
|
-
record.caller && /* @__PURE__ */ jsx3(DetailRow, { label: "Caller", children: /* @__PURE__ */ jsx3("span", { style: { color: theme.colors.textSecondary, fontFamily: theme.fontFamily.mono }, children: record.caller }) }),
|
|
244
|
-
/* @__PURE__ */ jsx3(DetailRow, { label: "Message", children: /* @__PURE__ */ jsx3("span", { style: { color: theme.colors.textPrimary }, children: record.messageText }) }),
|
|
245
|
-
hasProperties && /* @__PURE__ */ jsx3(DetailRow, { label: "Data", children: /* @__PURE__ */ jsx3(
|
|
246
|
-
"pre",
|
|
247
|
-
{
|
|
248
|
-
style: {
|
|
249
|
-
background: "rgba(0,0,0,0.3)",
|
|
250
|
-
borderRadius: theme.radius.md,
|
|
251
|
-
color: theme.colors.textPrimary,
|
|
252
|
-
fontFamily: theme.fontFamily.mono,
|
|
253
|
-
fontSize: theme.fontSize.md,
|
|
254
|
-
margin: 0,
|
|
255
|
-
maxHeight: "200px",
|
|
256
|
-
overflow: "auto",
|
|
257
|
-
padding: theme.spacing.lg,
|
|
258
|
-
whiteSpace: "pre-wrap",
|
|
259
|
-
wordBreak: "break-all"
|
|
260
|
-
},
|
|
261
|
-
children: safeStringify(record.properties)
|
|
262
|
-
}
|
|
263
|
-
) })
|
|
264
|
-
]
|
|
265
|
-
}
|
|
266
|
-
);
|
|
224
|
+
return /* @__PURE__ */ jsxs2("div", { "data-testid": "log-detail", style: { ...containerStyle, background: levelColors.bg }, children: [
|
|
225
|
+
/* @__PURE__ */ jsx3(DetailRow, { label: "Time", children: formatTime(record.timestamp) }),
|
|
226
|
+
/* @__PURE__ */ jsx3(DetailRow, { label: "Level", children: /* @__PURE__ */ jsx3("span", { style: { color: levelColors.color, fontWeight: 600 }, children: record.level }) }),
|
|
227
|
+
/* @__PURE__ */ jsx3(DetailRow, { label: "Category", children: /* @__PURE__ */ jsx3("span", { style: categoryStyle, children: record.category.join(".") }) }),
|
|
228
|
+
record.caller && /* @__PURE__ */ jsx3(DetailRow, { label: "Caller", children: /* @__PURE__ */ jsx3("span", { style: callerStyle, children: record.caller }) }),
|
|
229
|
+
/* @__PURE__ */ jsx3(DetailRow, { label: "Message", children: /* @__PURE__ */ jsx3("span", { style: messageStyle, children: record.messageText }) }),
|
|
230
|
+
hasProperties && /* @__PURE__ */ jsx3(DetailRow, { label: "Data", children: /* @__PURE__ */ jsx3("pre", { style: propertiesStyle, children: safeStringify(record.properties, 2) }) })
|
|
231
|
+
] });
|
|
267
232
|
};
|
|
268
233
|
|
|
269
234
|
// src/plugin/components/log-row.tsx
|
|
270
235
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
|
|
236
|
+
var rowStyle = {
|
|
237
|
+
alignItems: "center",
|
|
238
|
+
border: "none",
|
|
239
|
+
borderBottom: `1px solid ${theme.colors.border}`,
|
|
240
|
+
cursor: "pointer",
|
|
241
|
+
display: "flex",
|
|
242
|
+
gap: theme.spacing.lg,
|
|
243
|
+
padding: `${theme.spacing.md} ${theme.spacing.xl}`,
|
|
244
|
+
textAlign: "left",
|
|
245
|
+
transition: "background 0.1s, filter 0.1s",
|
|
246
|
+
width: "100%"
|
|
247
|
+
};
|
|
248
|
+
var timestampStyle = {
|
|
249
|
+
color: theme.colors.textDimmed,
|
|
250
|
+
flexShrink: 0,
|
|
251
|
+
fontFamily: theme.fontFamily.mono,
|
|
252
|
+
fontSize: theme.fontSize.md
|
|
253
|
+
};
|
|
254
|
+
var categoryStyle2 = {
|
|
255
|
+
color: theme.colors.accent,
|
|
256
|
+
flexShrink: 0,
|
|
257
|
+
fontFamily: theme.fontFamily.mono,
|
|
258
|
+
fontSize: theme.fontSize.md,
|
|
259
|
+
maxWidth: "180px",
|
|
260
|
+
overflow: "hidden",
|
|
261
|
+
textOverflow: "ellipsis",
|
|
262
|
+
whiteSpace: "nowrap"
|
|
263
|
+
};
|
|
264
|
+
var messageStyle2 = {
|
|
265
|
+
color: theme.colors.textPrimary,
|
|
266
|
+
flex: 1,
|
|
267
|
+
fontSize: theme.fontSize.base,
|
|
268
|
+
overflow: "hidden",
|
|
269
|
+
textOverflow: "ellipsis",
|
|
270
|
+
whiteSpace: "nowrap"
|
|
271
|
+
};
|
|
272
|
+
var callerStyle2 = {
|
|
273
|
+
color: theme.colors.textDimmed,
|
|
274
|
+
flexShrink: 0,
|
|
275
|
+
fontFamily: theme.fontFamily.mono,
|
|
276
|
+
fontSize: theme.fontSize.sm,
|
|
277
|
+
maxWidth: "200px",
|
|
278
|
+
opacity: 0.7,
|
|
279
|
+
overflow: "hidden",
|
|
280
|
+
textOverflow: "ellipsis",
|
|
281
|
+
whiteSpace: "nowrap"
|
|
282
|
+
};
|
|
283
|
+
var chevronStyle = {
|
|
284
|
+
color: theme.colors.textDimmed,
|
|
285
|
+
display: "flex",
|
|
286
|
+
flexShrink: 0,
|
|
287
|
+
transition: "transform 0.15s"
|
|
288
|
+
};
|
|
280
289
|
var LogRow = ({ record, expanded, onToggle }) => {
|
|
281
290
|
const levelColors = theme.colors.levels[record.level];
|
|
282
291
|
const handleClick = useCallback(() => {
|
|
@@ -290,94 +299,15 @@ var LogRow = ({ record, expanded, onToggle }) => {
|
|
|
290
299
|
"data-lt-interactive": "",
|
|
291
300
|
"data-testid": "log-row",
|
|
292
301
|
onClick: handleClick,
|
|
293
|
-
style: {
|
|
294
|
-
alignItems: "center",
|
|
295
|
-
background: expanded ? levelColors.bg : "transparent",
|
|
296
|
-
border: "none",
|
|
297
|
-
borderBottom: `1px solid ${theme.colors.border}`,
|
|
298
|
-
cursor: "pointer",
|
|
299
|
-
display: "flex",
|
|
300
|
-
gap: theme.spacing.lg,
|
|
301
|
-
padding: `${theme.spacing.md} ${theme.spacing.xl}`,
|
|
302
|
-
textAlign: "left",
|
|
303
|
-
transition: "background 0.1s, filter 0.1s",
|
|
304
|
-
width: "100%"
|
|
305
|
-
},
|
|
302
|
+
style: { ...rowStyle, background: expanded ? levelColors.bg : "transparent" },
|
|
306
303
|
type: "button",
|
|
307
304
|
children: [
|
|
308
|
-
/* @__PURE__ */ jsx4(
|
|
309
|
-
"span",
|
|
310
|
-
{
|
|
311
|
-
style: {
|
|
312
|
-
color: theme.colors.textDimmed,
|
|
313
|
-
flexShrink: 0,
|
|
314
|
-
fontFamily: theme.fontFamily.mono,
|
|
315
|
-
fontSize: theme.fontSize.md
|
|
316
|
-
},
|
|
317
|
-
children: formatTime(record.timestamp)
|
|
318
|
-
}
|
|
319
|
-
),
|
|
305
|
+
/* @__PURE__ */ jsx4("span", { style: timestampStyle, children: formatTime(record.timestamp) }),
|
|
320
306
|
/* @__PURE__ */ jsx4(LevelBadge, { level: record.level }),
|
|
321
|
-
/* @__PURE__ */ jsx4(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
color: theme.colors.accent,
|
|
326
|
-
flexShrink: 0,
|
|
327
|
-
fontFamily: theme.fontFamily.mono,
|
|
328
|
-
fontSize: theme.fontSize.md,
|
|
329
|
-
maxWidth: "180px",
|
|
330
|
-
overflow: "hidden",
|
|
331
|
-
textOverflow: "ellipsis",
|
|
332
|
-
whiteSpace: "nowrap"
|
|
333
|
-
},
|
|
334
|
-
children: record.category.join(".")
|
|
335
|
-
}
|
|
336
|
-
),
|
|
337
|
-
/* @__PURE__ */ jsx4(
|
|
338
|
-
"span",
|
|
339
|
-
{
|
|
340
|
-
style: {
|
|
341
|
-
color: theme.colors.textPrimary,
|
|
342
|
-
flex: 1,
|
|
343
|
-
fontSize: theme.fontSize.base,
|
|
344
|
-
overflow: "hidden",
|
|
345
|
-
textOverflow: "ellipsis",
|
|
346
|
-
whiteSpace: "nowrap"
|
|
347
|
-
},
|
|
348
|
-
children: record.messageText
|
|
349
|
-
}
|
|
350
|
-
),
|
|
351
|
-
record.caller && /* @__PURE__ */ jsx4(
|
|
352
|
-
"span",
|
|
353
|
-
{
|
|
354
|
-
style: {
|
|
355
|
-
color: theme.colors.textDimmed,
|
|
356
|
-
flexShrink: 0,
|
|
357
|
-
fontFamily: theme.fontFamily.mono,
|
|
358
|
-
fontSize: theme.fontSize.sm,
|
|
359
|
-
maxWidth: "200px",
|
|
360
|
-
opacity: 0.7,
|
|
361
|
-
overflow: "hidden",
|
|
362
|
-
textOverflow: "ellipsis",
|
|
363
|
-
whiteSpace: "nowrap"
|
|
364
|
-
},
|
|
365
|
-
children: record.caller
|
|
366
|
-
}
|
|
367
|
-
),
|
|
368
|
-
/* @__PURE__ */ jsx4(
|
|
369
|
-
"span",
|
|
370
|
-
{
|
|
371
|
-
style: {
|
|
372
|
-
color: theme.colors.textDimmed,
|
|
373
|
-
display: "flex",
|
|
374
|
-
flexShrink: 0,
|
|
375
|
-
transform: expanded ? "rotate(90deg)" : "rotate(0deg)",
|
|
376
|
-
transition: "transform 0.15s"
|
|
377
|
-
},
|
|
378
|
-
children: /* @__PURE__ */ jsx4(ChevronRightIcon, { size: 12 })
|
|
379
|
-
}
|
|
380
|
-
)
|
|
307
|
+
/* @__PURE__ */ jsx4("span", { style: categoryStyle2, children: record.category.join(".") }),
|
|
308
|
+
/* @__PURE__ */ jsx4("span", { style: messageStyle2, children: record.messageText }),
|
|
309
|
+
record.caller && /* @__PURE__ */ jsx4("span", { style: callerStyle2, children: record.caller }),
|
|
310
|
+
/* @__PURE__ */ jsx4("span", { style: { ...chevronStyle, transform: expanded ? "rotate(90deg)" : "rotate(0deg)" }, children: /* @__PURE__ */ jsx4(ChevronRightIcon, { size: 12 }) })
|
|
381
311
|
]
|
|
382
312
|
}
|
|
383
313
|
),
|
|
@@ -387,76 +317,92 @@ var LogRow = ({ record, expanded, onToggle }) => {
|
|
|
387
317
|
|
|
388
318
|
// src/plugin/components/log-list.tsx
|
|
389
319
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
320
|
+
var ESTIMATED_ROW_HEIGHT = 28;
|
|
321
|
+
var OVERSCAN = 10;
|
|
322
|
+
var STICK_THRESHOLD = 40;
|
|
323
|
+
var emptyStyle = {
|
|
324
|
+
alignItems: "center",
|
|
325
|
+
color: theme.colors.textMuted,
|
|
326
|
+
display: "flex",
|
|
327
|
+
flex: 1,
|
|
328
|
+
fontSize: theme.fontSize.lg,
|
|
329
|
+
justifyContent: "center"
|
|
330
|
+
};
|
|
331
|
+
var containerStyle2 = {
|
|
332
|
+
flex: 1,
|
|
333
|
+
overflow: "auto",
|
|
334
|
+
scrollbarColor: `${theme.colors.scrollbar} transparent`,
|
|
335
|
+
scrollbarWidth: "thin"
|
|
336
|
+
};
|
|
390
337
|
var LogList = ({ records, expandedId, onToggle, autoScroll }) => {
|
|
391
338
|
const containerRef = useRef(null);
|
|
392
339
|
const isAtBottomRef = useRef(true);
|
|
340
|
+
const virtualizer = useVirtualizer({
|
|
341
|
+
count: records.length,
|
|
342
|
+
estimateSize: () => ESTIMATED_ROW_HEIGHT,
|
|
343
|
+
getItemKey: (index) => records[index].id,
|
|
344
|
+
getScrollElement: () => containerRef.current,
|
|
345
|
+
overscan: OVERSCAN
|
|
346
|
+
});
|
|
393
347
|
const recordCount = records.length;
|
|
394
348
|
useEffect(() => {
|
|
395
|
-
|
|
396
|
-
if (!(el && autoScroll && isAtBottomRef.current)) {
|
|
349
|
+
if (recordCount === 0 || !(autoScroll && isAtBottomRef.current)) {
|
|
397
350
|
return;
|
|
398
351
|
}
|
|
399
|
-
|
|
400
|
-
}, [autoScroll, recordCount]);
|
|
401
|
-
const handleScroll = () => {
|
|
352
|
+
virtualizer.scrollToIndex(recordCount - 1, { align: "end" });
|
|
353
|
+
}, [autoScroll, recordCount, virtualizer]);
|
|
354
|
+
const handleScroll = useCallback2(() => {
|
|
402
355
|
const el = containerRef.current;
|
|
403
356
|
if (!el) {
|
|
404
357
|
return;
|
|
405
358
|
}
|
|
406
|
-
isAtBottomRef.current = el.scrollHeight - el.scrollTop - el.clientHeight <
|
|
407
|
-
};
|
|
359
|
+
isAtBottomRef.current = el.scrollHeight - el.scrollTop - el.clientHeight < STICK_THRESHOLD;
|
|
360
|
+
}, []);
|
|
408
361
|
if (records.length === 0) {
|
|
409
|
-
return /* @__PURE__ */ jsx5(
|
|
410
|
-
"div",
|
|
411
|
-
{
|
|
412
|
-
"data-testid": "log-list-empty",
|
|
413
|
-
style: {
|
|
414
|
-
alignItems: "center",
|
|
415
|
-
color: theme.colors.textMuted,
|
|
416
|
-
display: "flex",
|
|
417
|
-
flex: 1,
|
|
418
|
-
fontSize: theme.fontSize.lg,
|
|
419
|
-
justifyContent: "center"
|
|
420
|
-
},
|
|
421
|
-
children: "No logs yet"
|
|
422
|
-
}
|
|
423
|
-
);
|
|
362
|
+
return /* @__PURE__ */ jsx5("div", { "data-testid": "log-list-empty", style: emptyStyle, children: "No logs yet" });
|
|
424
363
|
}
|
|
425
|
-
|
|
364
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
365
|
+
return /* @__PURE__ */ jsx5("div", { "data-testid": "log-list", onScroll: handleScroll, ref: containerRef, style: containerStyle2, children: /* @__PURE__ */ jsx5(
|
|
426
366
|
"div",
|
|
427
367
|
{
|
|
428
|
-
"data-testid": "log-list",
|
|
429
|
-
onScroll: handleScroll,
|
|
430
|
-
ref: containerRef,
|
|
431
368
|
style: {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
scrollbarWidth: "thin"
|
|
369
|
+
height: `${virtualizer.getTotalSize()}px`,
|
|
370
|
+
position: "relative",
|
|
371
|
+
width: "100%"
|
|
436
372
|
},
|
|
437
|
-
children:
|
|
438
|
-
|
|
373
|
+
children: /* @__PURE__ */ jsx5(
|
|
374
|
+
"div",
|
|
439
375
|
{
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
376
|
+
style: {
|
|
377
|
+
left: 0,
|
|
378
|
+
position: "absolute",
|
|
379
|
+
top: 0,
|
|
380
|
+
transform: `translateY(${virtualItems[0]?.start ?? 0}px)`,
|
|
381
|
+
width: "100%"
|
|
382
|
+
},
|
|
383
|
+
children: virtualItems.map((virtualItem) => {
|
|
384
|
+
const record = records[virtualItem.index];
|
|
385
|
+
return /* @__PURE__ */ jsx5(
|
|
386
|
+
"div",
|
|
387
|
+
{
|
|
388
|
+
"data-index": virtualItem.index,
|
|
389
|
+
ref: virtualizer.measureElement,
|
|
390
|
+
children: /* @__PURE__ */ jsx5(LogRow, { expanded: expandedId === record.id, onToggle, record })
|
|
391
|
+
},
|
|
392
|
+
virtualItem.key
|
|
393
|
+
);
|
|
394
|
+
})
|
|
395
|
+
}
|
|
396
|
+
)
|
|
446
397
|
}
|
|
447
|
-
);
|
|
398
|
+
) });
|
|
448
399
|
};
|
|
449
400
|
|
|
450
401
|
// src/plugin/components/toolbar.tsx
|
|
451
402
|
import { Combobox } from "@base-ui-components/react/combobox";
|
|
452
403
|
import { Popover } from "@base-ui-components/react/popover";
|
|
453
404
|
import { Debouncer } from "@tanstack/pacer";
|
|
454
|
-
import { useCallback as
|
|
455
|
-
|
|
456
|
-
// src/types.ts
|
|
457
|
-
var LOG_LEVELS = ["trace", "debug", "info", "warning", "error", "fatal"];
|
|
458
|
-
|
|
459
|
-
// src/plugin/components/toolbar.tsx
|
|
405
|
+
import { useCallback as useCallback3, useEffect as useEffect2, useMemo, useState } from "react";
|
|
460
406
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
461
407
|
var HOVER_STYLE_ID = "logtape-devtools-hover";
|
|
462
408
|
function useHoverStyles() {
|
|
@@ -521,7 +467,7 @@ var LevelToggle = ({
|
|
|
521
467
|
onToggle
|
|
522
468
|
}) => {
|
|
523
469
|
const colors = theme.colors.levels[level];
|
|
524
|
-
const handleClick =
|
|
470
|
+
const handleClick = useCallback3(() => onToggle(level), [level, onToggle]);
|
|
525
471
|
return /* @__PURE__ */ jsx6(
|
|
526
472
|
"button",
|
|
527
473
|
{
|
|
@@ -561,31 +507,26 @@ var Toolbar = ({
|
|
|
561
507
|
categories,
|
|
562
508
|
categoryFilter,
|
|
563
509
|
onCategoryFilterChange,
|
|
564
|
-
searchText,
|
|
565
510
|
onSearchTextChange,
|
|
566
511
|
totalCount,
|
|
567
512
|
filteredCount
|
|
568
513
|
}) => {
|
|
569
514
|
useHoverStyles();
|
|
570
|
-
const [
|
|
515
|
+
const [search, setSearch] = useState("");
|
|
571
516
|
const debouncedSearch = useMemo(
|
|
572
517
|
() => new Debouncer(onSearchTextChange, { wait: 200 }),
|
|
573
518
|
[onSearchTextChange]
|
|
574
519
|
);
|
|
575
|
-
|
|
520
|
+
useEffect2(() => () => debouncedSearch.cancel(), [debouncedSearch]);
|
|
521
|
+
const handleSearchChange = useCallback3(
|
|
576
522
|
(e) => {
|
|
577
523
|
const value = e.target.value;
|
|
578
|
-
|
|
524
|
+
setSearch(value);
|
|
579
525
|
debouncedSearch.maybeExecute(value);
|
|
580
526
|
},
|
|
581
527
|
[debouncedSearch]
|
|
582
528
|
);
|
|
583
|
-
|
|
584
|
-
if (searchText === "" && localSearch !== "") {
|
|
585
|
-
setLocalSearch("");
|
|
586
|
-
}
|
|
587
|
-
}, [searchText, localSearch]);
|
|
588
|
-
const handleLevelToggle = useCallback2(
|
|
529
|
+
const handleLevelToggle = useCallback3(
|
|
589
530
|
(level) => {
|
|
590
531
|
const next = new Set(levelFilter);
|
|
591
532
|
if (next.has(level)) {
|
|
@@ -905,7 +846,7 @@ var Toolbar = ({
|
|
|
905
846
|
placeholder: "Search\u2026",
|
|
906
847
|
style: inputStyle,
|
|
907
848
|
type: "text",
|
|
908
|
-
value:
|
|
849
|
+
value: search
|
|
909
850
|
}
|
|
910
851
|
)
|
|
911
852
|
] })
|
|
@@ -916,6 +857,61 @@ var Toolbar = ({
|
|
|
916
857
|
|
|
917
858
|
// src/plugin/logtape-devtools-plugin.tsx
|
|
918
859
|
import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
860
|
+
var rootStyle = {
|
|
861
|
+
background: theme.colors.background,
|
|
862
|
+
color: theme.colors.textPrimary,
|
|
863
|
+
display: "flex",
|
|
864
|
+
flexDirection: "row",
|
|
865
|
+
fontFamily: theme.fontFamily.sans,
|
|
866
|
+
height: "100%",
|
|
867
|
+
overflow: "hidden"
|
|
868
|
+
};
|
|
869
|
+
var sidebarStyle = {
|
|
870
|
+
flexShrink: 0,
|
|
871
|
+
overflow: "hidden",
|
|
872
|
+
transition: "width 0.2s ease, opacity 0.15s ease"
|
|
873
|
+
};
|
|
874
|
+
var mainStyle = {
|
|
875
|
+
display: "flex",
|
|
876
|
+
flex: 1,
|
|
877
|
+
flexDirection: "column",
|
|
878
|
+
overflow: "hidden"
|
|
879
|
+
};
|
|
880
|
+
var topBarStyle = {
|
|
881
|
+
alignItems: "center",
|
|
882
|
+
borderBottom: `1px solid ${theme.colors.border}`,
|
|
883
|
+
display: "flex",
|
|
884
|
+
flexShrink: 0,
|
|
885
|
+
gap: theme.spacing.lg,
|
|
886
|
+
padding: `${theme.spacing.sm} ${theme.spacing.lg}`
|
|
887
|
+
};
|
|
888
|
+
var sidebarToggleStyle = {
|
|
889
|
+
background: "none",
|
|
890
|
+
border: "none",
|
|
891
|
+
color: theme.colors.textMuted,
|
|
892
|
+
cursor: "pointer",
|
|
893
|
+
fontFamily: theme.fontFamily.sans,
|
|
894
|
+
fontSize: theme.fontSize.md,
|
|
895
|
+
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
|
|
896
|
+
transition: "color 0.1s"
|
|
897
|
+
};
|
|
898
|
+
var iconLabelStyle = { alignItems: "center", display: "inline-flex", gap: "6px" };
|
|
899
|
+
var countStyle = {
|
|
900
|
+
color: theme.colors.textMuted,
|
|
901
|
+
fontFamily: theme.fontFamily.mono,
|
|
902
|
+
fontSize: theme.fontSize.sm
|
|
903
|
+
};
|
|
904
|
+
var compactButtonStyle = {
|
|
905
|
+
background: theme.colors.surfaceHover,
|
|
906
|
+
border: `1px solid ${theme.colors.border}`,
|
|
907
|
+
borderRadius: theme.radius.sm,
|
|
908
|
+
color: theme.colors.textPrimary,
|
|
909
|
+
cursor: "pointer",
|
|
910
|
+
fontFamily: theme.fontFamily.sans,
|
|
911
|
+
fontSize: theme.fontSize.sm,
|
|
912
|
+
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
|
|
913
|
+
transition: "filter 0.1s"
|
|
914
|
+
};
|
|
919
915
|
var LogTapeDevtoolsPlugin = ({ store }) => {
|
|
920
916
|
const allRecords = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
921
917
|
const [paused, setPaused] = useState2(false);
|
|
@@ -925,15 +921,15 @@ var LogTapeDevtoolsPlugin = ({ store }) => {
|
|
|
925
921
|
const [searchText, setSearchText] = useState2("");
|
|
926
922
|
const [expandedId, setExpandedId] = useState2(null);
|
|
927
923
|
const [sidebarOpen, setSidebarOpen] = useState2(true);
|
|
928
|
-
const handlePause =
|
|
924
|
+
const handlePause = useCallback4(() => {
|
|
929
925
|
setPaused(true);
|
|
930
926
|
setPausedRecords(store.getSnapshot());
|
|
931
927
|
}, [store]);
|
|
932
|
-
const handleResume =
|
|
928
|
+
const handleResume = useCallback4(() => {
|
|
933
929
|
setPaused(false);
|
|
934
930
|
setPausedRecords([]);
|
|
935
931
|
}, []);
|
|
936
|
-
const handleClear =
|
|
932
|
+
const handleClear = useCallback4(() => {
|
|
937
933
|
store.clear();
|
|
938
934
|
setPausedRecords([]);
|
|
939
935
|
setExpandedId(null);
|
|
@@ -963,158 +959,93 @@ var LogTapeDevtoolsPlugin = ({ store }) => {
|
|
|
963
959
|
return true;
|
|
964
960
|
});
|
|
965
961
|
}, [records, levelFilter, categoryFilter, searchText]);
|
|
966
|
-
return /* @__PURE__ */ jsxs5(
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
962
|
+
return /* @__PURE__ */ jsxs5("div", { style: rootStyle, children: [
|
|
963
|
+
/* @__PURE__ */ jsx7(
|
|
964
|
+
"div",
|
|
965
|
+
{
|
|
966
|
+
style: {
|
|
967
|
+
...sidebarStyle,
|
|
968
|
+
borderRight: sidebarOpen ? `1px solid ${theme.colors.border}` : "none",
|
|
969
|
+
opacity: sidebarOpen ? 1 : 0,
|
|
970
|
+
width: sidebarOpen ? "200px" : "0px"
|
|
971
|
+
},
|
|
972
|
+
children: /* @__PURE__ */ jsx7(
|
|
973
|
+
Toolbar,
|
|
974
|
+
{
|
|
975
|
+
categories: uniqueCategories,
|
|
976
|
+
categoryFilter,
|
|
977
|
+
filteredCount: filteredRecords.length,
|
|
978
|
+
levelFilter,
|
|
979
|
+
onCategoryFilterChange: setCategoryFilter,
|
|
980
|
+
onClear: handleClear,
|
|
981
|
+
onLevelFilterChange: setLevelFilter,
|
|
982
|
+
onPause: handlePause,
|
|
983
|
+
onResume: handleResume,
|
|
984
|
+
onSearchTextChange: setSearchText,
|
|
985
|
+
paused,
|
|
986
|
+
totalCount: records.length
|
|
987
|
+
}
|
|
988
|
+
)
|
|
989
|
+
}
|
|
990
|
+
),
|
|
991
|
+
/* @__PURE__ */ jsxs5("div", { style: mainStyle, children: [
|
|
992
|
+
/* @__PURE__ */ jsxs5("div", { style: topBarStyle, children: [
|
|
979
993
|
/* @__PURE__ */ jsx7(
|
|
980
|
-
"
|
|
994
|
+
"button",
|
|
981
995
|
{
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
{
|
|
993
|
-
categories: uniqueCategories,
|
|
994
|
-
categoryFilter,
|
|
995
|
-
filteredCount: filteredRecords.length,
|
|
996
|
-
levelFilter,
|
|
997
|
-
onCategoryFilterChange: setCategoryFilter,
|
|
998
|
-
onClear: handleClear,
|
|
999
|
-
onLevelFilterChange: setLevelFilter,
|
|
1000
|
-
onPause: handlePause,
|
|
1001
|
-
onResume: handleResume,
|
|
1002
|
-
onSearchTextChange: setSearchText,
|
|
1003
|
-
paused,
|
|
1004
|
-
searchText,
|
|
1005
|
-
totalCount: records.length
|
|
1006
|
-
}
|
|
1007
|
-
)
|
|
996
|
+
"aria-expanded": sidebarOpen,
|
|
997
|
+
"data-lt-clear-btn": "",
|
|
998
|
+
onClick: () => setSidebarOpen((v) => !v),
|
|
999
|
+
style: sidebarToggleStyle,
|
|
1000
|
+
title: sidebarOpen ? "Collapse sidebar" : "Expand sidebar",
|
|
1001
|
+
type: "button",
|
|
1002
|
+
children: /* @__PURE__ */ jsxs5("span", { style: iconLabelStyle, children: [
|
|
1003
|
+
sidebarOpen ? /* @__PURE__ */ jsx7(PanelLeftCloseIcon, { size: 14 }) : /* @__PURE__ */ jsx7(PanelLeftOpenIcon, { size: 14 }),
|
|
1004
|
+
sidebarOpen ? "Hide controls" : "Show controls"
|
|
1005
|
+
] })
|
|
1008
1006
|
}
|
|
1009
1007
|
),
|
|
1010
|
-
/* @__PURE__ */ jsxs5(
|
|
1011
|
-
/* @__PURE__ */
|
|
1012
|
-
|
|
1008
|
+
!sidebarOpen && /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
1009
|
+
/* @__PURE__ */ jsx7("span", { style: countStyle, children: filteredRecords.length === records.length ? `${records.length} logs` : `${filteredRecords.length} / ${records.length} logs` }),
|
|
1010
|
+
/* @__PURE__ */ jsx7(
|
|
1011
|
+
"button",
|
|
1013
1012
|
{
|
|
1013
|
+
"data-lt-interactive": "",
|
|
1014
|
+
onClick: paused ? handleResume : handlePause,
|
|
1014
1015
|
style: {
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
flexShrink: 0,
|
|
1019
|
-
gap: theme.spacing.lg,
|
|
1020
|
-
padding: `${theme.spacing.sm} ${theme.spacing.lg}`
|
|
1016
|
+
...compactButtonStyle,
|
|
1017
|
+
background: paused ? theme.colors.levels.warning.badge : compactButtonStyle.background,
|
|
1018
|
+
color: paused ? theme.colors.white : compactButtonStyle.color
|
|
1021
1019
|
},
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
{
|
|
1026
|
-
"aria-expanded": sidebarOpen,
|
|
1027
|
-
"data-lt-clear-btn": "",
|
|
1028
|
-
onClick: () => setSidebarOpen((v) => !v),
|
|
1029
|
-
style: {
|
|
1030
|
-
background: "none",
|
|
1031
|
-
border: "none",
|
|
1032
|
-
color: theme.colors.textMuted,
|
|
1033
|
-
cursor: "pointer",
|
|
1034
|
-
fontFamily: theme.fontFamily.sans,
|
|
1035
|
-
fontSize: theme.fontSize.md,
|
|
1036
|
-
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
|
|
1037
|
-
transition: "color 0.1s"
|
|
1038
|
-
},
|
|
1039
|
-
title: sidebarOpen ? "Collapse sidebar" : "Expand sidebar",
|
|
1040
|
-
type: "button",
|
|
1041
|
-
children: /* @__PURE__ */ jsxs5("span", { style: { alignItems: "center", display: "inline-flex", gap: "6px" }, children: [
|
|
1042
|
-
sidebarOpen ? /* @__PURE__ */ jsx7(PanelLeftCloseIcon, { size: 14 }) : /* @__PURE__ */ jsx7(PanelLeftOpenIcon, { size: 14 }),
|
|
1043
|
-
sidebarOpen ? "Hide controls" : "Show controls"
|
|
1044
|
-
] })
|
|
1045
|
-
}
|
|
1046
|
-
),
|
|
1047
|
-
!sidebarOpen && /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
1048
|
-
/* @__PURE__ */ jsx7(
|
|
1049
|
-
"span",
|
|
1050
|
-
{
|
|
1051
|
-
style: {
|
|
1052
|
-
color: theme.colors.textMuted,
|
|
1053
|
-
fontFamily: theme.fontFamily.mono,
|
|
1054
|
-
fontSize: theme.fontSize.sm
|
|
1055
|
-
},
|
|
1056
|
-
children: filteredRecords.length === records.length ? `${records.length} logs` : `${filteredRecords.length} / ${records.length} logs`
|
|
1057
|
-
}
|
|
1058
|
-
),
|
|
1059
|
-
/* @__PURE__ */ jsx7(
|
|
1060
|
-
"button",
|
|
1061
|
-
{
|
|
1062
|
-
"data-lt-interactive": "",
|
|
1063
|
-
onClick: paused ? handleResume : handlePause,
|
|
1064
|
-
style: {
|
|
1065
|
-
background: paused ? theme.colors.levels.warning.badge : theme.colors.surfaceHover,
|
|
1066
|
-
border: `1px solid ${theme.colors.border}`,
|
|
1067
|
-
borderRadius: theme.radius.sm,
|
|
1068
|
-
color: paused ? theme.colors.white : theme.colors.textPrimary,
|
|
1069
|
-
cursor: "pointer",
|
|
1070
|
-
fontFamily: theme.fontFamily.sans,
|
|
1071
|
-
fontSize: theme.fontSize.sm,
|
|
1072
|
-
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
|
|
1073
|
-
transition: "filter 0.1s"
|
|
1074
|
-
},
|
|
1075
|
-
title: paused ? "Resume" : "Pause",
|
|
1076
|
-
type: "button",
|
|
1077
|
-
children: paused ? /* @__PURE__ */ jsx7(PlayIcon, { size: 12 }) : /* @__PURE__ */ jsx7(PauseIcon, { size: 12 })
|
|
1078
|
-
}
|
|
1079
|
-
),
|
|
1080
|
-
/* @__PURE__ */ jsx7(
|
|
1081
|
-
"button",
|
|
1082
|
-
{
|
|
1083
|
-
"data-lt-interactive": "",
|
|
1084
|
-
onClick: handleClear,
|
|
1085
|
-
style: {
|
|
1086
|
-
background: theme.colors.surfaceHover,
|
|
1087
|
-
border: `1px solid ${theme.colors.border}`,
|
|
1088
|
-
borderRadius: theme.radius.sm,
|
|
1089
|
-
color: theme.colors.textPrimary,
|
|
1090
|
-
cursor: "pointer",
|
|
1091
|
-
fontFamily: theme.fontFamily.sans,
|
|
1092
|
-
fontSize: theme.fontSize.sm,
|
|
1093
|
-
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
|
|
1094
|
-
transition: "filter 0.1s"
|
|
1095
|
-
},
|
|
1096
|
-
title: "Clear",
|
|
1097
|
-
type: "button",
|
|
1098
|
-
children: /* @__PURE__ */ jsx7(Trash2Icon, { size: 12 })
|
|
1099
|
-
}
|
|
1100
|
-
)
|
|
1101
|
-
] })
|
|
1102
|
-
]
|
|
1020
|
+
title: paused ? "Resume" : "Pause",
|
|
1021
|
+
type: "button",
|
|
1022
|
+
children: paused ? /* @__PURE__ */ jsx7(PlayIcon, { size: 12 }) : /* @__PURE__ */ jsx7(PauseIcon, { size: 12 })
|
|
1103
1023
|
}
|
|
1104
1024
|
),
|
|
1105
1025
|
/* @__PURE__ */ jsx7(
|
|
1106
|
-
|
|
1026
|
+
"button",
|
|
1107
1027
|
{
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1028
|
+
"data-lt-interactive": "",
|
|
1029
|
+
onClick: handleClear,
|
|
1030
|
+
style: compactButtonStyle,
|
|
1031
|
+
title: "Clear",
|
|
1032
|
+
type: "button",
|
|
1033
|
+
children: /* @__PURE__ */ jsx7(Trash2Icon, { size: 12 })
|
|
1112
1034
|
}
|
|
1113
1035
|
)
|
|
1114
1036
|
] })
|
|
1115
|
-
]
|
|
1116
|
-
|
|
1117
|
-
|
|
1037
|
+
] }),
|
|
1038
|
+
/* @__PURE__ */ jsx7(
|
|
1039
|
+
LogList,
|
|
1040
|
+
{
|
|
1041
|
+
autoScroll: !paused,
|
|
1042
|
+
expandedId,
|
|
1043
|
+
onToggle: setExpandedId,
|
|
1044
|
+
records: filteredRecords
|
|
1045
|
+
}
|
|
1046
|
+
)
|
|
1047
|
+
] })
|
|
1048
|
+
] });
|
|
1118
1049
|
};
|
|
1119
1050
|
|
|
1120
1051
|
// src/plugin/create-logtape-devtools-plugin.tsx
|
|
@@ -1126,108 +1057,19 @@ var createLogTapeDevtoolsPlugin = (options) => ({
|
|
|
1126
1057
|
render: /* @__PURE__ */ jsx8(LogTapeDevtoolsPlugin, { store: options?.store ?? defaultLogStore })
|
|
1127
1058
|
});
|
|
1128
1059
|
|
|
1129
|
-
// src/
|
|
1130
|
-
|
|
1131
|
-
function renderMessage(message) {
|
|
1132
|
-
return message.map((part) => {
|
|
1133
|
-
if (typeof part === "string") {
|
|
1134
|
-
return part;
|
|
1135
|
-
}
|
|
1136
|
-
if (part === null || part === void 0) {
|
|
1137
|
-
return String(part);
|
|
1138
|
-
}
|
|
1139
|
-
try {
|
|
1140
|
-
return JSON.stringify(part);
|
|
1141
|
-
} catch {
|
|
1142
|
-
return String(part);
|
|
1143
|
-
}
|
|
1144
|
-
}).join("");
|
|
1145
|
-
}
|
|
1146
|
-
function safeCloneProperties(properties) {
|
|
1147
|
-
try {
|
|
1148
|
-
return JSON.parse(JSON.stringify(properties));
|
|
1149
|
-
} catch {
|
|
1150
|
-
const result = {};
|
|
1151
|
-
for (const [key, value] of Object.entries(properties)) {
|
|
1152
|
-
try {
|
|
1153
|
-
result[key] = JSON.parse(JSON.stringify(value));
|
|
1154
|
-
} catch {
|
|
1155
|
-
result[key] = String(value);
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
return result;
|
|
1159
|
-
}
|
|
1160
|
-
}
|
|
1161
|
-
var v8FrameRe = /at\s+(?:.*?\s+\()?(.+?):(\d+):(\d+)\)?$/;
|
|
1162
|
-
var smFrameRe = /(?:^|@)(.+?):(\d+):(\d+)$/;
|
|
1163
|
-
function captureCallerInfo() {
|
|
1164
|
-
const stack = new Error().stack;
|
|
1165
|
-
if (!stack) {
|
|
1166
|
-
return void 0;
|
|
1167
|
-
}
|
|
1168
|
-
const lines = stack.split("\n");
|
|
1169
|
-
for (const line of lines) {
|
|
1170
|
-
const trimmed = line.trim();
|
|
1171
|
-
if (!trimmed || trimmed === "Error") {
|
|
1172
|
-
continue;
|
|
1173
|
-
}
|
|
1174
|
-
if (/logtape/i.test(trimmed)) {
|
|
1175
|
-
continue;
|
|
1176
|
-
}
|
|
1177
|
-
const match = v8FrameRe.exec(trimmed) ?? smFrameRe.exec(trimmed);
|
|
1178
|
-
if (!match) {
|
|
1179
|
-
continue;
|
|
1180
|
-
}
|
|
1181
|
-
const [, filePath, lineNo, colNo] = match;
|
|
1182
|
-
const fileName = filePath.replace(/[?#].*$/, "").split("/").pop() ?? filePath;
|
|
1183
|
-
return `${fileName}:${lineNo}:${colNo}`;
|
|
1184
|
-
}
|
|
1185
|
-
return void 0;
|
|
1186
|
-
}
|
|
1187
|
-
function normalizeRecord(record, captureStack) {
|
|
1188
|
-
const normalized = {
|
|
1189
|
-
id: `log-${++counter}-${record.timestamp}`,
|
|
1190
|
-
timestamp: record.timestamp,
|
|
1191
|
-
level: record.level,
|
|
1192
|
-
category: [...record.category],
|
|
1193
|
-
message: [...record.message],
|
|
1194
|
-
messageText: renderMessage(record.message),
|
|
1195
|
-
properties: safeCloneProperties(record.properties)
|
|
1196
|
-
};
|
|
1197
|
-
if (captureStack) {
|
|
1198
|
-
const caller = captureCallerInfo();
|
|
1199
|
-
if (caller) {
|
|
1200
|
-
normalized.caller = caller;
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
return normalized;
|
|
1204
|
-
}
|
|
1205
|
-
function isProductionEnv() {
|
|
1206
|
-
try {
|
|
1207
|
-
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
|
|
1208
|
-
return true;
|
|
1209
|
-
}
|
|
1210
|
-
} catch {
|
|
1211
|
-
}
|
|
1212
|
-
return false;
|
|
1213
|
-
}
|
|
1214
|
-
function createDevtoolsSink(options) {
|
|
1060
|
+
// src/create-logtape-devtools.ts
|
|
1061
|
+
function createLogTapeDevtools(options) {
|
|
1215
1062
|
const store = options?.store ?? defaultLogStore;
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
try {
|
|
1220
|
-
const normalized = normalizeRecord(record, captureStack);
|
|
1221
|
-
store.addRecord(normalized);
|
|
1222
|
-
} catch {
|
|
1223
|
-
}
|
|
1063
|
+
return {
|
|
1064
|
+
plugin: createLogTapeDevtoolsPlugin({ ...options?.plugin, store }),
|
|
1065
|
+
sink: createDevtoolsSink({ ...options?.sink, store })
|
|
1224
1066
|
};
|
|
1225
1067
|
}
|
|
1226
1068
|
export {
|
|
1227
1069
|
LOG_LEVELS,
|
|
1228
|
-
LogTapeDevtoolsPlugin,
|
|
1229
1070
|
createDevtoolsSink,
|
|
1230
1071
|
createLogStore,
|
|
1072
|
+
createLogTapeDevtools,
|
|
1231
1073
|
createLogTapeDevtoolsPlugin,
|
|
1232
1074
|
defaultLogStore
|
|
1233
1075
|
};
|