@principal-ai/principal-view-react 0.7.9 → 0.7.11

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.
@@ -0,0 +1,158 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import { GraphRenderer } from '../components/GraphRenderer';
4
+ import { TestEventPanel } from '../components/TestEventPanel';
5
+ import type { ExtendedCanvas } from '@principal-ai/principal-view-core';
6
+ import { ThemeProvider, defaultEditorTheme } from '@principal-ade/industry-theme';
7
+ import executionCanvas from '../../../../.principal-views/graph-converter-execution.otel.canvas';
8
+ import validatedSpans from './data/graph-converter-validated-execution.json';
9
+
10
+ const meta = {
11
+ title: 'Features/Validated Execution',
12
+ component: GraphRenderer,
13
+ parameters: {
14
+ layout: 'fullscreen',
15
+ docs: {
16
+ description: {
17
+ component:
18
+ 'Demonstrates type-safe event emission with schema validation. The canvas defines expected events, and production code is validated against this schema. Shows how events match the schema defined in graph-converter-execution.otel.canvas.',
19
+ },
20
+ },
21
+ },
22
+ tags: ['autodocs'],
23
+ decorators: [
24
+ (Story) => (
25
+ <ThemeProvider theme={defaultEditorTheme}>
26
+ <div style={{ width: '100vw', height: '100vh', background: '#0a0a0a' }}>
27
+ <Story />
28
+ </div>
29
+ </ThemeProvider>
30
+ ),
31
+ ],
32
+ } satisfies Meta<typeof GraphRenderer>;
33
+
34
+ export default meta;
35
+ type Story = StoryObj<typeof meta>;
36
+
37
+ /**
38
+ * Graph visualization of the execution flow with event schema definitions.
39
+ *
40
+ * This canvas defines:
41
+ * - `graph-converter` node with 5 event types
42
+ * - `validation` node with 2 event types
43
+ * - `graph-output` node with 1 event type
44
+ *
45
+ * Each event type has a schema defining:
46
+ * - Required/optional fields
47
+ * - Field types (string, number, boolean, etc.)
48
+ * - Field descriptions
49
+ *
50
+ * See `.principal-views/graph-converter-execution.otel.canvas` for the full schema.
51
+ */
52
+ export const ExecutionFlow: Story = {
53
+ args: {
54
+ canvas: executionCanvas as ExtendedCanvas,
55
+ showControls: true,
56
+ },
57
+ };
58
+
59
+ /**
60
+ * Event panel showing validated execution data.
61
+ *
62
+ * These events were emitted using `createValidatedSpanEmitter()` which:
63
+ * - Validates events against the canvas schema
64
+ * - Ensures required fields are present
65
+ * - Checks field types match the schema
66
+ * - Throws errors in strict mode if validation fails
67
+ *
68
+ * All events in this panel passed schema validation.
69
+ */
70
+ export const ValidatedEvents: Story = {
71
+ render: () => (
72
+ <div style={{ width: '800px', height: '100vh' }}>
73
+ <TestEventPanel
74
+ spans={validatedSpans as any}
75
+ currentSpanIndex={0}
76
+ currentEventIndex={10} // Show all events
77
+ highlightedPhase={undefined}
78
+ />
79
+ </div>
80
+ ),
81
+ };
82
+
83
+ /**
84
+ * Side-by-side view of execution flow and validated events.
85
+ *
86
+ * **How it works:**
87
+ * 1. Canvas defines event schemas (what events should be emitted)
88
+ * 2. Tests use `createValidatedSpanEmitter()` to emit events
89
+ * 3. Events are validated against the schema in strict mode
90
+ * 4. If validation fails, test throws `EventValidationError`
91
+ * 5. If validation passes, events are emitted and collected
92
+ *
93
+ * This ensures production code emits events that match the architecture.
94
+ */
95
+ export const FlowWithValidation: Story = {
96
+ render: () => (
97
+ <div style={{ display: 'flex', width: '100%', height: '100%' }}>
98
+ {/* Graph Visualization - Left Side */}
99
+ <div style={{ flex: '0 0 60%', height: '100%', position: 'relative' }}>
100
+ <GraphRenderer
101
+ canvas={executionCanvas as ExtendedCanvas}
102
+ showControls={true}
103
+ />
104
+ </div>
105
+
106
+ {/* Event Panel - Right Side */}
107
+ <div style={{ flex: '0 0 40%', height: '100%', borderLeft: '1px solid #333' }}>
108
+ <div style={{ padding: '20px', color: '#fff', borderBottom: '1px solid #333' }}>
109
+ <h3 style={{ margin: '0 0 10px 0', fontSize: '16px' }}>
110
+ Type-Safe Validated Events
111
+ </h3>
112
+ <p style={{ margin: 0, fontSize: '12px', color: '#888' }}>
113
+ Events validated against canvas schema. See{' '}
114
+ <code>.principal-views/graph-converter-execution.otel.canvas</code>
115
+ </p>
116
+ </div>
117
+ <TestEventPanel
118
+ spans={validatedSpans as any}
119
+ currentSpanIndex={0}
120
+ currentEventIndex={10}
121
+ highlightedPhase={undefined}
122
+ />
123
+ </div>
124
+ </div>
125
+ ),
126
+ };
127
+
128
+ /**
129
+ * Canvas with event schema definitions (JSON view).
130
+ *
131
+ * Shows the raw canvas structure including event schemas.
132
+ * Notice the `pv.events` property on each node defining:
133
+ * - Event names (e.g., "conversion.started")
134
+ * - Event descriptions
135
+ * - Field schemas with types and requirements
136
+ */
137
+ export const CanvasSchema: Story = {
138
+ render: () => (
139
+ <div
140
+ style={{
141
+ padding: '20px',
142
+ color: '#fff',
143
+ fontFamily: 'monospace',
144
+ fontSize: '12px',
145
+ overflow: 'auto',
146
+ height: '100vh',
147
+ }}
148
+ >
149
+ <h2>Event Schema Definition</h2>
150
+ <p>
151
+ This canvas defines event schemas for type-safe telemetry validation.
152
+ </p>
153
+ <pre style={{ background: '#1e1e1e', padding: '20px', borderRadius: '8px' }}>
154
+ {JSON.stringify(executionCanvas, null, 2)}
155
+ </pre>
156
+ </div>
157
+ ),
158
+ };
@@ -0,0 +1,225 @@
1
+ [
2
+ {
3
+ "id": "span-1",
4
+ "name": "should convert simple config to nodes and edges",
5
+ "startTime": 1767808091637,
6
+ "attributes": {
7
+ "span.kind": "test.case",
8
+ "test.name": "should convert simple config to nodes and edges",
9
+ "test.framework": "bun",
10
+ "test.file": "GraphConverter.test.ts",
11
+ "test.suite": "GraphConverter",
12
+ "test.result": "pass"
13
+ },
14
+ "events": [
15
+ {
16
+ "time": 1767808091637,
17
+ "name": "setup.started",
18
+ "attributes": {
19
+ "code.filepath": "GraphConverter.test.ts",
20
+ "code.lineno": 28,
21
+ "description": "Creating test configuration with 2 nodes and 1 edge"
22
+ }
23
+ },
24
+ {
25
+ "time": 1767808091637,
26
+ "name": "setup.complete",
27
+ "attributes": {
28
+ "code.filepath": "GraphConverter.test.ts",
29
+ "code.lineno": 68,
30
+ "config.nodes": 2,
31
+ "config.edges": 1
32
+ }
33
+ },
34
+ {
35
+ "time": 1767808091637,
36
+ "name": "execution.started",
37
+ "attributes": {
38
+ "code.filepath": "GraphConverter.ts",
39
+ "code.lineno": 15,
40
+ "action": "GraphConverter.configToGraph()"
41
+ }
42
+ },
43
+ {
44
+ "time": 1767808091637,
45
+ "name": "execution.complete",
46
+ "attributes": {
47
+ "code.filepath": "GraphConverter.ts",
48
+ "code.lineno": 43,
49
+ "result.nodes.count": 2,
50
+ "result.edges.count": 1
51
+ }
52
+ },
53
+ {
54
+ "time": 1767808091637,
55
+ "name": "assertion.started",
56
+ "attributes": {
57
+ "code.filepath": "GraphConverter.test.ts",
58
+ "code.lineno": 91,
59
+ "assertions": "Verifying nodes and edges structure"
60
+ }
61
+ },
62
+ {
63
+ "time": 1767808091637,
64
+ "name": "assertion.complete",
65
+ "attributes": {
66
+ "code.filepath": "GraphConverter.test.ts",
67
+ "code.lineno": 114,
68
+ "assertions.passed": 11,
69
+ "assertions.failed": 0
70
+ }
71
+ }
72
+ ],
73
+ "status": "OK",
74
+ "endTime": 1767808091637,
75
+ "duration": 0
76
+ },
77
+ {
78
+ "id": "span-2",
79
+ "name": "should extract manual positions from node types",
80
+ "startTime": 1767808091637,
81
+ "attributes": {
82
+ "span.kind": "test.case",
83
+ "test.name": "should extract manual positions from node types",
84
+ "test.framework": "bun",
85
+ "test.file": "GraphConverter.test.ts",
86
+ "test.suite": "GraphConverter",
87
+ "test.result": "pass"
88
+ },
89
+ "events": [
90
+ {
91
+ "time": 1767808091637,
92
+ "name": "setup.started",
93
+ "attributes": {
94
+ "code.filepath": "GraphConverter.test.ts",
95
+ "code.lineno": 138,
96
+ "description": "Creating config with manual node positions"
97
+ }
98
+ },
99
+ {
100
+ "time": 1767808091637,
101
+ "name": "setup.complete",
102
+ "attributes": {
103
+ "code.filepath": "GraphConverter.test.ts",
104
+ "code.lineno": 165,
105
+ "config.nodes": 2,
106
+ "positions.defined": true
107
+ }
108
+ },
109
+ {
110
+ "time": 1767808091637,
111
+ "name": "execution.started",
112
+ "attributes": {
113
+ "code.filepath": "GraphConverter.ts",
114
+ "code.lineno": 15,
115
+ "action": "GraphConverter.configToGraph()"
116
+ }
117
+ },
118
+ {
119
+ "time": 1767808091637,
120
+ "name": "execution.complete",
121
+ "attributes": {
122
+ "code.filepath": "GraphConverter.ts",
123
+ "code.lineno": 43,
124
+ "result.nodes.count": 2
125
+ }
126
+ },
127
+ {
128
+ "time": 1767808091637,
129
+ "name": "assertion.started",
130
+ "attributes": {
131
+ "code.filepath": "GraphConverter.test.ts",
132
+ "code.lineno": 184,
133
+ "assertions": "Verifying positions preserved"
134
+ }
135
+ },
136
+ {
137
+ "time": 1767808091637,
138
+ "name": "assertion.complete",
139
+ "attributes": {
140
+ "code.filepath": "GraphConverter.test.ts",
141
+ "code.lineno": 191,
142
+ "assertions.passed": 2,
143
+ "assertions.failed": 0
144
+ }
145
+ }
146
+ ],
147
+ "status": "OK",
148
+ "endTime": 1767808091637,
149
+ "duration": 0
150
+ },
151
+ {
152
+ "id": "span-3",
153
+ "name": "should handle nodes without positions",
154
+ "startTime": 1767808091637,
155
+ "attributes": {
156
+ "span.kind": "test.case",
157
+ "test.name": "should handle nodes without positions",
158
+ "test.framework": "bun",
159
+ "test.file": "GraphConverter.test.ts",
160
+ "test.suite": "GraphConverter",
161
+ "test.result": "pass"
162
+ },
163
+ "events": [
164
+ {
165
+ "time": 1767808091637,
166
+ "name": "setup.started",
167
+ "attributes": {
168
+ "code.filepath": "GraphConverter.test.ts",
169
+ "code.lineno": 215,
170
+ "description": "Creating config without positions"
171
+ }
172
+ },
173
+ {
174
+ "time": 1767808091637,
175
+ "name": "setup.complete",
176
+ "attributes": {
177
+ "code.filepath": "GraphConverter.test.ts",
178
+ "code.lineno": 235,
179
+ "config.nodes": 1,
180
+ "positions.defined": false
181
+ }
182
+ },
183
+ {
184
+ "time": 1767808091637,
185
+ "name": "execution.started",
186
+ "attributes": {
187
+ "code.filepath": "GraphConverter.ts",
188
+ "code.lineno": 15,
189
+ "action": "GraphConverter.configToGraph()"
190
+ }
191
+ },
192
+ {
193
+ "time": 1767808091637,
194
+ "name": "execution.complete",
195
+ "attributes": {
196
+ "code.filepath": "GraphConverter.ts",
197
+ "code.lineno": 43,
198
+ "result.nodes.count": 1
199
+ }
200
+ },
201
+ {
202
+ "time": 1767808091637,
203
+ "name": "assertion.started",
204
+ "attributes": {
205
+ "code.filepath": "GraphConverter.test.ts",
206
+ "code.lineno": 254,
207
+ "assertions": "Verifying position is undefined"
208
+ }
209
+ },
210
+ {
211
+ "time": 1767808091637,
212
+ "name": "assertion.complete",
213
+ "attributes": {
214
+ "code.filepath": "GraphConverter.test.ts",
215
+ "code.lineno": 260,
216
+ "assertions.passed": 1,
217
+ "assertions.failed": 0
218
+ }
219
+ }
220
+ ],
221
+ "status": "OK",
222
+ "endTime": 1767808091637,
223
+ "duration": 0
224
+ }
225
+ ]
@@ -0,0 +1,58 @@
1
+ [
2
+ {
3
+ "id": "span-1",
4
+ "name": "graph conversion with validation",
5
+ "startTime": 1767809672129,
6
+ "attributes": {
7
+ "span.kind": "test.case",
8
+ "test.name": "graph conversion with validation",
9
+ "test.framework": "bun",
10
+ "test.file": "event-validation.test.ts",
11
+ "test.suite": "Event Schema Validation"
12
+ },
13
+ "events": [
14
+ {
15
+ "time": 1767809672129,
16
+ "name": "conversion.started",
17
+ "attributes": {
18
+ "code.filepath": "GraphConverter.ts",
19
+ "code.lineno": 15,
20
+ "config.nodeTypes": 2,
21
+ "config.edgeTypes": 1
22
+ }
23
+ },
24
+ {
25
+ "time": 1767809672129,
26
+ "name": "conversion.processingNodes",
27
+ "attributes": {
28
+ "code.filepath": "GraphConverter.ts",
29
+ "code.lineno": 28,
30
+ "nodes.count": 2
31
+ }
32
+ },
33
+ {
34
+ "time": 1767809672129,
35
+ "name": "conversion.processingEdges",
36
+ "attributes": {
37
+ "code.filepath": "GraphConverter.ts",
38
+ "code.lineno": 45,
39
+ "edges.count": 1
40
+ }
41
+ },
42
+ {
43
+ "time": 1767809672129,
44
+ "name": "conversion.complete",
45
+ "attributes": {
46
+ "code.filepath": "GraphConverter.ts",
47
+ "code.lineno": 60,
48
+ "result.nodes.count": 2,
49
+ "result.edges.count": 1,
50
+ "duration.ms": 5
51
+ }
52
+ }
53
+ ],
54
+ "status": "OK",
55
+ "endTime": 1767809672129,
56
+ "duration": 0
57
+ }
58
+ ]