@logixjs/devtools-react 0.0.1
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/dist/DevtoolsLayer.cjs +172 -0
- package/dist/DevtoolsLayer.d.cts +53 -0
- package/dist/DevtoolsLayer.d.ts +53 -0
- package/dist/DevtoolsLayer.js +33 -0
- package/dist/LogixDevtools.cjs +5333 -0
- package/dist/LogixDevtools.d.cts +16 -0
- package/dist/LogixDevtools.d.ts +16 -0
- package/dist/LogixDevtools.js +8 -0
- package/dist/StateTraitGraphView.cjs +186 -0
- package/dist/StateTraitGraphView.d.cts +22 -0
- package/dist/StateTraitGraphView.d.ts +22 -0
- package/dist/StateTraitGraphView.js +7 -0
- package/dist/chunk-AELNVFJN.js +6 -0
- package/dist/chunk-CZWYV2AZ.js +157 -0
- package/dist/chunk-FNWHBEXD.js +123 -0
- package/dist/chunk-HFUIUVQI.js +0 -0
- package/dist/chunk-WTZBDE4J.js +5052 -0
- package/dist/index.cjs +5371 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +46 -0
- package/dist/style.css +2 -0
- package/package.json +64 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import * as Logix from '@logixjs/core';
|
|
3
|
+
|
|
4
|
+
interface LogixDevtoolsProps {
|
|
5
|
+
readonly position?: 'bottom-left' | 'bottom-right';
|
|
6
|
+
readonly initialOpen?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Optional: provide a StateTraitProgram for the currently selected moduleId,
|
|
9
|
+
* so Devtools can render StateTraitGraph in the Inspector panel and coordinate with the Timeline.
|
|
10
|
+
* - If not provided, the Graph section only shows a placeholder and does not affect Timeline / Inspector behavior.
|
|
11
|
+
*/
|
|
12
|
+
readonly getProgramForModule?: (moduleId: string) => Logix.StateTrait.StateTraitProgram<any> | undefined;
|
|
13
|
+
}
|
|
14
|
+
declare const LogixDevtools: React.FC<LogixDevtoolsProps>;
|
|
15
|
+
|
|
16
|
+
export { LogixDevtools };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import * as Logix from '@logixjs/core';
|
|
3
|
+
|
|
4
|
+
interface LogixDevtoolsProps {
|
|
5
|
+
readonly position?: 'bottom-left' | 'bottom-right';
|
|
6
|
+
readonly initialOpen?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Optional: provide a StateTraitProgram for the currently selected moduleId,
|
|
9
|
+
* so Devtools can render StateTraitGraph in the Inspector panel and coordinate with the Timeline.
|
|
10
|
+
* - If not provided, the Graph section only shows a placeholder and does not affect Timeline / Inspector behavior.
|
|
11
|
+
*/
|
|
12
|
+
readonly getProgramForModule?: (moduleId: string) => Logix.StateTrait.StateTraitProgram<any> | undefined;
|
|
13
|
+
}
|
|
14
|
+
declare const LogixDevtools: React.FC<LogixDevtoolsProps>;
|
|
15
|
+
|
|
16
|
+
export { LogixDevtools };
|
|
@@ -0,0 +1,186 @@
|
|
|
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/StateTraitGraphView.tsx
|
|
21
|
+
var StateTraitGraphView_exports = {};
|
|
22
|
+
__export(StateTraitGraphView_exports, {
|
|
23
|
+
StateTraitGraphView: () => StateTraitGraphView
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(StateTraitGraphView_exports);
|
|
26
|
+
|
|
27
|
+
// src/style.ts
|
|
28
|
+
var import_meta = {};
|
|
29
|
+
var styleMarkerAttribute = "data-logix-devtools-style";
|
|
30
|
+
var ensureDevtoolsStyles = () => {
|
|
31
|
+
if (typeof document === "undefined") return;
|
|
32
|
+
const existing = document.querySelector(`link[${styleMarkerAttribute}="true"]`);
|
|
33
|
+
if (existing) return;
|
|
34
|
+
let href;
|
|
35
|
+
try {
|
|
36
|
+
href = new URL("./style.css", import_meta.url).toString();
|
|
37
|
+
} catch {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const link = document.createElement("link");
|
|
41
|
+
link.rel = "stylesheet";
|
|
42
|
+
link.href = href;
|
|
43
|
+
link.setAttribute(styleMarkerAttribute, "true");
|
|
44
|
+
document.head.appendChild(link);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// src/internal/ui/graph/StateTraitGraphView.tsx
|
|
48
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
49
|
+
var StateTraitGraphView = ({
|
|
50
|
+
program,
|
|
51
|
+
onSelectNode,
|
|
52
|
+
selectedFieldPath
|
|
53
|
+
}) => {
|
|
54
|
+
if (!program) {
|
|
55
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
56
|
+
"div",
|
|
57
|
+
{
|
|
58
|
+
className: "text-xs px-3 py-2",
|
|
59
|
+
style: {
|
|
60
|
+
color: "var(--dt-text-muted)",
|
|
61
|
+
backgroundColor: "var(--dt-bg-surface)"
|
|
62
|
+
},
|
|
63
|
+
children: "No StateTraitProgram available for this module."
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
const { graph } = program;
|
|
68
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
69
|
+
"div",
|
|
70
|
+
{
|
|
71
|
+
className: "text-[10px] font-mono px-3 py-2 space-y-2 overflow-auto",
|
|
72
|
+
style: {
|
|
73
|
+
backgroundColor: "var(--dt-bg-surface)",
|
|
74
|
+
color: "var(--dt-text-primary)"
|
|
75
|
+
},
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-[9px] uppercase tracking-wide mb-1", style: { color: "var(--dt-text-muted)" }, children: "StateTraitGraph" }),
|
|
78
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
79
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-[9px] mb-1", style: { color: "var(--dt-text-secondary)" }, children: [
|
|
80
|
+
"Nodes (",
|
|
81
|
+
graph.nodes.length,
|
|
82
|
+
")"
|
|
83
|
+
] }),
|
|
84
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "space-y-0.5", children: graph.nodes.map((node) => {
|
|
85
|
+
const fieldPath = node.field.path;
|
|
86
|
+
const label = node.meta?.label;
|
|
87
|
+
const tags = node.meta?.tags ?? [];
|
|
88
|
+
const handleClick = () => {
|
|
89
|
+
if (onSelectNode) {
|
|
90
|
+
onSelectNode(fieldPath);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { className: "flex items-center justify-between gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
94
|
+
"button",
|
|
95
|
+
{
|
|
96
|
+
type: "button",
|
|
97
|
+
onClick: handleClick,
|
|
98
|
+
className: "flex-1 flex items-center justify-between gap-2 text-left hover:bg-[var(--dt-bg-element)] rounded px-1 py-0.5 transition-colors",
|
|
99
|
+
style: selectedFieldPath === fieldPath ? {
|
|
100
|
+
backgroundColor: "var(--dt-info-bg)",
|
|
101
|
+
boxShadow: "0 0 0 1px var(--dt-info)"
|
|
102
|
+
} : void 0,
|
|
103
|
+
children: [
|
|
104
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex flex-col gap-0.5 min-w-0", children: [
|
|
105
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate", children: label ?? fieldPath }),
|
|
106
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[9px] truncate", style: { color: "var(--dt-text-muted)" }, children: fieldPath }) : null
|
|
107
|
+
] }),
|
|
108
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "text-[9px]", style: { color: "var(--dt-text-muted)" }, children: [
|
|
109
|
+
node.traits.map((t) => t.kind).join(", ") || "\u2014",
|
|
110
|
+
tags.length > 0 ? ` \xB7 #${tags.join(" #")}` : ""
|
|
111
|
+
] })
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
) }, node.id);
|
|
115
|
+
}) })
|
|
116
|
+
] }),
|
|
117
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
118
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-[9px] mt-2 mb-1", style: { color: "var(--dt-text-secondary)" }, children: [
|
|
119
|
+
"Resources (",
|
|
120
|
+
graph.resources.length,
|
|
121
|
+
")"
|
|
122
|
+
] }),
|
|
123
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "space-y-0.5", children: graph.resources.map((res) => {
|
|
124
|
+
const label = res.meta?.label;
|
|
125
|
+
const tags = res.meta?.tags ?? [];
|
|
126
|
+
const conflicts = res.metaConflicts ?? [];
|
|
127
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "flex items-center justify-between gap-2", children: [
|
|
128
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
129
|
+
res.resourceId,
|
|
130
|
+
label ? ` \xB7 ${label}` : ""
|
|
131
|
+
] }),
|
|
132
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "text-[9px] flex items-center gap-2", style: { color: "var(--dt-text-muted)" }, children: [
|
|
133
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
134
|
+
"owners: ",
|
|
135
|
+
res.ownerFields.length
|
|
136
|
+
] }),
|
|
137
|
+
tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
138
|
+
"#",
|
|
139
|
+
tags.join(" #")
|
|
140
|
+
] }) : null,
|
|
141
|
+
conflicts.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
142
|
+
"span",
|
|
143
|
+
{
|
|
144
|
+
className: "px-1 rounded",
|
|
145
|
+
style: {
|
|
146
|
+
color: "var(--dt-danger)",
|
|
147
|
+
backgroundColor: "var(--dt-danger-bg)",
|
|
148
|
+
boxShadow: "0 0 0 1px var(--dt-danger-border)"
|
|
149
|
+
},
|
|
150
|
+
title: "Multiple conflicting meta declarations detected for this resource id.",
|
|
151
|
+
children: [
|
|
152
|
+
"meta-conflict+",
|
|
153
|
+
conflicts.length
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
) : null
|
|
157
|
+
] })
|
|
158
|
+
] }, res.resourceId);
|
|
159
|
+
}) })
|
|
160
|
+
] }),
|
|
161
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
162
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-[9px] mt-2 mb-1", style: { color: "var(--dt-text-secondary)" }, children: [
|
|
163
|
+
"Edges (",
|
|
164
|
+
graph.edges.length,
|
|
165
|
+
")"
|
|
166
|
+
] }),
|
|
167
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "space-y-0.5", children: graph.edges.map((edge) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "flex items-center justify-between gap-2", children: [
|
|
168
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
169
|
+
edge.from,
|
|
170
|
+
" \u2192 ",
|
|
171
|
+
edge.to
|
|
172
|
+
] }),
|
|
173
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[9px]", style: { color: "var(--dt-text-muted)" }, children: edge.kind })
|
|
174
|
+
] }, edge.id)) })
|
|
175
|
+
] })
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
);
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// src/StateTraitGraphView.tsx
|
|
182
|
+
ensureDevtoolsStyles();
|
|
183
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
184
|
+
0 && (module.exports = {
|
|
185
|
+
StateTraitGraphView
|
|
186
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import * as Logix from '@logixjs/core';
|
|
3
|
+
|
|
4
|
+
interface StateTraitGraphViewProps {
|
|
5
|
+
/**
|
|
6
|
+
* Program output from Debug.getModuleTraits(module).
|
|
7
|
+
* - If not provided, the component only renders a placeholder.
|
|
8
|
+
*/
|
|
9
|
+
readonly program?: Logix.StateTrait.StateTraitProgram<any>;
|
|
10
|
+
/**
|
|
11
|
+
* Optional: notify the caller when the user clicks a field node,
|
|
12
|
+
* so the caller can coordinate the EffectOp timeline (e.g. filter by fieldPath).
|
|
13
|
+
*/
|
|
14
|
+
readonly onSelectNode?: (fieldPath: string) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Optional: the currently selected fieldPath to highlight in the graph.
|
|
17
|
+
*/
|
|
18
|
+
readonly selectedFieldPath?: string;
|
|
19
|
+
}
|
|
20
|
+
declare const StateTraitGraphView: React.FC<StateTraitGraphViewProps>;
|
|
21
|
+
|
|
22
|
+
export { StateTraitGraphView };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import * as Logix from '@logixjs/core';
|
|
3
|
+
|
|
4
|
+
interface StateTraitGraphViewProps {
|
|
5
|
+
/**
|
|
6
|
+
* Program output from Debug.getModuleTraits(module).
|
|
7
|
+
* - If not provided, the component only renders a placeholder.
|
|
8
|
+
*/
|
|
9
|
+
readonly program?: Logix.StateTrait.StateTraitProgram<any>;
|
|
10
|
+
/**
|
|
11
|
+
* Optional: notify the caller when the user clicks a field node,
|
|
12
|
+
* so the caller can coordinate the EffectOp timeline (e.g. filter by fieldPath).
|
|
13
|
+
*/
|
|
14
|
+
readonly onSelectNode?: (fieldPath: string) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Optional: the currently selected fieldPath to highlight in the graph.
|
|
17
|
+
*/
|
|
18
|
+
readonly selectedFieldPath?: string;
|
|
19
|
+
}
|
|
20
|
+
declare const StateTraitGraphView: React.FC<StateTraitGraphViewProps>;
|
|
21
|
+
|
|
22
|
+
export { StateTraitGraphView };
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// src/style.ts
|
|
2
|
+
var styleMarkerAttribute = "data-logix-devtools-style";
|
|
3
|
+
var ensureDevtoolsStyles = () => {
|
|
4
|
+
if (typeof document === "undefined") return;
|
|
5
|
+
const existing = document.querySelector(`link[${styleMarkerAttribute}="true"]`);
|
|
6
|
+
if (existing) return;
|
|
7
|
+
let href;
|
|
8
|
+
try {
|
|
9
|
+
href = new URL("./style.css", import.meta.url).toString();
|
|
10
|
+
} catch {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const link = document.createElement("link");
|
|
14
|
+
link.rel = "stylesheet";
|
|
15
|
+
link.href = href;
|
|
16
|
+
link.setAttribute(styleMarkerAttribute, "true");
|
|
17
|
+
document.head.appendChild(link);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// src/internal/ui/graph/StateTraitGraphView.tsx
|
|
21
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
22
|
+
var StateTraitGraphView = ({
|
|
23
|
+
program,
|
|
24
|
+
onSelectNode,
|
|
25
|
+
selectedFieldPath
|
|
26
|
+
}) => {
|
|
27
|
+
if (!program) {
|
|
28
|
+
return /* @__PURE__ */ jsx(
|
|
29
|
+
"div",
|
|
30
|
+
{
|
|
31
|
+
className: "text-xs px-3 py-2",
|
|
32
|
+
style: {
|
|
33
|
+
color: "var(--dt-text-muted)",
|
|
34
|
+
backgroundColor: "var(--dt-bg-surface)"
|
|
35
|
+
},
|
|
36
|
+
children: "No StateTraitProgram available for this module."
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
const { graph } = program;
|
|
41
|
+
return /* @__PURE__ */ jsxs(
|
|
42
|
+
"div",
|
|
43
|
+
{
|
|
44
|
+
className: "text-[10px] font-mono px-3 py-2 space-y-2 overflow-auto",
|
|
45
|
+
style: {
|
|
46
|
+
backgroundColor: "var(--dt-bg-surface)",
|
|
47
|
+
color: "var(--dt-text-primary)"
|
|
48
|
+
},
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ jsx("div", { className: "text-[9px] uppercase tracking-wide mb-1", style: { color: "var(--dt-text-muted)" }, children: "StateTraitGraph" }),
|
|
51
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
52
|
+
/* @__PURE__ */ jsxs("div", { className: "text-[9px] mb-1", style: { color: "var(--dt-text-secondary)" }, children: [
|
|
53
|
+
"Nodes (",
|
|
54
|
+
graph.nodes.length,
|
|
55
|
+
")"
|
|
56
|
+
] }),
|
|
57
|
+
/* @__PURE__ */ jsx("ul", { className: "space-y-0.5", children: graph.nodes.map((node) => {
|
|
58
|
+
const fieldPath = node.field.path;
|
|
59
|
+
const label = node.meta?.label;
|
|
60
|
+
const tags = node.meta?.tags ?? [];
|
|
61
|
+
const handleClick = () => {
|
|
62
|
+
if (onSelectNode) {
|
|
63
|
+
onSelectNode(fieldPath);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
return /* @__PURE__ */ jsx("li", { className: "flex items-center justify-between gap-2", children: /* @__PURE__ */ jsxs(
|
|
67
|
+
"button",
|
|
68
|
+
{
|
|
69
|
+
type: "button",
|
|
70
|
+
onClick: handleClick,
|
|
71
|
+
className: "flex-1 flex items-center justify-between gap-2 text-left hover:bg-[var(--dt-bg-element)] rounded px-1 py-0.5 transition-colors",
|
|
72
|
+
style: selectedFieldPath === fieldPath ? {
|
|
73
|
+
backgroundColor: "var(--dt-info-bg)",
|
|
74
|
+
boxShadow: "0 0 0 1px var(--dt-info)"
|
|
75
|
+
} : void 0,
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ jsxs("span", { className: "flex flex-col gap-0.5 min-w-0", children: [
|
|
78
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: label ?? fieldPath }),
|
|
79
|
+
label ? /* @__PURE__ */ jsx("span", { className: "text-[9px] truncate", style: { color: "var(--dt-text-muted)" }, children: fieldPath }) : null
|
|
80
|
+
] }),
|
|
81
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[9px]", style: { color: "var(--dt-text-muted)" }, children: [
|
|
82
|
+
node.traits.map((t) => t.kind).join(", ") || "\u2014",
|
|
83
|
+
tags.length > 0 ? ` \xB7 #${tags.join(" #")}` : ""
|
|
84
|
+
] })
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
) }, node.id);
|
|
88
|
+
}) })
|
|
89
|
+
] }),
|
|
90
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
91
|
+
/* @__PURE__ */ jsxs("div", { className: "text-[9px] mt-2 mb-1", style: { color: "var(--dt-text-secondary)" }, children: [
|
|
92
|
+
"Resources (",
|
|
93
|
+
graph.resources.length,
|
|
94
|
+
")"
|
|
95
|
+
] }),
|
|
96
|
+
/* @__PURE__ */ jsx("ul", { className: "space-y-0.5", children: graph.resources.map((res) => {
|
|
97
|
+
const label = res.meta?.label;
|
|
98
|
+
const tags = res.meta?.tags ?? [];
|
|
99
|
+
const conflicts = res.metaConflicts ?? [];
|
|
100
|
+
return /* @__PURE__ */ jsxs("li", { className: "flex items-center justify-between gap-2", children: [
|
|
101
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
102
|
+
res.resourceId,
|
|
103
|
+
label ? ` \xB7 ${label}` : ""
|
|
104
|
+
] }),
|
|
105
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[9px] flex items-center gap-2", style: { color: "var(--dt-text-muted)" }, children: [
|
|
106
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
107
|
+
"owners: ",
|
|
108
|
+
res.ownerFields.length
|
|
109
|
+
] }),
|
|
110
|
+
tags.length > 0 ? /* @__PURE__ */ jsxs("span", { children: [
|
|
111
|
+
"#",
|
|
112
|
+
tags.join(" #")
|
|
113
|
+
] }) : null,
|
|
114
|
+
conflicts.length > 0 ? /* @__PURE__ */ jsxs(
|
|
115
|
+
"span",
|
|
116
|
+
{
|
|
117
|
+
className: "px-1 rounded",
|
|
118
|
+
style: {
|
|
119
|
+
color: "var(--dt-danger)",
|
|
120
|
+
backgroundColor: "var(--dt-danger-bg)",
|
|
121
|
+
boxShadow: "0 0 0 1px var(--dt-danger-border)"
|
|
122
|
+
},
|
|
123
|
+
title: "Multiple conflicting meta declarations detected for this resource id.",
|
|
124
|
+
children: [
|
|
125
|
+
"meta-conflict+",
|
|
126
|
+
conflicts.length
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
) : null
|
|
130
|
+
] })
|
|
131
|
+
] }, res.resourceId);
|
|
132
|
+
}) })
|
|
133
|
+
] }),
|
|
134
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
135
|
+
/* @__PURE__ */ jsxs("div", { className: "text-[9px] mt-2 mb-1", style: { color: "var(--dt-text-secondary)" }, children: [
|
|
136
|
+
"Edges (",
|
|
137
|
+
graph.edges.length,
|
|
138
|
+
")"
|
|
139
|
+
] }),
|
|
140
|
+
/* @__PURE__ */ jsx("ul", { className: "space-y-0.5", children: graph.edges.map((edge) => /* @__PURE__ */ jsxs("li", { className: "flex items-center justify-between gap-2", children: [
|
|
141
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
142
|
+
edge.from,
|
|
143
|
+
" \u2192 ",
|
|
144
|
+
edge.to
|
|
145
|
+
] }),
|
|
146
|
+
/* @__PURE__ */ jsx("span", { className: "text-[9px]", style: { color: "var(--dt-text-muted)" }, children: edge.kind })
|
|
147
|
+
] }, edge.id)) })
|
|
148
|
+
] })
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export {
|
|
155
|
+
ensureDevtoolsStyles,
|
|
156
|
+
StateTraitGraphView
|
|
157
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// src/internal/snapshot/index.ts
|
|
2
|
+
import * as Logix from "@logixjs/core";
|
|
3
|
+
import { Context, Effect, Layer, Stream } from "effect";
|
|
4
|
+
var clearDevtoolsEvents = Logix.Debug.clearDevtoolsEvents;
|
|
5
|
+
var setInstanceLabel = Logix.Debug.setInstanceLabel;
|
|
6
|
+
var getInstanceLabel = Logix.Debug.getInstanceLabel;
|
|
7
|
+
var snapshotOverride;
|
|
8
|
+
var snapshotOverrideInfo;
|
|
9
|
+
var overrideSnapshotToken = Number.MIN_SAFE_INTEGER;
|
|
10
|
+
var nextOverrideSnapshotToken = () => {
|
|
11
|
+
overrideSnapshotToken += 1;
|
|
12
|
+
return overrideSnapshotToken;
|
|
13
|
+
};
|
|
14
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15
|
+
var asNonEmptyString = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
|
|
16
|
+
var asNonNegativeInt = (value) => {
|
|
17
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
|
|
18
|
+
const n = Math.floor(value);
|
|
19
|
+
return n >= 0 ? n : void 0;
|
|
20
|
+
};
|
|
21
|
+
var normalizeTxnSeqFromTxnId = (txnId, instanceId) => {
|
|
22
|
+
if (!txnId) return void 0;
|
|
23
|
+
const escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
24
|
+
const m = instanceId ? txnId.match(new RegExp(`^${escapeRe(instanceId)}::t(\\d+)$`)) : txnId.match(/::t(\d+)$/);
|
|
25
|
+
if (!m) return void 0;
|
|
26
|
+
const n = Number(m[1]);
|
|
27
|
+
return Number.isFinite(n) && n >= 0 ? Math.floor(n) : void 0;
|
|
28
|
+
};
|
|
29
|
+
var normalizeDevtoolsSnapshot = (snapshot) => {
|
|
30
|
+
const events = snapshot.events.map((e, index) => {
|
|
31
|
+
if (!isRecord(e)) {
|
|
32
|
+
return e;
|
|
33
|
+
}
|
|
34
|
+
const instanceId = asNonEmptyString(e.instanceId);
|
|
35
|
+
const txnId = asNonEmptyString(e.txnId);
|
|
36
|
+
const txnSeq = asNonNegativeInt(e.txnSeq) ?? normalizeTxnSeqFromTxnId(txnId, instanceId) ?? 0;
|
|
37
|
+
const eventSeq = asNonNegativeInt(e.eventSeq) ?? index + 1;
|
|
38
|
+
const eventId = asNonEmptyString(e.eventId) ?? (instanceId ? `${instanceId}::e${eventSeq}` : `unknown::e${eventSeq}`);
|
|
39
|
+
const patched = { ...e, eventId, eventSeq, txnSeq };
|
|
40
|
+
if (!patched.txnId && instanceId && txnSeq > 0) {
|
|
41
|
+
patched.txnId = `${instanceId}::t${txnSeq}`;
|
|
42
|
+
}
|
|
43
|
+
return patched;
|
|
44
|
+
});
|
|
45
|
+
return { ...snapshot, events };
|
|
46
|
+
};
|
|
47
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
48
|
+
var unsubscribeCore;
|
|
49
|
+
var notify = () => {
|
|
50
|
+
for (const listener of listeners) {
|
|
51
|
+
listener();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var ensureCoreSubscribed = () => {
|
|
55
|
+
if (unsubscribeCore) return;
|
|
56
|
+
unsubscribeCore = Logix.Debug.subscribeDevtoolsSnapshot(() => {
|
|
57
|
+
if (snapshotOverride) return;
|
|
58
|
+
notify();
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
var hasDevtoolsSnapshotOverride = () => snapshotOverride != null;
|
|
62
|
+
var getDevtoolsSnapshotOverrideInfo = () => snapshotOverrideInfo;
|
|
63
|
+
var setDevtoolsSnapshotOverride = (snapshot, info) => {
|
|
64
|
+
snapshotOverride = normalizeDevtoolsSnapshot({
|
|
65
|
+
...snapshot,
|
|
66
|
+
snapshotToken: nextOverrideSnapshotToken()
|
|
67
|
+
});
|
|
68
|
+
snapshotOverrideInfo = info;
|
|
69
|
+
notify();
|
|
70
|
+
};
|
|
71
|
+
var clearDevtoolsSnapshotOverride = () => {
|
|
72
|
+
snapshotOverride = void 0;
|
|
73
|
+
snapshotOverrideInfo = void 0;
|
|
74
|
+
notify();
|
|
75
|
+
};
|
|
76
|
+
var getDevtoolsSnapshot = () => snapshotOverride ?? Logix.Debug.getDevtoolsSnapshot();
|
|
77
|
+
var getDevtoolsSnapshotToken = () => getDevtoolsSnapshot().snapshotToken;
|
|
78
|
+
var subscribeDevtoolsSnapshot = (listener) => {
|
|
79
|
+
listeners.add(listener);
|
|
80
|
+
ensureCoreSubscribed();
|
|
81
|
+
return () => {
|
|
82
|
+
listeners.delete(listener);
|
|
83
|
+
if (listeners.size === 0 && unsubscribeCore) {
|
|
84
|
+
unsubscribeCore();
|
|
85
|
+
unsubscribeCore = void 0;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
var subscribeDevtoolsSnapshotToken = subscribeDevtoolsSnapshot;
|
|
90
|
+
var devtoolsLayer = Logix.Debug.devtoolsHubLayer();
|
|
91
|
+
var DevtoolsSnapshotStore = class extends Context.Tag("Logix/DevtoolsSnapshotStore")() {
|
|
92
|
+
};
|
|
93
|
+
var devtoolsSnapshotService = {
|
|
94
|
+
get: Effect.sync(() => getDevtoolsSnapshot()),
|
|
95
|
+
changes: Stream.async((emit) => {
|
|
96
|
+
const listener = () => {
|
|
97
|
+
emit.single(getDevtoolsSnapshot());
|
|
98
|
+
};
|
|
99
|
+
const unsubscribe = subscribeDevtoolsSnapshot(listener);
|
|
100
|
+
return Effect.sync(unsubscribe);
|
|
101
|
+
})
|
|
102
|
+
};
|
|
103
|
+
var devtoolsSnapshotLayer = Layer.succeed(
|
|
104
|
+
DevtoolsSnapshotStore,
|
|
105
|
+
devtoolsSnapshotService
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
clearDevtoolsEvents,
|
|
110
|
+
setInstanceLabel,
|
|
111
|
+
getInstanceLabel,
|
|
112
|
+
hasDevtoolsSnapshotOverride,
|
|
113
|
+
getDevtoolsSnapshotOverrideInfo,
|
|
114
|
+
setDevtoolsSnapshotOverride,
|
|
115
|
+
clearDevtoolsSnapshotOverride,
|
|
116
|
+
getDevtoolsSnapshot,
|
|
117
|
+
getDevtoolsSnapshotToken,
|
|
118
|
+
subscribeDevtoolsSnapshot,
|
|
119
|
+
subscribeDevtoolsSnapshotToken,
|
|
120
|
+
devtoolsLayer,
|
|
121
|
+
DevtoolsSnapshotStore,
|
|
122
|
+
devtoolsSnapshotLayer
|
|
123
|
+
};
|
|
File without changes
|