@akanjs/devkit 1.0.20 → 2.1.0-rc.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.
Files changed (195) hide show
  1. package/README.ko.md +65 -0
  2. package/README.md +62 -6
  3. package/aiEditor.ts +304 -0
  4. package/akanApp/akanApp.host.ts +393 -0
  5. package/akanApp/index.ts +1 -0
  6. package/akanConfig/akanConfig.test.ts +236 -0
  7. package/akanConfig/akanConfig.ts +384 -0
  8. package/akanConfig/index.ts +2 -0
  9. package/akanConfig/types.ts +23 -0
  10. package/applicationBuildReporter.ts +69 -0
  11. package/applicationBuildRunner.ts +302 -0
  12. package/applicationReleasePackager.ts +206 -0
  13. package/artifact/implicitRootLayout.ts +155 -0
  14. package/artifact/index.ts +1 -0
  15. package/artifact/routeSeedIndex.test.ts +98 -0
  16. package/artifact/routeSeedIndex.ts +130 -0
  17. package/auth.ts +41 -0
  18. package/builder.ts +164 -0
  19. package/capacitor.base.config.ts +88 -0
  20. package/capacitorApp.ts +440 -0
  21. package/commandDecorators/argMeta.ts +102 -0
  22. package/commandDecorators/command.ts +351 -0
  23. package/commandDecorators/commandBuilder.ts +224 -0
  24. package/commandDecorators/commandDecorators.test.ts +212 -0
  25. package/commandDecorators/commandMeta.ts +7 -0
  26. package/commandDecorators/dependencyBuilder.ts +100 -0
  27. package/{esm/src/commandDecorators/helpFormatter.js → commandDecorators/helpFormatter.ts} +100 -47
  28. package/{esm/src/commandDecorators/index.js → commandDecorators/index.ts} +4 -2
  29. package/commandDecorators/targetMeta.ts +31 -0
  30. package/commandDecorators/types.ts +10 -0
  31. package/constants.ts +25 -0
  32. package/createTunnel.ts +36 -0
  33. package/dependencyScanner.ts +357 -0
  34. package/devkitUtils.test.ts +259 -0
  35. package/executors.test.ts +315 -0
  36. package/executors.ts +1390 -0
  37. package/{esm/src/extractDeps.js → extractDeps.ts} +26 -20
  38. package/{esm/src/fileEditor.js → fileEditor.ts} +51 -32
  39. package/fileSys.ts +39 -0
  40. package/frontendBuild/allRoutesBuilder.ts +103 -0
  41. package/frontendBuild/buildRouteClient.test.ts +190 -0
  42. package/frontendBuild/clientBuildTypes.ts +114 -0
  43. package/frontendBuild/clientEntriesBundler.ts +303 -0
  44. package/frontendBuild/clientEntryDiscovery.ts +199 -0
  45. package/frontendBuild/csrArtifactBuilder.ts +237 -0
  46. package/frontendBuild/cssCompiler.ts +286 -0
  47. package/frontendBuild/cssImportResolver.ts +116 -0
  48. package/frontendBuild/fontOptimizer.ts +427 -0
  49. package/frontendBuild/frontendBuild.test.ts +204 -0
  50. package/frontendBuild/hmrChangeClassifier.ts +28 -0
  51. package/frontendBuild/hmrWatcher.ts +102 -0
  52. package/frontendBuild/index.ts +18 -0
  53. package/frontendBuild/pagesBundleBuilder.ts +137 -0
  54. package/frontendBuild/pagesEntrySourceGenerator.ts +37 -0
  55. package/frontendBuild/precompressArtifacts.ts +59 -0
  56. package/frontendBuild/routeClientBuilder.ts +290 -0
  57. package/frontendBuild/routesManifestArtifactSerializer.ts +62 -0
  58. package/frontendBuild/ssrBaseArtifactBuilder.ts +139 -0
  59. package/frontendBuild/vendorSpecifiers.ts +16 -0
  60. package/frontendBuild/watchRootResolver.ts +28 -0
  61. package/getCredentials.ts +19 -0
  62. package/getDirname.ts +3 -0
  63. package/getModelFileData.ts +59 -0
  64. package/getRelatedCnsts.ts +313 -0
  65. package/guideline.ts +19 -0
  66. package/incrementalBuilder/incrementalBuilder.host.test.ts +51 -0
  67. package/incrementalBuilder/incrementalBuilder.host.ts +152 -0
  68. package/incrementalBuilder/incrementalBuilder.proc.ts +331 -0
  69. package/incrementalBuilder/index.ts +1 -0
  70. package/{esm/src/index.js → index.ts} +28 -15
  71. package/lint/no-deep-internal-import.grit +25 -0
  72. package/lint/no-import-client-functions.grit +32 -0
  73. package/lint/no-import-external-library.grit +21 -0
  74. package/lint/no-js-private-class-method.grit +42 -0
  75. package/lint/no-use-client-in-server.grit +7 -0
  76. package/lint/non-scalar-props-restricted.grit +13 -0
  77. package/linter.ts +271 -0
  78. package/mobile/index.ts +1 -0
  79. package/mobile/mobileTarget.test.ts +53 -0
  80. package/mobile/mobileTarget.ts +88 -0
  81. package/package.json +48 -31
  82. package/prompter.ts +72 -0
  83. package/scanInfo.ts +606 -0
  84. package/selectModel.ts +11 -0
  85. package/{esm/src/spinner.js → spinner.ts} +22 -28
  86. package/{esm/src/capacitorApp.js → src/capacitorApp.ts} +82 -81
  87. package/sshTunnel.ts +152 -0
  88. package/{esm/src/streamAi.js → streamAi.ts} +18 -12
  89. package/transforms/barrelAnalyzer.ts +278 -0
  90. package/transforms/barrelImportsPlugin.ts +504 -0
  91. package/transforms/externalizeFrameworkPlugin.ts +185 -0
  92. package/transforms/index.ts +5 -0
  93. package/transforms/rscUseClientTransform.ts +59 -0
  94. package/transforms/transforms.test.ts +208 -0
  95. package/transforms/useClientBundlePlugin.ts +47 -0
  96. package/tsconfig.json +37 -0
  97. package/typeChecker.ts +264 -0
  98. package/types.ts +44 -0
  99. package/ui/MultiScrollList.tsx +242 -0
  100. package/ui/ScrollList.tsx +107 -0
  101. package/ui/index.ts +2 -0
  102. package/{esm/src/uploadRelease.js → uploadRelease.ts} +50 -34
  103. package/{esm/src/useStdoutDimensions.js → useStdoutDimensions.ts} +5 -5
  104. package/cjs/index.js +0 -21
  105. package/cjs/src/aiEditor.js +0 -311
  106. package/cjs/src/auth.js +0 -72
  107. package/cjs/src/builder.js +0 -114
  108. package/cjs/src/capacitorApp.js +0 -313
  109. package/cjs/src/commandDecorators/argMeta.js +0 -88
  110. package/cjs/src/commandDecorators/command.js +0 -324
  111. package/cjs/src/commandDecorators/commandMeta.js +0 -30
  112. package/cjs/src/commandDecorators/helpFormatter.js +0 -211
  113. package/cjs/src/commandDecorators/index.js +0 -31
  114. package/cjs/src/commandDecorators/targetMeta.js +0 -57
  115. package/cjs/src/commandDecorators/types.js +0 -15
  116. package/cjs/src/constants.js +0 -46
  117. package/cjs/src/createTunnel.js +0 -49
  118. package/cjs/src/dependencyScanner.js +0 -220
  119. package/cjs/src/executors.js +0 -964
  120. package/cjs/src/extractDeps.js +0 -103
  121. package/cjs/src/fileEditor.js +0 -120
  122. package/cjs/src/getCredentials.js +0 -44
  123. package/cjs/src/getDirname.js +0 -38
  124. package/cjs/src/getModelFileData.js +0 -66
  125. package/cjs/src/getRelatedCnsts.js +0 -260
  126. package/cjs/src/guideline.js +0 -15
  127. package/cjs/src/index.js +0 -65
  128. package/cjs/src/linter.js +0 -238
  129. package/cjs/src/prompter.js +0 -85
  130. package/cjs/src/scanInfo.js +0 -491
  131. package/cjs/src/selectModel.js +0 -46
  132. package/cjs/src/spinner.js +0 -93
  133. package/cjs/src/streamAi.js +0 -62
  134. package/cjs/src/typeChecker.js +0 -207
  135. package/cjs/src/types.js +0 -15
  136. package/cjs/src/uploadRelease.js +0 -112
  137. package/cjs/src/useStdoutDimensions.js +0 -43
  138. package/esm/index.js +0 -1
  139. package/esm/src/aiEditor.js +0 -282
  140. package/esm/src/auth.js +0 -42
  141. package/esm/src/builder.js +0 -81
  142. package/esm/src/commandDecorators/argMeta.js +0 -54
  143. package/esm/src/commandDecorators/command.js +0 -290
  144. package/esm/src/commandDecorators/commandMeta.js +0 -7
  145. package/esm/src/commandDecorators/targetMeta.js +0 -33
  146. package/esm/src/commandDecorators/types.js +0 -0
  147. package/esm/src/constants.js +0 -17
  148. package/esm/src/createTunnel.js +0 -26
  149. package/esm/src/dependencyScanner.js +0 -187
  150. package/esm/src/executors.js +0 -928
  151. package/esm/src/getCredentials.js +0 -11
  152. package/esm/src/getDirname.js +0 -5
  153. package/esm/src/getModelFileData.js +0 -33
  154. package/esm/src/getRelatedCnsts.js +0 -221
  155. package/esm/src/guideline.js +0 -0
  156. package/esm/src/linter.js +0 -205
  157. package/esm/src/prompter.js +0 -51
  158. package/esm/src/scanInfo.js +0 -455
  159. package/esm/src/selectModel.js +0 -13
  160. package/esm/src/typeChecker.js +0 -174
  161. package/esm/src/types.js +0 -0
  162. package/index.d.ts +0 -1
  163. package/src/aiEditor.d.ts +0 -50
  164. package/src/auth.d.ts +0 -9
  165. package/src/builder.d.ts +0 -18
  166. package/src/capacitorApp.d.ts +0 -39
  167. package/src/commandDecorators/argMeta.d.ts +0 -67
  168. package/src/commandDecorators/command.d.ts +0 -2
  169. package/src/commandDecorators/commandMeta.d.ts +0 -2
  170. package/src/commandDecorators/helpFormatter.d.ts +0 -3
  171. package/src/commandDecorators/index.d.ts +0 -6
  172. package/src/commandDecorators/targetMeta.d.ts +0 -19
  173. package/src/commandDecorators/types.d.ts +0 -1
  174. package/src/constants.d.ts +0 -26
  175. package/src/createTunnel.d.ts +0 -8
  176. package/src/dependencyScanner.d.ts +0 -23
  177. package/src/executors.d.ts +0 -296
  178. package/src/extractDeps.d.ts +0 -7
  179. package/src/fileEditor.d.ts +0 -16
  180. package/src/getCredentials.d.ts +0 -12
  181. package/src/getDirname.d.ts +0 -1
  182. package/src/getModelFileData.d.ts +0 -16
  183. package/src/getRelatedCnsts.d.ts +0 -53
  184. package/src/guideline.d.ts +0 -19
  185. package/src/index.d.ts +0 -23
  186. package/src/linter.d.ts +0 -109
  187. package/src/prompter.d.ts +0 -14
  188. package/src/scanInfo.d.ts +0 -82
  189. package/src/selectModel.d.ts +0 -1
  190. package/src/spinner.d.ts +0 -20
  191. package/src/streamAi.d.ts +0 -6
  192. package/src/typeChecker.d.ts +0 -52
  193. package/src/types.d.ts +0 -31
  194. package/src/uploadRelease.d.ts +0 -10
  195. package/src/useStdoutDimensions.d.ts +0 -1
@@ -0,0 +1,315 @@
1
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
+ import { mkdir, mkdtemp, readFile, rm, stat, writeFile } from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { AkanAppConfig } from "./akanConfig";
6
+ import { AppExecutor, Executor, PkgExecutor, WorkspaceExecutor } from "./executors";
7
+ import { AppInfo } from "./scanInfo";
8
+ import type { PackageJson } from "./types";
9
+
10
+ const originalEnv = { ...process.env };
11
+ const tempRoots: string[] = [];
12
+
13
+ const makeTempRoot = async () => {
14
+ const root = await mkdtemp(path.join(os.tmpdir(), "akan-devkit-"));
15
+ tempRoots.push(root);
16
+ return root;
17
+ };
18
+
19
+ const writeJson = async (filePath: string, value: object) => {
20
+ await mkdir(path.dirname(filePath), { recursive: true });
21
+ await writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`);
22
+ };
23
+
24
+ const rootPackageJson = (extra: Partial<PackageJson> = {}): PackageJson => ({
25
+ name: "fixture",
26
+ version: "1.0.0",
27
+ description: "fixture",
28
+ dependencies: {
29
+ react: "19.0.0",
30
+ "react-dom": "19.0.0",
31
+ "react-server-dom-webpack": "19.0.0",
32
+ sharp: "1.0.0",
33
+ lodash: "4.0.0",
34
+ },
35
+ devDependencies: {
36
+ typescript: "6.0.0",
37
+ },
38
+ ...extra,
39
+ });
40
+
41
+ beforeEach(() => {
42
+ process.env = { ...originalEnv };
43
+ });
44
+
45
+ afterEach(async () => {
46
+ process.env = { ...originalEnv };
47
+ await Promise.all(tempRoots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
48
+ });
49
+
50
+ describe("Executor filesystem helpers", () => {
51
+ test("resolves paths and reads/writes files relative to cwd", async () => {
52
+ const root = await makeTempRoot();
53
+ const exec = new Executor("fixture", root);
54
+
55
+ expect(exec.getPath("nested/file.txt")).toBe(path.join(root, "nested/file.txt"));
56
+ expect(exec.getPath("./relative.txt")).toBe(path.join(root, "relative.txt"));
57
+ expect(exec.getPath(root)).toBe(root);
58
+
59
+ await exec.mkdir("nested");
60
+ await exec.writeFile("nested/file.txt", "hello");
61
+ await exec.writeJson("nested/data.json", { ok: true });
62
+
63
+ expect(await exec.exists("nested/file.txt")).toBe(true);
64
+ expect(await exec.readFile("nested/file.txt")).toBe("hello");
65
+ expect(await exec.readJson("nested/data.json")).toEqual({ ok: true });
66
+ expect(await exec.readdir("nested")).toEqual(expect.arrayContaining(["file.txt", "data.json"]));
67
+
68
+ const entries = await exec.getFilesAndDirs(".");
69
+ expect(entries.dirs).toContain("nested");
70
+ });
71
+
72
+ test("applies CLI template files with dictionary replacement and overwrite control", async () => {
73
+ const root = await makeTempRoot();
74
+ const exec = new Executor("fixture", root);
75
+
76
+ const [created] = await exec.applyTemplate({
77
+ basePath: "local",
78
+ template: "localDev/docker-compose.yaml.template",
79
+ dict: { repoName: "sample" },
80
+ });
81
+ expect(created?.filePath).toBe(path.join(root, "local/docker-compose.yaml"));
82
+ expect(await readFile(path.join(root, "local/docker-compose.yaml"), "utf8")).toContain("sample-network");
83
+
84
+ await writeFile(path.join(root, "local/docker-compose.yaml"), "custom");
85
+ await exec.applyTemplate({
86
+ basePath: "local",
87
+ template: "localDev/docker-compose.yaml.template",
88
+ dict: { repoName: "changed" },
89
+ overwrite: false,
90
+ });
91
+ expect(await readFile(path.join(root, "local/docker-compose.yaml"), "utf8")).toBe("custom");
92
+ });
93
+
94
+ test("applies hidden files and directories from CLI templates", async () => {
95
+ const root = await makeTempRoot();
96
+ const exec = new Executor("fixture", root);
97
+
98
+ await exec.applyTemplate({
99
+ basePath: "workspace",
100
+ template: "workspaceRoot",
101
+ dict: { repoName: "sample", appName: "demo", serveDomain: "localhost" },
102
+ });
103
+
104
+ expect(await readFile(path.join(root, "workspace/.gitignore"), "utf8")).toContain("node_modules");
105
+ expect(await readFile(path.join(root, "workspace/.env"), "utf8")).toContain("AKAN_PUBLIC_REPO_NAME");
106
+ expect(await readFile(path.join(root, "workspace/.vscode/settings.json"), "utf8")).toContain("typescript.tsdk");
107
+ expect(await readFile(path.join(root, "workspace/biome.json"), "utf8")).toContain(
108
+ "./node_modules/@akanjs/devkit/lint/no-import-client-functions.grit",
109
+ );
110
+ });
111
+
112
+ test("copies static files from CLI templates", async () => {
113
+ const root = await makeTempRoot();
114
+ const exec = new Executor("fixture", root);
115
+
116
+ await exec.applyTemplate({
117
+ basePath: "app",
118
+ template: "app",
119
+ dict: { appName: "demo", companyName: "fixture", startDomain: "localhost" },
120
+ options: { libs: [] },
121
+ });
122
+
123
+ const templateRoot = path.resolve(import.meta.dir, "../cli/templates/app/public");
124
+ await expect(readFile(path.join(root, "app/public/logo.png"))).resolves.toEqual(
125
+ await readFile(path.join(templateRoot, "logo.png")),
126
+ );
127
+ await expect(readFile(path.join(root, "app/public/favicon.ico"))).resolves.toEqual(
128
+ await readFile(path.join(templateRoot, "favicon.ico")),
129
+ );
130
+ });
131
+ });
132
+
133
+ describe("Workspace and app executor environment contracts", () => {
134
+ test("reads base development environment and reports required missing values", () => {
135
+ process.env.AKAN_PUBLIC_REPO_NAME = "repo";
136
+ process.env.AKAN_PUBLIC_SERVE_DOMAIN = "example.com";
137
+ process.env.AKAN_PUBLIC_ENV = "local";
138
+ process.env.AKAN_PUBLIC_APP_NAME = "demo";
139
+ process.env.AKAN_WORKSPACE_ROOT = "/workspace";
140
+ process.env.PORT_OFFSET = "10";
141
+
142
+ expect(WorkspaceExecutor.getBaseDevEnv()).toEqual({
143
+ appName: "demo",
144
+ workspaceRoot: "/workspace",
145
+ repoName: "repo",
146
+ serveDomain: "example.com",
147
+ env: "local",
148
+ portOffset: 10,
149
+ });
150
+
151
+ delete process.env.AKAN_PUBLIC_REPO_NAME;
152
+ expect(() => WorkspaceExecutor.getBaseDevEnv()).toThrow("AKAN_PUBLIC_REPO_NAME is not set");
153
+ });
154
+
155
+ test("reads base development environment from an explicit env file", async () => {
156
+ const root = await makeTempRoot();
157
+ await writeFile(
158
+ path.join(root, ".env"),
159
+ [
160
+ "AKAN_PUBLIC_REPO_NAME=file-repo",
161
+ 'AKAN_PUBLIC_SERVE_DOMAIN="file.example.com"',
162
+ "AKAN_PUBLIC_ENV=develop",
163
+ "AKAN_WORKSPACE_ROOT=/from-file",
164
+ "AKAN_PUBLIC_APP_NAME=file-app",
165
+ "PORT_OFFSET=7",
166
+ "",
167
+ ].join("\n"),
168
+ );
169
+ delete process.env.AKAN_PUBLIC_REPO_NAME;
170
+ delete process.env.AKAN_PUBLIC_SERVE_DOMAIN;
171
+
172
+ expect(WorkspaceExecutor.getBaseDevEnv(path.join(root, ".env"))).toEqual({
173
+ appName: "file-app",
174
+ workspaceRoot: "/from-file",
175
+ repoName: "file-repo",
176
+ serveDomain: "file.example.com",
177
+ env: "develop",
178
+ portOffset: 7,
179
+ });
180
+ });
181
+
182
+ test("builds app command environment and prepareCommand artifacts", async () => {
183
+ const root = await makeTempRoot();
184
+ process.env.AKAN_PUBLIC_REPO_NAME = "repo";
185
+ process.env.AKAN_PUBLIC_SERVE_DOMAIN = "example.com";
186
+ process.env.AKAN_PUBLIC_ENV = "local";
187
+ process.env.PORT_OFFSET = "3";
188
+
189
+ await writeJson(path.join(root, "package.json"), rootPackageJson());
190
+ await mkdir(path.join(root, "apps/demo/private"), { recursive: true });
191
+ await mkdir(path.join(root, "apps/demo/public"), { recursive: true });
192
+ await writeFile(
193
+ path.join(root, "apps/demo/akan.config.ts"),
194
+ [
195
+ "export default {",
196
+ ' routes: [{ basePath: "admin", domains: { debug: ["Admin.Debug.Example.com:8282"] } }],',
197
+ ' i18n: { locales: ["en", "ko"], defaultLocale: "ko" },',
198
+ "};",
199
+ "",
200
+ ].join("\n"),
201
+ );
202
+
203
+ const workspace = new WorkspaceExecutor({ workspaceRoot: root, repoName: "repo" });
204
+ const app = AppExecutor.from(workspace, "demo");
205
+ const env = app.getCommandEnv({ EXTRA: "ok" });
206
+ expect(env.AKAN_PUBLIC_APP_NAME).toBe("demo");
207
+ expect(env.AKAN_WORKSPACE_ROOT).toBe(root);
208
+ expect(env.PORT).toBe("8285");
209
+ expect(env.AKAN_PUBLIC_CLIENT_PORT).toBe("8285");
210
+ expect(env.AKAN_PUBLIC_SERVER_PORT).toBe("8285");
211
+ expect(env.EXTRA).toBe("ok");
212
+
213
+ const prepared = await app.prepareCommand("build");
214
+ expect(prepared.env.AKAN_COMMAND_TYPE).toBe("build");
215
+ expect(prepared.env.AKAN_PUBLIC_BASE_PATHS).toBe("admin");
216
+ expect((await stat(path.join(root, "dist/apps/demo/private"))).isDirectory()).toBe(true);
217
+ expect((await stat(path.join(root, "dist/apps/demo/public"))).isDirectory()).toBe(true);
218
+ });
219
+ });
220
+
221
+ describe("PkgExecutor package generation", () => {
222
+ test("generates dist package metadata from root dependency versions", async () => {
223
+ const root = await makeTempRoot();
224
+ await writeJson(path.join(root, "package.json"), rootPackageJson());
225
+ await writeJson(path.join(root, "pkgs/@sample/tool/package.json"), {
226
+ name: "@sample/tool",
227
+ version: "0.1.0",
228
+ description: "tool",
229
+ exports: { "./extra": { import: "./extra.ts" } },
230
+ peerDependencies: { react: "19.0.0" },
231
+ peerDependenciesMeta: { react: { optional: true } },
232
+ optionalDependencies: { sharp: "1.0.0" },
233
+ });
234
+
235
+ const workspace = new WorkspaceExecutor({ workspaceRoot: root, repoName: "repo" });
236
+ const pkg = PkgExecutor.from(workspace, "@sample/tool");
237
+ const distPackageJson = await pkg.generateDistPackageJson(["lodash"], ["typescript"]);
238
+
239
+ expect(distPackageJson).toMatchObject({
240
+ name: "@sample/tool",
241
+ type: "module",
242
+ engines: { bun: ">=1.3.13" },
243
+ dependencies: { lodash: "4.0.0" },
244
+ devDependencies: { typescript: "6.0.0" },
245
+ peerDependencies: { react: "19.0.0" },
246
+ peerDependenciesMeta: { react: { optional: true } },
247
+ optionalDependencies: { sharp: "1.0.0" },
248
+ });
249
+ expect(distPackageJson.exports?.["."]).toEqual({
250
+ import: "./index.ts",
251
+ types: "./index.ts",
252
+ default: "./index.ts",
253
+ });
254
+ expect(await Bun.file(path.join(root, "dist/pkgs/@sample/tool/package.json")).json()).toEqual(distPackageJson);
255
+ expect(await Bun.file(path.join(root, "pkgs/@sample/tool/package.json")).json()).toEqual(distPackageJson);
256
+ });
257
+ });
258
+
259
+ describe("scan info construction", () => {
260
+ test("indexes database, service, and scalar file conventions from prepared scan results", () => {
261
+ const root = "/workspace";
262
+ const workspace = new WorkspaceExecutor({ workspaceRoot: root, repoName: "repo" });
263
+ const app = AppExecutor.from(workspace, "demo");
264
+ const config = new AkanAppConfig(
265
+ app,
266
+ [],
267
+ rootPackageJson(),
268
+ {},
269
+ {
270
+ repoName: "repo",
271
+ serveDomain: "example.com",
272
+ env: "debug",
273
+ portOffset: 0,
274
+ workspaceRoot: root,
275
+ },
276
+ );
277
+
278
+ const info = new AppInfo(
279
+ app,
280
+ {
281
+ name: "demo",
282
+ type: "app",
283
+ repoName: "repo",
284
+ serveDomain: "example.com",
285
+ akanConfig: config,
286
+ files: {
287
+ constant: { databases: ["post"], scalars: ["money"] },
288
+ dictionary: { databases: ["post"], services: ["auth"], scalars: ["money"] },
289
+ document: { databases: ["post"], scalars: ["money"] },
290
+ service: { databases: ["post"], services: ["auth"] },
291
+ signal: { databases: ["post"], services: ["auth"] },
292
+ store: { databases: [], services: [] },
293
+ template: { databases: [], services: [], scalars: [] },
294
+ unit: { databases: [], services: [], scalars: [] },
295
+ util: { databases: [], services: [], scalars: [] },
296
+ view: { databases: [], services: [], scalars: [] },
297
+ zone: { databases: [], services: [], scalars: [] },
298
+ },
299
+ libDeps: [],
300
+ pkgDeps: [],
301
+ dependencies: [],
302
+ devDependencies: [],
303
+ routes: ["./_index.tsx"],
304
+ },
305
+ [],
306
+ );
307
+
308
+ expect(info.getDatabaseModules()).toEqual(["post"]);
309
+ expect(info.getServiceModules()).toEqual(["auth"]);
310
+ expect(info.getScalarModules()).toEqual(["money"]);
311
+ expect(info.file.constant.databases.has("post")).toBe(true);
312
+ expect(info.file.dictionary.services.has("auth")).toBe(true);
313
+ expect(info.file.document.scalars.has("money")).toBe(true);
314
+ });
315
+ });