@vizzly-testing/cli 0.39.1 → 0.39.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/README.md +8 -0
  2. package/bin/vizzly.js +1 -1
  3. package/dist/{cli.js → adapters/cli/cli.js} +41 -35
  4. package/dist/adapters/cli/setup.js +34 -0
  5. package/dist/{client → adapters/client}/index.js +6 -7
  6. package/dist/adapters/http/cloud-proxy.js +29 -0
  7. package/dist/{server → adapters/http}/http-server.js +12 -13
  8. package/dist/{server-manager/operations.js → adapters/http/server-lifecycle.js} +10 -13
  9. package/dist/{server-manager/index.js → adapters/http/server-manager.js} +23 -27
  10. package/dist/{plugin-api.js → adapters/plugins/plugin-api.js} +1 -1
  11. package/dist/{plugin-loader.js → adapters/plugins/plugin-loader.js} +1 -1
  12. package/dist/{services/index.js → adapters/plugins/services.js} +4 -9
  13. package/dist/adapters/sdk/index.d.ts +89 -0
  14. package/dist/{sdk → adapters/sdk}/index.js +22 -19
  15. package/dist/{commands/api.js → domains/api/api.commands.js} +3 -3
  16. package/dist/{auth/client.js → domains/auth/auth-client.js} +4 -3
  17. package/dist/domains/auth/auth-errors.js +50 -0
  18. package/dist/domains/auth/auth-headers.js +41 -0
  19. package/dist/domains/auth/auth.normalizers.js +50 -0
  20. package/dist/{server/routers/auth.js → domains/auth/auth.routes.js} +9 -9
  21. package/dist/domains/auth/auth.rules.js +19 -0
  22. package/dist/domains/auth/auth.serializers.js +32 -0
  23. package/dist/{auth/operations.js → domains/auth/auth.service.js} +115 -17
  24. package/dist/domains/auth/auth.validations.js +21 -0
  25. package/dist/{api/client.js → domains/auth/cloud-client.js} +11 -18
  26. package/dist/{commands/login.js → domains/auth/login.commands.js} +11 -8
  27. package/dist/{commands/logout.js → domains/auth/logout.commands.js} +6 -4
  28. package/dist/domains/auth/token-store.js +81 -0
  29. package/dist/{commands/whoami.js → domains/auth/whoami.commands.js} +6 -3
  30. package/dist/domains/baselines/baseline-download.js +192 -0
  31. package/dist/domains/baselines/baseline-write.js +22 -0
  32. package/dist/{server/routers/baseline.js → domains/baselines/baseline.routes.js} +3 -3
  33. package/dist/{tdd/services/baseline-manager.js → domains/baselines/baseline.service.js} +1 -39
  34. package/dist/{commands/baselines.js → domains/baselines/baselines.commands.js} +3 -3
  35. package/dist/domains/baselines/cloud-baselines.js +9 -0
  36. package/dist/domains/baselines/cloud-baselines.routes.js +42 -0
  37. package/dist/domains/builds/build.normalizers.js +35 -0
  38. package/dist/domains/builds/build.serializers.js +164 -0
  39. package/dist/domains/builds/build.service.js +119 -0
  40. package/dist/domains/builds/build.validations.js +39 -0
  41. package/dist/{commands/builds.js → domains/builds/builds.commands.js} +6 -74
  42. package/dist/domains/builds/cloud-builds.routes.js +31 -0
  43. package/dist/{commands/finalize.js → domains/builds/finalize.commands.js} +5 -17
  44. package/dist/{commands/status.js → domains/builds/status.commands.js} +9 -120
  45. package/dist/domains/comparisons/cloud-comparisons.js +43 -0
  46. package/dist/{tdd/services/comparison-service.js → domains/comparisons/comparison.service.js} +1 -1
  47. package/dist/{commands/comparisons.js → domains/comparisons/comparisons.commands.js} +7 -5
  48. package/dist/domains/config/config-defaults.js +27 -0
  49. package/dist/{utils → domains/config}/config-discovery.js +1 -9
  50. package/dist/{utils → domains/config}/config-loader.js +10 -9
  51. package/dist/{commands/config-cmd.js → domains/config/config.commands.js} +4 -4
  52. package/dist/{types → domains/config}/config.d.ts +3 -3
  53. package/dist/domains/config/config.normalizers.js +126 -0
  54. package/dist/{server/routers/config.js → domains/config/config.routes.js} +13 -13
  55. package/dist/domains/config/config.rules.js +47 -0
  56. package/dist/domains/config/config.serializers.js +202 -0
  57. package/dist/domains/config/config.service.js +625 -0
  58. package/dist/{utils/config-schema.js → domains/config/config.validations.js} +9 -9
  59. package/dist/{utils/environment-config.js → domains/config/environment.js} +1 -8
  60. package/dist/domains/context/compact-context.validations.js +60 -0
  61. package/dist/domains/context/context-presentation.js +368 -0
  62. package/dist/domains/context/context.commands.js +385 -0
  63. package/dist/domains/context/context.serializers.js +157 -0
  64. package/dist/domains/context/context.service.js +76 -0
  65. package/dist/domains/context/context.validations.js +100 -0
  66. package/dist/{context → domains/context}/local-workspace-provider.js +1 -1
  67. package/dist/{commands/doctor.js → domains/diagnostics/doctor.commands.js} +6 -5
  68. package/dist/{server/routers/health.js → domains/diagnostics/health.routes.js} +11 -20
  69. package/dist/{commands/preview.js → domains/previews/preview.commands.js} +9 -7
  70. package/dist/domains/previews/preview.service.js +37 -0
  71. package/dist/domains/projects/cloud-projects.routes.js +28 -0
  72. package/dist/{commands/orgs.js → domains/projects/orgs.commands.js} +6 -8
  73. package/dist/{utils → domains/projects}/project-binding.js +3 -3
  74. package/dist/domains/projects/project-errors.js +61 -0
  75. package/dist/{utils → domains/projects}/project-link-store.js +2 -2
  76. package/dist/domains/projects/project-requests.js +61 -0
  77. package/dist/{commands/project.js → domains/projects/project.commands.js} +9 -41
  78. package/dist/domains/projects/project.normalizers.js +69 -0
  79. package/dist/{project/operations.js → domains/projects/project.service.js} +89 -16
  80. package/dist/domains/projects/project.validations.js +31 -0
  81. package/dist/{commands/projects.js → domains/projects/projects.commands.js} +6 -8
  82. package/dist/{server/routers/projects.js → domains/projects/projects.routes.js} +5 -5
  83. package/dist/domains/reports/dashboard.routes.js +96 -0
  84. package/dist/{server/routers/events.js → domains/reports/events.routes.js} +14 -36
  85. package/dist/domains/reports/report-assets.routes.js +81 -0
  86. package/dist/domains/reports/report-state.js +51 -0
  87. package/dist/domains/reports/report-store.js +85 -0
  88. package/dist/domains/reports/report.serializers.js +99 -0
  89. package/dist/{services/static-report-generator.js → domains/reports/report.service.js} +11 -33
  90. package/dist/{commands/review.js → domains/review/review.commands.js} +4 -4
  91. package/dist/domains/runs/run-environment.js +69 -0
  92. package/dist/{services/test-runner.js → domains/runs/run-events.js} +11 -9
  93. package/dist/{commands/run.js → domains/runs/run.commands.js} +16 -13
  94. package/dist/domains/runs/run.normalizers.js +8 -0
  95. package/dist/domains/runs/run.rules.js +56 -0
  96. package/dist/domains/runs/run.serializers.js +101 -0
  97. package/dist/{test-runner/operations.js → domains/runs/run.service.js} +35 -7
  98. package/dist/domains/runs/run.validations.js +17 -0
  99. package/dist/{utils/session.js → domains/runs/session-store.js} +3 -2
  100. package/dist/{server/handlers/api-handler.js → domains/screenshots/cloud-handler.js} +4 -4
  101. package/dist/domains/screenshots/cloud-screenshots.js +109 -0
  102. package/dist/{utils/file-helpers.js → domains/screenshots/image-files.js} +1 -1
  103. package/dist/domains/screenshots/screenshot-hash.js +53 -0
  104. package/dist/domains/screenshots/screenshot-server-options.js +28 -0
  105. package/dist/{screenshot-server/operations.js → domains/screenshots/screenshot-server.js} +14 -1
  106. package/dist/domains/screenshots/screenshot.normalizers.js +40 -0
  107. package/dist/{server/routers/screenshot.js → domains/screenshots/screenshot.routes.js} +4 -4
  108. package/dist/domains/screenshots/screenshot.serializers.js +146 -0
  109. package/dist/{utils/security.js → domains/screenshots/screenshot.validations.js} +20 -70
  110. package/dist/{init/agents.js → domains/setup/agent-setup.js} +4 -5
  111. package/dist/{commands/init.js → domains/setup/init.commands.js} +10 -41
  112. package/dist/{server/handlers/tdd-handler.js → domains/tdd/screenshot-handler.js} +46 -281
  113. package/dist/{commands/tdd-daemon.js → domains/tdd/tdd-daemon.commands.js} +6 -6
  114. package/dist/{commands/tdd-screenshots.js → domains/tdd/tdd-screenshots.commands.js} +5 -5
  115. package/dist/{commands/tdd.js → domains/tdd/tdd.commands.js} +16 -15
  116. package/dist/{tdd/tdd-service.js → domains/tdd/tdd.service.js} +81 -405
  117. package/dist/{utils → domains/updates}/cli-update.js +4 -6
  118. package/dist/{utils → domains/updates}/update-notifications.js +7 -7
  119. package/dist/domains/uploads/upload-defaults.js +4 -0
  120. package/dist/domains/uploads/upload-files.js +32 -0
  121. package/dist/domains/uploads/upload-settings.js +21 -0
  122. package/dist/domains/uploads/upload-timing.js +18 -0
  123. package/dist/{commands/upload.js → domains/uploads/upload.commands.js} +11 -9
  124. package/dist/domains/uploads/upload.normalizers.js +60 -0
  125. package/dist/domains/uploads/upload.serializers.js +179 -0
  126. package/dist/{uploader/operations.js → domains/uploads/upload.service.js} +85 -28
  127. package/dist/domains/uploads/upload.validations.js +77 -0
  128. package/dist/index.js +12 -12
  129. package/dist/reporter/reporter-bundle.iife.js +86 -86
  130. package/dist/reporter-ssr/ssr-entry.js +2 -2
  131. package/dist/shared/cloud-protocol.js +171 -0
  132. package/dist/{utils → shared}/file-changes.js +1 -1
  133. package/dist/shared/files.js +9 -0
  134. package/dist/{utils → shared}/global-config.js +7 -78
  135. package/dist/shared/log-level.js +7 -0
  136. package/dist/{utils → shared}/output.js +1 -1
  137. package/dist/{utils → shared}/package-info.js +5 -4
  138. package/dist/shared/paths.js +57 -0
  139. package/package.json +23 -22
  140. package/dist/api/core.js +0 -382
  141. package/dist/api/endpoints.js +0 -421
  142. package/dist/api/index.js +0 -19
  143. package/dist/auth/core.js +0 -237
  144. package/dist/auth/index.js +0 -31
  145. package/dist/commands/context.js +0 -1066
  146. package/dist/config/core.js +0 -439
  147. package/dist/config/operations.js +0 -327
  148. package/dist/project/core.js +0 -211
  149. package/dist/screenshot-server/core.js +0 -161
  150. package/dist/screenshot-server/index.js +0 -11
  151. package/dist/server/routers/assets.js +0 -95
  152. package/dist/server/routers/cloud-proxy.js +0 -146
  153. package/dist/server/routers/dashboard.js +0 -172
  154. package/dist/services/auth-service.js +0 -117
  155. package/dist/services/config-service.js +0 -313
  156. package/dist/services/project-service.js +0 -88
  157. package/dist/test-runner/core.js +0 -293
  158. package/dist/test-runner/index.js +0 -13
  159. package/dist/types/sdk.d.ts +0 -186
  160. package/dist/uploader/core.js +0 -432
  161. package/dist/uploader/index.js +0 -88
  162. /package/dist/{types/client.d.ts → adapters/client/index.d.ts} +0 -0
  163. /package/dist/{server → adapters/http}/middleware/cors.js +0 -0
  164. /package/dist/{server → adapters/http}/middleware/json-parser.js +0 -0
  165. /package/dist/{server → adapters/http}/middleware/response.js +0 -0
  166. /package/dist/{server-manager/core.js → adapters/http/server-options.js} +0 -0
  167. /package/dist/{utils/login-poll-wait.js → domains/auth/login-wait.js} +0 -0
  168. /package/dist/{tdd/metadata → domains/baselines}/baseline-metadata.js +0 -0
  169. /package/dist/{services/build-manager.js → domains/builds/build-info.js} +0 -0
  170. /package/dist/{tdd/services/result-service.js → domains/comparisons/comparison-results.js} +0 -0
  171. /package/dist/{init/core.js → domains/config/config-plan.js} +0 -0
  172. /package/dist/{utils/config-helpers.js → domains/config/config.js} +0 -0
  173. /package/dist/{utils/visual-context-normalizers.js → domains/context/context.normalizers.js} +0 -0
  174. /package/dist/{context → domains/context}/provider-resolver.js +0 -0
  175. /package/dist/{utils/context.js → domains/diagnostics/environment-context.js} +0 -0
  176. /package/dist/{utils/report-data.js → domains/reports/report.normalizers.js} +0 -0
  177. /package/dist/{utils/image-input-detector.js → domains/screenshots/image-input.js} +0 -0
  178. /package/dist/{tdd/core/signature.js → domains/screenshots/screenshot-identity.js} +0 -0
  179. /package/dist/{utils → domains/screenshots}/screenshot-options.js +0 -0
  180. /package/dist/{init/prompts.js → domains/setup/setup-prompts.js} +0 -0
  181. /package/dist/{tdd → domains/tdd}/runtime-context.js +0 -0
  182. /package/dist/{tdd → domains/tdd}/server-registry.js +0 -0
  183. /package/dist/{commands/tdd-daemon-process.js → domains/tdd/tdd-daemon-process.commands.js} +0 -0
  184. /package/dist/{utils → domains/updates}/update-check.js +0 -0
  185. /package/dist/{types/index.d.ts → index.d.ts} +0 -0
  186. /package/dist/{utils → shared}/api-url.js +0 -0
  187. /package/dist/{utils → shared}/async-utils.js +0 -0
  188. /package/dist/{utils → shared}/browser.js +0 -0
  189. /package/dist/{utils → shared}/ci-env.js +0 -0
  190. /package/dist/{utils → shared}/colors.js +0 -0
  191. /package/dist/{utils → shared}/fetch-utils.js +0 -0
  192. /package/dist/{utils → shared}/git.js +0 -0
  193. /package/dist/{utils → shared}/patterns.js +0 -0
  194. /package/dist/{utils → shared}/secret-store.js +0 -0
  195. /package/dist/{errors → shared}/vizzly-error.js +0 -0
package/README.md CHANGED
@@ -298,6 +298,14 @@ with `pnpm exec` when Vizzly is installed locally.
298
298
  Installed plugins add commands such as `storybook`, `static-site`, and `previews`.
299
299
  See their setup guides above for details.
300
300
 
301
+ ## Contributing
302
+
303
+ Start in `src/domains/<domain>/` for CLI behavior or
304
+ `src/reporter/src/domains/<domain>/` for reporter UI. The
305
+ [architecture guide](docs/architecture.md) explains ownership, file roles, and
306
+ the shared runtime boundaries. Run `pnpm run check:architecture` when changing
307
+ source organization or imports.
308
+
301
309
  ## More
302
310
 
303
311
  [Full docs](https://docs.vizzly.dev) ·
package/bin/vizzly.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import '../dist/cli.js';
3
+ import '../dist/adapters/cli/cli.js';
@@ -2,41 +2,45 @@
2
2
  import 'dotenv/config';
3
3
  import { existsSync, statSync } from 'node:fs';
4
4
  import { Option, program } from 'commander';
5
- import { apiCommand, apiSchemaCommand, validateApiOptions } from './commands/api.js';
6
- import { baselinesCommand } from './commands/baselines.js';
7
- import { buildsCommand, validateBuildsOptions } from './commands/builds.js';
8
- import { comparisonsCommand, validateComparisonsOptions } from './commands/comparisons.js';
9
- import { configCommand } from './commands/config-cmd.js';
10
- import { contextBuildCommand, contextComparisonCommand, contextReviewQueueCommand, contextScreenshotCommand, contextSimilarCommand, validateContextBuildOptions, validateContextComparisonOptions, validateContextReviewQueueOptions, validateContextScreenshotOptions, validateContextSimilarOptions } from './commands/context.js';
11
- import { doctorCommand } from './commands/doctor.js';
12
- import { finalizeCommand, validateFinalizeOptions } from './commands/finalize.js';
13
- import { init } from './commands/init.js';
14
- import { loginCommand } from './commands/login.js';
15
- import { logoutCommand } from './commands/logout.js';
16
- import { orgsCommand } from './commands/orgs.js';
17
- import { previewCommand, validatePreviewOptions } from './commands/preview.js';
18
- import { projectLinkCommand, validateProjectLinkOptions } from './commands/project.js';
19
- import { projectsCommand, validateProjectsOptions } from './commands/projects.js';
20
- import { approveCommand, commentCommand, rejectCommand, validateApproveOptions, validateCommentOptions, validateRejectOptions } from './commands/review.js';
21
- import { runCommand, validateRunOptions } from './commands/run.js';
22
- import { statusCommand, validateStatusOptions } from './commands/status.js';
23
- import { tddCommand, validateTddOptions } from './commands/tdd.js';
24
- import { runDaemonChild, tddListCommand, tddStartCommand, tddStatusCommand, tddStopCommand, validateTddStartOptions } from './commands/tdd-daemon.js';
25
- import { acceptTddScreenshot, latestTddScreenshot, listTddScreenshots, showTddScreenshot } from './commands/tdd-screenshots.js';
26
- import { uploadCommand, validateUploadOptions } from './commands/upload.js';
27
- import { whoamiCommand } from './commands/whoami.js';
28
- import { createPluginServices } from './plugin-api.js';
29
- import { loadPlugins } from './plugin-loader.js';
30
- import { createServices } from './services/index.js';
31
- import { withTimeout } from './utils/async-utils.js';
32
- import { runUpdatedCli } from './utils/cli-update.js';
33
- import { colors } from './utils/colors.js';
34
- import { loadConfig } from './utils/config-loader.js';
35
- import { getContext } from './utils/context.js';
36
- import { saveUserPath } from './utils/global-config.js';
37
- import * as output from './utils/output.js';
38
- import { getPackageVersion } from './utils/package-info.js';
39
- import { notifyUpdates } from './utils/update-notifications.js';
5
+ import { apiCommand, apiSchemaCommand, validateApiOptions } from '../../domains/api/api.commands.js';
6
+ import { loginCommand } from '../../domains/auth/login.commands.js';
7
+ import { logoutCommand } from '../../domains/auth/logout.commands.js';
8
+ import { whoamiCommand } from '../../domains/auth/whoami.commands.js';
9
+ import { baselinesCommand } from '../../domains/baselines/baselines.commands.js';
10
+ import { validateBuildsOptions, validateFinalizeOptions, validateStatusOptions } from '../../domains/builds/build.validations.js';
11
+ import { buildsCommand } from '../../domains/builds/builds.commands.js';
12
+ import { finalizeCommand } from '../../domains/builds/finalize.commands.js';
13
+ import { statusCommand } from '../../domains/builds/status.commands.js';
14
+ import { comparisonsCommand, validateComparisonsOptions } from '../../domains/comparisons/comparisons.commands.js';
15
+ import { configCommand } from '../../domains/config/config.commands.js';
16
+ import { loadConfig } from '../../domains/config/config-loader.js';
17
+ import { contextBuildCommand, contextComparisonCommand, contextReviewQueueCommand, contextScreenshotCommand, contextSimilarCommand } from '../../domains/context/context.commands.js';
18
+ import { validateContextBuildOptions, validateContextComparisonOptions, validateContextReviewQueueOptions, validateContextScreenshotOptions, validateContextSimilarOptions } from '../../domains/context/context.validations.js';
19
+ import { doctorCommand } from '../../domains/diagnostics/doctor.commands.js';
20
+ import { getContext } from '../../domains/diagnostics/environment-context.js';
21
+ import { previewCommand, validatePreviewOptions } from '../../domains/previews/preview.commands.js';
22
+ import { orgsCommand } from '../../domains/projects/orgs.commands.js';
23
+ import { projectLinkCommand } from '../../domains/projects/project.commands.js';
24
+ import { validateProjectLinkOptions } from '../../domains/projects/project.validations.js';
25
+ import { projectsCommand, validateProjectsOptions } from '../../domains/projects/projects.commands.js';
26
+ import { approveCommand, commentCommand, rejectCommand, validateApproveOptions, validateCommentOptions, validateRejectOptions } from '../../domains/review/review.commands.js';
27
+ import { runCommand, validateRunOptions } from '../../domains/runs/run.commands.js';
28
+ import { init } from '../../domains/setup/init.commands.js';
29
+ import { tddCommand, validateTddOptions } from '../../domains/tdd/tdd.commands.js';
30
+ import { runDaemonChild, tddListCommand, tddStartCommand, tddStatusCommand, tddStopCommand, validateTddStartOptions } from '../../domains/tdd/tdd-daemon.commands.js';
31
+ import { acceptTddScreenshot, latestTddScreenshot, listTddScreenshots, showTddScreenshot } from '../../domains/tdd/tdd-screenshots.commands.js';
32
+ import { runUpdatedCli } from '../../domains/updates/cli-update.js';
33
+ import { notifyUpdates } from '../../domains/updates/update-notifications.js';
34
+ import { uploadCommand, validateUploadOptions } from '../../domains/uploads/upload.commands.js';
35
+ import { withTimeout } from '../../shared/async-utils.js';
36
+ import { colors } from '../../shared/colors.js';
37
+ import { saveUserPath } from '../../shared/global-config.js';
38
+ import * as output from '../../shared/output.js';
39
+ import { getPackageVersion } from '../../shared/package-info.js';
40
+ import { createPluginServices } from '../plugins/plugin-api.js';
41
+ import { loadPlugins } from '../plugins/plugin-loader.js';
42
+ import { createServices } from '../plugins/services.js';
43
+ import { connectProject } from './setup.js';
40
44
 
41
45
  // Custom help formatting with BearDen design system
42
46
  const formatHelp = (cmd, helper) => {
@@ -471,6 +475,8 @@ program.command('init').description('Initialize Vizzly in your project').option(
471
475
  let result = await init({
472
476
  ...globalOptions,
473
477
  ...options
478
+ }, {
479
+ connectProject
474
480
  });
475
481
  process.exitCode = result.exitCode || 0;
476
482
  } catch (error) {
@@ -0,0 +1,34 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { fileURLToPath } from 'node:url';
3
+ import { projectLinkCommand } from '../../domains/projects/project.commands.js';
4
+ function runProcess(command, args) {
5
+ return new Promise((resolve, reject) => {
6
+ let child = spawn(command, args, {
7
+ stdio: 'inherit'
8
+ });
9
+ child.once('error', reject);
10
+ child.once('close', (code, signal) => {
11
+ if (code === 0) resolve();else reject(new Error(`${command} did not finish successfully (${signal || code}).`));
12
+ });
13
+ });
14
+ }
15
+ export async function connectProject(project, options) {
16
+ let exitCode = 0;
17
+ let link = () => projectLinkCommand(project, {}, options, {
18
+ exit: code => {
19
+ exitCode = code;
20
+ }
21
+ });
22
+ let result = await link();
23
+ if (result?.reason === 'auth_required') {
24
+ let cli = fileURLToPath(new URL('./cli.js', import.meta.url));
25
+ await runProcess(process.execPath, [cli, 'login']);
26
+ result = await link();
27
+ }
28
+ let status = result?.linked ? 'linked' : 'failed';
29
+ if (!result?.linked && exitCode === 1) status = 'auth_required';
30
+ return {
31
+ status,
32
+ project
33
+ };
34
+ }
@@ -7,8 +7,9 @@ import { existsSync, readFileSync } from 'node:fs';
7
7
  import { request as httpRequest } from 'node:http';
8
8
  import { request as httpsRequest } from 'node:https';
9
9
  import { dirname, join, parse } from 'node:path';
10
- import { getBuildId, getServerUrl, isTddMode, setVizzlyEnabled } from '../utils/environment-config.js';
11
- import { getScreenshotOptionsPayload, normalizeScreenshotOptions } from '../utils/screenshot-options.js';
10
+ import { getBuildId, getServerUrl, isTddMode, setVizzlyEnabled } from '../../domains/config/environment.js';
11
+ import { serializeScreenshotRequest } from '../../domains/screenshots/screenshot.serializers.js';
12
+ import { normalizeScreenshotOptions } from '../../domains/screenshots/screenshot-options.js';
12
13
 
13
14
  // Internal client state
14
15
  let currentClient = null;
@@ -209,14 +210,12 @@ function createSimpleClient(serverUrl, clientOptions = {}) {
209
210
  let isFilePath = typeof imageBuffer === 'string';
210
211
  let image = isFilePath ? imageBuffer : imageBuffer.toString('base64');
211
212
  let type = isFilePath ? 'file-path' : 'base64';
212
- let screenshotData = {
213
+ let screenshotData = serializeScreenshotRequest({
213
214
  buildId: normalizedOptions.buildId ?? getBuildId(),
214
215
  name,
215
216
  image,
216
- type,
217
- properties: normalizedOptions.properties
218
- };
219
- Object.assign(screenshotData, getScreenshotOptionsPayload(normalizedOptions));
217
+ type
218
+ }, normalizedOptions);
220
219
  let httpStart = Date.now();
221
220
  let {
222
221
  status,
@@ -0,0 +1,29 @@
1
+ import { createCloudBaselinesRouter } from '../../domains/baselines/cloud-baselines.routes.js';
2
+ import { createCloudBuildsRouter } from '../../domains/builds/cloud-builds.routes.js';
3
+ import { createCloudProjectsRouter } from '../../domains/projects/cloud-projects.routes.js';
4
+ import { sendError, sendServiceUnavailable } from './middleware/response.js';
5
+ export function createCloudProxyRouter({
6
+ authService
7
+ }) {
8
+ let projects = createCloudProjectsRouter({
9
+ authService
10
+ });
11
+ let builds = createCloudBuildsRouter({
12
+ authService
13
+ });
14
+ let baselines = createCloudBaselinesRouter({
15
+ authService
16
+ });
17
+ return async function handleCloudProxyRoute(req, res, pathname, parsedUrl) {
18
+ if (!pathname.startsWith('/api/cloud')) return false;
19
+ if (!authService) {
20
+ sendServiceUnavailable(res, 'Auth service');
21
+ return true;
22
+ }
23
+ if (await projects(req, res, pathname)) return true;
24
+ if (await builds(req, res, pathname, parsedUrl)) return true;
25
+ if (await baselines(req, res, pathname)) return true;
26
+ sendError(res, 404, 'Cloud API endpoint not found');
27
+ return true;
28
+ };
29
+ }
@@ -4,22 +4,21 @@
4
4
  */
5
5
 
6
6
  import { createServer } from 'node:http';
7
- import * as output from '../utils/output.js';
8
-
7
+ import { createAuthRouter } from '../../domains/auth/auth.routes.js';
8
+ import { createBaselineRouter } from '../../domains/baselines/baseline.routes.js';
9
+ import { createConfigRouter } from '../../domains/config/config.routes.js';
10
+ // Routers
11
+ import { createHealthRouter } from '../../domains/diagnostics/health.routes.js';
12
+ import { createProjectsRouter } from '../../domains/projects/projects.routes.js';
13
+ import { createDashboardRouter } from '../../domains/reports/dashboard.routes.js';
14
+ import { createEventsRouter } from '../../domains/reports/events.routes.js';
15
+ import { createAssetsRouter } from '../../domains/reports/report-assets.routes.js';
16
+ import { createScreenshotRouter } from '../../domains/screenshots/screenshot.routes.js';
17
+ import * as output from '../../shared/output.js';
18
+ import { createCloudProxyRouter } from './cloud-proxy.js';
9
19
  // Middleware
10
20
  import { corsMiddleware } from './middleware/cors.js';
11
21
  import { sendError } from './middleware/response.js';
12
- import { createAssetsRouter } from './routers/assets.js';
13
- import { createAuthRouter } from './routers/auth.js';
14
- import { createBaselineRouter } from './routers/baseline.js';
15
- import { createCloudProxyRouter } from './routers/cloud-proxy.js';
16
- import { createConfigRouter } from './routers/config.js';
17
- import { createDashboardRouter } from './routers/dashboard.js';
18
- import { createEventsRouter } from './routers/events.js';
19
- // Routers
20
- import { createHealthRouter } from './routers/health.js';
21
- import { createProjectsRouter } from './routers/projects.js';
22
- import { createScreenshotRouter } from './routers/screenshot.js';
23
22
  export const createHttpServer = (port, screenshotHandler, services = {}) => {
24
23
  let server = null;
25
24
  const defaultBuildId = services.buildId || null;
@@ -11,7 +11,7 @@
11
11
  * This makes them trivially testable without mocking modules.
12
12
  */
13
13
 
14
- import { buildServerInfo, buildServerJsonPaths, buildServicesWithExtras, determineHandlerMode, getPort } from './core.js';
14
+ import { buildServerInfo, buildServerJsonPaths, buildServicesWithExtras, determineHandlerMode, getPort } from './server-options.js';
15
15
 
16
16
  // ============================================================================
17
17
  // Server Lifecycle Operations
@@ -114,22 +114,19 @@ export async function stopServer({
114
114
  let {
115
115
  fs
116
116
  } = deps;
117
- if (httpServer) {
118
- await httpServer.stop();
119
- }
120
- if (handler?.cleanup) {
117
+ try {
118
+ await httpServer?.stop();
119
+ } finally {
121
120
  try {
122
- handler.cleanup();
121
+ await handler?.cleanup?.();
123
122
  } catch {
124
- // Don't throw - cleanup errors shouldn't fail the stop process
123
+ // Preserve the HTTP shutdown error when handler cleanup also fails.
125
124
  }
125
+ removeServerJson({
126
+ projectRoot,
127
+ fs
128
+ });
126
129
  }
127
-
128
- // Clean up server.json
129
- removeServerJson({
130
- projectRoot,
131
- fs
132
- });
133
130
  }
134
131
 
135
132
  // ============================================================================
@@ -1,24 +1,12 @@
1
- /**
2
- * Server Manager Module - Public exports
3
- *
4
- * Provides functional server management primitives:
5
- * - core.js: Pure functions for building server info, configs, interfaces
6
- * - operations.js: Server operations with dependency injection
7
- */
1
+ /** Screenshot server composition and lifecycle interface. */
8
2
 
9
3
  import { existsSync, mkdirSync, unlinkSync, writeFileSync } from 'node:fs';
10
- import { createApiClient } from '../api/index.js';
11
- import { createApiHandler } from '../server/handlers/api-handler.js';
12
- import { createTddHandler } from '../server/handlers/tdd-handler.js';
13
- import { createHttpServer } from '../server/http-server.js';
14
-
15
- // Core pure functions
16
- import { buildServerInterface } from './core.js';
17
- export { buildClientOptions, buildServerInfo, buildServerInterface, buildServerJsonPaths, buildServicesWithExtras, DEFAULT_PORT, determineHandlerMode, getPort, hasApiKey } from './core.js';
18
-
19
- // Server operations (take dependencies as parameters)
20
- import { getTddResults, startServer, stopServer } from './operations.js';
21
- export { getTddResults, removeServerJson, startServer, stopServer, writeServerJson } from './operations.js';
4
+ import { createApiClient } from '../../domains/auth/cloud-client.js';
5
+ import { createApiHandler } from '../../domains/screenshots/cloud-handler.js';
6
+ import { createTddHandler } from '../../domains/tdd/screenshot-handler.js';
7
+ import { createHttpServer } from './http-server.js';
8
+ import { getTddResults, startServer, stopServer } from './server-lifecycle.js';
9
+ import { buildServerInterface } from './server-options.js';
22
10
 
23
11
  /**
24
12
  * Create a server manager object that provides the interface commands expect.
@@ -26,9 +14,12 @@ export { getTddResults, removeServerJson, startServer, stopServer, writeServerJs
26
14
  *
27
15
  * @param {Object} config - Configuration object
28
16
  * @param {Object} [services={}] - Optional services object
17
+ * @param {Object} [options={}] - Runtime paths
18
+ * @param {string} [options.projectRoot] - Workspace for capture and discovery files
29
19
  * @returns {Object} Server manager with start/stop/getTddResults methods
30
20
  */
31
- export function createServerManager(config, services = {}) {
21
+ export function createServerManager(config, services = {}, options = {}) {
22
+ let projectRoot = options.projectRoot || process.cwd();
32
23
  let httpServer = null;
33
24
  let handler = null;
34
25
  let deps = {
@@ -50,7 +41,7 @@ export function createServerManager(config, services = {}) {
50
41
  buildId,
51
42
  tddMode,
52
43
  setBaseline,
53
- projectRoot: process.cwd(),
44
+ projectRoot,
54
45
  services,
55
46
  deps
56
47
  });
@@ -58,12 +49,17 @@ export function createServerManager(config, services = {}) {
58
49
  handler = result.handler;
59
50
  },
60
51
  async stop() {
61
- await stopServer({
62
- httpServer,
63
- handler,
64
- projectRoot: process.cwd(),
65
- deps
66
- });
52
+ try {
53
+ await stopServer({
54
+ httpServer,
55
+ handler,
56
+ projectRoot,
57
+ deps
58
+ });
59
+ } finally {
60
+ httpServer = null;
61
+ handler = null;
62
+ }
67
63
  },
68
64
  async getTddResults() {
69
65
  return getTddResults({
@@ -9,7 +9,7 @@
9
9
  * exposed to plugins to prevent coupling to implementation details.
10
10
  */
11
11
 
12
- import { detectBranch, detectCommit, detectCommitMessage, detectPullRequestNumber, generateBuildNameWithGit } from './utils/git.js';
12
+ import { detectBranch, detectCommit, detectCommitMessage, detectPullRequestNumber, generateBuildNameWithGit } from '../../shared/git.js';
13
13
 
14
14
  /**
15
15
  * Creates a stable plugin services object from the internal services
@@ -3,7 +3,7 @@ import { dirname, isAbsolute, relative, resolve, sep } from 'node:path';
3
3
  import { pathToFileURL } from 'node:url';
4
4
  import { glob } from 'glob';
5
5
  import { z } from 'zod';
6
- import * as output from './utils/output.js';
6
+ import * as output from '../../shared/output.js';
7
7
 
8
8
  /**
9
9
  * Load and register plugins from node_modules and config
@@ -1,16 +1,11 @@
1
1
  /**
2
2
  * Service Factory
3
- * Creates services for plugin API compatibility.
4
- *
5
- * Internal commands now use functional modules directly:
6
- * - API: import { createApiClient, getBuild } from '../api/index.js'
7
- * - Auth: import { createAuthClient, whoami } from '../auth/index.js'
8
- *
9
- * This factory is only used by cli.js to provide services to plugins.
3
+ * Assembles the execution and screenshot-server interfaces consumed by plugins.
4
+ * Commands import their domain operations directly.
10
5
  */
11
6
 
12
- import { createServerManager } from '../server-manager/index.js';
13
- import { TestRunner } from './test-runner.js';
7
+ import { TestRunner } from '../../domains/runs/run-events.js';
8
+ import { createServerManager } from '../http/server-manager.js';
14
9
 
15
10
  /**
16
11
  * Create services for plugin API compatibility.
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Vizzly SDK Type Definitions
3
+ * Full SDK for custom integrations
4
+ * @module @vizzly-testing/cli/sdk
5
+ */
6
+
7
+ // Re-export common types
8
+ /**
9
+ * VizzlySDK class - Full SDK for custom integrations
10
+ *
11
+ * @example
12
+ * import { createVizzly } from '@vizzly-testing/cli/sdk';
13
+ *
14
+ * const vizzly = await createVizzly({
15
+ * apiKey: process.env.VIZZLY_TOKEN,
16
+ * server: { port: 3003 }
17
+ * });
18
+ *
19
+ * await vizzly.start();
20
+ * await vizzly.screenshot('test', buffer);
21
+ * await vizzly.upload();
22
+ * await vizzly.stop();
23
+ */
24
+ export {
25
+ BaselineData,
26
+ ComparisonResult,
27
+ OutputUtils,
28
+ ScreenshotOptions,
29
+ TddResults,
30
+ TddService,
31
+ Uploader,
32
+ UploadOptions,
33
+ UploadResult,
34
+ VizzlyConfig,
35
+ VizzlySDK,
36
+ } from '../../index';
37
+
38
+ /**
39
+ * Create a new Vizzly SDK instance
40
+ *
41
+ * @param config - Configuration options
42
+ * @param options - Additional options
43
+ * @returns Configured Vizzly SDK instance
44
+ *
45
+ * @example
46
+ * const vizzly = await createVizzly({
47
+ * apiKey: process.env.VIZZLY_TOKEN,
48
+ * apiUrl: 'https://app.vizzly.dev',
49
+ * server: { port: 3003 }
50
+ * });
51
+ */
52
+ export function createVizzly(
53
+ config?: import('../../index').VizzlyConfig,
54
+ options?: { verbose?: boolean }
55
+ ): Promise<import('../../index').VizzlySDK>;
56
+
57
+ /** Load configuration from file and environment */
58
+ export function loadConfig(options?: {
59
+ cwd?: string;
60
+ }): Promise<import('../../index').VizzlyConfig>;
61
+
62
+ /** Output utilities */
63
+ export const output: import('../../index').OutputUtils;
64
+
65
+ /** Create an uploader instance */
66
+ export function createUploader(
67
+ config?: {
68
+ apiKey?: string;
69
+ apiUrl?: string;
70
+ userAgent?: string;
71
+ command?: string;
72
+ upload?: import('../../index').UploadConfig;
73
+ },
74
+ options?: {
75
+ signal?: AbortSignal;
76
+ batchSize?: number;
77
+ timeout?: number;
78
+ }
79
+ ): import('../../index').Uploader;
80
+
81
+ /** Create a TDD service instance */
82
+ export function createTDDService(
83
+ config: import('../../index').VizzlyConfig,
84
+ options?: {
85
+ workingDir?: string;
86
+ setBaseline?: boolean;
87
+ authService?: unknown;
88
+ }
89
+ ): import('../../index').TddService;
@@ -12,14 +12,15 @@
12
12
 
13
13
  import { EventEmitter } from 'node:events';
14
14
  import { createServer } from 'node:http';
15
- import { VizzlyError } from '../errors/vizzly-error.js';
16
- import { handleRequest as handleScreenshotRequest, startServer as startScreenshotServer, stopServer as stopScreenshotServer } from '../screenshot-server/index.js';
17
- import { createTDDService } from '../tdd/tdd-service.js';
18
- import { createUploader } from '../uploader/index.js';
19
- import { loadConfig } from '../utils/config-loader.js';
20
- import { resolveImageBuffer } from '../utils/file-helpers.js';
21
- import * as output from '../utils/output.js';
22
- import { getScreenshotOptionsPayload, normalizeScreenshotOptions } from '../utils/screenshot-options.js';
15
+ import { loadConfig } from '../../domains/config/config-loader.js';
16
+ import { resolveImageBuffer } from '../../domains/screenshots/image-files.js';
17
+ import { serializeScreenshotRequest } from '../../domains/screenshots/screenshot.serializers.js';
18
+ import { normalizeScreenshotOptions } from '../../domains/screenshots/screenshot-options.js';
19
+ import { handleRequest as handleScreenshotRequest, startServer as startScreenshotServer, stopServer as stopScreenshotServer } from '../../domains/screenshots/screenshot-server.js';
20
+ import { createTDDService } from '../../domains/tdd/tdd.service.js';
21
+ import { createUploader } from '../../domains/uploads/upload.service.js';
22
+ import * as output from '../../shared/output.js';
23
+ import { VizzlyError } from '../../shared/vizzly-error.js';
23
24
 
24
25
  /**
25
26
  * Create a new Vizzly instance with custom configuration
@@ -248,7 +249,10 @@ export class VizzlySDK extends EventEmitter {
248
249
  }
249
250
  async startTDD(options = {}) {
250
251
  let tddService = this.createTDDService(options);
251
- return tddService.start(options);
252
+ tddService.clearRunData();
253
+ await tddService.loadBaseline();
254
+ this.services.tddService = tddService;
255
+ return tddService;
252
256
  }
253
257
 
254
258
  /**
@@ -301,14 +305,12 @@ export class VizzlySDK extends EventEmitter {
301
305
 
302
306
  // Convert Buffer to base64 for JSON transport
303
307
  let imageBase64 = buffer.toString('base64');
304
- let screenshotData = {
308
+ let screenshotData = serializeScreenshotRequest({
305
309
  buildId,
306
310
  name,
307
311
  image: imageBase64,
308
- type: 'base64',
309
- properties: normalizedOptions.properties
310
- };
311
- Object.assign(screenshotData, getScreenshotOptionsPayload(normalizedOptions));
312
+ type: 'base64'
313
+ }, normalizedOptions);
312
314
  // POST to the local screenshot server
313
315
  let serverUrl = `http://localhost:${this.config.server?.port || 3000}`;
314
316
  let fetchFn = this.services.fetch || fetch;
@@ -419,9 +421,10 @@ export class VizzlySDK extends EventEmitter {
419
421
  }
420
422
  }
421
423
  }
422
- export { createTDDService } from '../tdd/tdd-service.js';
423
- // Export service creators for advanced usage
424
- export { createUploader } from '../uploader/index.js';
424
+
425
425
  // Re-export key utilities and errors
426
- export { loadConfig } from '../utils/config-loader.js';
427
- export * as output from '../utils/output.js';
426
+ export { loadConfig } from '../../domains/config/config-loader.js';
427
+ export { createTDDService } from '../../domains/tdd/tdd.service.js';
428
+ // Export service creators for advanced usage
429
+ export { createUploader } from '../../domains/uploads/upload.service.js';
430
+ export * as output from '../../shared/output.js';
@@ -6,9 +6,9 @@ import { open, readFile, unlink } from 'node:fs/promises';
6
6
  import { resolve } from 'node:path';
7
7
  import { Readable } from 'node:stream';
8
8
  import { pipeline } from 'node:stream/promises';
9
- import { createApiClient as defaultCreateApiClient } from '../api/index.js';
10
- import { loadConfig as defaultLoadConfig } from '../utils/config-loader.js';
11
- import * as defaultOutput from '../utils/output.js';
9
+ import * as defaultOutput from '../../shared/output.js';
10
+ import { createApiClient as defaultCreateApiClient } from '../auth/cloud-client.js';
11
+ import { loadConfig as defaultLoadConfig } from '../config/config-loader.js';
12
12
  let API_METHODS = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'];
13
13
  function createApiCommandDeps(deps = {}) {
14
14
  return {
@@ -1,12 +1,13 @@
1
+ import { getPackageVersion } from '../../shared/package-info.js';
2
+ import { parseAuthError, parseAuthenticatedError } from './auth-errors.js';
3
+ import { buildAuthUserAgent, buildRequestHeaders } from './auth-headers.js';
4
+
1
5
  /**
2
6
  * Auth Client - HTTP client factory for authentication
3
7
  *
4
8
  * Creates a thin HTTP wrapper that can be injected into operations.
5
9
  */
6
10
 
7
- import { getPackageVersion } from '../utils/package-info.js';
8
- import { buildAuthUserAgent, buildRequestHeaders, parseAuthError, parseAuthenticatedError } from './core.js';
9
-
10
11
  /**
11
12
  * Parse response body based on content type
12
13
  * @param {Response} response - Fetch response