@principal-ai/principal-view-cli 0.3.3 → 0.3.5

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.
Files changed (58) hide show
  1. package/dist/commands/coverage.d.ts +9 -0
  2. package/dist/commands/coverage.d.ts.map +1 -0
  3. package/dist/commands/coverage.js +158 -0
  4. package/dist/commands/create.d.ts +6 -0
  5. package/dist/commands/create.d.ts.map +1 -0
  6. package/dist/commands/create.js +50 -0
  7. package/dist/commands/doctor.d.ts +10 -0
  8. package/dist/commands/doctor.d.ts.map +1 -0
  9. package/dist/commands/doctor.js +274 -0
  10. package/dist/commands/formats.d.ts +6 -0
  11. package/dist/commands/formats.d.ts.map +1 -0
  12. package/dist/commands/formats.js +475 -0
  13. package/dist/commands/hooks.d.ts +9 -0
  14. package/dist/commands/hooks.d.ts.map +1 -0
  15. package/dist/commands/hooks.js +295 -0
  16. package/dist/commands/init.d.ts +6 -0
  17. package/dist/commands/init.d.ts.map +1 -0
  18. package/dist/commands/init.js +271 -0
  19. package/dist/commands/lint.d.ts +6 -0
  20. package/dist/commands/lint.d.ts.map +1 -0
  21. package/dist/commands/lint.js +506 -0
  22. package/dist/commands/list.d.ts +6 -0
  23. package/dist/commands/list.d.ts.map +1 -0
  24. package/dist/commands/list.js +80 -0
  25. package/dist/commands/narrative/index.d.ts +3 -0
  26. package/dist/commands/narrative/index.d.ts.map +1 -0
  27. package/dist/commands/narrative/index.js +17 -0
  28. package/dist/commands/narrative/inspect.d.ts +3 -0
  29. package/dist/commands/narrative/inspect.d.ts.map +1 -0
  30. package/dist/commands/narrative/inspect.js +109 -0
  31. package/dist/commands/narrative/list.d.ts +3 -0
  32. package/dist/commands/narrative/list.d.ts.map +1 -0
  33. package/dist/commands/narrative/list.js +101 -0
  34. package/dist/commands/narrative/render.d.ts +3 -0
  35. package/dist/commands/narrative/render.d.ts.map +1 -0
  36. package/dist/commands/narrative/render.js +99 -0
  37. package/dist/commands/narrative/test.d.ts +3 -0
  38. package/dist/commands/narrative/test.d.ts.map +1 -0
  39. package/dist/commands/narrative/test.js +150 -0
  40. package/dist/commands/narrative/utils.d.ts +49 -0
  41. package/dist/commands/narrative/utils.d.ts.map +1 -0
  42. package/dist/commands/narrative/utils.js +164 -0
  43. package/dist/commands/narrative/validate.d.ts +3 -0
  44. package/dist/commands/narrative/validate.d.ts.map +1 -0
  45. package/dist/commands/narrative/validate.js +149 -0
  46. package/dist/commands/schema.d.ts +6 -0
  47. package/dist/commands/schema.d.ts.map +1 -0
  48. package/dist/commands/schema.js +336 -0
  49. package/dist/commands/validate-execution.d.ts +11 -0
  50. package/dist/commands/validate-execution.d.ts.map +1 -0
  51. package/dist/commands/validate-execution.js +223 -0
  52. package/dist/commands/validate.d.ts +6 -0
  53. package/dist/commands/validate.d.ts.map +1 -0
  54. package/dist/commands/validate.js +1065 -0
  55. package/dist/index.d.ts +8 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +45 -0
  58. package/package.json +2 -2
@@ -0,0 +1,295 @@
1
+ /**
2
+ * Hooks command - Manage husky pre-commit hooks for Principal View
3
+ *
4
+ * This command installs/removes pre-commit hooks into a target project
5
+ * that will run `npx @principal-ai/principal-view-cli doctor` and `npx @principal-ai/principal-view-cli validate` before each commit.
6
+ */
7
+ import { Command } from 'commander';
8
+ import { existsSync, readFileSync, writeFileSync, unlinkSync, chmodSync } from 'node:fs';
9
+ import { resolve, join } from 'node:path';
10
+ import chalk from 'chalk';
11
+ import { execSync } from 'node:child_process';
12
+ const HUSKY_DIR = '.husky';
13
+ const PRE_COMMIT_HOOK = 'pre-commit';
14
+ const VV_HOOK_MARKER = '# Principal View checks';
15
+ /**
16
+ * Get the Principal View pre-commit hook content
17
+ */
18
+ function getVVHookContent() {
19
+ return `${VV_HOOK_MARKER}
20
+ echo "Running Principal View doctor check..."
21
+ npx @principal-ai/principal-view-cli doctor --errors-only || {
22
+ echo "❌ Principal View doctor check failed (errors found)"
23
+ echo " Run 'npx @principal-ai/principal-view-cli doctor' to see details"
24
+ exit 1
25
+ }
26
+
27
+ echo "Running Principal View canvas validation..."
28
+ npx @principal-ai/principal-view-cli validate --quiet 2>/dev/null || {
29
+ if [ $? -ne 0 ]; then
30
+ echo "❌ Canvas validation failed"
31
+ echo " Run 'npx @principal-ai/principal-view-cli validate' to see details"
32
+ exit 1
33
+ fi
34
+ }
35
+ `;
36
+ }
37
+ /**
38
+ * Find the repository root by looking for .git directory
39
+ */
40
+ function findRepoRoot(startPath) {
41
+ let current = resolve(startPath);
42
+ const root = resolve('/');
43
+ while (current !== root) {
44
+ if (existsSync(join(current, '.git'))) {
45
+ return current;
46
+ }
47
+ current = resolve(current, '..');
48
+ }
49
+ throw new Error('Not a git repository (or any parent up to mount point)');
50
+ }
51
+ /**
52
+ * Check if husky is installed
53
+ */
54
+ function isHuskyInstalled(repoPath) {
55
+ const huskyPath = join(repoPath, HUSKY_DIR);
56
+ return existsSync(huskyPath);
57
+ }
58
+ /**
59
+ * Initialize husky if not already installed
60
+ */
61
+ function initializeHusky(repoPath) {
62
+ if (!isHuskyInstalled(repoPath)) {
63
+ console.log('📦 Installing husky...');
64
+ try {
65
+ // Check if package.json exists
66
+ const packageJsonPath = join(repoPath, 'package.json');
67
+ if (!existsSync(packageJsonPath)) {
68
+ throw new Error('No package.json found. Please run npm init first.');
69
+ }
70
+ // Install husky
71
+ execSync('npm install --save-dev husky', {
72
+ cwd: repoPath,
73
+ stdio: 'inherit',
74
+ });
75
+ // Initialize husky
76
+ execSync('npx husky init', {
77
+ cwd: repoPath,
78
+ stdio: 'inherit',
79
+ });
80
+ // Remove the default placeholder if it exists
81
+ const hookPath = join(repoPath, HUSKY_DIR, PRE_COMMIT_HOOK);
82
+ if (existsSync(hookPath)) {
83
+ const content = readFileSync(hookPath, 'utf8').trim();
84
+ if (content === 'npm test') {
85
+ // Remove the placeholder file - we'll create our own when --add is used
86
+ unlinkSync(hookPath);
87
+ console.log('ℹ️ Removed default husky placeholder hook');
88
+ }
89
+ }
90
+ console.log('✅ Husky installed and initialized');
91
+ }
92
+ catch (error) {
93
+ throw new Error(`Failed to initialize husky: ${error instanceof Error ? error.message : String(error)}`);
94
+ }
95
+ }
96
+ }
97
+ /**
98
+ * Check if pre-commit hook has PV validation
99
+ */
100
+ function hasVVHook(repoPath) {
101
+ const hookPath = join(repoPath, HUSKY_DIR, PRE_COMMIT_HOOK);
102
+ if (!existsSync(hookPath)) {
103
+ return false;
104
+ }
105
+ const content = readFileSync(hookPath, 'utf8');
106
+ return content.includes(VV_HOOK_MARKER);
107
+ }
108
+ /**
109
+ * Add PV validation to pre-commit hook
110
+ */
111
+ function addVVHook(repoPath) {
112
+ const hookPath = join(repoPath, HUSKY_DIR, PRE_COMMIT_HOOK);
113
+ const vvContent = getVVHookContent();
114
+ if (existsSync(hookPath)) {
115
+ // Append to existing hook
116
+ const existingContent = readFileSync(hookPath, 'utf8');
117
+ // Check if already has PV hook
118
+ if (existingContent.includes(VV_HOOK_MARKER)) {
119
+ return;
120
+ }
121
+ // Remove default husky placeholder if it's the only content
122
+ const trimmedContent = existingContent.trim();
123
+ if (trimmedContent === 'npm test') {
124
+ // Replace the placeholder entirely
125
+ writeFileSync(hookPath, vvContent, 'utf8');
126
+ console.log('ℹ️ Replaced default husky placeholder with Principal View checks');
127
+ }
128
+ else {
129
+ // Add PV hook at the end
130
+ const updatedContent = existingContent.trimEnd() + '\n\n' + vvContent;
131
+ writeFileSync(hookPath, updatedContent, 'utf8');
132
+ }
133
+ }
134
+ else {
135
+ // Create new hook file
136
+ writeFileSync(hookPath, vvContent, 'utf8');
137
+ // Make it executable
138
+ chmodSync(hookPath, 0o755);
139
+ }
140
+ }
141
+ /**
142
+ * Remove PV validation from pre-commit hook
143
+ */
144
+ function removeVVHook(repoPath) {
145
+ const hookPath = join(repoPath, HUSKY_DIR, PRE_COMMIT_HOOK);
146
+ if (!existsSync(hookPath)) {
147
+ return;
148
+ }
149
+ const content = readFileSync(hookPath, 'utf8');
150
+ if (!content.includes(VV_HOOK_MARKER)) {
151
+ return;
152
+ }
153
+ // Split content by lines and find the PV section
154
+ const lines = content.split('\n');
155
+ const startIndex = lines.findIndex((line) => line.includes(VV_HOOK_MARKER));
156
+ if (startIndex === -1) {
157
+ return;
158
+ }
159
+ // Find the end of the PV section
160
+ let endIndex = lines.length - 1;
161
+ let inVVBlock = true;
162
+ let i = startIndex + 1;
163
+ while (i < lines.length && inVVBlock) {
164
+ const line = lines[i];
165
+ // Check if this line is part of the PV block
166
+ if (line &&
167
+ (line.includes('@principal-ai/principal-view-cli ') ||
168
+ line.includes('Principal View') ||
169
+ line.includes('echo "Running Visual') ||
170
+ (line.includes('exit 1') && i > startIndex && i < startIndex + 15) ||
171
+ (line === '}' && i > startIndex && i < startIndex + 15) ||
172
+ (line.trim() === '' && i === startIndex + 1))) {
173
+ endIndex = i;
174
+ i++;
175
+ }
176
+ else if (line && line.trim() === '' && i < startIndex + 15) {
177
+ // Empty line might be part of our block
178
+ endIndex = i;
179
+ i++;
180
+ }
181
+ else {
182
+ // We've reached content that's not part of our block
183
+ inVVBlock = false;
184
+ }
185
+ }
186
+ // Remove the section (inclusive)
187
+ lines.splice(startIndex, endIndex - startIndex + 1);
188
+ // Clean up extra blank lines
189
+ let result = lines.join('\n');
190
+ result = result.replace(/\n{3,}/g, '\n\n').trim();
191
+ if (result) {
192
+ writeFileSync(hookPath, result + '\n', 'utf8');
193
+ }
194
+ else {
195
+ // If hook is now empty, remove it
196
+ unlinkSync(hookPath);
197
+ }
198
+ }
199
+ export function createHooksCommand() {
200
+ const command = new Command('hooks');
201
+ command
202
+ .description('Manage husky pre-commit hooks for Principal View')
203
+ .option('-p, --path <path>', 'Repository path (defaults to current directory)')
204
+ .option('--add', 'Add Principal View checks to pre-commit hook')
205
+ .option('--remove', 'Remove Principal View checks from pre-commit hook')
206
+ .option('--check', 'Check if Principal View checks exist in pre-commit hook')
207
+ .option('--init', 'Initialize husky if not already installed')
208
+ .action((options) => {
209
+ try {
210
+ const repoPath = findRepoRoot(options.path || process.cwd());
211
+ // Check if it's a git repository
212
+ if (!existsSync(join(repoPath, '.git'))) {
213
+ console.error(chalk.red('❌ Not a git repository'));
214
+ process.exit(1);
215
+ }
216
+ // Handle init option
217
+ if (options.init) {
218
+ initializeHusky(repoPath);
219
+ return;
220
+ }
221
+ // Check if husky is installed
222
+ if (!isHuskyInstalled(repoPath)) {
223
+ if (options.check) {
224
+ console.log(chalk.red('❌ Husky is not installed'));
225
+ console.log(' Run "npx @principal-ai/principal-view-cli hooks --init" to install husky');
226
+ process.exit(1);
227
+ }
228
+ else if (options.add) {
229
+ console.log(chalk.red('❌ Husky is not installed'));
230
+ console.log(' Run "npx @principal-ai/principal-view-cli hooks --init" first to install husky');
231
+ process.exit(1);
232
+ }
233
+ else if (options.remove) {
234
+ console.log('ℹ️ Husky is not installed');
235
+ return;
236
+ }
237
+ else {
238
+ console.log(chalk.red('❌ Husky is not installed in this repository'));
239
+ console.log('\nTo install husky and set up Principal View hooks:');
240
+ console.log(' npx @principal-ai/principal-view-cli hooks --init --add');
241
+ process.exit(1);
242
+ }
243
+ }
244
+ const hasHook = hasVVHook(repoPath);
245
+ if (options.check) {
246
+ if (hasHook) {
247
+ console.log(chalk.green('✅ Principal View checks found in pre-commit hook'));
248
+ }
249
+ else {
250
+ console.log(chalk.red('❌ No Principal View checks in pre-commit hook'));
251
+ process.exit(1);
252
+ }
253
+ }
254
+ else if (options.add) {
255
+ if (hasHook) {
256
+ console.log('ℹ️ Principal View checks already exist in pre-commit hook');
257
+ }
258
+ else {
259
+ addVVHook(repoPath);
260
+ console.log(chalk.green('✅ Added Principal View checks to pre-commit hook'));
261
+ console.log('\nPre-commit hook will now:');
262
+ console.log(' • Run npx @principal-ai/principal-view-cli doctor to check for stale configurations');
263
+ console.log(' • Validate all .canvas files');
264
+ }
265
+ }
266
+ else if (options.remove) {
267
+ if (!hasHook) {
268
+ console.log('ℹ️ No Principal View checks found in pre-commit hook');
269
+ }
270
+ else {
271
+ removeVVHook(repoPath);
272
+ console.log(chalk.green('✅ Removed Principal View checks from pre-commit hook'));
273
+ }
274
+ }
275
+ else {
276
+ // Default action: show status
277
+ console.log(chalk.bold('\nPrincipal View Hooks Status\n'));
278
+ console.log(`Repository: ${repoPath}`);
279
+ console.log(`Husky: ${chalk.green('installed')}`);
280
+ console.log(`PV Hooks: ${hasHook ? chalk.green('configured') : chalk.yellow('not configured')}`);
281
+ if (hasHook) {
282
+ console.log('\nUse --remove to remove or --check to verify');
283
+ }
284
+ else {
285
+ console.log('\nUse --add to add or --check to verify');
286
+ }
287
+ }
288
+ }
289
+ catch (error) {
290
+ console.error(chalk.red('Error:'), error instanceof Error ? error.message : String(error));
291
+ process.exit(1);
292
+ }
293
+ });
294
+ return command;
295
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Init command - Initialize a .principal-views folder with template files and linting setup
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function createInitCommand(): Command;
6
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+GpC,wBAAgB,iBAAiB,IAAI,OAAO,CA4L3C"}
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Init command - Initialize a .principal-views folder with template files and linting setup
3
+ */
4
+ import { Command } from 'commander';
5
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, chmodSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { execSync } from 'node:child_process';
8
+ import chalk from 'chalk';
9
+ const TEMPLATE_CANVAS = {
10
+ nodes: [],
11
+ edges: [],
12
+ };
13
+ const TEMPLATE_PRIVURC = `# Principal View Configuration Lint Rules
14
+ # See: https://github.com/principal-ai/principal-view
15
+
16
+ # File patterns to include
17
+ include:
18
+ - ".principal-views/**/*.yaml"
19
+ - ".principal-views/**/*.yml"
20
+ - ".principal-views/**/*.json"
21
+
22
+ # File patterns to exclude
23
+ exclude:
24
+ - "**/node_modules/**"
25
+ - ".principal-views/library.yaml"
26
+
27
+ # Path to component library (optional)
28
+ library: ".principal-views/library.yaml"
29
+
30
+ # Rule configuration
31
+ # Severity: "off" | "warn" | "error" (or 0 | 1 | 2)
32
+ rules:
33
+ # Schema rules - validate structure
34
+ no-unknown-fields: error
35
+ required-metadata: error
36
+ valid-node-types: error
37
+ valid-edge-types: error
38
+ valid-color-format: error
39
+
40
+ # Reference rules - check cross-references
41
+ connection-type-references: error
42
+ state-transition-references: error
43
+
44
+ # Structure rules - ensure completeness
45
+ minimum-node-sources:
46
+ severity: error
47
+ options:
48
+ minimum: 1
49
+ excludeNodeTypes: []
50
+ orphaned-node-types: error
51
+ orphaned-edge-types: error
52
+ unreachable-states: error
53
+ dead-end-states: error
54
+
55
+ # Pattern rules - validate regex patterns
56
+ valid-action-patterns:
57
+ severity: error
58
+ options:
59
+ strictMode: false
60
+
61
+ # Library rules - check against component library
62
+ library-node-type-match:
63
+ severity: error
64
+ options:
65
+ allowExtra: true
66
+ `;
67
+ const HUSKY_PRE_COMMIT = `# Run principal view linting on staged .principal-views files
68
+ npx @principal-ai/principal-view-cli lint --quiet
69
+ `;
70
+ /**
71
+ * Check if we're in a git repository
72
+ */
73
+ function isGitRepo() {
74
+ try {
75
+ execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
76
+ return true;
77
+ }
78
+ catch {
79
+ return false;
80
+ }
81
+ }
82
+ /**
83
+ * Get the git root directory
84
+ */
85
+ function getGitRoot() {
86
+ try {
87
+ return execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
88
+ }
89
+ catch {
90
+ return null;
91
+ }
92
+ }
93
+ /**
94
+ * Check if husky is already installed
95
+ */
96
+ function isHuskyInstalled(gitRoot) {
97
+ return existsSync(join(gitRoot, '.husky'));
98
+ }
99
+ /**
100
+ * Detect package manager
101
+ */
102
+ function detectPackageManager() {
103
+ if (existsSync('bun.lockb'))
104
+ return 'bun';
105
+ if (existsSync('pnpm-lock.yaml'))
106
+ return 'pnpm';
107
+ if (existsSync('yarn.lock'))
108
+ return 'yarn';
109
+ return 'npm';
110
+ }
111
+ export function createInitCommand() {
112
+ const command = new Command('init');
113
+ command
114
+ .description('Initialize a .principal-views folder with template files and linting setup')
115
+ .option('-f, --force', 'Overwrite existing files')
116
+ .option('-n, --name <name>', 'Name for the canvas file', 'architecture')
117
+ .option('--no-husky', 'Skip Husky pre-commit hook setup')
118
+ .option('--no-lint-config', 'Skip .privurc.yaml creation')
119
+ .action(async (options) => {
120
+ try {
121
+ const cwd = process.cwd();
122
+ const principalViewsDir = join(cwd, '.principal-views');
123
+ const canvasFile = join(principalViewsDir, `${options.name}.canvas`);
124
+ const libraryFile = join(principalViewsDir, 'library.yaml');
125
+ const privurcFile = join(cwd, '.privurc.yaml');
126
+ // Check if .principal-views directory exists
127
+ if (!existsSync(principalViewsDir)) {
128
+ mkdirSync(principalViewsDir, { recursive: true });
129
+ console.log(chalk.green(`Created directory: .principal-views/`));
130
+ }
131
+ // Create canvas file
132
+ if (existsSync(canvasFile) && !options.force) {
133
+ console.log(chalk.yellow(`Canvas file already exists: .principal-views/${options.name}.canvas`));
134
+ }
135
+ else {
136
+ writeFileSync(canvasFile, JSON.stringify(TEMPLATE_CANVAS, null, 2));
137
+ console.log(chalk.green(`Created canvas file: .principal-views/${options.name}.canvas`));
138
+ }
139
+ // Create library file
140
+ if (existsSync(libraryFile) && !options.force) {
141
+ console.log(chalk.yellow(`Library file already exists: .principal-views/library.yaml`));
142
+ }
143
+ else {
144
+ const libraryYaml = `version: "1.0.0"
145
+ name: "Component Library"
146
+
147
+ nodeComponents: {}
148
+
149
+ edgeComponents: {}
150
+ `;
151
+ writeFileSync(libraryFile, libraryYaml);
152
+ console.log(chalk.green(`Created library file: .principal-views/library.yaml`));
153
+ }
154
+ // Create .privurc.yaml config file
155
+ if (options.lintConfig !== false) {
156
+ if (existsSync(privurcFile) && !options.force) {
157
+ console.log(chalk.yellow(`Config file already exists: .privurc.yaml`));
158
+ }
159
+ else {
160
+ writeFileSync(privurcFile, TEMPLATE_PRIVURC);
161
+ console.log(chalk.green(`Created lint config: .privurc.yaml`));
162
+ }
163
+ }
164
+ // Set up Husky pre-commit hook
165
+ let huskySetup = false;
166
+ if (options.husky !== false) {
167
+ if (!isGitRepo()) {
168
+ console.log(chalk.yellow(`Skipping Husky setup: not a git repository`));
169
+ }
170
+ else {
171
+ const gitRoot = getGitRoot();
172
+ if (!gitRoot) {
173
+ console.log(chalk.yellow(`Skipping Husky setup: could not find git root`));
174
+ }
175
+ else {
176
+ const huskyDir = join(gitRoot, '.husky');
177
+ const preCommitFile = join(huskyDir, 'pre-commit');
178
+ if (isHuskyInstalled(gitRoot)) {
179
+ // Husky is already installed, just add/update pre-commit hook
180
+ if (existsSync(preCommitFile)) {
181
+ // Check if our hook is already in the file
182
+ const existingContent = readFileSync(preCommitFile, 'utf8');
183
+ if (existingContent.includes('principal-view-cli lint')) {
184
+ console.log(chalk.yellow(`Husky pre-commit hook already includes principal view linting`));
185
+ }
186
+ else {
187
+ // Append our lint command to existing pre-commit
188
+ const updatedContent = existingContent.trimEnd() +
189
+ '\n\n# Run principal view linting\nnpx @principal-ai/principal-view-cli lint --quiet\n';
190
+ writeFileSync(preCommitFile, updatedContent);
191
+ console.log(chalk.green(`Updated Husky pre-commit hook with principal view linting`));
192
+ huskySetup = true;
193
+ }
194
+ }
195
+ else {
196
+ // Create new pre-commit hook
197
+ writeFileSync(preCommitFile, HUSKY_PRE_COMMIT);
198
+ chmodSync(preCommitFile, '755');
199
+ console.log(chalk.green(`Created Husky pre-commit hook`));
200
+ huskySetup = true;
201
+ }
202
+ }
203
+ else {
204
+ // Husky is not installed, try to install it
205
+ const pm = detectPackageManager();
206
+ const packageJsonPath = join(gitRoot, 'package.json');
207
+ if (!existsSync(packageJsonPath)) {
208
+ console.log(chalk.yellow(`Skipping Husky setup: no package.json found`));
209
+ }
210
+ else {
211
+ console.log(chalk.dim(`Installing Husky...`));
212
+ try {
213
+ // Install husky as dev dependency
214
+ const installCmd = {
215
+ npm: 'npm install --save-dev husky',
216
+ yarn: 'yarn add --dev husky',
217
+ pnpm: 'pnpm add --save-dev husky',
218
+ bun: 'bun add --dev husky',
219
+ }[pm];
220
+ execSync(installCmd, { stdio: 'inherit', cwd: gitRoot });
221
+ // Initialize husky
222
+ execSync('npx husky init', { stdio: 'inherit', cwd: gitRoot });
223
+ // Write our pre-commit hook
224
+ writeFileSync(preCommitFile, HUSKY_PRE_COMMIT);
225
+ chmodSync(preCommitFile, '755');
226
+ console.log(chalk.green(`Installed Husky and created pre-commit hook`));
227
+ huskySetup = true;
228
+ }
229
+ catch (installError) {
230
+ console.log(chalk.yellow(`Could not install Husky automatically: ${installError.message}`));
231
+ console.log(chalk.dim(` You can install it manually: ${pm} add --dev husky && npx husky init`));
232
+ }
233
+ }
234
+ }
235
+ }
236
+ }
237
+ }
238
+ console.log('');
239
+ console.log(chalk.bold('Setup complete!'));
240
+ console.log('');
241
+ console.log(chalk.bold('Files created:'));
242
+ console.log(` • ${chalk.cyan('.principal-views/library.yaml')} - Component library definitions`);
243
+ console.log(` • ${chalk.cyan(`.principal-views/${options.name}.canvas`)} - Graph canvas file`);
244
+ if (options.lintConfig !== false) {
245
+ console.log(` • ${chalk.cyan('.privurc.yaml')} - Lint configuration`);
246
+ }
247
+ if (huskySetup) {
248
+ console.log(` • ${chalk.cyan('.husky/pre-commit')} - Pre-commit hook`);
249
+ }
250
+ console.log('');
251
+ console.log(chalk.bold('Next steps:'));
252
+ console.log(` 1. Define components in ${chalk.cyan('.principal-views/library.yaml')}`);
253
+ console.log(` 2. Build your graph in ${chalk.cyan(`.principal-views/${options.name}.canvas`)}`);
254
+ console.log(` 3. Run ${chalk.cyan('npx @principal-ai/principal-view-cli lint')} to validate your configuration`);
255
+ if (huskySetup) {
256
+ console.log(` 4. Commits will now automatically lint .principal-views files`);
257
+ }
258
+ console.log('');
259
+ console.log(chalk.bold('Commands:'));
260
+ console.log(` • ${chalk.cyan('npx @principal-ai/principal-view-cli lint')} - Lint configuration files`);
261
+ console.log(` • ${chalk.cyan('npx @principal-ai/principal-view-cli lint --json')} - Output lint results as JSON`);
262
+ console.log(` • ${chalk.cyan('npx @principal-ai/principal-view-cli validate')} - Validate canvas files`);
263
+ console.log(` • ${chalk.cyan('npx @principal-ai/principal-view-cli doctor')} - Check project setup`);
264
+ }
265
+ catch (error) {
266
+ console.error(chalk.red('Error:'), error.message);
267
+ process.exit(1);
268
+ }
269
+ });
270
+ return command;
271
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Lint command - Lint graph configuration files using the rules engine
3
+ */
4
+ import { Command } from 'commander';
5
+ export declare function createLintCommand(): Command;
6
+ //# sourceMappingURL=lint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsUpC,wBAAgB,iBAAiB,IAAI,OAAO,CA+P3C"}