@buoy-gg/console 7.0.40 → 7.0.42
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 +11 -65
- package/lib/commonjs/components/ConsoleIcon.js +1 -19
- package/lib/commonjs/components/ConsoleLogList.js +1 -152
- package/lib/commonjs/components/ConsoleModal.js +1 -48
- package/lib/commonjs/components/ConsoleRoot.js +1 -37
- package/lib/commonjs/devtools/ConsoleBody.js +1 -234
- package/lib/commonjs/devtools/ConsoleHeader.js +1 -114
- package/lib/commonjs/devtools/ConsoleMessageRow.js +1 -356
- package/lib/commonjs/devtools/ConsoleValue.js +1 -254
- package/lib/commonjs/devtools/ConsoleView.js +1 -54
- package/lib/commonjs/devtools/consoleFilter.js +1 -125
- package/lib/commonjs/devtools/consoleFormat.js +1 -313
- package/lib/commonjs/devtools/origin.js +1 -191
- package/lib/commonjs/devtools/theme.js +1 -152
- package/lib/commonjs/devtools/useConsoleController.js +1 -82
- package/lib/commonjs/devtools/useConsoleMessages.js +1 -241
- package/lib/commonjs/hooks/useConsoleLogs.js +1 -23
- package/lib/commonjs/index.js +1 -181
- package/lib/commonjs/preset.js +1 -63
- package/lib/commonjs/store/consoleLogStore.js +6 -587
- package/lib/commonjs/store/sanitize.js +1 -83
- package/lib/commonjs/sync/consoleSyncAdapter.js +1 -86
- package/lib/module/components/ConsoleIcon.js +1 -12
- package/lib/module/components/ConsoleLogList.js +1 -147
- package/lib/module/components/ConsoleModal.js +1 -44
- package/lib/module/components/ConsoleRoot.js +1 -33
- package/lib/module/devtools/ConsoleBody.js +1 -229
- package/lib/module/devtools/ConsoleHeader.js +1 -109
- package/lib/module/devtools/ConsoleMessageRow.js +1 -352
- package/lib/module/devtools/ConsoleValue.js +1 -249
- package/lib/module/devtools/ConsoleView.js +1 -49
- package/lib/module/devtools/consoleFilter.js +1 -119
- package/lib/module/devtools/consoleFormat.js +1 -309
- package/lib/module/devtools/origin.js +1 -183
- package/lib/module/devtools/theme.js +1 -143
- package/lib/module/devtools/useConsoleController.js +1 -79
- package/lib/module/devtools/useConsoleMessages.js +1 -238
- package/lib/module/hooks/useConsoleLogs.js +1 -19
- package/lib/module/index.js +1 -52
- package/lib/module/preset.js +1 -61
- package/lib/module/store/consoleLogStore.js +6 -573
- package/lib/module/store/sanitize.js +1 -77
- package/lib/module/sync/consoleSyncAdapter.js +1 -82
- package/lib/web/index.mjs +17 -0
- package/package.json +39 -5
- package/lib/commonjs/components/ConsoleIcon.js.map +0 -1
- package/lib/commonjs/components/ConsoleLogList.js.map +0 -1
- package/lib/commonjs/components/ConsoleModal.js.map +0 -1
- package/lib/commonjs/components/ConsoleRoot.js.map +0 -1
- package/lib/commonjs/devtools/ConsoleBody.js.map +0 -1
- package/lib/commonjs/devtools/ConsoleHeader.js.map +0 -1
- package/lib/commonjs/devtools/ConsoleMessageRow.js.map +0 -1
- package/lib/commonjs/devtools/ConsoleValue.js.map +0 -1
- package/lib/commonjs/devtools/ConsoleView.js.map +0 -1
- package/lib/commonjs/devtools/consoleFilter.js.map +0 -1
- package/lib/commonjs/devtools/consoleFormat.js.map +0 -1
- package/lib/commonjs/devtools/origin.js.map +0 -1
- package/lib/commonjs/devtools/theme.js.map +0 -1
- package/lib/commonjs/devtools/useConsoleController.js.map +0 -1
- package/lib/commonjs/devtools/useConsoleMessages.js.map +0 -1
- package/lib/commonjs/hooks/useConsoleLogs.js.map +0 -1
- package/lib/commonjs/index.js.map +0 -1
- package/lib/commonjs/preset.js.map +0 -1
- package/lib/commonjs/store/consoleLogStore.js.map +0 -1
- package/lib/commonjs/store/sanitize.js.map +0 -1
- package/lib/commonjs/sync/consoleSyncAdapter.js.map +0 -1
- package/lib/module/components/ConsoleIcon.js.map +0 -1
- package/lib/module/components/ConsoleLogList.js.map +0 -1
- package/lib/module/components/ConsoleModal.js.map +0 -1
- package/lib/module/components/ConsoleRoot.js.map +0 -1
- package/lib/module/devtools/ConsoleBody.js.map +0 -1
- package/lib/module/devtools/ConsoleHeader.js.map +0 -1
- package/lib/module/devtools/ConsoleMessageRow.js.map +0 -1
- package/lib/module/devtools/ConsoleValue.js.map +0 -1
- package/lib/module/devtools/ConsoleView.js.map +0 -1
- package/lib/module/devtools/consoleFilter.js.map +0 -1
- package/lib/module/devtools/consoleFormat.js.map +0 -1
- package/lib/module/devtools/origin.js.map +0 -1
- package/lib/module/devtools/theme.js.map +0 -1
- package/lib/module/devtools/useConsoleController.js.map +0 -1
- package/lib/module/devtools/useConsoleMessages.js.map +0 -1
- package/lib/module/hooks/useConsoleLogs.js.map +0 -1
- package/lib/module/index.js.map +0 -1
- package/lib/module/preset.js.map +0 -1
- package/lib/module/store/consoleLogStore.js.map +0 -1
- package/lib/module/store/sanitize.js.map +0 -1
- package/lib/module/sync/consoleSyncAdapter.js.map +0 -1
- package/lib/typescript/components/ConsoleIcon.d.ts.map +0 -1
- package/lib/typescript/components/ConsoleLogList.d.ts.map +0 -1
- package/lib/typescript/components/ConsoleModal.d.ts.map +0 -1
- package/lib/typescript/components/ConsoleRoot.d.ts.map +0 -1
- package/lib/typescript/devtools/ConsoleBody.d.ts.map +0 -1
- package/lib/typescript/devtools/ConsoleHeader.d.ts.map +0 -1
- package/lib/typescript/devtools/ConsoleMessageRow.d.ts.map +0 -1
- package/lib/typescript/devtools/ConsoleValue.d.ts.map +0 -1
- package/lib/typescript/devtools/ConsoleView.d.ts.map +0 -1
- package/lib/typescript/devtools/consoleFilter.d.ts.map +0 -1
- package/lib/typescript/devtools/consoleFormat.d.ts.map +0 -1
- package/lib/typescript/devtools/origin.d.ts.map +0 -1
- package/lib/typescript/devtools/theme.d.ts.map +0 -1
- package/lib/typescript/devtools/useConsoleController.d.ts.map +0 -1
- package/lib/typescript/devtools/useConsoleMessages.d.ts.map +0 -1
- package/lib/typescript/hooks/useConsoleLogs.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- package/lib/typescript/store/consoleLogStore.d.ts.map +0 -1
- package/lib/typescript/store/sanitize.d.ts.map +0 -1
- package/lib/typescript/sync/consoleSyncAdapter.d.ts.map +0 -1
|
@@ -1,79 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* useConsoleController — owns all Console view state so the header and the body
|
|
5
|
-
* can be composed separately (the shared ModalHeader pattern: controls live in
|
|
6
|
-
* the modal header's `customContent`, the list/sub-views live in the body).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { useCallback, useState } from "react";
|
|
10
|
-
import { useConsoleMessages } from "./useConsoleMessages";
|
|
11
|
-
import { DEFAULT_LEVELS, levelMenuSummary } from "./consoleFilter";
|
|
12
|
-
import { clearEntries } from "../store/consoleLogStore";
|
|
13
|
-
|
|
14
|
-
/** Which screen the modal body shows (list, or the back-navigable filters page). */
|
|
15
|
-
|
|
16
|
-
export function useConsoleController() {
|
|
17
|
-
const [query, setQuery] = useState("");
|
|
18
|
-
const [searchActive, setSearchActive] = useState(false);
|
|
19
|
-
const [levelsMask, setLevelsMask] = useState({
|
|
20
|
-
...DEFAULT_LEVELS
|
|
21
|
-
});
|
|
22
|
-
const [showTimestamps, setShowTimestamps] = useState(false);
|
|
23
|
-
const [collapsedOverrides, setCollapsedOverrides] = useState({});
|
|
24
|
-
const [layoutMode, setLayoutMode] = useState("chrono");
|
|
25
|
-
const [view, setView] = useState("list");
|
|
26
|
-
const [clusterExpanded, setClusterExpanded] = useState({});
|
|
27
|
-
const {
|
|
28
|
-
rows,
|
|
29
|
-
hiddenCount
|
|
30
|
-
} = useConsoleMessages({
|
|
31
|
-
levelsMask,
|
|
32
|
-
query,
|
|
33
|
-
showTimestamps,
|
|
34
|
-
collapsedOverrides,
|
|
35
|
-
groupDimension: "function",
|
|
36
|
-
layoutMode,
|
|
37
|
-
clusterExpanded
|
|
38
|
-
});
|
|
39
|
-
const onToggleGroup = useCallback((groupId, currentlyCollapsed) => {
|
|
40
|
-
setCollapsedOverrides(prev => ({
|
|
41
|
-
...prev,
|
|
42
|
-
[groupId]: !currentlyCollapsed
|
|
43
|
-
}));
|
|
44
|
-
}, []);
|
|
45
|
-
const onToggleCluster = useCallback(key => {
|
|
46
|
-
setClusterExpanded(prev => ({
|
|
47
|
-
...prev,
|
|
48
|
-
[key]: !(prev[key] ?? false)
|
|
49
|
-
}));
|
|
50
|
-
}, []);
|
|
51
|
-
const clear = useCallback(() => {
|
|
52
|
-
clearEntries();
|
|
53
|
-
setCollapsedOverrides({});
|
|
54
|
-
}, []);
|
|
55
|
-
const levelSummary = levelMenuSummary(levelsMask);
|
|
56
|
-
const isLevelCustom = levelSummary !== "All levels" && levelSummary !== "Default levels";
|
|
57
|
-
return {
|
|
58
|
-
query,
|
|
59
|
-
setQuery,
|
|
60
|
-
searchActive,
|
|
61
|
-
setSearchActive,
|
|
62
|
-
levelsMask,
|
|
63
|
-
setLevelsMask,
|
|
64
|
-
showTimestamps,
|
|
65
|
-
setShowTimestamps,
|
|
66
|
-
layoutMode,
|
|
67
|
-
setLayoutMode,
|
|
68
|
-
view,
|
|
69
|
-
setView,
|
|
70
|
-
rows,
|
|
71
|
-
hiddenCount,
|
|
72
|
-
onToggleGroup,
|
|
73
|
-
onToggleCluster,
|
|
74
|
-
clear,
|
|
75
|
-
levelSummary,
|
|
76
|
-
isLevelCustom
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
//# sourceMappingURL=useConsoleController.js.map
|
|
1
|
+
"use strict";import{useCallback as n,useState as e}from"react";import{useConsoleMessages as D}from"./useConsoleMessages";import{DEFAULT_LEVELS as k,levelMenuSummary as O}from"./consoleFilter";import{clearEntries as V}from"../store/consoleLogStore";export function useConsoleController(){const[r,i]=e("");const[m,d]=e(false);const[t,p]=e({...k});const[c,v]=e(false);const[f,a]=e({});const[u,C]=e("chrono");const[g,h]=e("list");const[E,L]=e({});const{rows:M,hiddenCount:S}=D({levelsMask:t,query:r,showTimestamps:c,collapsedOverrides:f,groupDimension:"function",layoutMode:u,clusterExpanded:E});const w=n((s,o)=>{a(x=>({...x,[s]:!o}))},[]);const y=n(s=>{L(o=>({...o,[s]:!(o[s]??false)}))},[]);const T=n(()=>{V();a({})},[]);const l=O(t);const A=l!=="All levels"&&l!=="Default levels";return{query:r,setQuery:i,searchActive:m,setSearchActive:d,levelsMask:t,setLevelsMask:p,showTimestamps:c,setShowTimestamps:v,layoutMode:u,setLayoutMode:C,view:g,setView:h,rows:M,hiddenCount:S,onToggleGroup:w,onToggleCluster:y,clear:T,levelSummary:l,isLevelCustom:A}}
|
|
@@ -1,238 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* useConsoleMessages — derives the displayed row model from raw captured
|
|
5
|
-
* entries, mirroring DevTools `ConsoleView.updateMessageList`:
|
|
6
|
-
*
|
|
7
|
-
* - level + text filtering (consoleFilter)
|
|
8
|
-
* - consecutive-identical collapse into a repeat-count badge (when timestamps
|
|
9
|
-
* are off, matching `tryToCollapseMessages`)
|
|
10
|
-
* - console.group / groupCollapsed nesting + collapse/expand
|
|
11
|
-
*
|
|
12
|
-
* Returns the visible rows plus the count of messages hidden by filters
|
|
13
|
-
* ("N hidden"), and per-level totals for the toolbar.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { useMemo, useSyncExternalStore } from "react";
|
|
17
|
-
import { subscribe, getEntries } from "../store/consoleLogStore";
|
|
18
|
-
import { parseFilterQuery, shouldBeVisible } from "./consoleFilter";
|
|
19
|
-
import { sourceKey, sourceLabel, colorForKey, bracketGlyph } from "./origin";
|
|
20
|
-
|
|
21
|
-
/** How the origin gutter is laid out. */
|
|
22
|
-
|
|
23
|
-
/** One swimlane gutter cell. */
|
|
24
|
-
|
|
25
|
-
const MAX_LANES = 5;
|
|
26
|
-
|
|
27
|
-
/** Grouped mode collapses any source cluster larger than this into a header. */
|
|
28
|
-
const CLUSTER_THRESHOLD = 5;
|
|
29
|
-
|
|
30
|
-
/** First pass: tag each row with its origin source key, color, and label. */
|
|
31
|
-
function computeSourceInfo(rows, dim) {
|
|
32
|
-
for (const row of rows) {
|
|
33
|
-
const key = sourceKey(row.entry.origin, dim);
|
|
34
|
-
row.sourceKey = key;
|
|
35
|
-
row.originColor = key ? colorForKey(key) : undefined;
|
|
36
|
-
row.originLabel = dim === "off" ? undefined : sourceLabel(row.entry.origin, dim);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** lnav single-column gutter: bracket consecutive same-source runs. */
|
|
41
|
-
function attachContiguousBrackets(rows) {
|
|
42
|
-
for (let i = 0; i < rows.length; i++) {
|
|
43
|
-
const key = rows[i].sourceKey;
|
|
44
|
-
if (key == null) {
|
|
45
|
-
rows[i].bracketGlyph = undefined;
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
const sameAsPrev = i > 0 && rows[i - 1].sourceKey === key;
|
|
49
|
-
const sameAsNext = i < rows.length - 1 && rows[i + 1].sourceKey === key;
|
|
50
|
-
const bracket = !sameAsPrev && !sameAsNext ? "single" : !sameAsPrev ? "top" : !sameAsNext ? "bottom" : "mid";
|
|
51
|
-
rows[i].bracketGlyph = bracketGlyph(bracket);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Re-order rows so all rows of one source are contiguous (groups ordered by
|
|
57
|
-
* first appearance, chronological within each). Clusters larger than
|
|
58
|
-
* CLUSTER_THRESHOLD collapse into a single expandable header (Chrome-style),
|
|
59
|
-
* unless the user has expanded that cluster.
|
|
60
|
-
*/
|
|
61
|
-
function clusterRows(rows, expanded) {
|
|
62
|
-
const order = [];
|
|
63
|
-
const groups = new Map();
|
|
64
|
-
for (const r of rows) {
|
|
65
|
-
const k = r.sourceKey ?? "—";
|
|
66
|
-
let g = groups.get(k);
|
|
67
|
-
if (!g) {
|
|
68
|
-
g = [];
|
|
69
|
-
groups.set(k, g);
|
|
70
|
-
order.push(k);
|
|
71
|
-
}
|
|
72
|
-
g.push(r);
|
|
73
|
-
}
|
|
74
|
-
const out = [];
|
|
75
|
-
for (const k of order) {
|
|
76
|
-
const group = groups.get(k);
|
|
77
|
-
for (const r of group) r.depth = 0; // clustering ignores console.group nesting
|
|
78
|
-
|
|
79
|
-
const isLarge = group.length > CLUSTER_THRESHOLD;
|
|
80
|
-
const isExpanded = expanded[k] ?? false;
|
|
81
|
-
if (isLarge) {
|
|
82
|
-
out.push({
|
|
83
|
-
key: `cluster:${k}`,
|
|
84
|
-
entry: group[0].entry,
|
|
85
|
-
depth: 0,
|
|
86
|
-
repeatCount: 1,
|
|
87
|
-
isGroupHeader: false,
|
|
88
|
-
sourceKey: k,
|
|
89
|
-
originColor: group[0].originColor,
|
|
90
|
-
originLabel: group[0].originLabel,
|
|
91
|
-
clusterHeader: {
|
|
92
|
-
key: k,
|
|
93
|
-
count: group.length,
|
|
94
|
-
expanded: isExpanded
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
if (!isExpanded) continue;
|
|
98
|
-
}
|
|
99
|
-
group.forEach((r, i) => {
|
|
100
|
-
const single = group.length === 1;
|
|
101
|
-
const bracket = single ? "single" : i === 0 ? "top" : i === group.length - 1 ? "bottom" : "mid";
|
|
102
|
-
r.bracketGlyph = bracketGlyph(bracket);
|
|
103
|
-
out.push(r);
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
return out;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/** Git-graph swimlanes: each source gets a continuous vertical track so its
|
|
110
|
-
* line stays unbroken when other sources interrupt it. */
|
|
111
|
-
function attachSwimlanes(rows) {
|
|
112
|
-
const first = new Map();
|
|
113
|
-
const last = new Map();
|
|
114
|
-
rows.forEach((r, i) => {
|
|
115
|
-
const k = r.sourceKey;
|
|
116
|
-
if (k == null) return;
|
|
117
|
-
if (!first.has(k)) first.set(k, i);
|
|
118
|
-
last.set(k, i);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// Assign each source a lane, reusing a lane once its occupant's run ended.
|
|
122
|
-
const sources = [...first.keys()].sort((a, b) => first.get(a) - first.get(b));
|
|
123
|
-
const laneOf = new Map();
|
|
124
|
-
const laneEnd = [];
|
|
125
|
-
for (const s of sources) {
|
|
126
|
-
let lane = laneEnd.findIndex(end => end < first.get(s));
|
|
127
|
-
if (lane === -1) {
|
|
128
|
-
lane = laneEnd.length < MAX_LANES ? laneEnd.length : MAX_LANES - 1;
|
|
129
|
-
if (lane >= laneEnd.length) laneEnd.push(0);
|
|
130
|
-
}
|
|
131
|
-
laneOf.set(s, lane);
|
|
132
|
-
laneEnd[lane] = Math.max(laneEnd[lane] ?? 0, last.get(s));
|
|
133
|
-
}
|
|
134
|
-
const laneCount = Math.max(1, Math.min(laneEnd.length, MAX_LANES));
|
|
135
|
-
rows.forEach((r, i) => {
|
|
136
|
-
const cells = Array.from({
|
|
137
|
-
length: laneCount
|
|
138
|
-
}, () => ({
|
|
139
|
-
glyph: " "
|
|
140
|
-
}));
|
|
141
|
-
for (const s of sources) {
|
|
142
|
-
const lane = laneOf.get(s);
|
|
143
|
-
if (lane >= laneCount) continue;
|
|
144
|
-
if (i >= first.get(s) && i <= last.get(s)) {
|
|
145
|
-
cells[lane] = {
|
|
146
|
-
glyph: r.sourceKey === s ? "●" : "│",
|
|
147
|
-
color: colorForKey(s)
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
r.lanes = cells;
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
const GROUP_STARTS = new Set(["group", "groupCollapsed"]);
|
|
155
|
-
function buildDisplayRows(entries, opts) {
|
|
156
|
-
const {
|
|
157
|
-
levelsMask,
|
|
158
|
-
query,
|
|
159
|
-
showTimestamps,
|
|
160
|
-
collapsedOverrides
|
|
161
|
-
} = opts;
|
|
162
|
-
const parsed = parseFilterQuery(query.trim());
|
|
163
|
-
const rows = [];
|
|
164
|
-
const levelCounts = {
|
|
165
|
-
verbose: 0,
|
|
166
|
-
info: 0,
|
|
167
|
-
warning: 0,
|
|
168
|
-
error: 0
|
|
169
|
-
};
|
|
170
|
-
let hiddenCount = 0;
|
|
171
|
-
const stack = [];
|
|
172
|
-
const anyAncestorCollapsed = () => stack.some(g => g.collapsed);
|
|
173
|
-
for (const entry of entries) {
|
|
174
|
-
levelCounts[entry.level]++;
|
|
175
|
-
if (entry.method === "groupEnd") {
|
|
176
|
-
stack.pop();
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
const isHeader = GROUP_STARTS.has(entry.method);
|
|
180
|
-
const hiddenByGroup = anyAncestorCollapsed();
|
|
181
|
-
const passesFilter = shouldBeVisible(entry, levelsMask, parsed);
|
|
182
|
-
if (!passesFilter) {
|
|
183
|
-
hiddenCount++;
|
|
184
|
-
} else if (!hiddenByGroup) {
|
|
185
|
-
// Repeat-count collapse: only when timestamps are hidden and the previous
|
|
186
|
-
// visible row is an identical, non-header message at the same depth.
|
|
187
|
-
const prev = rows[rows.length - 1];
|
|
188
|
-
if (!showTimestamps && !isHeader && prev && !prev.isGroupHeader && prev.depth === stack.length && prev.entry.method === entry.method && prev.entry.message === entry.message) {
|
|
189
|
-
prev.repeatCount++;
|
|
190
|
-
} else {
|
|
191
|
-
rows.push({
|
|
192
|
-
key: String(entry.id),
|
|
193
|
-
entry,
|
|
194
|
-
depth: stack.length,
|
|
195
|
-
repeatCount: 1,
|
|
196
|
-
isGroupHeader: isHeader,
|
|
197
|
-
groupId: isHeader ? entry.id : undefined,
|
|
198
|
-
groupCollapsed: undefined
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
if (isHeader) {
|
|
203
|
-
const defaultCollapsed = entry.method === "groupCollapsed";
|
|
204
|
-
const collapsed = collapsedOverrides[entry.id] ?? defaultCollapsed;
|
|
205
|
-
// Record the collapse state on the just-pushed header row (if visible).
|
|
206
|
-
const headerRow = rows[rows.length - 1];
|
|
207
|
-
if (headerRow && headerRow.groupId === entry.id) {
|
|
208
|
-
headerRow.groupCollapsed = collapsed;
|
|
209
|
-
}
|
|
210
|
-
stack.push({
|
|
211
|
-
id: entry.id,
|
|
212
|
-
collapsed: collapsed || hiddenByGroup
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
computeSourceInfo(rows, opts.groupDimension);
|
|
217
|
-
let finalRows = rows;
|
|
218
|
-
if (opts.groupDimension !== "off") {
|
|
219
|
-
if (opts.layoutMode === "cluster") {
|
|
220
|
-
finalRows = clusterRows(rows, opts.clusterExpanded);
|
|
221
|
-
} else if (opts.layoutMode === "swimlane") {
|
|
222
|
-
attachSwimlanes(rows);
|
|
223
|
-
} else {
|
|
224
|
-
attachContiguousBrackets(rows);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return {
|
|
228
|
-
rows: finalRows,
|
|
229
|
-
hiddenCount,
|
|
230
|
-
levelCounts,
|
|
231
|
-
totalCount: entries.length
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
export function useConsoleMessages(opts) {
|
|
235
|
-
const entries = useSyncExternalStore(subscribe, getEntries, getEntries);
|
|
236
|
-
return useMemo(() => buildDisplayRows(entries, opts), [entries, opts.levelsMask, opts.query, opts.showTimestamps, opts.collapsedOverrides, opts.groupDimension, opts.layoutMode, opts.clusterExpanded]);
|
|
237
|
-
}
|
|
238
|
-
//# sourceMappingURL=useConsoleMessages.js.map
|
|
1
|
+
"use strict";import{useMemo as w,useSyncExternalStore as x}from"react";import{subscribe as K,getEntries as b}from"../store/consoleLogStore";import{parseFilterQuery as v,shouldBeVisible as G}from"./consoleFilter";import{sourceKey as L,sourceLabel as R,colorForKey as M,bracketGlyph as E}from"./origin";const m=5;const A=5;function H(t,e){for(const r of t){const i=L(r.entry.origin,e);r.sourceKey=i;r.originColor=i?M(i):void 0;r.originLabel=e==="off"?void 0:R(r.entry.origin,e)}}function T(t){for(let e=0;e<t.length;e++){const r=t[e].sourceKey;if(r==null){t[e].bracketGlyph=void 0;continue}const i=e>0&&t[e-1].sourceKey===r;const d=e<t.length-1&&t[e+1].sourceKey===r;const n=!i&&!d?"single":!i?"top":!d?"bottom":"mid";t[e].bracketGlyph=E(n)}}function D(t,e){const r=[];const i=new Map;for(const n of t){const l=n.sourceKey??"\u2014";let o=i.get(l);if(!o){o=[];i.set(l,o);r.push(l)}o.push(n)}const d=[];for(const n of r){const l=i.get(n);for(const c of l)c.depth=0;const o=l.length>A;const s=e[n]??false;if(o){d.push({key:`cluster:${n}`,entry:l[0].entry,depth:0,repeatCount:1,isGroupHeader:false,sourceKey:n,originColor:l[0].originColor,originLabel:l[0].originLabel,clusterHeader:{key:n,count:l.length,expanded:s}});if(!s)continue}l.forEach((c,u)=>{const p=l.length===1;const g=p?"single":u===0?"top":u===l.length-1?"bottom":"mid";c.bracketGlyph=E(g);d.push(c)})}return d}function O(t){const e=new Map;const r=new Map;t.forEach((o,s)=>{const c=o.sourceKey;if(c==null)return;if(!e.has(c))e.set(c,s);r.set(c,s)});const i=[...e.keys()].sort((o,s)=>e.get(o)-e.get(s));const d=new Map;const n=[];for(const o of i){let s=n.findIndex(c=>c<e.get(o));if(s===-1){s=n.length<m?n.length:m-1;if(s>=n.length)n.push(0)}d.set(o,s);n[s]=Math.max(n[s]??0,r.get(o))}const l=Math.max(1,Math.min(n.length,m));t.forEach((o,s)=>{const c=Array.from({length:l},()=>({glyph:" "}));for(const u of i){const p=d.get(u);if(p>=l)continue;if(s>=e.get(u)&&s<=r.get(u)){c[p]={glyph:o.sourceKey===u?"\u25CF":"\u2502",color:M(u)}}}o.lanes=c})}const I=new Set(["group","groupCollapsed"]);function B(t,e){const{levelsMask:r,query:i,showTimestamps:d,collapsedOverrides:n}=e;const l=v(i.trim());const o=[];const s={verbose:0,info:0,warning:0,error:0};let c=0;const u=[];const p=()=>u.some(a=>a.collapsed);for(const a of t){s[a.level]++;if(a.method==="groupEnd"){u.pop();continue}const h=I.has(a.method);const k=p();const S=G(a,r,l);if(!S){c++}else if(!k){const f=o[o.length-1];if(!d&&!h&&f&&!f.isGroupHeader&&f.depth===u.length&&f.entry.method===a.method&&f.entry.message===a.message){f.repeatCount++}else{o.push({key:String(a.id),entry:a,depth:u.length,repeatCount:1,isGroupHeader:h,groupId:h?a.id:void 0,groupCollapsed:void 0})}}if(h){const f=a.method==="groupCollapsed";const C=n[a.id]??f;const y=o[o.length-1];if(y&&y.groupId===a.id){y.groupCollapsed=C}u.push({id:a.id,collapsed:C||k})}}H(o,e.groupDimension);let g=o;if(e.groupDimension!=="off"){if(e.layoutMode==="cluster"){g=D(o,e.clusterExpanded)}else if(e.layoutMode==="swimlane"){O(o)}else{T(o)}}return{rows:g,hiddenCount:c,levelCounts:s,totalCount:t.length}}export function useConsoleMessages(t){const e=x(K,b,b);return w(()=>B(e,t),[e,t.levelsMask,t.query,t.showTimestamps,t.collapsedOverrides,t.groupDimension,t.layoutMode,t.clusterExpanded])}
|
|
@@ -1,19 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { useSyncExternalStore, useEffect } from "react";
|
|
4
|
-
import { subscribe, getEntries, installConsoleCapture } from "../store/consoleLogStore";
|
|
5
|
-
/**
|
|
6
|
-
* Subscribe to captured console logs. Installs the console interceptor on mount
|
|
7
|
-
* (idempotent) and re-renders whenever a new entry is captured or the buffer is
|
|
8
|
-
* cleared.
|
|
9
|
-
*/
|
|
10
|
-
export function useConsoleLogs() {
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
installConsoleCapture();
|
|
13
|
-
}, []);
|
|
14
|
-
const logs = useSyncExternalStore(subscribe, getEntries, getEntries);
|
|
15
|
-
return {
|
|
16
|
-
logs
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=useConsoleLogs.js.map
|
|
1
|
+
"use strict";import{useSyncExternalStore as o,useEffect as s}from"react";import{subscribe as r,getEntries as e,installConsoleCapture as n}from"../store/consoleLogStore";export function useConsoleLogs(){s(()=>{n()},[]);const t=o(r,e,e);return{logs:t}}
|
package/lib/module/index.js
CHANGED
|
@@ -1,52 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @buoy-gg/console
|
|
5
|
-
*
|
|
6
|
-
* Captures global `console.*` output and renders it as a Buoy devtool.
|
|
7
|
-
*
|
|
8
|
-
* This is the BASIC version: direct console patching + a flat list, used to
|
|
9
|
-
* verify the capture pipeline end to end. Next step is a 1:1 port of Chrome
|
|
10
|
-
* DevTools' console view.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
// =============================================================================
|
|
14
|
-
// PRESET (Primary entry point — pass to <FloatingDevTools apps={[...]} />)
|
|
15
|
-
// =============================================================================
|
|
16
|
-
export { consoleToolPreset, createConsoleTool } from "./preset";
|
|
17
|
-
|
|
18
|
-
// =============================================================================
|
|
19
|
-
// ROOT (Mount once at app root to capture logs from startup)
|
|
20
|
-
// =============================================================================
|
|
21
|
-
export { ConsoleRoot } from "./components/ConsoleRoot";
|
|
22
|
-
|
|
23
|
-
// =============================================================================
|
|
24
|
-
// COMPONENTS
|
|
25
|
-
// =============================================================================
|
|
26
|
-
export { ConsoleModal } from "./components/ConsoleModal";
|
|
27
|
-
export { ConsoleIcon, CONSOLE_ICON_COLOR } from "./components/ConsoleIcon";
|
|
28
|
-
|
|
29
|
-
// DevTools-style console panel (the 1:1 Chrome console port)
|
|
30
|
-
export { ConsoleView } from "./devtools/ConsoleView";
|
|
31
|
-
export { ConsoleMessageRow } from "./devtools/ConsoleMessageRow";
|
|
32
|
-
export { ConsoleValue } from "./devtools/ConsoleValue";
|
|
33
|
-
export { useConsoleMessages } from "./devtools/useConsoleMessages";
|
|
34
|
-
export { consoleTheme, levelStyles } from "./devtools/theme";
|
|
35
|
-
|
|
36
|
-
// Basic flat list (kept for simple/embedded use)
|
|
37
|
-
export { ConsoleLogList } from "./components/ConsoleLogList";
|
|
38
|
-
|
|
39
|
-
// =============================================================================
|
|
40
|
-
// HOOK
|
|
41
|
-
// =============================================================================
|
|
42
|
-
export { useConsoleLogs } from "./hooks/useConsoleLogs";
|
|
43
|
-
// =============================================================================
|
|
44
|
-
// EXTERNAL SYNC (device → desktop dashboard)
|
|
45
|
-
// =============================================================================
|
|
46
|
-
export { consoleSyncAdapter } from "./sync/consoleSyncAdapter";
|
|
47
|
-
|
|
48
|
-
// =============================================================================
|
|
49
|
-
// CAPTURE STORE (install/teardown + types)
|
|
50
|
-
// =============================================================================
|
|
51
|
-
export { installConsoleCapture, installFatalErrorCapture, uninstallConsoleCapture, clearEntries, getEntries, subscribe, replaceEntries, onClear, initConsolePersistence, getPreserveLog, setPreserveLog, subscribePreserveLog } from "./store/consoleLogStore";
|
|
52
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
"use strict";export{consoleToolPreset,createConsoleTool}from"./preset";export{ConsoleRoot}from"./components/ConsoleRoot";export{ConsoleModal}from"./components/ConsoleModal";export{ConsoleIcon,CONSOLE_ICON_COLOR}from"./components/ConsoleIcon";export{ConsoleView}from"./devtools/ConsoleView";export{ConsoleMessageRow}from"./devtools/ConsoleMessageRow";export{ConsoleValue}from"./devtools/ConsoleValue";export{useConsoleMessages}from"./devtools/useConsoleMessages";export{consoleTheme,levelStyles}from"./devtools/theme";export{ConsoleLogList}from"./components/ConsoleLogList";export{useConsoleLogs}from"./hooks/useConsoleLogs";export{consoleSyncAdapter}from"./sync/consoleSyncAdapter";export{installConsoleCapture,installFatalErrorCapture,uninstallConsoleCapture,clearEntries,getEntries,subscribe,replaceEntries,onClear,initConsolePersistence,getPreserveLog,setPreserveLog,subscribePreserveLog}from"./store/consoleLogStore";
|
package/lib/module/preset.js
CHANGED
|
@@ -1,61 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Pre-configured Console tool for FloatingDevTools.
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* ```tsx
|
|
8
|
-
* import { consoleToolPreset } from '@buoy-gg/console';
|
|
9
|
-
*
|
|
10
|
-
* <FloatingDevTools apps={[consoleToolPreset]} />
|
|
11
|
-
* ```
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { ConsoleIcon, CONSOLE_ICON_COLOR } from "./components/ConsoleIcon";
|
|
15
|
-
import { ConsoleModal } from "./components/ConsoleModal";
|
|
16
|
-
import { installConsoleCapture } from "./store/consoleLogStore";
|
|
17
|
-
import { createToolFactory, defineToolPreset } from "@buoy-gg/shared-ui";
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Install console + fatal-error capture at IMPORT time, not first UI mount.
|
|
21
|
-
*
|
|
22
|
-
* Deliberately a module side effect (same pattern as @buoy-gg/network's
|
|
23
|
-
* override hydration): a fatal error thrown during the app's FIRST render
|
|
24
|
-
* kills the tree before FloatingDevTools' effects ever run, so mount-time
|
|
25
|
-
* install (`ConsoleRoot`) captured nothing for exactly the crashes that most
|
|
26
|
-
* need capturing. Importing the preset happens at bundle-eval, before any
|
|
27
|
-
* rendering, so the `console.*` patch and both fatal-error hooks (`ErrorUtils`
|
|
28
|
-
* and RN's native exception listener) are live from the first line of app code.
|
|
29
|
-
*
|
|
30
|
-
* Guards:
|
|
31
|
-
* - `ErrorUtils` OR `RN$registerExceptionListener` present = a real React Native
|
|
32
|
-
* runtime. The desktop dashboard and web mirrors import this package too, and
|
|
33
|
-
* must never patch their OWN console (they mirror device entries via
|
|
34
|
-
* `replaceEntries`).
|
|
35
|
-
* - Dev-only. In production the existing mount-time path still applies (the
|
|
36
|
-
* tools only mount there for licensed users), so end-user builds are never
|
|
37
|
-
* patched at import.
|
|
38
|
-
*/
|
|
39
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
40
|
-
const rnGlobals = globalThis;
|
|
41
|
-
const isReactNativeRuntime = typeof rnGlobals.ErrorUtils?.setGlobalHandler === "function" || typeof rnGlobals.RN$registerExceptionListener === "function";
|
|
42
|
-
if (isReactNativeRuntime && typeof __DEV__ !== "undefined" && __DEV__) {
|
|
43
|
-
installConsoleCapture();
|
|
44
|
-
}
|
|
45
|
-
export const consoleToolPreset = defineToolPreset({
|
|
46
|
-
id: "console",
|
|
47
|
-
name: "CONSOLE",
|
|
48
|
-
description: "Captured console.* output",
|
|
49
|
-
slot: "both",
|
|
50
|
-
color: CONSOLE_ICON_COLOR,
|
|
51
|
-
icon: ({
|
|
52
|
-
size
|
|
53
|
-
}) => /*#__PURE__*/_jsx(ConsoleIcon, {
|
|
54
|
-
size: size
|
|
55
|
-
}),
|
|
56
|
-
component: ConsoleModal
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
/** Create a custom Console tool configuration. */
|
|
60
|
-
export const createConsoleTool = createToolFactory(consoleToolPreset);
|
|
61
|
-
//# sourceMappingURL=preset.js.map
|
|
1
|
+
"use strict";import{ConsoleIcon as t,CONSOLE_ICON_COLOR as n}from"./components/ConsoleIcon";import{ConsoleModal as r}from"./components/ConsoleModal";import{installConsoleCapture as s}from"./store/consoleLogStore";import{createToolFactory as i,defineToolPreset as l}from"@buoy-gg/shared-ui";import{jsx as c}from"react/jsx-runtime";const o=globalThis;const p=typeof o.ErrorUtils?.setGlobalHandler==="function"||typeof o.RN$registerExceptionListener==="function";if(p&&typeof __DEV__!=="undefined"&&__DEV__){s()}export const consoleToolPreset=l({id:"console",name:"CONSOLE",description:"Captured console.* output",slot:"both",color:n,icon:({size:e})=>c(t,{size:e}),component:r});export const createConsoleTool=i(consoleToolPreset);
|