@vertaaux/cli 0.2.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.
- package/README.md +345 -0
- package/dist/auth/ci-token.d.ts +49 -0
- package/dist/auth/ci-token.d.ts.map +1 -0
- package/dist/auth/ci-token.js +83 -0
- package/dist/auth/device-flow.d.ts +66 -0
- package/dist/auth/device-flow.d.ts.map +1 -0
- package/dist/auth/device-flow.js +156 -0
- package/dist/auth/token-store.d.ts +53 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +78 -0
- package/dist/baseline/diff.d.ts +57 -0
- package/dist/baseline/diff.d.ts.map +1 -0
- package/dist/baseline/diff.js +152 -0
- package/dist/baseline/hash.d.ts +54 -0
- package/dist/baseline/hash.d.ts.map +1 -0
- package/dist/baseline/hash.js +66 -0
- package/dist/baseline/manager.d.ts +89 -0
- package/dist/baseline/manager.d.ts.map +1 -0
- package/dist/baseline/manager.js +157 -0
- package/dist/cache/index.d.ts +8 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +7 -0
- package/dist/cache/route-cache.d.ts +119 -0
- package/dist/cache/route-cache.d.ts.map +1 -0
- package/dist/cache/route-cache.js +213 -0
- package/dist/ci/changed-routes.d.ts +95 -0
- package/dist/ci/changed-routes.d.ts.map +1 -0
- package/dist/ci/changed-routes.js +304 -0
- package/dist/ci/github-api.d.ts +68 -0
- package/dist/ci/github-api.d.ts.map +1 -0
- package/dist/ci/github-api.js +138 -0
- package/dist/ci/gitlab-api.d.ts +75 -0
- package/dist/ci/gitlab-api.d.ts.map +1 -0
- package/dist/ci/gitlab-api.js +180 -0
- package/dist/ci/index.d.ts +6 -0
- package/dist/ci/index.d.ts.map +1 -0
- package/dist/ci/index.js +4 -0
- package/dist/commands/audit.d.ts +58 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +862 -0
- package/dist/commands/baseline.d.ts +22 -0
- package/dist/commands/baseline.d.ts.map +1 -0
- package/dist/commands/baseline.js +210 -0
- package/dist/commands/comment.d.ts +14 -0
- package/dist/commands/comment.d.ts.map +1 -0
- package/dist/commands/comment.js +363 -0
- package/dist/commands/diff.d.ts +24 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +196 -0
- package/dist/commands/doctor.d.ts +58 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +338 -0
- package/dist/commands/download.d.ts +12 -0
- package/dist/commands/download.d.ts.map +1 -0
- package/dist/commands/download.js +183 -0
- package/dist/commands/explain.d.ts +62 -0
- package/dist/commands/explain.d.ts.map +1 -0
- package/dist/commands/explain.js +302 -0
- package/dist/commands/init.d.ts +12 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +212 -0
- package/dist/commands/login.d.ts +14 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +222 -0
- package/dist/commands/policy.d.ts +13 -0
- package/dist/commands/policy.d.ts.map +1 -0
- package/dist/commands/policy.js +347 -0
- package/dist/commands/upload.d.ts +12 -0
- package/dist/commands/upload.d.ts.map +1 -0
- package/dist/commands/upload.js +158 -0
- package/dist/config/defaults.d.ts +21 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +49 -0
- package/dist/config/loader.d.ts +66 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +167 -0
- package/dist/config/schema.d.ts +55 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +6 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1090 -0
- package/dist/interactive/fix-wizard.d.ts +44 -0
- package/dist/interactive/fix-wizard.d.ts.map +1 -0
- package/dist/interactive/fix-wizard.js +286 -0
- package/dist/interactive/init-wizard.d.ts +32 -0
- package/dist/interactive/init-wizard.d.ts.map +1 -0
- package/dist/interactive/init-wizard.js +193 -0
- package/dist/interactive/prompts.d.ts +62 -0
- package/dist/interactive/prompts.d.ts.map +1 -0
- package/dist/interactive/prompts.js +78 -0
- package/dist/monorepo/detector.d.ts +70 -0
- package/dist/monorepo/detector.d.ts.map +1 -0
- package/dist/monorepo/detector.js +278 -0
- package/dist/monorepo/index.d.ts +9 -0
- package/dist/monorepo/index.d.ts.map +1 -0
- package/dist/monorepo/index.js +8 -0
- package/dist/monorepo/workspace.d.ts +142 -0
- package/dist/monorepo/workspace.d.ts.map +1 -0
- package/dist/monorepo/workspace.js +171 -0
- package/dist/output/envelope.d.ts +21 -0
- package/dist/output/envelope.d.ts.map +1 -0
- package/dist/output/envelope.js +27 -0
- package/dist/output/factory.d.ts +73 -0
- package/dist/output/factory.d.ts.map +1 -0
- package/dist/output/factory.js +60 -0
- package/dist/output/formats.d.ts +11 -0
- package/dist/output/formats.d.ts.map +1 -0
- package/dist/output/formats.js +41 -0
- package/dist/output/html.d.ts +45 -0
- package/dist/output/html.d.ts.map +1 -0
- package/dist/output/html.js +607 -0
- package/dist/output/human.d.ts +41 -0
- package/dist/output/human.d.ts.map +1 -0
- package/dist/output/human.js +274 -0
- package/dist/output/json.d.ts +42 -0
- package/dist/output/json.d.ts.map +1 -0
- package/dist/output/json.js +37 -0
- package/dist/output/junit.d.ts +56 -0
- package/dist/output/junit.d.ts.map +1 -0
- package/dist/output/junit.js +135 -0
- package/dist/output/markdown.d.ts +77 -0
- package/dist/output/markdown.d.ts.map +1 -0
- package/dist/output/markdown.js +411 -0
- package/dist/output/sarif.d.ts +160 -0
- package/dist/output/sarif.d.ts.map +1 -0
- package/dist/output/sarif.js +207 -0
- package/dist/policy/evaluator.d.ts +111 -0
- package/dist/policy/evaluator.d.ts.map +1 -0
- package/dist/policy/evaluator.js +362 -0
- package/dist/policy/index.d.ts +15 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +11 -0
- package/dist/policy/loader.d.ts +97 -0
- package/dist/policy/loader.d.ts.map +1 -0
- package/dist/policy/loader.js +281 -0
- package/dist/policy/schema.d.ts +297 -0
- package/dist/policy/schema.d.ts.map +1 -0
- package/dist/policy/schema.js +230 -0
- package/dist/quality-gate/evaluator.d.ts +58 -0
- package/dist/quality-gate/evaluator.d.ts.map +1 -0
- package/dist/quality-gate/evaluator.js +274 -0
- package/dist/quality-gate/index.d.ts +10 -0
- package/dist/quality-gate/index.d.ts.map +1 -0
- package/dist/quality-gate/index.js +7 -0
- package/dist/quality-gate/types.d.ts +103 -0
- package/dist/quality-gate/types.d.ts.map +1 -0
- package/dist/quality-gate/types.js +23 -0
- package/dist/templates/azure-devops.d.ts +25 -0
- package/dist/templates/azure-devops.d.ts.map +1 -0
- package/dist/templates/azure-devops.js +109 -0
- package/dist/templates/circleci.d.ts +28 -0
- package/dist/templates/circleci.d.ts.map +1 -0
- package/dist/templates/circleci.js +86 -0
- package/dist/templates/github-actions.d.ts +81 -0
- package/dist/templates/github-actions.d.ts.map +1 -0
- package/dist/templates/github-actions.js +393 -0
- package/dist/templates/gitlab-ci.d.ts +26 -0
- package/dist/templates/gitlab-ci.d.ts.map +1 -0
- package/dist/templates/gitlab-ci.js +70 -0
- package/dist/templates/index.d.ts +72 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +112 -0
- package/dist/templates/jenkins.d.ts +26 -0
- package/dist/templates/jenkins.d.ts.map +1 -0
- package/dist/templates/jenkins.js +110 -0
- package/dist/ui/banner.d.ts +31 -0
- package/dist/ui/banner.d.ts.map +1 -0
- package/dist/ui/banner.js +84 -0
- package/dist/ui/diagnostics.d.ts +39 -0
- package/dist/ui/diagnostics.d.ts.map +1 -0
- package/dist/ui/diagnostics.js +153 -0
- package/dist/ui/spinner.d.ts +61 -0
- package/dist/ui/spinner.d.ts.map +1 -0
- package/dist/ui/spinner.js +101 -0
- package/dist/ui/table.d.ts +63 -0
- package/dist/ui/table.d.ts.map +1 -0
- package/dist/ui/table.js +236 -0
- package/dist/utils/client.d.ts +82 -0
- package/dist/utils/client.d.ts.map +1 -0
- package/dist/utils/client.js +128 -0
- package/dist/utils/detect-env.d.ts +59 -0
- package/dist/utils/detect-env.d.ts.map +1 -0
- package/dist/utils/detect-env.js +115 -0
- package/dist/utils/exit-codes.d.ts +47 -0
- package/dist/utils/exit-codes.d.ts.map +1 -0
- package/dist/utils/exit-codes.js +61 -0
- package/dist/utils/logger.d.ts +87 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +185 -0
- package/dist/utils/sanitize.d.ts +36 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +64 -0
- package/dist/utils/validators.d.ts +41 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +123 -0
- package/package.json +63 -0
- package/schemas/vertaaux.config.schema.json +103 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic exit codes for CLI commands (CLI-12).
|
|
3
|
+
*
|
|
4
|
+
* CI tools depend on exit codes for gating decisions.
|
|
5
|
+
* These codes allow distinguishing between:
|
|
6
|
+
* - Success (no issues)
|
|
7
|
+
* - Issues found (but not necessarily a failure)
|
|
8
|
+
* - Runtime errors
|
|
9
|
+
* - Threshold/score failures
|
|
10
|
+
*/
|
|
11
|
+
export const ExitCode = {
|
|
12
|
+
/** Audit passed, no issues above threshold */
|
|
13
|
+
SUCCESS: 0,
|
|
14
|
+
/** Issues found at or above specified severity */
|
|
15
|
+
ISSUES_FOUND: 1,
|
|
16
|
+
/** Runtime error, invalid input, network failure */
|
|
17
|
+
ERROR: 2,
|
|
18
|
+
/** Score below threshold */
|
|
19
|
+
THRESHOLD_BREACH: 3,
|
|
20
|
+
};
|
|
21
|
+
/** Severity ranking for comparison */
|
|
22
|
+
const SEVERITY_RANK = {
|
|
23
|
+
error: 3,
|
|
24
|
+
critical: 3,
|
|
25
|
+
warning: 2,
|
|
26
|
+
serious: 2,
|
|
27
|
+
info: 1,
|
|
28
|
+
minor: 1,
|
|
29
|
+
moderate: 1,
|
|
30
|
+
};
|
|
31
|
+
function severityRank(severity) {
|
|
32
|
+
return SEVERITY_RANK[severity.toLowerCase()] ?? 0;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Determine the appropriate exit code based on audit results and options.
|
|
36
|
+
*
|
|
37
|
+
* @param result - The audit result
|
|
38
|
+
* @param options - Exit code determination options
|
|
39
|
+
* @returns The semantic exit code
|
|
40
|
+
*/
|
|
41
|
+
export function determineExitCode(result, options = {}) {
|
|
42
|
+
// Runtime errors take precedence
|
|
43
|
+
if (result.error) {
|
|
44
|
+
return ExitCode.ERROR;
|
|
45
|
+
}
|
|
46
|
+
// Check threshold breach
|
|
47
|
+
if (options.threshold !== undefined &&
|
|
48
|
+
result.scores?.overall !== undefined &&
|
|
49
|
+
result.scores.overall < options.threshold) {
|
|
50
|
+
return ExitCode.THRESHOLD_BREACH;
|
|
51
|
+
}
|
|
52
|
+
// Check severity-based failure
|
|
53
|
+
if (options.failOn && result.issues) {
|
|
54
|
+
const hasSevereIssues = result.issues.some((issue) => issue.severity &&
|
|
55
|
+
severityRank(issue.severity) >= severityRank(options.failOn));
|
|
56
|
+
if (hasSevereIssues) {
|
|
57
|
+
return ExitCode.ISSUES_FOUND;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return ExitCode.SUCCESS;
|
|
61
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logging for CI environments.
|
|
3
|
+
*
|
|
4
|
+
* Provides both human-readable and JSON log output modes,
|
|
5
|
+
* with automatic CI environment detection.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Log levels in order of severity.
|
|
9
|
+
*/
|
|
10
|
+
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
11
|
+
/**
|
|
12
|
+
* Structured log entry.
|
|
13
|
+
*/
|
|
14
|
+
export interface LogEntry {
|
|
15
|
+
/** ISO 8601 timestamp */
|
|
16
|
+
timestamp: string;
|
|
17
|
+
/** Log level */
|
|
18
|
+
level: LogLevel;
|
|
19
|
+
/** Log message */
|
|
20
|
+
message: string;
|
|
21
|
+
/** Additional context */
|
|
22
|
+
context?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Logger configuration options.
|
|
26
|
+
*/
|
|
27
|
+
export interface LoggerOptions {
|
|
28
|
+
/** Minimum log level to output */
|
|
29
|
+
level: LogLevel;
|
|
30
|
+
/** Output JSON format (for CI parsing) */
|
|
31
|
+
json: boolean;
|
|
32
|
+
/** Include timestamps in output */
|
|
33
|
+
timestamps: boolean;
|
|
34
|
+
/** Automatically include context in all log calls */
|
|
35
|
+
autoContext: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Logger interface.
|
|
39
|
+
*/
|
|
40
|
+
export interface Logger {
|
|
41
|
+
/** Log debug message */
|
|
42
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
43
|
+
/** Log info message */
|
|
44
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
45
|
+
/** Log warning message */
|
|
46
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
47
|
+
/** Log error message */
|
|
48
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
49
|
+
/** Create child logger with additional context */
|
|
50
|
+
child(context: Record<string, unknown>): Logger;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create a structured logger.
|
|
54
|
+
*
|
|
55
|
+
* @param options - Logger configuration options
|
|
56
|
+
* @returns Logger instance
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* // Basic usage
|
|
61
|
+
* const logger = createLogger({ level: 'debug' });
|
|
62
|
+
* logger.info('Starting audit', { url: 'https://example.com' });
|
|
63
|
+
*
|
|
64
|
+
* // CI usage (JSON output)
|
|
65
|
+
* const ciLogger = createLogger({ json: true });
|
|
66
|
+
* ciLogger.info('Route cached', { route: '/about', contentHash: 'abc123' });
|
|
67
|
+
* // Output: {"timestamp":"2026-01-28T12:00:00Z","level":"info","message":"Route cached","context":{"route":"/about","contentHash":"abc123"}}
|
|
68
|
+
*
|
|
69
|
+
* // Child logger with bound context
|
|
70
|
+
* const wsLogger = logger.child({ workspace: 'web-app' });
|
|
71
|
+
* wsLogger.info('Auditing workspace');
|
|
72
|
+
* // Output includes workspace in context
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare function createLogger(options?: Partial<LoggerOptions>): Logger;
|
|
76
|
+
/**
|
|
77
|
+
* Get a logger with CI-appropriate defaults.
|
|
78
|
+
*
|
|
79
|
+
* - JSON output in CI environments
|
|
80
|
+
* - Human-readable output in local development
|
|
81
|
+
* - Respects VERTAAUX_LOG_LEVEL and VERTAAUX_LOG_JSON env vars
|
|
82
|
+
*
|
|
83
|
+
* @returns Logger instance
|
|
84
|
+
*/
|
|
85
|
+
export declare function getCILogger(): Logger;
|
|
86
|
+
export declare const logger: Logger;
|
|
87
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAY3D;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB;IAChB,KAAK,EAAE,QAAQ,CAAC;IAChB,kBAAkB;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,kCAAkC;IAClC,KAAK,EAAE,QAAQ,CAAC;IAChB,0CAA0C;IAC1C,IAAI,EAAE,OAAO,CAAC;IACd,mCAAmC;IACnC,UAAU,EAAE,OAAO,CAAC;IACpB,qDAAqD;IACrD,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,wBAAwB;IACxB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAChE,uBAAuB;IACvB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/D,0BAA0B;IAC1B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC/D,wBAAwB;IACxB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAChE,kDAAkD;IAClD,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;CACjD;AAuKD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,MAAM,CAEzE;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAGD,eAAO,MAAM,MAAM,QAAiB,CAAC"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured logging for CI environments.
|
|
3
|
+
*
|
|
4
|
+
* Provides both human-readable and JSON log output modes,
|
|
5
|
+
* with automatic CI environment detection.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Numeric values for log level comparison.
|
|
9
|
+
*/
|
|
10
|
+
const LOG_LEVEL_VALUES = {
|
|
11
|
+
debug: 0,
|
|
12
|
+
info: 1,
|
|
13
|
+
warn: 2,
|
|
14
|
+
error: 3,
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Default logger options.
|
|
18
|
+
*/
|
|
19
|
+
const DEFAULT_OPTIONS = {
|
|
20
|
+
level: "info",
|
|
21
|
+
json: false,
|
|
22
|
+
timestamps: true,
|
|
23
|
+
autoContext: false,
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Detect if running in CI environment.
|
|
27
|
+
*/
|
|
28
|
+
function isCI() {
|
|
29
|
+
return !!(process.env.CI ||
|
|
30
|
+
process.env.GITHUB_ACTIONS ||
|
|
31
|
+
process.env.GITLAB_CI ||
|
|
32
|
+
process.env.CIRCLECI ||
|
|
33
|
+
process.env.JENKINS_URL ||
|
|
34
|
+
process.env.BUILDKITE ||
|
|
35
|
+
process.env.TRAVIS);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get default options based on environment.
|
|
39
|
+
*/
|
|
40
|
+
function getDefaultOptions() {
|
|
41
|
+
const options = { ...DEFAULT_OPTIONS };
|
|
42
|
+
// In CI, prefer JSON output
|
|
43
|
+
if (isCI()) {
|
|
44
|
+
options.json = true;
|
|
45
|
+
}
|
|
46
|
+
// Check environment variables
|
|
47
|
+
if (process.env.VERTAAUX_LOG_LEVEL) {
|
|
48
|
+
const level = process.env.VERTAAUX_LOG_LEVEL.toLowerCase();
|
|
49
|
+
if (LOG_LEVEL_VALUES[level] !== undefined) {
|
|
50
|
+
options.level = level;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (process.env.VERTAAUX_LOG_JSON === "true") {
|
|
54
|
+
options.json = true;
|
|
55
|
+
}
|
|
56
|
+
else if (process.env.VERTAAUX_LOG_JSON === "false") {
|
|
57
|
+
options.json = false;
|
|
58
|
+
}
|
|
59
|
+
return options;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Format log entry for JSON output.
|
|
63
|
+
*/
|
|
64
|
+
function formatJson(entry) {
|
|
65
|
+
return JSON.stringify(entry);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Format log entry for human-readable output.
|
|
69
|
+
*/
|
|
70
|
+
function formatHuman(entry, showTimestamp) {
|
|
71
|
+
const parts = [];
|
|
72
|
+
if (showTimestamp) {
|
|
73
|
+
// Use short timestamp format
|
|
74
|
+
const time = new Date(entry.timestamp).toISOString().split("T")[1].slice(0, 8);
|
|
75
|
+
parts.push(`[${time}]`);
|
|
76
|
+
}
|
|
77
|
+
// Level with color
|
|
78
|
+
const levelStr = entry.level.toUpperCase().padEnd(5);
|
|
79
|
+
parts.push(levelStr);
|
|
80
|
+
// Message
|
|
81
|
+
parts.push(entry.message);
|
|
82
|
+
// Context (if present)
|
|
83
|
+
if (entry.context && Object.keys(entry.context).length > 0) {
|
|
84
|
+
const contextStr = Object.entries(entry.context)
|
|
85
|
+
.map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`)
|
|
86
|
+
.join(" ");
|
|
87
|
+
parts.push(`(${contextStr})`);
|
|
88
|
+
}
|
|
89
|
+
return parts.join(" ");
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Internal logger implementation.
|
|
93
|
+
*/
|
|
94
|
+
class LoggerImpl {
|
|
95
|
+
options;
|
|
96
|
+
baseContext;
|
|
97
|
+
constructor(options = {}, baseContext = {}) {
|
|
98
|
+
this.options = { ...getDefaultOptions(), ...options };
|
|
99
|
+
this.baseContext = baseContext;
|
|
100
|
+
}
|
|
101
|
+
log(level, message, context) {
|
|
102
|
+
// Check if this level should be logged
|
|
103
|
+
if (LOG_LEVEL_VALUES[level] < LOG_LEVEL_VALUES[this.options.level]) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const entry = {
|
|
107
|
+
timestamp: new Date().toISOString(),
|
|
108
|
+
level,
|
|
109
|
+
message,
|
|
110
|
+
};
|
|
111
|
+
// Merge contexts
|
|
112
|
+
const mergedContext = {
|
|
113
|
+
...(this.options.autoContext ? this.baseContext : {}),
|
|
114
|
+
...this.baseContext,
|
|
115
|
+
...context,
|
|
116
|
+
};
|
|
117
|
+
if (Object.keys(mergedContext).length > 0) {
|
|
118
|
+
entry.context = mergedContext;
|
|
119
|
+
}
|
|
120
|
+
// Format and output
|
|
121
|
+
const output = this.options.json
|
|
122
|
+
? formatJson(entry)
|
|
123
|
+
: formatHuman(entry, this.options.timestamps);
|
|
124
|
+
// All logger output goes to stderr -- logs are diagnostics, never primary command output
|
|
125
|
+
process.stderr.write(output + "\n");
|
|
126
|
+
}
|
|
127
|
+
debug(message, context) {
|
|
128
|
+
this.log("debug", message, context);
|
|
129
|
+
}
|
|
130
|
+
info(message, context) {
|
|
131
|
+
this.log("info", message, context);
|
|
132
|
+
}
|
|
133
|
+
warn(message, context) {
|
|
134
|
+
this.log("warn", message, context);
|
|
135
|
+
}
|
|
136
|
+
error(message, context) {
|
|
137
|
+
this.log("error", message, context);
|
|
138
|
+
}
|
|
139
|
+
child(context) {
|
|
140
|
+
return new LoggerImpl(this.options, {
|
|
141
|
+
...this.baseContext,
|
|
142
|
+
...context,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Create a structured logger.
|
|
148
|
+
*
|
|
149
|
+
* @param options - Logger configuration options
|
|
150
|
+
* @returns Logger instance
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* // Basic usage
|
|
155
|
+
* const logger = createLogger({ level: 'debug' });
|
|
156
|
+
* logger.info('Starting audit', { url: 'https://example.com' });
|
|
157
|
+
*
|
|
158
|
+
* // CI usage (JSON output)
|
|
159
|
+
* const ciLogger = createLogger({ json: true });
|
|
160
|
+
* ciLogger.info('Route cached', { route: '/about', contentHash: 'abc123' });
|
|
161
|
+
* // Output: {"timestamp":"2026-01-28T12:00:00Z","level":"info","message":"Route cached","context":{"route":"/about","contentHash":"abc123"}}
|
|
162
|
+
*
|
|
163
|
+
* // Child logger with bound context
|
|
164
|
+
* const wsLogger = logger.child({ workspace: 'web-app' });
|
|
165
|
+
* wsLogger.info('Auditing workspace');
|
|
166
|
+
* // Output includes workspace in context
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
export function createLogger(options = {}) {
|
|
170
|
+
return new LoggerImpl(options);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get a logger with CI-appropriate defaults.
|
|
174
|
+
*
|
|
175
|
+
* - JSON output in CI environments
|
|
176
|
+
* - Human-readable output in local development
|
|
177
|
+
* - Respects VERTAAUX_LOG_LEVEL and VERTAAUX_LOG_JSON env vars
|
|
178
|
+
*
|
|
179
|
+
* @returns Logger instance
|
|
180
|
+
*/
|
|
181
|
+
export function getCILogger() {
|
|
182
|
+
return createLogger();
|
|
183
|
+
}
|
|
184
|
+
// Export a default logger instance for convenience
|
|
185
|
+
export const logger = createLogger();
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized input validation for the VertaaUX CLI.
|
|
3
|
+
*
|
|
4
|
+
* Provides validation functions to prevent:
|
|
5
|
+
* - Command injection via branch names (SEC-01)
|
|
6
|
+
* - Path traversal via artifact filenames (SEC-02)
|
|
7
|
+
*
|
|
8
|
+
* These are pure validation functions -- they throw on invalid input
|
|
9
|
+
* and return the validated value on success. Callers decide how to
|
|
10
|
+
* handle errors (exit codes, logging, etc.).
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Validate a git branch name against an allowlist of safe characters.
|
|
14
|
+
*
|
|
15
|
+
* Rejects branch names containing shell metacharacters, backticks,
|
|
16
|
+
* semicolons, pipes, dollar signs, or other characters that could
|
|
17
|
+
* enable command injection when interpolated into shell commands.
|
|
18
|
+
*
|
|
19
|
+
* @param branch - The branch name to validate
|
|
20
|
+
* @returns The branch name unchanged if valid
|
|
21
|
+
* @throws Error if the branch name contains disallowed characters, is empty, or exceeds 255 characters
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateBranchName(branch: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Assert that a candidate path resolves within the given root directory.
|
|
26
|
+
*
|
|
27
|
+
* Prevents path traversal attacks where filenames like "../../../etc/passwd"
|
|
28
|
+
* could write to arbitrary filesystem locations.
|
|
29
|
+
*
|
|
30
|
+
* @param candidatePath - The relative path to check (e.g., an artifact filename from an API response)
|
|
31
|
+
* @param rootDir - The root directory that the path must stay within
|
|
32
|
+
* @returns The resolved absolute path if it is contained within rootDir
|
|
33
|
+
* @throws Error if the resolved path escapes the root directory
|
|
34
|
+
*/
|
|
35
|
+
export declare function assertPathContainment(candidatePath: string, rootDir: string): string;
|
|
36
|
+
//# sourceMappingURL=sanitize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/utils/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgBH;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAoBzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAWpF"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized input validation for the VertaaUX CLI.
|
|
3
|
+
*
|
|
4
|
+
* Provides validation functions to prevent:
|
|
5
|
+
* - Command injection via branch names (SEC-01)
|
|
6
|
+
* - Path traversal via artifact filenames (SEC-02)
|
|
7
|
+
*
|
|
8
|
+
* These are pure validation functions -- they throw on invalid input
|
|
9
|
+
* and return the validated value on success. Callers decide how to
|
|
10
|
+
* handle errors (exit codes, logging, etc.).
|
|
11
|
+
*/
|
|
12
|
+
import path from "path";
|
|
13
|
+
/**
|
|
14
|
+
* Allowlist regex for valid git branch names.
|
|
15
|
+
*
|
|
16
|
+
* Permits: letters, digits, dots, underscores, hyphens, forward slashes.
|
|
17
|
+
* This covers standard branch naming conventions like:
|
|
18
|
+
* main, feature/login, release/v1.2.3, hotfix-123, my_branch
|
|
19
|
+
*/
|
|
20
|
+
const BRANCH_NAME_REGEX = /^[a-zA-Z0-9._\/-]+$/;
|
|
21
|
+
/** Maximum allowed branch name length. */
|
|
22
|
+
const MAX_BRANCH_NAME_LENGTH = 255;
|
|
23
|
+
/**
|
|
24
|
+
* Validate a git branch name against an allowlist of safe characters.
|
|
25
|
+
*
|
|
26
|
+
* Rejects branch names containing shell metacharacters, backticks,
|
|
27
|
+
* semicolons, pipes, dollar signs, or other characters that could
|
|
28
|
+
* enable command injection when interpolated into shell commands.
|
|
29
|
+
*
|
|
30
|
+
* @param branch - The branch name to validate
|
|
31
|
+
* @returns The branch name unchanged if valid
|
|
32
|
+
* @throws Error if the branch name contains disallowed characters, is empty, or exceeds 255 characters
|
|
33
|
+
*/
|
|
34
|
+
export function validateBranchName(branch) {
|
|
35
|
+
if (!branch || branch.length === 0) {
|
|
36
|
+
throw new Error('Invalid branch name: "". Branch names may only contain letters, digits, dots, underscores, hyphens, and forward slashes.');
|
|
37
|
+
}
|
|
38
|
+
if (branch.length > MAX_BRANCH_NAME_LENGTH) {
|
|
39
|
+
throw new Error(`Invalid branch name: "${branch}". Branch names may only contain letters, digits, dots, underscores, hyphens, and forward slashes.`);
|
|
40
|
+
}
|
|
41
|
+
if (!BRANCH_NAME_REGEX.test(branch)) {
|
|
42
|
+
throw new Error(`Invalid branch name: "${branch}". Branch names may only contain letters, digits, dots, underscores, hyphens, and forward slashes.`);
|
|
43
|
+
}
|
|
44
|
+
return branch;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Assert that a candidate path resolves within the given root directory.
|
|
48
|
+
*
|
|
49
|
+
* Prevents path traversal attacks where filenames like "../../../etc/passwd"
|
|
50
|
+
* could write to arbitrary filesystem locations.
|
|
51
|
+
*
|
|
52
|
+
* @param candidatePath - The relative path to check (e.g., an artifact filename from an API response)
|
|
53
|
+
* @param rootDir - The root directory that the path must stay within
|
|
54
|
+
* @returns The resolved absolute path if it is contained within rootDir
|
|
55
|
+
* @throws Error if the resolved path escapes the root directory
|
|
56
|
+
*/
|
|
57
|
+
export function assertPathContainment(candidatePath, rootDir) {
|
|
58
|
+
const normalizedRoot = path.resolve(rootDir);
|
|
59
|
+
const resolved = path.resolve(rootDir, candidatePath);
|
|
60
|
+
if (resolved !== normalizedRoot && !resolved.startsWith(normalizedRoot + path.sep)) {
|
|
61
|
+
throw new Error(`Path traversal rejected: "${candidatePath}" resolves outside output directory "${rootDir}".`);
|
|
62
|
+
}
|
|
63
|
+
return resolved;
|
|
64
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure validation functions for CLI option parsing.
|
|
3
|
+
*
|
|
4
|
+
* All validators throw Commander's InvalidArgumentError on failure,
|
|
5
|
+
* which integrates with Commander's built-in error handling pipeline.
|
|
6
|
+
* No process.exit calls -- callers decide error handling.
|
|
7
|
+
*
|
|
8
|
+
* Includes Levenshtein distance for "Did you mean?" suggestions on enum typos.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Find the closest match for `input` among `candidates` using Levenshtein distance.
|
|
12
|
+
* Returns null if no candidate is within `maxDistance`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function closestMatch(input: string, candidates: readonly string[], maxDistance?: number): string | null;
|
|
15
|
+
export interface NumericConstraint {
|
|
16
|
+
min?: number;
|
|
17
|
+
max?: number;
|
|
18
|
+
integer?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate and parse a numeric string value.
|
|
22
|
+
* Throws InvalidArgumentError with descriptive message on failure.
|
|
23
|
+
*
|
|
24
|
+
* Uses Number() (not parseInt) to reject partial parses like "12abc".
|
|
25
|
+
*/
|
|
26
|
+
export declare function validateNumeric(value: string, name: string, constraints?: NumericConstraint): number;
|
|
27
|
+
/**
|
|
28
|
+
* Validate a string value against an allowed set.
|
|
29
|
+
* Throws InvalidArgumentError with "Did you mean?" suggestion on typos.
|
|
30
|
+
*/
|
|
31
|
+
export declare function validateEnum(value: string, name: string, allowed: readonly string[]): string;
|
|
32
|
+
export declare function parseTimeout(value: string): number;
|
|
33
|
+
export declare function parseInterval(value: string): number;
|
|
34
|
+
export declare function parseConcurrency(value: string): number;
|
|
35
|
+
export declare function parseThreshold(value: string): number;
|
|
36
|
+
export declare function parseScore(value: string): number;
|
|
37
|
+
export declare function parseMode(value: string): string;
|
|
38
|
+
export declare function parseFailOn(value: string): string;
|
|
39
|
+
export declare function parseGroupBy(value: string): string;
|
|
40
|
+
export declare function parseBudget(value: string): string;
|
|
41
|
+
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAsCH;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,WAAW,SAAI,GACd,MAAM,GAAG,IAAI,CAaf;AAMD,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,WAAW,GAAE,iBAAsB,GAClC,MAAM,CAkCR;AAMD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,MAAM,CASR;AAQD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure validation functions for CLI option parsing.
|
|
3
|
+
*
|
|
4
|
+
* All validators throw Commander's InvalidArgumentError on failure,
|
|
5
|
+
* which integrates with Commander's built-in error handling pipeline.
|
|
6
|
+
* No process.exit calls -- callers decide error handling.
|
|
7
|
+
*
|
|
8
|
+
* Includes Levenshtein distance for "Did you mean?" suggestions on enum typos.
|
|
9
|
+
*/
|
|
10
|
+
import { InvalidArgumentError } from "commander";
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Levenshtein distance (private)
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
/**
|
|
15
|
+
* Compute Levenshtein edit distance between two strings.
|
|
16
|
+
* Case-insensitive comparison.
|
|
17
|
+
*/
|
|
18
|
+
function levenshtein(a, b) {
|
|
19
|
+
const al = a.toLowerCase();
|
|
20
|
+
const bl = b.toLowerCase();
|
|
21
|
+
const m = al.length;
|
|
22
|
+
const n = bl.length;
|
|
23
|
+
const dp = Array.from({ length: m + 1 }, (_, i) => Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)));
|
|
24
|
+
for (let i = 1; i <= m; i++) {
|
|
25
|
+
for (let j = 1; j <= n; j++) {
|
|
26
|
+
dp[i][j] =
|
|
27
|
+
al[i - 1] === bl[j - 1]
|
|
28
|
+
? dp[i - 1][j - 1]
|
|
29
|
+
: 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return dp[m][n];
|
|
33
|
+
}
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Closest match
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
/**
|
|
38
|
+
* Find the closest match for `input` among `candidates` using Levenshtein distance.
|
|
39
|
+
* Returns null if no candidate is within `maxDistance`.
|
|
40
|
+
*/
|
|
41
|
+
export function closestMatch(input, candidates, maxDistance = 3) {
|
|
42
|
+
let best = null;
|
|
43
|
+
let bestDist = maxDistance + 1;
|
|
44
|
+
for (const candidate of candidates) {
|
|
45
|
+
const dist = levenshtein(input, candidate);
|
|
46
|
+
if (dist < bestDist) {
|
|
47
|
+
bestDist = dist;
|
|
48
|
+
best = candidate;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return best;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Validate and parse a numeric string value.
|
|
55
|
+
* Throws InvalidArgumentError with descriptive message on failure.
|
|
56
|
+
*
|
|
57
|
+
* Uses Number() (not parseInt) to reject partial parses like "12abc".
|
|
58
|
+
*/
|
|
59
|
+
export function validateNumeric(value, name, constraints = {}) {
|
|
60
|
+
if (value.trim() === "") {
|
|
61
|
+
throw new InvalidArgumentError(`Invalid value for --${name}: "${value}" is not a number`);
|
|
62
|
+
}
|
|
63
|
+
const parsed = Number(value);
|
|
64
|
+
if (Number.isNaN(parsed)) {
|
|
65
|
+
throw new InvalidArgumentError(`Invalid value for --${name}: "${value}" is not a number`);
|
|
66
|
+
}
|
|
67
|
+
if (constraints.integer && !Number.isInteger(parsed)) {
|
|
68
|
+
throw new InvalidArgumentError(`Invalid value for --${name}: "${value}" must be an integer`);
|
|
69
|
+
}
|
|
70
|
+
if (constraints.min !== undefined && parsed < constraints.min) {
|
|
71
|
+
throw new InvalidArgumentError(`Invalid value for --${name}: ${parsed} is below minimum ${constraints.min}`);
|
|
72
|
+
}
|
|
73
|
+
if (constraints.max !== undefined && parsed > constraints.max) {
|
|
74
|
+
throw new InvalidArgumentError(`Invalid value for --${name}: ${parsed} exceeds maximum ${constraints.max}`);
|
|
75
|
+
}
|
|
76
|
+
return parsed;
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Enum validation
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
/**
|
|
82
|
+
* Validate a string value against an allowed set.
|
|
83
|
+
* Throws InvalidArgumentError with "Did you mean?" suggestion on typos.
|
|
84
|
+
*/
|
|
85
|
+
export function validateEnum(value, name, allowed) {
|
|
86
|
+
if (allowed.includes(value))
|
|
87
|
+
return value;
|
|
88
|
+
const suggestion = closestMatch(value, allowed);
|
|
89
|
+
const hint = suggestion ? ` Did you mean "${suggestion}"?` : "";
|
|
90
|
+
throw new InvalidArgumentError(`Unknown value "${value}" for --${name}.${hint} Valid values: ${allowed.join(", ")}`);
|
|
91
|
+
}
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// Convenience Commander parser factories
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// These are used as the 3rd argument to Commander's .option() method.
|
|
96
|
+
// Commander catches InvalidArgumentError and routes it through configureOutput.
|
|
97
|
+
export function parseTimeout(value) {
|
|
98
|
+
return validateNumeric(value, "timeout", { min: 1, max: 300000, integer: true });
|
|
99
|
+
}
|
|
100
|
+
export function parseInterval(value) {
|
|
101
|
+
return validateNumeric(value, "interval", { min: 1, max: 300000, integer: true });
|
|
102
|
+
}
|
|
103
|
+
export function parseConcurrency(value) {
|
|
104
|
+
return validateNumeric(value, "concurrency", { min: 1, max: 50, integer: true });
|
|
105
|
+
}
|
|
106
|
+
export function parseThreshold(value) {
|
|
107
|
+
return validateNumeric(value, "threshold", { min: 0, max: 100, integer: true });
|
|
108
|
+
}
|
|
109
|
+
export function parseScore(value) {
|
|
110
|
+
return validateNumeric(value, "fail-on-score", { min: 0, max: 100, integer: true });
|
|
111
|
+
}
|
|
112
|
+
export function parseMode(value) {
|
|
113
|
+
return validateEnum(value, "mode", ["basic", "standard", "deep"]);
|
|
114
|
+
}
|
|
115
|
+
export function parseFailOn(value) {
|
|
116
|
+
return validateEnum(value, "fail-on", ["error", "warning", "info", "none"]);
|
|
117
|
+
}
|
|
118
|
+
export function parseGroupBy(value) {
|
|
119
|
+
return validateEnum(value, "group-by", ["severity", "category", "route"]);
|
|
120
|
+
}
|
|
121
|
+
export function parseBudget(value) {
|
|
122
|
+
return validateEnum(value, "budget", ["quick", "standard", "full"]);
|
|
123
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vertaaux/cli",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "VertaaUX CLI for UX audits, accessibility checks, and CI gating.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"vertaa": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"schemas",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"vertaaux",
|
|
17
|
+
"vertaa",
|
|
18
|
+
"cli",
|
|
19
|
+
"ux",
|
|
20
|
+
"audit",
|
|
21
|
+
"accessibility",
|
|
22
|
+
"a11y",
|
|
23
|
+
"ci"
|
|
24
|
+
],
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/vertaaux/vertaa"
|
|
28
|
+
},
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=18"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"dev": "tsc -w",
|
|
39
|
+
"start": "node dist/index.js",
|
|
40
|
+
"prepublishOnly": "npm run build && node scripts/verify-package.mjs",
|
|
41
|
+
"test": "vitest run --config vitest.config.ts"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@inquirer/prompts": "^8.2.0",
|
|
45
|
+
"ajv": "^8.17.1",
|
|
46
|
+
"ajv-formats": "^3.0.1",
|
|
47
|
+
"chalk": "^5.6.2",
|
|
48
|
+
"cli-table3": "^0.6.5",
|
|
49
|
+
"commander": "^14.0.2",
|
|
50
|
+
"cosmiconfig": "^9.0.0",
|
|
51
|
+
"dotenv": "^17.2.3",
|
|
52
|
+
"minimatch": "^10.1.1",
|
|
53
|
+
"ora": "^9.1.0",
|
|
54
|
+
"semver": "^7.7.3",
|
|
55
|
+
"yaml": "^2.8.2"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/minimatch": "^5.1.2",
|
|
59
|
+
"@types/node": "^20.11.25",
|
|
60
|
+
"@types/semver": "^7.7.1",
|
|
61
|
+
"typescript": "^5.6.3"
|
|
62
|
+
}
|
|
63
|
+
}
|