@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
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import { parseJsonBody } from '../../adapters/http/middleware/json-parser.js';
|
|
2
|
+
import { sendError, sendServiceUnavailable, sendSuccess } from '../../adapters/http/middleware/response.js';
|
|
3
|
+
import * as output from '../../shared/output.js';
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* Config Router
|
|
3
7
|
* Handles configuration management endpoints
|
|
4
8
|
*/
|
|
5
9
|
|
|
6
|
-
import * as output from '../../utils/output.js';
|
|
7
|
-
import { parseJsonBody } from '../middleware/json-parser.js';
|
|
8
|
-
import { sendError, sendServiceUnavailable, sendSuccess } from '../middleware/response.js';
|
|
9
|
-
|
|
10
10
|
/**
|
|
11
11
|
* Create config router
|
|
12
12
|
* @param {Object} context - Router context
|
|
@@ -26,7 +26,7 @@ export function createConfigRouter({
|
|
|
26
26
|
// Get merged config with sources
|
|
27
27
|
if (req.method === 'GET' && pathname === '/api/config') {
|
|
28
28
|
try {
|
|
29
|
-
|
|
29
|
+
let configData = await configService.getConfig('merged');
|
|
30
30
|
sendSuccess(res, configData);
|
|
31
31
|
return true;
|
|
32
32
|
} catch (error) {
|
|
@@ -41,7 +41,7 @@ export function createConfigRouter({
|
|
|
41
41
|
// Get project-level config
|
|
42
42
|
if (req.method === 'GET' && pathname === '/api/config/project') {
|
|
43
43
|
try {
|
|
44
|
-
|
|
44
|
+
let configData = await configService.getConfig('project');
|
|
45
45
|
sendSuccess(res, configData);
|
|
46
46
|
return true;
|
|
47
47
|
} catch (error) {
|
|
@@ -56,7 +56,7 @@ export function createConfigRouter({
|
|
|
56
56
|
// Get global config
|
|
57
57
|
if (req.method === 'GET' && pathname === '/api/config/global') {
|
|
58
58
|
try {
|
|
59
|
-
|
|
59
|
+
let configData = await configService.getConfig('global');
|
|
60
60
|
sendSuccess(res, configData);
|
|
61
61
|
return true;
|
|
62
62
|
} catch (error) {
|
|
@@ -71,8 +71,8 @@ export function createConfigRouter({
|
|
|
71
71
|
// Update project config
|
|
72
72
|
if (req.method === 'POST' && pathname === '/api/config/project') {
|
|
73
73
|
try {
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
let body = await parseJsonBody(req);
|
|
75
|
+
let result = await configService.updateConfig('project', body);
|
|
76
76
|
sendSuccess(res, {
|
|
77
77
|
success: true,
|
|
78
78
|
...result
|
|
@@ -90,8 +90,8 @@ export function createConfigRouter({
|
|
|
90
90
|
// Update global config
|
|
91
91
|
if (req.method === 'POST' && pathname === '/api/config/global') {
|
|
92
92
|
try {
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
let body = await parseJsonBody(req);
|
|
94
|
+
let result = await configService.updateConfig('global', body);
|
|
95
95
|
sendSuccess(res, {
|
|
96
96
|
success: true,
|
|
97
97
|
...result
|
|
@@ -109,8 +109,8 @@ export function createConfigRouter({
|
|
|
109
109
|
// Validate config
|
|
110
110
|
if (req.method === 'POST' && pathname === '/api/config/validate') {
|
|
111
111
|
try {
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
let body = await parseJsonBody(req);
|
|
113
|
+
let result = await configService.validateConfig(body);
|
|
114
114
|
sendSuccess(res, result);
|
|
115
115
|
return true;
|
|
116
116
|
} catch (error) {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { VizzlyError } from '../../shared/vizzly-error.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Valid config scopes for reading
|
|
5
|
+
*/
|
|
6
|
+
export let READ_SCOPES = ['project', 'global', 'merged'];
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Valid config scopes for writing
|
|
10
|
+
*/
|
|
11
|
+
export let WRITE_SCOPES = ['project', 'global'];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Validate that a scope is valid for reading
|
|
15
|
+
* @param {string} scope - Scope to validate
|
|
16
|
+
* @returns {{ valid: boolean, error: Error|null }}
|
|
17
|
+
*/
|
|
18
|
+
export function validateReadScope(scope) {
|
|
19
|
+
if (!READ_SCOPES.includes(scope)) {
|
|
20
|
+
return {
|
|
21
|
+
valid: false,
|
|
22
|
+
error: new VizzlyError(`Invalid config scope: ${scope}. Must be 'project', 'global', or 'merged'`, 'INVALID_CONFIG_SCOPE')
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
valid: true,
|
|
27
|
+
error: null
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Validate that a scope is valid for writing
|
|
33
|
+
* @param {string} scope - Scope to validate
|
|
34
|
+
* @returns {{ valid: boolean, error: Error|null }}
|
|
35
|
+
*/
|
|
36
|
+
export function validateWriteScope(scope) {
|
|
37
|
+
if (!WRITE_SCOPES.includes(scope)) {
|
|
38
|
+
return {
|
|
39
|
+
valid: false,
|
|
40
|
+
error: new VizzlyError(`Invalid config scope for update: ${scope}. Must be 'project' or 'global'`, 'INVALID_CONFIG_SCOPE')
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
valid: true,
|
|
45
|
+
error: null
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { VizzlyError } from '../../shared/vizzly-error.js';
|
|
2
|
+
import { buildMergedConfig } from './config.normalizers.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Build a project config result object
|
|
6
|
+
* @param {Object|null} config - Config object or null if not found
|
|
7
|
+
* @param {string|null} filepath - Path to config file or null
|
|
8
|
+
* @returns {{ config: Object, filepath: string|null, isEmpty: boolean }}
|
|
9
|
+
*/
|
|
10
|
+
export function buildProjectConfigResult(config, filepath) {
|
|
11
|
+
if (!config) {
|
|
12
|
+
return {
|
|
13
|
+
config: {},
|
|
14
|
+
filepath: null,
|
|
15
|
+
isEmpty: true
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
config,
|
|
20
|
+
filepath,
|
|
21
|
+
isEmpty: Object.keys(config).length === 0
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Build a global config result object
|
|
27
|
+
* @param {Object} config - Global config object
|
|
28
|
+
* @param {string} filepath - Path to global config file
|
|
29
|
+
* @returns {{ config: Object, filepath: string, isEmpty: boolean }}
|
|
30
|
+
*/
|
|
31
|
+
export function buildGlobalConfigResult(config, filepath) {
|
|
32
|
+
return {
|
|
33
|
+
config,
|
|
34
|
+
filepath,
|
|
35
|
+
isEmpty: Object.keys(config).length === 0
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Build a merged config result object
|
|
41
|
+
* @param {Object} options - Build options
|
|
42
|
+
* @returns {{ config: Object, sources: Object, projectFilepath: string|null, globalFilepath: string }}
|
|
43
|
+
*/
|
|
44
|
+
export function buildMergedConfigResult({
|
|
45
|
+
projectConfig,
|
|
46
|
+
globalConfig,
|
|
47
|
+
envOverrides,
|
|
48
|
+
projectFilepath,
|
|
49
|
+
globalFilepath
|
|
50
|
+
}) {
|
|
51
|
+
let {
|
|
52
|
+
config,
|
|
53
|
+
sources
|
|
54
|
+
} = buildMergedConfig({
|
|
55
|
+
projectConfig,
|
|
56
|
+
globalConfig,
|
|
57
|
+
envOverrides
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
config,
|
|
61
|
+
sources,
|
|
62
|
+
projectFilepath,
|
|
63
|
+
globalFilepath
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Stringify a value with proper indentation for JavaScript output
|
|
69
|
+
* @param {*} value - Value to stringify
|
|
70
|
+
* @param {number} depth - Current depth for indentation
|
|
71
|
+
* @returns {string} JavaScript representation of value
|
|
72
|
+
*/
|
|
73
|
+
export function stringifyWithIndent(value, depth = 0) {
|
|
74
|
+
let indent = ' '.repeat(depth);
|
|
75
|
+
let prevIndent = depth > 0 ? ' '.repeat(depth - 1) : '';
|
|
76
|
+
if (value === null || value === undefined) {
|
|
77
|
+
return String(value);
|
|
78
|
+
}
|
|
79
|
+
if (typeof value === 'string') {
|
|
80
|
+
return `'${value.replace(/'/g, "\\'")}'`;
|
|
81
|
+
}
|
|
82
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
83
|
+
return String(value);
|
|
84
|
+
}
|
|
85
|
+
if (Array.isArray(value)) {
|
|
86
|
+
if (value.length === 0) return '[]';
|
|
87
|
+
let items = value.map(item => `${indent}${stringifyWithIndent(item, depth + 1)}`);
|
|
88
|
+
return `[\n${items.join(',\n')}\n${prevIndent}]`;
|
|
89
|
+
}
|
|
90
|
+
if (typeof value === 'object') {
|
|
91
|
+
let keys = Object.keys(value);
|
|
92
|
+
if (keys.length === 0) return '{}';
|
|
93
|
+
let items = keys.map(key => {
|
|
94
|
+
let val = stringifyWithIndent(value[key], depth + 1);
|
|
95
|
+
return `${indent}${key}: ${val}`;
|
|
96
|
+
});
|
|
97
|
+
return `{\n${items.join(',\n')}\n${prevIndent}}`;
|
|
98
|
+
}
|
|
99
|
+
return String(value);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Serialize config to JavaScript module format
|
|
104
|
+
* @param {Object} config - Config object to serialize
|
|
105
|
+
* @returns {string} JavaScript source code
|
|
106
|
+
*/
|
|
107
|
+
export function serializeToJavaScript(config) {
|
|
108
|
+
let lines = ['/**', ' * Vizzly Configuration', ' * @see https://docs.vizzly.dev/cli/configuration', ' */', '', "import { defineConfig } from '@vizzly-testing/cli/config';", '', 'export default defineConfig(', stringifyWithIndent(config, 1), ');', ''];
|
|
109
|
+
return lines.join('\n');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Serialize config to JSON format
|
|
114
|
+
* @param {Object} config - Config object to serialize
|
|
115
|
+
* @returns {string} JSON string with 2-space indentation
|
|
116
|
+
*/
|
|
117
|
+
export function serializeToJson(config) {
|
|
118
|
+
return JSON.stringify(config, null, 2);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Determine the serialization format based on filepath
|
|
123
|
+
* @param {string} filepath - Path to config file
|
|
124
|
+
* @returns {'javascript'|'json'|'package'|'unknown'} Format type
|
|
125
|
+
*/
|
|
126
|
+
export function getConfigFormat(filepath) {
|
|
127
|
+
if (filepath.endsWith('.js') || filepath.endsWith('.mjs')) {
|
|
128
|
+
return 'javascript';
|
|
129
|
+
}
|
|
130
|
+
if (filepath.endsWith('.json') && !filepath.endsWith('package.json')) {
|
|
131
|
+
return 'json';
|
|
132
|
+
}
|
|
133
|
+
if (filepath.endsWith('package.json')) {
|
|
134
|
+
return 'package';
|
|
135
|
+
}
|
|
136
|
+
return 'unknown';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Serialize config for writing to file
|
|
141
|
+
* @param {Object} config - Config object to serialize
|
|
142
|
+
* @param {string} filepath - Target file path
|
|
143
|
+
* @returns {{ content: string|null, format: string, error: Error|null }}
|
|
144
|
+
*/
|
|
145
|
+
export function serializeConfig(config, filepath) {
|
|
146
|
+
let format = getConfigFormat(filepath);
|
|
147
|
+
if (format === 'javascript') {
|
|
148
|
+
return {
|
|
149
|
+
content: serializeToJavaScript(config),
|
|
150
|
+
format,
|
|
151
|
+
error: null
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (format === 'json') {
|
|
155
|
+
return {
|
|
156
|
+
content: serializeToJson(config),
|
|
157
|
+
format,
|
|
158
|
+
error: null
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
if (format === 'package') {
|
|
162
|
+
// Can't serialize standalone, need existing package.json
|
|
163
|
+
return {
|
|
164
|
+
content: null,
|
|
165
|
+
format,
|
|
166
|
+
error: null
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
content: null,
|
|
171
|
+
format,
|
|
172
|
+
error: new VizzlyError(`Unsupported config file format: ${filepath}`, 'UNSUPPORTED_CONFIG_FORMAT')
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Build a validation success result
|
|
178
|
+
* @param {Object} validatedConfig - Validated config
|
|
179
|
+
* @returns {{ valid: true, config: Object, errors: [] }}
|
|
180
|
+
*/
|
|
181
|
+
export function buildValidationSuccess(validatedConfig) {
|
|
182
|
+
return {
|
|
183
|
+
valid: true,
|
|
184
|
+
config: validatedConfig,
|
|
185
|
+
errors: []
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Build a validation failure result
|
|
191
|
+
* @param {Error} error - Validation error
|
|
192
|
+
* @returns {{ valid: false, config: null, errors: Array }}
|
|
193
|
+
*/
|
|
194
|
+
export function buildValidationFailure(error) {
|
|
195
|
+
return {
|
|
196
|
+
valid: false,
|
|
197
|
+
config: null,
|
|
198
|
+
errors: error.errors || [{
|
|
199
|
+
message: error.message
|
|
200
|
+
}]
|
|
201
|
+
};
|
|
202
|
+
}
|