@principal-ai/principal-view-cli 0.2.1 → 0.2.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAunCpC,wBAAgB,qBAAqB,IAAI,OAAO,CAsH/C"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+pCpC,wBAAgB,qBAAqB,IAAI,OAAO,CAiI/C"}
@@ -396,8 +396,9 @@ function hasOtelFeatures(canvas) {
396
396
  * - Edge types reference defined types in pv.edgeTypes or library.edgeComponents
397
397
  * - Node types reference defined types in pv.nodeTypes or library.nodeComponents
398
398
  * - Canvas has pv extension with name and version
399
+ * - OTEL nodes have source file references and the files exist
399
400
  */
400
- function validateCanvas(canvas, filePath, library) {
401
+ function validateCanvas(canvas, filePath, library, repositoryPath) {
401
402
  const issues = [];
402
403
  if (!canvas || typeof canvas !== 'object') {
403
404
  issues.push({ type: 'error', message: 'Canvas must be an object' });
@@ -633,6 +634,37 @@ function validateCanvas(canvas, filePath, library) {
633
634
  if (nodePv.otel && typeof nodePv.otel === 'object') {
634
635
  checkUnknownFields(nodePv.otel, ALLOWED_CANVAS_FIELDS.nodePvOtel, `${nodePath}.pv.otel`, issues);
635
636
  }
637
+ // Validate source file references for OTEL event nodes
638
+ const hasOtelFeatures = nodePv.otel !== undefined || nodePv.events !== undefined;
639
+ if (hasOtelFeatures) {
640
+ // OTEL nodes must have at least one source file reference
641
+ if (!Array.isArray(nodePv.sources) || nodePv.sources.length === 0) {
642
+ issues.push({
643
+ type: 'error',
644
+ message: `Node "${nodeLabel}" has OTEL features but is missing required "pv.sources" field`,
645
+ path: `${nodePath}.pv.sources`,
646
+ suggestion: 'Add at least one source file reference, e.g.: "sources": ["src/services/MyService.ts"]',
647
+ });
648
+ }
649
+ }
650
+ // Validate that all source files exist (if repository path is provided)
651
+ if (Array.isArray(nodePv.sources) && repositoryPath) {
652
+ nodePv.sources.forEach((source, sourceIndex) => {
653
+ if (typeof source === 'string') {
654
+ // Remove glob patterns (* characters) to get the base path
655
+ const cleanPath = source.replace(/\*/g, '');
656
+ const fullPath = resolve(repositoryPath, cleanPath);
657
+ if (!existsSync(fullPath)) {
658
+ issues.push({
659
+ type: 'error',
660
+ message: `Node "${nodeLabel}" references non-existent source file: ${source}`,
661
+ path: `${nodePath}.pv.sources[${sourceIndex}]`,
662
+ suggestion: `Verify the file path is correct relative to repository root: ${repositoryPath}`,
663
+ });
664
+ }
665
+ }
666
+ });
667
+ }
636
668
  if (Array.isArray(nodePv.actions)) {
637
669
  nodePv.actions.forEach((action, actionIndex) => {
638
670
  if (action && typeof action === 'object') {
@@ -855,7 +887,7 @@ function validateCanvas(canvas, filePath, library) {
855
887
  /**
856
888
  * Validate a single .canvas file
857
889
  */
858
- function validateFile(filePath, library) {
890
+ function validateFile(filePath, library, repositoryPath) {
859
891
  const absolutePath = resolve(filePath);
860
892
  const relativePath = relative(process.cwd(), absolutePath);
861
893
  if (!existsSync(absolutePath)) {
@@ -868,7 +900,7 @@ function validateFile(filePath, library) {
868
900
  try {
869
901
  const content = readFileSync(absolutePath, 'utf8');
870
902
  const canvas = JSON.parse(content);
871
- const issues = validateCanvas(canvas, relativePath, library);
903
+ const issues = validateCanvas(canvas, relativePath, library, repositoryPath);
872
904
  const hasErrors = issues.some((i) => i.type === 'error');
873
905
  return {
874
906
  file: relativePath,
@@ -892,6 +924,7 @@ export function createValidateCommand() {
892
924
  .argument('[files...]', 'Files or glob patterns to validate (defaults to .principal-views/*.canvas)')
893
925
  .option('-q, --quiet', 'Only output errors')
894
926
  .option('--json', 'Output results as JSON')
927
+ .option('-r, --repository <path>', 'Repository root path for validating source file references (defaults to current directory)')
895
928
  .action(async (files, options) => {
896
929
  try {
897
930
  // Default to .principal-views/*.canvas if no files specified
@@ -914,6 +947,10 @@ export function createValidateCommand() {
914
947
  // Load library from .principal-views directory (used for type validation)
915
948
  const principalViewsDir = resolve(process.cwd(), '.principal-views');
916
949
  const library = loadLibrary(principalViewsDir);
950
+ // Determine repository path for source file validation
951
+ const repositoryPath = options.repository
952
+ ? resolve(options.repository)
953
+ : process.cwd();
917
954
  // Validate library if present
918
955
  let libraryResult = null;
919
956
  if (library && Object.keys(library.raw).length > 0) {
@@ -926,7 +963,7 @@ export function createValidateCommand() {
926
963
  };
927
964
  }
928
965
  // Validate all canvas files
929
- const results = matchedFiles.map((f) => validateFile(f, library));
966
+ const results = matchedFiles.map((f) => validateFile(f, library, repositoryPath));
930
967
  // Combine results
931
968
  const allResults = libraryResult ? [libraryResult, ...results] : results;
932
969
  const validCount = allResults.filter((r) => r.isValid).length;
package/dist/index.cjs CHANGED
@@ -228747,7 +228747,7 @@ function hasOtelFeatures(canvas) {
228747
228747
  }
228748
228748
  return false;
228749
228749
  }
228750
- function validateCanvas(canvas, filePath, library) {
228750
+ function validateCanvas(canvas, filePath, library, repositoryPath) {
228751
228751
  const issues = [];
228752
228752
  if (!canvas || typeof canvas !== "object") {
228753
228753
  issues.push({ type: "error", message: "Canvas must be an object" });
@@ -229019,6 +229019,33 @@ function validateCanvas(canvas, filePath, library) {
229019
229019
  issues
229020
229020
  );
229021
229021
  }
229022
+ const hasOtelFeatures2 = nodePv.otel !== void 0 || nodePv.events !== void 0;
229023
+ if (hasOtelFeatures2) {
229024
+ if (!Array.isArray(nodePv.sources) || nodePv.sources.length === 0) {
229025
+ issues.push({
229026
+ type: "error",
229027
+ message: `Node "${nodeLabel}" has OTEL features but is missing required "pv.sources" field`,
229028
+ path: `${nodePath2}.pv.sources`,
229029
+ suggestion: 'Add at least one source file reference, e.g.: "sources": ["src/services/MyService.ts"]'
229030
+ });
229031
+ }
229032
+ }
229033
+ if (Array.isArray(nodePv.sources) && repositoryPath) {
229034
+ nodePv.sources.forEach((source, sourceIndex) => {
229035
+ if (typeof source === "string") {
229036
+ const cleanPath = source.replace(/\*/g, "");
229037
+ const fullPath = (0, import_node_path5.resolve)(repositoryPath, cleanPath);
229038
+ if (!(0, import_node_fs4.existsSync)(fullPath)) {
229039
+ issues.push({
229040
+ type: "error",
229041
+ message: `Node "${nodeLabel}" references non-existent source file: ${source}`,
229042
+ path: `${nodePath2}.pv.sources[${sourceIndex}]`,
229043
+ suggestion: `Verify the file path is correct relative to repository root: ${repositoryPath}`
229044
+ });
229045
+ }
229046
+ }
229047
+ });
229048
+ }
229022
229049
  if (Array.isArray(nodePv.actions)) {
229023
229050
  nodePv.actions.forEach((action, actionIndex) => {
229024
229051
  if (action && typeof action === "object") {
@@ -229230,7 +229257,7 @@ function validateCanvas(canvas, filePath, library) {
229230
229257
  }
229231
229258
  return issues;
229232
229259
  }
229233
- function validateFile(filePath, library) {
229260
+ function validateFile(filePath, library, repositoryPath) {
229234
229261
  const absolutePath = (0, import_node_path5.resolve)(filePath);
229235
229262
  const relativePath = (0, import_node_path5.relative)(process.cwd(), absolutePath);
229236
229263
  if (!(0, import_node_fs4.existsSync)(absolutePath)) {
@@ -229243,7 +229270,7 @@ function validateFile(filePath, library) {
229243
229270
  try {
229244
229271
  const content = (0, import_node_fs4.readFileSync)(absolutePath, "utf8");
229245
229272
  const canvas = JSON.parse(content);
229246
- const issues = validateCanvas(canvas, relativePath, library);
229273
+ const issues = validateCanvas(canvas, relativePath, library, repositoryPath);
229247
229274
  const hasErrors = issues.some((i) => i.type === "error");
229248
229275
  return {
229249
229276
  file: relativePath,
@@ -229264,7 +229291,10 @@ function createValidateCommand() {
229264
229291
  command.description("Validate .canvas configuration files").argument(
229265
229292
  "[files...]",
229266
229293
  "Files or glob patterns to validate (defaults to .principal-views/*.canvas)"
229267
- ).option("-q, --quiet", "Only output errors").option("--json", "Output results as JSON").action(async (files, options) => {
229294
+ ).option("-q, --quiet", "Only output errors").option("--json", "Output results as JSON").option(
229295
+ "-r, --repository <path>",
229296
+ "Repository root path for validating source file references (defaults to current directory)"
229297
+ ).action(async (files, options) => {
229268
229298
  try {
229269
229299
  const patterns = files.length > 0 ? files : [".principal-views/*.canvas"];
229270
229300
  const matchedFiles = await globby(patterns, {
@@ -229282,6 +229312,7 @@ function createValidateCommand() {
229282
229312
  }
229283
229313
  const principalViewsDir = (0, import_node_path5.resolve)(process.cwd(), ".principal-views");
229284
229314
  const library = loadLibrary(principalViewsDir);
229315
+ const repositoryPath = options.repository ? (0, import_node_path5.resolve)(options.repository) : process.cwd();
229285
229316
  let libraryResult = null;
229286
229317
  if (library && Object.keys(library.raw).length > 0) {
229287
229318
  const libraryIssues = validateLibrary(library);
@@ -229292,7 +229323,9 @@ function createValidateCommand() {
229292
229323
  issues: libraryIssues
229293
229324
  };
229294
229325
  }
229295
- const results = matchedFiles.map((f) => validateFile(f, library));
229326
+ const results = matchedFiles.map(
229327
+ (f) => validateFile(f, library, repositoryPath)
229328
+ );
229296
229329
  const allResults = libraryResult ? [libraryResult, ...results] : results;
229297
229330
  const validCount = allResults.filter((r) => r.isValid).length;
229298
229331
  const invalidCount = allResults.length - validCount;