feat: establish facade-first runtime boundary
This commit is contained in:
34
scripts/check-facade-boundary.mjs
Normal file
34
scripts/check-facade-boundary.mjs
Normal file
@@ -0,0 +1,34 @@
|
||||
import { readdir, readFile } from 'node:fs/promises'
|
||||
import { join } from 'node:path'
|
||||
|
||||
const sourceRoot = new URL('../src/', import.meta.url)
|
||||
const forbidden = [
|
||||
/from\s+["']three(?:\/|["'])/, /from\s+["']@types\/three/, /from\s+["']sqlite3?/, /from\s+["']@sqlite/, /from\s+["']opfs/, /SharedArrayBuffer/, /\bpostMessage\s*\(/,
|
||||
]
|
||||
const allowDirectRuntime = new Set(['facade/threeViewport.ts', 'facade/threeViewport.tsx', 'facade/persistenceWorker.ts', 'facade/geometryWorker.ts'])
|
||||
|
||||
async function walk(relative = '') {
|
||||
const directory = new URL(relative, sourceRoot)
|
||||
const entries = await readdir(directory, { withFileTypes: true })
|
||||
const files = []
|
||||
for (const entry of entries) {
|
||||
const next = join(relative, entry.name)
|
||||
if (entry.isDirectory()) files.push(...await walk(next))
|
||||
else if (/\.(ts|tsx)$/.test(entry.name)) files.push(next)
|
||||
}
|
||||
return files
|
||||
}
|
||||
|
||||
const violations = []
|
||||
for (const file of await walk()) {
|
||||
if (allowDirectRuntime.has(file)) continue
|
||||
const content = await readFile(new URL(file, sourceRoot), 'utf8')
|
||||
for (const pattern of forbidden) if (pattern.test(content)) violations.push(`${file}: ${pattern}`)
|
||||
}
|
||||
|
||||
if (violations.length) {
|
||||
console.error('Facade-only boundary failed:')
|
||||
violations.forEach((violation) => console.error(`- ${violation}`))
|
||||
process.exit(1)
|
||||
}
|
||||
console.log(`Facade-only boundary passed (${(await walk()).length} TypeScript source files checked).`)
|
||||
Reference in New Issue
Block a user