@akanjs/devkit 3.0.0-alpha.2 → 3.0.0-alpha.20

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.
Files changed (47) hide show
  1. package/README.ko.md +1 -1
  2. package/README.md +1 -1
  3. package/agentsIndex.test.ts +10 -0
  4. package/agentsIndex.ts +47 -1
  5. package/aiEditor.ts +1 -1
  6. package/akanConfig/akanConfig.test.ts +0 -10
  7. package/akanConfig/akanConfig.ts +1 -11
  8. package/akanContext.ts +43 -31
  9. package/applicationBuildRunner.test.ts +1 -1
  10. package/applicationBuildRunner.ts +1 -2
  11. package/biome.base.json +317 -0
  12. package/biomeBase.ts +9 -0
  13. package/capacitorApp.test.ts +8 -0
  14. package/capacitorApp.ts +112 -18
  15. package/executors.test.ts +42 -5
  16. package/executors.ts +44 -4
  17. package/frontendBuild/allRoutesBuilder.ts +27 -8
  18. package/frontendBuild/buildRouteClient.test.ts +28 -2
  19. package/frontendBuild/clientBuildTypes.ts +4 -0
  20. package/frontendBuild/clientEntriesBundler.ts +4 -1
  21. package/frontendBuild/cssCandidateCache.test.ts +38 -0
  22. package/frontendBuild/cssCandidateCache.ts +15 -3
  23. package/frontendBuild/cssCompiler.ts +122 -11
  24. package/frontendBuild/cssImportResolver.ts +8 -7
  25. package/frontendBuild/frontendBuild.test.ts +88 -1
  26. package/frontendBuild/precompressArtifacts.ts +35 -7
  27. package/frontendBuild/routeClientBuilder.ts +26 -7
  28. package/frontendBuild/ssrBaseArtifactBuilder.ts +20 -4
  29. package/frontendBuild/vendorSpecifiers.ts +1 -0
  30. package/getCredentials.ts +1 -3
  31. package/incrementalBuilder/devWatchBatch.test.ts +18 -20
  32. package/lint/no-bang-comment-in-client.grit +20 -0
  33. package/lint/no-import-client-in-server.grit +48 -0
  34. package/lint/no-import-server-in-client.grit +45 -0
  35. package/lint/no-model-type-in-util-zone.grit +16 -0
  36. package/lint/no-return-in-store-action.grit +35 -0
  37. package/linter.ts +17 -12
  38. package/package.json +4 -4
  39. package/qualityScanner.test.ts +23 -0
  40. package/qualityScanner.ts +5 -44
  41. package/repoIdentity.ts +42 -0
  42. package/routeSourceValidator.test.ts +41 -0
  43. package/routeSourceValidator.ts +2 -44
  44. package/scanInfo.ts +2 -43
  45. package/transforms/externalizeFrameworkPlugin.ts +0 -1
  46. package/workspaceLayout.test.ts +26 -0
  47. package/workspaceLayout.ts +60 -0
package/scanInfo.ts CHANGED
@@ -11,6 +11,7 @@ import type {
11
11
  } from "./akanConfig";
12
12
 
13
13
  import { AppExecutor, LibExecutor, PkgExecutor, WorkspaceExecutor } from "./executors";
14
+ import { appRootAllowedDirs, appRootAllowedFiles, libFacetRootAllowedFiles } from "./workspaceLayout";
14
15
 
15
16
  const scalarFileTypes = ["constant", "dictionary", "document", "template", "unit", "util", "view", "zone"] as const;
16
17
  type ScalarFileType = (typeof scalarFileTypes)[number];
@@ -43,49 +44,7 @@ type DatabaseFileType = (typeof databaseFileTypes)[number];
43
44
 
44
45
  type ModuleKind = "database" | "service" | "scalar";
45
46
 
46
- const appRootAllowedFiles = new Set([
47
- // 스코프 에이전트 가이드 — scan(write) 이 유지하는 색인 + 마커 밖 hand-written 내용 (agentsIndex.ts)
48
- "AGENTS.md",
49
- "CLAUDE.md",
50
- "akan.app.json",
51
- "akan.config.ts",
52
- "capacitor.config.ts",
53
- "client.ts",
54
- "main.ts",
55
- "package.json",
56
- "server.ts",
57
- "tsconfig.json",
58
- "tsconfig.tsbuildinfo",
59
- ]);
60
47
  const generatedRootCapacitorConfigFiles = ["capacitor.config.js", "capacitor.config.json"] as const;
61
- const appRootAllowedDirs = new Set([
62
- ".akan",
63
- "android",
64
- "env",
65
- "ios",
66
- "lib",
67
- "mobile",
68
- "page",
69
- "private",
70
- "public",
71
- "script",
72
- "ui",
73
- "srvkit",
74
- "webkit",
75
- "common",
76
- "secrets",
77
- ]);
78
- const libRootAllowedFiles = new Set([
79
- "cnst.ts",
80
- "db.ts",
81
- "dict.ts",
82
- "option.ts",
83
- "sig.ts",
84
- "srv.ts",
85
- "st.ts",
86
- "useClient.ts",
87
- "useServer.ts",
88
- ]);
89
48
  const internalLibDirs = new Set(["__lib", "__scalar"]);
90
49
  const moduleNonUiFileTypes = {
91
50
  database: new Set(["constant", "dictionary", "document", "service", "signal", "store"]),
@@ -107,7 +66,7 @@ const createDependencyScanner = async (exec: AppExecutor | LibExecutor | PkgExec
107
66
 
108
67
  const isAllowedTestFile = (filename: string) => testFilePattern.test(filename);
109
68
  const isAllowedLibRootFile = (filename: string) =>
110
- libRootAllowedFiles.has(filename) || rootSignalTestFilePattern.test(filename);
69
+ libFacetRootAllowedFiles.has(filename) || rootSignalTestFilePattern.test(filename);
111
70
  const getScanPath = (exec: AppExecutor | LibExecutor, relativePath: string) =>
112
71
  path.posix.join(`${exec.type}s`, exec.name, relativePath.split(path.sep).join("/"));
113
72
  async function clearGeneratedRootCapacitorConfigs(exec: AppExecutor | LibExecutor) {
@@ -65,7 +65,6 @@ const DEFAULT_EXCLUDE_PREFIX = ["@akanjs/cli/", "@akanjs/devkit/"];
65
65
  const OPTIONAL_BACKEND_EXTERNAL_EXACT = new Set<string>([
66
66
  "@libsql/client",
67
67
  "bullmq",
68
- "croner",
69
68
  "ioredis",
70
69
  "postgres",
71
70
  "protobufjs",
@@ -0,0 +1,26 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { appRootAllowedDirs, appRootAllowedFiles, isScannedAppRootEntry } from "./workspaceLayout";
3
+
4
+ describe("app root layout allowlist", () => {
5
+ test("admits the scoped agent guides sync writes into every app", () => {
6
+ expect(appRootAllowedFiles.has("AGENTS.md")).toBe(true);
7
+ expect(appRootAllowedFiles.has("CLAUDE.md")).toBe(true);
8
+ });
9
+
10
+ test("admits every documented app root folder", () => {
11
+ for (const dirname of ["mobile", "plugin", "secrets", "srvkit", "webkit"]) {
12
+ expect(appRootAllowedDirs.has(dirname)).toBe(true);
13
+ }
14
+ });
15
+
16
+ test("rejects an app root entry no facet owns", () => {
17
+ expect(appRootAllowedFiles.has("helper.ts")).toBe(false);
18
+ expect(appRootAllowedDirs.has("base")).toBe(false);
19
+ });
20
+
21
+ test("skips dotfile artifacts the sync glob never sees, but keeps .akan", () => {
22
+ expect(isScannedAppRootEntry(".DS_Store")).toBe(false);
23
+ expect(isScannedAppRootEntry(".akan")).toBe(true);
24
+ expect(isScannedAppRootEntry("lib")).toBe(true);
25
+ });
26
+ });
@@ -0,0 +1,60 @@
1
+ /**
2
+ * App/lib 루트 레이아웃 허용 목록 — 단일 소스.
3
+ *
4
+ * 같은 규칙을 scanInfo(`akan sync`, hard error) · akanContext(`akan doctor`, diagnostic) ·
5
+ * qualityScanner(`akan quality scan`, warning) 세 곳이 각자 복사해 두면서 실제로 어긋났다
6
+ * (스코프 AGENTS.md/CLAUDE.md 는 sync 만 허용, `plugin` 은 문서에만, `secrets` 는 doctor 만 거부).
7
+ * 규칙을 추가할 때는 이 파일만 고치고, 루트 AGENTS.md 의 목록도 같이 갱신한다.
8
+ */
9
+
10
+ export const appRootAllowedFiles = new Set([
11
+ // 스코프 에이전트 가이드 — scan(write) 이 유지하는 색인 + 마커 밖 hand-written 내용 (agentsIndex.ts)
12
+ "AGENTS.md",
13
+ "CLAUDE.md",
14
+ "akan.app.json",
15
+ "akan.config.ts",
16
+ "capacitor.config.ts",
17
+ "client.ts",
18
+ "main.ts",
19
+ "package.json",
20
+ "server.ts",
21
+ "tsconfig.json",
22
+ "tsconfig.tsbuildinfo",
23
+ ]);
24
+
25
+ export const appRootAllowedDirs = new Set([
26
+ ".akan",
27
+ "android",
28
+ "common",
29
+ "env",
30
+ "ios",
31
+ "lib",
32
+ "mobile",
33
+ "page",
34
+ "plugin",
35
+ "private",
36
+ "public",
37
+ "script",
38
+ "secrets",
39
+ "srvkit",
40
+ "ui",
41
+ "webkit",
42
+ ]);
43
+
44
+ export const libFacetRootAllowedFiles = new Set([
45
+ "cnst.ts",
46
+ "db.ts",
47
+ "dict.ts",
48
+ "option.ts",
49
+ "sig.ts",
50
+ "srv.ts",
51
+ "st.ts",
52
+ "useClient.ts",
53
+ "useServer.ts",
54
+ ]);
55
+
56
+ /**
57
+ * scanSync 는 앱 루트를 `Bun.Glob("*")` 로 읽어 dotfile 을 아예 보지 못한다. 디렉터리를 직접 읽는
58
+ * doctor 가 그 차이만큼 `.DS_Store` 같은 툴 산출물을 에러로 올리므로 같은 기준으로 걸러낸다.
59
+ */
60
+ export const isScannedAppRootEntry = (name: string) => !name.startsWith(".") || appRootAllowedDirs.has(name);