@principal-ai/principal-studio-cli 0.35.3
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 +172 -0
- package/dist/commands/agent-session.d.ts +3 -0
- package/dist/commands/agent-session.d.ts.map +1 -0
- package/dist/commands/agent-session.js +67 -0
- package/dist/commands/agent-sessions.d.ts +11 -0
- package/dist/commands/agent-sessions.d.ts.map +1 -0
- package/dist/commands/agent-sessions.js +39 -0
- package/dist/commands/auxiliary/index.d.ts +3 -0
- package/dist/commands/auxiliary/index.d.ts.map +1 -0
- package/dist/commands/auxiliary/index.js +9 -0
- package/dist/commands/auxiliary/validate.d.ts +3 -0
- package/dist/commands/auxiliary/validate.d.ts.map +1 -0
- package/dist/commands/auxiliary/validate.js +123 -0
- package/dist/commands/collector/check.d.ts +6 -0
- package/dist/commands/collector/check.d.ts.map +1 -0
- package/dist/commands/collector/check.js +153 -0
- package/dist/commands/collector/diagnose.d.ts +6 -0
- package/dist/commands/collector/diagnose.d.ts.map +1 -0
- package/dist/commands/collector/diagnose.js +229 -0
- package/dist/commands/collector/index.d.ts +6 -0
- package/dist/commands/collector/index.d.ts.map +1 -0
- package/dist/commands/collector/index.js +16 -0
- package/dist/commands/collector/status.d.ts +6 -0
- package/dist/commands/collector/status.d.ts.map +1 -0
- package/dist/commands/collector/status.js +77 -0
- package/dist/commands/collector/utils.d.ts +92 -0
- package/dist/commands/collector/utils.d.ts.map +1 -0
- package/dist/commands/collector/utils.js +154 -0
- package/dist/commands/coverage.d.ts +9 -0
- package/dist/commands/coverage.d.ts.map +1 -0
- package/dist/commands/coverage.js +252 -0
- package/dist/commands/create.d.ts +6 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +50 -0
- package/dist/commands/events/index.d.ts +3 -0
- package/dist/commands/events/index.d.ts.map +1 -0
- package/dist/commands/events/index.js +9 -0
- package/dist/commands/events/validate.d.ts +3 -0
- package/dist/commands/events/validate.d.ts.map +1 -0
- package/dist/commands/events/validate.js +124 -0
- package/dist/commands/formats.d.ts +6 -0
- package/dist/commands/formats.d.ts.map +1 -0
- package/dist/commands/formats.js +1118 -0
- package/dist/commands/hooks.d.ts +9 -0
- package/dist/commands/hooks.d.ts.map +1 -0
- package/dist/commands/hooks.js +295 -0
- package/dist/commands/inbox.d.ts +13 -0
- package/dist/commands/inbox.d.ts.map +1 -0
- package/dist/commands/inbox.js +179 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +220 -0
- package/dist/commands/lint.d.ts +11 -0
- package/dist/commands/lint.d.ts.map +1 -0
- package/dist/commands/lint.js +71 -0
- package/dist/commands/list.d.ts +6 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +78 -0
- package/dist/commands/migrate-nodes.d.ts +9 -0
- package/dist/commands/migrate-nodes.d.ts.map +1 -0
- package/dist/commands/migrate-nodes.js +363 -0
- package/dist/commands/migrate-scopes-to-canvas.d.ts +3 -0
- package/dist/commands/migrate-scopes-to-canvas.d.ts.map +1 -0
- package/dist/commands/migrate-scopes-to-canvas.js +143 -0
- package/dist/commands/migration.d.ts +6 -0
- package/dist/commands/migration.d.ts.map +1 -0
- package/dist/commands/migration.js +247 -0
- package/dist/commands/open-studio.d.ts +10 -0
- package/dist/commands/open-studio.d.ts.map +1 -0
- package/dist/commands/open-studio.js +32 -0
- package/dist/commands/opencode/fetch.d.ts +3 -0
- package/dist/commands/opencode/fetch.d.ts.map +1 -0
- package/dist/commands/opencode/fetch.js +25 -0
- package/dist/commands/opencode/index.d.ts +3 -0
- package/dist/commands/opencode/index.d.ts.map +1 -0
- package/dist/commands/opencode/index.js +11 -0
- package/dist/commands/opencode/list-sessions.d.ts +3 -0
- package/dist/commands/opencode/list-sessions.d.ts.map +1 -0
- package/dist/commands/opencode/list-sessions.js +20 -0
- package/dist/commands/repo.d.ts +18 -0
- package/dist/commands/repo.d.ts.map +1 -0
- package/dist/commands/repo.js +233 -0
- package/dist/commands/schema.d.ts +6 -0
- package/dist/commands/schema.d.ts.map +1 -0
- package/dist/commands/schema.js +367 -0
- package/dist/commands/scopes/index.d.ts +3 -0
- package/dist/commands/scopes/index.d.ts.map +1 -0
- package/dist/commands/scopes/index.js +9 -0
- package/dist/commands/scopes/validate.d.ts +3 -0
- package/dist/commands/scopes/validate.d.ts.map +1 -0
- package/dist/commands/scopes/validate.js +187 -0
- package/dist/commands/setup.d.ts +6 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +406 -0
- package/dist/commands/starred-collections.d.ts +12 -0
- package/dist/commands/starred-collections.d.ts.map +1 -0
- package/dist/commands/starred-collections.js +310 -0
- package/dist/commands/subsystem-model.d.ts +11 -0
- package/dist/commands/subsystem-model.d.ts.map +1 -0
- package/dist/commands/subsystem-model.js +249 -0
- package/dist/commands/topic.d.ts +15 -0
- package/dist/commands/topic.d.ts.map +1 -0
- package/dist/commands/topic.js +683 -0
- package/dist/commands/tour.d.ts +23 -0
- package/dist/commands/tour.d.ts.map +1 -0
- package/dist/commands/tour.js +783 -0
- package/dist/commands/trace/flow.d.ts +6 -0
- package/dist/commands/trace/flow.d.ts.map +1 -0
- package/dist/commands/trace/flow.js +158 -0
- package/dist/commands/trace/index.d.ts +6 -0
- package/dist/commands/trace/index.d.ts.map +1 -0
- package/dist/commands/trace/index.js +20 -0
- package/dist/commands/trace/inspect.d.ts +6 -0
- package/dist/commands/trace/inspect.d.ts.map +1 -0
- package/dist/commands/trace/inspect.js +187 -0
- package/dist/commands/trace/list.d.ts +6 -0
- package/dist/commands/trace/list.d.ts.map +1 -0
- package/dist/commands/trace/list.js +145 -0
- package/dist/commands/trace/registrations.d.ts +6 -0
- package/dist/commands/trace/registrations.d.ts.map +1 -0
- package/dist/commands/trace/registrations.js +81 -0
- package/dist/commands/trace/validate.d.ts +6 -0
- package/dist/commands/trace/validate.d.ts.map +1 -0
- package/dist/commands/trace/validate.js +276 -0
- package/dist/commands/trail.d.ts +36 -0
- package/dist/commands/trail.d.ts.map +1 -0
- package/dist/commands/trail.js +622 -0
- package/dist/commands/validate.d.ts +12 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +3334 -0
- package/dist/commands/workflow/implementation.d.ts +3 -0
- package/dist/commands/workflow/implementation.d.ts.map +1 -0
- package/dist/commands/workflow/implementation.js +51 -0
- package/dist/commands/workflow/index.d.ts +3 -0
- package/dist/commands/workflow/index.d.ts.map +1 -0
- package/dist/commands/workflow/index.js +19 -0
- package/dist/commands/workflow/inspect.d.ts +3 -0
- package/dist/commands/workflow/inspect.d.ts.map +1 -0
- package/dist/commands/workflow/inspect.js +123 -0
- package/dist/commands/workflow/list.d.ts +3 -0
- package/dist/commands/workflow/list.d.ts.map +1 -0
- package/dist/commands/workflow/list.js +95 -0
- package/dist/commands/workflow/render.d.ts +3 -0
- package/dist/commands/workflow/render.d.ts.map +1 -0
- package/dist/commands/workflow/render.js +88 -0
- package/dist/commands/workflow/test.d.ts +3 -0
- package/dist/commands/workflow/test.d.ts.map +1 -0
- package/dist/commands/workflow/test.js +141 -0
- package/dist/commands/workflow/utils.d.ts +49 -0
- package/dist/commands/workflow/utils.d.ts.map +1 -0
- package/dist/commands/workflow/utils.js +164 -0
- package/dist/commands/workflow/validate.d.ts +3 -0
- package/dist/commands/workflow/validate.d.ts.map +1 -0
- package/dist/commands/workflow/validate.js +344 -0
- package/dist/file-utils.d.ts +15 -0
- package/dist/file-utils.d.ts.map +1 -0
- package/dist/file-utils.js +29 -0
- package/dist/index.cjs +285718 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +81 -0
- package/dist/lib/bridge-ipc.d.ts +29 -0
- package/dist/lib/bridge-ipc.d.ts.map +1 -0
- package/dist/lib/bridge-ipc.js +128 -0
- package/dist/lib/github-user.d.ts +17 -0
- package/dist/lib/github-user.d.ts.map +1 -0
- package/dist/lib/github-user.js +53 -0
- package/dist/lib/open-url.d.ts +11 -0
- package/dist/lib/open-url.d.ts.map +1 -0
- package/dist/lib/open-url.js +45 -0
- package/dist/lib/subsystem-model-store.d.ts +74 -0
- package/dist/lib/subsystem-model-store.d.ts.map +1 -0
- package/dist/lib/subsystem-model-store.js +292 -0
- package/dist/lib/tour-cache.d.ts +26 -0
- package/dist/lib/tour-cache.d.ts.map +1 -0
- package/dist/lib/tour-cache.js +46 -0
- package/dist/lib/trail-cache.d.ts +40 -0
- package/dist/lib/trail-cache.d.ts.map +1 -0
- package/dist/lib/trail-cache.js +97 -0
- package/dist/lib/viewer-ipc.d.ts +44 -0
- package/dist/lib/viewer-ipc.d.ts.map +1 -0
- package/dist/lib/viewer-ipc.js +68 -0
- package/package.json +68 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migrate Canvas Node Types
|
|
3
|
+
*
|
|
4
|
+
* Transforms canvas files from the legacy format (type: "text" + pv.nodeType)
|
|
5
|
+
* to the new semantic format (type: "otel-event", "otel-scope", etc.)
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { resolve, relative } from 'node:path';
|
|
10
|
+
import { readFileSync, writeFileSync, existsSync, copyFileSync, readdirSync, statSync } from 'node:fs';
|
|
11
|
+
/**
|
|
12
|
+
* Strip markdown formatting from a string
|
|
13
|
+
* Removes: **bold**, *italic*, __underline__, # headers, `code`, [links](url)
|
|
14
|
+
*/
|
|
15
|
+
function stripMarkdown(text) {
|
|
16
|
+
return text
|
|
17
|
+
.replace(/\*\*/g, '') // Remove bold **
|
|
18
|
+
.replace(/\*/g, '') // Remove italic *
|
|
19
|
+
.replace(/__/g, '') // Remove underline __
|
|
20
|
+
.replace(/_/g, ' ') // Replace _ with space
|
|
21
|
+
.replace(/^#+\s*/gm, '') // Remove headers
|
|
22
|
+
.replace(/`/g, '') // Remove code backticks
|
|
23
|
+
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') // Replace [text](url) with text
|
|
24
|
+
.trim();
|
|
25
|
+
}
|
|
26
|
+
// Node type mapping from pv.nodeType to new type
|
|
27
|
+
const NODE_TYPE_MAP = {
|
|
28
|
+
'event': 'otel-event',
|
|
29
|
+
'span': 'otel-span-convention',
|
|
30
|
+
'span-convention': 'otel-span-convention',
|
|
31
|
+
'scope': 'otel-scope',
|
|
32
|
+
'resource': 'otel-resource',
|
|
33
|
+
'boundary': 'otel-boundary',
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Transform a legacy node to the new format
|
|
37
|
+
*/
|
|
38
|
+
function transformNode(node) {
|
|
39
|
+
// Only transform text nodes with pv.nodeType
|
|
40
|
+
if (node.type !== 'text' || !node.pv?.nodeType) {
|
|
41
|
+
return { transformed: node, changed: false };
|
|
42
|
+
}
|
|
43
|
+
const nodeType = node.pv.nodeType;
|
|
44
|
+
const newType = NODE_TYPE_MAP[nodeType];
|
|
45
|
+
if (!newType) {
|
|
46
|
+
// Unknown nodeType, skip
|
|
47
|
+
return { transformed: node, changed: false };
|
|
48
|
+
}
|
|
49
|
+
const pv = node.pv;
|
|
50
|
+
// Build the new node
|
|
51
|
+
const newNode = {
|
|
52
|
+
id: node.id,
|
|
53
|
+
type: newType,
|
|
54
|
+
x: node.x,
|
|
55
|
+
y: node.y,
|
|
56
|
+
width: node.width,
|
|
57
|
+
height: node.height,
|
|
58
|
+
color: node.color,
|
|
59
|
+
};
|
|
60
|
+
// Add label from pv.name (required for all otel-* nodes)
|
|
61
|
+
// Strip markdown formatting from label
|
|
62
|
+
const rawLabel = pv.name || node.text?.split('\n')[0]?.replace(/^#+ /, '').substring(0, 50) || 'Unnamed';
|
|
63
|
+
const label = stripMarkdown(rawLabel);
|
|
64
|
+
newNode.label = label;
|
|
65
|
+
// Transfer visual properties
|
|
66
|
+
if (pv.icon)
|
|
67
|
+
newNode.icon = pv.icon;
|
|
68
|
+
if (pv.fill)
|
|
69
|
+
newNode.fill = pv.fill;
|
|
70
|
+
if (pv.stroke)
|
|
71
|
+
newNode.stroke = pv.stroke;
|
|
72
|
+
if (pv.shape)
|
|
73
|
+
newNode.shape = pv.shape;
|
|
74
|
+
// Handle type-specific fields
|
|
75
|
+
switch (newType) {
|
|
76
|
+
case 'otel-event': {
|
|
77
|
+
// Transfer event schema
|
|
78
|
+
if (pv.event) {
|
|
79
|
+
newNode.event = pv.event;
|
|
80
|
+
}
|
|
81
|
+
if (pv.eventRef) {
|
|
82
|
+
newNode.eventRef = pv.eventRef;
|
|
83
|
+
}
|
|
84
|
+
if (pv.dataSchema) {
|
|
85
|
+
newNode.dataSchema = pv.dataSchema;
|
|
86
|
+
}
|
|
87
|
+
// Build otel metadata
|
|
88
|
+
const otel = {};
|
|
89
|
+
if (pv.status)
|
|
90
|
+
otel.status = pv.status;
|
|
91
|
+
if (pv.otel?.scope)
|
|
92
|
+
otel.scope = pv.otel.scope;
|
|
93
|
+
if (pv.otel?.files)
|
|
94
|
+
otel.files = pv.otel.files;
|
|
95
|
+
if (pv.otel?.origin)
|
|
96
|
+
otel.origin = pv.otel.origin;
|
|
97
|
+
if (pv.otel?.references)
|
|
98
|
+
otel.references = pv.otel.references;
|
|
99
|
+
if (Object.keys(otel).length > 0) {
|
|
100
|
+
newNode.otel = otel;
|
|
101
|
+
}
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case 'otel-span-convention': {
|
|
105
|
+
// Description for span nodes
|
|
106
|
+
if (pv.description) {
|
|
107
|
+
newNode.description = pv.description;
|
|
108
|
+
}
|
|
109
|
+
// Build otel metadata (spanPattern required)
|
|
110
|
+
const otel = {};
|
|
111
|
+
if (pv.status)
|
|
112
|
+
otel.status = pv.status;
|
|
113
|
+
if (pv.otel?.spanPattern)
|
|
114
|
+
otel.spanPattern = pv.otel.spanPattern;
|
|
115
|
+
if (pv.otel?.spanKind)
|
|
116
|
+
otel.spanKind = pv.otel.spanKind;
|
|
117
|
+
if (pv.otel?.spanMatch)
|
|
118
|
+
otel.spanMatch = pv.otel.spanMatch;
|
|
119
|
+
if (pv.otel?.scope)
|
|
120
|
+
otel.scope = pv.otel.scope;
|
|
121
|
+
if (pv.otel?.files)
|
|
122
|
+
otel.files = pv.otel.files;
|
|
123
|
+
if (pv.otel?.origin)
|
|
124
|
+
otel.origin = pv.otel.origin;
|
|
125
|
+
if (pv.otel?.references)
|
|
126
|
+
otel.references = pv.otel.references;
|
|
127
|
+
newNode.otel = otel;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
case 'otel-scope': {
|
|
131
|
+
// Description for scope nodes
|
|
132
|
+
if (pv.description) {
|
|
133
|
+
newNode.description = pv.description;
|
|
134
|
+
}
|
|
135
|
+
// Build otel metadata (scope required)
|
|
136
|
+
const otel = {};
|
|
137
|
+
if (pv.status)
|
|
138
|
+
otel.status = pv.status;
|
|
139
|
+
if (pv.otel?.scope)
|
|
140
|
+
otel.scope = pv.otel.scope;
|
|
141
|
+
if (pv.otel?.files)
|
|
142
|
+
otel.files = pv.otel.files;
|
|
143
|
+
if (pv.otel?.origin)
|
|
144
|
+
otel.origin = pv.otel.origin;
|
|
145
|
+
if (pv.otel?.references)
|
|
146
|
+
otel.references = pv.otel.references;
|
|
147
|
+
newNode.otel = otel;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case 'otel-resource': {
|
|
151
|
+
// Description for resource nodes
|
|
152
|
+
if (pv.description) {
|
|
153
|
+
newNode.description = pv.description;
|
|
154
|
+
}
|
|
155
|
+
// Build otel metadata (resourceMatch required)
|
|
156
|
+
const otel = {};
|
|
157
|
+
if (pv.status)
|
|
158
|
+
otel.status = pv.status;
|
|
159
|
+
if (pv.otel?.resourceMatch)
|
|
160
|
+
otel.resourceMatch = pv.otel.resourceMatch;
|
|
161
|
+
if (pv.otel?.scope)
|
|
162
|
+
otel.scope = pv.otel.scope;
|
|
163
|
+
if (pv.otel?.files)
|
|
164
|
+
otel.files = pv.otel.files;
|
|
165
|
+
if (pv.otel?.origin)
|
|
166
|
+
otel.origin = pv.otel.origin;
|
|
167
|
+
if (pv.otel?.references)
|
|
168
|
+
otel.references = pv.otel.references;
|
|
169
|
+
newNode.otel = otel;
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
case 'otel-boundary': {
|
|
173
|
+
// Description for boundary nodes
|
|
174
|
+
if (pv.description) {
|
|
175
|
+
newNode.description = pv.description;
|
|
176
|
+
}
|
|
177
|
+
// Build otel metadata
|
|
178
|
+
const otel = {};
|
|
179
|
+
if (pv.status)
|
|
180
|
+
otel.status = pv.status;
|
|
181
|
+
if (pv.otel?.scope)
|
|
182
|
+
otel.scope = pv.otel.scope;
|
|
183
|
+
if (pv.otel?.files)
|
|
184
|
+
otel.files = pv.otel.files;
|
|
185
|
+
if (pv.otel?.origin)
|
|
186
|
+
otel.origin = pv.otel.origin;
|
|
187
|
+
if (pv.otel?.references)
|
|
188
|
+
otel.references = pv.otel.references;
|
|
189
|
+
if (Object.keys(otel).length > 0) {
|
|
190
|
+
newNode.otel = otel;
|
|
191
|
+
}
|
|
192
|
+
// Transfer boundary data
|
|
193
|
+
if (pv.boundary) {
|
|
194
|
+
newNode.boundary = pv.boundary;
|
|
195
|
+
}
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return { transformed: newNode, changed: true };
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Migrate a single canvas file
|
|
203
|
+
*/
|
|
204
|
+
function migrateCanvas(filePath, options) {
|
|
205
|
+
const result = {
|
|
206
|
+
path: filePath,
|
|
207
|
+
nodesTransformed: 0,
|
|
208
|
+
nodesSkipped: 0,
|
|
209
|
+
errors: [],
|
|
210
|
+
};
|
|
211
|
+
try {
|
|
212
|
+
// Read the canvas file
|
|
213
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
214
|
+
const canvas = JSON.parse(content);
|
|
215
|
+
if (!canvas.nodes || canvas.nodes.length === 0) {
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
// Transform each node
|
|
219
|
+
const newNodes = [];
|
|
220
|
+
for (const node of canvas.nodes) {
|
|
221
|
+
const { transformed, changed } = transformNode(node);
|
|
222
|
+
newNodes.push(transformed);
|
|
223
|
+
if (changed) {
|
|
224
|
+
result.nodesTransformed++;
|
|
225
|
+
if (options.verbose) {
|
|
226
|
+
// If changed, we know it was a text node with pv.nodeType
|
|
227
|
+
const oldType = (node.type === 'text' && 'pv' in node && node.pv?.nodeType)
|
|
228
|
+
? `text+${node.pv.nodeType}`
|
|
229
|
+
: node.type;
|
|
230
|
+
console.log(chalk.gray(` • Transformed node "${node.id}" from ${oldType} to ${transformed.type}`));
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
result.nodesSkipped++;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Only write if there were changes
|
|
238
|
+
if (result.nodesTransformed > 0) {
|
|
239
|
+
// Create backup if requested
|
|
240
|
+
if (options.backup && !options.dryRun) {
|
|
241
|
+
const backupPath = filePath + '.backup';
|
|
242
|
+
copyFileSync(filePath, backupPath);
|
|
243
|
+
result.backup = backupPath;
|
|
244
|
+
}
|
|
245
|
+
// Write the migrated canvas
|
|
246
|
+
if (!options.dryRun) {
|
|
247
|
+
const newCanvas = { ...canvas, nodes: newNodes };
|
|
248
|
+
// Preserve the original formatting (2-space indent)
|
|
249
|
+
writeFileSync(filePath, JSON.stringify(newCanvas, null, 2) + '\n');
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
result.errors.push(error.message);
|
|
255
|
+
}
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Find all canvas files in a directory
|
|
260
|
+
*/
|
|
261
|
+
function findCanvasFiles(dir) {
|
|
262
|
+
const files = [];
|
|
263
|
+
function walkDir(currentPath) {
|
|
264
|
+
const entries = readdirSync(currentPath);
|
|
265
|
+
for (const entry of entries) {
|
|
266
|
+
// Skip node_modules and hidden directories
|
|
267
|
+
if (entry === 'node_modules' || entry.startsWith('.')) {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
const fullPath = resolve(currentPath, entry);
|
|
271
|
+
const stat = statSync(fullPath);
|
|
272
|
+
if (stat.isDirectory()) {
|
|
273
|
+
walkDir(fullPath);
|
|
274
|
+
}
|
|
275
|
+
else if (entry.endsWith('.canvas') || entry.endsWith('.otel.canvas')) {
|
|
276
|
+
files.push(fullPath);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
walkDir(dir);
|
|
281
|
+
return files;
|
|
282
|
+
}
|
|
283
|
+
export function createMigrateNodesCommand() {
|
|
284
|
+
const command = new Command('migrate-nodes');
|
|
285
|
+
command
|
|
286
|
+
.description('Migrate canvas files from legacy node format to new semantic types')
|
|
287
|
+
.argument('[path]', 'Path to canvas file or directory (default: .principal-views)')
|
|
288
|
+
.option('--dry-run', 'Show what would be changed without modifying files')
|
|
289
|
+
.option('--no-backup', 'Do not create backup files')
|
|
290
|
+
.option('-d, --dir <path>', 'Base directory (default: cwd)')
|
|
291
|
+
.option('-v, --verbose', 'Show detailed transformation info')
|
|
292
|
+
.action(async (path, options) => {
|
|
293
|
+
try {
|
|
294
|
+
const baseDir = options.dir || process.cwd();
|
|
295
|
+
const targetPath = path ? resolve(baseDir, path) : resolve(baseDir, '.principal-views');
|
|
296
|
+
if (!existsSync(targetPath)) {
|
|
297
|
+
console.error(chalk.red('Error:'), `Path not found: ${targetPath}`);
|
|
298
|
+
process.exit(1);
|
|
299
|
+
}
|
|
300
|
+
// Find canvas files
|
|
301
|
+
let canvasFiles;
|
|
302
|
+
const stat = statSync(targetPath);
|
|
303
|
+
if (stat.isDirectory()) {
|
|
304
|
+
canvasFiles = findCanvasFiles(targetPath);
|
|
305
|
+
console.log(chalk.bold(`\nMigrating canvas files in: ${relative(baseDir, targetPath)}\n`));
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
canvasFiles = [targetPath];
|
|
309
|
+
console.log(chalk.bold(`\nMigrating canvas file: ${relative(baseDir, targetPath)}\n`));
|
|
310
|
+
}
|
|
311
|
+
if (canvasFiles.length === 0) {
|
|
312
|
+
console.log(chalk.yellow('No canvas files found.'));
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (options.dryRun) {
|
|
316
|
+
console.log(chalk.cyan('Dry run mode - no files will be modified\n'));
|
|
317
|
+
}
|
|
318
|
+
// Migrate each file
|
|
319
|
+
let totalTransformed = 0;
|
|
320
|
+
let totalSkipped = 0;
|
|
321
|
+
let filesModified = 0;
|
|
322
|
+
for (const filePath of canvasFiles) {
|
|
323
|
+
const relativePath = relative(baseDir, filePath);
|
|
324
|
+
const result = migrateCanvas(filePath, { ...options, backup: options.backup !== false });
|
|
325
|
+
if (result.errors.length > 0) {
|
|
326
|
+
console.log(chalk.red('✗'), relativePath);
|
|
327
|
+
for (const error of result.errors) {
|
|
328
|
+
console.log(chalk.red(` Error: ${error}`));
|
|
329
|
+
}
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (result.nodesTransformed > 0) {
|
|
333
|
+
filesModified++;
|
|
334
|
+
console.log(chalk.green('✓'), relativePath);
|
|
335
|
+
console.log(chalk.gray(` ${result.nodesTransformed} node(s) transformed, ${result.nodesSkipped} skipped`));
|
|
336
|
+
if (result.backup) {
|
|
337
|
+
console.log(chalk.gray(` Backup: ${relative(baseDir, result.backup)}`));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
else if (options.verbose) {
|
|
341
|
+
console.log(chalk.gray('○'), relativePath, chalk.gray('(no changes needed)'));
|
|
342
|
+
}
|
|
343
|
+
totalTransformed += result.nodesTransformed;
|
|
344
|
+
totalSkipped += result.nodesSkipped;
|
|
345
|
+
}
|
|
346
|
+
// Summary
|
|
347
|
+
console.log(chalk.bold('\nSummary:'));
|
|
348
|
+
console.log(chalk.gray(` • Files processed: ${canvasFiles.length}`));
|
|
349
|
+
console.log(chalk.gray(` • Files modified: ${filesModified}`));
|
|
350
|
+
console.log(chalk.gray(` • Nodes transformed: ${totalTransformed}`));
|
|
351
|
+
console.log(chalk.gray(` • Nodes skipped: ${totalSkipped}`));
|
|
352
|
+
if (options.dryRun && totalTransformed > 0) {
|
|
353
|
+
console.log(chalk.cyan('\nRun without --dry-run to apply changes.'));
|
|
354
|
+
}
|
|
355
|
+
console.log();
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
console.error(chalk.red('Error:'), error.message);
|
|
359
|
+
process.exit(1);
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
return command;
|
|
363
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-scopes-to-canvas.d.ts","sourceRoot":"","sources":["../../src/commands/migrate-scopes-to-canvas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0BpC,wBAAgB,0BAA0B,IAAI,OAAO,CAkJpD"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { resolve, relative } from 'node:path';
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
5
|
+
import yaml from 'js-yaml';
|
|
6
|
+
export function createMigrateScopesCommand() {
|
|
7
|
+
const command = new Command('scopes-to-canvas');
|
|
8
|
+
command
|
|
9
|
+
.description('Migrate scopes from library.yaml to .scopes.canvas')
|
|
10
|
+
.option('--dry-run', 'Preview changes without writing files')
|
|
11
|
+
.option('--force', 'Overwrite existing scope nodes in canvas')
|
|
12
|
+
.option('-d, --dir <path>', 'Project directory (default: cwd)')
|
|
13
|
+
.option('-o, --output <path>', 'Output path for scopes canvas')
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
const baseDir = resolve(options.dir || process.cwd());
|
|
16
|
+
// 1. Load library.yaml
|
|
17
|
+
const libraryPath = resolve(baseDir, '.principal-views/library.yaml');
|
|
18
|
+
if (!existsSync(libraryPath)) {
|
|
19
|
+
console.error(chalk.red('✗ Error: library.yaml not found at .principal-views/library.yaml'));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const library = yaml.load(readFileSync(libraryPath, 'utf-8'));
|
|
23
|
+
if (!library.scopes || Object.keys(library.scopes).length === 0) {
|
|
24
|
+
console.log(chalk.green('✓ No scopes section found - nothing to migrate'));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// 2. Find or create scopes canvas
|
|
28
|
+
const scopesCanvasPath = options.output || findScopesCanvasPath(baseDir) || resolve(baseDir, '.principal-views/architecture.scopes.canvas');
|
|
29
|
+
let scopesCanvas;
|
|
30
|
+
const existingScopes = new Set();
|
|
31
|
+
if (existsSync(scopesCanvasPath)) {
|
|
32
|
+
scopesCanvas = JSON.parse(readFileSync(scopesCanvasPath, 'utf-8'));
|
|
33
|
+
// Track existing scopes
|
|
34
|
+
for (const node of scopesCanvas.nodes || []) {
|
|
35
|
+
if (node.type === 'otel-scope' && node.otel?.scope) {
|
|
36
|
+
existingScopes.add(node.otel.scope);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
scopesCanvas = {
|
|
42
|
+
name: 'Instrumentation Scopes',
|
|
43
|
+
description: 'Defines instrumentation scopes for the application',
|
|
44
|
+
nodes: [],
|
|
45
|
+
edges: [],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// 3. Convert scopes to nodes
|
|
49
|
+
const scopeEntries = Object.entries(library.scopes);
|
|
50
|
+
const added = [];
|
|
51
|
+
const skipped = [];
|
|
52
|
+
const overwritten = [];
|
|
53
|
+
// Calculate starting X position (append to right of existing nodes)
|
|
54
|
+
let maxX = 0;
|
|
55
|
+
for (const node of scopesCanvas.nodes || []) {
|
|
56
|
+
const nodeMaxX = node.x + (node.width || 200);
|
|
57
|
+
maxX = Math.max(maxX, nodeMaxX);
|
|
58
|
+
}
|
|
59
|
+
let x = maxX > 0 ? maxX + 50 : 0;
|
|
60
|
+
for (const [scopeName, scopeDef] of scopeEntries) {
|
|
61
|
+
const existsInCanvas = existingScopes.has(scopeName);
|
|
62
|
+
if (existsInCanvas && !options.force) {
|
|
63
|
+
skipped.push(scopeName);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (existsInCanvas && options.force) {
|
|
67
|
+
// Remove existing node
|
|
68
|
+
scopesCanvas.nodes =
|
|
69
|
+
scopesCanvas.nodes?.filter(n => !(n.type === 'otel-scope' && n.otel?.scope === scopeName)) || [];
|
|
70
|
+
overwritten.push(scopeName);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
added.push(scopeName);
|
|
74
|
+
}
|
|
75
|
+
// Create new node
|
|
76
|
+
const newNode = {
|
|
77
|
+
id: `${scopeName}-scope`,
|
|
78
|
+
type: 'otel-scope',
|
|
79
|
+
label: scopeDef.description || scopeName,
|
|
80
|
+
color: scopeDef.color,
|
|
81
|
+
description: scopeDef.description,
|
|
82
|
+
x,
|
|
83
|
+
y: 0,
|
|
84
|
+
width: 200,
|
|
85
|
+
height: 80,
|
|
86
|
+
otel: {
|
|
87
|
+
scope: scopeName,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
// Add icon if present
|
|
91
|
+
if (scopeDef.icon) {
|
|
92
|
+
newNode.icon = scopeDef.icon;
|
|
93
|
+
}
|
|
94
|
+
scopesCanvas.nodes = scopesCanvas.nodes || [];
|
|
95
|
+
scopesCanvas.nodes.push(newNode);
|
|
96
|
+
x += 250; // Space nodes horizontally
|
|
97
|
+
}
|
|
98
|
+
// 4. Report results
|
|
99
|
+
console.log(chalk.bold('\nScope Migration Summary\n'));
|
|
100
|
+
console.log('━'.repeat(60));
|
|
101
|
+
if (added.length > 0) {
|
|
102
|
+
console.log(chalk.green(`✓ Added ${added.length} scope(s):`));
|
|
103
|
+
added.forEach(s => console.log(chalk.gray(` • ${s}`)));
|
|
104
|
+
}
|
|
105
|
+
if (skipped.length > 0) {
|
|
106
|
+
console.log(chalk.yellow(`\n⊘ Skipped ${skipped.length} scope(s) (already in canvas):`));
|
|
107
|
+
skipped.forEach(s => console.log(chalk.gray(` • ${s}`)));
|
|
108
|
+
console.log(chalk.gray(` Run with --force to overwrite existing nodes`));
|
|
109
|
+
}
|
|
110
|
+
if (overwritten.length > 0) {
|
|
111
|
+
console.log(chalk.cyan(`\n↻ Overwritten ${overwritten.length} scope(s):`));
|
|
112
|
+
overwritten.forEach(s => console.log(chalk.gray(` • ${s}`)));
|
|
113
|
+
}
|
|
114
|
+
// 5. Write canvas (unless dry run)
|
|
115
|
+
const relativePath = relative(baseDir, scopesCanvasPath);
|
|
116
|
+
if (!options.dryRun) {
|
|
117
|
+
writeFileSync(scopesCanvasPath, JSON.stringify(scopesCanvas, null, 2) + '\n');
|
|
118
|
+
console.log(chalk.green(`\n✓ Wrote ${relativePath}`));
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
console.log(chalk.cyan(`\n[DRY RUN] Would write to: ${relativePath}`));
|
|
122
|
+
}
|
|
123
|
+
// 6. Next steps
|
|
124
|
+
console.log(chalk.bold('\nNext Steps:'));
|
|
125
|
+
console.log(chalk.gray(' 1. Review the generated .scopes.canvas file'));
|
|
126
|
+
console.log(chalk.gray(' 2. Remove the "scopes:" section from library.yaml'));
|
|
127
|
+
console.log(chalk.gray(' 3. Run "pv validate" to verify the migration'));
|
|
128
|
+
console.log();
|
|
129
|
+
});
|
|
130
|
+
return command;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Find existing .scopes.canvas file in project
|
|
134
|
+
*/
|
|
135
|
+
function findScopesCanvasPath(baseDir) {
|
|
136
|
+
const candidates = ['.principal-views/architecture.scopes.canvas', '.principal-views/scopes.canvas'];
|
|
137
|
+
for (const candidate of candidates) {
|
|
138
|
+
const path = resolve(baseDir, candidate);
|
|
139
|
+
if (existsSync(path))
|
|
140
|
+
return path;
|
|
141
|
+
}
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/commands/migration.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4OpC,wBAAgB,sBAAsB,IAAI,OAAO,CAWhD"}
|