First cut
This commit is contained in:
42
shared/src/repo-validation.ts
Normal file
42
shared/src/repo-validation.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { z } from 'zod';
|
||||
import {
|
||||
siteContextSchema,
|
||||
sectionFileSchema,
|
||||
eventsFileSchema,
|
||||
smsSitesConfigSchema,
|
||||
} from './schemas/index.js';
|
||||
|
||||
const EDITABLE_PATTERNS: Array<{ pattern: RegExp; schema: z.ZodTypeAny }> = [
|
||||
{ pattern: /^content\/sections\/[^/]+\.json$/, schema: sectionFileSchema },
|
||||
{ pattern: /^content\/events\.json$/, schema: eventsFileSchema },
|
||||
{ pattern: /^site-context\.json$/, schema: siteContextSchema },
|
||||
{ pattern: /^config\/sms-sites\.json$/, schema: smsSitesConfigSchema },
|
||||
];
|
||||
|
||||
export function schemaForRepoRelativePath(relativePath: string): z.ZodTypeAny | null {
|
||||
for (const { pattern, schema } of EDITABLE_PATTERNS) {
|
||||
if (pattern.test(relativePath)) return schema;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function isEditableContentRepoPath(relativePath: string): boolean {
|
||||
return EDITABLE_PATTERNS.some(({ pattern }) => pattern.test(relativePath));
|
||||
}
|
||||
|
||||
export function parseAndValidateRepoJson(
|
||||
repoRelativePath: string,
|
||||
rawText: string
|
||||
): { success: true; data: unknown } | { success: false; error: string } {
|
||||
const schema = schemaForRepoRelativePath(repoRelativePath);
|
||||
if (!schema) return { success: false, error: `No schema found for path: ${repoRelativePath}` };
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(rawText);
|
||||
const result = schema.safeParse(parsed);
|
||||
if (result.success) return { success: true, data: result.data };
|
||||
return { success: false, error: result.error.issues.map(i => `${i.path.join('.')}: ${i.message}`).join('; ') };
|
||||
} catch (e) {
|
||||
return { success: false, error: `Invalid JSON: ${(e as Error).message}` };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user