/** * cli:aggregate-outbox — validate.ts * * Deliberately light (no client-mode gate — scaffold-pwa carries the heavy * gates): Zod parse + web-root resolution + existence. The aggregator is safe * to run on any web tree: it only reads outbox modules and (re)writes ONE * generated file. */ import fs from 'node:fs' import path from 'node:path' import { findSmartStackStructure } from '../../../../../lib/detector.js' import { AggregateOutboxInputSchema, type ValidationResult, } from './types.js' export async function validate(raw: unknown): Promise { const parsed = AggregateOutboxInputSchema.safeParse(raw) if (!parsed.success) { return { valid: false, errors: parsed.error.issues.map((i) => `[${i.path.join('.')}] ${i.message}`), warnings: [], } } const spec = parsed.data let webRootAbs: string if (spec.webRoot) { webRootAbs = path.resolve(spec.projectPath, spec.webRoot) } else { const structure = await findSmartStackStructure(spec.projectPath) if (!structure.web) { return { valid: false, errors: [ `Could not locate a web project under ${spec.projectPath} — pass \`webRoot\` explicitly (relative to projectPath).`, ], warnings: [], } } webRootAbs = path.resolve(structure.web) } if (!fs.existsSync(webRootAbs)) { return { valid: false, errors: [`Web root not found: ${webRootAbs}`], warnings: [] } } return { valid: true, errors: [], warnings: [], spec, webRootAbs } }