Scaffold Vite + TypeScript + Three.js (scène vide : sol + boîte, marqueur de build), store et encodage de l'état dans l'URL (5 tests), lint de frontières entre modules, pipeline d'extraction Rhino (graine du 26/09) et première géométrie v0, deploy.sh statique (releases + lien symbolique + smoke), AGENTS.md, RUNBOOK, licences MIT + CC BY-SA 4.0. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
49 lines
1.7 KiB
JavaScript
49 lines
1.7 KiB
JavaScript
#!/usr/bin/env node
|
|
// Lint de frontières entre modules (ARCHITECTURE §4). Échoue si un import franchit une frontière interdite.
|
|
// ui/ ne doit importer ni gen/ ni fx/ ni horscamp/ (il passe par core/state)
|
|
// gen/ fx/ horscamp/ ne doivent pas importer ui/
|
|
// personne n'importe main.ts
|
|
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
import { join, relative, dirname, resolve } from 'node:path';
|
|
|
|
const racine = resolve(new URL('..', import.meta.url).pathname, 'src');
|
|
const interdits = {
|
|
ui: ['gen', 'fx', 'horscamp'],
|
|
gen: ['ui'],
|
|
fx: ['ui'],
|
|
horscamp: ['ui'],
|
|
core: ['ui', 'gen', 'fx', 'horscamp'],
|
|
content: ['ui', 'gen', 'fx', 'horscamp'],
|
|
};
|
|
|
|
function fichiers(d) {
|
|
return readdirSync(d).flatMap((n) => {
|
|
const p = join(d, n);
|
|
return statSync(p).isDirectory() ? fichiers(p) : p.endsWith('.ts') ? [p] : [];
|
|
});
|
|
}
|
|
|
|
let erreurs = 0;
|
|
for (const f of fichiers(racine)) {
|
|
const rel = relative(racine, f);
|
|
const module = rel.includes('/') ? rel.split('/')[0] : '(racine)';
|
|
const src = readFileSync(f, 'utf8');
|
|
for (const m of src.matchAll(/from\s+['"](\.[^'"]+)['"]/g)) {
|
|
const cible = relative(racine, resolve(dirname(f), m[1]));
|
|
const moduleCible = cible.includes('/') ? cible.split('/')[0] : cible.replace(/\.ts$/, '');
|
|
if (moduleCible === 'main' && rel !== 'main.ts') {
|
|
console.error(`✗ ${rel} importe main.ts`);
|
|
erreurs++;
|
|
}
|
|
if ((interdits[module] ?? []).includes(moduleCible)) {
|
|
console.error(`✗ ${rel} (${module}) importe ${cible} (${moduleCible}) : frontière interdite`);
|
|
erreurs++;
|
|
}
|
|
}
|
|
}
|
|
if (erreurs) {
|
|
console.error(`${erreurs} franchissement(s) de frontière.`);
|
|
process.exit(1);
|
|
}
|
|
console.log('frontières respectées');
|