qualyx 0.3.0

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 (100) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +523 -0
  3. package/dist/cli/commands/init.d.ts +6 -0
  4. package/dist/cli/commands/init.d.ts.map +1 -0
  5. package/dist/cli/commands/init.js +124 -0
  6. package/dist/cli/commands/init.js.map +1 -0
  7. package/dist/cli/commands/list.d.ts +3 -0
  8. package/dist/cli/commands/list.d.ts.map +1 -0
  9. package/dist/cli/commands/list.js +122 -0
  10. package/dist/cli/commands/list.js.map +1 -0
  11. package/dist/cli/commands/run.d.ts +12 -0
  12. package/dist/cli/commands/run.d.ts.map +1 -0
  13. package/dist/cli/commands/run.js +160 -0
  14. package/dist/cli/commands/run.js.map +1 -0
  15. package/dist/cli/commands/schedule.d.ts +19 -0
  16. package/dist/cli/commands/schedule.d.ts.map +1 -0
  17. package/dist/cli/commands/schedule.js +240 -0
  18. package/dist/cli/commands/schedule.js.map +1 -0
  19. package/dist/cli/commands/validate.d.ts +3 -0
  20. package/dist/cli/commands/validate.d.ts.map +1 -0
  21. package/dist/cli/commands/validate.js +47 -0
  22. package/dist/cli/commands/validate.js.map +1 -0
  23. package/dist/cli/index.d.ts +3 -0
  24. package/dist/cli/index.d.ts.map +1 -0
  25. package/dist/cli/index.js +194 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/core/claude-runner.d.ts +23 -0
  28. package/dist/core/claude-runner.d.ts.map +1 -0
  29. package/dist/core/claude-runner.js +196 -0
  30. package/dist/core/claude-runner.js.map +1 -0
  31. package/dist/core/config-loader.d.ts +137 -0
  32. package/dist/core/config-loader.d.ts.map +1 -0
  33. package/dist/core/config-loader.js +239 -0
  34. package/dist/core/config-loader.js.map +1 -0
  35. package/dist/core/executor.d.ts +75 -0
  36. package/dist/core/executor.d.ts.map +1 -0
  37. package/dist/core/executor.js +337 -0
  38. package/dist/core/executor.js.map +1 -0
  39. package/dist/core/index.d.ts +6 -0
  40. package/dist/core/index.d.ts.map +1 -0
  41. package/dist/core/index.js +7 -0
  42. package/dist/core/index.js.map +1 -0
  43. package/dist/core/prompt-builder.d.ts +24 -0
  44. package/dist/core/prompt-builder.d.ts.map +1 -0
  45. package/dist/core/prompt-builder.js +145 -0
  46. package/dist/core/prompt-builder.js.map +1 -0
  47. package/dist/core/retry-handler.d.ts +42 -0
  48. package/dist/core/retry-handler.d.ts.map +1 -0
  49. package/dist/core/retry-handler.js +126 -0
  50. package/dist/core/retry-handler.js.map +1 -0
  51. package/dist/index.d.ts +3 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +16 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/integrations/email.d.ts +38 -0
  56. package/dist/integrations/email.d.ts.map +1 -0
  57. package/dist/integrations/email.js +216 -0
  58. package/dist/integrations/email.js.map +1 -0
  59. package/dist/integrations/index.d.ts +5 -0
  60. package/dist/integrations/index.d.ts.map +1 -0
  61. package/dist/integrations/index.js +5 -0
  62. package/dist/integrations/index.js.map +1 -0
  63. package/dist/integrations/jira.d.ts +68 -0
  64. package/dist/integrations/jira.d.ts.map +1 -0
  65. package/dist/integrations/jira.js +288 -0
  66. package/dist/integrations/jira.js.map +1 -0
  67. package/dist/integrations/slack.d.ts +66 -0
  68. package/dist/integrations/slack.d.ts.map +1 -0
  69. package/dist/integrations/slack.js +192 -0
  70. package/dist/integrations/slack.js.map +1 -0
  71. package/dist/integrations/teams.d.ts +72 -0
  72. package/dist/integrations/teams.d.ts.map +1 -0
  73. package/dist/integrations/teams.js +197 -0
  74. package/dist/integrations/teams.js.map +1 -0
  75. package/dist/reporters/console.d.ts +83 -0
  76. package/dist/reporters/console.d.ts.map +1 -0
  77. package/dist/reporters/console.js +299 -0
  78. package/dist/reporters/console.js.map +1 -0
  79. package/dist/reporters/html.d.ts +29 -0
  80. package/dist/reporters/html.d.ts.map +1 -0
  81. package/dist/reporters/html.js +105 -0
  82. package/dist/reporters/html.js.map +1 -0
  83. package/dist/storage/results.d.ts +61 -0
  84. package/dist/storage/results.d.ts.map +1 -0
  85. package/dist/storage/results.js +111 -0
  86. package/dist/storage/results.js.map +1 -0
  87. package/dist/storage/sqlite.d.ts +70 -0
  88. package/dist/storage/sqlite.d.ts.map +1 -0
  89. package/dist/storage/sqlite.js +240 -0
  90. package/dist/storage/sqlite.js.map +1 -0
  91. package/dist/types/index.d.ts +1239 -0
  92. package/dist/types/index.d.ts.map +1 -0
  93. package/dist/types/index.js +105 -0
  94. package/dist/types/index.js.map +1 -0
  95. package/package.json +75 -0
  96. package/templates/crontab.hbs +24 -0
  97. package/templates/github-schedule.yml.hbs +153 -0
  98. package/templates/prompt.md.hbs +147 -0
  99. package/templates/report.html.hbs +423 -0
  100. package/templates/slack-message.json.hbs +93 -0
@@ -0,0 +1,122 @@
1
+ import chalk from 'chalk';
2
+ import { loadConfig, ConfigLoadError } from '../../core/config-loader.js';
3
+ import { printList } from '../../reporters/console.js';
4
+ export async function runList(resource, configPath, options = {}) {
5
+ try {
6
+ const result = loadConfig(configPath);
7
+ const config = result.config;
8
+ if (options.format === 'json') {
9
+ // Output as JSON
10
+ if (resource === 'apps') {
11
+ const apps = config.apps.map((app) => ({
12
+ name: app.name,
13
+ url: app.url,
14
+ environments: app.environments,
15
+ rulesCount: app.rules.length,
16
+ }));
17
+ console.log(JSON.stringify(apps, null, 2));
18
+ }
19
+ else if (resource === 'rules') {
20
+ const rules = config.apps.flatMap((app) => app.rules.map((rule) => ({
21
+ appName: app.name,
22
+ id: rule.id,
23
+ name: rule.name,
24
+ severity: rule.severity,
25
+ stepsCount: rule.steps.length,
26
+ validationsCount: rule.validations?.length || 0,
27
+ })));
28
+ console.log(JSON.stringify(rules, null, 2));
29
+ }
30
+ else {
31
+ // Output full config summary
32
+ const summary = {
33
+ organization: config.organization.name,
34
+ appsCount: config.apps.length,
35
+ totalRules: config.apps.reduce((sum, app) => sum + app.rules.length, 0),
36
+ apps: config.apps.map((app) => ({
37
+ name: app.name,
38
+ url: app.url,
39
+ rulesCount: app.rules.length,
40
+ rules: app.rules.map((rule) => ({
41
+ id: rule.id,
42
+ name: rule.name,
43
+ severity: rule.severity,
44
+ })),
45
+ })),
46
+ };
47
+ console.log(JSON.stringify(summary, null, 2));
48
+ }
49
+ return;
50
+ }
51
+ // Table/text output
52
+ if (resource === 'apps') {
53
+ printApps(config.apps);
54
+ }
55
+ else if (resource === 'rules') {
56
+ printRules(config.apps);
57
+ }
58
+ else {
59
+ // Print everything
60
+ printList(config.apps.map((app) => ({
61
+ name: app.name,
62
+ url: app.url,
63
+ rules: app.rules.map((rule) => ({
64
+ id: rule.id,
65
+ name: rule.name,
66
+ severity: rule.severity,
67
+ })),
68
+ })));
69
+ }
70
+ }
71
+ catch (error) {
72
+ if (error instanceof ConfigLoadError) {
73
+ console.log();
74
+ console.log(chalk.red(` Error: ${error.message}`));
75
+ console.log();
76
+ process.exit(1);
77
+ }
78
+ throw error;
79
+ }
80
+ }
81
+ function printApps(apps) {
82
+ console.log();
83
+ console.log(chalk.bold.cyan(' Apps'));
84
+ console.log();
85
+ for (const app of apps) {
86
+ console.log(chalk.bold(` ${app.name}`));
87
+ console.log(chalk.gray(` URL: ${app.url}`));
88
+ console.log(chalk.gray(` Rules: ${app.rules.length}`));
89
+ console.log();
90
+ }
91
+ }
92
+ function printRules(apps) {
93
+ console.log();
94
+ console.log(chalk.bold.cyan(' Rules'));
95
+ console.log();
96
+ for (const app of apps) {
97
+ console.log(chalk.bold(` ${app.name}`));
98
+ for (const rule of app.rules) {
99
+ const severityColor = getSeverityColor(rule.severity);
100
+ console.log(` ${chalk.gray('•')} ${rule.name}`);
101
+ console.log(chalk.gray(` ID: ${rule.id}`));
102
+ console.log(` Severity: ${severityColor(rule.severity.toUpperCase())}`);
103
+ console.log(chalk.gray(` Steps: ${rule.steps.length}`));
104
+ }
105
+ console.log();
106
+ }
107
+ }
108
+ function getSeverityColor(severity) {
109
+ switch (severity) {
110
+ case 'critical':
111
+ return chalk.red;
112
+ case 'high':
113
+ return chalk.yellow;
114
+ case 'medium':
115
+ return chalk.blue;
116
+ case 'low':
117
+ return chalk.gray;
118
+ default:
119
+ return chalk.white;
120
+ }
121
+ }
122
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/cli/commands/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { RunOptions } from '../../types/index.js';
2
+ export interface RunCommandOptions extends RunOptions {
3
+ config?: string;
4
+ report?: boolean;
5
+ reportDir?: string;
6
+ save?: boolean;
7
+ parallel?: boolean;
8
+ maxParallel?: number;
9
+ collectMetrics?: boolean;
10
+ }
11
+ export declare function runRun(options?: RunCommandOptions): Promise<void>;
12
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/run.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAA2B,MAAM,sBAAsB,CAAC;AAEhF,MAAM,WAAW,iBAAkB,SAAQ,UAAU;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AA6DD,wBAAsB,MAAM,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2G3E"}
@@ -0,0 +1,160 @@
1
+ import chalk from 'chalk';
2
+ import { loadConfig, ConfigLoadError } from '../../core/config-loader.js';
3
+ import { Executor } from '../../core/executor.js';
4
+ import { ConsoleReporter, printDryRunPreview } from '../../reporters/console.js';
5
+ import { generateHtmlReport } from '../../reporters/html.js';
6
+ import { saveRunResult } from '../../storage/results.js';
7
+ import { sendSlackNotification } from '../../integrations/slack.js';
8
+ import { sendEmailNotification } from '../../integrations/email.js';
9
+ import { sendTeamsNotification } from '../../integrations/teams.js';
10
+ import { processJiraIssues } from '../../integrations/jira.js';
11
+ /**
12
+ * Process integrations (notifications, Jira issues) after a test run.
13
+ */
14
+ async function processIntegrations(runResult, config, reportPath) {
15
+ // Send Slack notification
16
+ if (config.notifications?.slack) {
17
+ try {
18
+ await sendSlackNotification(runResult, config, reportPath);
19
+ console.log(chalk.gray(' Slack notification sent'));
20
+ }
21
+ catch (error) {
22
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
23
+ console.log(chalk.yellow(` Warning: Slack notification failed: ${errorMessage}`));
24
+ }
25
+ }
26
+ // Send email notification
27
+ if (config.notifications?.email) {
28
+ try {
29
+ await sendEmailNotification(runResult, config, reportPath);
30
+ console.log(chalk.gray(' Email notification sent'));
31
+ }
32
+ catch (error) {
33
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
34
+ console.log(chalk.yellow(` Warning: Email notification failed: ${errorMessage}`));
35
+ }
36
+ }
37
+ // Send Teams notification
38
+ if (config.notifications?.teams) {
39
+ try {
40
+ await sendTeamsNotification(runResult, config, reportPath);
41
+ console.log(chalk.gray(' Teams notification sent'));
42
+ }
43
+ catch (error) {
44
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
45
+ console.log(chalk.yellow(` Warning: Teams notification failed: ${errorMessage}`));
46
+ }
47
+ }
48
+ // Process Jira issues for failures
49
+ if (config.integrations?.jira && runResult.failed > 0) {
50
+ try {
51
+ const jiraResults = await processJiraIssues(runResult, config);
52
+ if (jiraResults.length > 0) {
53
+ console.log(chalk.gray(' Jira issues processed:'));
54
+ for (const result of jiraResults) {
55
+ const action = result.action === 'created' ? 'Created' : 'Updated';
56
+ console.log(chalk.gray(` ${action}: ${result.issueKey} (${result.testId})`));
57
+ }
58
+ }
59
+ }
60
+ catch (error) {
61
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
62
+ console.log(chalk.yellow(` Warning: Jira integration failed: ${errorMessage}`));
63
+ }
64
+ }
65
+ }
66
+ export async function runRun(options = {}) {
67
+ try {
68
+ // Load configuration
69
+ const result = loadConfig(options.config);
70
+ const config = result.config;
71
+ // Show warnings
72
+ if (result.warnings.length > 0) {
73
+ console.log();
74
+ console.log(chalk.yellow(' Warnings:'));
75
+ for (const warning of result.warnings) {
76
+ console.log(chalk.yellow(` - ${warning}`));
77
+ }
78
+ console.log();
79
+ }
80
+ // Create executor
81
+ const executor = new Executor(config, {
82
+ app: options.app,
83
+ rule: options.rule,
84
+ environment: options.environment,
85
+ dryRun: options.dryRun,
86
+ headed: options.headed,
87
+ verbose: options.verbose,
88
+ retries: options.retries,
89
+ timeout: options.timeout,
90
+ parallel: options.parallel,
91
+ maxParallel: options.maxParallel,
92
+ collectMetrics: options.collectMetrics,
93
+ });
94
+ // Handle dry-run mode
95
+ if (options.dryRun) {
96
+ const previews = executor.getExecutionPreview();
97
+ if (previews.length === 0) {
98
+ console.log();
99
+ console.log(chalk.yellow(' No tests match the specified filters'));
100
+ console.log();
101
+ return;
102
+ }
103
+ printDryRunPreview(previews, options.verbose);
104
+ return;
105
+ }
106
+ // Set up console reporter
107
+ const consoleReporter = new ConsoleReporter({ verbose: options.verbose });
108
+ const callbacks = consoleReporter.getCallbacks();
109
+ // Execute tests with callbacks
110
+ const runResult = await new Executor(config, {
111
+ ...options,
112
+ callbacks,
113
+ }).run();
114
+ // Save results to storage if enabled (default: true)
115
+ if (options.save !== false) {
116
+ try {
117
+ saveRunResult(runResult, config);
118
+ }
119
+ catch (error) {
120
+ // Non-fatal: log warning but continue
121
+ console.log(chalk.yellow(` Warning: Could not save results to storage`));
122
+ }
123
+ }
124
+ // Generate HTML report if requested
125
+ let reportPath;
126
+ if (options.report) {
127
+ try {
128
+ reportPath = generateHtmlReport(runResult, { outputDir: options.reportDir || './qualyx-reports' }, config.organization.name);
129
+ console.log(chalk.green(` HTML report generated: ${reportPath}`));
130
+ console.log();
131
+ }
132
+ catch (error) {
133
+ console.log(chalk.yellow(` Warning: Could not generate HTML report`));
134
+ }
135
+ }
136
+ // Send notifications and process integrations
137
+ await processIntegrations(runResult, config, reportPath);
138
+ // Exit with appropriate code
139
+ if (runResult.failed > 0) {
140
+ process.exit(1);
141
+ }
142
+ }
143
+ catch (error) {
144
+ if (error instanceof ConfigLoadError) {
145
+ console.log();
146
+ console.log(chalk.red(` Configuration Error: ${error.message}`));
147
+ console.log();
148
+ process.exit(1);
149
+ }
150
+ // Handle Claude not available
151
+ if (error instanceof Error && error.message.includes('Claude Code CLI')) {
152
+ console.log();
153
+ console.log(chalk.red(` ${error.message}`));
154
+ console.log();
155
+ process.exit(1);
156
+ }
157
+ throw error;
158
+ }
159
+ }
160
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/cli/commands/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface ScheduleCommandOptions {
2
+ config?: string;
3
+ output?: string;
4
+ format?: 'table' | 'json';
5
+ projectPath?: string;
6
+ }
7
+ /**
8
+ * List all scheduled rules.
9
+ */
10
+ export declare function runScheduleList(options?: ScheduleCommandOptions): Promise<void>;
11
+ /**
12
+ * Generate crontab entries for scheduled rules.
13
+ */
14
+ export declare function runScheduleCron(options?: ScheduleCommandOptions): Promise<void>;
15
+ /**
16
+ * Generate GitHub Actions workflow for scheduled rules.
17
+ */
18
+ export declare function runScheduleGithub(options?: ScheduleCommandOptions): Promise<void>;
19
+ //# sourceMappingURL=schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/schedule.ts"],"names":[],"mappings":"AA0DA,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CzF;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CzF;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAyD3F"}
@@ -0,0 +1,240 @@
1
+ import chalk from 'chalk';
2
+ import { readFileSync, writeFileSync, existsSync } from 'node:fs';
3
+ import { resolve, dirname } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import Handlebars from 'handlebars';
6
+ import { loadConfig, getScheduledRules, ConfigLoadError } from '../../core/config-loader.js';
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+ // Template paths
10
+ const crontabTemplatePath = resolve(__dirname, '../../../templates/crontab.hbs');
11
+ const githubTemplatePath = resolve(__dirname, '../../../templates/github-schedule.yml.hbs');
12
+ // Register Handlebars helpers
13
+ Handlebars.registerHelper('escapeShell', (str) => {
14
+ return str.replace(/'/g, "'\\''");
15
+ });
16
+ Handlebars.registerHelper('gt', (a, b) => {
17
+ return a > b;
18
+ });
19
+ Handlebars.registerHelper('formatCronDescription', (schedule) => {
20
+ // Basic cron expression descriptions
21
+ const parts = schedule.split(' ');
22
+ if (parts.length !== 5)
23
+ return schedule;
24
+ const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
25
+ // Common patterns
26
+ if (schedule === '* * * * *')
27
+ return 'every minute';
28
+ if (schedule === '0 * * * *')
29
+ return 'every hour';
30
+ if (schedule === '0 0 * * *')
31
+ return 'daily at midnight';
32
+ if (schedule === '0 0 * * 0')
33
+ return 'weekly on Sunday';
34
+ if (minute.includes('/')) {
35
+ const interval = minute.split('/')[1];
36
+ return `every ${interval} minutes`;
37
+ }
38
+ if (hour.includes('/')) {
39
+ const interval = hour.split('/')[1];
40
+ return `every ${interval} hours`;
41
+ }
42
+ if (dayOfMonth === '*' && month === '*') {
43
+ if (dayOfWeek !== '*') {
44
+ const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
45
+ const dayNum = parseInt(dayOfWeek, 10);
46
+ if (!isNaN(dayNum) && dayNum >= 0 && dayNum <= 6) {
47
+ return `weekly on ${days[dayNum]} at ${hour}:${minute.padStart(2, '0')}`;
48
+ }
49
+ }
50
+ return `daily at ${hour}:${minute.padStart(2, '0')}`;
51
+ }
52
+ return schedule;
53
+ });
54
+ /**
55
+ * List all scheduled rules.
56
+ */
57
+ export async function runScheduleList(options = {}) {
58
+ try {
59
+ const result = loadConfig(options.config);
60
+ const scheduledRules = getScheduledRules(result.config);
61
+ if (scheduledRules.length === 0) {
62
+ console.log();
63
+ console.log(chalk.yellow(' No scheduled rules found'));
64
+ console.log(chalk.gray(' Add a schedule field to rules in your qualyx.yml:'));
65
+ console.log(chalk.gray(' schedule: "0 7 * * *" # Daily at 7 AM'));
66
+ console.log();
67
+ return;
68
+ }
69
+ if (options.format === 'json') {
70
+ console.log(JSON.stringify(scheduledRules, null, 2));
71
+ return;
72
+ }
73
+ console.log();
74
+ console.log(chalk.bold.cyan(' Scheduled Rules'));
75
+ console.log();
76
+ for (const rule of scheduledRules) {
77
+ const severityBadge = getSeverityBadge(rule.severity);
78
+ console.log(` ${severityBadge} ${chalk.bold(rule.ruleName)}`);
79
+ console.log(chalk.gray(` App: ${rule.appName}`));
80
+ console.log(chalk.gray(` ID: ${rule.ruleId}`));
81
+ console.log(chalk.cyan(` Schedule: ${rule.schedule}`));
82
+ console.log();
83
+ }
84
+ console.log(chalk.gray(` Total: ${scheduledRules.length} scheduled rule(s)`));
85
+ console.log();
86
+ }
87
+ catch (error) {
88
+ if (error instanceof ConfigLoadError) {
89
+ console.log();
90
+ console.log(chalk.red(` Configuration Error: ${error.message}`));
91
+ console.log();
92
+ process.exit(1);
93
+ }
94
+ throw error;
95
+ }
96
+ }
97
+ /**
98
+ * Generate crontab entries for scheduled rules.
99
+ */
100
+ export async function runScheduleCron(options = {}) {
101
+ try {
102
+ const result = loadConfig(options.config);
103
+ const scheduledRules = getScheduledRules(result.config);
104
+ if (scheduledRules.length === 0) {
105
+ console.log();
106
+ console.log(chalk.yellow(' No scheduled rules found'));
107
+ console.log();
108
+ return;
109
+ }
110
+ const projectPath = options.projectPath || process.cwd();
111
+ const templateSource = loadTemplate(crontabTemplatePath);
112
+ const template = Handlebars.compile(templateSource);
113
+ const output = template({
114
+ rules: scheduledRules,
115
+ projectPath,
116
+ generatedAt: new Date().toISOString(),
117
+ });
118
+ if (options.output) {
119
+ writeFileSync(options.output, output, 'utf-8');
120
+ console.log();
121
+ console.log(chalk.green(` Crontab entries written to: ${options.output}`));
122
+ console.log(chalk.gray(` Install with: crontab ${options.output}`));
123
+ console.log();
124
+ }
125
+ else {
126
+ console.log();
127
+ console.log(chalk.bold.cyan(' Generated Crontab Entries'));
128
+ console.log();
129
+ console.log(output);
130
+ }
131
+ }
132
+ catch (error) {
133
+ if (error instanceof ConfigLoadError) {
134
+ console.log();
135
+ console.log(chalk.red(` Configuration Error: ${error.message}`));
136
+ console.log();
137
+ process.exit(1);
138
+ }
139
+ throw error;
140
+ }
141
+ }
142
+ /**
143
+ * Generate GitHub Actions workflow for scheduled rules.
144
+ */
145
+ export async function runScheduleGithub(options = {}) {
146
+ try {
147
+ const result = loadConfig(options.config);
148
+ const scheduledRules = getScheduledRules(result.config);
149
+ if (scheduledRules.length === 0) {
150
+ console.log();
151
+ console.log(chalk.yellow(' No scheduled rules found'));
152
+ console.log();
153
+ return;
154
+ }
155
+ const templateSource = loadTemplate(githubTemplatePath);
156
+ const template = Handlebars.compile(templateSource);
157
+ // Group rules by schedule for efficient workflow triggers
158
+ const scheduleGroups = groupBySchedule(scheduledRules);
159
+ const output = template({
160
+ rules: scheduledRules,
161
+ scheduleGroups,
162
+ generatedAt: new Date().toISOString(),
163
+ organizationName: result.config.organization.name,
164
+ });
165
+ const defaultOutputPath = '.github/workflows/qualyx-scheduled.yml';
166
+ if (options.output) {
167
+ // Ensure directory exists
168
+ const outputDir = dirname(options.output);
169
+ if (outputDir && outputDir !== '.' && !existsSync(outputDir)) {
170
+ const fs = await import('node:fs');
171
+ fs.mkdirSync(outputDir, { recursive: true });
172
+ }
173
+ writeFileSync(options.output, output, 'utf-8');
174
+ console.log();
175
+ console.log(chalk.green(` GitHub Actions workflow written to: ${options.output}`));
176
+ console.log(chalk.gray(' Commit and push to enable scheduled runs.'));
177
+ console.log();
178
+ }
179
+ else {
180
+ console.log();
181
+ console.log(chalk.bold.cyan(' Generated GitHub Actions Workflow'));
182
+ console.log();
183
+ console.log(output);
184
+ console.log();
185
+ console.log(chalk.gray(` To save: qualyx schedule github --output ${defaultOutputPath}`));
186
+ console.log();
187
+ }
188
+ }
189
+ catch (error) {
190
+ if (error instanceof ConfigLoadError) {
191
+ console.log();
192
+ console.log(chalk.red(` Configuration Error: ${error.message}`));
193
+ console.log();
194
+ process.exit(1);
195
+ }
196
+ throw error;
197
+ }
198
+ }
199
+ /**
200
+ * Load a Handlebars template file.
201
+ */
202
+ function loadTemplate(templatePath) {
203
+ if (!existsSync(templatePath)) {
204
+ throw new Error(`Template not found: ${templatePath}`);
205
+ }
206
+ return readFileSync(templatePath, 'utf-8');
207
+ }
208
+ /**
209
+ * Get colored severity badge.
210
+ */
211
+ function getSeverityBadge(severity) {
212
+ switch (severity) {
213
+ case 'critical':
214
+ return chalk.bgRed.white(' CRITICAL ');
215
+ case 'high':
216
+ return chalk.bgYellow.black(' HIGH ');
217
+ case 'medium':
218
+ return chalk.bgBlue.white(' MEDIUM ');
219
+ case 'low':
220
+ return chalk.bgGray.white(' LOW ');
221
+ default:
222
+ return chalk.bgGray.white(` ${severity.toUpperCase()} `);
223
+ }
224
+ }
225
+ /**
226
+ * Group scheduled rules by their cron schedule.
227
+ */
228
+ function groupBySchedule(rules) {
229
+ const groups = new Map();
230
+ for (const rule of rules) {
231
+ const existing = groups.get(rule.schedule) || [];
232
+ existing.push(rule);
233
+ groups.set(rule.schedule, existing);
234
+ }
235
+ return Array.from(groups.entries()).map(([schedule, rules]) => ({
236
+ schedule,
237
+ rules,
238
+ }));
239
+ }
240
+ //# sourceMappingURL=schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../../src/cli/commands/schedule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ValidateOptions } from '../../types/index.js';
2
+ export declare function runValidate(configPath?: string, options?: ValidateOptions): Promise<void>;
3
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/validate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,wBAAsB,WAAW,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDnG"}
@@ -0,0 +1,47 @@
1
+ import chalk from 'chalk';
2
+ import { loadConfig, ConfigLoadError } from '../../core/config-loader.js';
3
+ import { printValidationResult } from '../../reporters/console.js';
4
+ export async function runValidate(configPath, options = {}) {
5
+ try {
6
+ const result = loadConfig(configPath);
7
+ // Gather statistics
8
+ const stats = {
9
+ apps: result.config.apps.length,
10
+ rules: result.config.apps.reduce((sum, app) => sum + app.rules.length, 0),
11
+ criticalRules: result.config.apps
12
+ .flatMap((app) => app.rules)
13
+ .filter((rule) => rule.severity === 'critical').length,
14
+ };
15
+ printValidationResult(result.filePath, true, [], result.warnings);
16
+ console.log(chalk.gray(' Configuration Summary:'));
17
+ console.log(chalk.gray(` Organization: ${result.config.organization.name}`));
18
+ console.log(chalk.gray(` Apps: ${stats.apps}`));
19
+ console.log(chalk.gray(` Total Rules: ${stats.rules}`));
20
+ console.log(chalk.gray(` Critical Rules: ${stats.criticalRules}`));
21
+ if (result.config.organization.defaults) {
22
+ console.log(chalk.gray(' Defaults:'));
23
+ console.log(chalk.gray(` Timeout: ${result.config.organization.defaults.timeout}ms`));
24
+ console.log(chalk.gray(` Retries: ${result.config.organization.defaults.retries}`));
25
+ }
26
+ console.log();
27
+ // In strict mode, warnings are treated as errors
28
+ if (options.strict && result.warnings.length > 0) {
29
+ console.log(chalk.red(' Strict mode: warnings treated as errors'));
30
+ process.exit(1);
31
+ }
32
+ }
33
+ catch (error) {
34
+ if (error instanceof ConfigLoadError) {
35
+ const errors = error.validationErrors
36
+ ? error.validationErrors.errors.map((e) => {
37
+ const path = e.path.length > 0 ? ` at "${e.path.join('.')}"` : '';
38
+ return `${e.message}${path}`;
39
+ })
40
+ : [error.message];
41
+ printValidationResult(error.filePath || 'unknown', false, errors, []);
42
+ process.exit(1);
43
+ }
44
+ throw error;
45
+ }
46
+ }
47
+ //# sourceMappingURL=validate.js.map