- docs/PLAN.md — план по этапам, обновляется по мере работы - docs/TECHNICAL.md — слои, карта папок, контракты, рабочие процессы - docs/DECISIONS.md — журнал решений, принятых самостоятельно - разрешение 1080x1920, fit-width (портрет, 4:3..21:9) - каркас assets/scripts (core / modules / app / ui) - headless-тесты на vitest + strict typecheck + защита чистоты core - Rng: детерминированный генератор и перемешивание Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
29 lines
950 B
JavaScript
29 lines
950 B
JavaScript
// Guards the one architectural rule that the type system cannot express:
|
|
// assets/scripts/core must never import the Cocos engine. See docs/TECHNICAL.md.
|
|
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
|
|
const ROOT = 'assets/scripts/core';
|
|
const FORBIDDEN = /from\s+['"](cc|cc\/env|db:\/\/)/;
|
|
const offenders = [];
|
|
|
|
function walk(dir) {
|
|
for (const entry of readdirSync(dir)) {
|
|
const p = join(dir, entry);
|
|
if (statSync(p).isDirectory()) walk(p);
|
|
else if (p.endsWith('.ts')) {
|
|
const src = readFileSync(p, 'utf8');
|
|
src.split('\n').forEach((line, i) => {
|
|
if (FORBIDDEN.test(line)) offenders.push(`${p}:${i + 1} ${line.trim()}`);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
walk(ROOT);
|
|
if (offenders.length) {
|
|
console.error('core/ must not import the engine:\n' + offenders.join('\n'));
|
|
process.exit(1);
|
|
}
|
|
console.log('core purity OK');
|