@principal-ai/principal-view-cli 0.1.13 → 0.1.15
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 +2 -2
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +6 -9
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +322 -35
- package/dist/index.cjs +289 -52
- package/dist/index.cjs.map +3 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -13464,18 +13464,162 @@ function loadLibrary(principalViewsDir) {
|
|
|
13464
13464
|
if (library && typeof library === "object") {
|
|
13465
13465
|
return {
|
|
13466
13466
|
nodeComponents: library.nodeComponents || {},
|
|
13467
|
-
edgeComponents: library.edgeComponents || {}
|
|
13467
|
+
edgeComponents: library.edgeComponents || {},
|
|
13468
|
+
raw: library,
|
|
13469
|
+
path: libraryPath
|
|
13468
13470
|
};
|
|
13469
13471
|
}
|
|
13470
13472
|
} catch {
|
|
13471
|
-
return { nodeComponents: {}, edgeComponents: {} };
|
|
13473
|
+
return { nodeComponents: {}, edgeComponents: {}, raw: {}, path: libraryPath };
|
|
13472
13474
|
}
|
|
13473
13475
|
}
|
|
13474
13476
|
}
|
|
13475
13477
|
return null;
|
|
13476
13478
|
}
|
|
13479
|
+
function validateLibrary(library) {
|
|
13480
|
+
const issues = [];
|
|
13481
|
+
const lib = library.raw;
|
|
13482
|
+
checkUnknownFields(lib, ALLOWED_LIBRARY_FIELDS.root, "", issues);
|
|
13483
|
+
if (lib.nodeComponents && typeof lib.nodeComponents === "object") {
|
|
13484
|
+
for (const [compId, compDef] of Object.entries(lib.nodeComponents)) {
|
|
13485
|
+
if (compDef && typeof compDef === "object") {
|
|
13486
|
+
const comp = compDef;
|
|
13487
|
+
checkUnknownFields(comp, ALLOWED_LIBRARY_FIELDS.nodeComponent, `nodeComponents.${compId}`, issues);
|
|
13488
|
+
if (comp.size && typeof comp.size === "object") {
|
|
13489
|
+
checkUnknownFields(comp.size, ALLOWED_LIBRARY_FIELDS.nodeComponentSize, `nodeComponents.${compId}.size`, issues);
|
|
13490
|
+
}
|
|
13491
|
+
if (comp.states && typeof comp.states === "object") {
|
|
13492
|
+
for (const [stateId, stateDef] of Object.entries(comp.states)) {
|
|
13493
|
+
if (stateDef && typeof stateDef === "object") {
|
|
13494
|
+
checkUnknownFields(stateDef, ALLOWED_LIBRARY_FIELDS.nodeComponentState, `nodeComponents.${compId}.states.${stateId}`, issues);
|
|
13495
|
+
}
|
|
13496
|
+
}
|
|
13497
|
+
}
|
|
13498
|
+
if (comp.dataSchema && typeof comp.dataSchema === "object") {
|
|
13499
|
+
for (const [fieldName, fieldDef] of Object.entries(comp.dataSchema)) {
|
|
13500
|
+
if (fieldDef && typeof fieldDef === "object") {
|
|
13501
|
+
checkUnknownFields(fieldDef, ALLOWED_LIBRARY_FIELDS.nodeComponentDataSchemaField, `nodeComponents.${compId}.dataSchema.${fieldName}`, issues);
|
|
13502
|
+
}
|
|
13503
|
+
}
|
|
13504
|
+
}
|
|
13505
|
+
if (comp.layout && typeof comp.layout === "object") {
|
|
13506
|
+
checkUnknownFields(comp.layout, ALLOWED_LIBRARY_FIELDS.nodeComponentLayout, `nodeComponents.${compId}.layout`, issues);
|
|
13507
|
+
}
|
|
13508
|
+
if (Array.isArray(comp.actions)) {
|
|
13509
|
+
comp.actions.forEach((action, actionIndex) => {
|
|
13510
|
+
if (action && typeof action === "object") {
|
|
13511
|
+
checkUnknownFields(action, ALLOWED_LIBRARY_FIELDS.nodeComponentAction, `nodeComponents.${compId}.actions[${actionIndex}]`, issues);
|
|
13512
|
+
}
|
|
13513
|
+
});
|
|
13514
|
+
}
|
|
13515
|
+
}
|
|
13516
|
+
}
|
|
13517
|
+
}
|
|
13518
|
+
if (lib.edgeComponents && typeof lib.edgeComponents === "object") {
|
|
13519
|
+
for (const [compId, compDef] of Object.entries(lib.edgeComponents)) {
|
|
13520
|
+
if (compDef && typeof compDef === "object") {
|
|
13521
|
+
const comp = compDef;
|
|
13522
|
+
checkUnknownFields(comp, ALLOWED_LIBRARY_FIELDS.edgeComponent, `edgeComponents.${compId}`, issues);
|
|
13523
|
+
if (comp.animation && typeof comp.animation === "object") {
|
|
13524
|
+
checkUnknownFields(comp.animation, ALLOWED_LIBRARY_FIELDS.edgeComponentAnimation, `edgeComponents.${compId}.animation`, issues);
|
|
13525
|
+
}
|
|
13526
|
+
if (comp.label && typeof comp.label === "object") {
|
|
13527
|
+
checkUnknownFields(comp.label, ALLOWED_LIBRARY_FIELDS.edgeComponentLabel, `edgeComponents.${compId}.label`, issues);
|
|
13528
|
+
}
|
|
13529
|
+
}
|
|
13530
|
+
}
|
|
13531
|
+
}
|
|
13532
|
+
if (Array.isArray(lib.connectionRules)) {
|
|
13533
|
+
lib.connectionRules.forEach((rule, ruleIndex) => {
|
|
13534
|
+
if (rule && typeof rule === "object") {
|
|
13535
|
+
const r = rule;
|
|
13536
|
+
checkUnknownFields(r, ALLOWED_LIBRARY_FIELDS.connectionRule, `connectionRules[${ruleIndex}]`, issues);
|
|
13537
|
+
if (r.constraints && typeof r.constraints === "object") {
|
|
13538
|
+
checkUnknownFields(r.constraints, ALLOWED_LIBRARY_FIELDS.connectionRuleConstraints, `connectionRules[${ruleIndex}].constraints`, issues);
|
|
13539
|
+
}
|
|
13540
|
+
}
|
|
13541
|
+
});
|
|
13542
|
+
}
|
|
13543
|
+
return issues;
|
|
13544
|
+
}
|
|
13477
13545
|
var STANDARD_CANVAS_TYPES = ["text", "group", "file", "link"];
|
|
13478
13546
|
var VALID_NODE_SHAPES = ["circle", "rectangle", "hexagon", "diamond", "custom"];
|
|
13547
|
+
var ALLOWED_CANVAS_FIELDS = {
|
|
13548
|
+
root: ["nodes", "edges", "pv"],
|
|
13549
|
+
pv: ["version", "name", "description", "nodeTypes", "edgeTypes", "pathConfig", "display"],
|
|
13550
|
+
pvPathConfig: ["projectRoot", "captureSource", "enableActionPatterns", "logLevel", "ignoreUnsourced"],
|
|
13551
|
+
pvDisplay: ["layout", "theme", "animations"],
|
|
13552
|
+
pvDisplayTheme: ["primary", "success", "warning", "danger", "info"],
|
|
13553
|
+
pvDisplayAnimations: ["enabled", "speed"],
|
|
13554
|
+
pvNodeType: ["label", "description", "color", "icon", "shape"],
|
|
13555
|
+
pvEdgeType: ["label", "style", "color", "width", "directed", "animation", "labelConfig", "activatedBy"],
|
|
13556
|
+
pvEdgeTypeAnimation: ["type", "duration", "color"],
|
|
13557
|
+
pvEdgeTypeLabelConfig: ["field", "position"],
|
|
13558
|
+
// Base node fields from JSON Canvas spec
|
|
13559
|
+
nodeBase: ["id", "type", "x", "y", "width", "height", "color", "pv"],
|
|
13560
|
+
// Type-specific node fields
|
|
13561
|
+
nodeText: ["text"],
|
|
13562
|
+
nodeFile: ["file", "subpath"],
|
|
13563
|
+
nodeLink: ["url"],
|
|
13564
|
+
nodeGroup: ["label", "background", "backgroundStyle"],
|
|
13565
|
+
// Node pv extension
|
|
13566
|
+
nodePv: ["nodeType", "description", "shape", "icon", "fill", "stroke", "states", "sources", "actions", "dataSchema", "layout"],
|
|
13567
|
+
nodePvState: ["color", "icon", "label"],
|
|
13568
|
+
nodePvAction: ["pattern", "event", "state", "metadata", "triggerEdges"],
|
|
13569
|
+
nodePvDataSchemaField: ["type", "required", "displayInLabel"],
|
|
13570
|
+
nodePvLayout: ["layer", "cluster"],
|
|
13571
|
+
// Edge fields
|
|
13572
|
+
edge: ["id", "fromNode", "toNode", "fromSide", "toSide", "fromEnd", "toEnd", "color", "label", "pv"],
|
|
13573
|
+
edgePv: ["edgeType", "style", "width", "animation", "activatedBy"],
|
|
13574
|
+
edgePvAnimation: ["type", "duration", "color"],
|
|
13575
|
+
edgePvActivatedBy: ["action", "animation", "direction", "duration"]
|
|
13576
|
+
};
|
|
13577
|
+
var ALLOWED_LIBRARY_FIELDS = {
|
|
13578
|
+
root: ["version", "name", "description", "nodeComponents", "edgeComponents", "connectionRules"],
|
|
13579
|
+
nodeComponent: ["description", "tags", "defaultLabel", "shape", "icon", "color", "size", "states", "sources", "actions", "dataSchema", "layout"],
|
|
13580
|
+
nodeComponentSize: ["width", "height"],
|
|
13581
|
+
nodeComponentState: ["color", "icon", "label"],
|
|
13582
|
+
nodeComponentAction: ["pattern", "event", "state", "metadata", "triggerEdges"],
|
|
13583
|
+
nodeComponentDataSchemaField: ["type", "required", "displayInLabel", "label", "displayInInfo"],
|
|
13584
|
+
nodeComponentLayout: ["layer", "cluster"],
|
|
13585
|
+
edgeComponent: ["description", "tags", "style", "color", "width", "directed", "animation", "label"],
|
|
13586
|
+
edgeComponentAnimation: ["type", "duration", "color"],
|
|
13587
|
+
edgeComponentLabel: ["field", "position"],
|
|
13588
|
+
connectionRule: ["from", "to", "via", "constraints"],
|
|
13589
|
+
connectionRuleConstraints: ["maxInstances", "bidirectional", "exclusive"]
|
|
13590
|
+
};
|
|
13591
|
+
function checkUnknownFields(obj, allowedFields, path4, issues) {
|
|
13592
|
+
for (const field of Object.keys(obj)) {
|
|
13593
|
+
if (!allowedFields.includes(field)) {
|
|
13594
|
+
const suggestion = findSimilarField(field, allowedFields);
|
|
13595
|
+
issues.push({
|
|
13596
|
+
type: "error",
|
|
13597
|
+
message: `Unknown field "${field}"${path4 ? ` in ${path4}` : " at root level"}`,
|
|
13598
|
+
path: path4 ? `${path4}.${field}` : field,
|
|
13599
|
+
suggestion: suggestion ? `Did you mean "${suggestion}"? Allowed fields: ${allowedFields.join(", ")}` : `Allowed fields: ${allowedFields.join(", ")}`
|
|
13600
|
+
});
|
|
13601
|
+
}
|
|
13602
|
+
}
|
|
13603
|
+
}
|
|
13604
|
+
function findSimilarField(field, allowedFields) {
|
|
13605
|
+
const fieldLower = field.toLowerCase();
|
|
13606
|
+
for (const allowed of allowedFields) {
|
|
13607
|
+
const allowedLower = allowed.toLowerCase();
|
|
13608
|
+
if (fieldLower.includes(allowedLower) || allowedLower.includes(fieldLower)) {
|
|
13609
|
+
return allowed;
|
|
13610
|
+
}
|
|
13611
|
+
if (Math.abs(field.length - allowed.length) <= 2) {
|
|
13612
|
+
let differences = 0;
|
|
13613
|
+
const minLen = Math.min(fieldLower.length, allowedLower.length);
|
|
13614
|
+
for (let i = 0; i < minLen; i++) {
|
|
13615
|
+
if (fieldLower[i] !== allowedLower[i]) differences++;
|
|
13616
|
+
}
|
|
13617
|
+
differences += Math.abs(field.length - allowed.length);
|
|
13618
|
+
if (differences <= 2) return allowed;
|
|
13619
|
+
}
|
|
13620
|
+
}
|
|
13621
|
+
return null;
|
|
13622
|
+
}
|
|
13479
13623
|
function validateCanvas(canvas, filePath, library) {
|
|
13480
13624
|
const issues = [];
|
|
13481
13625
|
if (!canvas || typeof canvas !== "object") {
|
|
@@ -13483,6 +13627,7 @@ function validateCanvas(canvas, filePath, library) {
|
|
|
13483
13627
|
return issues;
|
|
13484
13628
|
}
|
|
13485
13629
|
const c = canvas;
|
|
13630
|
+
checkUnknownFields(c, ALLOWED_CANVAS_FIELDS.root, "", issues);
|
|
13486
13631
|
const libraryNodeTypes = library ? Object.keys(library.nodeComponents) : [];
|
|
13487
13632
|
const libraryEdgeTypes = library ? Object.keys(library.edgeComponents) : [];
|
|
13488
13633
|
let canvasEdgeTypes = [];
|
|
@@ -13498,6 +13643,7 @@ function validateCanvas(canvas, filePath, library) {
|
|
|
13498
13643
|
issues.push({ type: "error", message: '"pv" extension must be an object' });
|
|
13499
13644
|
} else {
|
|
13500
13645
|
const pv = c.pv;
|
|
13646
|
+
checkUnknownFields(pv, ALLOWED_CANVAS_FIELDS.pv, "pv", issues);
|
|
13501
13647
|
if (typeof pv.version !== "string" || !pv.version) {
|
|
13502
13648
|
issues.push({
|
|
13503
13649
|
type: "error",
|
|
@@ -13514,11 +13660,41 @@ function validateCanvas(canvas, filePath, library) {
|
|
|
13514
13660
|
suggestion: 'Add: "name": "My Graph"'
|
|
13515
13661
|
});
|
|
13516
13662
|
}
|
|
13517
|
-
if (pv.
|
|
13518
|
-
|
|
13663
|
+
if (pv.pathConfig && typeof pv.pathConfig === "object") {
|
|
13664
|
+
checkUnknownFields(pv.pathConfig, ALLOWED_CANVAS_FIELDS.pvPathConfig, "pv.pathConfig", issues);
|
|
13665
|
+
}
|
|
13666
|
+
if (pv.display && typeof pv.display === "object") {
|
|
13667
|
+
const display = pv.display;
|
|
13668
|
+
checkUnknownFields(display, ALLOWED_CANVAS_FIELDS.pvDisplay, "pv.display", issues);
|
|
13669
|
+
if (display.theme && typeof display.theme === "object") {
|
|
13670
|
+
checkUnknownFields(display.theme, ALLOWED_CANVAS_FIELDS.pvDisplayTheme, "pv.display.theme", issues);
|
|
13671
|
+
}
|
|
13672
|
+
if (display.animations && typeof display.animations === "object") {
|
|
13673
|
+
checkUnknownFields(display.animations, ALLOWED_CANVAS_FIELDS.pvDisplayAnimations, "pv.display.animations", issues);
|
|
13674
|
+
}
|
|
13519
13675
|
}
|
|
13520
13676
|
if (pv.nodeTypes && typeof pv.nodeTypes === "object") {
|
|
13521
13677
|
canvasNodeTypes = Object.keys(pv.nodeTypes);
|
|
13678
|
+
for (const [typeId, typeDef] of Object.entries(pv.nodeTypes)) {
|
|
13679
|
+
if (typeDef && typeof typeDef === "object") {
|
|
13680
|
+
checkUnknownFields(typeDef, ALLOWED_CANVAS_FIELDS.pvNodeType, `pv.nodeTypes.${typeId}`, issues);
|
|
13681
|
+
}
|
|
13682
|
+
}
|
|
13683
|
+
}
|
|
13684
|
+
if (pv.edgeTypes && typeof pv.edgeTypes === "object") {
|
|
13685
|
+
canvasEdgeTypes = Object.keys(pv.edgeTypes);
|
|
13686
|
+
for (const [typeId, typeDef] of Object.entries(pv.edgeTypes)) {
|
|
13687
|
+
if (typeDef && typeof typeDef === "object") {
|
|
13688
|
+
const edgeTypeDef = typeDef;
|
|
13689
|
+
checkUnknownFields(edgeTypeDef, ALLOWED_CANVAS_FIELDS.pvEdgeType, `pv.edgeTypes.${typeId}`, issues);
|
|
13690
|
+
if (edgeTypeDef.animation && typeof edgeTypeDef.animation === "object") {
|
|
13691
|
+
checkUnknownFields(edgeTypeDef.animation, ALLOWED_CANVAS_FIELDS.pvEdgeTypeAnimation, `pv.edgeTypes.${typeId}.animation`, issues);
|
|
13692
|
+
}
|
|
13693
|
+
if (edgeTypeDef.labelConfig && typeof edgeTypeDef.labelConfig === "object") {
|
|
13694
|
+
checkUnknownFields(edgeTypeDef.labelConfig, ALLOWED_CANVAS_FIELDS.pvEdgeTypeLabelConfig, `pv.edgeTypes.${typeId}.labelConfig`, issues);
|
|
13695
|
+
}
|
|
13696
|
+
}
|
|
13697
|
+
}
|
|
13522
13698
|
}
|
|
13523
13699
|
}
|
|
13524
13700
|
const allDefinedNodeTypes = [.../* @__PURE__ */ new Set([...canvasNodeTypes, ...libraryNodeTypes])];
|
|
@@ -13532,25 +13708,38 @@ function validateCanvas(canvas, filePath, library) {
|
|
|
13532
13708
|
return;
|
|
13533
13709
|
}
|
|
13534
13710
|
const n = node;
|
|
13711
|
+
const nodePath2 = `nodes[${index}]`;
|
|
13712
|
+
const nodeLabel = n.id || index;
|
|
13713
|
+
const nodeType = n.type;
|
|
13714
|
+
let allowedNodeFields = [...ALLOWED_CANVAS_FIELDS.nodeBase];
|
|
13715
|
+
if (nodeType === "text") {
|
|
13716
|
+
allowedNodeFields = [...allowedNodeFields, ...ALLOWED_CANVAS_FIELDS.nodeText];
|
|
13717
|
+
} else if (nodeType === "file") {
|
|
13718
|
+
allowedNodeFields = [...allowedNodeFields, ...ALLOWED_CANVAS_FIELDS.nodeFile];
|
|
13719
|
+
} else if (nodeType === "link") {
|
|
13720
|
+
allowedNodeFields = [...allowedNodeFields, ...ALLOWED_CANVAS_FIELDS.nodeLink];
|
|
13721
|
+
} else if (nodeType === "group") {
|
|
13722
|
+
allowedNodeFields = [...allowedNodeFields, ...ALLOWED_CANVAS_FIELDS.nodeGroup];
|
|
13723
|
+
}
|
|
13724
|
+
checkUnknownFields(n, allowedNodeFields, nodePath2, issues);
|
|
13535
13725
|
if (typeof n.id !== "string" || !n.id) {
|
|
13536
|
-
issues.push({ type: "error", message: `Node at index ${index} must have a string "id"`, path:
|
|
13726
|
+
issues.push({ type: "error", message: `Node at index ${index} must have a string "id"`, path: `${nodePath2}.id` });
|
|
13537
13727
|
}
|
|
13538
13728
|
if (typeof n.type !== "string") {
|
|
13539
|
-
issues.push({ type: "error", message: `Node "${
|
|
13729
|
+
issues.push({ type: "error", message: `Node "${nodeLabel}" must have a string "type"`, path: `${nodePath2}.type` });
|
|
13540
13730
|
}
|
|
13541
13731
|
if (typeof n.x !== "number") {
|
|
13542
|
-
issues.push({ type: "error", message: `Node "${
|
|
13732
|
+
issues.push({ type: "error", message: `Node "${nodeLabel}" must have a numeric "x" position`, path: `${nodePath2}.x` });
|
|
13543
13733
|
}
|
|
13544
13734
|
if (typeof n.y !== "number") {
|
|
13545
|
-
issues.push({ type: "error", message: `Node "${
|
|
13735
|
+
issues.push({ type: "error", message: `Node "${nodeLabel}" must have a numeric "y" position`, path: `${nodePath2}.y` });
|
|
13546
13736
|
}
|
|
13547
13737
|
if (typeof n.width !== "number") {
|
|
13548
|
-
issues.push({ type: "error", message: `Node "${
|
|
13738
|
+
issues.push({ type: "error", message: `Node "${nodeLabel}" must have a numeric "width"`, path: `${nodePath2}.width` });
|
|
13549
13739
|
}
|
|
13550
13740
|
if (typeof n.height !== "number") {
|
|
13551
|
-
issues.push({ type: "error", message: `Node "${
|
|
13741
|
+
issues.push({ type: "error", message: `Node "${nodeLabel}" must have a numeric "height"`, path: `${nodePath2}.height` });
|
|
13552
13742
|
}
|
|
13553
|
-
const nodeType = n.type;
|
|
13554
13743
|
const isStandardType = STANDARD_CANVAS_TYPES.includes(nodeType);
|
|
13555
13744
|
if (!isStandardType) {
|
|
13556
13745
|
if (!n.pv || typeof n.pv !== "object") {
|
|
@@ -13581,12 +13770,37 @@ function validateCanvas(canvas, filePath, library) {
|
|
|
13581
13770
|
}
|
|
13582
13771
|
if (n.pv && typeof n.pv === "object") {
|
|
13583
13772
|
const nodePv = n.pv;
|
|
13773
|
+
checkUnknownFields(nodePv, ALLOWED_CANVAS_FIELDS.nodePv, `${nodePath2}.pv`, issues);
|
|
13774
|
+
if (nodePv.states && typeof nodePv.states === "object") {
|
|
13775
|
+
for (const [stateId, stateDef] of Object.entries(nodePv.states)) {
|
|
13776
|
+
if (stateDef && typeof stateDef === "object") {
|
|
13777
|
+
checkUnknownFields(stateDef, ALLOWED_CANVAS_FIELDS.nodePvState, `${nodePath2}.pv.states.${stateId}`, issues);
|
|
13778
|
+
}
|
|
13779
|
+
}
|
|
13780
|
+
}
|
|
13781
|
+
if (nodePv.dataSchema && typeof nodePv.dataSchema === "object") {
|
|
13782
|
+
for (const [fieldName, fieldDef] of Object.entries(nodePv.dataSchema)) {
|
|
13783
|
+
if (fieldDef && typeof fieldDef === "object") {
|
|
13784
|
+
checkUnknownFields(fieldDef, ALLOWED_CANVAS_FIELDS.nodePvDataSchemaField, `${nodePath2}.pv.dataSchema.${fieldName}`, issues);
|
|
13785
|
+
}
|
|
13786
|
+
}
|
|
13787
|
+
}
|
|
13788
|
+
if (nodePv.layout && typeof nodePv.layout === "object") {
|
|
13789
|
+
checkUnknownFields(nodePv.layout, ALLOWED_CANVAS_FIELDS.nodePvLayout, `${nodePath2}.pv.layout`, issues);
|
|
13790
|
+
}
|
|
13791
|
+
if (Array.isArray(nodePv.actions)) {
|
|
13792
|
+
nodePv.actions.forEach((action, actionIndex) => {
|
|
13793
|
+
if (action && typeof action === "object") {
|
|
13794
|
+
checkUnknownFields(action, ALLOWED_CANVAS_FIELDS.nodePvAction, `${nodePath2}.pv.actions[${actionIndex}]`, issues);
|
|
13795
|
+
}
|
|
13796
|
+
});
|
|
13797
|
+
}
|
|
13584
13798
|
if (typeof nodePv.nodeType === "string" && nodePv.nodeType) {
|
|
13585
13799
|
if (allDefinedNodeTypes.length === 0) {
|
|
13586
13800
|
issues.push({
|
|
13587
13801
|
type: "error",
|
|
13588
|
-
message: `Node "${
|
|
13589
|
-
path:
|
|
13802
|
+
message: `Node "${nodeLabel}" uses nodeType "${nodePv.nodeType}" but no node types are defined`,
|
|
13803
|
+
path: `${nodePath2}.pv.nodeType`,
|
|
13590
13804
|
suggestion: "Define node types in canvas pv.nodeTypes or library.yaml nodeComponents"
|
|
13591
13805
|
});
|
|
13592
13806
|
} else if (!allDefinedNodeTypes.includes(nodePv.nodeType)) {
|
|
@@ -13600,8 +13814,8 @@ function validateCanvas(canvas, filePath, library) {
|
|
|
13600
13814
|
const suggestion = sources.length > 0 ? `Available types from ${sources.join(" | ")}` : "Define node types in canvas pv.nodeTypes or library.yaml nodeComponents";
|
|
13601
13815
|
issues.push({
|
|
13602
13816
|
type: "error",
|
|
13603
|
-
message: `Node "${
|
|
13604
|
-
path:
|
|
13817
|
+
message: `Node "${nodeLabel}" uses undefined nodeType "${nodePv.nodeType}"`,
|
|
13818
|
+
path: `${nodePath2}.pv.nodeType`,
|
|
13605
13819
|
suggestion
|
|
13606
13820
|
});
|
|
13607
13821
|
}
|
|
@@ -13619,27 +13833,41 @@ function validateCanvas(canvas, filePath, library) {
|
|
|
13619
13833
|
return;
|
|
13620
13834
|
}
|
|
13621
13835
|
const e = edge;
|
|
13836
|
+
const edgePath = `edges[${index}]`;
|
|
13837
|
+
const edgeLabel = e.id || index;
|
|
13838
|
+
checkUnknownFields(e, ALLOWED_CANVAS_FIELDS.edge, edgePath, issues);
|
|
13622
13839
|
if (typeof e.id !== "string" || !e.id) {
|
|
13623
|
-
issues.push({ type: "error", message: `Edge at index ${index} must have a string "id"`, path:
|
|
13840
|
+
issues.push({ type: "error", message: `Edge at index ${index} must have a string "id"`, path: `${edgePath}.id` });
|
|
13624
13841
|
}
|
|
13625
13842
|
if (typeof e.fromNode !== "string") {
|
|
13626
|
-
issues.push({ type: "error", message: `Edge "${
|
|
13843
|
+
issues.push({ type: "error", message: `Edge "${edgeLabel}" must have a string "fromNode"`, path: `${edgePath}.fromNode` });
|
|
13627
13844
|
} else if (!nodeIds.has(e.fromNode)) {
|
|
13628
|
-
issues.push({ type: "error", message: `Edge "${
|
|
13845
|
+
issues.push({ type: "error", message: `Edge "${edgeLabel}" references unknown node "${e.fromNode}"`, path: `${edgePath}.fromNode` });
|
|
13629
13846
|
}
|
|
13630
13847
|
if (typeof e.toNode !== "string") {
|
|
13631
|
-
issues.push({ type: "error", message: `Edge "${
|
|
13848
|
+
issues.push({ type: "error", message: `Edge "${edgeLabel}" must have a string "toNode"`, path: `${edgePath}.toNode` });
|
|
13632
13849
|
} else if (!nodeIds.has(e.toNode)) {
|
|
13633
|
-
issues.push({ type: "error", message: `Edge "${
|
|
13850
|
+
issues.push({ type: "error", message: `Edge "${edgeLabel}" references unknown node "${e.toNode}"`, path: `${edgePath}.toNode` });
|
|
13634
13851
|
}
|
|
13635
13852
|
if (e.pv && typeof e.pv === "object") {
|
|
13636
13853
|
const edgePv = e.pv;
|
|
13854
|
+
checkUnknownFields(edgePv, ALLOWED_CANVAS_FIELDS.edgePv, `${edgePath}.pv`, issues);
|
|
13855
|
+
if (edgePv.animation && typeof edgePv.animation === "object") {
|
|
13856
|
+
checkUnknownFields(edgePv.animation, ALLOWED_CANVAS_FIELDS.edgePvAnimation, `${edgePath}.pv.animation`, issues);
|
|
13857
|
+
}
|
|
13858
|
+
if (Array.isArray(edgePv.activatedBy)) {
|
|
13859
|
+
edgePv.activatedBy.forEach((trigger, triggerIndex) => {
|
|
13860
|
+
if (trigger && typeof trigger === "object") {
|
|
13861
|
+
checkUnknownFields(trigger, ALLOWED_CANVAS_FIELDS.edgePvActivatedBy, `${edgePath}.pv.activatedBy[${triggerIndex}]`, issues);
|
|
13862
|
+
}
|
|
13863
|
+
});
|
|
13864
|
+
}
|
|
13637
13865
|
if (edgePv.edgeType && typeof edgePv.edgeType === "string") {
|
|
13638
13866
|
if (allDefinedEdgeTypes.length === 0) {
|
|
13639
13867
|
issues.push({
|
|
13640
13868
|
type: "error",
|
|
13641
|
-
message: `Edge "${
|
|
13642
|
-
path:
|
|
13869
|
+
message: `Edge "${edgeLabel}" uses edgeType "${edgePv.edgeType}" but no edge types are defined`,
|
|
13870
|
+
path: `${edgePath}.pv.edgeType`,
|
|
13643
13871
|
suggestion: "Define edge types in canvas pv.edgeTypes or library.yaml edgeComponents"
|
|
13644
13872
|
});
|
|
13645
13873
|
} else if (!allDefinedEdgeTypes.includes(edgePv.edgeType)) {
|
|
@@ -13653,8 +13881,8 @@ function validateCanvas(canvas, filePath, library) {
|
|
|
13653
13881
|
const suggestion = sources.length > 0 ? `Available types from ${sources.join(" | ")}` : "Define edge types in canvas pv.edgeTypes or library.yaml edgeComponents";
|
|
13654
13882
|
issues.push({
|
|
13655
13883
|
type: "error",
|
|
13656
|
-
message: `Edge "${
|
|
13657
|
-
path:
|
|
13884
|
+
message: `Edge "${edgeLabel}" uses undefined edgeType "${edgePv.edgeType}"`,
|
|
13885
|
+
path: `${edgePath}.pv.edgeType`,
|
|
13658
13886
|
suggestion
|
|
13659
13887
|
});
|
|
13660
13888
|
}
|
|
@@ -13713,21 +13941,33 @@ function createValidateCommand() {
|
|
|
13713
13941
|
}
|
|
13714
13942
|
const principalViewsDir = (0, import_node_path5.resolve)(process.cwd(), ".principal-views");
|
|
13715
13943
|
const library = loadLibrary(principalViewsDir);
|
|
13944
|
+
let libraryResult = null;
|
|
13945
|
+
if (library && Object.keys(library.raw).length > 0) {
|
|
13946
|
+
const libraryIssues = validateLibrary(library);
|
|
13947
|
+
const libraryHasErrors = libraryIssues.some((i) => i.type === "error");
|
|
13948
|
+
libraryResult = {
|
|
13949
|
+
file: (0, import_node_path5.relative)(process.cwd(), library.path),
|
|
13950
|
+
isValid: !libraryHasErrors,
|
|
13951
|
+
issues: libraryIssues
|
|
13952
|
+
};
|
|
13953
|
+
}
|
|
13716
13954
|
const results = matchedFiles.map((f) => validateFile(f, library));
|
|
13717
|
-
const
|
|
13718
|
-
const
|
|
13955
|
+
const allResults = libraryResult ? [libraryResult, ...results] : results;
|
|
13956
|
+
const validCount = allResults.filter((r) => r.isValid).length;
|
|
13957
|
+
const invalidCount = allResults.length - validCount;
|
|
13719
13958
|
if (options.json) {
|
|
13720
13959
|
console.log(JSON.stringify({
|
|
13721
|
-
files:
|
|
13722
|
-
summary: { total:
|
|
13960
|
+
files: allResults,
|
|
13961
|
+
summary: { total: allResults.length, valid: validCount, invalid: invalidCount }
|
|
13723
13962
|
}, null, 2));
|
|
13724
13963
|
} else {
|
|
13725
13964
|
if (!options.quiet) {
|
|
13965
|
+
const fileCount = libraryResult ? `${results.length} canvas file(s) + library` : `${results.length} canvas file(s)`;
|
|
13726
13966
|
console.log(source_default.bold(`
|
|
13727
|
-
Validating ${
|
|
13967
|
+
Validating ${fileCount}...
|
|
13728
13968
|
`));
|
|
13729
13969
|
}
|
|
13730
|
-
for (const result of
|
|
13970
|
+
for (const result of allResults) {
|
|
13731
13971
|
if (result.isValid) {
|
|
13732
13972
|
if (!options.quiet) {
|
|
13733
13973
|
console.log(source_default.green(`\u2713 ${result.file}`));
|
|
@@ -13754,7 +13994,7 @@ Validating ${results.length} canvas file(s)...
|
|
|
13754
13994
|
if (invalidCount === 0) {
|
|
13755
13995
|
console.log(source_default.green(`\u2713 All ${validCount} file(s) are valid`));
|
|
13756
13996
|
} else {
|
|
13757
|
-
console.log(source_default.red(`\u2717 ${invalidCount} of ${
|
|
13997
|
+
console.log(source_default.red(`\u2717 ${invalidCount} of ${allResults.length} file(s) failed validation`));
|
|
13758
13998
|
process.exit(1);
|
|
13759
13999
|
}
|
|
13760
14000
|
}
|
|
@@ -14915,19 +15155,19 @@ var ConfigurationLoader = class _ConfigurationLoader {
|
|
|
14915
15155
|
this.fsAdapter = fsAdapter;
|
|
14916
15156
|
}
|
|
14917
15157
|
/**
|
|
14918
|
-
* Check if the .
|
|
15158
|
+
* Check if the .principal-views/ configuration directory exists
|
|
14919
15159
|
*
|
|
14920
15160
|
* @param baseDir - Base directory to search from
|
|
14921
|
-
* @returns True if .
|
|
15161
|
+
* @returns True if .principal-views/ directory exists
|
|
14922
15162
|
*/
|
|
14923
15163
|
hasConfigDirectory(baseDir) {
|
|
14924
15164
|
const configPath = this.fsAdapter.join(baseDir, _ConfigurationLoader.CONFIG_DIR);
|
|
14925
15165
|
return this.fsAdapter.exists(configPath) && this.fsAdapter.isDirectory(configPath);
|
|
14926
15166
|
}
|
|
14927
15167
|
/**
|
|
14928
|
-
* List all available configuration names in .
|
|
15168
|
+
* List all available configuration names in .principal-views/ folder
|
|
14929
15169
|
*
|
|
14930
|
-
* @param baseDir - Base directory containing .
|
|
15170
|
+
* @param baseDir - Base directory containing .principal-views/ folder
|
|
14931
15171
|
* @returns Array of configuration names (without extensions)
|
|
14932
15172
|
*/
|
|
14933
15173
|
listConfigurations(baseDir) {
|
|
@@ -14942,7 +15182,7 @@ var ConfigurationLoader = class _ConfigurationLoader {
|
|
|
14942
15182
|
* Load a specific configuration by name
|
|
14943
15183
|
*
|
|
14944
15184
|
* @param name - Configuration name (without extension)
|
|
14945
|
-
* @param baseDir - Base directory containing .
|
|
15185
|
+
* @param baseDir - Base directory containing .principal-views/ folder
|
|
14946
15186
|
* @returns Configuration file or null if not found/invalid
|
|
14947
15187
|
*/
|
|
14948
15188
|
loadByName(name, baseDir) {
|
|
@@ -14972,9 +15212,9 @@ var ConfigurationLoader = class _ConfigurationLoader {
|
|
|
14972
15212
|
return null;
|
|
14973
15213
|
}
|
|
14974
15214
|
/**
|
|
14975
|
-
* Load all configurations from .
|
|
15215
|
+
* Load all configurations from .principal-views/ folder
|
|
14976
15216
|
*
|
|
14977
|
-
* @param baseDir - Base directory containing .
|
|
15217
|
+
* @param baseDir - Base directory containing .principal-views/ folder
|
|
14978
15218
|
* @returns Result containing all loaded configs and any errors
|
|
14979
15219
|
*/
|
|
14980
15220
|
loadAll(baseDir) {
|
|
@@ -14984,8 +15224,8 @@ var ConfigurationLoader = class _ConfigurationLoader {
|
|
|
14984
15224
|
};
|
|
14985
15225
|
if (!this.hasConfigDirectory(baseDir)) {
|
|
14986
15226
|
result.errors.push({
|
|
14987
|
-
file: ".
|
|
14988
|
-
error: "Configuration directory .
|
|
15227
|
+
file: ".principal-views",
|
|
15228
|
+
error: "Configuration directory .principal-views/ not found"
|
|
14989
15229
|
});
|
|
14990
15230
|
return result;
|
|
14991
15231
|
}
|
|
@@ -15027,13 +15267,13 @@ var ConfigurationLoader = class _ConfigurationLoader {
|
|
|
15027
15267
|
* Get the configuration directory path
|
|
15028
15268
|
*
|
|
15029
15269
|
* @param baseDir - Base directory
|
|
15030
|
-
* @returns Full path to .
|
|
15270
|
+
* @returns Full path to .principal-views/ directory
|
|
15031
15271
|
*/
|
|
15032
15272
|
getConfigDirectoryPath(baseDir) {
|
|
15033
15273
|
return this.fsAdapter.join(baseDir, _ConfigurationLoader.CONFIG_DIR);
|
|
15034
15274
|
}
|
|
15035
15275
|
};
|
|
15036
|
-
ConfigurationLoader.CONFIG_DIR = ".
|
|
15276
|
+
ConfigurationLoader.CONFIG_DIR = ".principal-views";
|
|
15037
15277
|
|
|
15038
15278
|
// ../core/dist/rules/types.js
|
|
15039
15279
|
function normalizeSeverity(severity) {
|
|
@@ -15270,7 +15510,7 @@ function createRulesEngine(rules) {
|
|
|
15270
15510
|
}
|
|
15271
15511
|
|
|
15272
15512
|
// ../core/dist/rules/config.js
|
|
15273
|
-
var DEFAULT_INCLUDE_PATTERNS = [".
|
|
15513
|
+
var DEFAULT_INCLUDE_PATTERNS = [".principal-views/**/*.yaml", ".principal-views/**/*.yml", ".principal-views/**/*.json"];
|
|
15274
15514
|
var DEFAULT_EXCLUDE_PATTERNS = ["**/node_modules/**", "**/*.test.*"];
|
|
15275
15515
|
var VALID_SEVERITIES = [
|
|
15276
15516
|
"off",
|
|
@@ -16189,7 +16429,7 @@ var noUnknownFields = {
|
|
|
16189
16429
|
function checkFields(obj, allowedFields, path4, configPath, violations) {
|
|
16190
16430
|
for (const field of Object.keys(obj)) {
|
|
16191
16431
|
if (!allowedFields.includes(field)) {
|
|
16192
|
-
const suggestion =
|
|
16432
|
+
const suggestion = findSimilarField2(field, allowedFields);
|
|
16193
16433
|
violations.push({
|
|
16194
16434
|
ruleId: "no-unknown-fields",
|
|
16195
16435
|
severity: "error",
|
|
@@ -16204,7 +16444,7 @@ function checkFields(obj, allowedFields, path4, configPath, violations) {
|
|
|
16204
16444
|
}
|
|
16205
16445
|
}
|
|
16206
16446
|
}
|
|
16207
|
-
function
|
|
16447
|
+
function findSimilarField2(field, allowedFields) {
|
|
16208
16448
|
const fieldLower = field.toLowerCase();
|
|
16209
16449
|
for (const allowed of allowedFields) {
|
|
16210
16450
|
const allowedLower = allowed.toLowerCase();
|
|
@@ -16924,12 +17164,9 @@ function createDefaultRulesEngine() {
|
|
|
16924
17164
|
|
|
16925
17165
|
// src/commands/lint.ts
|
|
16926
17166
|
var CONFIG_FILE_NAMES2 = [
|
|
16927
|
-
".
|
|
16928
|
-
".
|
|
16929
|
-
".
|
|
16930
|
-
"privu.config.json",
|
|
16931
|
-
"privu.config.yaml",
|
|
16932
|
-
"privu.config.yml"
|
|
17167
|
+
".privurc.yaml",
|
|
17168
|
+
".privurc.yml",
|
|
17169
|
+
".privurc.json"
|
|
16933
17170
|
];
|
|
16934
17171
|
function findConfig(startDir) {
|
|
16935
17172
|
let currentDir = (0, import_node_path11.resolve)(startDir);
|
|
@@ -17142,7 +17379,7 @@ function createLintCommand() {
|
|
|
17142
17379
|
});
|
|
17143
17380
|
const configFiles = matchedFiles.filter((f) => {
|
|
17144
17381
|
const name = (0, import_node_path11.basename)(f).toLowerCase();
|
|
17145
|
-
return !name.startsWith("library.") && !name.startsWith(".
|
|
17382
|
+
return !name.startsWith("library.") && !name.startsWith(".privurc");
|
|
17146
17383
|
});
|
|
17147
17384
|
if (configFiles.length === 0) {
|
|
17148
17385
|
if (options.json) {
|