@principal-ai/principal-view-cli 0.1.19 → 0.1.21

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/index.cjs CHANGED
@@ -13484,31 +13484,68 @@ function validateLibrary(library) {
13484
13484
  for (const [compId, compDef] of Object.entries(lib.nodeComponents)) {
13485
13485
  if (compDef && typeof compDef === "object") {
13486
13486
  const comp = compDef;
13487
- checkUnknownFields(comp, ALLOWED_LIBRARY_FIELDS.nodeComponent, `nodeComponents.${compId}`, issues);
13487
+ checkUnknownFields(
13488
+ comp,
13489
+ ALLOWED_LIBRARY_FIELDS.nodeComponent,
13490
+ `nodeComponents.${compId}`,
13491
+ issues
13492
+ );
13493
+ validateIconName(comp.icon, `nodeComponents.${compId}.icon`, issues);
13488
13494
  if (comp.size && typeof comp.size === "object") {
13489
- checkUnknownFields(comp.size, ALLOWED_LIBRARY_FIELDS.nodeComponentSize, `nodeComponents.${compId}.size`, issues);
13495
+ checkUnknownFields(
13496
+ comp.size,
13497
+ ALLOWED_LIBRARY_FIELDS.nodeComponentSize,
13498
+ `nodeComponents.${compId}.size`,
13499
+ issues
13500
+ );
13490
13501
  }
13491
13502
  if (comp.states && typeof comp.states === "object") {
13492
- for (const [stateId, stateDef] of Object.entries(comp.states)) {
13503
+ for (const [stateId, stateDef] of Object.entries(
13504
+ comp.states
13505
+ )) {
13493
13506
  if (stateDef && typeof stateDef === "object") {
13494
- checkUnknownFields(stateDef, ALLOWED_LIBRARY_FIELDS.nodeComponentState, `nodeComponents.${compId}.states.${stateId}`, issues);
13507
+ checkUnknownFields(
13508
+ stateDef,
13509
+ ALLOWED_LIBRARY_FIELDS.nodeComponentState,
13510
+ `nodeComponents.${compId}.states.${stateId}`,
13511
+ issues
13512
+ );
13513
+ const state = stateDef;
13514
+ validateIconName(state.icon, `nodeComponents.${compId}.states.${stateId}.icon`, issues);
13495
13515
  }
13496
13516
  }
13497
13517
  }
13498
13518
  if (comp.dataSchema && typeof comp.dataSchema === "object") {
13499
- for (const [fieldName, fieldDef] of Object.entries(comp.dataSchema)) {
13519
+ for (const [fieldName, fieldDef] of Object.entries(
13520
+ comp.dataSchema
13521
+ )) {
13500
13522
  if (fieldDef && typeof fieldDef === "object") {
13501
- checkUnknownFields(fieldDef, ALLOWED_LIBRARY_FIELDS.nodeComponentDataSchemaField, `nodeComponents.${compId}.dataSchema.${fieldName}`, issues);
13523
+ checkUnknownFields(
13524
+ fieldDef,
13525
+ ALLOWED_LIBRARY_FIELDS.nodeComponentDataSchemaField,
13526
+ `nodeComponents.${compId}.dataSchema.${fieldName}`,
13527
+ issues
13528
+ );
13502
13529
  }
13503
13530
  }
13504
13531
  }
13505
13532
  if (comp.layout && typeof comp.layout === "object") {
13506
- checkUnknownFields(comp.layout, ALLOWED_LIBRARY_FIELDS.nodeComponentLayout, `nodeComponents.${compId}.layout`, issues);
13533
+ checkUnknownFields(
13534
+ comp.layout,
13535
+ ALLOWED_LIBRARY_FIELDS.nodeComponentLayout,
13536
+ `nodeComponents.${compId}.layout`,
13537
+ issues
13538
+ );
13507
13539
  }
13508
13540
  if (Array.isArray(comp.actions)) {
13509
13541
  comp.actions.forEach((action, actionIndex) => {
13510
13542
  if (action && typeof action === "object") {
13511
- checkUnknownFields(action, ALLOWED_LIBRARY_FIELDS.nodeComponentAction, `nodeComponents.${compId}.actions[${actionIndex}]`, issues);
13543
+ checkUnknownFields(
13544
+ action,
13545
+ ALLOWED_LIBRARY_FIELDS.nodeComponentAction,
13546
+ `nodeComponents.${compId}.actions[${actionIndex}]`,
13547
+ issues
13548
+ );
13512
13549
  }
13513
13550
  });
13514
13551
  }
@@ -13519,12 +13556,27 @@ function validateLibrary(library) {
13519
13556
  for (const [compId, compDef] of Object.entries(lib.edgeComponents)) {
13520
13557
  if (compDef && typeof compDef === "object") {
13521
13558
  const comp = compDef;
13522
- checkUnknownFields(comp, ALLOWED_LIBRARY_FIELDS.edgeComponent, `edgeComponents.${compId}`, issues);
13559
+ checkUnknownFields(
13560
+ comp,
13561
+ ALLOWED_LIBRARY_FIELDS.edgeComponent,
13562
+ `edgeComponents.${compId}`,
13563
+ issues
13564
+ );
13523
13565
  if (comp.animation && typeof comp.animation === "object") {
13524
- checkUnknownFields(comp.animation, ALLOWED_LIBRARY_FIELDS.edgeComponentAnimation, `edgeComponents.${compId}.animation`, issues);
13566
+ checkUnknownFields(
13567
+ comp.animation,
13568
+ ALLOWED_LIBRARY_FIELDS.edgeComponentAnimation,
13569
+ `edgeComponents.${compId}.animation`,
13570
+ issues
13571
+ );
13525
13572
  }
13526
13573
  if (comp.label && typeof comp.label === "object") {
13527
- checkUnknownFields(comp.label, ALLOWED_LIBRARY_FIELDS.edgeComponentLabel, `edgeComponents.${compId}.label`, issues);
13574
+ checkUnknownFields(
13575
+ comp.label,
13576
+ ALLOWED_LIBRARY_FIELDS.edgeComponentLabel,
13577
+ `edgeComponents.${compId}.label`,
13578
+ issues
13579
+ );
13528
13580
  }
13529
13581
  }
13530
13582
  }
@@ -13533,9 +13585,19 @@ function validateLibrary(library) {
13533
13585
  lib.connectionRules.forEach((rule, ruleIndex) => {
13534
13586
  if (rule && typeof rule === "object") {
13535
13587
  const r = rule;
13536
- checkUnknownFields(r, ALLOWED_LIBRARY_FIELDS.connectionRule, `connectionRules[${ruleIndex}]`, issues);
13588
+ checkUnknownFields(
13589
+ r,
13590
+ ALLOWED_LIBRARY_FIELDS.connectionRule,
13591
+ `connectionRules[${ruleIndex}]`,
13592
+ issues
13593
+ );
13537
13594
  if (r.constraints && typeof r.constraints === "object") {
13538
- checkUnknownFields(r.constraints, ALLOWED_LIBRARY_FIELDS.connectionRuleConstraints, `connectionRules[${ruleIndex}].constraints`, issues);
13595
+ checkUnknownFields(
13596
+ r.constraints,
13597
+ ALLOWED_LIBRARY_FIELDS.connectionRuleConstraints,
13598
+ `connectionRules[${ruleIndex}].constraints`,
13599
+ issues
13600
+ );
13539
13601
  }
13540
13602
  }
13541
13603
  });
@@ -13544,15 +13606,60 @@ function validateLibrary(library) {
13544
13606
  }
13545
13607
  var STANDARD_CANVAS_TYPES = ["text", "group", "file", "link"];
13546
13608
  var VALID_NODE_SHAPES = ["circle", "rectangle", "hexagon", "diamond", "custom"];
13609
+ function kebabToPascalCase(str2) {
13610
+ return str2.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
13611
+ }
13612
+ function isKebabCase(str2) {
13613
+ return str2.includes("-") && str2 === str2.toLowerCase();
13614
+ }
13615
+ function validateIconName(iconValue, path4, issues) {
13616
+ if (typeof iconValue !== "string" || !iconValue) {
13617
+ return;
13618
+ }
13619
+ if (isKebabCase(iconValue)) {
13620
+ const suggested = kebabToPascalCase(iconValue);
13621
+ issues.push({
13622
+ type: "error",
13623
+ message: `Invalid icon name "${iconValue}" - icons must be in PascalCase`,
13624
+ path: path4,
13625
+ suggestion: `Use "${suggested}" instead of "${iconValue}"`
13626
+ });
13627
+ return;
13628
+ }
13629
+ if (iconValue[0] === iconValue[0].toLowerCase() && iconValue[0] !== iconValue[0].toUpperCase()) {
13630
+ const suggested = iconValue.charAt(0).toUpperCase() + iconValue.slice(1);
13631
+ issues.push({
13632
+ type: "error",
13633
+ message: `Invalid icon name "${iconValue}" - icons must start with uppercase`,
13634
+ path: path4,
13635
+ suggestion: `Use "${suggested}" instead of "${iconValue}"`
13636
+ });
13637
+ }
13638
+ }
13547
13639
  var ALLOWED_CANVAS_FIELDS = {
13548
13640
  root: ["nodes", "edges", "pv"],
13549
13641
  pv: ["version", "name", "description", "nodeTypes", "edgeTypes", "pathConfig", "display"],
13550
- pvPathConfig: ["projectRoot", "captureSource", "enableActionPatterns", "logLevel", "ignoreUnsourced"],
13642
+ pvPathConfig: [
13643
+ "projectRoot",
13644
+ "captureSource",
13645
+ "enableActionPatterns",
13646
+ "logLevel",
13647
+ "ignoreUnsourced"
13648
+ ],
13551
13649
  pvDisplay: ["layout", "theme", "animations"],
13552
13650
  pvDisplayTheme: ["primary", "success", "warning", "danger", "info"],
13553
13651
  pvDisplayAnimations: ["enabled", "speed"],
13554
13652
  pvNodeType: ["label", "description", "color", "icon", "shape"],
13555
- pvEdgeType: ["label", "style", "color", "width", "directed", "animation", "labelConfig", "activatedBy"],
13653
+ pvEdgeType: [
13654
+ "label",
13655
+ "style",
13656
+ "color",
13657
+ "width",
13658
+ "directed",
13659
+ "animation",
13660
+ "labelConfig",
13661
+ "activatedBy"
13662
+ ],
13556
13663
  pvEdgeTypeAnimation: ["type", "duration", "color"],
13557
13664
  pvEdgeTypeLabelConfig: ["field", "position"],
13558
13665
  // Base node fields from JSON Canvas spec
@@ -13563,26 +13670,71 @@ var ALLOWED_CANVAS_FIELDS = {
13563
13670
  nodeLink: ["url"],
13564
13671
  nodeGroup: ["label", "background", "backgroundStyle"],
13565
13672
  // Node pv extension
13566
- nodePv: ["nodeType", "description", "shape", "icon", "fill", "stroke", "states", "sources", "actions", "dataSchema", "layout"],
13673
+ nodePv: [
13674
+ "nodeType",
13675
+ "description",
13676
+ "shape",
13677
+ "icon",
13678
+ "fill",
13679
+ "stroke",
13680
+ "states",
13681
+ "sources",
13682
+ "actions",
13683
+ "dataSchema",
13684
+ "layout"
13685
+ ],
13567
13686
  nodePvState: ["color", "icon", "label"],
13568
13687
  nodePvAction: ["pattern", "event", "state", "metadata", "triggerEdges"],
13569
13688
  nodePvDataSchemaField: ["type", "required", "displayInLabel"],
13570
13689
  nodePvLayout: ["layer", "cluster"],
13571
13690
  // Edge fields
13572
- edge: ["id", "fromNode", "toNode", "fromSide", "toSide", "fromEnd", "toEnd", "color", "label", "pv"],
13691
+ edge: [
13692
+ "id",
13693
+ "fromNode",
13694
+ "toNode",
13695
+ "fromSide",
13696
+ "toSide",
13697
+ "fromEnd",
13698
+ "toEnd",
13699
+ "color",
13700
+ "label",
13701
+ "pv"
13702
+ ],
13573
13703
  edgePv: ["edgeType", "style", "width", "animation", "activatedBy"],
13574
13704
  edgePvAnimation: ["type", "duration", "color"],
13575
13705
  edgePvActivatedBy: ["action", "animation", "direction", "duration"]
13576
13706
  };
13577
13707
  var ALLOWED_LIBRARY_FIELDS = {
13578
13708
  root: ["version", "name", "description", "nodeComponents", "edgeComponents", "connectionRules"],
13579
- nodeComponent: ["description", "tags", "defaultLabel", "shape", "icon", "color", "size", "states", "sources", "actions", "dataSchema", "layout"],
13709
+ nodeComponent: [
13710
+ "description",
13711
+ "tags",
13712
+ "defaultLabel",
13713
+ "shape",
13714
+ "icon",
13715
+ "color",
13716
+ "size",
13717
+ "states",
13718
+ "sources",
13719
+ "actions",
13720
+ "dataSchema",
13721
+ "layout"
13722
+ ],
13580
13723
  nodeComponentSize: ["width", "height"],
13581
13724
  nodeComponentState: ["color", "icon", "label"],
13582
13725
  nodeComponentAction: ["pattern", "event", "state", "metadata", "triggerEdges"],
13583
13726
  nodeComponentDataSchemaField: ["type", "required", "displayInLabel", "label", "displayInInfo"],
13584
13727
  nodeComponentLayout: ["layer", "cluster"],
13585
- edgeComponent: ["description", "tags", "style", "color", "width", "directed", "animation", "label"],
13728
+ edgeComponent: [
13729
+ "description",
13730
+ "tags",
13731
+ "style",
13732
+ "color",
13733
+ "width",
13734
+ "directed",
13735
+ "animation",
13736
+ "label"
13737
+ ],
13586
13738
  edgeComponentAnimation: ["type", "duration", "color"],
13587
13739
  edgeComponentLabel: ["field", "position"],
13588
13740
  connectionRule: ["from", "to", "via", "constraints"],
@@ -13661,23 +13813,45 @@ function validateCanvas(canvas, filePath, library) {
13661
13813
  });
13662
13814
  }
13663
13815
  if (pv.pathConfig && typeof pv.pathConfig === "object") {
13664
- checkUnknownFields(pv.pathConfig, ALLOWED_CANVAS_FIELDS.pvPathConfig, "pv.pathConfig", issues);
13816
+ checkUnknownFields(
13817
+ pv.pathConfig,
13818
+ ALLOWED_CANVAS_FIELDS.pvPathConfig,
13819
+ "pv.pathConfig",
13820
+ issues
13821
+ );
13665
13822
  }
13666
13823
  if (pv.display && typeof pv.display === "object") {
13667
13824
  const display = pv.display;
13668
13825
  checkUnknownFields(display, ALLOWED_CANVAS_FIELDS.pvDisplay, "pv.display", issues);
13669
13826
  if (display.theme && typeof display.theme === "object") {
13670
- checkUnknownFields(display.theme, ALLOWED_CANVAS_FIELDS.pvDisplayTheme, "pv.display.theme", issues);
13827
+ checkUnknownFields(
13828
+ display.theme,
13829
+ ALLOWED_CANVAS_FIELDS.pvDisplayTheme,
13830
+ "pv.display.theme",
13831
+ issues
13832
+ );
13671
13833
  }
13672
13834
  if (display.animations && typeof display.animations === "object") {
13673
- checkUnknownFields(display.animations, ALLOWED_CANVAS_FIELDS.pvDisplayAnimations, "pv.display.animations", issues);
13835
+ checkUnknownFields(
13836
+ display.animations,
13837
+ ALLOWED_CANVAS_FIELDS.pvDisplayAnimations,
13838
+ "pv.display.animations",
13839
+ issues
13840
+ );
13674
13841
  }
13675
13842
  }
13676
13843
  if (pv.nodeTypes && typeof pv.nodeTypes === "object") {
13677
13844
  canvasNodeTypes = Object.keys(pv.nodeTypes);
13678
13845
  for (const [typeId, typeDef] of Object.entries(pv.nodeTypes)) {
13679
13846
  if (typeDef && typeof typeDef === "object") {
13680
- checkUnknownFields(typeDef, ALLOWED_CANVAS_FIELDS.pvNodeType, `pv.nodeTypes.${typeId}`, issues);
13847
+ checkUnknownFields(
13848
+ typeDef,
13849
+ ALLOWED_CANVAS_FIELDS.pvNodeType,
13850
+ `pv.nodeTypes.${typeId}`,
13851
+ issues
13852
+ );
13853
+ const nodeType = typeDef;
13854
+ validateIconName(nodeType.icon, `pv.nodeTypes.${typeId}.icon`, issues);
13681
13855
  }
13682
13856
  }
13683
13857
  }
@@ -13686,12 +13860,27 @@ function validateCanvas(canvas, filePath, library) {
13686
13860
  for (const [typeId, typeDef] of Object.entries(pv.edgeTypes)) {
13687
13861
  if (typeDef && typeof typeDef === "object") {
13688
13862
  const edgeTypeDef = typeDef;
13689
- checkUnknownFields(edgeTypeDef, ALLOWED_CANVAS_FIELDS.pvEdgeType, `pv.edgeTypes.${typeId}`, issues);
13863
+ checkUnknownFields(
13864
+ edgeTypeDef,
13865
+ ALLOWED_CANVAS_FIELDS.pvEdgeType,
13866
+ `pv.edgeTypes.${typeId}`,
13867
+ issues
13868
+ );
13690
13869
  if (edgeTypeDef.animation && typeof edgeTypeDef.animation === "object") {
13691
- checkUnknownFields(edgeTypeDef.animation, ALLOWED_CANVAS_FIELDS.pvEdgeTypeAnimation, `pv.edgeTypes.${typeId}.animation`, issues);
13870
+ checkUnknownFields(
13871
+ edgeTypeDef.animation,
13872
+ ALLOWED_CANVAS_FIELDS.pvEdgeTypeAnimation,
13873
+ `pv.edgeTypes.${typeId}.animation`,
13874
+ issues
13875
+ );
13692
13876
  }
13693
13877
  if (edgeTypeDef.labelConfig && typeof edgeTypeDef.labelConfig === "object") {
13694
- checkUnknownFields(edgeTypeDef.labelConfig, ALLOWED_CANVAS_FIELDS.pvEdgeTypeLabelConfig, `pv.edgeTypes.${typeId}.labelConfig`, issues);
13878
+ checkUnknownFields(
13879
+ edgeTypeDef.labelConfig,
13880
+ ALLOWED_CANVAS_FIELDS.pvEdgeTypeLabelConfig,
13881
+ `pv.edgeTypes.${typeId}.labelConfig`,
13882
+ issues
13883
+ );
13695
13884
  }
13696
13885
  }
13697
13886
  }
@@ -13704,7 +13893,11 @@ function validateCanvas(canvas, filePath, library) {
13704
13893
  } else {
13705
13894
  c.nodes.forEach((node, index) => {
13706
13895
  if (!node || typeof node !== "object") {
13707
- issues.push({ type: "error", message: `Node at index ${index} must be an object`, path: `nodes[${index}]` });
13896
+ issues.push({
13897
+ type: "error",
13898
+ message: `Node at index ${index} must be an object`,
13899
+ path: `nodes[${index}]`
13900
+ });
13708
13901
  return;
13709
13902
  }
13710
13903
  const n = node;
@@ -13723,31 +13916,83 @@ function validateCanvas(canvas, filePath, library) {
13723
13916
  }
13724
13917
  checkUnknownFields(n, allowedNodeFields, nodePath2, issues);
13725
13918
  if (typeof n.id !== "string" || !n.id) {
13726
- issues.push({ type: "error", message: `Node at index ${index} must have a string "id"`, path: `${nodePath2}.id` });
13919
+ issues.push({
13920
+ type: "error",
13921
+ message: `Node at index ${index} must have a string "id"`,
13922
+ path: `${nodePath2}.id`
13923
+ });
13727
13924
  }
13728
13925
  if (typeof n.type !== "string") {
13729
- issues.push({ type: "error", message: `Node "${nodeLabel}" must have a string "type"`, path: `${nodePath2}.type` });
13926
+ issues.push({
13927
+ type: "error",
13928
+ message: `Node "${nodeLabel}" must have a string "type"`,
13929
+ path: `${nodePath2}.type`
13930
+ });
13730
13931
  }
13731
13932
  if (typeof n.x !== "number") {
13732
- issues.push({ type: "error", message: `Node "${nodeLabel}" must have a numeric "x" position`, path: `${nodePath2}.x` });
13933
+ issues.push({
13934
+ type: "error",
13935
+ message: `Node "${nodeLabel}" must have a numeric "x" position`,
13936
+ path: `${nodePath2}.x`
13937
+ });
13733
13938
  }
13734
13939
  if (typeof n.y !== "number") {
13735
- issues.push({ type: "error", message: `Node "${nodeLabel}" must have a numeric "y" position`, path: `${nodePath2}.y` });
13940
+ issues.push({
13941
+ type: "error",
13942
+ message: `Node "${nodeLabel}" must have a numeric "y" position`,
13943
+ path: `${nodePath2}.y`
13944
+ });
13736
13945
  }
13737
13946
  if (typeof n.width !== "number") {
13738
- issues.push({ type: "error", message: `Node "${nodeLabel}" must have a numeric "width"`, path: `${nodePath2}.width` });
13947
+ issues.push({
13948
+ type: "error",
13949
+ message: `Node "${nodeLabel}" must have a numeric "width"`,
13950
+ path: `${nodePath2}.width`
13951
+ });
13739
13952
  }
13740
13953
  if (typeof n.height !== "number") {
13741
- issues.push({ type: "error", message: `Node "${nodeLabel}" must have a numeric "height"`, path: `${nodePath2}.height` });
13954
+ issues.push({
13955
+ type: "error",
13956
+ message: `Node "${nodeLabel}" must have a numeric "height"`,
13957
+ path: `${nodePath2}.height`
13958
+ });
13959
+ }
13960
+ if (nodeType === "text" && (typeof n.text !== "string" || !n.text)) {
13961
+ issues.push({
13962
+ type: "error",
13963
+ message: `Node "${nodeLabel}" has type "text" but is missing required "text" field`,
13964
+ path: `${nodePath2}.text`,
13965
+ suggestion: 'Add a "text" field with markdown content, or change the node type'
13966
+ });
13967
+ }
13968
+ if (nodeType === "file" && (typeof n.file !== "string" || !n.file)) {
13969
+ issues.push({
13970
+ type: "error",
13971
+ message: `Node "${nodeLabel}" has type "file" but is missing required "file" field`,
13972
+ path: `${nodePath2}.file`,
13973
+ suggestion: 'Add a "file" field with a file path, or change the node type'
13974
+ });
13975
+ }
13976
+ if (nodeType === "link" && (typeof n.url !== "string" || !n.url)) {
13977
+ issues.push({
13978
+ type: "error",
13979
+ message: `Node "${nodeLabel}" has type "link" but is missing required "url" field`,
13980
+ path: `${nodePath2}.url`,
13981
+ suggestion: 'Add a "url" field with a URL, or change the node type'
13982
+ });
13742
13983
  }
13743
- const isStandardType = STANDARD_CANVAS_TYPES.includes(nodeType);
13984
+ const isStandardType = STANDARD_CANVAS_TYPES.includes(
13985
+ nodeType
13986
+ );
13744
13987
  if (!isStandardType) {
13745
13988
  if (!n.pv || typeof n.pv !== "object") {
13746
13989
  issues.push({
13747
13990
  type: "error",
13748
13991
  message: `Node "${n.id || index}" uses custom type "${nodeType}" but has no "pv" extension`,
13749
13992
  path: `nodes[${index}].pv`,
13750
- suggestion: `Use a standard type (${STANDARD_CANVAS_TYPES.join(", ")}) or add pv.nodeType and pv.shape`
13993
+ suggestion: `Use a standard type (${STANDARD_CANVAS_TYPES.join(
13994
+ ", "
13995
+ )}) or add pv.nodeType and pv.shape`
13751
13996
  });
13752
13997
  } else {
13753
13998
  const nodePv = n.pv;
@@ -13771,27 +14016,54 @@ function validateCanvas(canvas, filePath, library) {
13771
14016
  if (n.pv && typeof n.pv === "object") {
13772
14017
  const nodePv = n.pv;
13773
14018
  checkUnknownFields(nodePv, ALLOWED_CANVAS_FIELDS.nodePv, `${nodePath2}.pv`, issues);
14019
+ validateIconName(nodePv.icon, `${nodePath2}.pv.icon`, issues);
13774
14020
  if (nodePv.states && typeof nodePv.states === "object") {
13775
- for (const [stateId, stateDef] of Object.entries(nodePv.states)) {
14021
+ for (const [stateId, stateDef] of Object.entries(
14022
+ nodePv.states
14023
+ )) {
13776
14024
  if (stateDef && typeof stateDef === "object") {
13777
- checkUnknownFields(stateDef, ALLOWED_CANVAS_FIELDS.nodePvState, `${nodePath2}.pv.states.${stateId}`, issues);
14025
+ checkUnknownFields(
14026
+ stateDef,
14027
+ ALLOWED_CANVAS_FIELDS.nodePvState,
14028
+ `${nodePath2}.pv.states.${stateId}`,
14029
+ issues
14030
+ );
14031
+ const state = stateDef;
14032
+ validateIconName(state.icon, `${nodePath2}.pv.states.${stateId}.icon`, issues);
13778
14033
  }
13779
14034
  }
13780
14035
  }
13781
14036
  if (nodePv.dataSchema && typeof nodePv.dataSchema === "object") {
13782
- for (const [fieldName, fieldDef] of Object.entries(nodePv.dataSchema)) {
14037
+ for (const [fieldName, fieldDef] of Object.entries(
14038
+ nodePv.dataSchema
14039
+ )) {
13783
14040
  if (fieldDef && typeof fieldDef === "object") {
13784
- checkUnknownFields(fieldDef, ALLOWED_CANVAS_FIELDS.nodePvDataSchemaField, `${nodePath2}.pv.dataSchema.${fieldName}`, issues);
14041
+ checkUnknownFields(
14042
+ fieldDef,
14043
+ ALLOWED_CANVAS_FIELDS.nodePvDataSchemaField,
14044
+ `${nodePath2}.pv.dataSchema.${fieldName}`,
14045
+ issues
14046
+ );
13785
14047
  }
13786
14048
  }
13787
14049
  }
13788
14050
  if (nodePv.layout && typeof nodePv.layout === "object") {
13789
- checkUnknownFields(nodePv.layout, ALLOWED_CANVAS_FIELDS.nodePvLayout, `${nodePath2}.pv.layout`, issues);
14051
+ checkUnknownFields(
14052
+ nodePv.layout,
14053
+ ALLOWED_CANVAS_FIELDS.nodePvLayout,
14054
+ `${nodePath2}.pv.layout`,
14055
+ issues
14056
+ );
13790
14057
  }
13791
14058
  if (Array.isArray(nodePv.actions)) {
13792
14059
  nodePv.actions.forEach((action, actionIndex) => {
13793
14060
  if (action && typeof action === "object") {
13794
- checkUnknownFields(action, ALLOWED_CANVAS_FIELDS.nodePvAction, `${nodePath2}.pv.actions[${actionIndex}]`, issues);
14061
+ checkUnknownFields(
14062
+ action,
14063
+ ALLOWED_CANVAS_FIELDS.nodePvAction,
14064
+ `${nodePath2}.pv.actions[${actionIndex}]`,
14065
+ issues
14066
+ );
13795
14067
  }
13796
14068
  });
13797
14069
  }
@@ -13829,7 +14101,11 @@ function validateCanvas(canvas, filePath, library) {
13829
14101
  const nodeIds = new Set(c.nodes?.map((n) => n.id) || []);
13830
14102
  c.edges.forEach((edge, index) => {
13831
14103
  if (!edge || typeof edge !== "object") {
13832
- issues.push({ type: "error", message: `Edge at index ${index} must be an object`, path: `edges[${index}]` });
14104
+ issues.push({
14105
+ type: "error",
14106
+ message: `Edge at index ${index} must be an object`,
14107
+ path: `edges[${index}]`
14108
+ });
13833
14109
  return;
13834
14110
  }
13835
14111
  const e = edge;
@@ -13837,28 +14113,89 @@ function validateCanvas(canvas, filePath, library) {
13837
14113
  const edgeLabel = e.id || index;
13838
14114
  checkUnknownFields(e, ALLOWED_CANVAS_FIELDS.edge, edgePath, issues);
13839
14115
  if (typeof e.id !== "string" || !e.id) {
13840
- issues.push({ type: "error", message: `Edge at index ${index} must have a string "id"`, path: `${edgePath}.id` });
14116
+ issues.push({
14117
+ type: "error",
14118
+ message: `Edge at index ${index} must have a string "id"`,
14119
+ path: `${edgePath}.id`
14120
+ });
13841
14121
  }
13842
14122
  if (typeof e.fromNode !== "string") {
13843
- issues.push({ type: "error", message: `Edge "${edgeLabel}" must have a string "fromNode"`, path: `${edgePath}.fromNode` });
14123
+ issues.push({
14124
+ type: "error",
14125
+ message: `Edge "${edgeLabel}" must have a string "fromNode"`,
14126
+ path: `${edgePath}.fromNode`
14127
+ });
13844
14128
  } else if (!nodeIds.has(e.fromNode)) {
13845
- issues.push({ type: "error", message: `Edge "${edgeLabel}" references unknown node "${e.fromNode}"`, path: `${edgePath}.fromNode` });
14129
+ issues.push({
14130
+ type: "error",
14131
+ message: `Edge "${edgeLabel}" references unknown node "${e.fromNode}"`,
14132
+ path: `${edgePath}.fromNode`
14133
+ });
13846
14134
  }
13847
14135
  if (typeof e.toNode !== "string") {
13848
- issues.push({ type: "error", message: `Edge "${edgeLabel}" must have a string "toNode"`, path: `${edgePath}.toNode` });
14136
+ issues.push({
14137
+ type: "error",
14138
+ message: `Edge "${edgeLabel}" must have a string "toNode"`,
14139
+ path: `${edgePath}.toNode`
14140
+ });
13849
14141
  } else if (!nodeIds.has(e.toNode)) {
13850
- issues.push({ type: "error", message: `Edge "${edgeLabel}" references unknown node "${e.toNode}"`, path: `${edgePath}.toNode` });
14142
+ issues.push({
14143
+ type: "error",
14144
+ message: `Edge "${edgeLabel}" references unknown node "${e.toNode}"`,
14145
+ path: `${edgePath}.toNode`
14146
+ });
14147
+ }
14148
+ const VALID_SIDES = ["top", "right", "bottom", "left"];
14149
+ if (typeof e.fromSide !== "string") {
14150
+ issues.push({
14151
+ type: "error",
14152
+ message: `Edge "${edgeLabel}" must have a "fromSide" field`,
14153
+ path: `${edgePath}.fromSide`,
14154
+ suggestion: `Specify which side of the source node the edge starts from: ${VALID_SIDES.join(", ")}`
14155
+ });
14156
+ } else if (!VALID_SIDES.includes(e.fromSide)) {
14157
+ issues.push({
14158
+ type: "error",
14159
+ message: `Edge "${edgeLabel}" has invalid fromSide "${e.fromSide}"`,
14160
+ path: `${edgePath}.fromSide`,
14161
+ suggestion: `Valid values: ${VALID_SIDES.join(", ")}`
14162
+ });
14163
+ }
14164
+ if (typeof e.toSide !== "string") {
14165
+ issues.push({
14166
+ type: "error",
14167
+ message: `Edge "${edgeLabel}" must have a "toSide" field`,
14168
+ path: `${edgePath}.toSide`,
14169
+ suggestion: `Specify which side of the target node the edge connects to: ${VALID_SIDES.join(", ")}`
14170
+ });
14171
+ } else if (!VALID_SIDES.includes(e.toSide)) {
14172
+ issues.push({
14173
+ type: "error",
14174
+ message: `Edge "${edgeLabel}" has invalid toSide "${e.toSide}"`,
14175
+ path: `${edgePath}.toSide`,
14176
+ suggestion: `Valid values: ${VALID_SIDES.join(", ")}`
14177
+ });
13851
14178
  }
13852
14179
  if (e.pv && typeof e.pv === "object") {
13853
14180
  const edgePv = e.pv;
13854
14181
  checkUnknownFields(edgePv, ALLOWED_CANVAS_FIELDS.edgePv, `${edgePath}.pv`, issues);
13855
14182
  if (edgePv.animation && typeof edgePv.animation === "object") {
13856
- checkUnknownFields(edgePv.animation, ALLOWED_CANVAS_FIELDS.edgePvAnimation, `${edgePath}.pv.animation`, issues);
14183
+ checkUnknownFields(
14184
+ edgePv.animation,
14185
+ ALLOWED_CANVAS_FIELDS.edgePvAnimation,
14186
+ `${edgePath}.pv.animation`,
14187
+ issues
14188
+ );
13857
14189
  }
13858
14190
  if (Array.isArray(edgePv.activatedBy)) {
13859
14191
  edgePv.activatedBy.forEach((trigger, triggerIndex) => {
13860
14192
  if (trigger && typeof trigger === "object") {
13861
- checkUnknownFields(trigger, ALLOWED_CANVAS_FIELDS.edgePvActivatedBy, `${edgePath}.pv.activatedBy[${triggerIndex}]`, issues);
14193
+ checkUnknownFields(
14194
+ trigger,
14195
+ ALLOWED_CANVAS_FIELDS.edgePvActivatedBy,
14196
+ `${edgePath}.pv.activatedBy[${triggerIndex}]`,
14197
+ issues
14198
+ );
13862
14199
  }
13863
14200
  });
13864
14201
  }
@@ -13923,7 +14260,10 @@ function validateFile(filePath, library) {
13923
14260
  }
13924
14261
  function createValidateCommand() {
13925
14262
  const command = new Command("validate");
13926
- command.description("Validate .canvas configuration files").argument("[files...]", "Files or glob patterns to validate (defaults to .principal-views/*.canvas)").option("-q, --quiet", "Only output errors").option("--json", "Output results as JSON").action(async (files, options) => {
14263
+ command.description("Validate .canvas configuration files").argument(
14264
+ "[files...]",
14265
+ "Files or glob patterns to validate (defaults to .principal-views/*.canvas)"
14266
+ ).option("-q, --quiet", "Only output errors").option("--json", "Output results as JSON").action(async (files, options) => {
13927
14267
  try {
13928
14268
  const patterns = files.length > 0 ? files : [".principal-views/*.canvas"];
13929
14269
  const matchedFiles = await globby(patterns, {
@@ -13956,10 +14296,16 @@ function createValidateCommand() {
13956
14296
  const validCount = allResults.filter((r) => r.isValid).length;
13957
14297
  const invalidCount = allResults.length - validCount;
13958
14298
  if (options.json) {
13959
- console.log(JSON.stringify({
13960
- files: allResults,
13961
- summary: { total: allResults.length, valid: validCount, invalid: invalidCount }
13962
- }, null, 2));
14299
+ console.log(
14300
+ JSON.stringify(
14301
+ {
14302
+ files: allResults,
14303
+ summary: { total: allResults.length, valid: validCount, invalid: invalidCount }
14304
+ },
14305
+ null,
14306
+ 2
14307
+ )
14308
+ );
13963
14309
  } else {
13964
14310
  if (!options.quiet) {
13965
14311
  const fileCount = libraryResult ? `${results.length} canvas file(s) + library` : `${results.length} canvas file(s)`;
@@ -13994,7 +14340,9 @@ Validating ${fileCount}...
13994
14340
  if (invalidCount === 0) {
13995
14341
  console.log(source_default.green(`\u2713 All ${validCount} file(s) are valid`));
13996
14342
  } else {
13997
- console.log(source_default.red(`\u2717 ${invalidCount} of ${allResults.length} file(s) failed validation`));
14343
+ console.log(
14344
+ source_default.red(`\u2717 ${invalidCount} of ${allResults.length} file(s) failed validation`)
14345
+ );
13998
14346
  process.exit(1);
13999
14347
  }
14000
14348
  }
@@ -14109,7 +14457,9 @@ function createInitCommand() {
14109
14457
  console.log(source_default.green(`Created directory: .principal-views/`));
14110
14458
  }
14111
14459
  if ((0, import_node_fs5.existsSync)(canvasFile) && !options.force) {
14112
- console.log(source_default.yellow(`Canvas file already exists: .principal-views/${options.name}.canvas`));
14460
+ console.log(
14461
+ source_default.yellow(`Canvas file already exists: .principal-views/${options.name}.canvas`)
14462
+ );
14113
14463
  } else {
14114
14464
  (0, import_node_fs5.writeFileSync)(canvasFile, JSON.stringify(TEMPLATE_CANVAS, null, 2));
14115
14465
  console.log(source_default.green(`Created canvas file: .principal-views/${options.name}.canvas`));
@@ -14150,11 +14500,15 @@ edgeComponents: {}
14150
14500
  if ((0, import_node_fs5.existsSync)(preCommitFile)) {
14151
14501
  const existingContent = (0, import_node_fs5.readFileSync)(preCommitFile, "utf8");
14152
14502
  if (existingContent.includes("principal-view-cli lint") || existingContent.includes("privu lint")) {
14153
- console.log(source_default.yellow(`Husky pre-commit hook already includes principal view linting`));
14503
+ console.log(
14504
+ source_default.yellow(`Husky pre-commit hook already includes principal view linting`)
14505
+ );
14154
14506
  } else {
14155
14507
  const updatedContent = existingContent.trimEnd() + "\n\n# Run principal view linting\nnpx @principal-ai/principal-view-cli lint --quiet\n";
14156
14508
  (0, import_node_fs5.writeFileSync)(preCommitFile, updatedContent);
14157
- console.log(source_default.green(`Updated Husky pre-commit hook with principal view linting`));
14509
+ console.log(
14510
+ source_default.green(`Updated Husky pre-commit hook with principal view linting`)
14511
+ );
14158
14512
  huskySetup = true;
14159
14513
  }
14160
14514
  } else {
@@ -14184,8 +14538,16 @@ edgeComponents: {}
14184
14538
  console.log(source_default.green(`Installed Husky and created pre-commit hook`));
14185
14539
  huskySetup = true;
14186
14540
  } catch (installError) {
14187
- console.log(source_default.yellow(`Could not install Husky automatically: ${installError.message}`));
14188
- console.log(source_default.dim(` You can install it manually: ${pm} add --dev husky && npx husky init`));
14541
+ console.log(
14542
+ source_default.yellow(
14543
+ `Could not install Husky automatically: ${installError.message}`
14544
+ )
14545
+ );
14546
+ console.log(
14547
+ source_default.dim(
14548
+ ` You can install it manually: ${pm} add --dev husky && npx husky init`
14549
+ )
14550
+ );
14189
14551
  }
14190
14552
  }
14191
14553
  }
@@ -14196,8 +14558,12 @@ edgeComponents: {}
14196
14558
  console.log(source_default.bold("Setup complete!"));
14197
14559
  console.log("");
14198
14560
  console.log(source_default.bold("Files created:"));
14199
- console.log(` \u2022 ${source_default.cyan(".principal-views/library.yaml")} - Component library definitions`);
14200
- console.log(` \u2022 ${source_default.cyan(`.principal-views/${options.name}.canvas`)} - Graph canvas file`);
14561
+ console.log(
14562
+ ` \u2022 ${source_default.cyan(".principal-views/library.yaml")} - Component library definitions`
14563
+ );
14564
+ console.log(
14565
+ ` \u2022 ${source_default.cyan(`.principal-views/${options.name}.canvas`)} - Graph canvas file`
14566
+ );
14201
14567
  if (options.lintConfig !== false) {
14202
14568
  console.log(` \u2022 ${source_default.cyan(".privurc.yaml")} - Lint configuration`);
14203
14569
  }
@@ -14207,7 +14573,9 @@ edgeComponents: {}
14207
14573
  console.log("");
14208
14574
  console.log(source_default.bold("Next steps:"));
14209
14575
  console.log(` 1. Define components in ${source_default.cyan(".principal-views/library.yaml")}`);
14210
- console.log(` 2. Build your graph in ${source_default.cyan(`.principal-views/${options.name}.canvas`)}`);
14576
+ console.log(
14577
+ ` 2. Build your graph in ${source_default.cyan(`.principal-views/${options.name}.canvas`)}`
14578
+ );
14211
14579
  console.log(` 3. Run ${source_default.cyan("privu lint")} to validate your configuration`);
14212
14580
  if (huskySetup) {
14213
14581
  console.log(` 4. Commits will now automatically lint .principal-views files`);
@@ -14303,11 +14671,21 @@ with standard canvas tools like Obsidian.
14303
14671
  ${source_default.bold("Required Structure:")}
14304
14672
  ${source_default.dim("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510")}
14305
14673
  ${source_default.dim("\u2502")} { ${source_default.dim("\u2502")}
14306
- ${source_default.dim("\u2502")} ${source_default.green('"nodes"')}: [...], ${source_default.dim("// Required: array of nodes")} ${source_default.dim("\u2502")}
14307
- ${source_default.dim("\u2502")} ${source_default.green('"edges"')}: [...], ${source_default.dim("// Optional: array of edges")} ${source_default.dim("\u2502")}
14308
- ${source_default.dim("\u2502")} ${source_default.green('"pv"')}: { ${source_default.dim("// Required: PV extension")} ${source_default.dim("\u2502")}
14309
- ${source_default.dim("\u2502")} ${source_default.yellow('"name"')}: "...", ${source_default.dim("// Required: graph name")} ${source_default.dim("\u2502")}
14310
- ${source_default.dim("\u2502")} ${source_default.yellow('"version"')}: "..." ${source_default.dim("// Required: schema version")} ${source_default.dim("\u2502")}
14674
+ ${source_default.dim("\u2502")} ${source_default.green('"nodes"')}: [...], ${source_default.dim(
14675
+ "// Required: array of nodes"
14676
+ )} ${source_default.dim("\u2502")}
14677
+ ${source_default.dim("\u2502")} ${source_default.green('"edges"')}: [...], ${source_default.dim(
14678
+ "// Optional: array of edges"
14679
+ )} ${source_default.dim("\u2502")}
14680
+ ${source_default.dim("\u2502")} ${source_default.green('"pv"')}: { ${source_default.dim(
14681
+ "// Required: PV extension"
14682
+ )} ${source_default.dim("\u2502")}
14683
+ ${source_default.dim("\u2502")} ${source_default.yellow('"name"')}: "...", ${source_default.dim(
14684
+ "// Required: graph name"
14685
+ )} ${source_default.dim("\u2502")}
14686
+ ${source_default.dim("\u2502")} ${source_default.yellow('"version"')}: "..." ${source_default.dim(
14687
+ "// Required: schema version"
14688
+ )} ${source_default.dim("\u2502")}
14311
14689
  ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
14312
14690
  ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
14313
14691
  ${source_default.dim("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518")}
@@ -14338,7 +14716,9 @@ ${source_default.bold("Standard Node Types:")}
14338
14716
  Requires: ${source_default.dim("text")} (string)
14339
14717
 
14340
14718
  ${source_default.yellow("group")} Visual container for other nodes
14341
- Optional: ${source_default.dim("label")}, ${source_default.dim("background")}, ${source_default.dim("backgroundStyle")}
14719
+ Optional: ${source_default.dim("label")}, ${source_default.dim("background")}, ${source_default.dim(
14720
+ "backgroundStyle"
14721
+ )}
14342
14722
 
14343
14723
  ${source_default.yellow("file")} Reference to external file
14344
14724
  Requires: ${source_default.dim("file")} (path string)
@@ -14384,10 +14764,10 @@ ${source_default.bold("Required Fields:")}
14384
14764
  ${source_default.green("id")} ${source_default.dim("string")} Unique identifier
14385
14765
  ${source_default.green("fromNode")} ${source_default.dim("string")} Source node ID
14386
14766
  ${source_default.green("toNode")} ${source_default.dim("string")} Target node ID
14387
-
14388
- ${source_default.bold("Optional Fields:")}
14389
14767
  ${source_default.green("fromSide")} ${source_default.dim("string")} Side of source: top, right, bottom, left
14390
14768
  ${source_default.green("toSide")} ${source_default.dim("string")} Side of target: top, right, bottom, left
14769
+
14770
+ ${source_default.bold("Optional Fields:")}
14391
14771
  ${source_default.green("fromEnd")} ${source_default.dim("string")} Source endpoint: none, arrow
14392
14772
  ${source_default.green("toEnd")} ${source_default.dim("string")} Target endpoint: none, arrow (default)
14393
14773
  ${source_default.green("color")} ${source_default.dim("string")} Edge color (hex or preset)
@@ -14397,6 +14777,7 @@ ${source_default.bold("PV Edge Extension:")}
14397
14777
  ${source_default.dim("{")}
14398
14778
  ${source_default.green('"id"')}: "edge-1",
14399
14779
  ${source_default.green('"fromNode"')}: "api", ${source_default.green('"toNode"')}: "db",
14780
+ ${source_default.green('"fromSide"')}: "right", ${source_default.green('"toSide"')}: "left",
14400
14781
  ${source_default.green('"pv"')}: {
14401
14782
  ${source_default.yellow('"edgeType"')}: "query" ${source_default.dim("// Must be defined in vv.edgeTypes")}
14402
14783
  }
@@ -14409,7 +14790,9 @@ ${source_default.bold("Defining Edge Types (in canvas vv):")}
14409
14790
  "version": "1.0.0",
14410
14791
  ${source_default.yellow('"edgeTypes"')}: {
14411
14792
  "query": {
14412
- ${source_default.cyan('"style"')}: "solid", ${source_default.dim("// solid, dashed, dotted, animated")}
14793
+ ${source_default.cyan('"style"')}: "solid", ${source_default.dim(
14794
+ "// solid, dashed, dotted, animated"
14795
+ )}
14413
14796
  ${source_default.cyan('"color"')}: "#64748b", ${source_default.dim("// Hex color")}
14414
14797
  ${source_default.cyan('"width"')}: 2, ${source_default.dim("// Line width in pixels")}
14415
14798
  ${source_default.cyan('"directed"')}: true, ${source_default.dim("// Show arrow")}
@@ -14463,7 +14846,9 @@ ${source_default.bold("Node-Level pv (for custom types):")}
14463
14846
  ${source_default.yellow('"nodeType"')}: "service", ${source_default.dim("// Required: Type identifier")}
14464
14847
  ${source_default.yellow('"shape"')}: "rectangle", ${source_default.dim("// Required: Visual shape")}
14465
14848
  ${source_default.cyan('"fill"')}: "#3b82f6", ${source_default.dim("// Optional: Fill color (hex)")}
14466
- ${source_default.cyan('"stroke"')}: "#1d4ed8", ${source_default.dim("// Optional: Border color (hex)")}
14849
+ ${source_default.cyan('"stroke"')}: "#1d4ed8", ${source_default.dim(
14850
+ "// Optional: Border color (hex)"
14851
+ )}
14467
14852
  ${source_default.cyan('"icon"')}: "Server", ${source_default.dim("// Optional: Lucide icon name")}
14468
14853
  ${source_default.cyan('"sources"')}: ["src/**/*.ts"], ${source_default.dim("// Optional: Source patterns")}
14469
14854
  ${source_default.cyan('"states"')}: { ${source_default.dim("// Optional: State definitions")}
@@ -14574,6 +14959,8 @@ ${source_default.dim("\u2500".repeat(50))}
14574
14959
  "id": "api-to-db",
14575
14960
  "fromNode": "api",
14576
14961
  "toNode": "db",
14962
+ "fromSide": "right",
14963
+ "toSide": "left",
14577
14964
  "pv": { "edgeType": "query" }
14578
14965
  }
14579
14966
  ],
@@ -14705,7 +15092,9 @@ async function checkConfig(configPath, projectRoot) {
14705
15092
  type: "warning",
14706
15093
  configFile: relativePath,
14707
15094
  nodeType: nodeTypeName,
14708
- message: `Config may be stale: "${newestFile}" was modified ${formatTimeDiff(timeDiff)} after the config`,
15095
+ message: `Config may be stale: "${newestFile}" was modified ${formatTimeDiff(
15096
+ timeDiff
15097
+ )} after the config`,
14709
15098
  details: `Pattern: ${pattern} (matched ${matchedFiles.length} file${matchedFiles.length > 1 ? "s" : ""})`
14710
15099
  });
14711
15100
  }
@@ -14729,7 +15118,9 @@ function createDoctorCommand() {
14729
15118
  const vgcDir = (0, import_node_path8.resolve)(projectRoot, ".principal-views");
14730
15119
  if (!(0, import_node_fs7.existsSync)(vgcDir)) {
14731
15120
  if (options.json) {
14732
- console.log(JSON.stringify({ error: "No .principal-views directory found", results: [] }));
15121
+ console.log(
15122
+ JSON.stringify({ error: "No .principal-views directory found", results: [] })
15123
+ );
14733
15124
  } else {
14734
15125
  console.log(source_default.yellow("No .principal-views directory found."));
14735
15126
  console.log(source_default.dim('Run "privu init" to create a configuration.'));
@@ -14743,7 +15134,9 @@ function createDoctorCommand() {
14743
15134
  });
14744
15135
  if (configFiles.length === 0) {
14745
15136
  if (options.json) {
14746
- console.log(JSON.stringify({ error: "No config files found in .principal-views", results: [] }));
15137
+ console.log(
15138
+ JSON.stringify({ error: "No config files found in .principal-views", results: [] })
15139
+ );
14747
15140
  } else {
14748
15141
  console.log(source_default.yellow("No configuration files found in .principal-views/"));
14749
15142
  }
@@ -14803,7 +15196,9 @@ Checking ${results.length} configuration file(s)...
14803
15196
  for (const result of results) {
14804
15197
  const issues = filterIssues(result.issues);
14805
15198
  if (issues.length === 0 && !options.quiet && !options.errorsOnly) {
14806
- console.log(source_default.green(`\u2713 ${result.configFile}`) + source_default.dim(` (${result.configName})`));
15199
+ console.log(
15200
+ source_default.green(`\u2713 ${result.configFile}`) + source_default.dim(` (${result.configName})`)
15201
+ );
14807
15202
  continue;
14808
15203
  }
14809
15204
  if (issues.length > 0) {
@@ -14923,7 +15318,9 @@ function initializeHusky(repoPath) {
14923
15318
  }
14924
15319
  console.log("\u2705 Husky installed and initialized");
14925
15320
  } catch (error) {
14926
- throw new Error(`Failed to initialize husky: ${error instanceof Error ? error.message : String(error)}`);
15321
+ throw new Error(
15322
+ `Failed to initialize husky: ${error instanceof Error ? error.message : String(error)}`
15323
+ );
14927
15324
  }
14928
15325
  }
14929
15326
  }
@@ -14939,7 +15336,7 @@ function addVVHook(repoPath) {
14939
15336
  const hookPath = (0, import_node_path9.join)(repoPath, HUSKY_DIR, PRE_COMMIT_HOOK);
14940
15337
  const vvContent = getVVHookContent();
14941
15338
  if ((0, import_node_fs8.existsSync)(hookPath)) {
14942
- let existingContent = (0, import_node_fs8.readFileSync)(hookPath, "utf8");
15339
+ const existingContent = (0, import_node_fs8.readFileSync)(hookPath, "utf8");
14943
15340
  if (existingContent.includes(VV_HOOK_MARKER)) {
14944
15341
  return;
14945
15342
  }
@@ -15055,7 +15452,9 @@ function createHooksCommand() {
15055
15452
  console.log(source_default.bold("\nPrincipal View Hooks Status\n"));
15056
15453
  console.log(`Repository: ${repoPath}`);
15057
15454
  console.log(`Husky: ${source_default.green("installed")}`);
15058
- console.log(`PV Hooks: ${hasHook ? source_default.green("configured") : source_default.yellow("not configured")}`);
15455
+ console.log(
15456
+ `PV Hooks: ${hasHook ? source_default.green("configured") : source_default.yellow("not configured")}`
15457
+ );
15059
15458
  if (hasHook) {
15060
15459
  console.log("\nUse --remove to remove or --check to verify");
15061
15460
  } else {
@@ -15079,7 +15478,10 @@ var TEMPLATE_CANVAS2 = {
15079
15478
  };
15080
15479
  function createCreateCommand() {
15081
15480
  const command = new Command("create");
15082
- command.description("Create a new canvas file in the .principal-views folder").requiredOption("-n, --name <name>", 'Name for the canvas file (e.g., "cache-sync-architecture")').option("-f, --force", "Overwrite existing file").action(async (options) => {
15481
+ command.description("Create a new canvas file in the .principal-views folder").requiredOption(
15482
+ "-n, --name <name>",
15483
+ 'Name for the canvas file (e.g., "cache-sync-architecture")'
15484
+ ).option("-f, --force", "Overwrite existing file").action(async (options) => {
15083
15485
  try {
15084
15486
  const vgcDir = (0, import_node_path10.join)(process.cwd(), ".principal-views");
15085
15487
  const canvasFile = (0, import_node_path10.join)(vgcDir, `${options.name}.canvas`);
@@ -15088,7 +15490,9 @@ function createCreateCommand() {
15088
15490
  console.log(source_default.green(`Created directory: .principal-views/`));
15089
15491
  }
15090
15492
  if ((0, import_node_fs9.existsSync)(canvasFile) && !options.force) {
15091
- console.error(source_default.red(`Error: Canvas file already exists: .principal-views/${options.name}.canvas`));
15493
+ console.error(
15494
+ source_default.red(`Error: Canvas file already exists: .principal-views/${options.name}.canvas`)
15495
+ );
15092
15496
  console.log(source_default.yellow(`Use ${source_default.cyan("--force")} to overwrite`));
15093
15497
  process.exit(1);
15094
15498
  }
@@ -15096,7 +15500,9 @@ function createCreateCommand() {
15096
15500
  console.log(source_default.green(`\u2713 Created canvas file: .principal-views/${options.name}.canvas`));
15097
15501
  console.log("");
15098
15502
  console.log(source_default.bold("Next steps:"));
15099
- console.log(` 1. Open ${source_default.cyan(`.principal-views/${options.name}.canvas`)} in your editor`);
15503
+ console.log(
15504
+ ` 1. Open ${source_default.cyan(`.principal-views/${options.name}.canvas`)} in your editor`
15505
+ );
15100
15506
  console.log(` 2. Add nodes and edges to define your architecture`);
15101
15507
  console.log(` 3. Run ${source_default.cyan("privu validate")} to check your configuration`);
15102
15508
  console.log(` 4. Run ${source_default.cyan("privu doctor")} to verify source mappings`);
@@ -15508,7 +15914,11 @@ function createRulesEngine(rules) {
15508
15914
  }
15509
15915
 
15510
15916
  // ../core/dist/rules/config.js
15511
- var DEFAULT_INCLUDE_PATTERNS = [".principal-views/**/*.yaml", ".principal-views/**/*.yml", ".principal-views/**/*.json"];
15917
+ var DEFAULT_INCLUDE_PATTERNS = [
15918
+ ".principal-views/**/*.yaml",
15919
+ ".principal-views/**/*.yml",
15920
+ ".principal-views/**/*.json"
15921
+ ];
15512
15922
  var DEFAULT_EXCLUDE_PATTERNS = ["**/node_modules/**", "**/*.test.*"];
15513
15923
  var VALID_SEVERITIES = [
15514
15924
  "off",
@@ -17174,11 +17584,7 @@ function createDefaultRulesEngine() {
17174
17584
  }
17175
17585
 
17176
17586
  // src/commands/lint.ts
17177
- var CONFIG_FILE_NAMES2 = [
17178
- ".privurc.yaml",
17179
- ".privurc.yml",
17180
- ".privurc.json"
17181
- ];
17587
+ var CONFIG_FILE_NAMES2 = [".privurc.yaml", ".privurc.yml", ".privurc.json"];
17182
17588
  function findConfig(startDir) {
17183
17589
  let currentDir = (0, import_node_path11.resolve)(startDir);
17184
17590
  while (true) {
@@ -17334,7 +17740,10 @@ function formatJsonOutput(results) {
17334
17740
  }
17335
17741
  function createLintCommand() {
17336
17742
  const command = new Command("lint");
17337
- command.description("Lint graph configuration files").argument("[files...]", "Files or glob patterns to lint (defaults to .principal-views/**/*.yaml)").option("-c, --config <path>", "Path to config file").option("--library <path>", "Path to component library file").option("-q, --quiet", "Only output errors").option("--json", "Output results as JSON").option("--rule <rules...>", "Only run specific rules").option("--ignore-rule <rules...>", "Skip specific rules").action(async (files, options) => {
17743
+ command.description("Lint graph configuration files").argument(
17744
+ "[files...]",
17745
+ "Files or glob patterns to lint (defaults to .principal-views/**/*.yaml)"
17746
+ ).option("-c, --config <path>", "Path to config file").option("--library <path>", "Path to component library file").option("-q, --quiet", "Only output errors").option("--json", "Output results as JSON").option("--rule <rules...>", "Only run specific rules").option("--ignore-rule <rules...>", "Skip specific rules").action(async (files, options) => {
17338
17747
  try {
17339
17748
  const cwd = process.cwd();
17340
17749
  let privuConfig = getDefaultConfig();
@@ -17382,7 +17791,11 @@ function createLintCommand() {
17382
17791
  } else if (privuConfig.include && privuConfig.include.length > 0) {
17383
17792
  patterns = privuConfig.include;
17384
17793
  } else {
17385
- patterns = [".principal-views/**/*.yaml", ".principal-views/**/*.yml", ".principal-views/**/*.json"];
17794
+ patterns = [
17795
+ ".principal-views/**/*.yaml",
17796
+ ".principal-views/**/*.yml",
17797
+ ".principal-views/**/*.json"
17798
+ ];
17386
17799
  }
17387
17800
  const matchedFiles = await globby(patterns, {
17388
17801
  ignore: privuConfig.exclude || ["**/node_modules/**"],
@@ -17397,9 +17810,16 @@ function createLintCommand() {
17397
17810
  });
17398
17811
  if (configFiles.length === 0) {
17399
17812
  if (options.json) {
17400
- console.log(JSON.stringify({ files: [], summary: { totalFiles: 0, totalErrors: 0, totalWarnings: 0, totalFixable: 0 } }));
17813
+ console.log(
17814
+ JSON.stringify({
17815
+ files: [],
17816
+ summary: { totalFiles: 0, totalErrors: 0, totalWarnings: 0, totalFixable: 0 }
17817
+ })
17818
+ );
17401
17819
  } else {
17402
- console.log(source_default.yellow("No configuration files found matching the specified patterns."));
17820
+ console.log(
17821
+ source_default.yellow("No configuration files found matching the specified patterns.")
17822
+ );
17403
17823
  console.log(source_default.dim(`Patterns searched: ${patterns.join(", ")}`));
17404
17824
  }
17405
17825
  return;
@@ -17421,14 +17841,16 @@ function createLintCommand() {
17421
17841
  const loaded = loadGraphConfig(absolutePath);
17422
17842
  if (!loaded) {
17423
17843
  results.set(relativePath, {
17424
- violations: [{
17425
- ruleId: "parse-error",
17426
- severity: "error",
17427
- file: relativePath,
17428
- message: `Could not parse file: ${filePath}`,
17429
- impact: "File cannot be validated",
17430
- fixable: false
17431
- }],
17844
+ violations: [
17845
+ {
17846
+ ruleId: "parse-error",
17847
+ severity: "error",
17848
+ file: relativePath,
17849
+ message: `Could not parse file: ${filePath}`,
17850
+ impact: "File cannot be validated",
17851
+ fixable: false
17852
+ }
17853
+ ],
17432
17854
  errorCount: 1,
17433
17855
  warningCount: 0,
17434
17856
  fixableCount: 0,