Files
workbuddy_skills/oil-motion/scripts/credential-ui/src/page.ts
T

27 lines
1.7 KiB
TypeScript
Raw Normal View History

import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { loadManifest, object, PublicError, validateManifest, type Manifest } from './config.ts';
export type PageUI = { title?: string; label?: string; saveLabel?: string };
export function validatePageUI(ui: unknown): PageUI {
if (!object(ui) || Object.entries(ui).some(([key, value]) =>
!['title', 'label', 'saveLabel'].includes(key) || typeof value !== 'string' || !value.trim() || value.length > 120))
throw new PublicError('页面文案配置不合法。');
return ui as PageUI;
}
export function validateFields(fields: Manifest[]): Manifest[] {
if (!Array.isArray(fields) || fields.length < 1 || fields.length > 16) throw new PublicError('每页需要 1 至 16 项凭据声明。');
fields.forEach(validateManifest);
if (new Set(fields.map(field => field.credential)).size !== fields.length) throw new PublicError('同一页不能重复引用相同凭据。');
return fields;
}
export async function loadPage(file: string) {
let value: unknown;
try { value = JSON.parse(await readFile(file, 'utf8')); } catch { throw new PublicError('无法读取页面配置。'); }
if (!object(value) || value.version !== 1 || Object.keys(value).some(key => !['version', 'manifests', 'ui'].includes(key))
|| !Array.isArray(value.manifests) || !value.manifests.length || value.manifests.length > 16
|| value.manifests.some(item => typeof item !== 'string' || !item.trim())) throw new PublicError('页面配置不合法。');
const ui = validatePageUI(value.ui ?? {});
const manifests = validateFields(await Promise.all(value.manifests.map(item => loadManifest(path.resolve(path.dirname(file), item)))));
return { manifests, ui };
}