@plitzi/sdk-dev-tools 0.36.0 → 0.36.2
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/CHANGELOG.md +22 -0
- package/dist/DevToolsContainer.mjs +54 -53
- package/dist/DevToolsRoot.d.ts +18 -0
- package/dist/DevToolsRoot.mjs +43 -0
- package/dist/components/DevToolsPanel/DevToolsBody.mjs +33 -31
- package/dist/components/DevToolsPanel/DevToolsHeader.mjs +5 -0
- package/dist/components/DevToolsPanel/tabs/ActionsViewer/components/RunDetail/RunDetail.mjs +14 -14
- package/dist/components/DevToolsPanel/tabs/ActionsViewer/helpers.d.ts +0 -1
- package/dist/components/DevToolsPanel/tabs/ActionsViewer/helpers.mjs +1 -1
- package/dist/components/DevToolsPanel/tabs/CacheViewer/CacheViewer.d.ts +12 -0
- package/dist/components/DevToolsPanel/tabs/CacheViewer/CacheViewer.mjs +91 -0
- package/dist/components/DevToolsPanel/tabs/CacheViewer/components/CacheRow/CacheRow.d.ts +16 -0
- package/dist/components/DevToolsPanel/tabs/CacheViewer/components/CacheRow/CacheRow.mjs +87 -0
- package/dist/components/DevToolsPanel/tabs/CacheViewer/components/CacheRow/index.d.ts +3 -0
- package/dist/components/DevToolsPanel/tabs/CacheViewer/components/CacheRow/index.mjs +5 -0
- package/dist/components/DevToolsPanel/tabs/CacheViewer/index.d.ts +2 -0
- package/dist/components/DevToolsPanel/tabs/CacheViewer/index.mjs +5 -0
- package/dist/components/DevToolsPanel/tabs/Logs/categories/LogInteraction/BodyHeader.mjs +1 -1
- package/dist/components/DevToolsPanel/tabs/StoreViewer/StoreViewer.mjs +52 -54
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessMark/FreshnessMark.d.ts +16 -0
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessMark/FreshnessMark.mjs +13 -0
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessMark/index.d.ts +3 -0
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/{FreshnessPanel → FreshnessMark}/index.mjs +2 -2
- package/dist/components/DevToolsPanel/tabs/StoreViewer/helpers/renderFreshnessKey.d.ts +14 -0
- package/dist/components/DevToolsPanel/tabs/StoreViewer/helpers/renderFreshnessKey.mjs +18 -0
- package/dist/components/DevToolsPanel/tabs/TracingViewer/helpers.d.ts +5 -0
- package/dist/components/DevToolsPanel/tabs/TracingViewer/helpers.mjs +65 -55
- package/dist/components/PayloadView/PayloadView.d.ts +11 -0
- package/dist/components/{DevToolsPanel/tabs/ActionsViewer/components/PayloadView → PayloadView}/PayloadView.mjs +1 -1
- package/dist/components/PayloadView/index.mjs +5 -0
- package/dist/freshness/describeQueryPath.d.ts +22 -0
- package/dist/freshness/describeQueryPath.mjs +22 -0
- package/dist/freshness/formatDuration.d.ts +3 -0
- package/dist/freshness/formatDuration.mjs +9 -0
- package/dist/freshness/index.d.ts +8 -0
- package/dist/freshness/index.mjs +6 -0
- package/dist/freshness/rows.d.ts +42 -0
- package/dist/freshness/rows.mjs +29 -0
- package/dist/freshness/useFreshnessByStore.d.ts +15 -0
- package/dist/freshness/useFreshnessByStore.mjs +20 -0
- package/dist/freshness/useSecondsClock.d.ts +8 -0
- package/dist/freshness/useSecondsClock.mjs +12 -0
- package/dist/scope/helpers.d.ts +1 -0
- package/dist/scope/helpers.mjs +7 -7
- package/dist/scope/useScope.d.ts +3 -1
- package/dist/scope/useScope.mjs +21 -18
- package/dist/useRegisterQueriesStore.mjs +3 -3
- package/package.json +89 -49
- package/dist/components/DevToolsPanel/tabs/ActionsViewer/components/PayloadView/PayloadView.d.ts +0 -6
- package/dist/components/DevToolsPanel/tabs/ActionsViewer/components/PayloadView/index.mjs +0 -5
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessPanel/FreshnessPanel.d.ts +0 -11
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessPanel/FreshnessPanel.mjs +0 -49
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessPanel/components/FreshnessRow/FreshnessRow.d.ts +0 -7
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessPanel/components/FreshnessRow/FreshnessRow.mjs +0 -43
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessPanel/components/FreshnessRow/index.d.ts +0 -3
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessPanel/components/FreshnessRow/index.mjs +0 -5
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessPanel/helpers.d.ts +0 -14
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessPanel/helpers.mjs +0 -18
- package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessPanel/index.d.ts +0 -3
- package/dist/scope/useFreshnessRecords.d.ts +0 -3
- package/dist/scope/useFreshnessRecords.mjs +0 -8
- /package/dist/components/{DevToolsPanel/tabs/ActionsViewer/components/PayloadView → PayloadView}/index.d.ts +0 -0
|
@@ -6,7 +6,7 @@ import { formatDate as o } from "@plitzi/sdk-shared/helpers";
|
|
|
6
6
|
//#region src/components/DevToolsPanel/tabs/Logs/categories/LogInteraction/BodyHeader.tsx
|
|
7
7
|
var s = ({ triggerName: s, startTime: c, endTime: l, duration: u, elementId: d, hostElementId: f }) => {
|
|
8
8
|
let [p] = i("schema.flat"), m = t(() => d ? a(p, d) : void 0, [d, p]), h = t(() => o(c, "HH:mm:ss.SSS"), [c]), g = t(() => o(l, "HH:mm:ss.SSS"), [l]), _ = t(() => {
|
|
9
|
-
if (
|
|
9
|
+
if (typeof document < "u") return document.querySelector(`[data-id="${d}"]`);
|
|
10
10
|
}, [d]), v = e(() => {
|
|
11
11
|
_?.scrollIntoView({
|
|
12
12
|
behavior: "smooth",
|
|
@@ -1,64 +1,62 @@
|
|
|
1
|
-
import e from "
|
|
2
|
-
import t from "
|
|
3
|
-
import n from "
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import d from "
|
|
11
|
-
import
|
|
12
|
-
import m from "@
|
|
13
|
-
import
|
|
14
|
-
import
|
|
1
|
+
import e from "../../../../freshness/useFreshnessByStore.mjs";
|
|
2
|
+
import t from "../../../../freshness/useSecondsClock.mjs";
|
|
3
|
+
import { useSelectedStore as n, useSelectedStoreEntry as r } from "../../../../scope/useScope.mjs";
|
|
4
|
+
import i from "./helpers/mapFunctionValues.mjs";
|
|
5
|
+
import a from "./helpers/renderFreshnessKey.mjs";
|
|
6
|
+
import o from "./helpers/renderFunctionValue.mjs";
|
|
7
|
+
import s from "../../../../scope/useStoreState.mjs";
|
|
8
|
+
import c from "@plitzi/plitzi-ui/hooks/useStorage";
|
|
9
|
+
import l from "clsx";
|
|
10
|
+
import { use as u, useCallback as d, useMemo as f } from "react";
|
|
11
|
+
import p from "@plitzi/sdk-shared/theme/useTheme";
|
|
12
|
+
import m from "@plitzi/sdk-shared/devTools/DevToolsContext";
|
|
13
|
+
import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
14
|
+
import _ from "@uiw/react-json-view";
|
|
15
|
+
import * as v from "@uiw/react-json-view/vscode";
|
|
16
|
+
import { emptyObject as y } from "@plitzi/sdk-shared/helpers/utils";
|
|
15
17
|
//#region src/components/DevToolsPanel/tabs/StoreViewer/StoreViewer.tsx
|
|
16
|
-
var
|
|
17
|
-
...
|
|
18
|
+
var b = {
|
|
19
|
+
...v.vscodeTheme,
|
|
18
20
|
width: "100%",
|
|
19
21
|
height: "100%",
|
|
20
22
|
overflow: "auto",
|
|
21
23
|
padding: "8px",
|
|
22
24
|
fontSize: "14px"
|
|
23
|
-
},
|
|
24
|
-
let { resolvedTheme:
|
|
25
|
-
return /* @__PURE__ */
|
|
25
|
+
}, x = (e) => l("cursor-pointer rounded px-2 py-0.5 font-medium transition-colors", e ? "bg-violet-500/15 text-violet-600 dark:text-violet-300" : "text-zinc-500 hover:bg-zinc-200/70 hover:text-zinc-800 dark:text-zinc-400 dark:hover:bg-zinc-700/50 dark:hover:text-zinc-100"), S = {}, C = [], w = ({ elementSelected: l }) => {
|
|
26
|
+
let { resolvedTheme: v } = p(), { getData: w } = u(m), T = r(), E = n(), [D, O] = c("plitzi-sdk.dev-tools.store.view", "own"), k = s(l ? void 0 : E, D === "merged"), A = d(() => O("own"), [O]), j = d(() => O("merged"), [O]), M = l ? w?.(`getElementDataSource-${l}`) : k, N = f(() => i(M), [M]), P = f(() => T ? [T] : C, [T]), F = e(P)[0]?.records ?? S, I = f(() => Object.values(F).reduce((e, t) => Math.max(e, t.updatedAt), 0), [F]), L = t(Object.keys(F).length > 0, I), R = f(() => a(F, L), [F, L]);
|
|
27
|
+
return /* @__PURE__ */ g("div", {
|
|
26
28
|
className: "flex h-full w-full flex-col",
|
|
27
|
-
children: [
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
displayDataTypes: !1,
|
|
58
|
-
children: /* @__PURE__ */ f(m.String, { render: n })
|
|
59
|
-
})
|
|
60
|
-
]
|
|
29
|
+
children: [!l && /* @__PURE__ */ g("div", {
|
|
30
|
+
className: "flex shrink-0 items-center gap-1 border-b border-zinc-200 px-2 py-1 text-[11px] dark:border-zinc-800",
|
|
31
|
+
children: [
|
|
32
|
+
/* @__PURE__ */ h("span", {
|
|
33
|
+
className: "mr-1 text-zinc-400 dark:text-zinc-500",
|
|
34
|
+
children: "View"
|
|
35
|
+
}),
|
|
36
|
+
/* @__PURE__ */ h("button", {
|
|
37
|
+
className: x(D === "own"),
|
|
38
|
+
onClick: A,
|
|
39
|
+
title: "Only this scope's own layer",
|
|
40
|
+
children: "Own"
|
|
41
|
+
}),
|
|
42
|
+
/* @__PURE__ */ h("button", {
|
|
43
|
+
className: x(D === "merged"),
|
|
44
|
+
onClick: j,
|
|
45
|
+
title: "Own layer merged over the parent scope chain",
|
|
46
|
+
children: "Merged"
|
|
47
|
+
})
|
|
48
|
+
]
|
|
49
|
+
}), /* @__PURE__ */ g(_, {
|
|
50
|
+
value: N ?? y,
|
|
51
|
+
style: v === "dark" ? b : void 0,
|
|
52
|
+
enableClipboard: !1,
|
|
53
|
+
indentWidth: 15,
|
|
54
|
+
collapsed: 2,
|
|
55
|
+
displayObjectSize: !1,
|
|
56
|
+
displayDataTypes: !1,
|
|
57
|
+
children: [/* @__PURE__ */ h(_.String, { render: o }), /* @__PURE__ */ h(_.KeyName, { render: R })]
|
|
58
|
+
})]
|
|
61
59
|
});
|
|
62
60
|
};
|
|
63
61
|
//#endregion
|
|
64
|
-
export {
|
|
62
|
+
export { w as default };
|
package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessMark/FreshnessMark.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PathFreshness } from '@plitzi/nexus';
|
|
2
|
+
export type FreshnessMarkProps = {
|
|
3
|
+
record: PathFreshness;
|
|
4
|
+
/** A clock the caller moves, so every mark on the tree counts down in step. */
|
|
5
|
+
now: number;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* What a path in the state tree is worth in time: how long before it stops being current, or that it already has.
|
|
9
|
+
*
|
|
10
|
+
* On the path itself, because the question a reader arrives at the tree with is about the state in front of them —
|
|
11
|
+
* which of these is cached, and for how much longer. A path with no mark was written with no `ttl` at all, which is
|
|
12
|
+
* every path unless somebody asked for one. The rest of what there is to say about it is the Cache tab's job, so
|
|
13
|
+
* nothing here hides behind a tooltip.
|
|
14
|
+
*/
|
|
15
|
+
declare const FreshnessMark: ({ record: { expiresAt }, now }: FreshnessMarkProps) => import("react").JSX.Element;
|
|
16
|
+
export default FreshnessMark;
|
package/dist/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessMark/FreshnessMark.mjs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import e from "../../../../../../freshness/formatDuration.mjs";
|
|
2
|
+
import t from "clsx";
|
|
3
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessMark/FreshnessMark.tsx
|
|
5
|
+
var r = ({ record: { expiresAt: r }, now: i }) => {
|
|
6
|
+
let a = i >= r, o = Number.isFinite(r) ? `${e(r - i)} left` : "no expiry";
|
|
7
|
+
return /* @__PURE__ */ n("span", {
|
|
8
|
+
className: t("ml-1 rounded px-1 align-middle text-[10px] font-medium", a ? "bg-amber-500/15 text-amber-700 dark:text-amber-300" : "bg-emerald-500/15 text-emerald-700 dark:text-emerald-300"),
|
|
9
|
+
children: a ? "stale" : o
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { r as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import e from "./
|
|
2
|
-
//#region src/components/DevToolsPanel/tabs/StoreViewer/components/
|
|
1
|
+
import e from "./FreshnessMark.mjs";
|
|
2
|
+
//#region src/components/DevToolsPanel/tabs/StoreViewer/components/FreshnessMark/index.ts
|
|
3
3
|
var t = e;
|
|
4
4
|
//#endregion
|
|
5
5
|
export { t as default };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PathFreshness } from '@plitzi/nexus';
|
|
2
|
+
import { default as JsonView } from '@uiw/react-json-view';
|
|
3
|
+
import { ComponentProps } from 'react';
|
|
4
|
+
/** Taken from the component rather than from a type the package does not export at its root. */
|
|
5
|
+
export type FreshnessKeyRenderer = NonNullable<ComponentProps<typeof JsonView.KeyName>['render']>;
|
|
6
|
+
/**
|
|
7
|
+
* The tree's key names, with a countdown on the paths that have one.
|
|
8
|
+
*
|
|
9
|
+
* Only the path a record was written AT is marked, never the ones it covers: a record answers for its whole subtree,
|
|
10
|
+
* so marking those too would say that every field under a cached answer had a TTL of its own. Returning nothing
|
|
11
|
+
* leaves the key to the viewer's own renderer, which is every path nobody gave a `ttl`.
|
|
12
|
+
*/
|
|
13
|
+
declare const renderFreshnessKey: (records: Readonly<Partial<Record<string, PathFreshness>>>, now: number) => FreshnessKeyRenderer;
|
|
14
|
+
export default renderFreshnessKey;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import e from "../components/FreshnessMark/index.mjs";
|
|
2
|
+
import { Fragment as t, jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/DevToolsPanel/tabs/StoreViewer/helpers/renderFreshnessKey.tsx
|
|
4
|
+
var i = (i, a) => (o, { keys: s }) => {
|
|
5
|
+
let c = i[(s ?? []).join(".")];
|
|
6
|
+
if (!c) return null;
|
|
7
|
+
let { className: l, style: u, children: d } = o;
|
|
8
|
+
return /* @__PURE__ */ r(t, { children: [/* @__PURE__ */ n("span", {
|
|
9
|
+
className: l,
|
|
10
|
+
style: u,
|
|
11
|
+
children: d
|
|
12
|
+
}), /* @__PURE__ */ n(e, {
|
|
13
|
+
record: c,
|
|
14
|
+
now: a
|
|
15
|
+
})] });
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { i as default };
|
|
@@ -97,6 +97,11 @@ export type TreeIndex = {
|
|
|
97
97
|
base: Map<string, number>;
|
|
98
98
|
children: Map<string, string[]>;
|
|
99
99
|
elementOf: Map<string, string>;
|
|
100
|
+
/** When each instance was on the page, for the ones whose presence is not the whole timeline. */
|
|
101
|
+
lifetime: Map<string, {
|
|
102
|
+
mountedAt: number;
|
|
103
|
+
unmountedAt: number;
|
|
104
|
+
}>;
|
|
100
105
|
};
|
|
101
106
|
export declare const buildTreeIndex: (tree: TracingTree) => TreeIndex;
|
|
102
107
|
export declare const buildFlameModel: (commit: CommitEntry, tree: TracingTree, flat: Record<string, Element> | undefined, index?: TreeIndex) => FlameModel;
|
|
@@ -66,21 +66,31 @@ var t = (e) => {
|
|
|
66
66
|
}, g = (e, t) => t?.[e]?.definition.type ?? "unknown", _ = (t, n) => {
|
|
67
67
|
let r = e(n?.[t], "definition.initialState.visibility", !0);
|
|
68
68
|
return r !== !1 && r !== "false";
|
|
69
|
-
}, v = (e, t) => t === "self" ? e.selfDuration : e.actualDuration, y = .01, b = 1e-6, x = (e) => {
|
|
70
|
-
let
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
}, v = (e, t) => t === "self" ? e.selfDuration : e.actualDuration, y = .01, b = 1e-6, x = (e, t, n) => {
|
|
70
|
+
let r = e.lifetime.get(t);
|
|
71
|
+
return !r || r.mountedAt <= n && n < r.unmountedAt;
|
|
72
|
+
}, S = (e) => {
|
|
73
|
+
let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
|
|
74
|
+
for (let a of Object.keys(e)) {
|
|
75
|
+
let { parentId: o, baseDuration: s, elementId: c, mountedAt: l, unmountedAt: u } = e[a];
|
|
76
|
+
t.set(a, o), n.set(a, s), r.set(a, c), (l !== void 0 || u !== void 0) && i.set(a, {
|
|
77
|
+
mountedAt: l ?? 0,
|
|
78
|
+
unmountedAt: u ?? Infinity
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
let a = /* @__PURE__ */ new Map();
|
|
73
82
|
for (let [e, n] of t) if (n !== void 0 && t.has(n)) {
|
|
74
|
-
let t =
|
|
75
|
-
t ? t.push(e) :
|
|
83
|
+
let t = a.get(n);
|
|
84
|
+
t ? t.push(e) : a.set(n, [e]);
|
|
76
85
|
}
|
|
77
86
|
return {
|
|
78
87
|
parent: t,
|
|
79
88
|
base: n,
|
|
80
|
-
children:
|
|
81
|
-
elementOf: r
|
|
89
|
+
children: a,
|
|
90
|
+
elementOf: r,
|
|
91
|
+
lifetime: i
|
|
82
92
|
};
|
|
83
|
-
},
|
|
93
|
+
}, C = (e, t) => {
|
|
84
94
|
let { parent: n } = t, r = new Map(e.elements.map((e) => [e.id, e])), i = /* @__PURE__ */ new Map();
|
|
85
95
|
for (let t of e.elements) i.set(t.id, t.actualDuration);
|
|
86
96
|
for (let t of e.elements) {
|
|
@@ -100,62 +110,62 @@ var t = (e) => {
|
|
|
100
110
|
self: i,
|
|
101
111
|
roots: [...a]
|
|
102
112
|
};
|
|
103
|
-
},
|
|
104
|
-
let { children: i, base: a, elementOf: o } = r, { rendered: s, self: c, roots: l } =
|
|
113
|
+
}, w = (e, t, n, r = S(t)) => {
|
|
114
|
+
let { children: i, base: a, elementOf: o } = r, { rendered: s, self: c, roots: l } = C(e, r), u = (e) => {
|
|
105
115
|
let t = a.get(e) ?? 0;
|
|
106
116
|
if (t > 0) return t;
|
|
107
117
|
let n = s.get(e)?.actualDuration ?? 0;
|
|
108
118
|
return n > 0 ? n : y;
|
|
109
|
-
}, d = [], f = [], p = 0, m = 0, v = 0,
|
|
119
|
+
}, d = [], f = [], p = 0, m = 0, v = 0, w = [], T = l.map(u), E = T.reduce((e, t) => e + t, 0) || 1, D = 0;
|
|
110
120
|
for (l.forEach((e, t) => {
|
|
111
|
-
let n = (
|
|
112
|
-
|
|
121
|
+
let n = (T[t] || y) / E;
|
|
122
|
+
w.push({
|
|
113
123
|
id: e,
|
|
114
124
|
parentId: void 0,
|
|
115
|
-
x:
|
|
125
|
+
x: D,
|
|
116
126
|
width: n,
|
|
117
127
|
depth: 0,
|
|
118
128
|
ancestorRendered: !1
|
|
119
|
-
}),
|
|
120
|
-
}),
|
|
121
|
-
let
|
|
122
|
-
if (
|
|
123
|
-
let { id:
|
|
124
|
-
|
|
125
|
-
let
|
|
129
|
+
}), D += n;
|
|
130
|
+
}), w.reverse(); w.length > 0;) {
|
|
131
|
+
let t = w.pop();
|
|
132
|
+
if (t === void 0) break;
|
|
133
|
+
let { id: l, parentId: S, x: C, width: T, depth: E, ancestorRendered: D } = t, O = s.get(l), k = c.get(l) ?? 0, A = O ? k > b ? "rendered" : "bubbled" : "hatched", j = A === "rendered" && !D;
|
|
134
|
+
A === "rendered" && (m += k, v += 1), j && f.push(l), p = Math.max(p, E);
|
|
135
|
+
let M = o.get(l) ?? O?.elementId ?? l;
|
|
126
136
|
d.push({
|
|
127
|
-
id:
|
|
128
|
-
elementId:
|
|
129
|
-
name: h(
|
|
130
|
-
type: g(
|
|
131
|
-
state:
|
|
132
|
-
visible: _(
|
|
133
|
-
trigger:
|
|
134
|
-
phase:
|
|
135
|
-
actualDuration:
|
|
136
|
-
baseDuration: a.get(
|
|
137
|
-
selfDuration:
|
|
138
|
-
depth:
|
|
139
|
-
parentId:
|
|
140
|
-
changedProps:
|
|
141
|
-
x:
|
|
142
|
-
width:
|
|
137
|
+
id: l,
|
|
138
|
+
elementId: M,
|
|
139
|
+
name: h(M, n),
|
|
140
|
+
type: g(M, n),
|
|
141
|
+
state: A,
|
|
142
|
+
visible: _(M, n),
|
|
143
|
+
trigger: j,
|
|
144
|
+
phase: O?.phase,
|
|
145
|
+
actualDuration: O?.actualDuration ?? 0,
|
|
146
|
+
baseDuration: a.get(l) ?? O?.baseDuration ?? 0,
|
|
147
|
+
selfDuration: k,
|
|
148
|
+
depth: E,
|
|
149
|
+
parentId: S,
|
|
150
|
+
changedProps: O?.changedProps,
|
|
151
|
+
x: C,
|
|
152
|
+
width: T
|
|
143
153
|
});
|
|
144
|
-
let
|
|
145
|
-
if (
|
|
146
|
-
let
|
|
147
|
-
|
|
148
|
-
let
|
|
149
|
-
|
|
154
|
+
let N = (i.get(l) ?? []).filter((t) => s.has(t) || x(r, t, e.commitId));
|
|
155
|
+
if (N.length === 0) continue;
|
|
156
|
+
let P = N.map(u), F = P.reduce((e, t) => e + t, 0), I = Math.max(u(l), F) || 1, L = C, R = [];
|
|
157
|
+
N.forEach((e, t) => {
|
|
158
|
+
let n = (P[t] || y) / I * T;
|
|
159
|
+
R.push({
|
|
150
160
|
id: e,
|
|
151
|
-
parentId:
|
|
152
|
-
x:
|
|
153
|
-
width:
|
|
154
|
-
depth:
|
|
155
|
-
ancestorRendered:
|
|
156
|
-
}),
|
|
161
|
+
parentId: l,
|
|
162
|
+
x: L,
|
|
163
|
+
width: n,
|
|
164
|
+
depth: E + 1,
|
|
165
|
+
ancestorRendered: D || A === "rendered"
|
|
166
|
+
}), L += n;
|
|
157
167
|
});
|
|
158
|
-
for (let e =
|
|
168
|
+
for (let e = R.length - 1; e >= 0; --e) w.push(R[e]);
|
|
159
169
|
}
|
|
160
170
|
return {
|
|
161
171
|
nodes: d,
|
|
@@ -164,10 +174,10 @@ var t = (e) => {
|
|
|
164
174
|
renderedCount: v,
|
|
165
175
|
triggers: f
|
|
166
176
|
};
|
|
167
|
-
},
|
|
168
|
-
let r =
|
|
177
|
+
}, T = (e, t, n) => {
|
|
178
|
+
let r = S(t), i = /* @__PURE__ */ new Map();
|
|
169
179
|
for (let t of e) {
|
|
170
|
-
let { self: e } =
|
|
180
|
+
let { self: e } = C(t, r);
|
|
171
181
|
for (let n of t.elements) {
|
|
172
182
|
let t = e.get(n.id) ?? 0;
|
|
173
183
|
if (t <= b) continue;
|
|
@@ -194,4 +204,4 @@ var t = (e) => {
|
|
|
194
204
|
}));
|
|
195
205
|
};
|
|
196
206
|
//#endregion
|
|
197
|
-
export { d as BUBBLED_COLOR, a as COMMIT_ORIGIN_BADGE, i as COMMIT_ORIGIN_LABEL, o as COMMIT_ORIGIN_LEGEND, u as DURATION_LEGEND, f as HATCH_STYLE, n as SSR_COMMIT_ID,
|
|
207
|
+
export { d as BUBBLED_COLOR, a as COMMIT_ORIGIN_BADGE, i as COMMIT_ORIGIN_LABEL, o as COMMIT_ORIGIN_LEGEND, u as DURATION_LEGEND, f as HATCH_STYLE, n as SSR_COMMIT_ID, w as buildFlameModel, T as buildHotspots, S as buildTreeIndex, r as commitOrigin, l as durationColor, _ as elementVisible, s as formatMs, c as formatPercent, p as frameColor, m as frameTextColor, v as rowDuration };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type PayloadViewProps = {
|
|
2
|
+
value: unknown;
|
|
3
|
+
};
|
|
4
|
+
/**
|
|
5
|
+
* A value, read the way the panel reads values: the same JSON viewer everywhere, wearing the panel's theme.
|
|
6
|
+
*
|
|
7
|
+
* Shared rather than per tab because the viewer ships a light palette and nothing else — on a dark panel its keys
|
|
8
|
+
* come out near-black on near-black — and every tab that shows a payload had to remember to dress it.
|
|
9
|
+
*/
|
|
10
|
+
declare const PayloadView: ({ value }: PayloadViewProps) => import("react").JSX.Element;
|
|
11
|
+
export default PayloadView;
|
|
@@ -2,7 +2,7 @@ import e from "@plitzi/sdk-shared/theme/useTheme";
|
|
|
2
2
|
import { jsx as t } from "react/jsx-runtime";
|
|
3
3
|
import n from "@uiw/react-json-view";
|
|
4
4
|
import * as r from "@uiw/react-json-view/vscode";
|
|
5
|
-
//#region src/components/
|
|
5
|
+
//#region src/components/PayloadView/PayloadView.tsx
|
|
6
6
|
var i = {
|
|
7
7
|
...r.vscodeTheme,
|
|
8
8
|
width: "100%",
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { DescribePath } from './rows';
|
|
2
|
+
/**
|
|
3
|
+
* A query cache path, read as the request it holds and as what is keeping it.
|
|
4
|
+
*
|
|
5
|
+
* The cache keys its entries by a hash of the request, because a URL is full of the store's path separator — so the
|
|
6
|
+
* path alone (`entries.22yn2ezdarx`) says nothing about which provider asked. The entry itself carries the URL and the
|
|
7
|
+
* tags, and a provider's tag is its element id.
|
|
8
|
+
*
|
|
9
|
+
* The usage is the other half, and the one that stops a panel reading as a leak: an answer nobody renders is kept on
|
|
10
|
+
* purpose, so that coming back within the grace period paints at once. Saying which of the two a row is — and when the
|
|
11
|
+
* grace period runs out — is the difference between "this page is holding rubbish" and "this page is holding this".
|
|
12
|
+
*/
|
|
13
|
+
declare const describeQueryPath: DescribePath;
|
|
14
|
+
/**
|
|
15
|
+
* Lets go of a cached answer now, rather than at the end of its grace period.
|
|
16
|
+
*
|
|
17
|
+
* Here rather than in the panel because only this file knows a query path from any other: the cache has to be told,
|
|
18
|
+
* so that the request still out for it is dropped too and the next reader asks afresh. Answers false for a path this
|
|
19
|
+
* does not own, and for a query something still renders — that one has nothing to ask again with.
|
|
20
|
+
*/
|
|
21
|
+
export declare const forgetQueryPath: (store: object, path: string) => boolean;
|
|
22
|
+
export default describeQueryPath;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { queryCache as e } from "@plitzi/sdk-shared/queries";
|
|
2
|
+
//#region src/freshness/describeQueryPath.ts
|
|
3
|
+
var t = e.store, n = "entries.", r = (r, i) => {
|
|
4
|
+
if (r === t && i.startsWith(n)) return e.store.getState().entries[i.slice(n.length)];
|
|
5
|
+
}, i = (t, n) => {
|
|
6
|
+
let i = r(t.entry.store, n);
|
|
7
|
+
if (!i) return;
|
|
8
|
+
let a = e.usage(i.key);
|
|
9
|
+
return {
|
|
10
|
+
label: i.url,
|
|
11
|
+
tags: i.tags,
|
|
12
|
+
usage: a && {
|
|
13
|
+
inUse: a.observers > 0 || a.holds > 0,
|
|
14
|
+
collectAt: a.collectAt
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}, a = (t, n) => {
|
|
18
|
+
let i = r(t, n);
|
|
19
|
+
return i ? e.remove(i.key) : !1;
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { i as default, a as forgetQueryPath };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/freshness/formatDuration.ts
|
|
2
|
+
var e = (e) => {
|
|
3
|
+
let t = Math.max(0, Math.round(e / 1e3));
|
|
4
|
+
if (t < 60) return `${t}s`;
|
|
5
|
+
let n = Math.floor(t / 60);
|
|
6
|
+
return n < 60 ? `${n}m ${t % 60}s` : `${Math.floor(n / 60)}h ${n % 60}m`;
|
|
7
|
+
};
|
|
8
|
+
//#endregion
|
|
9
|
+
export { e as default };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { default as describeQueryPath } from './describeQueryPath';
|
|
2
|
+
import { default as formatDuration } from './formatDuration';
|
|
3
|
+
import { default as useFreshnessByStore } from './useFreshnessByStore';
|
|
4
|
+
import { default as useSecondsClock } from './useSecondsClock';
|
|
5
|
+
export * from './describeQueryPath';
|
|
6
|
+
export * from './rows';
|
|
7
|
+
export * from './useFreshnessByStore';
|
|
8
|
+
export { describeQueryPath, formatDuration, useFreshnessByStore, useSecondsClock };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import e, { forgetQueryPath as t } from "./describeQueryPath.mjs";
|
|
2
|
+
import n from "./formatDuration.mjs";
|
|
3
|
+
import r from "./useFreshnessByStore.mjs";
|
|
4
|
+
import i from "./useSecondsClock.mjs";
|
|
5
|
+
import { toRows as a } from "./rows.mjs";
|
|
6
|
+
export { e as describeQueryPath, t as forgetQueryPath, n as formatDuration, a as toRows, r as useFreshnessByStore, i as useSecondsClock };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { FreshnessGroup } from './useFreshnessByStore';
|
|
2
|
+
/** Whether anything is rendering what a path holds, and when it is let go of if nothing starts. */
|
|
3
|
+
export type PathUsage = {
|
|
4
|
+
inUse: boolean;
|
|
5
|
+
collectAt?: number;
|
|
6
|
+
};
|
|
7
|
+
/** What a path stands for, when the path itself is an opaque key — a query cache entry is a hash of its request. */
|
|
8
|
+
export type PathDescription = {
|
|
9
|
+
label: string;
|
|
10
|
+
tags: string[];
|
|
11
|
+
usage?: PathUsage;
|
|
12
|
+
};
|
|
13
|
+
export type DescribePath = (group: FreshnessGroup, path: string) => PathDescription | undefined;
|
|
14
|
+
export type FreshnessRowModel = {
|
|
15
|
+
/** The store and path together: two stores can hold the same path. */
|
|
16
|
+
key: string;
|
|
17
|
+
uid: string;
|
|
18
|
+
storeLabel: string;
|
|
19
|
+
path: string;
|
|
20
|
+
label: string;
|
|
21
|
+
tags: string[];
|
|
22
|
+
isStale: boolean;
|
|
23
|
+
/** How long ago it was written, e.g. `12s ago`. */
|
|
24
|
+
age: string;
|
|
25
|
+
/** `18s left` while current, `stale` once it is not. */
|
|
26
|
+
status: string;
|
|
27
|
+
/** The TTL it was written with — not what is left of it, which is what `status` says. */
|
|
28
|
+
ttl: string;
|
|
29
|
+
/** What is left of the TTL, `1` down to `0` — a bar says "half gone" in a glance that a countdown does not. */
|
|
30
|
+
progress: number;
|
|
31
|
+
/** Whether anything renders this, where that is known: only what can be let go of can be offered to. */
|
|
32
|
+
inUse?: boolean;
|
|
33
|
+
/** `forgotten in 3m 58s`, while a grace period is running. */
|
|
34
|
+
kept?: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* One row per record of every store, stale ones last so what is still being served is what the panel shows first.
|
|
38
|
+
*
|
|
39
|
+
* `now` is never earlier than the newest write: the clock is a render-time snapshot, and a record written after it
|
|
40
|
+
* read as written in the future — "0s ago" and "0s left" on an answer that was never current at all.
|
|
41
|
+
*/
|
|
42
|
+
export declare const toRows: (groups: ReadonlyArray<FreshnessGroup>, labelOf: (group: FreshnessGroup) => string, now: number, describe?: DescribePath) => FreshnessRowModel[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import e from "./formatDuration.mjs";
|
|
2
|
+
//#region src/freshness/rows.ts
|
|
3
|
+
var t = (t, n, r, { updatedAt: i, expiresAt: a, ttl: o }, s, c) => {
|
|
4
|
+
let l = s >= a, u = Number.isFinite(a), d = "no expiry";
|
|
5
|
+
return l ? d = "stale" : u && (d = `${e(a - s)} left`), {
|
|
6
|
+
key: `${t.entry.uid}:${r}`,
|
|
7
|
+
uid: t.entry.uid,
|
|
8
|
+
storeLabel: n,
|
|
9
|
+
path: r,
|
|
10
|
+
label: c?.label ?? r,
|
|
11
|
+
tags: c?.tags ?? [],
|
|
12
|
+
isStale: l,
|
|
13
|
+
age: `${e(s - i)} ago`,
|
|
14
|
+
status: d,
|
|
15
|
+
ttl: Number.isFinite(o) ? e(o) : "∞",
|
|
16
|
+
inUse: c?.usage?.inUse,
|
|
17
|
+
kept: c?.usage?.collectAt ? `forgotten in ${e(c.usage.collectAt - s)}` : void 0,
|
|
18
|
+
progress: l ? 0 : Math.min(1, Number.isFinite(o) ? (a - s) / o : 1)
|
|
19
|
+
};
|
|
20
|
+
}, n = (e, n, r, i) => {
|
|
21
|
+
let a = r;
|
|
22
|
+
for (let t of e) for (let e of Object.values(t.records)) a = Math.max(a, e.updatedAt);
|
|
23
|
+
return e.flatMap((e) => {
|
|
24
|
+
let r = n(e);
|
|
25
|
+
return Object.entries(e.records).map(([n, o]) => t(e, r, n, o, a, i?.(e, n)));
|
|
26
|
+
}).sort((e, t) => Number(e.isStale) - Number(t.isStale) || e.storeLabel.localeCompare(t.storeLabel) || e.label.localeCompare(t.label));
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { n as toRows };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DevStoreEntry, PathFreshness } from '@plitzi/nexus';
|
|
2
|
+
export type FreshnessGroup = {
|
|
3
|
+
entry: DevStoreEntry;
|
|
4
|
+
records: Readonly<Record<string, PathFreshness>>;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* The paths written with a TTL, across every store given — the stores that hold none are left out.
|
|
8
|
+
*
|
|
9
|
+
* Across all of them because the one holding a TTL is rarely the one being looked at: a provider's answers live in the
|
|
10
|
+
* query cache, not in the provider's own scope, and a panel that only read the picked store showed nothing unless its
|
|
11
|
+
* reader already knew where to look. Each store hands out the same records object until one changes, so the list is
|
|
12
|
+
* rebuilt only when something did.
|
|
13
|
+
*/
|
|
14
|
+
declare const useFreshnessByStore: (entries: ReadonlyArray<DevStoreEntry>) => ReadonlyArray<FreshnessGroup>;
|
|
15
|
+
export default useFreshnessByStore;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useCallback as e, useRef as t, useSyncExternalStore as n } from "react";
|
|
2
|
+
//#region src/freshness/useFreshnessByStore.ts
|
|
3
|
+
var r = [], i = (e, t) => e.length === t.length && e.every((e, n) => e.entry === t[n].entry && e.records === t[n].records), a = (e) => Object.fromEntries(Object.entries(e).filter(([, e]) => e.ttl > 0)), o = (o) => {
|
|
4
|
+
let s = t(r), c = t(/* @__PURE__ */ new WeakMap()), l = e((e) => {
|
|
5
|
+
let t = o.map(({ store: t }) => t.watchFreshness(e));
|
|
6
|
+
return () => t.forEach((e) => e());
|
|
7
|
+
}, [o]), u = e(() => {
|
|
8
|
+
let e = o.map((e) => {
|
|
9
|
+
let t = e.store.getFreshnessRecords(), n = c.current.get(t);
|
|
10
|
+
return n || (n = a(t), c.current.set(t, n)), {
|
|
11
|
+
entry: e,
|
|
12
|
+
records: n
|
|
13
|
+
};
|
|
14
|
+
}).filter((e) => Object.keys(e.records).length > 0);
|
|
15
|
+
return i(s.current, e) || (s.current = e.length > 0 ? e : r), s.current;
|
|
16
|
+
}, [o]);
|
|
17
|
+
return n(l, u, u);
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { o as default };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Date.now()`, moving once a second while `active` — the finest step a countdown shows.
|
|
3
|
+
*
|
|
4
|
+
* Never earlier than `floor`: the clock is a render-time snapshot, and a value written after it read as written in
|
|
5
|
+
* the future — "0s ago" and "0s left" on an answer that was never current at all.
|
|
6
|
+
*/
|
|
7
|
+
declare const useSecondsClock: (active: boolean, floor?: number) => number;
|
|
8
|
+
export default useSecondsClock;
|