@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.
- package/README.md +8 -0
- package/bin/vizzly.js +1 -1
- package/dist/{cli.js → adapters/cli/cli.js} +41 -35
- package/dist/adapters/cli/setup.js +34 -0
- package/dist/{client → adapters/client}/index.js +6 -7
- package/dist/adapters/http/cloud-proxy.js +29 -0
- package/dist/{server → adapters/http}/http-server.js +12 -13
- package/dist/{server-manager/operations.js → adapters/http/server-lifecycle.js} +10 -13
- package/dist/{server-manager/index.js → adapters/http/server-manager.js} +23 -27
- package/dist/{plugin-api.js → adapters/plugins/plugin-api.js} +1 -1
- package/dist/{plugin-loader.js → adapters/plugins/plugin-loader.js} +1 -1
- package/dist/{services/index.js → adapters/plugins/services.js} +4 -9
- package/dist/adapters/sdk/index.d.ts +89 -0
- package/dist/{sdk → adapters/sdk}/index.js +22 -19
- package/dist/{commands/api.js → domains/api/api.commands.js} +3 -3
- package/dist/{auth/client.js → domains/auth/auth-client.js} +4 -3
- package/dist/domains/auth/auth-errors.js +50 -0
- package/dist/domains/auth/auth-headers.js +41 -0
- package/dist/domains/auth/auth.normalizers.js +50 -0
- package/dist/{server/routers/auth.js → domains/auth/auth.routes.js} +9 -9
- package/dist/domains/auth/auth.rules.js +19 -0
- package/dist/domains/auth/auth.serializers.js +32 -0
- package/dist/{auth/operations.js → domains/auth/auth.service.js} +115 -17
- package/dist/domains/auth/auth.validations.js +21 -0
- package/dist/{api/client.js → domains/auth/cloud-client.js} +11 -18
- package/dist/{commands/login.js → domains/auth/login.commands.js} +11 -8
- package/dist/{commands/logout.js → domains/auth/logout.commands.js} +6 -4
- package/dist/domains/auth/token-store.js +81 -0
- package/dist/{commands/whoami.js → domains/auth/whoami.commands.js} +6 -3
- package/dist/domains/baselines/baseline-download.js +192 -0
- package/dist/domains/baselines/baseline-write.js +22 -0
- package/dist/{server/routers/baseline.js → domains/baselines/baseline.routes.js} +3 -3
- package/dist/{tdd/services/baseline-manager.js → domains/baselines/baseline.service.js} +1 -39
- package/dist/{commands/baselines.js → domains/baselines/baselines.commands.js} +3 -3
- package/dist/domains/baselines/cloud-baselines.js +9 -0
- package/dist/domains/baselines/cloud-baselines.routes.js +42 -0
- package/dist/domains/builds/build.normalizers.js +35 -0
- package/dist/domains/builds/build.serializers.js +164 -0
- package/dist/domains/builds/build.service.js +119 -0
- package/dist/domains/builds/build.validations.js +39 -0
- package/dist/{commands/builds.js → domains/builds/builds.commands.js} +6 -74
- package/dist/domains/builds/cloud-builds.routes.js +31 -0
- package/dist/{commands/finalize.js → domains/builds/finalize.commands.js} +5 -17
- package/dist/{commands/status.js → domains/builds/status.commands.js} +9 -120
- package/dist/domains/comparisons/cloud-comparisons.js +43 -0
- package/dist/{tdd/services/comparison-service.js → domains/comparisons/comparison.service.js} +1 -1
- package/dist/{commands/comparisons.js → domains/comparisons/comparisons.commands.js} +7 -5
- package/dist/domains/config/config-defaults.js +27 -0
- package/dist/{utils → domains/config}/config-discovery.js +1 -9
- package/dist/{utils → domains/config}/config-loader.js +10 -9
- package/dist/{commands/config-cmd.js → domains/config/config.commands.js} +4 -4
- package/dist/{types → domains/config}/config.d.ts +3 -3
- package/dist/domains/config/config.normalizers.js +126 -0
- package/dist/{server/routers/config.js → domains/config/config.routes.js} +13 -13
- package/dist/domains/config/config.rules.js +47 -0
- package/dist/domains/config/config.serializers.js +202 -0
- package/dist/domains/config/config.service.js +625 -0
- package/dist/{utils/config-schema.js → domains/config/config.validations.js} +9 -9
- package/dist/{utils/environment-config.js → domains/config/environment.js} +1 -8
- package/dist/domains/context/compact-context.validations.js +60 -0
- package/dist/domains/context/context-presentation.js +368 -0
- package/dist/domains/context/context.commands.js +385 -0
- package/dist/domains/context/context.serializers.js +157 -0
- package/dist/domains/context/context.service.js +76 -0
- package/dist/domains/context/context.validations.js +100 -0
- package/dist/{context → domains/context}/local-workspace-provider.js +1 -1
- package/dist/{commands/doctor.js → domains/diagnostics/doctor.commands.js} +6 -5
- package/dist/{server/routers/health.js → domains/diagnostics/health.routes.js} +11 -20
- package/dist/{commands/preview.js → domains/previews/preview.commands.js} +9 -7
- package/dist/domains/previews/preview.service.js +37 -0
- package/dist/domains/projects/cloud-projects.routes.js +28 -0
- package/dist/{commands/orgs.js → domains/projects/orgs.commands.js} +6 -8
- package/dist/{utils → domains/projects}/project-binding.js +3 -3
- package/dist/domains/projects/project-errors.js +61 -0
- package/dist/{utils → domains/projects}/project-link-store.js +2 -2
- package/dist/domains/projects/project-requests.js +61 -0
- package/dist/{commands/project.js → domains/projects/project.commands.js} +9 -41
- package/dist/domains/projects/project.normalizers.js +69 -0
- package/dist/{project/operations.js → domains/projects/project.service.js} +89 -16
- package/dist/domains/projects/project.validations.js +31 -0
- package/dist/{commands/projects.js → domains/projects/projects.commands.js} +6 -8
- package/dist/{server/routers/projects.js → domains/projects/projects.routes.js} +5 -5
- package/dist/domains/reports/dashboard.routes.js +96 -0
- package/dist/{server/routers/events.js → domains/reports/events.routes.js} +14 -36
- package/dist/domains/reports/report-assets.routes.js +81 -0
- package/dist/domains/reports/report-state.js +51 -0
- package/dist/domains/reports/report-store.js +85 -0
- package/dist/domains/reports/report.serializers.js +99 -0
- package/dist/{services/static-report-generator.js → domains/reports/report.service.js} +11 -33
- package/dist/{commands/review.js → domains/review/review.commands.js} +4 -4
- package/dist/domains/runs/run-environment.js +69 -0
- package/dist/{services/test-runner.js → domains/runs/run-events.js} +11 -9
- package/dist/{commands/run.js → domains/runs/run.commands.js} +16 -13
- package/dist/domains/runs/run.normalizers.js +8 -0
- package/dist/domains/runs/run.rules.js +56 -0
- package/dist/domains/runs/run.serializers.js +101 -0
- package/dist/{test-runner/operations.js → domains/runs/run.service.js} +35 -7
- package/dist/domains/runs/run.validations.js +17 -0
- package/dist/{utils/session.js → domains/runs/session-store.js} +3 -2
- package/dist/{server/handlers/api-handler.js → domains/screenshots/cloud-handler.js} +4 -4
- package/dist/domains/screenshots/cloud-screenshots.js +109 -0
- package/dist/{utils/file-helpers.js → domains/screenshots/image-files.js} +1 -1
- package/dist/domains/screenshots/screenshot-hash.js +53 -0
- package/dist/domains/screenshots/screenshot-server-options.js +28 -0
- package/dist/{screenshot-server/operations.js → domains/screenshots/screenshot-server.js} +14 -1
- package/dist/domains/screenshots/screenshot.normalizers.js +40 -0
- package/dist/{server/routers/screenshot.js → domains/screenshots/screenshot.routes.js} +4 -4
- package/dist/domains/screenshots/screenshot.serializers.js +146 -0
- package/dist/{utils/security.js → domains/screenshots/screenshot.validations.js} +20 -70
- package/dist/{init/agents.js → domains/setup/agent-setup.js} +4 -5
- package/dist/{commands/init.js → domains/setup/init.commands.js} +10 -41
- package/dist/{server/handlers/tdd-handler.js → domains/tdd/screenshot-handler.js} +46 -281
- package/dist/{commands/tdd-daemon.js → domains/tdd/tdd-daemon.commands.js} +6 -6
- package/dist/{commands/tdd-screenshots.js → domains/tdd/tdd-screenshots.commands.js} +5 -5
- package/dist/{commands/tdd.js → domains/tdd/tdd.commands.js} +16 -15
- package/dist/{tdd/tdd-service.js → domains/tdd/tdd.service.js} +81 -405
- package/dist/{utils → domains/updates}/cli-update.js +4 -6
- package/dist/{utils → domains/updates}/update-notifications.js +7 -7
- package/dist/domains/uploads/upload-defaults.js +4 -0
- package/dist/domains/uploads/upload-files.js +32 -0
- package/dist/domains/uploads/upload-settings.js +21 -0
- package/dist/domains/uploads/upload-timing.js +18 -0
- package/dist/{commands/upload.js → domains/uploads/upload.commands.js} +11 -9
- package/dist/domains/uploads/upload.normalizers.js +60 -0
- package/dist/domains/uploads/upload.serializers.js +179 -0
- package/dist/{uploader/operations.js → domains/uploads/upload.service.js} +85 -28
- package/dist/domains/uploads/upload.validations.js +77 -0
- package/dist/index.js +12 -12
- package/dist/reporter/reporter-bundle.iife.js +86 -86
- package/dist/reporter-ssr/ssr-entry.js +2 -2
- package/dist/shared/cloud-protocol.js +171 -0
- package/dist/{utils → shared}/file-changes.js +1 -1
- package/dist/shared/files.js +9 -0
- package/dist/{utils → shared}/global-config.js +7 -78
- package/dist/shared/log-level.js +7 -0
- package/dist/{utils → shared}/output.js +1 -1
- package/dist/{utils → shared}/package-info.js +5 -4
- package/dist/shared/paths.js +57 -0
- package/package.json +23 -22
- package/dist/api/core.js +0 -382
- package/dist/api/endpoints.js +0 -421
- package/dist/api/index.js +0 -19
- package/dist/auth/core.js +0 -237
- package/dist/auth/index.js +0 -31
- package/dist/commands/context.js +0 -1066
- package/dist/config/core.js +0 -439
- package/dist/config/operations.js +0 -327
- package/dist/project/core.js +0 -211
- package/dist/screenshot-server/core.js +0 -161
- package/dist/screenshot-server/index.js +0 -11
- package/dist/server/routers/assets.js +0 -95
- package/dist/server/routers/cloud-proxy.js +0 -146
- package/dist/server/routers/dashboard.js +0 -172
- package/dist/services/auth-service.js +0 -117
- package/dist/services/config-service.js +0 -313
- package/dist/services/project-service.js +0 -88
- package/dist/test-runner/core.js +0 -293
- package/dist/test-runner/index.js +0 -13
- package/dist/types/sdk.d.ts +0 -186
- package/dist/uploader/core.js +0 -432
- package/dist/uploader/index.js +0 -88
- /package/dist/{types/client.d.ts → adapters/client/index.d.ts} +0 -0
- /package/dist/{server → adapters/http}/middleware/cors.js +0 -0
- /package/dist/{server → adapters/http}/middleware/json-parser.js +0 -0
- /package/dist/{server → adapters/http}/middleware/response.js +0 -0
- /package/dist/{server-manager/core.js → adapters/http/server-options.js} +0 -0
- /package/dist/{utils/login-poll-wait.js → domains/auth/login-wait.js} +0 -0
- /package/dist/{tdd/metadata → domains/baselines}/baseline-metadata.js +0 -0
- /package/dist/{services/build-manager.js → domains/builds/build-info.js} +0 -0
- /package/dist/{tdd/services/result-service.js → domains/comparisons/comparison-results.js} +0 -0
- /package/dist/{init/core.js → domains/config/config-plan.js} +0 -0
- /package/dist/{utils/config-helpers.js → domains/config/config.js} +0 -0
- /package/dist/{utils/visual-context-normalizers.js → domains/context/context.normalizers.js} +0 -0
- /package/dist/{context → domains/context}/provider-resolver.js +0 -0
- /package/dist/{utils/context.js → domains/diagnostics/environment-context.js} +0 -0
- /package/dist/{utils/report-data.js → domains/reports/report.normalizers.js} +0 -0
- /package/dist/{utils/image-input-detector.js → domains/screenshots/image-input.js} +0 -0
- /package/dist/{tdd/core/signature.js → domains/screenshots/screenshot-identity.js} +0 -0
- /package/dist/{utils → domains/screenshots}/screenshot-options.js +0 -0
- /package/dist/{init/prompts.js → domains/setup/setup-prompts.js} +0 -0
- /package/dist/{tdd → domains/tdd}/runtime-context.js +0 -0
- /package/dist/{tdd → domains/tdd}/server-registry.js +0 -0
- /package/dist/{commands/tdd-daemon-process.js → domains/tdd/tdd-daemon-process.commands.js} +0 -0
- /package/dist/{utils → domains/updates}/update-check.js +0 -0
- /package/dist/{types/index.d.ts → index.d.ts} +0 -0
- /package/dist/{utils → shared}/api-url.js +0 -0
- /package/dist/{utils → shared}/async-utils.js +0 -0
- /package/dist/{utils → shared}/browser.js +0 -0
- /package/dist/{utils → shared}/ci-env.js +0 -0
- /package/dist/{utils → shared}/colors.js +0 -0
- /package/dist/{utils → shared}/fetch-utils.js +0 -0
- /package/dist/{utils → shared}/git.js +0 -0
- /package/dist/{utils → shared}/patterns.js +0 -0
- /package/dist/{utils → shared}/secret-store.js +0 -0
- /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
|
@@ -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 '
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { finalizeCommand
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import { runUpdatedCli } from '
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import
|
|
38
|
-
import
|
|
39
|
-
import {
|
|
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 '
|
|
11
|
-
import {
|
|
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
|
-
|
|
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
|
|
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 './
|
|
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
|
-
|
|
118
|
-
await httpServer
|
|
119
|
-
}
|
|
120
|
-
if (handler?.cleanup) {
|
|
117
|
+
try {
|
|
118
|
+
await httpServer?.stop();
|
|
119
|
+
} finally {
|
|
121
120
|
try {
|
|
122
|
-
handler
|
|
121
|
+
await handler?.cleanup?.();
|
|
123
122
|
} catch {
|
|
124
|
-
//
|
|
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 '
|
|
11
|
-
import { createApiHandler } from '
|
|
12
|
-
import { createTddHandler } from '
|
|
13
|
-
import { createHttpServer } from '
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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 '
|
|
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 '
|
|
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
|
-
*
|
|
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 {
|
|
13
|
-
import {
|
|
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 {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import
|
|
22
|
-
import
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 '
|
|
427
|
-
export
|
|
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
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
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
|