45 lines
1.6 KiB
JavaScript
45 lines
1.6 KiB
JavaScript
import { readdir, readFile } from "node:fs/promises";
|
|
import { extname, relative, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const frontendDir = fileURLToPath(new URL("../", import.meta.url));
|
|
const sourceDir = resolve(frontendDir, "src");
|
|
const runtimeDir = resolve(sourceDir, "runtime");
|
|
const sourceExtensions = new Set([".ts", ".tsx", ".vue", ".js", ".jsx"]);
|
|
const violations = [];
|
|
|
|
const walk = async (directory) => {
|
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
return (
|
|
await Promise.all(
|
|
entries.map(async (entry) => {
|
|
const path = resolve(directory, entry.name);
|
|
return entry.isDirectory() ? walk(path) : path;
|
|
}),
|
|
)
|
|
).flat();
|
|
};
|
|
|
|
for (const path of await walk(sourceDir)) {
|
|
if (!sourceExtensions.has(extname(path)) || path.startsWith(`${runtimeDir}/`)) continue;
|
|
|
|
const source = await readFile(path, "utf8");
|
|
const file = relative(frontendDir, path);
|
|
if (source.includes("@tauri-apps/") || source.includes("__TAURI")) {
|
|
violations.push(`${file}: direct Tauri access is only allowed inside src/runtime`);
|
|
}
|
|
if (/from\s+["'][^"']*\/runtime\/[^"']+["']/.test(source)) {
|
|
violations.push(`${file}: import platform behavior through src/runtime/index.ts`);
|
|
}
|
|
if (/\bindexedDB\b|\bcaches\.open\s*\(|\bCacheStorage\b|\bsqlite\b/i.test(source)) {
|
|
violations.push(`${file}: local data cache storage must be routed through src/runtime`);
|
|
}
|
|
}
|
|
|
|
if (violations.length > 0) {
|
|
console.error(`Runtime boundary violations:\n${violations.map((item) => ` ${item}`).join("\n")}`);
|
|
process.exitCode = 1;
|
|
} else {
|
|
console.log("Runtime boundary is respected.");
|
|
}
|