Guard component lang namespaces

active-uix
dev 5 months ago
parent c050e04ef1
commit a093963b04

@ -29,6 +29,7 @@ import { EngineSemantic, defineEngineSemantic } from './sema';
import { SemaConfigError } from './sema/errors';
import { createSomaRuntime } from './soma/runtime.svelte';
import { UIX_LAYER_CONTRACTS } from './contracts';
import { componentLangs } from './langs';
const minimalLang = { schema: {} satisfies LangNode, defaultLocale: 'es' as const };
const prefsProjectionSchema = standardPrefsDimensions({
@ -111,6 +112,36 @@ function collectDataAttrs(source: string): Set<string> {
return attrs;
}
function collectComponentLangPathViolations(source: string, file: string): string[] {
const clean = stripComments(source);
const violations: string[] = [];
const refRe = /#\?components\.([^|'"`\s]+)/g;
let match: RegExpExecArray | null;
while ((match = refRe.exec(clean))) {
const path = match[1];
const segments = path.split('.');
if (segments.some((segment) => /[A-Z]/.test(segment))) {
violations.push(`${file.replace(REPO_ROOT, '')}: components.${path}`);
}
}
return violations;
}
function collectLangCatalogKeyViolations(
node: unknown,
prefix = 'components'
): string[] {
if (!node || typeof node !== 'object') return [];
return Object.entries(node as Record<string, unknown>).flatMap(([key, value]) => {
const path = `${prefix}.${key}`;
const ownViolation = /[A-Z]/.test(key) ? [path] : [];
return [...ownViolation, ...collectLangCatalogKeyViolations(value, path)];
});
}
describe('UIX layer contracts', () => {
it('pins ActiveUix public service names and rejects legacy aliases', () => {
const uix = createActiveUix({ langs: minimalLang });
@ -266,6 +297,21 @@ describe('UIX layer contracts', () => {
expect(violations).toEqual([]);
});
it('guards component translation namespaces as kebab-case', () => {
const sourceRoots = [
join(HERE, 'soma', 'components'),
join(HERE, 'morfo', 'components')
];
const pathViolations = sourceRoots.flatMap((root) =>
listSourceFiles(root).flatMap((file) =>
collectComponentLangPathViolations(readFileSync(file, 'utf8'), file)
)
);
expect(pathViolations).toEqual([]);
expect(collectLangCatalogKeyViolations(componentLangs)).toEqual([]);
});
it('events/sema uses events as service name and requires dom or projector for visual projection', () => {
const factory = defineEngineSemantic({ visual: false });
expect(factory.name).toBe(UIX_LAYER_CONTRACTS.events.publicServiceName);

Loading…
Cancel
Save

Powered by TurnKey Linux.