@vizzly-testing/cli 0.19.2 → 0.20.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.js +134 -0
- package/dist/api/core.js +341 -0
- package/dist/api/endpoints.js +314 -0
- package/dist/api/index.js +19 -0
- package/dist/auth/client.js +91 -0
- package/dist/auth/core.js +176 -0
- package/dist/auth/index.js +30 -0
- package/dist/auth/operations.js +148 -0
- package/dist/cli.js +1 -1
- package/dist/client/index.js +0 -1
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/finalize.js +41 -15
- package/dist/commands/login.js +7 -6
- package/dist/commands/logout.js +4 -4
- package/dist/commands/project.js +5 -4
- package/dist/commands/run.js +158 -90
- package/dist/commands/status.js +22 -18
- package/dist/commands/tdd.js +105 -78
- package/dist/commands/upload.js +61 -26
- package/dist/commands/whoami.js +4 -4
- package/dist/config/core.js +438 -0
- package/dist/config/index.js +13 -0
- package/dist/config/operations.js +327 -0
- package/dist/index.js +1 -1
- package/dist/project/core.js +295 -0
- package/dist/project/index.js +13 -0
- package/dist/project/operations.js +393 -0
- package/dist/report-generator/core.js +315 -0
- package/dist/report-generator/index.js +8 -0
- package/dist/report-generator/operations.js +196 -0
- package/dist/reporter/reporter-bundle.iife.js +16 -16
- package/dist/screenshot-server/core.js +157 -0
- package/dist/screenshot-server/index.js +11 -0
- package/dist/screenshot-server/operations.js +183 -0
- package/dist/sdk/index.js +3 -2
- package/dist/server/handlers/api-handler.js +14 -5
- package/dist/server/handlers/tdd-handler.js +80 -48
- package/dist/server-manager/core.js +183 -0
- package/dist/server-manager/index.js +81 -0
- package/dist/server-manager/operations.js +208 -0
- package/dist/services/build-manager.js +2 -69
- package/dist/services/index.js +21 -48
- package/dist/services/screenshot-server.js +40 -74
- package/dist/services/server-manager.js +45 -80
- package/dist/services/static-report-generator.js +21 -163
- package/dist/services/test-runner.js +90 -249
- package/dist/services/uploader.js +56 -358
- package/dist/tdd/core/hotspot-coverage.js +112 -0
- package/dist/tdd/core/signature.js +101 -0
- package/dist/tdd/index.js +19 -0
- package/dist/tdd/metadata/baseline-metadata.js +103 -0
- package/dist/tdd/metadata/hotspot-metadata.js +93 -0
- package/dist/tdd/services/baseline-downloader.js +151 -0
- package/dist/tdd/services/baseline-manager.js +166 -0
- package/dist/tdd/services/comparison-service.js +230 -0
- package/dist/tdd/services/hotspot-service.js +71 -0
- package/dist/tdd/services/result-service.js +123 -0
- package/dist/tdd/tdd-service.js +1081 -0
- package/dist/test-runner/core.js +255 -0
- package/dist/test-runner/index.js +13 -0
- package/dist/test-runner/operations.js +483 -0
- package/dist/types/client.d.ts +4 -2
- package/dist/types/index.d.ts +5 -0
- package/dist/uploader/core.js +396 -0
- package/dist/uploader/index.js +11 -0
- package/dist/uploader/operations.js +412 -0
- package/dist/utils/config-schema.js +8 -3
- package/package.json +7 -12
- package/dist/services/api-service.js +0 -412
- package/dist/services/auth-service.js +0 -226
- package/dist/services/config-service.js +0 -369
- package/dist/services/html-report-generator.js +0 -455
- package/dist/services/project-service.js +0 -326
- package/dist/services/report-generator/report.css +0 -411
- package/dist/services/report-generator/viewer.js +0 -102
- package/dist/services/tdd-service.js +0 -1429
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Core - Pure functions for configuration logic
|
|
3
|
+
*
|
|
4
|
+
* No I/O, no side effects - just data transformations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { VizzlyError } from '../errors/vizzly-error.js';
|
|
8
|
+
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Default Configuration
|
|
11
|
+
// ============================================================================
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Default configuration values
|
|
15
|
+
*/
|
|
16
|
+
export const CONFIG_DEFAULTS = {
|
|
17
|
+
apiUrl: 'https://app.vizzly.dev',
|
|
18
|
+
server: {
|
|
19
|
+
port: 47392,
|
|
20
|
+
timeout: 30000
|
|
21
|
+
},
|
|
22
|
+
build: {
|
|
23
|
+
name: 'Build {timestamp}',
|
|
24
|
+
environment: 'test'
|
|
25
|
+
},
|
|
26
|
+
upload: {
|
|
27
|
+
screenshotsDir: './screenshots',
|
|
28
|
+
batchSize: 10,
|
|
29
|
+
timeout: 30000
|
|
30
|
+
},
|
|
31
|
+
comparison: {
|
|
32
|
+
threshold: 2.0
|
|
33
|
+
},
|
|
34
|
+
tdd: {
|
|
35
|
+
openReport: false
|
|
36
|
+
},
|
|
37
|
+
plugins: []
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Valid config scopes for reading
|
|
42
|
+
*/
|
|
43
|
+
export const READ_SCOPES = ['project', 'global', 'merged'];
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Valid config scopes for writing
|
|
47
|
+
*/
|
|
48
|
+
export const WRITE_SCOPES = ['project', 'global'];
|
|
49
|
+
|
|
50
|
+
// ============================================================================
|
|
51
|
+
// Scope Validation
|
|
52
|
+
// ============================================================================
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Validate that a scope is valid for reading
|
|
56
|
+
* @param {string} scope - Scope to validate
|
|
57
|
+
* @returns {{ valid: boolean, error: Error|null }}
|
|
58
|
+
*/
|
|
59
|
+
export function validateReadScope(scope) {
|
|
60
|
+
if (!READ_SCOPES.includes(scope)) {
|
|
61
|
+
return {
|
|
62
|
+
valid: false,
|
|
63
|
+
error: new VizzlyError(`Invalid config scope: ${scope}. Must be 'project', 'global', or 'merged'`, 'INVALID_CONFIG_SCOPE')
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
valid: true,
|
|
68
|
+
error: null
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Validate that a scope is valid for writing
|
|
74
|
+
* @param {string} scope - Scope to validate
|
|
75
|
+
* @returns {{ valid: boolean, error: Error|null }}
|
|
76
|
+
*/
|
|
77
|
+
export function validateWriteScope(scope) {
|
|
78
|
+
if (!WRITE_SCOPES.includes(scope)) {
|
|
79
|
+
return {
|
|
80
|
+
valid: false,
|
|
81
|
+
error: new VizzlyError(`Invalid config scope for update: ${scope}. Must be 'project' or 'global'`, 'INVALID_CONFIG_SCOPE')
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
valid: true,
|
|
86
|
+
error: null
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ============================================================================
|
|
91
|
+
// Deep Merge
|
|
92
|
+
// ============================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Deep merge two objects
|
|
96
|
+
* @param {Object} target - Target object
|
|
97
|
+
* @param {Object} source - Source object
|
|
98
|
+
* @returns {Object} Merged object (new object, inputs not mutated)
|
|
99
|
+
*/
|
|
100
|
+
export function deepMerge(target, source) {
|
|
101
|
+
let output = {
|
|
102
|
+
...target
|
|
103
|
+
};
|
|
104
|
+
for (let key of Object.keys(source)) {
|
|
105
|
+
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
|
106
|
+
if (target[key] && typeof target[key] === 'object' && !Array.isArray(target[key])) {
|
|
107
|
+
output[key] = deepMerge(target[key], source[key]);
|
|
108
|
+
} else {
|
|
109
|
+
output[key] = source[key];
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
output[key] = source[key];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return output;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ============================================================================
|
|
119
|
+
// Config Merging with Source Tracking
|
|
120
|
+
// ============================================================================
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Ensure value is a plain object, return empty object otherwise
|
|
124
|
+
* @param {*} value - Value to check
|
|
125
|
+
* @returns {Object} The value if it's an object, empty object otherwise
|
|
126
|
+
*/
|
|
127
|
+
function ensureObject(value) {
|
|
128
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
return {};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Build merged config from layers with source tracking
|
|
136
|
+
* @param {Object} options - Config layers
|
|
137
|
+
* @param {Object} options.projectConfig - Project config (from vizzly.config.js)
|
|
138
|
+
* @param {Object} options.globalConfig - Global config (from ~/.vizzly/config.json)
|
|
139
|
+
* @param {Object} [options.envOverrides] - Environment variable overrides
|
|
140
|
+
* @returns {{ config: Object, sources: Object }}
|
|
141
|
+
*/
|
|
142
|
+
export function buildMergedConfig({
|
|
143
|
+
projectConfig = {},
|
|
144
|
+
globalConfig = {},
|
|
145
|
+
envOverrides = {}
|
|
146
|
+
} = {}) {
|
|
147
|
+
// Ensure all inputs are plain objects
|
|
148
|
+
let safeProjectConfig = ensureObject(projectConfig);
|
|
149
|
+
let safeGlobalConfig = ensureObject(globalConfig);
|
|
150
|
+
let safeEnvOverrides = ensureObject(envOverrides);
|
|
151
|
+
let mergedConfig = {};
|
|
152
|
+
let sources = {};
|
|
153
|
+
|
|
154
|
+
// Layer 1: Defaults
|
|
155
|
+
for (let key of Object.keys(CONFIG_DEFAULTS)) {
|
|
156
|
+
mergedConfig[key] = CONFIG_DEFAULTS[key];
|
|
157
|
+
sources[key] = 'default';
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Layer 2: Global config (auth, project mappings, user preferences)
|
|
161
|
+
if (safeGlobalConfig.auth) {
|
|
162
|
+
mergedConfig.auth = safeGlobalConfig.auth;
|
|
163
|
+
sources.auth = 'global';
|
|
164
|
+
}
|
|
165
|
+
if (safeGlobalConfig.projects) {
|
|
166
|
+
mergedConfig.projects = safeGlobalConfig.projects;
|
|
167
|
+
sources.projects = 'global';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Layer 3: Project config file
|
|
171
|
+
for (let key of Object.keys(safeProjectConfig)) {
|
|
172
|
+
mergedConfig[key] = safeProjectConfig[key];
|
|
173
|
+
sources[key] = 'project';
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Layer 4: Environment variables
|
|
177
|
+
for (let key of Object.keys(safeEnvOverrides)) {
|
|
178
|
+
mergedConfig[key] = safeEnvOverrides[key];
|
|
179
|
+
sources[key] = 'env';
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
config: mergedConfig,
|
|
183
|
+
sources
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Extract environment variable overrides
|
|
189
|
+
* @param {Object} env - Environment variables object (defaults to process.env)
|
|
190
|
+
* @returns {Object} Overrides from environment
|
|
191
|
+
*/
|
|
192
|
+
export function extractEnvOverrides(env = process.env) {
|
|
193
|
+
let overrides = {};
|
|
194
|
+
if (env.VIZZLY_TOKEN) {
|
|
195
|
+
overrides.apiKey = env.VIZZLY_TOKEN;
|
|
196
|
+
}
|
|
197
|
+
if (env.VIZZLY_API_URL) {
|
|
198
|
+
overrides.apiUrl = env.VIZZLY_API_URL;
|
|
199
|
+
}
|
|
200
|
+
return overrides;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ============================================================================
|
|
204
|
+
// Config Result Building
|
|
205
|
+
// ============================================================================
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Build a project config result object
|
|
209
|
+
* @param {Object|null} config - Config object or null if not found
|
|
210
|
+
* @param {string|null} filepath - Path to config file or null
|
|
211
|
+
* @returns {{ config: Object, filepath: string|null, isEmpty: boolean }}
|
|
212
|
+
*/
|
|
213
|
+
export function buildProjectConfigResult(config, filepath) {
|
|
214
|
+
if (!config) {
|
|
215
|
+
return {
|
|
216
|
+
config: {},
|
|
217
|
+
filepath: null,
|
|
218
|
+
isEmpty: true
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
config,
|
|
223
|
+
filepath,
|
|
224
|
+
isEmpty: Object.keys(config).length === 0
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Build a global config result object
|
|
230
|
+
* @param {Object} config - Global config object
|
|
231
|
+
* @param {string} filepath - Path to global config file
|
|
232
|
+
* @returns {{ config: Object, filepath: string, isEmpty: boolean }}
|
|
233
|
+
*/
|
|
234
|
+
export function buildGlobalConfigResult(config, filepath) {
|
|
235
|
+
return {
|
|
236
|
+
config,
|
|
237
|
+
filepath,
|
|
238
|
+
isEmpty: Object.keys(config).length === 0
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Build a merged config result object
|
|
244
|
+
* @param {Object} options - Build options
|
|
245
|
+
* @returns {{ config: Object, sources: Object, projectFilepath: string|null, globalFilepath: string }}
|
|
246
|
+
*/
|
|
247
|
+
export function buildMergedConfigResult({
|
|
248
|
+
projectConfig,
|
|
249
|
+
globalConfig,
|
|
250
|
+
envOverrides,
|
|
251
|
+
projectFilepath,
|
|
252
|
+
globalFilepath
|
|
253
|
+
}) {
|
|
254
|
+
let {
|
|
255
|
+
config,
|
|
256
|
+
sources
|
|
257
|
+
} = buildMergedConfig({
|
|
258
|
+
projectConfig,
|
|
259
|
+
globalConfig,
|
|
260
|
+
envOverrides
|
|
261
|
+
});
|
|
262
|
+
return {
|
|
263
|
+
config,
|
|
264
|
+
sources,
|
|
265
|
+
projectFilepath,
|
|
266
|
+
globalFilepath
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// ============================================================================
|
|
271
|
+
// Config Serialization
|
|
272
|
+
// ============================================================================
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Stringify a value with proper indentation for JavaScript output
|
|
276
|
+
* @param {*} value - Value to stringify
|
|
277
|
+
* @param {number} depth - Current depth for indentation
|
|
278
|
+
* @returns {string} JavaScript representation of value
|
|
279
|
+
*/
|
|
280
|
+
export function stringifyWithIndent(value, depth = 0) {
|
|
281
|
+
let indent = ' '.repeat(depth);
|
|
282
|
+
let prevIndent = depth > 0 ? ' '.repeat(depth - 1) : '';
|
|
283
|
+
if (value === null || value === undefined) {
|
|
284
|
+
return String(value);
|
|
285
|
+
}
|
|
286
|
+
if (typeof value === 'string') {
|
|
287
|
+
return `'${value.replace(/'/g, "\\'")}'`;
|
|
288
|
+
}
|
|
289
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
290
|
+
return String(value);
|
|
291
|
+
}
|
|
292
|
+
if (Array.isArray(value)) {
|
|
293
|
+
if (value.length === 0) return '[]';
|
|
294
|
+
let items = value.map(item => `${indent}${stringifyWithIndent(item, depth + 1)}`);
|
|
295
|
+
return `[\n${items.join(',\n')}\n${prevIndent}]`;
|
|
296
|
+
}
|
|
297
|
+
if (typeof value === 'object') {
|
|
298
|
+
let keys = Object.keys(value);
|
|
299
|
+
if (keys.length === 0) return '{}';
|
|
300
|
+
let items = keys.map(key => {
|
|
301
|
+
let val = stringifyWithIndent(value[key], depth + 1);
|
|
302
|
+
return `${indent}${key}: ${val}`;
|
|
303
|
+
});
|
|
304
|
+
return `{\n${items.join(',\n')}\n${prevIndent}}`;
|
|
305
|
+
}
|
|
306
|
+
return String(value);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Serialize config to JavaScript module format
|
|
311
|
+
* @param {Object} config - Config object to serialize
|
|
312
|
+
* @returns {string} JavaScript source code
|
|
313
|
+
*/
|
|
314
|
+
export function serializeToJavaScript(config) {
|
|
315
|
+
let lines = ['/**', ' * Vizzly Configuration', ' * @see https://docs.vizzly.dev/cli/configuration', ' */', '', "import { defineConfig } from '@vizzly-testing/cli/config';", '', 'export default defineConfig(', stringifyWithIndent(config, 1), ');', ''];
|
|
316
|
+
return lines.join('\n');
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Serialize config to JSON format
|
|
321
|
+
* @param {Object} config - Config object to serialize
|
|
322
|
+
* @returns {string} JSON string with 2-space indentation
|
|
323
|
+
*/
|
|
324
|
+
export function serializeToJson(config) {
|
|
325
|
+
return JSON.stringify(config, null, 2);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Determine the serialization format based on filepath
|
|
330
|
+
* @param {string} filepath - Path to config file
|
|
331
|
+
* @returns {'javascript'|'json'|'package'|'unknown'} Format type
|
|
332
|
+
*/
|
|
333
|
+
export function getConfigFormat(filepath) {
|
|
334
|
+
if (filepath.endsWith('.js') || filepath.endsWith('.mjs')) {
|
|
335
|
+
return 'javascript';
|
|
336
|
+
}
|
|
337
|
+
if (filepath.endsWith('.json') && !filepath.endsWith('package.json')) {
|
|
338
|
+
return 'json';
|
|
339
|
+
}
|
|
340
|
+
if (filepath.endsWith('package.json')) {
|
|
341
|
+
return 'package';
|
|
342
|
+
}
|
|
343
|
+
return 'unknown';
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Serialize config for writing to file
|
|
348
|
+
* @param {Object} config - Config object to serialize
|
|
349
|
+
* @param {string} filepath - Target file path
|
|
350
|
+
* @returns {{ content: string|null, format: string, error: Error|null }}
|
|
351
|
+
*/
|
|
352
|
+
export function serializeConfig(config, filepath) {
|
|
353
|
+
let format = getConfigFormat(filepath);
|
|
354
|
+
if (format === 'javascript') {
|
|
355
|
+
return {
|
|
356
|
+
content: serializeToJavaScript(config),
|
|
357
|
+
format,
|
|
358
|
+
error: null
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
if (format === 'json') {
|
|
362
|
+
return {
|
|
363
|
+
content: serializeToJson(config),
|
|
364
|
+
format,
|
|
365
|
+
error: null
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
if (format === 'package') {
|
|
369
|
+
// Can't serialize standalone, need existing package.json
|
|
370
|
+
return {
|
|
371
|
+
content: null,
|
|
372
|
+
format,
|
|
373
|
+
error: null
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
return {
|
|
377
|
+
content: null,
|
|
378
|
+
format,
|
|
379
|
+
error: new VizzlyError(`Unsupported config file format: ${filepath}`, 'UNSUPPORTED_CONFIG_FORMAT')
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// ============================================================================
|
|
384
|
+
// Config Extraction
|
|
385
|
+
// ============================================================================
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Extract config from cosmiconfig result (handles .default exports)
|
|
389
|
+
* @param {Object|null} result - Cosmiconfig result
|
|
390
|
+
* @returns {{ config: Object|null, filepath: string|null }}
|
|
391
|
+
*/
|
|
392
|
+
export function extractCosmiconfigResult(result) {
|
|
393
|
+
if (!result || !result.config) {
|
|
394
|
+
return {
|
|
395
|
+
config: null,
|
|
396
|
+
filepath: null
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Handle both `export default` and `module.exports`
|
|
401
|
+
let config = result.config.default || result.config;
|
|
402
|
+
return {
|
|
403
|
+
config,
|
|
404
|
+
filepath: result.filepath
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// ============================================================================
|
|
409
|
+
// Validation Result Building
|
|
410
|
+
// ============================================================================
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Build a validation success result
|
|
414
|
+
* @param {Object} validatedConfig - Validated config
|
|
415
|
+
* @returns {{ valid: true, config: Object, errors: [] }}
|
|
416
|
+
*/
|
|
417
|
+
export function buildValidationSuccess(validatedConfig) {
|
|
418
|
+
return {
|
|
419
|
+
valid: true,
|
|
420
|
+
config: validatedConfig,
|
|
421
|
+
errors: []
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Build a validation failure result
|
|
427
|
+
* @param {Error} error - Validation error
|
|
428
|
+
* @returns {{ valid: false, config: null, errors: Array }}
|
|
429
|
+
*/
|
|
430
|
+
export function buildValidationFailure(error) {
|
|
431
|
+
return {
|
|
432
|
+
valid: false,
|
|
433
|
+
config: null,
|
|
434
|
+
errors: error.errors || [{
|
|
435
|
+
message: error.message
|
|
436
|
+
}]
|
|
437
|
+
};
|
|
438
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Module - Public exports
|
|
3
|
+
*
|
|
4
|
+
* Provides functional configuration primitives:
|
|
5
|
+
* - core.js: Pure functions for merging, serialization, validation results
|
|
6
|
+
* - operations.js: Config operations with dependency injection
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Core pure functions
|
|
10
|
+
export { buildGlobalConfigResult, buildMergedConfig, buildMergedConfigResult, buildProjectConfigResult, buildValidationFailure, buildValidationSuccess, CONFIG_DEFAULTS, deepMerge, extractCosmiconfigResult, extractEnvOverrides, getConfigFormat, READ_SCOPES, serializeConfig, serializeToJavaScript, serializeToJson, stringifyWithIndent, validateReadScope, validateWriteScope, WRITE_SCOPES } from './core.js';
|
|
11
|
+
|
|
12
|
+
// Config operations (take dependencies as parameters)
|
|
13
|
+
export { getConfig, getConfigSource, getGlobalConfig, getMergedConfig, getProjectConfig, updateConfig, updateGlobalConfig, updateProjectConfig, validateConfig, writeProjectConfigFile } from './operations.js';
|