feat: add main features
Agents for developpement added + frontend add + backend added. Git viewer created + agent and template creator + layout and project creator
This commit is contained in:
55
frontend/src/app/no-direct-invoke.test.ts
Normal file
55
frontend/src/app/no-direct-invoke.test.ts
Normal file
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* L1 architecture guard: only `src/adapters` may import `@tauri-apps/api` or
|
||||
* call `invoke()`. React components (features/app) must go through the gateway
|
||||
* ports (ARCHITECTURE §1.3, L1 DoD "Aucun invoke() direct dans les composants").
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readdirSync, readFileSync, statSync } from "node:fs";
|
||||
import { join, sep } from "node:path";
|
||||
|
||||
// Vitest runs with cwd = frontend/; scan the whole `src` tree from there.
|
||||
const SRC = join(process.cwd(), "src");
|
||||
|
||||
/** Recursively collect .ts/.tsx files, skipping the allowed adapters dir. */
|
||||
function collectSourceFiles(dir: string, out: string[] = []): string[] {
|
||||
for (const entry of readdirSync(dir)) {
|
||||
const full = join(dir, entry);
|
||||
if (statSync(full).isDirectory()) {
|
||||
// `src/adapters` is the single allowed home of Tauri transport code.
|
||||
if (full.endsWith(`${sep}adapters`)) continue;
|
||||
collectSourceFiles(full, out);
|
||||
} else if (/\.tsx?$/.test(entry) && !/\.test\.tsx?$/.test(entry)) {
|
||||
out.push(full);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Strips block and line comments so doc-comment mentions don't false-positive. */
|
||||
function stripComments(src: string): string {
|
||||
return src
|
||||
.replace(/\/\*[\s\S]*?\*\//g, "")
|
||||
.replace(/\/\/[^\n]*/g, "");
|
||||
}
|
||||
|
||||
describe("no direct Tauri usage outside src/adapters", () => {
|
||||
const files = collectSourceFiles(SRC);
|
||||
|
||||
it("finds source files to scan", () => {
|
||||
expect(files.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("no file imports @tauri-apps/api", () => {
|
||||
const offenders = files.filter((f) =>
|
||||
stripComments(readFileSync(f, "utf8")).includes("@tauri-apps/api"),
|
||||
);
|
||||
expect(offenders, `offending files: ${offenders.join(", ")}`).toEqual([]);
|
||||
});
|
||||
|
||||
it("no file calls invoke( (ignoring comments)", () => {
|
||||
const offenders = files.filter((f) =>
|
||||
/\binvoke\s*\(/.test(stripComments(readFileSync(f, "utf8"))),
|
||||
);
|
||||
expect(offenders, `offending files: ${offenders.join(", ")}`).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user