@mugenlabs/logtape-devtools 0.2.1 → 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 +337 -501
- 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,32 +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]);
|
|
576
|
-
const handleSearchChange =
|
|
521
|
+
const handleSearchChange = useCallback3(
|
|
577
522
|
(e) => {
|
|
578
523
|
const value = e.target.value;
|
|
579
|
-
|
|
524
|
+
setSearch(value);
|
|
580
525
|
debouncedSearch.maybeExecute(value);
|
|
581
526
|
},
|
|
582
527
|
[debouncedSearch]
|
|
583
528
|
);
|
|
584
|
-
|
|
585
|
-
if (searchText === "" && localSearch !== "") {
|
|
586
|
-
setLocalSearch("");
|
|
587
|
-
}
|
|
588
|
-
}, [searchText, localSearch]);
|
|
589
|
-
const handleLevelToggle = useCallback2(
|
|
529
|
+
const handleLevelToggle = useCallback3(
|
|
590
530
|
(level) => {
|
|
591
531
|
const next = new Set(levelFilter);
|
|
592
532
|
if (next.has(level)) {
|
|
@@ -906,7 +846,7 @@ var Toolbar = ({
|
|
|
906
846
|
placeholder: "Search\u2026",
|
|
907
847
|
style: inputStyle,
|
|
908
848
|
type: "text",
|
|
909
|
-
value:
|
|
849
|
+
value: search
|
|
910
850
|
}
|
|
911
851
|
)
|
|
912
852
|
] })
|
|
@@ -917,6 +857,61 @@ var Toolbar = ({
|
|
|
917
857
|
|
|
918
858
|
// src/plugin/logtape-devtools-plugin.tsx
|
|
919
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
|
+
};
|
|
920
915
|
var LogTapeDevtoolsPlugin = ({ store }) => {
|
|
921
916
|
const allRecords = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
922
917
|
const [paused, setPaused] = useState2(false);
|
|
@@ -926,15 +921,15 @@ var LogTapeDevtoolsPlugin = ({ store }) => {
|
|
|
926
921
|
const [searchText, setSearchText] = useState2("");
|
|
927
922
|
const [expandedId, setExpandedId] = useState2(null);
|
|
928
923
|
const [sidebarOpen, setSidebarOpen] = useState2(true);
|
|
929
|
-
const handlePause =
|
|
924
|
+
const handlePause = useCallback4(() => {
|
|
930
925
|
setPaused(true);
|
|
931
926
|
setPausedRecords(store.getSnapshot());
|
|
932
927
|
}, [store]);
|
|
933
|
-
const handleResume =
|
|
928
|
+
const handleResume = useCallback4(() => {
|
|
934
929
|
setPaused(false);
|
|
935
930
|
setPausedRecords([]);
|
|
936
931
|
}, []);
|
|
937
|
-
const handleClear =
|
|
932
|
+
const handleClear = useCallback4(() => {
|
|
938
933
|
store.clear();
|
|
939
934
|
setPausedRecords([]);
|
|
940
935
|
setExpandedId(null);
|
|
@@ -964,158 +959,93 @@ var LogTapeDevtoolsPlugin = ({ store }) => {
|
|
|
964
959
|
return true;
|
|
965
960
|
});
|
|
966
961
|
}, [records, levelFilter, categoryFilter, searchText]);
|
|
967
|
-
return /* @__PURE__ */ jsxs5(
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
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: [
|
|
980
993
|
/* @__PURE__ */ jsx7(
|
|
981
|
-
"
|
|
994
|
+
"button",
|
|
982
995
|
{
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
{
|
|
994
|
-
categories: uniqueCategories,
|
|
995
|
-
categoryFilter,
|
|
996
|
-
filteredCount: filteredRecords.length,
|
|
997
|
-
levelFilter,
|
|
998
|
-
onCategoryFilterChange: setCategoryFilter,
|
|
999
|
-
onClear: handleClear,
|
|
1000
|
-
onLevelFilterChange: setLevelFilter,
|
|
1001
|
-
onPause: handlePause,
|
|
1002
|
-
onResume: handleResume,
|
|
1003
|
-
onSearchTextChange: setSearchText,
|
|
1004
|
-
paused,
|
|
1005
|
-
searchText,
|
|
1006
|
-
totalCount: records.length
|
|
1007
|
-
}
|
|
1008
|
-
)
|
|
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
|
+
] })
|
|
1009
1006
|
}
|
|
1010
1007
|
),
|
|
1011
|
-
/* @__PURE__ */ jsxs5(
|
|
1012
|
-
/* @__PURE__ */
|
|
1013
|
-
|
|
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",
|
|
1014
1012
|
{
|
|
1013
|
+
"data-lt-interactive": "",
|
|
1014
|
+
onClick: paused ? handleResume : handlePause,
|
|
1015
1015
|
style: {
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
flexShrink: 0,
|
|
1020
|
-
gap: theme.spacing.lg,
|
|
1021
|
-
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
|
|
1022
1019
|
},
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
{
|
|
1027
|
-
"aria-expanded": sidebarOpen,
|
|
1028
|
-
"data-lt-clear-btn": "",
|
|
1029
|
-
onClick: () => setSidebarOpen((v) => !v),
|
|
1030
|
-
style: {
|
|
1031
|
-
background: "none",
|
|
1032
|
-
border: "none",
|
|
1033
|
-
color: theme.colors.textMuted,
|
|
1034
|
-
cursor: "pointer",
|
|
1035
|
-
fontFamily: theme.fontFamily.sans,
|
|
1036
|
-
fontSize: theme.fontSize.md,
|
|
1037
|
-
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
|
|
1038
|
-
transition: "color 0.1s"
|
|
1039
|
-
},
|
|
1040
|
-
title: sidebarOpen ? "Collapse sidebar" : "Expand sidebar",
|
|
1041
|
-
type: "button",
|
|
1042
|
-
children: /* @__PURE__ */ jsxs5("span", { style: { alignItems: "center", display: "inline-flex", gap: "6px" }, children: [
|
|
1043
|
-
sidebarOpen ? /* @__PURE__ */ jsx7(PanelLeftCloseIcon, { size: 14 }) : /* @__PURE__ */ jsx7(PanelLeftOpenIcon, { size: 14 }),
|
|
1044
|
-
sidebarOpen ? "Hide controls" : "Show controls"
|
|
1045
|
-
] })
|
|
1046
|
-
}
|
|
1047
|
-
),
|
|
1048
|
-
!sidebarOpen && /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
1049
|
-
/* @__PURE__ */ jsx7(
|
|
1050
|
-
"span",
|
|
1051
|
-
{
|
|
1052
|
-
style: {
|
|
1053
|
-
color: theme.colors.textMuted,
|
|
1054
|
-
fontFamily: theme.fontFamily.mono,
|
|
1055
|
-
fontSize: theme.fontSize.sm
|
|
1056
|
-
},
|
|
1057
|
-
children: filteredRecords.length === records.length ? `${records.length} logs` : `${filteredRecords.length} / ${records.length} logs`
|
|
1058
|
-
}
|
|
1059
|
-
),
|
|
1060
|
-
/* @__PURE__ */ jsx7(
|
|
1061
|
-
"button",
|
|
1062
|
-
{
|
|
1063
|
-
"data-lt-interactive": "",
|
|
1064
|
-
onClick: paused ? handleResume : handlePause,
|
|
1065
|
-
style: {
|
|
1066
|
-
background: paused ? theme.colors.levels.warning.badge : theme.colors.surfaceHover,
|
|
1067
|
-
border: `1px solid ${theme.colors.border}`,
|
|
1068
|
-
borderRadius: theme.radius.sm,
|
|
1069
|
-
color: paused ? theme.colors.white : theme.colors.textPrimary,
|
|
1070
|
-
cursor: "pointer",
|
|
1071
|
-
fontFamily: theme.fontFamily.sans,
|
|
1072
|
-
fontSize: theme.fontSize.sm,
|
|
1073
|
-
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
|
|
1074
|
-
transition: "filter 0.1s"
|
|
1075
|
-
},
|
|
1076
|
-
title: paused ? "Resume" : "Pause",
|
|
1077
|
-
type: "button",
|
|
1078
|
-
children: paused ? /* @__PURE__ */ jsx7(PlayIcon, { size: 12 }) : /* @__PURE__ */ jsx7(PauseIcon, { size: 12 })
|
|
1079
|
-
}
|
|
1080
|
-
),
|
|
1081
|
-
/* @__PURE__ */ jsx7(
|
|
1082
|
-
"button",
|
|
1083
|
-
{
|
|
1084
|
-
"data-lt-interactive": "",
|
|
1085
|
-
onClick: handleClear,
|
|
1086
|
-
style: {
|
|
1087
|
-
background: theme.colors.surfaceHover,
|
|
1088
|
-
border: `1px solid ${theme.colors.border}`,
|
|
1089
|
-
borderRadius: theme.radius.sm,
|
|
1090
|
-
color: theme.colors.textPrimary,
|
|
1091
|
-
cursor: "pointer",
|
|
1092
|
-
fontFamily: theme.fontFamily.sans,
|
|
1093
|
-
fontSize: theme.fontSize.sm,
|
|
1094
|
-
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
|
|
1095
|
-
transition: "filter 0.1s"
|
|
1096
|
-
},
|
|
1097
|
-
title: "Clear",
|
|
1098
|
-
type: "button",
|
|
1099
|
-
children: /* @__PURE__ */ jsx7(Trash2Icon, { size: 12 })
|
|
1100
|
-
}
|
|
1101
|
-
)
|
|
1102
|
-
] })
|
|
1103
|
-
]
|
|
1020
|
+
title: paused ? "Resume" : "Pause",
|
|
1021
|
+
type: "button",
|
|
1022
|
+
children: paused ? /* @__PURE__ */ jsx7(PlayIcon, { size: 12 }) : /* @__PURE__ */ jsx7(PauseIcon, { size: 12 })
|
|
1104
1023
|
}
|
|
1105
1024
|
),
|
|
1106
1025
|
/* @__PURE__ */ jsx7(
|
|
1107
|
-
|
|
1026
|
+
"button",
|
|
1108
1027
|
{
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1028
|
+
"data-lt-interactive": "",
|
|
1029
|
+
onClick: handleClear,
|
|
1030
|
+
style: compactButtonStyle,
|
|
1031
|
+
title: "Clear",
|
|
1032
|
+
type: "button",
|
|
1033
|
+
children: /* @__PURE__ */ jsx7(Trash2Icon, { size: 12 })
|
|
1113
1034
|
}
|
|
1114
1035
|
)
|
|
1115
1036
|
] })
|
|
1116
|
-
]
|
|
1117
|
-
|
|
1118
|
-
|
|
1037
|
+
] }),
|
|
1038
|
+
/* @__PURE__ */ jsx7(
|
|
1039
|
+
LogList,
|
|
1040
|
+
{
|
|
1041
|
+
autoScroll: !paused,
|
|
1042
|
+
expandedId,
|
|
1043
|
+
onToggle: setExpandedId,
|
|
1044
|
+
records: filteredRecords
|
|
1045
|
+
}
|
|
1046
|
+
)
|
|
1047
|
+
] })
|
|
1048
|
+
] });
|
|
1119
1049
|
};
|
|
1120
1050
|
|
|
1121
1051
|
// src/plugin/create-logtape-devtools-plugin.tsx
|
|
@@ -1127,113 +1057,19 @@ var createLogTapeDevtoolsPlugin = (options) => ({
|
|
|
1127
1057
|
render: /* @__PURE__ */ jsx8(LogTapeDevtoolsPlugin, { store: options?.store ?? defaultLogStore })
|
|
1128
1058
|
});
|
|
1129
1059
|
|
|
1130
|
-
// src/
|
|
1131
|
-
function
|
|
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, id) {
|
|
1188
|
-
const normalized = {
|
|
1189
|
-
id,
|
|
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
|
-
let counter = 0;
|
|
1220
|
-
return (record) => {
|
|
1221
|
-
try {
|
|
1222
|
-
const normalized = normalizeRecord(
|
|
1223
|
-
record,
|
|
1224
|
-
captureStack,
|
|
1225
|
-
`log-${sinkId}-${++counter}-${record.timestamp}`
|
|
1226
|
-
);
|
|
1227
|
-
store.addRecord(normalized);
|
|
1228
|
-
} catch {
|
|
1229
|
-
}
|
|
1063
|
+
return {
|
|
1064
|
+
plugin: createLogTapeDevtoolsPlugin({ ...options?.plugin, store }),
|
|
1065
|
+
sink: createDevtoolsSink({ ...options?.sink, store })
|
|
1230
1066
|
};
|
|
1231
1067
|
}
|
|
1232
1068
|
export {
|
|
1233
1069
|
LOG_LEVELS,
|
|
1234
|
-
LogTapeDevtoolsPlugin,
|
|
1235
1070
|
createDevtoolsSink,
|
|
1236
1071
|
createLogStore,
|
|
1072
|
+
createLogTapeDevtools,
|
|
1237
1073
|
createLogTapeDevtoolsPlugin,
|
|
1238
1074
|
defaultLogStore
|
|
1239
1075
|
};
|