@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.
Files changed (198) hide show
  1. package/README.md +345 -0
  2. package/dist/auth/ci-token.d.ts +49 -0
  3. package/dist/auth/ci-token.d.ts.map +1 -0
  4. package/dist/auth/ci-token.js +83 -0
  5. package/dist/auth/device-flow.d.ts +66 -0
  6. package/dist/auth/device-flow.d.ts.map +1 -0
  7. package/dist/auth/device-flow.js +156 -0
  8. package/dist/auth/token-store.d.ts +53 -0
  9. package/dist/auth/token-store.d.ts.map +1 -0
  10. package/dist/auth/token-store.js +78 -0
  11. package/dist/baseline/diff.d.ts +57 -0
  12. package/dist/baseline/diff.d.ts.map +1 -0
  13. package/dist/baseline/diff.js +152 -0
  14. package/dist/baseline/hash.d.ts +54 -0
  15. package/dist/baseline/hash.d.ts.map +1 -0
  16. package/dist/baseline/hash.js +66 -0
  17. package/dist/baseline/manager.d.ts +89 -0
  18. package/dist/baseline/manager.d.ts.map +1 -0
  19. package/dist/baseline/manager.js +157 -0
  20. package/dist/cache/index.d.ts +8 -0
  21. package/dist/cache/index.d.ts.map +1 -0
  22. package/dist/cache/index.js +7 -0
  23. package/dist/cache/route-cache.d.ts +119 -0
  24. package/dist/cache/route-cache.d.ts.map +1 -0
  25. package/dist/cache/route-cache.js +213 -0
  26. package/dist/ci/changed-routes.d.ts +95 -0
  27. package/dist/ci/changed-routes.d.ts.map +1 -0
  28. package/dist/ci/changed-routes.js +304 -0
  29. package/dist/ci/github-api.d.ts +68 -0
  30. package/dist/ci/github-api.d.ts.map +1 -0
  31. package/dist/ci/github-api.js +138 -0
  32. package/dist/ci/gitlab-api.d.ts +75 -0
  33. package/dist/ci/gitlab-api.d.ts.map +1 -0
  34. package/dist/ci/gitlab-api.js +180 -0
  35. package/dist/ci/index.d.ts +6 -0
  36. package/dist/ci/index.d.ts.map +1 -0
  37. package/dist/ci/index.js +4 -0
  38. package/dist/commands/audit.d.ts +58 -0
  39. package/dist/commands/audit.d.ts.map +1 -0
  40. package/dist/commands/audit.js +862 -0
  41. package/dist/commands/baseline.d.ts +22 -0
  42. package/dist/commands/baseline.d.ts.map +1 -0
  43. package/dist/commands/baseline.js +210 -0
  44. package/dist/commands/comment.d.ts +14 -0
  45. package/dist/commands/comment.d.ts.map +1 -0
  46. package/dist/commands/comment.js +363 -0
  47. package/dist/commands/diff.d.ts +24 -0
  48. package/dist/commands/diff.d.ts.map +1 -0
  49. package/dist/commands/diff.js +196 -0
  50. package/dist/commands/doctor.d.ts +58 -0
  51. package/dist/commands/doctor.d.ts.map +1 -0
  52. package/dist/commands/doctor.js +338 -0
  53. package/dist/commands/download.d.ts +12 -0
  54. package/dist/commands/download.d.ts.map +1 -0
  55. package/dist/commands/download.js +183 -0
  56. package/dist/commands/explain.d.ts +62 -0
  57. package/dist/commands/explain.d.ts.map +1 -0
  58. package/dist/commands/explain.js +302 -0
  59. package/dist/commands/init.d.ts +12 -0
  60. package/dist/commands/init.d.ts.map +1 -0
  61. package/dist/commands/init.js +212 -0
  62. package/dist/commands/login.d.ts +14 -0
  63. package/dist/commands/login.d.ts.map +1 -0
  64. package/dist/commands/login.js +222 -0
  65. package/dist/commands/policy.d.ts +13 -0
  66. package/dist/commands/policy.d.ts.map +1 -0
  67. package/dist/commands/policy.js +347 -0
  68. package/dist/commands/upload.d.ts +12 -0
  69. package/dist/commands/upload.d.ts.map +1 -0
  70. package/dist/commands/upload.js +158 -0
  71. package/dist/config/defaults.d.ts +21 -0
  72. package/dist/config/defaults.d.ts.map +1 -0
  73. package/dist/config/defaults.js +49 -0
  74. package/dist/config/loader.d.ts +66 -0
  75. package/dist/config/loader.d.ts.map +1 -0
  76. package/dist/config/loader.js +167 -0
  77. package/dist/config/schema.d.ts +55 -0
  78. package/dist/config/schema.d.ts.map +1 -0
  79. package/dist/config/schema.js +6 -0
  80. package/dist/index.d.ts +9 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +1090 -0
  83. package/dist/interactive/fix-wizard.d.ts +44 -0
  84. package/dist/interactive/fix-wizard.d.ts.map +1 -0
  85. package/dist/interactive/fix-wizard.js +286 -0
  86. package/dist/interactive/init-wizard.d.ts +32 -0
  87. package/dist/interactive/init-wizard.d.ts.map +1 -0
  88. package/dist/interactive/init-wizard.js +193 -0
  89. package/dist/interactive/prompts.d.ts +62 -0
  90. package/dist/interactive/prompts.d.ts.map +1 -0
  91. package/dist/interactive/prompts.js +78 -0
  92. package/dist/monorepo/detector.d.ts +70 -0
  93. package/dist/monorepo/detector.d.ts.map +1 -0
  94. package/dist/monorepo/detector.js +278 -0
  95. package/dist/monorepo/index.d.ts +9 -0
  96. package/dist/monorepo/index.d.ts.map +1 -0
  97. package/dist/monorepo/index.js +8 -0
  98. package/dist/monorepo/workspace.d.ts +142 -0
  99. package/dist/monorepo/workspace.d.ts.map +1 -0
  100. package/dist/monorepo/workspace.js +171 -0
  101. package/dist/output/envelope.d.ts +21 -0
  102. package/dist/output/envelope.d.ts.map +1 -0
  103. package/dist/output/envelope.js +27 -0
  104. package/dist/output/factory.d.ts +73 -0
  105. package/dist/output/factory.d.ts.map +1 -0
  106. package/dist/output/factory.js +60 -0
  107. package/dist/output/formats.d.ts +11 -0
  108. package/dist/output/formats.d.ts.map +1 -0
  109. package/dist/output/formats.js +41 -0
  110. package/dist/output/html.d.ts +45 -0
  111. package/dist/output/html.d.ts.map +1 -0
  112. package/dist/output/html.js +607 -0
  113. package/dist/output/human.d.ts +41 -0
  114. package/dist/output/human.d.ts.map +1 -0
  115. package/dist/output/human.js +274 -0
  116. package/dist/output/json.d.ts +42 -0
  117. package/dist/output/json.d.ts.map +1 -0
  118. package/dist/output/json.js +37 -0
  119. package/dist/output/junit.d.ts +56 -0
  120. package/dist/output/junit.d.ts.map +1 -0
  121. package/dist/output/junit.js +135 -0
  122. package/dist/output/markdown.d.ts +77 -0
  123. package/dist/output/markdown.d.ts.map +1 -0
  124. package/dist/output/markdown.js +411 -0
  125. package/dist/output/sarif.d.ts +160 -0
  126. package/dist/output/sarif.d.ts.map +1 -0
  127. package/dist/output/sarif.js +207 -0
  128. package/dist/policy/evaluator.d.ts +111 -0
  129. package/dist/policy/evaluator.d.ts.map +1 -0
  130. package/dist/policy/evaluator.js +362 -0
  131. package/dist/policy/index.d.ts +15 -0
  132. package/dist/policy/index.d.ts.map +1 -0
  133. package/dist/policy/index.js +11 -0
  134. package/dist/policy/loader.d.ts +97 -0
  135. package/dist/policy/loader.d.ts.map +1 -0
  136. package/dist/policy/loader.js +281 -0
  137. package/dist/policy/schema.d.ts +297 -0
  138. package/dist/policy/schema.d.ts.map +1 -0
  139. package/dist/policy/schema.js +230 -0
  140. package/dist/quality-gate/evaluator.d.ts +58 -0
  141. package/dist/quality-gate/evaluator.d.ts.map +1 -0
  142. package/dist/quality-gate/evaluator.js +274 -0
  143. package/dist/quality-gate/index.d.ts +10 -0
  144. package/dist/quality-gate/index.d.ts.map +1 -0
  145. package/dist/quality-gate/index.js +7 -0
  146. package/dist/quality-gate/types.d.ts +103 -0
  147. package/dist/quality-gate/types.d.ts.map +1 -0
  148. package/dist/quality-gate/types.js +23 -0
  149. package/dist/templates/azure-devops.d.ts +25 -0
  150. package/dist/templates/azure-devops.d.ts.map +1 -0
  151. package/dist/templates/azure-devops.js +109 -0
  152. package/dist/templates/circleci.d.ts +28 -0
  153. package/dist/templates/circleci.d.ts.map +1 -0
  154. package/dist/templates/circleci.js +86 -0
  155. package/dist/templates/github-actions.d.ts +81 -0
  156. package/dist/templates/github-actions.d.ts.map +1 -0
  157. package/dist/templates/github-actions.js +393 -0
  158. package/dist/templates/gitlab-ci.d.ts +26 -0
  159. package/dist/templates/gitlab-ci.d.ts.map +1 -0
  160. package/dist/templates/gitlab-ci.js +70 -0
  161. package/dist/templates/index.d.ts +72 -0
  162. package/dist/templates/index.d.ts.map +1 -0
  163. package/dist/templates/index.js +112 -0
  164. package/dist/templates/jenkins.d.ts +26 -0
  165. package/dist/templates/jenkins.d.ts.map +1 -0
  166. package/dist/templates/jenkins.js +110 -0
  167. package/dist/ui/banner.d.ts +31 -0
  168. package/dist/ui/banner.d.ts.map +1 -0
  169. package/dist/ui/banner.js +84 -0
  170. package/dist/ui/diagnostics.d.ts +39 -0
  171. package/dist/ui/diagnostics.d.ts.map +1 -0
  172. package/dist/ui/diagnostics.js +153 -0
  173. package/dist/ui/spinner.d.ts +61 -0
  174. package/dist/ui/spinner.d.ts.map +1 -0
  175. package/dist/ui/spinner.js +101 -0
  176. package/dist/ui/table.d.ts +63 -0
  177. package/dist/ui/table.d.ts.map +1 -0
  178. package/dist/ui/table.js +236 -0
  179. package/dist/utils/client.d.ts +82 -0
  180. package/dist/utils/client.d.ts.map +1 -0
  181. package/dist/utils/client.js +128 -0
  182. package/dist/utils/detect-env.d.ts +59 -0
  183. package/dist/utils/detect-env.d.ts.map +1 -0
  184. package/dist/utils/detect-env.js +115 -0
  185. package/dist/utils/exit-codes.d.ts +47 -0
  186. package/dist/utils/exit-codes.d.ts.map +1 -0
  187. package/dist/utils/exit-codes.js +61 -0
  188. package/dist/utils/logger.d.ts +87 -0
  189. package/dist/utils/logger.d.ts.map +1 -0
  190. package/dist/utils/logger.js +185 -0
  191. package/dist/utils/sanitize.d.ts +36 -0
  192. package/dist/utils/sanitize.d.ts.map +1 -0
  193. package/dist/utils/sanitize.js +64 -0
  194. package/dist/utils/validators.d.ts +41 -0
  195. package/dist/utils/validators.d.ts.map +1 -0
  196. package/dist/utils/validators.js +123 -0
  197. package/package.json +63 -0
  198. package/schemas/vertaaux.config.schema.json +103 -0
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Reusable prompt patterns for interactive CLI mode.
3
+ *
4
+ * Wraps @inquirer/prompts with consistent styling.
5
+ * Keyboard navigation is handled natively by @inquirer/prompts:
6
+ * - Arrow keys for navigation
7
+ * - Enter to confirm
8
+ * - Space to select (multi-select)
9
+ */
10
+ import { select, confirm, input } from "@inquirer/prompts";
11
+ /**
12
+ * Prompt user to select from a list of options.
13
+ *
14
+ * Uses arrow keys for navigation, Enter to confirm.
15
+ *
16
+ * @param message - Prompt message
17
+ * @param choices - List of options
18
+ * @returns Selected value
19
+ */
20
+ export async function selectAction(message, choices) {
21
+ return select({
22
+ message,
23
+ choices: choices.map((c) => ({
24
+ name: c.name,
25
+ value: c.value,
26
+ description: c.description,
27
+ disabled: c.disabled,
28
+ })),
29
+ });
30
+ }
31
+ /**
32
+ * Prompt user for yes/no confirmation.
33
+ *
34
+ * @param message - Question to confirm
35
+ * @param defaultValue - Default value if user just presses Enter
36
+ * @returns true for yes, false for no
37
+ */
38
+ export async function confirmAction(message, defaultValue = true) {
39
+ return confirm({
40
+ message,
41
+ default: defaultValue,
42
+ });
43
+ }
44
+ /**
45
+ * Prompt user for text input.
46
+ *
47
+ * @param message - Prompt message
48
+ * @param defaultValue - Optional default value
49
+ * @param required - Whether input is required (default: false)
50
+ * @returns User input string
51
+ */
52
+ export async function inputText(message, defaultValue, required = false) {
53
+ return input({
54
+ message,
55
+ default: defaultValue,
56
+ validate: required
57
+ ? (value) => (value.trim() ? true : "This field is required")
58
+ : undefined,
59
+ });
60
+ }
61
+ /**
62
+ * Check if running in an interactive TTY environment.
63
+ *
64
+ * @returns true if stdin/stdout are TTY
65
+ */
66
+ export function isInteractive() {
67
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY);
68
+ }
69
+ /**
70
+ * Assert that the environment is interactive, throwing if not.
71
+ *
72
+ * @throws Error if not in interactive TTY mode
73
+ */
74
+ export function requireInteractive() {
75
+ if (!isInteractive()) {
76
+ throw new Error("Interactive mode requires a terminal. Use --format json in CI or piped environments.");
77
+ }
78
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Monorepo detection and workspace discovery.
3
+ *
4
+ * Supports:
5
+ * - npm/yarn/pnpm workspaces
6
+ * - Nx monorepos
7
+ * - Turborepo
8
+ * - Lerna
9
+ */
10
+ /**
11
+ * Monorepo configuration detected from project root.
12
+ */
13
+ export interface MonorepoConfig {
14
+ /** Type of monorepo detected */
15
+ type: "npm" | "yarn" | "pnpm" | "nx" | "turbo" | "lerna" | "none";
16
+ /** Root directory of the monorepo */
17
+ root: string;
18
+ /** Detected workspaces */
19
+ workspaces: Workspace[];
20
+ }
21
+ /**
22
+ * Individual workspace in a monorepo.
23
+ */
24
+ export interface Workspace {
25
+ /** Package name from package.json */
26
+ name: string;
27
+ /** Relative path from monorepo root */
28
+ path: string;
29
+ /** Absolute path to package.json */
30
+ packageJson: string;
31
+ /** Scripts defined in package.json */
32
+ scripts?: Record<string, string>;
33
+ /** Detected app type for URL inference */
34
+ appType?: "nextjs" | "remix" | "sveltekit" | "vite" | "cra" | "unknown";
35
+ /** Inferred dev server URL if detectable */
36
+ url?: string;
37
+ /** Inferred dev server port */
38
+ port?: number;
39
+ }
40
+ /**
41
+ * Package.json structure (partial).
42
+ */
43
+ interface PackageJson {
44
+ name?: string;
45
+ workspaces?: string[] | {
46
+ packages: string[];
47
+ };
48
+ scripts?: Record<string, string>;
49
+ dependencies?: Record<string, string>;
50
+ devDependencies?: Record<string, string>;
51
+ }
52
+ /**
53
+ * Detect monorepo configuration from project root.
54
+ *
55
+ * @param projectRoot - Root directory to scan (defaults to cwd)
56
+ * @returns MonorepoConfig with detected type and workspaces
57
+ */
58
+ export declare function detectMonorepo(projectRoot?: string): Promise<MonorepoConfig>;
59
+ /**
60
+ * Get list of auditable apps from monorepo.
61
+ *
62
+ * Filters workspaces to only those that are web apps with dev servers,
63
+ * excluding libraries and tools.
64
+ *
65
+ * @param config - MonorepoConfig from detectMonorepo
66
+ * @returns List of auditable workspaces
67
+ */
68
+ export declare function getAuditableApps(config: MonorepoConfig): Workspace[];
69
+ export type { PackageJson };
70
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../src/monorepo/detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,IAAI,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IAClE,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,0CAA0C;IAC1C,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;IACxE,4CAA4C;IAC5C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,UAAU,WAAW;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAuLD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,cAAc,CAAC,CA+FzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,EAAE,CAEpE;AAGD,YAAY,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,278 @@
1
+ /**
2
+ * Monorepo detection and workspace discovery.
3
+ *
4
+ * Supports:
5
+ * - npm/yarn/pnpm workspaces
6
+ * - Nx monorepos
7
+ * - Turborepo
8
+ * - Lerna
9
+ */
10
+ import fs from "fs";
11
+ import path from "path";
12
+ /**
13
+ * Expand glob patterns to actual directory paths.
14
+ */
15
+ function expandGlobPatterns(root, patterns) {
16
+ const results = [];
17
+ for (const pattern of patterns) {
18
+ // Handle simple glob patterns like "packages/*" or "apps/*"
19
+ if (pattern.endsWith("/*")) {
20
+ const basePath = pattern.slice(0, -2);
21
+ const fullBasePath = path.join(root, basePath);
22
+ if (fs.existsSync(fullBasePath)) {
23
+ const entries = fs.readdirSync(fullBasePath, { withFileTypes: true });
24
+ for (const entry of entries) {
25
+ if (entry.isDirectory()) {
26
+ const pkgJsonPath = path.join(fullBasePath, entry.name, "package.json");
27
+ if (fs.existsSync(pkgJsonPath)) {
28
+ results.push(path.join(basePath, entry.name));
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
34
+ else if (pattern.includes("**")) {
35
+ // Recursive glob - simplified implementation
36
+ // For "packages/**" pattern, scan all subdirectories
37
+ const basePath = pattern.split("**")[0].replace(/\/$/, "");
38
+ const fullBasePath = path.join(root, basePath);
39
+ if (fs.existsSync(fullBasePath)) {
40
+ const scanDir = (dir, relativePath) => {
41
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
42
+ for (const entry of entries) {
43
+ if (entry.isDirectory()) {
44
+ const entryPath = path.join(dir, entry.name);
45
+ const entryRelative = path.join(relativePath, entry.name);
46
+ const pkgJsonPath = path.join(entryPath, "package.json");
47
+ if (fs.existsSync(pkgJsonPath)) {
48
+ results.push(entryRelative);
49
+ }
50
+ // Continue scanning deeper
51
+ scanDir(entryPath, entryRelative);
52
+ }
53
+ }
54
+ };
55
+ scanDir(fullBasePath, basePath);
56
+ }
57
+ }
58
+ else {
59
+ // Exact path
60
+ const fullPath = path.join(root, pattern);
61
+ const pkgJsonPath = path.join(fullPath, "package.json");
62
+ if (fs.existsSync(pkgJsonPath)) {
63
+ results.push(pattern);
64
+ }
65
+ }
66
+ }
67
+ return results;
68
+ }
69
+ /**
70
+ * Read and parse package.json file.
71
+ */
72
+ function readPackageJson(pkgJsonPath) {
73
+ try {
74
+ const content = fs.readFileSync(pkgJsonPath, "utf-8");
75
+ return JSON.parse(content);
76
+ }
77
+ catch {
78
+ return null;
79
+ }
80
+ }
81
+ /**
82
+ * Detect app type from package.json dependencies.
83
+ */
84
+ function detectAppType(pkg) {
85
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
86
+ // Check for Next.js
87
+ if (deps.next) {
88
+ return "nextjs";
89
+ }
90
+ // Check for Remix
91
+ if (deps["@remix-run/react"] || deps["@remix-run/node"]) {
92
+ return "remix";
93
+ }
94
+ // Check for SvelteKit
95
+ if (deps["@sveltejs/kit"]) {
96
+ return "sveltekit";
97
+ }
98
+ // Check for Create React App
99
+ if (deps["react-scripts"]) {
100
+ return "cra";
101
+ }
102
+ // Check for Vite (generic, check last as many frameworks use Vite)
103
+ if (deps.vite) {
104
+ return "vite";
105
+ }
106
+ return "unknown";
107
+ }
108
+ /**
109
+ * Get default port for app type.
110
+ */
111
+ function getDefaultPort(appType) {
112
+ switch (appType) {
113
+ case "nextjs":
114
+ return 3000;
115
+ case "remix":
116
+ return 3000;
117
+ case "sveltekit":
118
+ return 5173;
119
+ case "vite":
120
+ return 5173;
121
+ case "cra":
122
+ return 3000;
123
+ default:
124
+ return 3000;
125
+ }
126
+ }
127
+ /**
128
+ * Check if a workspace is an auditable app (has a dev server).
129
+ */
130
+ function isAuditableApp(workspace) {
131
+ // Check if it has a dev script
132
+ if (workspace.scripts?.dev || workspace.scripts?.start) {
133
+ return true;
134
+ }
135
+ // Check if it's a known app type (not a library)
136
+ if (workspace.appType && workspace.appType !== "unknown") {
137
+ return true;
138
+ }
139
+ return false;
140
+ }
141
+ /**
142
+ * Parse pnpm-workspace.yaml content.
143
+ */
144
+ function parsePnpmWorkspace(content) {
145
+ // Simple YAML parsing for workspace patterns
146
+ const patterns = [];
147
+ const lines = content.split("\n");
148
+ let inPackages = false;
149
+ for (const line of lines) {
150
+ const trimmed = line.trim();
151
+ if (trimmed === "packages:") {
152
+ inPackages = true;
153
+ continue;
154
+ }
155
+ if (inPackages) {
156
+ if (trimmed.startsWith("-")) {
157
+ // Extract pattern, removing quotes if present
158
+ let pattern = trimmed.slice(1).trim();
159
+ pattern = pattern.replace(/^['"]|['"]$/g, "");
160
+ if (pattern) {
161
+ patterns.push(pattern);
162
+ }
163
+ }
164
+ else if (trimmed && !trimmed.startsWith("#")) {
165
+ // Non-empty, non-comment line means end of packages section
166
+ break;
167
+ }
168
+ }
169
+ }
170
+ return patterns;
171
+ }
172
+ /**
173
+ * Detect monorepo configuration from project root.
174
+ *
175
+ * @param projectRoot - Root directory to scan (defaults to cwd)
176
+ * @returns MonorepoConfig with detected type and workspaces
177
+ */
178
+ export async function detectMonorepo(projectRoot) {
179
+ const root = projectRoot || process.cwd();
180
+ const rootPkgJsonPath = path.join(root, "package.json");
181
+ const rootPkg = readPackageJson(rootPkgJsonPath);
182
+ let type = "none";
183
+ let workspacePatterns = [];
184
+ // Check for pnpm-workspace.yaml first
185
+ const pnpmWorkspacePath = path.join(root, "pnpm-workspace.yaml");
186
+ if (fs.existsSync(pnpmWorkspacePath)) {
187
+ type = "pnpm";
188
+ const content = fs.readFileSync(pnpmWorkspacePath, "utf-8");
189
+ workspacePatterns = parsePnpmWorkspace(content);
190
+ }
191
+ // Check for nx.json
192
+ else if (fs.existsSync(path.join(root, "nx.json"))) {
193
+ type = "nx";
194
+ // Nx workspaces are typically in packages/ or apps/
195
+ if (rootPkg?.workspaces) {
196
+ workspacePatterns = Array.isArray(rootPkg.workspaces)
197
+ ? rootPkg.workspaces
198
+ : rootPkg.workspaces.packages || [];
199
+ }
200
+ else {
201
+ workspacePatterns = ["packages/*", "apps/*", "libs/*"];
202
+ }
203
+ }
204
+ // Check for turbo.json
205
+ else if (fs.existsSync(path.join(root, "turbo.json"))) {
206
+ type = "turbo";
207
+ if (rootPkg?.workspaces) {
208
+ workspacePatterns = Array.isArray(rootPkg.workspaces)
209
+ ? rootPkg.workspaces
210
+ : rootPkg.workspaces.packages || [];
211
+ }
212
+ else {
213
+ workspacePatterns = ["packages/*", "apps/*"];
214
+ }
215
+ }
216
+ // Check for lerna.json
217
+ else if (fs.existsSync(path.join(root, "lerna.json"))) {
218
+ type = "lerna";
219
+ try {
220
+ const lernaConfig = JSON.parse(fs.readFileSync(path.join(root, "lerna.json"), "utf-8"));
221
+ workspacePatterns = lernaConfig.packages || ["packages/*"];
222
+ }
223
+ catch {
224
+ workspacePatterns = ["packages/*"];
225
+ }
226
+ }
227
+ // Check for npm/yarn workspaces in package.json
228
+ else if (rootPkg?.workspaces) {
229
+ // Determine if yarn or npm based on lock file
230
+ if (fs.existsSync(path.join(root, "yarn.lock"))) {
231
+ type = "yarn";
232
+ }
233
+ else {
234
+ type = "npm";
235
+ }
236
+ workspacePatterns = Array.isArray(rootPkg.workspaces)
237
+ ? rootPkg.workspaces
238
+ : rootPkg.workspaces.packages || [];
239
+ }
240
+ // If no monorepo detected, return early
241
+ if (type === "none") {
242
+ return { type, root, workspaces: [] };
243
+ }
244
+ // Expand patterns to actual workspace paths
245
+ const workspacePaths = expandGlobPatterns(root, workspacePatterns);
246
+ // Build workspace objects
247
+ const workspaces = [];
248
+ for (const wsPath of workspacePaths) {
249
+ const pkgJsonPath = path.join(root, wsPath, "package.json");
250
+ const pkg = readPackageJson(pkgJsonPath);
251
+ if (!pkg)
252
+ continue;
253
+ const appType = detectAppType(pkg);
254
+ const port = getDefaultPort(appType);
255
+ workspaces.push({
256
+ name: pkg.name || path.basename(wsPath),
257
+ path: wsPath,
258
+ packageJson: pkgJsonPath,
259
+ scripts: pkg.scripts,
260
+ appType,
261
+ port,
262
+ url: `http://localhost:${port}`,
263
+ });
264
+ }
265
+ return { type, root, workspaces };
266
+ }
267
+ /**
268
+ * Get list of auditable apps from monorepo.
269
+ *
270
+ * Filters workspaces to only those that are web apps with dev servers,
271
+ * excluding libraries and tools.
272
+ *
273
+ * @param config - MonorepoConfig from detectMonorepo
274
+ * @returns List of auditable workspaces
275
+ */
276
+ export function getAuditableApps(config) {
277
+ return config.workspaces.filter(isAuditableApp);
278
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Monorepo support module.
3
+ *
4
+ * Provides detection, workspace discovery, and orchestration
5
+ * for auditing multi-package repositories.
6
+ */
7
+ export { detectMonorepo, getAuditableApps, type MonorepoConfig, type Workspace, } from "./detector.js";
8
+ export { auditWorkspace, generateMatrixConfig, aggregateResults, formatAggregatedResults, type WorkspaceAuditOptions, type WorkspaceResult, type AuditResult, type MatrixConfig, type AggregatedResults, } from "./workspace.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/monorepo/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,SAAS,GACf,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,iBAAiB,GACvB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Monorepo support module.
3
+ *
4
+ * Provides detection, workspace discovery, and orchestration
5
+ * for auditing multi-package repositories.
6
+ */
7
+ export { detectMonorepo, getAuditableApps, } from "./detector.js";
8
+ export { auditWorkspace, generateMatrixConfig, aggregateResults, formatAggregatedResults, } from "./workspace.js";
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Workspace audit orchestration for monorepos.
3
+ *
4
+ * Handles running audits across multiple workspaces with
5
+ * proper isolation and result aggregation.
6
+ */
7
+ import type { Workspace } from "./detector.js";
8
+ /**
9
+ * Options for auditing a single workspace.
10
+ */
11
+ export interface WorkspaceAuditOptions {
12
+ /** Workspace to audit */
13
+ workspace: Workspace;
14
+ /** Override base URL (if not using workspace's inferred URL) */
15
+ baseUrl?: string;
16
+ /** Override port (if not using workspace's inferred port) */
17
+ port?: number;
18
+ /** Command to start the dev server */
19
+ startCommand?: string;
20
+ /** Timeout for server startup in ms */
21
+ startupTimeout?: number;
22
+ }
23
+ /**
24
+ * Audit result for a single workspace.
25
+ */
26
+ export interface AuditResult {
27
+ /** Job ID from audit API */
28
+ job_id?: string;
29
+ /** URL that was audited */
30
+ url?: string;
31
+ /** Audit status */
32
+ status?: string;
33
+ /** Issues found */
34
+ issues?: unknown[];
35
+ /** Scores */
36
+ scores?: Record<string, number>;
37
+ }
38
+ /**
39
+ * Result of auditing a workspace.
40
+ */
41
+ export interface WorkspaceResult {
42
+ /** The workspace that was audited */
43
+ workspace: Workspace;
44
+ /** Audit result if successful */
45
+ auditResult: AuditResult | null;
46
+ /** Error if audit failed */
47
+ error?: Error;
48
+ /** Duration of audit in milliseconds */
49
+ duration: number;
50
+ /** Whether cache was used */
51
+ cached?: boolean;
52
+ }
53
+ /**
54
+ * Matrix configuration for CI parallel execution.
55
+ */
56
+ export interface MatrixConfig {
57
+ include: Array<{
58
+ name: string;
59
+ path: string;
60
+ url?: string;
61
+ port?: number;
62
+ appType?: string;
63
+ }>;
64
+ }
65
+ /**
66
+ * Aggregated results from multiple workspace audits.
67
+ */
68
+ export interface AggregatedResults {
69
+ /** Total number of workspaces audited */
70
+ totalWorkspaces: number;
71
+ /** Number of successful audits */
72
+ successfulAudits: number;
73
+ /** Number of failed audits */
74
+ failedAudits: number;
75
+ /** Total issues across all workspaces */
76
+ totalIssues: number;
77
+ /** Issues by severity across all workspaces */
78
+ issuesBySeverity: {
79
+ error: number;
80
+ warning: number;
81
+ info: number;
82
+ };
83
+ /** Results per workspace */
84
+ workspaceResults: WorkspaceResult[];
85
+ /** Total duration in milliseconds */
86
+ totalDuration: number;
87
+ }
88
+ /**
89
+ * Audit a single workspace.
90
+ *
91
+ * If URL not provided, uses the workspace's inferred URL.
92
+ * In future versions, this could start the dev server automatically.
93
+ *
94
+ * @param options - Workspace audit options
95
+ * @returns WorkspaceResult with audit outcome
96
+ */
97
+ export declare function auditWorkspace(options: WorkspaceAuditOptions): Promise<WorkspaceResult>;
98
+ /**
99
+ * Generate matrix configuration for CI parallel execution.
100
+ *
101
+ * This generates a JSON structure suitable for GitHub Actions matrix strategy
102
+ * or similar CI systems that support parallel job execution.
103
+ *
104
+ * @param workspaces - List of workspaces to include in matrix
105
+ * @returns Matrix configuration object
106
+ *
107
+ * @example
108
+ * ```yaml
109
+ * # In GitHub Actions:
110
+ * jobs:
111
+ * detect-apps:
112
+ * runs-on: ubuntu-latest
113
+ * outputs:
114
+ * matrix: ${{ steps.detect.outputs.matrix }}
115
+ * steps:
116
+ * - id: detect
117
+ * run: echo "matrix=$(vertaa audit --detect-matrix --json)" >> $GITHUB_OUTPUT
118
+ *
119
+ * audit:
120
+ * needs: detect-apps
121
+ * strategy:
122
+ * matrix: ${{ fromJson(needs.detect-apps.outputs.matrix) }}
123
+ * steps:
124
+ * - run: vertaa audit --workspace ${{ matrix.name }}
125
+ * ```
126
+ */
127
+ export declare function generateMatrixConfig(workspaces: Workspace[]): MatrixConfig;
128
+ /**
129
+ * Aggregate results from multiple workspace audits.
130
+ *
131
+ * @param results - Array of workspace results
132
+ * @returns Aggregated results summary
133
+ */
134
+ export declare function aggregateResults(results: WorkspaceResult[]): AggregatedResults;
135
+ /**
136
+ * Format aggregated results for display.
137
+ *
138
+ * @param aggregated - Aggregated results
139
+ * @returns Formatted string for console output
140
+ */
141
+ export declare function formatAggregatedResults(aggregated: AggregatedResults): string;
142
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/monorepo/workspace.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,yBAAyB;IACzB,SAAS,EAAE,SAAS,CAAC;IACrB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB;IACnB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB,aAAa;IACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,iCAAiC;IACjC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,4BAA4B;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,6BAA6B;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,eAAe,EAAE,MAAM,CAAC;IACxB,kCAAkC;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,8BAA8B;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,gBAAgB,EAAE;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,4BAA4B;IAC5B,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,qCAAqC;IACrC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAkC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,YAAY,CAU1E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,iBAAiB,CA6C9E;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,iBAAiB,GAAG,MAAM,CAyC7E"}