@zaaxch/tailframe 3.0.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/flutter.mjs DELETED
@@ -1,111 +0,0 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
-
4
- const ALLOWED_ROOTS = new Set(["app", "core", "modules", "platform"]);
5
- const ALLOWED_APP_DIRECTORIES = new Set(["components", "public", "state", "theme", "views"]);
6
- const ALLOWED_MODULE_DIRECTORIES = new Set(["api", "components", "public", "state", "types", "views"]);
7
- const IMPORT_PATTERN = /(?:import|export)\s+["']([^"']+)["']/g;
8
-
9
- const toPosix = (value) => value.split(path.sep).join("/");
10
-
11
- function walk(target) {
12
- const results = [];
13
- for (const entry of fs.readdirSync(target, { withFileTypes: true })) {
14
- if ([".dart_tool", "build", ".git"].includes(entry.name)) continue;
15
- const absolute = path.join(target, entry.name);
16
- if (entry.isDirectory()) results.push(...walk(absolute));
17
- else if (entry.name.endsWith(".dart")) results.push(absolute);
18
- }
19
- return results;
20
- }
21
-
22
- function resolveImport(source, specifier, packageName) {
23
- if (specifier.startsWith(`package:${packageName}/`)) return specifier.slice(`package:${packageName}/`.length);
24
- if (specifier.startsWith(".")) return path.posix.normalize(path.posix.join(path.posix.dirname(source), specifier));
25
- return undefined;
26
- }
27
-
28
- export function readFlutterPackageName(rootArgument) {
29
- try {
30
- return fs.readFileSync(path.join(path.resolve(rootArgument), "pubspec.yaml"), "utf8").match(/^name:\s*([a-zA-Z0-9_]+)/m)?.[1];
31
- } catch {
32
- return undefined;
33
- }
34
- }
35
-
36
- export function validateFlutter(rootArgument) {
37
- const root = path.resolve(rootArgument);
38
- const lib = path.join(root, "lib");
39
- const errors = [];
40
- if (!fs.existsSync(lib)) return ["Missing Flutter architecture directory: lib"];
41
- const packageName = readFlutterPackageName(root);
42
- if (!packageName) errors.push("pubspec.yaml must declare a package name");
43
- for (const entry of fs.readdirSync(lib, { withFileTypes: true })) {
44
- if (entry.isDirectory() && !ALLOWED_ROOTS.has(entry.name)) errors.push(`lib/${entry.name} is not a recognized architecture root`);
45
- if (entry.isFile() && entry.name !== "main.dart") errors.push(`lib/${entry.name} is not the root bootstrap lib/main.dart`);
46
- }
47
- const files = walk(lib);
48
- const relativeFiles = new Set(files.map((file) => toPosix(path.relative(lib, file))));
49
- const graph = new Map();
50
- for (const relative of relativeFiles) {
51
- const parts = relative.split("/");
52
- if (relative === "main.dart") {
53
- // Checked after imports resolve below.
54
- } else if (!ALLOWED_ROOTS.has(parts[0])) {
55
- errors.push(`lib/${relative} is outside an architecture root`);
56
- }
57
- if (parts[0] === "core" && parts.length !== 2) errors.push(`lib/${relative} violates the flat core contract`);
58
- if (parts[0] === "app" && parts.length > 2 && !ALLOWED_APP_DIRECTORIES.has(parts[1])) {
59
- errors.push(`lib/${relative} uses an unsupported app directory`);
60
- }
61
- if (parts[0] === "modules") {
62
- if (parts.length < 4 || !ALLOWED_MODULE_DIRECTORIES.has(parts[2])) errors.push(`lib/${relative} is not in a canonical module layer`);
63
- if (parts[2] === "public" && (parts.length !== 4 || parts.at(-1) === "index.dart")) errors.push(`lib/${relative} is not a named direct module public entry`);
64
- }
65
- const source = fs.readFileSync(path.join(lib, relative), "utf8");
66
- for (const match of source.matchAll(IMPORT_PATTERN)) {
67
- const specifier = match[1];
68
- const target = packageName ? resolveImport(relative, specifier, packageName) : undefined;
69
- if (!target) {
70
- if (parts[0] === "core" && specifier.startsWith("package:")) {
71
- errors.push(`lib/${relative} violates core purity by importing ${specifier}`);
72
- }
73
- continue;
74
- }
75
- if (!relativeFiles.has(target)) {
76
- errors.push(`lib/${relative} references missing lib/${target}`);
77
- continue;
78
- }
79
- if (relative === "main.dart" && !target.startsWith("app/")) errors.push(`lib/main.dart may import only application bootstrap code, not lib/${target}`);
80
- if (parts[0] === "core" && !target.startsWith("core/")) errors.push(`lib/${relative} crosses outward from core to lib/${target}`);
81
- if (parts[0] === "platform" && (target.startsWith("app/") || target.startsWith("modules/"))) errors.push(`lib/${relative} crosses from platform to lib/${target}`);
82
- if (parts[0] === "app" && target.startsWith("modules/")) {
83
- const targetParts = target.split("/");
84
- if (targetParts[2] !== "public" || targetParts.length !== 4) errors.push(`lib/${relative} imports private module file lib/${target}`);
85
- }
86
- if (parts[0] !== "modules") continue;
87
- if (target.startsWith("app/") && !target.startsWith("app/public/")) errors.push(`lib/${relative} imports private app file lib/${target}`);
88
- if (!target.startsWith("modules/")) continue;
89
- const targetParts = target.split("/");
90
- if (targetParts[1] === parts[1]) continue;
91
- if (targetParts[2] !== "public" || targetParts.length !== 4) errors.push(`lib/${relative} imports private sibling file lib/${target}`);
92
- else {
93
- if (!graph.has(parts[1])) graph.set(parts[1], new Set());
94
- graph.get(parts[1]).add(targetParts[1]);
95
- }
96
- }
97
- }
98
- const visiting = new Set();
99
- const visited = new Set();
100
- const visit = (module) => {
101
- if (visiting.has(module)) return true;
102
- if (visited.has(module)) return false;
103
- visiting.add(module);
104
- for (const dependency of graph.get(module) ?? []) if (visit(dependency)) return true;
105
- visiting.delete(module);
106
- visited.add(module);
107
- return false;
108
- };
109
- for (const module of graph.keys()) if (visit(module)) errors.push(`Flutter module dependency graph contains a cycle involving ${module}`);
110
- return [...new Set(errors)];
111
- }