@fluixi/devtools 0.2.0-alpha.2 → 0.2.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -2
- package/dist/callsite.cjs +72 -0
- package/dist/callsite.d.ts +22 -0
- package/dist/callsite.d.ts.map +1 -0
- package/dist/callsite.js +82 -0
- package/dist/callsite.mjs +51 -0
- package/dist/change-view.cjs +134 -0
- package/dist/change-view.d.ts +10 -0
- package/dist/change-view.d.ts.map +1 -0
- package/dist/change-view.js +102 -0
- package/dist/change-view.mjs +111 -0
- package/dist/copy.cjs +63 -0
- package/dist/copy.d.ts +9 -0
- package/dist/copy.d.ts.map +1 -0
- package/dist/copy.js +52 -0
- package/dist/copy.mjs +42 -0
- package/dist/describe.cjs +55 -0
- package/dist/describe.d.ts +3 -0
- package/dist/describe.d.ts.map +1 -0
- package/dist/describe.js +47 -0
- package/dist/describe.mjs +34 -0
- package/dist/detail-panel.cjs +307 -0
- package/dist/detail-panel.d.ts +17 -0
- package/dist/detail-panel.d.ts.map +1 -0
- package/dist/detail-panel.js +217 -0
- package/dist/detail-panel.mjs +284 -0
- package/dist/diff.cjs +225 -0
- package/dist/diff.d.ts +31 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +132 -0
- package/dist/diff.mjs +202 -0
- package/dist/dom.cjs +204 -0
- package/dist/dom.d.ts +81 -0
- package/dist/dom.d.ts.map +1 -0
- package/dist/dom.js +269 -0
- package/dist/dom.mjs +183 -0
- package/dist/export.cjs +221 -0
- package/dist/export.d.ts +55 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +90 -0
- package/dist/export.mjs +209 -0
- package/dist/float.cjs +232 -0
- package/dist/float.d.ts +54 -0
- package/dist/float.d.ts.map +1 -0
- package/dist/float.js +256 -0
- package/dist/float.mjs +211 -0
- package/dist/format.cjs +175 -0
- package/dist/format.d.ts +16 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +188 -0
- package/dist/format.mjs +154 -0
- package/dist/graph-view.cjs +893 -0
- package/dist/graph-view.d.ts +79 -2
- package/dist/graph-view.d.ts.map +1 -1
- package/dist/graph-view.js +866 -50
- package/dist/graph-view.mjs +870 -0
- package/dist/highlight.cjs +140 -0
- package/dist/highlight.d.ts +56 -0
- package/dist/highlight.d.ts.map +1 -0
- package/dist/highlight.js +154 -0
- package/dist/highlight.mjs +119 -0
- package/dist/history.cjs +95 -0
- package/dist/history.d.ts +59 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +85 -0
- package/dist/history.mjs +74 -0
- package/dist/hook.cjs +1562 -0
- package/dist/hook.d.ts +60 -0
- package/dist/hook.d.ts.map +1 -0
- package/dist/hook.js +142 -0
- package/dist/hook.mjs +1553 -0
- package/dist/index.cjs +4552 -0
- package/dist/index.d.ts +44 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -1
- package/dist/index.mjs +4544 -0
- package/dist/inspector.cjs +688 -0
- package/dist/inspector.d.ts +60 -0
- package/dist/inspector.d.ts.map +1 -0
- package/dist/inspector.js +415 -0
- package/dist/inspector.mjs +676 -0
- package/dist/instrument.cjs +497 -0
- package/dist/instrument.d.ts +147 -5
- package/dist/instrument.d.ts.map +1 -1
- package/dist/instrument.js +164 -44
- package/dist/instrument.mjs +487 -0
- package/dist/kind-filter.cjs +172 -0
- package/dist/kind-filter.d.ts +39 -0
- package/dist/kind-filter.d.ts.map +1 -0
- package/dist/kind-filter.js +151 -0
- package/dist/kind-filter.mjs +151 -0
- package/dist/menu.cjs +141 -0
- package/dist/menu.d.ts +37 -0
- package/dist/menu.d.ts.map +1 -0
- package/dist/menu.js +125 -0
- package/dist/menu.mjs +120 -0
- package/dist/observe.cjs +1352 -0
- package/dist/observe.d.ts +80 -0
- package/dist/observe.d.ts.map +1 -0
- package/dist/observe.js +893 -0
- package/dist/observe.mjs +1345 -0
- package/dist/palette.cjs +52 -0
- package/dist/palette.d.ts +11 -0
- package/dist/palette.d.ts.map +1 -0
- package/dist/palette.js +27 -0
- package/dist/palette.mjs +31 -0
- package/dist/path.cjs +45 -0
- package/dist/path.d.ts +19 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +49 -0
- package/dist/path.mjs +24 -0
- package/dist/plugin.cjs +87 -0
- package/dist/plugin.d.ts +121 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +74 -0
- package/dist/plugin.mjs +66 -0
- package/dist/plugins/context.cjs +98 -0
- package/dist/plugins/context.d.ts +10 -0
- package/dist/plugins/context.d.ts.map +1 -0
- package/dist/plugins/context.js +80 -0
- package/dist/plugins/context.mjs +75 -0
- package/dist/plugins/directives.cjs +98 -0
- package/dist/plugins/directives.d.ts +25 -0
- package/dist/plugins/directives.d.ts.map +1 -0
- package/dist/plugins/directives.js +78 -0
- package/dist/plugins/directives.mjs +75 -0
- package/dist/plugins/index.cjs +162 -0
- package/dist/plugins/index.d.ts +7 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +9 -0
- package/dist/plugins/index.mjs +140 -0
- package/dist/source.cjs +111 -0
- package/dist/source.d.ts +72 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +153 -0
- package/dist/source.mjs +90 -0
- package/dist/timeline.cjs +350 -0
- package/dist/timeline.d.ts +30 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +271 -0
- package/dist/timeline.mjs +327 -0
- package/dist/tree.cjs +574 -0
- package/dist/tree.d.ts +128 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +645 -0
- package/dist/tree.mjs +551 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/value-pane.cjs +223 -0
- package/dist/value-pane.d.ts +10 -0
- package/dist/value-pane.d.ts.map +1 -0
- package/dist/value-pane.js +61 -0
- package/dist/value-pane.mjs +200 -0
- package/dist/wire.cjs +109 -0
- package/dist/wire.d.ts +100 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +93 -0
- package/dist/wire.mjs +89 -0
- package/package.json +17 -5
package/dist/hook.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type ObservedGraph } from './observe.js';
|
|
2
|
+
import { type GraphSnapshot } from './wire.js';
|
|
3
|
+
export interface DevtoolsHook {
|
|
4
|
+
/**
|
|
5
|
+
* Called by the runtime when it loads.
|
|
6
|
+
*
|
|
7
|
+
* `watch` is how the caller says it brought its own devtools. Two copies live on a page
|
|
8
|
+
* routinely — a browser extension injects one at document_start and an application's own
|
|
9
|
+
* agent loads another — and the first to arrive owns the hook. Without this the graph is
|
|
10
|
+
* built by whichever copy got there first, which for an installed extension is a build
|
|
11
|
+
* that knows nothing of the compiler that made the application.
|
|
12
|
+
*/
|
|
13
|
+
inject(runtime: {
|
|
14
|
+
observeReactiveNodes: (o: never) => () => void;
|
|
15
|
+
version: string;
|
|
16
|
+
watch?: (options: {
|
|
17
|
+
observe: (o: never) => () => void;
|
|
18
|
+
}) => ObservedGraph;
|
|
19
|
+
}): void;
|
|
20
|
+
/** The graph, once a runtime has turned up. */
|
|
21
|
+
readonly observed: ObservedGraph | null;
|
|
22
|
+
/** The version of the runtime that injected, for a panel reporting what it is attached to. */
|
|
23
|
+
readonly version: string | null;
|
|
24
|
+
/**
|
|
25
|
+
* How many copies of this module tried to install one.
|
|
26
|
+
*
|
|
27
|
+
* Ordinarily two: an extension's and the application's own. Worth having for a panel
|
|
28
|
+
* reporting what it is attached to; which one watches is settled by `inject`.
|
|
29
|
+
*/
|
|
30
|
+
readonly copies: number;
|
|
31
|
+
/**
|
|
32
|
+
* Everything, or only what moved after `since`.
|
|
33
|
+
*
|
|
34
|
+
* The cursor comes back on every snapshot; a consumer folding in deltas keeps it and
|
|
35
|
+
* hands it back. Asking consumes nothing, so a page with a browser panel and an editor
|
|
36
|
+
* panel watching at the same time gives each of them every change. Draining a shared
|
|
37
|
+
* one meant whichever polled first took them.
|
|
38
|
+
*
|
|
39
|
+
* A cursor older than the removal log gets a full snapshot instead, since there is no
|
|
40
|
+
* longer any way to say what went missing.
|
|
41
|
+
*/
|
|
42
|
+
snapshot(options?: {
|
|
43
|
+
partial?: boolean;
|
|
44
|
+
since?: number;
|
|
45
|
+
}): GraphSnapshot | null;
|
|
46
|
+
/**
|
|
47
|
+
* Draw the overlay over something in the page, for a panel that is not in it.
|
|
48
|
+
*
|
|
49
|
+
* A number is a node, and covers everywhere it reaches. A string is one element, written
|
|
50
|
+
* as the tree keys them: the tag's id, the index of the root it rendered, then a child
|
|
51
|
+
* index per step — `12:0/1/2`. Null clears it.
|
|
52
|
+
*/
|
|
53
|
+
highlight(target: number | string | null): void;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Install the hook. Returns the existing one if something got there first, so two agents on
|
|
57
|
+
* one page share a graph rather than each seeing half of it.
|
|
58
|
+
*/
|
|
59
|
+
export declare function installDevtoolsHook(): DevtoolsHook;
|
|
60
|
+
//# sourceMappingURL=hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"AAYA,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAmC,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAQhF,MAAM,WAAW,YAAY;IAC3B;;;;;;;;OAQG;IACH,MAAM,CAAC,OAAO,EAAE;QACd,oBAAoB,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,MAAM,IAAI,CAAC;QAC/C,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE;YAAE,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,MAAM,IAAI,CAAA;SAAE,KAAK,aAAa,CAAC;KAC3E,GAAG,IAAI,CAAC;IACT,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IACxC,8FAA8F;IAC9F,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa,GAAG,IAAI,CAAC;IAChF;;;;;;OAMG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;CACjD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,YAAY,CAiHlD"}
|
package/dist/hook.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// The agent side of the rendezvous.
|
|
2
|
+
//
|
|
3
|
+
// A browser extension or a dev-server injection runs this before the application loads. It
|
|
4
|
+
// leaves a global behind; when the app's copy of @fluixi/reactive is first evaluated, the
|
|
5
|
+
// runtime finds it and hands over its own `observeReactiveNodes`. The graph is then built
|
|
6
|
+
// from the app's framework rather than this bundle's — two copies of the runtime each keep
|
|
7
|
+
// their own nodes, so watching the wrong one shows an empty graph.
|
|
8
|
+
//
|
|
9
|
+
// The app imports nothing and knows nothing about this. It also works against a production
|
|
10
|
+
// build: the reporting calls are unconditional, so only the names and source locations are
|
|
11
|
+
// missing there.
|
|
12
|
+
import { withoutElements } from './dom.js';
|
|
13
|
+
import { observeGraph } from './observe.js';
|
|
14
|
+
import { hideHighlight, showHighlight } from './highlight.js';
|
|
15
|
+
import { serializeGraph } from './wire.js';
|
|
16
|
+
/** A few hundred interactions' worth. */
|
|
17
|
+
const HISTORY = 500;
|
|
18
|
+
/** Kept in step with the name in @fluixi/reactive's observe.ts. */
|
|
19
|
+
const HOOK = '__FLUIXI_DEVTOOLS_HOOK__';
|
|
20
|
+
/**
|
|
21
|
+
* Install the hook. Returns the existing one if something got there first, so two agents on
|
|
22
|
+
* one page share a graph rather than each seeing half of it.
|
|
23
|
+
*/
|
|
24
|
+
export function installDevtoolsHook() {
|
|
25
|
+
const host = globalThis;
|
|
26
|
+
const existing = host[HOOK];
|
|
27
|
+
if (existing) {
|
|
28
|
+
// Counted, not complained about. Two copies is the ordinary case — an extension injects
|
|
29
|
+
// one before anything else runs and the application's agent loads another — and `inject`
|
|
30
|
+
// sorts out which of them ends up watching.
|
|
31
|
+
existing.copies = (existing.copies ?? 1) + 1;
|
|
32
|
+
return existing;
|
|
33
|
+
}
|
|
34
|
+
let observed = null;
|
|
35
|
+
/** Whether whoever is watching brought its own devtools, rather than being given this one. */
|
|
36
|
+
let owned = false;
|
|
37
|
+
let version = null;
|
|
38
|
+
/** What has happened, for whoever asks. Bounded: nothing here is ever consumed. */
|
|
39
|
+
const history = [];
|
|
40
|
+
const hook = {
|
|
41
|
+
copies: 1,
|
|
42
|
+
inject(runtime) {
|
|
43
|
+
version = runtime.version;
|
|
44
|
+
if (!observed) {
|
|
45
|
+
observed = (runtime.watch ?? observeGraph)({ observe: runtime.observeReactiveNodes });
|
|
46
|
+
owned = runtime.watch !== undefined;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// The runtime injects the moment it is evaluated, and it brings no devtools of its
|
|
50
|
+
// own — so an extension's copy starts watching first. The application's agent runs
|
|
51
|
+
// straight after, before any of its own modules have made a node, and hands over an
|
|
52
|
+
// observer that matches the compiler that built it. That one takes over.
|
|
53
|
+
if (owned || !runtime.watch)
|
|
54
|
+
return;
|
|
55
|
+
observed.detach();
|
|
56
|
+
observed = runtime.watch({ observe: runtime.observeReactiveNodes });
|
|
57
|
+
owned = true;
|
|
58
|
+
},
|
|
59
|
+
get observed() {
|
|
60
|
+
return observed;
|
|
61
|
+
},
|
|
62
|
+
get version() {
|
|
63
|
+
return version;
|
|
64
|
+
},
|
|
65
|
+
highlight(target) {
|
|
66
|
+
if (!observed || target === null) {
|
|
67
|
+
hideHighlight();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (typeof target === 'number') {
|
|
71
|
+
const found = observed.elementsFor(target);
|
|
72
|
+
if (found.length)
|
|
73
|
+
showHighlight(found, observed.graph.get(target)?.label);
|
|
74
|
+
else
|
|
75
|
+
hideHighlight();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// Walked through the description rather than the elements, because that is what the
|
|
79
|
+
// keys were built from: a tag's roots there include what it was mounted into and what
|
|
80
|
+
// it writes to, neither of which it rendered.
|
|
81
|
+
const [head, ...steps] = target.split('/');
|
|
82
|
+
const [tag, root] = (head ?? '').split(':');
|
|
83
|
+
let node = observed.domFor(Number(tag))[Number(root)];
|
|
84
|
+
for (const step of steps)
|
|
85
|
+
node = node?.children[Number(step)];
|
|
86
|
+
const element = node?.element;
|
|
87
|
+
if (element)
|
|
88
|
+
showHighlight(element, element.tagName.toLowerCase());
|
|
89
|
+
else
|
|
90
|
+
hideHighlight();
|
|
91
|
+
},
|
|
92
|
+
snapshot({ partial = false, since } = {}) {
|
|
93
|
+
if (!observed)
|
|
94
|
+
return null;
|
|
95
|
+
// Detection is shared and has to run: it is what notices anything moved at all.
|
|
96
|
+
const changed = observed.sample();
|
|
97
|
+
const cursor = observed.revision;
|
|
98
|
+
// Kept, not handed out once. The hook can have more than one reader — a dev server
|
|
99
|
+
// agent polling and a browser panel open at the same time — and draining here gave
|
|
100
|
+
// each of them whichever events the other had not taken yet. Every event carries a
|
|
101
|
+
// seq, so a reader keeps what is new to it.
|
|
102
|
+
history.push(...observed.takeEvents());
|
|
103
|
+
if (history.length > HISTORY)
|
|
104
|
+
history.splice(0, history.length - HISTORY);
|
|
105
|
+
const events = history.slice();
|
|
106
|
+
// Described, not held: whoever reads this snapshot is usually not in the page, and the
|
|
107
|
+
// elements would only cross as empty objects anyway.
|
|
108
|
+
const dom = (id) => {
|
|
109
|
+
const described = observed.domFor(id);
|
|
110
|
+
return described.length ? withoutElements(described) : undefined;
|
|
111
|
+
};
|
|
112
|
+
// The observer can be older than this hook. The application hands its own over and the
|
|
113
|
+
// two are built separately, so a cursor is only offered when it can be honoured.
|
|
114
|
+
const cursors = typeof observed.changedSince === 'function';
|
|
115
|
+
// Everything, and the cursor to come back with. Also the answer for a consumer that
|
|
116
|
+
// has fallen further behind than the log reaches.
|
|
117
|
+
const whole = partial === false || since === undefined || !cursors || observed.outrun(since);
|
|
118
|
+
if (whole) {
|
|
119
|
+
// An older observer cannot say what was dropped after a revision, so a delta from
|
|
120
|
+
// it would quietly keep nodes that are gone. Everything, every time, is correct.
|
|
121
|
+
if (partial && !cursors) {
|
|
122
|
+
return serializeGraph(observed.graph, Date.now(), {
|
|
123
|
+
ids: changed,
|
|
124
|
+
removed: observed.takeRemoved(),
|
|
125
|
+
events,
|
|
126
|
+
dom,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return serializeGraph(observed.graph, Date.now(), { events, dom, cursor });
|
|
130
|
+
}
|
|
131
|
+
return serializeGraph(observed.graph, Date.now(), {
|
|
132
|
+
ids: observed.changedSince(since),
|
|
133
|
+
removed: observed.removedSince(since),
|
|
134
|
+
events,
|
|
135
|
+
dom,
|
|
136
|
+
cursor,
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
host[HOOK] = hook;
|
|
141
|
+
return hook;
|
|
142
|
+
}
|