Files
bridgeable-build/src/validate.js
T
2026-04-28 15:32:23 -06:00

78 lines
2.0 KiB
JavaScript

import { existsSync, readFileSync } from 'node:fs';
import { join, relative, resolve } from 'node:path';
import { walkFiles } from './file-rules.js';
const allowedSchemaVersions = new Set([1]);
const readJson = (path) => JSON.parse(readFileSync(path, 'utf8'));
export const validateSource = (sourceDir, config) => {
const sourceRoot = resolve(sourceDir);
const errors = [];
const warnings = [];
if (!allowedSchemaVersions.has(config.schemaVersion)) {
errors.push(`Unsupported schemaVersion: ${config.schemaVersion}`);
}
if (config.type !== 'bridgeable-components') {
errors.push(`Unsupported type: ${config.type}`);
}
for (const [key, path] of Object.entries(config.paths)) {
if (!path || typeof path !== 'string') {
errors.push(`paths.${key} must be a non-empty string.`);
continue;
}
if (!existsSync(join(sourceRoot, path))) {
warnings.push(`Configured path is missing: ${path}`);
}
}
if (!existsSync(join(sourceRoot, config.entry.globalStyles))) {
warnings.push(`Global style entry is missing: ${config.entry.globalStyles}`);
}
let specCount = 0;
walkFiles(sourceRoot, (absolutePath) => {
if (!absolutePath.endsWith('.component.json')) {
return;
}
specCount += 1;
const relativePath = relative(sourceRoot, absolutePath);
let spec;
try {
spec = readJson(absolutePath);
} catch (error) {
errors.push(`Invalid JSON in ${relativePath}: ${error.message}`);
return;
}
const expectedType = relativePath.startsWith(`${config.paths.components}/`)
? 'component'
: 'section';
if (spec.type && spec.type !== expectedType) {
errors.push(`${relativePath} has type "${spec.type}" but expected "${expectedType}".`);
}
if (!spec.name || typeof spec.name !== 'string') {
errors.push(`${relativePath} must define a string "name".`);
}
});
if (specCount === 0) {
warnings.push('No *.component.json files were found.');
}
return {
valid: errors.length === 0,
errors,
warnings,
specCount
};
};