@principal-ai/principal-view-cli 0.1.24 → 0.1.26

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
@@ -13688,6 +13688,7 @@ var ALLOWED_CANVAS_FIELDS = {
13688
13688
  "name",
13689
13689
  "description",
13690
13690
  "otel",
13691
+ "events",
13691
13692
  "shape",
13692
13693
  "icon",
13693
13694
  "fill",
@@ -13790,6 +13791,38 @@ function findSimilarField(field, allowedFields) {
13790
13791
  }
13791
13792
  return null;
13792
13793
  }
13794
+ function hasOtelFeatures(canvas) {
13795
+ if (!canvas || typeof canvas !== "object") {
13796
+ return false;
13797
+ }
13798
+ const c = canvas;
13799
+ if (c.pv && typeof c.pv === "object") {
13800
+ const pv = c.pv;
13801
+ if (pv.scope !== void 0 || pv.audit !== void 0) {
13802
+ return true;
13803
+ }
13804
+ }
13805
+ if (Array.isArray(c.nodes)) {
13806
+ for (const node of c.nodes) {
13807
+ if (node && typeof node === "object") {
13808
+ const n = node;
13809
+ if (n.pv && typeof n.pv === "object") {
13810
+ const nodePv = n.pv;
13811
+ if (nodePv.otel !== void 0) {
13812
+ return true;
13813
+ }
13814
+ if (nodePv.events !== void 0) {
13815
+ return true;
13816
+ }
13817
+ if (nodePv.resourceMatch !== void 0) {
13818
+ return true;
13819
+ }
13820
+ }
13821
+ }
13822
+ }
13823
+ }
13824
+ return false;
13825
+ }
13793
13826
  function validateCanvas(canvas, filePath, library) {
13794
13827
  const issues = [];
13795
13828
  if (!canvas || typeof canvas !== "object") {
@@ -14256,6 +14289,21 @@ function validateCanvas(canvas, filePath, library) {
14256
14289
  }
14257
14290
  });
14258
14291
  }
14292
+ const hasOtel = hasOtelFeatures(canvas);
14293
+ const isOtelCanvas = filePath.endsWith(".otel.canvas");
14294
+ if (hasOtel && !isOtelCanvas) {
14295
+ issues.push({
14296
+ type: "error",
14297
+ message: "Canvas contains OTEL features but does not use .otel.canvas naming convention",
14298
+ suggestion: 'Rename file to use .otel.canvas extension (e.g., "graph-name.otel.canvas")'
14299
+ });
14300
+ } else if (!hasOtel && isOtelCanvas) {
14301
+ issues.push({
14302
+ type: "warning",
14303
+ message: "Canvas uses .otel.canvas naming but does not contain any OTEL features",
14304
+ suggestion: "Either add OTEL features (pv.otel, pv.events, pv.scope, pv.audit, resourceMatch) or rename to .canvas"
14305
+ });
14306
+ }
14259
14307
  return issues;
14260
14308
  }
14261
14309
  function validateFile(filePath, library) {
@@ -14304,7 +14352,7 @@ function createValidateCommand() {
14304
14352
  } else {
14305
14353
  console.log(source_default.yellow("No .canvas files found matching the specified patterns."));
14306
14354
  console.log(source_default.dim(`Patterns searched: ${patterns.join(", ")}`));
14307
- console.log(source_default.dim("\nTo create a new .principal-views folder, run: privu init"));
14355
+ console.log(source_default.dim("\nTo create a new .principal-views folder, run: npx @principal-ai/principal-view-cli init"));
14308
14356
  }
14309
14357
  return;
14310
14358
  }
@@ -14528,7 +14576,7 @@ edgeComponents: {}
14528
14576
  if (isHuskyInstalled(gitRoot)) {
14529
14577
  if ((0, import_node_fs5.existsSync)(preCommitFile)) {
14530
14578
  const existingContent = (0, import_node_fs5.readFileSync)(preCommitFile, "utf8");
14531
- if (existingContent.includes("principal-view-cli lint") || existingContent.includes("privu lint")) {
14579
+ if (existingContent.includes("principal-view-cli lint")) {
14532
14580
  console.log(
14533
14581
  source_default.yellow(`Husky pre-commit hook already includes principal view linting`)
14534
14582
  );
@@ -14605,16 +14653,16 @@ edgeComponents: {}
14605
14653
  console.log(
14606
14654
  ` 2. Build your graph in ${source_default.cyan(`.principal-views/${options.name}.canvas`)}`
14607
14655
  );
14608
- console.log(` 3. Run ${source_default.cyan("privu lint")} to validate your configuration`);
14656
+ console.log(` 3. Run ${source_default.cyan("npx @principal-ai/principal-view-cli lint")} to validate your configuration`);
14609
14657
  if (huskySetup) {
14610
14658
  console.log(` 4. Commits will now automatically lint .principal-views files`);
14611
14659
  }
14612
14660
  console.log("");
14613
14661
  console.log(source_default.bold("Commands:"));
14614
- console.log(` \u2022 ${source_default.cyan("privu lint")} - Lint configuration files`);
14615
- console.log(` \u2022 ${source_default.cyan("privu lint --json")} - Output lint results as JSON`);
14616
- console.log(` \u2022 ${source_default.cyan("privu validate")} - Validate canvas files`);
14617
- console.log(` \u2022 ${source_default.cyan("privu doctor")} - Check project setup`);
14662
+ console.log(` \u2022 ${source_default.cyan("npx @principal-ai/principal-view-cli lint")} - Lint configuration files`);
14663
+ console.log(` \u2022 ${source_default.cyan("npx @principal-ai/principal-view-cli lint --json")} - Output lint results as JSON`);
14664
+ console.log(` \u2022 ${source_default.cyan("npx @principal-ai/principal-view-cli validate")} - Validate canvas files`);
14665
+ console.log(` \u2022 ${source_default.cyan("npx @principal-ai/principal-view-cli doctor")} - Check project setup`);
14618
14666
  } catch (error) {
14619
14667
  console.error(source_default.red("Error:"), error.message);
14620
14668
  process.exit(1);
@@ -14660,7 +14708,7 @@ function createListCommand() {
14660
14708
  if (!options.all) {
14661
14709
  console.log(source_default.dim("Run with --all to search all directories"));
14662
14710
  }
14663
- console.log(source_default.dim("\nTo create a new canvas, run: privu init"));
14711
+ console.log(source_default.dim("\nTo create a new canvas, run: npx @principal-ai/principal-view-cli init"));
14664
14712
  }
14665
14713
  return;
14666
14714
  }
@@ -14719,7 +14767,7 @@ ${source_default.dim("\u2502")} }
14719
14767
  ${source_default.dim("\u2502")} } ${source_default.dim("\u2502")}
14720
14768
  ${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")}
14721
14769
 
14722
- Run ${source_default.cyan("privu schema <section>")} for details on:
14770
+ Run ${source_default.cyan("npx @principal-ai/principal-view-cli schema <section>")} for details on:
14723
14771
  ${source_default.yellow("nodes")} Node types and properties
14724
14772
  ${source_default.yellow("edges")} Edge properties and types
14725
14773
  ${source_default.yellow("vv")} Principal View extension fields
@@ -15010,8 +15058,8 @@ ${source_default.dim("\u2500".repeat(50))}
15010
15058
  }
15011
15059
  }
15012
15060
 
15013
- ${source_default.bold("Run validation:")} ${source_default.cyan("privu validate <file>")}
15014
- ${source_default.bold("Initialize project:")} ${source_default.cyan("privu init")}
15061
+ ${source_default.bold("Run validation:")} ${source_default.cyan("npx @principal-ai/principal-view-cli validate <file>")}
15062
+ ${source_default.bold("Initialize project:")} ${source_default.cyan("npx @principal-ai/principal-view-cli init")}
15015
15063
  `
15016
15064
  };
15017
15065
  function createSchemaCommand() {
@@ -15152,7 +15200,7 @@ function createDoctorCommand() {
15152
15200
  );
15153
15201
  } else {
15154
15202
  console.log(source_default.yellow("No .principal-views directory found."));
15155
- console.log(source_default.dim('Run "privu init" to create a configuration.'));
15203
+ console.log(source_default.dim('Run "npx @principal-ai/principal-view-cli init" to create a configuration.'));
15156
15204
  }
15157
15205
  return;
15158
15206
  }
@@ -15290,17 +15338,17 @@ var VV_HOOK_MARKER = "# Principal View checks";
15290
15338
  function getVVHookContent() {
15291
15339
  return `${VV_HOOK_MARKER}
15292
15340
  echo "Running Principal View doctor check..."
15293
- npx privu doctor --errors-only || {
15341
+ npx @principal-ai/principal-view-cli doctor --errors-only || {
15294
15342
  echo "\u274C Principal View doctor check failed (errors found)"
15295
- echo " Run 'privu doctor' to see details"
15343
+ echo " Run 'npx @principal-ai/principal-view-cli doctor' to see details"
15296
15344
  exit 1
15297
15345
  }
15298
15346
 
15299
15347
  echo "Running Principal View canvas validation..."
15300
- npx privu validate --quiet 2>/dev/null || {
15348
+ npx @principal-ai/principal-view-cli validate --quiet 2>/dev/null || {
15301
15349
  if [ $? -ne 0 ]; then
15302
15350
  echo "\u274C Canvas validation failed"
15303
- echo " Run 'privu validate' to see details"
15351
+ echo " Run 'npx @principal-ai/principal-view-cli validate' to see details"
15304
15352
  exit 1
15305
15353
  fi
15306
15354
  }
@@ -15401,7 +15449,7 @@ function removeVVHook(repoPath) {
15401
15449
  let i = startIndex + 1;
15402
15450
  while (i < lines.length && inVVBlock) {
15403
15451
  const line = lines[i];
15404
- if (line && (line.includes("privu ") || line.includes("Principal View") || line.includes('echo "Running Visual') || line.includes("exit 1") && i > startIndex && i < startIndex + 15 || line === "}" && i > startIndex && i < startIndex + 15 || line.trim() === "" && i === startIndex + 1)) {
15452
+ if (line && (line.includes("@principal-ai/principal-view-cli ") || line.includes("Principal View") || line.includes('echo "Running Visual') || line.includes("exit 1") && i > startIndex && i < startIndex + 15 || line === "}" && i > startIndex && i < startIndex + 15 || line.trim() === "" && i === startIndex + 1)) {
15405
15453
  endIndex = i;
15406
15454
  i++;
15407
15455
  } else if (line && line.trim() === "" && i < startIndex + 15) {
@@ -15436,11 +15484,11 @@ function createHooksCommand() {
15436
15484
  if (!isHuskyInstalled2(repoPath)) {
15437
15485
  if (options.check) {
15438
15486
  console.log(source_default.red("\u274C Husky is not installed"));
15439
- console.log(' Run "privu hooks --init" to install husky');
15487
+ console.log(' Run "npx @principal-ai/principal-view-cli hooks --init" to install husky');
15440
15488
  process.exit(1);
15441
15489
  } else if (options.add) {
15442
15490
  console.log(source_default.red("\u274C Husky is not installed"));
15443
- console.log(' Run "privu hooks --init" first to install husky');
15491
+ console.log(' Run "npx @principal-ai/principal-view-cli hooks --init" first to install husky');
15444
15492
  process.exit(1);
15445
15493
  } else if (options.remove) {
15446
15494
  console.log("\u2139\uFE0F Husky is not installed");
@@ -15448,7 +15496,7 @@ function createHooksCommand() {
15448
15496
  } else {
15449
15497
  console.log(source_default.red("\u274C Husky is not installed in this repository"));
15450
15498
  console.log("\nTo install husky and set up Principal View hooks:");
15451
- console.log(" privu hooks --init --add");
15499
+ console.log(" npx @principal-ai/principal-view-cli hooks --init --add");
15452
15500
  process.exit(1);
15453
15501
  }
15454
15502
  }
@@ -15467,7 +15515,7 @@ function createHooksCommand() {
15467
15515
  addVVHook(repoPath);
15468
15516
  console.log(source_default.green("\u2705 Added Principal View checks to pre-commit hook"));
15469
15517
  console.log("\nPre-commit hook will now:");
15470
- console.log(" \u2022 Run privu doctor to check for stale configurations");
15518
+ console.log(" \u2022 Run npx @principal-ai/principal-view-cli doctor to check for stale configurations");
15471
15519
  console.log(" \u2022 Validate all .canvas files");
15472
15520
  }
15473
15521
  } else if (options.remove) {
@@ -15533,8 +15581,8 @@ function createCreateCommand() {
15533
15581
  ` 1. Open ${source_default.cyan(`.principal-views/${options.name}.canvas`)} in your editor`
15534
15582
  );
15535
15583
  console.log(` 2. Add nodes and edges to define your architecture`);
15536
- console.log(` 3. Run ${source_default.cyan("privu validate")} to check your configuration`);
15537
- console.log(` 4. Run ${source_default.cyan("privu doctor")} to verify source mappings`);
15584
+ console.log(` 3. Run ${source_default.cyan("npx @principal-ai/principal-view-cli validate")} to check your configuration`);
15585
+ console.log(` 4. Run ${source_default.cyan("npx @principal-ai/principal-view-cli doctor")} to verify source mappings`);
15538
15586
  } catch (error) {
15539
15587
  console.error(source_default.red("Error:"), error.message);
15540
15588
  process.exit(1);
@@ -15547,6 +15595,212 @@ function createCreateCommand() {
15547
15595
  var import_node_fs10 = require("node:fs");
15548
15596
  var import_node_path11 = require("node:path");
15549
15597
 
15598
+ // ../core/dist/codegen/type-generator.js
15599
+ var TypeScriptGenerator = class {
15600
+ constructor() {
15601
+ this.language = "typescript";
15602
+ }
15603
+ generate(canvas, options) {
15604
+ const opts = {
15605
+ readonly: options?.style?.readonly ?? false,
15606
+ strictNullChecks: options?.style?.strictNullChecks ?? true,
15607
+ includeDocComments: options?.style?.includeDocComments ?? true,
15608
+ namespace: options?.namespace
15609
+ };
15610
+ const lines = [];
15611
+ lines.push("/**");
15612
+ lines.push(` * Generated types from canvas: ${canvas.pv?.name || "Untitled"}`);
15613
+ lines.push(" *");
15614
+ lines.push(" * DO NOT EDIT MANUALLY - This file is auto-generated");
15615
+ lines.push(" * Generated by @principal-ai/principal-view-core");
15616
+ lines.push(" *");
15617
+ lines.push(` * Canvas: ${canvas.pv?.description || "No description"}`);
15618
+ lines.push(` * Version: ${canvas.pv?.version || "1.0.0"}`);
15619
+ lines.push(" */");
15620
+ lines.push("");
15621
+ if (opts.namespace) {
15622
+ lines.push(`export namespace ${opts.namespace} {`);
15623
+ }
15624
+ if (canvas.nodes) {
15625
+ for (const node of canvas.nodes) {
15626
+ if (node.pv?.events) {
15627
+ lines.push(...this.generateNodeTypes(node.id, node.pv.events, opts));
15628
+ lines.push("");
15629
+ }
15630
+ }
15631
+ }
15632
+ lines.push(...this.generateEventNameUnion(canvas, opts));
15633
+ lines.push("");
15634
+ lines.push(...this.generateEmitterTypes(canvas, opts));
15635
+ if (opts.namespace) {
15636
+ lines.push("}");
15637
+ }
15638
+ const code = lines.join("\n");
15639
+ const filename = this.generateFilename(canvas);
15640
+ return {
15641
+ code,
15642
+ extension: "ts",
15643
+ filename
15644
+ };
15645
+ }
15646
+ generateNodeTypes(nodeId, events, opts) {
15647
+ const lines = [];
15648
+ const typeName = this.nodeIdToTypeName(nodeId);
15649
+ if (opts.includeDocComments) {
15650
+ lines.push(`/**`);
15651
+ lines.push(` * Event types for node: ${nodeId}`);
15652
+ lines.push(` */`);
15653
+ }
15654
+ lines.push(`export namespace ${typeName} {`);
15655
+ for (const [eventName, eventSchema] of Object.entries(events)) {
15656
+ lines.push(...this.generateEventInterface(eventName, eventSchema, opts));
15657
+ lines.push("");
15658
+ }
15659
+ const eventNames = Object.keys(events);
15660
+ const interfaceNames = eventNames.map((name) => this.eventNameToTypeName(name));
15661
+ lines.push(" /**");
15662
+ lines.push(` * Union of all event types for ${nodeId}`);
15663
+ lines.push(" */");
15664
+ lines.push(` export type Event = ${interfaceNames.join(" | ")};`);
15665
+ lines.push("");
15666
+ lines.push(" /**");
15667
+ lines.push(` * Literal union of event names for ${nodeId}`);
15668
+ lines.push(" */");
15669
+ lines.push(` export type EventName = ${eventNames.map((n) => `'${n}'`).join(" | ")};`);
15670
+ lines.push("}");
15671
+ return lines;
15672
+ }
15673
+ generateEventInterface(eventName, schema2, opts) {
15674
+ const lines = [];
15675
+ const interfaceName = this.eventNameToTypeName(eventName);
15676
+ const readonly = opts.readonly ? "readonly " : "";
15677
+ if (opts.includeDocComments) {
15678
+ lines.push(" /**");
15679
+ lines.push(` * ${schema2.description}`);
15680
+ lines.push(" */");
15681
+ }
15682
+ lines.push(` export interface ${interfaceName} {`);
15683
+ lines.push(` ${readonly}name: '${eventName}';`);
15684
+ lines.push(` ${readonly}attributes: {`);
15685
+ for (const [fieldName, fieldSchema] of Object.entries(schema2.attributes)) {
15686
+ const optional = !fieldSchema.required && opts.strictNullChecks ? "?" : "";
15687
+ const type2 = this.fieldTypeToTsType(fieldSchema);
15688
+ if (opts.includeDocComments && fieldSchema.description) {
15689
+ lines.push(` /** ${fieldSchema.description} */`);
15690
+ }
15691
+ lines.push(` ${readonly}'${fieldName}'${optional}: ${type2};`);
15692
+ }
15693
+ lines.push(" };");
15694
+ lines.push(" }");
15695
+ return lines;
15696
+ }
15697
+ generateEventNameUnion(canvas, opts) {
15698
+ const lines = [];
15699
+ const allEventNames = /* @__PURE__ */ new Set();
15700
+ if (canvas.nodes) {
15701
+ for (const node of canvas.nodes) {
15702
+ if (node.pv?.events) {
15703
+ Object.keys(node.pv.events).forEach((name) => allEventNames.add(name));
15704
+ }
15705
+ }
15706
+ }
15707
+ if (allEventNames.size === 0) {
15708
+ return lines;
15709
+ }
15710
+ if (opts.includeDocComments) {
15711
+ lines.push("/**");
15712
+ lines.push(" * Union of all event names in the canvas");
15713
+ lines.push(" */");
15714
+ }
15715
+ lines.push(`export type AllEventNames = ${Array.from(allEventNames).map((n) => `'${n}'`).join(" | ")};`);
15716
+ return lines;
15717
+ }
15718
+ generateEmitterTypes(canvas, opts) {
15719
+ const lines = [];
15720
+ if (opts.includeDocComments) {
15721
+ lines.push("/**");
15722
+ lines.push(" * Type-safe event emitter for a specific node");
15723
+ lines.push(" *");
15724
+ lines.push(" * @example");
15725
+ lines.push(" * ```typescript");
15726
+ lines.push(" * const emit: NodeEmitter<GraphConverter.EventName, GraphConverter.Event> = ...");
15727
+ lines.push(" * emit('conversion.started', {");
15728
+ lines.push(" * name: 'conversion.started',");
15729
+ lines.push(" * attributes: { ... }");
15730
+ lines.push(" * });");
15731
+ lines.push(" * ```");
15732
+ lines.push(" */");
15733
+ }
15734
+ lines.push("export type NodeEmitter<");
15735
+ lines.push(" TEventName extends string,");
15736
+ lines.push(" TEvent extends { name: TEventName; attributes: Record<string, any> }");
15737
+ lines.push("> = (event: TEvent) => void;");
15738
+ lines.push("");
15739
+ if (opts.includeDocComments) {
15740
+ lines.push("/**");
15741
+ lines.push(" * Type-safe event emitter by event name");
15742
+ lines.push(" *");
15743
+ lines.push(" * @example");
15744
+ lines.push(" * ```typescript");
15745
+ lines.push(" * const emit: NodeEmitterByName<GraphConverter.Event> = ...");
15746
+ lines.push(" * emit('conversion.started', {");
15747
+ lines.push(" * 'config.nodeTypes': 2,");
15748
+ lines.push(" * 'config.edgeTypes': 1");
15749
+ lines.push(" * });");
15750
+ lines.push(" * ```");
15751
+ lines.push(" */");
15752
+ }
15753
+ lines.push("export type NodeEmitterByName<");
15754
+ lines.push(" TEvent extends { name: string; attributes: Record<string, any> }");
15755
+ lines.push("> = <TName extends TEvent['name']>(");
15756
+ lines.push(" eventName: TName,");
15757
+ lines.push(" attributes: Extract<TEvent, { name: TName }>['attributes']");
15758
+ lines.push(") => void;");
15759
+ return lines;
15760
+ }
15761
+ nodeIdToTypeName(nodeId) {
15762
+ return nodeId.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
15763
+ }
15764
+ eventNameToTypeName(eventName) {
15765
+ return eventName.split(".").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
15766
+ }
15767
+ fieldTypeToTsType(fieldSchema) {
15768
+ switch (fieldSchema.type) {
15769
+ case "string":
15770
+ return "string";
15771
+ case "number":
15772
+ return "number";
15773
+ case "boolean":
15774
+ return "boolean";
15775
+ case "array":
15776
+ return "any[]";
15777
+ case "object":
15778
+ return "Record<string, any>";
15779
+ default:
15780
+ return "any";
15781
+ }
15782
+ }
15783
+ generateFilename(canvas) {
15784
+ const name = canvas.pv?.name || "canvas";
15785
+ const kebab = name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
15786
+ return `${kebab}.types.ts`;
15787
+ }
15788
+ };
15789
+ var generatorRegistry = {
15790
+ generators: /* @__PURE__ */ new Map([
15791
+ ["typescript", new TypeScriptGenerator()]
15792
+ ]),
15793
+ register(generator) {
15794
+ this.generators.set(generator.language, generator);
15795
+ },
15796
+ get(language) {
15797
+ return this.generators.get(language);
15798
+ },
15799
+ list() {
15800
+ return Array.from(this.generators.keys());
15801
+ }
15802
+ };
15803
+
15550
15804
  // ../core/dist/utils/YamlParser.js
15551
15805
  function parseYaml(content, filename) {
15552
15806
  try {