@fluixi/devtools 0.2.0-alpha.3 → 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.
Files changed (64) hide show
  1. package/dist/callsite.cjs +72 -0
  2. package/dist/callsite.mjs +51 -0
  3. package/dist/change-view.cjs +134 -0
  4. package/dist/change-view.mjs +111 -0
  5. package/dist/copy.cjs +63 -0
  6. package/dist/copy.mjs +42 -0
  7. package/dist/describe.cjs +55 -0
  8. package/dist/describe.mjs +34 -0
  9. package/dist/detail-panel.cjs +307 -0
  10. package/dist/detail-panel.mjs +284 -0
  11. package/dist/diff.cjs +225 -0
  12. package/dist/diff.mjs +202 -0
  13. package/dist/dom.cjs +204 -0
  14. package/dist/dom.mjs +183 -0
  15. package/dist/export.cjs +221 -0
  16. package/dist/export.mjs +209 -0
  17. package/dist/float.cjs +232 -0
  18. package/dist/float.mjs +211 -0
  19. package/dist/format.cjs +175 -0
  20. package/dist/format.mjs +154 -0
  21. package/dist/graph-view.cjs +893 -0
  22. package/dist/graph-view.mjs +870 -0
  23. package/dist/highlight.cjs +140 -0
  24. package/dist/highlight.mjs +119 -0
  25. package/dist/history.cjs +95 -0
  26. package/dist/history.mjs +74 -0
  27. package/dist/hook.cjs +1562 -0
  28. package/dist/hook.mjs +1553 -0
  29. package/dist/index.cjs +4552 -0
  30. package/dist/index.mjs +4544 -0
  31. package/dist/inspector.cjs +688 -0
  32. package/dist/inspector.mjs +676 -0
  33. package/dist/instrument.cjs +497 -0
  34. package/dist/instrument.mjs +487 -0
  35. package/dist/kind-filter.cjs +172 -0
  36. package/dist/kind-filter.mjs +151 -0
  37. package/dist/menu.cjs +141 -0
  38. package/dist/menu.mjs +120 -0
  39. package/dist/observe.cjs +1352 -0
  40. package/dist/observe.mjs +1345 -0
  41. package/dist/palette.cjs +52 -0
  42. package/dist/palette.mjs +31 -0
  43. package/dist/path.cjs +45 -0
  44. package/dist/path.mjs +24 -0
  45. package/dist/plugin.cjs +87 -0
  46. package/dist/plugin.mjs +66 -0
  47. package/dist/plugins/context.cjs +98 -0
  48. package/dist/plugins/context.mjs +75 -0
  49. package/dist/plugins/directives.cjs +98 -0
  50. package/dist/plugins/directives.mjs +75 -0
  51. package/dist/plugins/index.cjs +162 -0
  52. package/dist/plugins/index.mjs +140 -0
  53. package/dist/source.cjs +111 -0
  54. package/dist/source.mjs +90 -0
  55. package/dist/timeline.cjs +350 -0
  56. package/dist/timeline.mjs +327 -0
  57. package/dist/tree.cjs +574 -0
  58. package/dist/tree.mjs +551 -0
  59. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  60. package/dist/value-pane.cjs +223 -0
  61. package/dist/value-pane.mjs +200 -0
  62. package/dist/wire.cjs +109 -0
  63. package/dist/wire.mjs +89 -0
  64. package/package.json +13 -6
@@ -0,0 +1,497 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/instrument.ts
21
+ var instrument_exports = {};
22
+ __export(instrument_exports, {
23
+ KIND_OF_BUILTIN: () => KIND_OF_BUILTIN,
24
+ createReactor: () => createReactor,
25
+ fmt: () => fmt,
26
+ nodeState: () => nodeState,
27
+ nodeVersion: () => nodeVersion,
28
+ short: () => short
29
+ });
30
+ module.exports = __toCommonJS(instrument_exports);
31
+ var import_signal = require("@fluixi/reactive/signal");
32
+ var import_store = require("@fluixi/reactive/store");
33
+
34
+ // src/source.ts
35
+ var MARKER = "__fx_source";
36
+ var COMPONENT_MARKER = "__fx_component";
37
+ var HOLE_MARKER = "__fx_hole";
38
+ var PROPS_MARKER = "__fx_props";
39
+ var MARKS = "__FLUIXI_DEVTOOLS_MARKS__";
40
+ var host = globalThis;
41
+ var shared = host[MARKS] ?? {
42
+ pending: null,
43
+ expiring: false,
44
+ components: /* @__PURE__ */ new Map()
45
+ };
46
+ host[MARKS] = shared;
47
+ function markReactiveSource(file, line, column, name) {
48
+ const location = locate(file, line, column);
49
+ if (shared.pending && location.external && !shared.pending.location?.external) return;
50
+ shared.pending = { name, location };
51
+ shared.expiring = false;
52
+ }
53
+ function locate(file, line, column) {
54
+ const external = !!file && (/^([a-zA-Z]:)?[\\/]/.test(file) || file.includes("node_modules/"));
55
+ return external ? { file, line, column, external } : { file, line, column };
56
+ }
57
+ function markComponentSource(name, file, line, column) {
58
+ const seen = shared.components.get(name);
59
+ const next = locate(file, line, column);
60
+ if (seen === void 0) {
61
+ shared.components.set(name, next);
62
+ return;
63
+ }
64
+ if (!seen || seen.file !== file || seen.line !== line) shared.components.set(name, null);
65
+ }
66
+ function componentSource(name) {
67
+ return shared.components.get(name) ?? void 0;
68
+ }
69
+ function takeReactiveSource() {
70
+ const mark = shared.pending;
71
+ if (mark) {
72
+ if (mark.name !== void 0) shared.pending = { location: mark.location };
73
+ if (!shared.expiring) {
74
+ shared.expiring = true;
75
+ queueMicrotask(() => {
76
+ shared.expiring = false;
77
+ shared.pending = null;
78
+ });
79
+ }
80
+ }
81
+ return mark;
82
+ }
83
+ var HOLES = /* @__PURE__ */ new WeakMap();
84
+ var HOLE_TAG = "__fx_at";
85
+ function markHole(accessor, line, column, name) {
86
+ if (accessor && (typeof accessor === "object" || typeof accessor === "function")) {
87
+ const at = name === void 0 ? { line, column } : { line, column, name };
88
+ HOLES.set(accessor, at);
89
+ try {
90
+ Object.defineProperty(accessor, HOLE_TAG, { value: at, configurable: true });
91
+ } catch {
92
+ }
93
+ }
94
+ shared.pending = null;
95
+ return accessor;
96
+ }
97
+ var PROPS = /* @__PURE__ */ new WeakMap();
98
+ function markProps(props, at) {
99
+ if (props && typeof props === "object") PROPS.set(props, at);
100
+ return props;
101
+ }
102
+ function installSourceMarker() {
103
+ if (typeof host[MARKER] !== "function") host[MARKER] = markReactiveSource;
104
+ if (typeof host[COMPONENT_MARKER] !== "function") host[COMPONENT_MARKER] = markComponentSource;
105
+ if (typeof host[HOLE_MARKER] !== "function") host[HOLE_MARKER] = markHole;
106
+ if (typeof host[PROPS_MARKER] !== "function") host[PROPS_MARKER] = markProps;
107
+ }
108
+
109
+ // src/format.ts
110
+ var MAX_DEPTH = 3;
111
+ var MAX_ENTRIES = 8;
112
+ function domName(v) {
113
+ if (typeof v?.nodeType !== "number" || typeof v.nodeName !== "string") return null;
114
+ return v.tagName ? `<${v.tagName.toLowerCase()}>` : `#${v.nodeName.toLowerCase()}`;
115
+ }
116
+ function fnName(v) {
117
+ return v.name ? `ƒ ${v.name}()` : "ƒ";
118
+ }
119
+ function className(v) {
120
+ const name = v.constructor?.name;
121
+ return name && name !== "Object" ? `${name} ` : "";
122
+ }
123
+ function primitive(v) {
124
+ if (v === null) return "null";
125
+ switch (typeof v) {
126
+ case "undefined":
127
+ return "undefined";
128
+ case "string":
129
+ return JSON.stringify(v);
130
+ case "number":
131
+ case "boolean":
132
+ return String(v);
133
+ case "bigint":
134
+ return `${v}n`;
135
+ case "symbol":
136
+ return v.toString();
137
+ case "function":
138
+ return fnName(v);
139
+ default:
140
+ return null;
141
+ }
142
+ }
143
+ function walk(value, depth, seen) {
144
+ const simple = primitive(value);
145
+ if (simple !== null) return simple;
146
+ const object = value;
147
+ if (seen.has(object)) return "[circular]";
148
+ const dom = domName(object);
149
+ if (dom) return dom;
150
+ if (object instanceof Date) return Number.isNaN(object.getTime()) ? "Invalid Date" : object.toISOString();
151
+ if (object instanceof RegExp) return String(object);
152
+ if (object instanceof Error) return `${object.name}: ${object.message}`;
153
+ if (object instanceof Promise) return "Promise";
154
+ if (ArrayBuffer.isView(object)) {
155
+ return `${className(object).trim()}(${object.length ?? ""})`;
156
+ }
157
+ if (depth >= MAX_DEPTH) return Array.isArray(object) ? "[…]" : "{…}";
158
+ seen.add(object);
159
+ try {
160
+ if (Array.isArray(object)) {
161
+ const shown2 = object.slice(0, MAX_ENTRIES).map((item) => walk(item, depth + 1, seen));
162
+ if (object.length > MAX_ENTRIES) shown2.push("…");
163
+ return `[${shown2.join(", ")}]`;
164
+ }
165
+ if (object instanceof Map) {
166
+ const shown2 = [];
167
+ for (const [k, v] of object) {
168
+ if (shown2.length === MAX_ENTRIES) {
169
+ shown2.push("…");
170
+ break;
171
+ }
172
+ shown2.push(`${walk(k, depth + 1, seen)} => ${walk(v, depth + 1, seen)}`);
173
+ }
174
+ return `Map(${object.size}) {${shown2.join(", ")}}`;
175
+ }
176
+ if (object instanceof Set) {
177
+ const shown2 = [];
178
+ for (const item of object) {
179
+ if (shown2.length === MAX_ENTRIES) {
180
+ shown2.push("…");
181
+ break;
182
+ }
183
+ shown2.push(walk(item, depth + 1, seen));
184
+ }
185
+ return `Set(${object.size}) {${shown2.join(", ")}}`;
186
+ }
187
+ const keys = Object.keys(object);
188
+ const shown = keys.slice(0, MAX_ENTRIES).map((key) => {
189
+ let read;
190
+ try {
191
+ read = walk(object[key], depth + 1, seen);
192
+ } catch {
193
+ read = "[unreadable]";
194
+ }
195
+ return `${key}: ${read}`;
196
+ });
197
+ if (keys.length > MAX_ENTRIES) shown.push("…");
198
+ return `${className(object)}{${shown.join(", ")}}`;
199
+ } finally {
200
+ seen.delete(object);
201
+ }
202
+ }
203
+ function formatValue(value, limit = 240) {
204
+ let text;
205
+ try {
206
+ text = walk(value, 0, /* @__PURE__ */ new Set());
207
+ } catch {
208
+ text = "[unreadable]";
209
+ }
210
+ return text.length > limit ? `${text.slice(0, limit - 1)}…` : text;
211
+ }
212
+ function shorten(text, limit = 18) {
213
+ return text.length > limit ? `${text.slice(0, limit - 1)}…` : text;
214
+ }
215
+
216
+ // src/instrument.ts
217
+ var $NODE = /* @__PURE__ */ Symbol.for("signal-node");
218
+ var KIND_OF_BUILTIN = {
219
+ Show: "control",
220
+ For: "control",
221
+ Index: "control",
222
+ Switch: "control",
223
+ Match: "control",
224
+ Portal: "control",
225
+ Dynamic: "control",
226
+ ErrorBoundary: "control",
227
+ Suspense: "control",
228
+ SuspenseList: "control",
229
+ Await: "control",
230
+ Router: "router",
231
+ Outlet: "router",
232
+ Redirect: "router",
233
+ Link: "router"
234
+ };
235
+ var CORE_STATE = { 0: "clean", 1: "check", 2: "dirty" };
236
+ function nodeVersion(n) {
237
+ return n.core && typeof n.core.version === "number" ? n.core.version : n.runs;
238
+ }
239
+ function nodeState(n) {
240
+ return n.core && typeof n.core.state === "number" ? CORE_STATE[n.core.state] : void 0;
241
+ }
242
+ var fmt = (v) => formatValue(v);
243
+ var short = (s, n = 18) => shorten(s, n);
244
+ function createReactor() {
245
+ installSourceMarker();
246
+ const graph = /* @__PURE__ */ new Map();
247
+ const runsAtLastSample = /* @__PURE__ */ new Map();
248
+ const unnamed = /* @__PURE__ */ new Set();
249
+ const consumerStack = [];
250
+ let seq = 0;
251
+ let dispose = () => {
252
+ };
253
+ let rootOwner = null;
254
+ const claims = (node, value) => {
255
+ for (const dep of node.deps) {
256
+ const other = graph.get(dep);
257
+ if (other?.read && other.read() === value) return false;
258
+ }
259
+ return true;
260
+ };
261
+ const forget = (id) => {
262
+ const owner = (0, import_signal.getOwner)() ?? rootOwner;
263
+ if (owner) {
264
+ (0, import_signal.runWithOwner)(
265
+ owner,
266
+ () => (0, import_signal.onCleanup)(() => {
267
+ graph.delete(id);
268
+ runsAtLastSample.delete(id);
269
+ unnamed.delete(id);
270
+ })
271
+ );
272
+ }
273
+ };
274
+ const recordRead = (sourceId) => {
275
+ const c = consumerStack[consumerStack.length - 1];
276
+ if (c != null) graph.get(c)?.deps.add(sourceId);
277
+ };
278
+ const recordWrite = (targetId) => {
279
+ const c = consumerStack[consumerStack.length - 1];
280
+ if (c != null && c !== targetId) graph.get(c)?.writes.add(targetId);
281
+ };
282
+ const base = (id, named, kind, fallback) => {
283
+ const mark = takeReactiveSource();
284
+ if (!named && !mark?.name) unnamed.add(id);
285
+ return {
286
+ id,
287
+ label: named ?? mark?.name ?? fallback,
288
+ kind,
289
+ deps: /* @__PURE__ */ new Set(),
290
+ writes: /* @__PURE__ */ new Set(),
291
+ runs: 0,
292
+ lastPulse: 0,
293
+ ...mark?.location ? { source: mark.location } : {}
294
+ };
295
+ };
296
+ const trackedCreateSignal = (value, options) => {
297
+ const id = seq++;
298
+ const [get, set] = (0, import_signal.createSignal)(value, options);
299
+ const node = base(id, options?.name, "state", `s${id}`);
300
+ node.read = () => (0, import_signal.untrack)(get);
301
+ node.detail = formatValue(value);
302
+ node.value = shorten(node.detail);
303
+ node.core = get[$NODE] ?? null;
304
+ graph.set(id, node);
305
+ forget(id);
306
+ const read = () => {
307
+ recordRead(id);
308
+ return get();
309
+ };
310
+ const write = (v) => {
311
+ recordWrite(id);
312
+ return set(typeof v === "function" ? v((0, import_signal.untrack)(get)) : v);
313
+ };
314
+ return [read, write];
315
+ };
316
+ const trackedCreateMemo = (fn, value, options) => {
317
+ const id = seq++;
318
+ const node = base(id, options?.name, "memo", `m${id}`);
319
+ graph.set(id, node);
320
+ forget(id);
321
+ const m = (0, import_signal.createMemo)(() => {
322
+ node.core ??= import_signal.Signal.subtle.currentComputed();
323
+ node.deps.clear();
324
+ node.writes.clear();
325
+ node.runs++;
326
+ consumerStack.push(id);
327
+ try {
328
+ return fn();
329
+ } finally {
330
+ consumerStack.pop();
331
+ }
332
+ }, value, options);
333
+ node.read = () => (0, import_signal.untrack)(m);
334
+ return () => {
335
+ recordRead(id);
336
+ return m();
337
+ };
338
+ };
339
+ const trackedCreateEffect = (fn, options) => {
340
+ const id = seq++;
341
+ const node = base(id, options?.name, "effect", `e${id}`);
342
+ graph.set(id, node);
343
+ forget(id);
344
+ (0, import_signal.createEffect)(() => {
345
+ node.core ??= import_signal.Signal.subtle.currentComputed();
346
+ node.deps.clear();
347
+ node.writes.clear();
348
+ node.runs++;
349
+ node.lastPulse = performance.now();
350
+ consumerStack.push(id);
351
+ try {
352
+ fn();
353
+ } finally {
354
+ consumerStack.pop();
355
+ }
356
+ });
357
+ };
358
+ const trackedCreateStore = (initial, options) => {
359
+ const id = seq++;
360
+ const [proxy, setter] = (0, import_store.createStore)(initial, { immutable: true, ...options });
361
+ const node = base(id, options?.name, "store", `store${id}`);
362
+ node.read = () => {
363
+ try {
364
+ return (0, import_signal.untrack)(() => JSON.stringify(proxy));
365
+ } catch {
366
+ return "{…}";
367
+ }
368
+ };
369
+ node.value = "{…}";
370
+ graph.set(id, node);
371
+ forget(id);
372
+ const recording = new Proxy(proxy, {
373
+ get(t, p, r) {
374
+ recordRead(id);
375
+ return Reflect.get(t, p, r);
376
+ }
377
+ });
378
+ const write = (...args) => {
379
+ recordWrite(id);
380
+ return setter(...args);
381
+ };
382
+ return [recording, write];
383
+ };
384
+ const trackedCreateResource = (...args) => {
385
+ const id = seq++;
386
+ const last = args[args.length - 1];
387
+ const name = last && typeof last === "object" && !Array.isArray(last) && typeof last !== "function" ? last.name : void 0;
388
+ const node = base(id, name, "resource", `res${id}`);
389
+ const [data, actions] = (0, import_signal.createResource)(...args);
390
+ node.read = () => {
391
+ try {
392
+ return (0, import_signal.untrack)(() => data.loading ? "⏳ loading" : JSON.stringify(data.latest));
393
+ } catch {
394
+ return "?";
395
+ }
396
+ };
397
+ node.value = "⏳ loading";
398
+ graph.set(id, node);
399
+ forget(id);
400
+ const accessor = (() => {
401
+ recordRead(id);
402
+ return data();
403
+ });
404
+ for (const k of ["loading", "error", "latest", "state"]) {
405
+ Object.defineProperty(accessor, k, { get: () => data[k] });
406
+ }
407
+ return [accessor, actions];
408
+ };
409
+ const trackedSignal = (value, options) => {
410
+ const [read, write] = trackedCreateSignal(value, options);
411
+ Object.defineProperty(read, "set", { value: write });
412
+ return read;
413
+ };
414
+ const trackedMemo = trackedCreateMemo;
415
+ const trackedEffect = trackedCreateEffect;
416
+ const trackedStore = (initial, options) => {
417
+ const [state, set] = trackedCreateStore(initial, options);
418
+ return new Proxy(state, {
419
+ get: (target, key) => key === "set" ? set : target[key],
420
+ has: (target, key) => key === "set" || Reflect.has(target, key)
421
+ });
422
+ };
423
+ const trackedResource = (...args) => {
424
+ const [accessor, controls] = trackedCreateResource(...args);
425
+ return Object.assign(accessor, controls);
426
+ };
427
+ const api = {
428
+ createSignal: trackedCreateSignal,
429
+ createMemo: trackedCreateMemo,
430
+ createEffect: trackedCreateEffect,
431
+ createStore: trackedCreateStore,
432
+ createResource: trackedCreateResource,
433
+ signal: trackedSignal,
434
+ memo: trackedMemo,
435
+ store: trackedStore,
436
+ effect: trackedEffect,
437
+ resource: trackedResource
438
+ };
439
+ return {
440
+ graph,
441
+ run(setup) {
442
+ dispose();
443
+ graph.clear();
444
+ runsAtLastSample.clear();
445
+ unnamed.clear();
446
+ seq = 0;
447
+ consumerStack.length = 0;
448
+ (0, import_signal.createRoot)((d) => {
449
+ dispose = d;
450
+ rootOwner = (0, import_signal.getOwner)();
451
+ setup(api);
452
+ });
453
+ },
454
+ sample() {
455
+ const changed = [];
456
+ const now = Date.now();
457
+ for (const node of graph.values()) {
458
+ if (!node.read) {
459
+ const seen = runsAtLastSample.get(node.id);
460
+ if (seen !== void 0 && node.runs > seen) {
461
+ node.lastPulse = now;
462
+ changed.push(node.id);
463
+ }
464
+ runsAtLastSample.set(node.id, node.runs);
465
+ continue;
466
+ }
467
+ const raw = node.read();
468
+ const stamped = raw?.$name;
469
+ if (node.kind === "memo" && typeof stamped === "string" && stamped && claims(node, raw)) {
470
+ node.kind = KIND_OF_BUILTIN[stamped] ?? "component";
471
+ node.declaredAt = componentSource(stamped);
472
+ node.source ??= node.declaredAt;
473
+ if (unnamed.has(node.id)) {
474
+ node.label = stamped;
475
+ unnamed.delete(node.id);
476
+ }
477
+ }
478
+ const detail = formatValue(raw);
479
+ const next = shorten(detail);
480
+ if (next !== node.value || detail !== node.detail) {
481
+ node.detail = detail;
482
+ node.value = next;
483
+ node.runs++;
484
+ node.lastPulse = now;
485
+ changed.push(node.id);
486
+ }
487
+ runsAtLastSample.set(node.id, node.runs);
488
+ }
489
+ return changed;
490
+ },
491
+ dispose() {
492
+ dispose();
493
+ dispose = () => {
494
+ };
495
+ }
496
+ };
497
+ }