@akanjs/devkit 3.0.0-beta.2 → 3.0.0-beta.21

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 (289) hide show
  1. package/README.ko.md +2 -2
  2. package/README.md +3 -2
  3. package/abstractDoc.test.ts +6 -15
  4. package/abstractDoc.ts +6 -8
  5. package/agentsIndex.test.ts +4 -7
  6. package/agentsIndex.ts +6 -22
  7. package/akanApp/BackendImportGraph.test.ts +8 -22
  8. package/akanApp/BackendImportGraph.ts +1 -20
  9. package/akanApp/akanApp.host.test.ts +1 -3
  10. package/akanApp/akanApp.host.ts +82 -254
  11. package/akanApp/devHostPolicy.test.ts +10 -34
  12. package/akanApp/devHostPolicy.ts +12 -98
  13. package/akanConfig/akanConfig.test.ts +142 -106
  14. package/akanConfig/akanConfig.ts +147 -191
  15. package/akanConfig/types.ts +4 -3
  16. package/akanContext.ts +110 -160
  17. package/akanMcpContract.ts +28 -73
  18. package/appSelectionMemory.ts +1 -4
  19. package/applicationBuildReporter.ts +37 -5
  20. package/applicationBuildRunner.test.ts +5 -3
  21. package/applicationBuildRunner.ts +54 -61
  22. package/applicationTestPreload.ts +3 -12
  23. package/artifact/implicitRootLayout.test.ts +32 -30
  24. package/artifact/implicitRootLayout.ts +58 -106
  25. package/artifact/routeSeedIndex.test.ts +7 -6
  26. package/artifact/routeSeedIndex.ts +11 -44
  27. package/biome.base.json +32 -1
  28. package/biomeBase.ts +2 -5
  29. package/cloud/cloudApi.test.ts +202 -0
  30. package/cloud/cloudApi.ts +77 -39
  31. package/cloud/configLock.test.ts +64 -0
  32. package/cloud/configLock.ts +96 -0
  33. package/cloud/constants.ts +26 -5
  34. package/cloud/globalConfig.ts +70 -32
  35. package/codeAgent/agent/AkanCodeServices.ts +97 -0
  36. package/codeAgent/agent/AkanContextFiles.ts +94 -0
  37. package/codeAgent/agent/CodeAgent.ts +551 -0
  38. package/codeAgent/agent/CodeAgentAsks.ts +66 -0
  39. package/codeAgent/agent/CodeAgentEventMapper.ts +225 -0
  40. package/codeAgent/agent/CodeAgentGate.ts +93 -0
  41. package/codeAgent/agent/CodeAgentProxy.ts +82 -0
  42. package/codeAgent/agent/CodeAgentRpcHost.ts +103 -0
  43. package/codeAgent/agent/CodeAgentRpcListener.ts +109 -0
  44. package/codeAgent/agent/CodeAgentStreamPrinter.ts +86 -0
  45. package/codeAgent/agent/CodeAgentSuspended.ts +85 -0
  46. package/codeAgent/agent/CodeAgentUi.ts +47 -0
  47. package/codeAgent/agent/CodeMailbox.ts +148 -0
  48. package/codeAgent/agent/CodeSessionFork.ts +56 -0
  49. package/codeAgent/agent/CodeSessionIndex.ts +78 -0
  50. package/codeAgent/agent/SubagentPool.ts +214 -0
  51. package/codeAgent/agent/akanCodeModel.ts +47 -0
  52. package/codeAgent/agent/akanCodePaths.ts +31 -0
  53. package/codeAgent/agent/akanContextFiles.test.ts +114 -0
  54. package/codeAgent/agent/akanSystemPrompt.ts +46 -0
  55. package/codeAgent/agent/codeAgent.test.ts +178 -0
  56. package/codeAgent/agent/codeAgentContract.test.ts +523 -0
  57. package/codeAgent/agent/codeAgentProxy.test.ts +74 -0
  58. package/codeAgent/agent/codeAgentRpcListener.test.ts +113 -0
  59. package/codeAgent/agent/codeAgentSuspended.test.ts +47 -0
  60. package/codeAgent/agent/codeMailbox.test.ts +76 -0
  61. package/codeAgent/agent/codeSessionFork.test.ts +58 -0
  62. package/codeAgent/agent/codeSessionIndex.test.ts +77 -0
  63. package/codeAgent/agent/consoleToStderr.ts +8 -0
  64. package/codeAgent/agent/jsonLines.ts +29 -0
  65. package/codeAgent/agent/stringArg.ts +5 -0
  66. package/codeAgent/feedback/DevLogFeedback.ts +82 -0
  67. package/codeAgent/feedback/PreviewChrome.ts +82 -0
  68. package/codeAgent/feedback/PreviewFeedback.ts +46 -0
  69. package/codeAgent/feedback/PreviewView.ts +95 -0
  70. package/codeAgent/feedback/TurnFeedback.ts +98 -0
  71. package/codeAgent/feedback/VerifyFeedback.ts +40 -0
  72. package/codeAgent/feedback/previewChrome.test.ts +73 -0
  73. package/codeAgent/index.ts +34 -0
  74. package/codeAgent/skills/akan-code/SKILL.md +130 -0
  75. package/codeAgent/skills/akan-debug/SKILL.md +42 -0
  76. package/codeAgent/skills/akan-deps/SKILL.md +50 -0
  77. package/codeAgent/skills/akan-err/SKILL.md +39 -0
  78. package/codeAgent/skills/akan-module/SKILL.md +45 -0
  79. package/codeAgent/skills/akan-scaffold/SKILL.md +76 -0
  80. package/codeAgent/skills/akan-scalar/SKILL.md +52 -0
  81. package/codeAgent/skills/akan-service/SKILL.md +34 -0
  82. package/codeAgent/skills/akan-store/SKILL.md +67 -0
  83. package/codeAgent/skills/akan-ui/SKILL.md +63 -0
  84. package/codeAgent/skills/akan-validate/SKILL.md +44 -0
  85. package/codeAgent/tools/AkanCli.ts +50 -0
  86. package/codeAgent/tools/AkanCodePlugins.ts +136 -0
  87. package/codeAgent/tools/AkanEditScope.ts +48 -0
  88. package/codeAgent/tools/AkanEnvKeys.ts +50 -0
  89. package/codeAgent/tools/AkanToolPack.ts +92 -0
  90. package/codeAgent/tools/AkanVerifier.ts +48 -0
  91. package/codeAgent/tools/AskToolPack.ts +99 -0
  92. package/codeAgent/tools/MailToolPack.ts +76 -0
  93. package/codeAgent/tools/McpClient.ts +187 -0
  94. package/codeAgent/tools/McpOAuth.ts +233 -0
  95. package/codeAgent/tools/McpOAuthLoopback.ts +64 -0
  96. package/codeAgent/tools/McpServerConfig.ts +129 -0
  97. package/codeAgent/tools/McpSignIn.ts +158 -0
  98. package/codeAgent/tools/McpTokenStore.ts +81 -0
  99. package/codeAgent/tools/McpToolPack.ts +199 -0
  100. package/codeAgent/tools/SessionToolPack.ts +91 -0
  101. package/codeAgent/tools/WebToolPack.ts +147 -0
  102. package/codeAgent/tools/akanCodePlugins.test.ts +677 -0
  103. package/codeAgent/tools/askToolPack.test.ts +116 -0
  104. package/codeAgent/tools/mcpOAuth.test.ts +612 -0
  105. package/codeAgent/tools/mcpServerConfig.test.ts +212 -0
  106. package/codegenLock.test.ts +4 -13
  107. package/codegenLock.ts +3 -17
  108. package/commandDecorators/argMeta.ts +1 -5
  109. package/commandDecorators/camelToKebabCase.ts +1 -0
  110. package/commandDecorators/command.ts +46 -102
  111. package/commandDecorators/commandBuilder.ts +30 -61
  112. package/commandDecorators/commandDecorators.test.ts +2 -10
  113. package/commandDecorators/dependencyBuilder.ts +10 -1
  114. package/commandDecorators/helpFormatter.ts +68 -145
  115. package/commandDecorators/index.ts +0 -2
  116. package/commandDecorators/targetMeta.ts +9 -7
  117. package/createTunnel.ts +7 -14
  118. package/dependencyScanner.test.ts +4 -16
  119. package/dependencyScanner.ts +31 -80
  120. package/devkitUtils.test.ts +48 -20
  121. package/executors.linkFallback.test.ts +103 -0
  122. package/executors.test.ts +132 -106
  123. package/executors.ts +195 -496
  124. package/fileEditor.ts +9 -37
  125. package/{getDirname.test.ts → fileSys.test.ts} +5 -3
  126. package/fileSys.ts +6 -8
  127. package/formSetterScanner.ts +3 -16
  128. package/frontendBuild/allRoutesBuilder.ts +7 -21
  129. package/frontendBuild/autoImportSync.test.ts +27 -38
  130. package/frontendBuild/autoImportSync.ts +31 -65
  131. package/frontendBuild/buildRouteClient.test.ts +62 -37
  132. package/frontendBuild/bundleDefine.ts +12 -0
  133. package/frontendBuild/clientBuildTypes.ts +5 -36
  134. package/frontendBuild/clientEntriesBundler.ts +9 -40
  135. package/frontendBuild/clientEntryDiscovery.ts +6 -41
  136. package/frontendBuild/csrArtifactBuilder.ts +6 -25
  137. package/frontendBuild/cssCandidateCache.test.ts +0 -6
  138. package/frontendBuild/cssCandidateCache.ts +6 -41
  139. package/frontendBuild/cssCompiler.ts +29 -78
  140. package/frontendBuild/cssImportResolver.ts +6 -19
  141. package/frontendBuild/devChangePlanner.ts +7 -10
  142. package/frontendBuild/devGeneratedIndexSync.test.ts +12 -27
  143. package/frontendBuild/devGeneratedIndexSync.ts +1 -4
  144. package/frontendBuild/fontOptimizer.test.ts +6 -14
  145. package/frontendBuild/fontOptimizer.ts +15 -72
  146. package/frontendBuild/fontPruner.test.ts +5 -10
  147. package/frontendBuild/fontPruner.ts +5 -20
  148. package/frontendBuild/frontendBuild.test.ts +46 -69
  149. package/frontendBuild/hmrChangeClassifier.ts +2 -2
  150. package/frontendBuild/hmrWatcher.test.ts +8 -32
  151. package/frontendBuild/hmrWatcher.ts +14 -71
  152. package/frontendBuild/pagesBundleBuilder.ts +4 -29
  153. package/frontendBuild/precompressArtifacts.ts +5 -18
  154. package/frontendBuild/routeClientBuilder.ts +23 -46
  155. package/frontendBuild/routesManifestArtifactSerializer.ts +5 -36
  156. package/frontendBuild/sourceMtimeIndex.test.ts +41 -97
  157. package/frontendBuild/sourceMtimeIndex.ts +19 -130
  158. package/frontendBuild/ssrBaseArtifactBuilder.ts +2 -8
  159. package/frontendBuild/styleContract.ts +1 -8
  160. package/frontendBuild/themeValidator.ts +4 -26
  161. package/frontendBuild/watchRootResolver.test.ts +23 -42
  162. package/frontendBuild/watchRootResolver.ts +5 -27
  163. package/getRelatedCnsts.ts +12 -92
  164. package/incrementalBuilder/buildBatch.proc.ts +29 -58
  165. package/incrementalBuilder/buildBatchProtocol.ts +8 -36
  166. package/incrementalBuilder/buildBatchRunner.test.ts +34 -0
  167. package/incrementalBuilder/buildBatchRunner.ts +10 -31
  168. package/incrementalBuilder/builderChannel.test.ts +24 -49
  169. package/incrementalBuilder/builderChannel.ts +6 -37
  170. package/incrementalBuilder/builderRequestRouter.test.ts +0 -8
  171. package/incrementalBuilder/builderRequestRouter.ts +5 -24
  172. package/incrementalBuilder/devWatchBatch.test.ts +21 -24
  173. package/incrementalBuilder/incrementalBuilder.host.test.ts +18 -55
  174. package/incrementalBuilder/incrementalBuilder.host.ts +18 -76
  175. package/incrementalBuilder/incrementalBuilder.proc.test.ts +81 -0
  176. package/incrementalBuilder/incrementalBuilder.proc.ts +49 -161
  177. package/index.ts +5 -19
  178. package/integration/devResourceProbe.ts +50 -56
  179. package/integration/devStability.integration.test.ts +47 -194
  180. package/integration/devStabilityHarness.test.ts +13 -28
  181. package/integration/devStabilityHarness.ts +65 -330
  182. package/integration/ssrMemoryProbe.ts +41 -167
  183. package/libSource.test.ts +4 -15
  184. package/libSource.ts +19 -31
  185. package/lint/__fixtures__/no-document-cookie/bad.tsx +4 -0
  186. package/lint/__fixtures__/no-document-cookie/good.tsx +7 -0
  187. package/lint/__fixtures__/no-web-only-api-outside-webkit/bad.tsx +7 -0
  188. package/lint/__fixtures__/no-web-only-api-outside-webkit/good.tsx +11 -0
  189. package/lint/__fixtures__/no-web-storage/bad.tsx +6 -0
  190. package/lint/__fixtures__/no-web-storage/good.tsx +7 -0
  191. package/lint/gritRules.test.ts +8 -24
  192. package/lint/no-deep-internal-import.grit +2 -2
  193. package/lint/no-document-cookie.grit +29 -0
  194. package/lint/no-redeclare-predefined-endpoint.grit +2 -1
  195. package/lint/no-web-only-api-outside-webkit.grit +44 -0
  196. package/lint/no-web-storage.grit +30 -0
  197. package/linter.test.ts +1 -2
  198. package/linter.ts +26 -116
  199. package/mobile/index.ts +6 -0
  200. package/mobile/mobileTarget.ts +16 -13
  201. package/mobile/nativeApi.test.ts +30 -0
  202. package/mobile/nativeApi.ts +40 -0
  203. package/mobile/nativeApp.test.ts +85 -0
  204. package/mobile/nativeApp.ts +210 -0
  205. package/mobile/nativeConfig.test.ts +199 -0
  206. package/mobile/nativeConfig.ts +184 -0
  207. package/mobile/nativeWebDir.test.ts +80 -0
  208. package/mobile/nativeWebDir.ts +62 -0
  209. package/mobile/placeholderAppId.test.ts +13 -0
  210. package/mobile/placeholderAppId.ts +16 -0
  211. package/mobile/usageDescriptions.test.ts +27 -0
  212. package/mobile/usageDescriptions.ts +24 -0
  213. package/package.json +10 -10
  214. package/packageExports.test.ts +3 -18
  215. package/packageExportsMap.ts +3 -19
  216. package/piDependencyPins.test.ts +46 -0
  217. package/platformTest/BunTestReport.test.ts +60 -0
  218. package/platformTest/BunTestReport.ts +65 -0
  219. package/platformTest/IdleWatchedProcess.test.ts +56 -0
  220. package/platformTest/IdleWatchedProcess.ts +73 -0
  221. package/platformTest/LinuxDockerTarget.ts +105 -0
  222. package/platformTest/PlatformTestRun.test.ts +64 -0
  223. package/platformTest/PlatformTestRun.ts +141 -0
  224. package/platformTest/PlatformTestTarget.ts +142 -0
  225. package/platformTest/TestSnapshot.test.ts +72 -0
  226. package/platformTest/TestSnapshot.ts +103 -0
  227. package/platformTest/WindowsSshTarget.ts +151 -0
  228. package/prompter.ts +3 -13
  229. package/qualityScanner.test.ts +9 -26
  230. package/qualityScanner.ts +200 -286
  231. package/recipeScanner.test.ts +7 -12
  232. package/recipeScanner.ts +9 -38
  233. package/repoIdentity.ts +2 -9
  234. package/routeSourceValidator.test.ts +0 -1
  235. package/routeSourceValidator.ts +7 -42
  236. package/scanInfo.ts +91 -225
  237. package/selectModel.ts +1 -2
  238. package/semver.ts +3 -5
  239. package/slicePlanner.test.ts +6 -24
  240. package/slicePlanner.ts +11 -32
  241. package/spinner.test.ts +3 -8
  242. package/spinner.ts +4 -16
  243. package/sshTunnel.ts +1 -6
  244. package/ssrScanner.test.ts +1 -6
  245. package/ssrScanner.ts +103 -113
  246. package/stripAnsi.ts +3 -0
  247. package/subspace.test.ts +30 -25
  248. package/subspace.ts +81 -115
  249. package/subspaceConfig.ts +11 -9
  250. package/testHelpers.ts +194 -0
  251. package/transforms/asyncDefaultExportDetector.ts +3 -11
  252. package/transforms/barrelAnalyzer.ts +43 -135
  253. package/transforms/barrelImportsPlugin.ts +38 -175
  254. package/transforms/externalizeFrameworkPlugin.test.ts +39 -118
  255. package/transforms/externalizeFrameworkPlugin.ts +13 -87
  256. package/transforms/moduleSyntax.ts +32 -0
  257. package/transforms/rscUseClientTransform.ts +35 -20
  258. package/transforms/transforms.test.ts +153 -44
  259. package/transforms/tsconfigPackageResolver.test.ts +6 -24
  260. package/transforms/useClientBundlePlugin.ts +2 -22
  261. package/typeChecker.ts +7 -63
  262. package/types.ts +1 -0
  263. package/uploadRelease.ts +10 -25
  264. package/workflow/artifacts.ts +18 -0
  265. package/workflow/executor.test.ts +1 -12
  266. package/workflow/executor.ts +101 -110
  267. package/workflow/index.ts +0 -1
  268. package/workflow/moduleIndex.test.ts +4 -15
  269. package/workflow/moduleIndex.ts +9 -49
  270. package/workflow/plan.ts +18 -25
  271. package/workflow/render.ts +80 -96
  272. package/workflow/rolloutGate.test.ts +1 -1
  273. package/workflow/source.ts +52 -69
  274. package/workflow/sourceAst.ts +50 -0
  275. package/workspaceLayout.test.ts +13 -3
  276. package/workspaceLayout.ts +20 -23
  277. package/abstractCompactor.ts +0 -112
  278. package/aiEditor.test.ts +0 -60
  279. package/aiEditor.ts +0 -387
  280. package/applicationReleasePackager.ts +0 -209
  281. package/capacitorApp.test.ts +0 -372
  282. package/capacitorApp.ts +0 -1648
  283. package/commandDecorators/commandMeta.ts +0 -7
  284. package/commandDecorators/types.ts +0 -10
  285. package/getDirname.ts +0 -4
  286. package/guideline.ts +0 -19
  287. package/local/optimize-resource/ipcprobe/child.ts +0 -1
  288. package/local/optimize-resource/ipcprobe/parent.ts +0 -11
  289. package/workflow/primitive.ts +0 -59
@@ -2,7 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import type { AkanPlugin } from "akanjs";
5
- import { normalizeRoutePrefix } from "akanjs/base";
5
+ import { DatabaseModes, normalizeRoutePrefix } from "akanjs/base";
6
6
  import { type AkanI18nConfig, resolveAkanI18nConfig } from "akanjs/common";
7
7
  import type { AkanImageConfig } from "akanjs/server";
8
8
  import type { App, Lib } from "../commandDecorators";
@@ -11,6 +11,7 @@ import type { BaseDevEnv, PackageJson } from "../types";
11
11
  import {
12
12
  type AkanApiConfig,
13
13
  type AkanAssetsConfig,
14
+ type AkanDatabaseConfig,
14
15
  type AkanMobileConfig,
15
16
  type AkanMobileTargetConfig,
16
17
  type AkanRouteConfig,
@@ -31,78 +32,14 @@ import {
31
32
 
32
33
  const DEFAULT_BARREL_IMPORTS = ["akanjs/webkit", "akanjs/common", "akanjs/ui", "akanjs/server"];
33
34
  const DEFAULT_OPTIMIZE_IMPORTS = [
34
- "lucide-react",
35
- "date-fns",
36
- "lodash-es",
37
- "ramda",
38
- "antd",
39
- "react-bootstrap",
40
- "ahooks",
41
- "@ant-design/icons",
42
- "@headlessui/react",
43
- "@headlessui-float/react",
44
- "@heroicons/react/20/solid",
45
- "@heroicons/react/24/solid",
46
- "@heroicons/react/24/outline",
47
- "@visx/visx",
48
- "@tremor/react",
49
- "rxjs",
50
- "@mui/material",
51
- "@mui/icons-material",
52
- "recharts",
53
- "react-use",
54
- "@material-ui/core",
55
- "@material-ui/icons",
56
- "@tabler/icons-react",
57
- "mui-core",
58
- "react-icons/*",
59
- ];
35
+ "lucide-react date-fns lodash-es ramda antd react-bootstrap ahooks @ant-design/icons @headlessui/react",
36
+ "@headlessui-float/react @heroicons/react/20/solid @heroicons/react/24/solid @heroicons/react/24/outline",
37
+ "@visx/visx @tremor/react rxjs @mui/material @mui/icons-material recharts react-use @material-ui/core",
38
+ "@material-ui/icons @tabler/icons-react mui-core react-icons/*",
39
+ ].flatMap((line) => line.split(" "));
60
40
  const WORKSPACE_BARREL_FACETS = ["ui", "webkit", "common", "client", "server"] as const;
61
41
  const DEFAULT_DOCKER_IMAGE = "oven/bun:1-slim";
62
42
  const SSR_RUNTIME_PACKAGES = ["react", "react-dom", "react-server-dom-webpack"] as const;
63
- // The firebase client (push tokens) and the Capacitor toolchain — `@capacitor/cli` (`npx cap`),
64
- // `@capacitor/assets` (`npx @capacitor/assets`) plus the `@capacitor/core`/`ios`/`android` runtime
65
- // and native-platform packages that `npx cap add`/`sync` resolve from the workspace node_modules.
66
- // All are declared only as optional peers, so a fresh workspace never auto-installs them; the mobile
67
- // preflight installs them (together with MOBILE_APP_CAPACITOR_PLUGINS) at the workspace root.
68
- const MOBILE_RUNTIME_PACKAGES = [
69
- "@capacitor/cli",
70
- "@capacitor/core",
71
- "@capacitor/ios",
72
- "@capacitor/android",
73
- "@capacitor/assets",
74
- ] as const;
75
- // Capacitor plugins that must additionally be declared in the *app's* package.json
76
- // (apps/<app>/package.json): `npx cap sync` discovers plugins by scanning the app directory's
77
- // dependencies and registers their native code into the iOS/Android projects; packages present only
78
- // at the workspace root are never registered, so the JS bridge throws
79
- // `Capacitor plugin "Device" is not available.` at runtime. They are installed at the workspace root
80
- // alongside MOBILE_RUNTIME_PACKAGES (pinned via optional peers) and declared in the app with a "*"
81
- // range so bun dedupes them to that hoisted version instead of pinning a second source of truth.
82
- const MOBILE_APP_CAPACITOR_PLUGINS = [
83
- "@capacitor/app",
84
- "@capacitor/browser",
85
- "@capacitor/camera",
86
- "@capacitor/core",
87
- "@capacitor/device",
88
- "@capacitor/geolocation",
89
- "@capacitor/haptics",
90
- "@capacitor/inappbrowser",
91
- "@capacitor/keyboard",
92
- "@capacitor/preferences",
93
- "@capacitor/push-notifications",
94
- "capacitor-plugin-safe-area",
95
- ] as const;
96
- const DATABASE_MODE_RUNTIME_PACKAGES = {
97
- single: [],
98
- multiple: ["@libsql/client", "bullmq", "ioredis", "protobufjs"],
99
- cluster: ["bullmq", "ioredis", "postgres", "protobufjs"],
100
- } satisfies Record<DatabaseMode, readonly string[]>;
101
- const AKAN_RUNTIME_PACKAGES = new Set<string>([
102
- ...SSR_RUNTIME_PACKAGES,
103
- ...MOBILE_RUNTIME_PACKAGES,
104
- ...Object.values(DATABASE_MODE_RUNTIME_PACKAGES).flat(),
105
- ]);
106
43
  const DEFAULT_AKAN_IMAGE_CONFIG: AkanImageConfig = {
107
44
  deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
108
45
  imageSizes: [32, 48, 64, 96, 128, 256, 384],
@@ -130,18 +67,14 @@ const normalizeStringList = (values: string[] | undefined) => {
130
67
  return normalized.length > 0 ? [...new Set(normalized)] : undefined;
131
68
  };
132
69
 
133
- // Reduce a free-form name to a valid reverse-DNS / Android package segment: lowercase, alphanumerics
134
- // only (hyphens/spaces dropped), never empty, never starting with a digit.
70
+ // A reverse-DNS / Android package segment: lowercase alphanumerics, never empty, never starting with a digit.
135
71
  const sanitizeAppIdSegment = (value: string): string => {
136
72
  const cleaned = value.toLowerCase().replace(/[^a-z0-9]+/g, "");
137
73
  if (!cleaned) return "app";
138
74
  return /^[a-z]/.test(cleaned) ? cleaned : `app${cleaned}`;
139
75
  };
140
76
 
141
- // The default mobile bundle id for an app that has not pinned `mobile.appId`. Uses the workspace
142
- // (repo) name as the org segment so the default is far less collision-prone than a bare
143
- // `com.<appName>.app`, which Apple's portal routinely already has claimed. Apps that ship pin an
144
- // explicit appId, so this only affects unconfigured/dev apps.
77
+ // The repo name is the org segment: a bare `com.<appName>.app` is routinely already claimed on Apple's portal.
145
78
  export const deriveDefaultAppId = (orgName: string, appName: string): string =>
146
79
  `com.${sanitizeAppIdSegment(orgName)}.${sanitizeAppIdSegment(appName)}`;
147
80
 
@@ -174,13 +107,11 @@ const normalizeDeepLinks = (deepLinks: DeepPartial<AkanMobileTargetConfig["deepL
174
107
  } satisfies AkanMobileTargetConfig["deepLinks"];
175
108
  };
176
109
 
177
- /** What `akan.config.ts` may write: the resolved shape made partial, with `docker` and `web` in their unions. */
178
110
  type AppConfigDeclaration = Omit<DeepPartial<AppConfigResult>, "docker" | "web"> & {
179
111
  docker?: DockerOption;
180
112
  web?: AkanWebOption;
181
113
  };
182
114
 
183
- /** What the workspace's libs add to an app's build, read off each `libs/<lib>/akan.config.ts`. */
184
115
  export interface LibContributions {
185
116
  externalLibs: string[];
186
117
  docker: LibDockerConfig;
@@ -211,7 +142,7 @@ export class AkanAppConfig implements AppConfigResult {
211
142
  docker: DockerConfig;
212
143
  /** The Dockerfile `akan build` writes: the declared string verbatim, or one assembled from the parts. */
213
144
  dockerfile: string;
214
- defaultDatabaseMode: DatabaseMode;
145
+ database: AkanDatabaseConfig;
215
146
  web: AkanWebConfig;
216
147
  externalLibs: string[];
217
148
  barrelImports: string[];
@@ -225,7 +156,7 @@ export class AkanAppConfig implements AppConfigResult {
225
156
  hasMobileConfig: boolean;
226
157
  secrets: string[];
227
158
  assets: AkanAssetsConfig;
228
- /** Raw setting; resolved against the app's lib deps at sync time (see `AppExecutor.syncPages`). */
159
+ /** Raw setting, resolved against the app's lib deps at sync time. */
229
160
  syncPageLibs: string[] | boolean;
230
161
  baseDevEnv: BaseDevEnv;
231
162
  libs: string[];
@@ -250,7 +181,7 @@ export class AkanAppConfig implements AppConfigResult {
250
181
  this.baseDevEnv = baseDevEnv;
251
182
  this.plugins = plugins;
252
183
  this.#applyRoutes(config?.routes);
253
- this.defaultDatabaseMode = config?.defaultDatabaseMode ?? "single";
184
+ this.database = AkanAppConfig.#database(app, config);
254
185
  this.externalLibs = [...new Set([...(config?.externalLibs ?? []), ...libContributions.externalLibs])];
255
186
  this.barrelImports = [
256
187
  ...DEFAULT_BARREL_IMPORTS,
@@ -290,7 +221,7 @@ export class AkanAppConfig implements AppConfigResult {
290
221
  // `akan build-ios` / `build-android` copy `dist/apps/<app>/csr/<target>.html` into the native project.
291
222
  if (!resolved.csr && this.hasMobileConfig)
292
223
  throw new Error(
293
- `apps/${this.app.name}/akan.config.ts turns the CSR bundle off but declares mobile targets; the Capacitor build ships that bundle. Drop the mobile section or leave CSR on.`,
224
+ `apps/${this.app.name}/akan.config.ts turns the CSR bundle off but declares mobile targets; the mobile apps ship that bundle. Drop the mobile section or leave CSR on.`,
294
225
  );
295
226
  return resolved;
296
227
  }
@@ -300,10 +231,14 @@ export class AkanAppConfig implements AppConfigResult {
300
231
  indexPath: _indexPath,
301
232
  ...rawMobile
302
233
  } = (mobile ?? {}) as DeepPartial<AkanMobileConfig> & { indexPath?: unknown };
234
+ const configPath = `apps/${this.app.name}/akan.config.ts`;
235
+ AkanAppConfig.#assertMobileKeys(rawMobile, AkanAppConfig.#mobileKeys, "mobile", configPath);
303
236
  const appName = rawMobile.appName ?? this.app.name;
304
237
  const appId = rawMobile.appId ?? deriveDefaultAppId(this.baseDevEnv.repoName, this.app.name);
305
238
  const version = rawMobile.version ?? "0.0.1";
306
239
  const buildNum = rawMobile.buildNum ?? 1;
240
+ const files = AkanAppConfig.#resolveMobileFiles(rawMobile.files as AkanMobileConfig["files"], "mobile", configPath);
241
+ const native = rawMobile.native as AkanMobileConfig["native"];
307
242
  const defaultTargetName = this.#defaultMobileTargetName(rawTargets);
308
243
  const targetEntries = Object.entries(
309
244
  rawTargets ?? {
@@ -312,52 +247,114 @@ export class AkanAppConfig implements AppConfigResult {
312
247
  );
313
248
  const targets = Object.fromEntries(
314
249
  targetEntries.map(([name, rawTarget]) => {
315
- const target = rawTarget as DeepPartial<AkanMobileTargetConfig>;
250
+ const target = (rawTarget ?? {}) as DeepPartial<AkanMobileTargetConfig>;
251
+ const where = `mobile.targets.${name}`;
252
+ AkanAppConfig.#assertMobileKeys(target, AkanAppConfig.#targetKeys, where, configPath);
316
253
  const fallbackBasePath = !rawTargets && this.basePaths.has(name) ? name : undefined;
317
254
  const basePath = (target.basePath ?? fallbackBasePath)?.replace(/^\/+|\/+$/g, "") || undefined;
318
255
  const indexPath = normalizeIndexPath(target.indexPath as string | undefined);
319
256
  const deepLinks = normalizeDeepLinks(target.deepLinks);
320
257
  if (basePath && !this.basePaths.has(basePath)) {
321
- throw new Error(
322
- `Mobile target '${name}' uses unknown basePath '${basePath}' in apps/${this.app.name}/akan.config.ts`,
323
- );
258
+ throw new Error(`Mobile target '${name}' uses unknown basePath '${basePath}' in ${configPath}`);
324
259
  }
260
+ const targetFiles = AkanAppConfig.#resolveMobileFiles(
261
+ target.files as AkanMobileTargetConfig["files"],
262
+ where,
263
+ configPath,
264
+ );
265
+ const fileName = (target.fileName ?? rawMobile.fileName) as string | undefined;
325
266
  const resolved = {
326
- ...rawMobile,
327
- ...target,
328
267
  name,
329
268
  basePath,
330
269
  indexPath,
331
270
  deepLinks,
332
271
  appName: target.appName ?? appName,
333
272
  appId: target.appId ?? appId,
273
+ ...(fileName ? { fileName } : {}),
334
274
  version: target.version ?? version,
335
275
  buildNum: target.buildNum ?? buildNum,
336
- plugins: {
337
- ...rawMobile.plugins,
338
- ...target.plugins,
339
- },
340
- android: {
341
- ...rawMobile.android,
342
- ...target.android,
343
- },
344
- ios: {
345
- ...rawMobile.ios,
346
- ...target.ios,
347
- },
276
+ ...(target.assets ? { assets: target.assets as AkanMobileTargetConfig["assets"] } : {}),
277
+ ...(target.permissions ? { permissions: target.permissions as AkanMobileTargetConfig["permissions"] } : {}),
278
+ ...(files || targetFiles ? { files: { ...files, ...targetFiles } } : {}),
279
+ ...(native || target.native
280
+ ? { native: AkanAppConfig.#mergeNative(native, target.native as AkanMobileTargetConfig["native"]) }
281
+ : {}),
348
282
  } satisfies AkanMobileTargetConfig;
349
283
  return [name, resolved];
350
284
  }),
351
285
  );
352
286
  return {
353
- ...rawMobile,
354
287
  appName,
355
288
  appId,
289
+ ...(rawMobile.fileName ? { fileName: rawMobile.fileName as string } : {}),
356
290
  version,
357
291
  buildNum,
292
+ ...(files ? { files } : {}),
293
+ ...(native ? { native } : {}),
358
294
  targets,
359
- plugins: rawMobile.plugins,
360
- } as AkanMobileConfig;
295
+ };
296
+ }
297
+ static readonly #mobileKeys = ["appName", "appId", "fileName", "version", "buildNum", "files", "native"];
298
+ static readonly #targetKeys = [
299
+ "basePath",
300
+ "indexPath",
301
+ "appName",
302
+ "appId",
303
+ "fileName",
304
+ "version",
305
+ "buildNum",
306
+ "assets",
307
+ "permissions",
308
+ "deepLinks",
309
+ "files",
310
+ "native",
311
+ ];
312
+ //* The Capacitor keys used to pass straight through; the native runtime takes typed ones, so a leftover is refused.
313
+ static #assertMobileKeys(section: object, known: string[], where: string, configPath: string) {
314
+ for (const key of Object.keys(section)) {
315
+ if (known.includes(key)) continue;
316
+ if (key === "plugins" || key === "ios" || key === "android")
317
+ throw new Error(
318
+ `${where}.${key} in ${configPath} is a Capacitor setting. The native runtime reads native.plugins, native.ios.{infoPlist,entitlements} and native.android.{manifest,application,activity,googleServices} instead.`,
319
+ );
320
+ throw new Error(`${where}.${key} in ${configPath} is not a mobile setting. Known: ${known.join(", ")}.`);
321
+ }
322
+ }
323
+ static readonly #fileTargetPattern = /^(?:ios\/.+|android\/res\/[^/]+\/[^/]+|android\/assets\/.+)$/;
324
+ static #resolveMobileFiles(files: AkanMobileTargetConfig["files"] | undefined, where: string, configPath: string) {
325
+ if (!files) return undefined;
326
+ for (const [to, from] of Object.entries(files)) {
327
+ if (typeof from !== "string")
328
+ throw new Error(
329
+ `${where}.files in ${configPath} maps where a file lands to its source now, e.g. { "android/res/raw/chime.mp3": "assets/chime.mp3" }. google-services.json goes to native.android.googleServices, and GoogleService-Info.plist is no longer needed.`,
330
+ );
331
+ if (!AkanAppConfig.#fileTargetPattern.test(to))
332
+ throw new Error(
333
+ `${where}.files["${to}"] in ${configPath} must land under ios/<path>, android/res/<type>/<file> or android/assets/<path>.`,
334
+ );
335
+ }
336
+ return files;
337
+ }
338
+ static #mergeNative(
339
+ base: AkanMobileTargetConfig["native"],
340
+ override: AkanMobileTargetConfig["native"],
341
+ ): NonNullable<AkanMobileTargetConfig["native"]> {
342
+ const plugins = [...new Set([...(base?.plugins ?? []), ...(override?.plugins ?? [])])];
343
+ const ios = { ...base?.ios, ...override?.ios };
344
+ const android: NonNullable<NonNullable<AkanMobileTargetConfig["native"]>["android"]> = {
345
+ ...base?.android,
346
+ ...override?.android,
347
+ };
348
+ for (const key of ["manifest", "application", "activity"] as const) {
349
+ const merged = [...(base?.android?.[key] ?? []), ...(override?.android?.[key] ?? [])];
350
+ if (merged.length) android[key] = merged;
351
+ else delete android[key];
352
+ }
353
+ return {
354
+ ...(plugins.length ? { plugins } : {}),
355
+ ...(Object.keys(ios).length ? { ios } : {}),
356
+ ...(Object.keys(android).length ? { android } : {}),
357
+ };
361
358
  }
362
359
  #defaultMobileTargetName(rawTargets: DeepPartial<AkanMobileConfig>["targets"] | undefined) {
363
360
  if (rawTargets && Object.keys(rawTargets).length > 0) return Object.keys(rawTargets)[0] as string;
@@ -365,24 +362,12 @@ export class AkanAppConfig implements AppConfigResult {
365
362
  }
366
363
  #applyRoutes(routes: AkanRouteConfig[] = []) {
367
364
  for (const route of routes) {
368
- if (route.basePath) {
369
- const basePath = route.basePath.replace(/^\/+|\/+$/g, "");
370
- this.basePaths.add(basePath);
371
- const domains = this.subRoutes.getOrInsert(basePath, new Set());
372
- Object.keys(route.domains).forEach((branch) => void this.branches.add(branch));
373
- Object.values(route.domains)
374
- .flat()
375
- .forEach((domain) => {
376
- if (domain) domains.add(domain.toLowerCase().replace(/:\d+$/, ""));
377
- });
378
- } else {
379
- Object.keys(route.domains).forEach((branch) => void this.branches.add(branch));
380
- Object.values(route.domains)
381
- .flat()
382
- .forEach((domain) => {
383
- if (domain) this.domains.add(domain.toLowerCase().replace(/:\d+$/, ""));
384
- });
385
- }
365
+ const basePath = route.basePath ? route.basePath.replace(/^\/+|\/+$/g, "") : null;
366
+ if (basePath !== null) this.basePaths.add(basePath);
367
+ const domains = basePath !== null ? this.subRoutes.getOrInsert(basePath, new Set()) : this.domains;
368
+ for (const branch of Object.keys(route.domains)) this.branches.add(branch);
369
+ for (const domain of Object.values(route.domains).flat())
370
+ if (domain) domains.add(domain.toLowerCase().replace(/:\d+$/, ""));
386
371
  }
387
372
  const appName = this.app.name.toLowerCase();
388
373
  const serveDomain = this.baseDevEnv.serveDomain.toLowerCase();
@@ -426,11 +411,8 @@ export class AkanAppConfig implements AppConfigResult {
426
411
  const preRunScripts = this.#getDockerRunScripts(preRuns);
427
412
  const postRunScripts = this.#getDockerRunScripts(postRuns);
428
413
  const imageScript = this.#getDockerImageScript(image, DEFAULT_DOCKER_IMAGE);
429
- // The image default matches what the build actually produced; a deployment narrows it further with its
430
- // own env, and can never widen it past the artifacts that are in the image.
431
- // File logging is off in the image: a container's writable layer is ephemeral and nothing collects a
432
- // file from it, so the rotating files would only fill the node disk (50MB x 100 at `trace`). stdout is
433
- // the collection path; a deployment that wants the files back sets `AKAN_LOG_TO_FILE=1`.
414
+ // The web env matches what was built (a deployment can only narrow it). File logging is off: a container's
415
+ // writable layer is ephemeral and stdout is the collection path.
434
416
  const webEnvLines = [
435
417
  ...(this.web.ssr ? [] : ["ENV AKAN_SSR=false"]),
436
418
  ...(this.web.csr ? [] : ["ENV AKAN_CSR=false"]),
@@ -458,16 +440,13 @@ ENV AKAN_PUBLIC_LOCALES=${this.i18n.locales.join(",")}
458
440
  ENV AKAN_PUBLIC_API_PREFIX=${this.api.prefix}
459
441
  ENV AKAN_PUBLIC_WS_PREFIX=${this.api.websocketPrefix}
460
442
  ENV AKAN_PUBLIC_OPERATION_MODE=cloud
443
+ ENV AKAN_DATABASE_MODES=${this.database.modes.join(",")}
461
444
  ENV AKAN_LOG_TO_FILE=0
462
445
  ${webEnvLines}
463
446
  CMD [${command.map((c) => `"${c}"`).join(",")}]`;
464
447
  }
465
448
  static #importGeneration = 0;
466
- /**
467
- * Bun caches dynamic imports by path, so a plain re-import after the user edits the config file
468
- * returns the stale module. `bustImportCache` appends a fresh query string to force re-evaluation
469
- * of the config module itself; modules it imports keep their cached instances.
470
- */
449
+ // Bun caches dynamic imports by path; a fresh query string re-evaluates the config module (its imports stay cached).
471
450
  static async importConfigModule<T = unknown>(
472
451
  cwdPath: string,
473
452
  { bustImportCache = false }: { bustImportCache?: boolean } = {},
@@ -519,31 +498,37 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
519
498
  #resolveProductionDependencyVersion(lib: string) {
520
499
  const rootVersion = this.rootPackageJson.dependencies?.[lib] ?? this.rootPackageJson.devDependencies?.[lib];
521
500
  if (rootVersion) return rootVersion;
522
- // Fall back to the framework package's own (peer)dependencies so plugin-declared runtime
523
- // packages (e.g. firebase for the push plugin) resolve a version without the framework
524
- // hardcoding a per-feature package list.
501
+ // The framework's own (peer)dependencies resolve plugin runtime packages without a hardcoded list.
525
502
  const akanPackageJson = getAkanPackageJson();
526
- return akanPackageJson.dependencies?.[lib] ?? akanPackageJson.peerDependencies?.[lib];
503
+ const version = akanPackageJson.dependencies?.[lib] ?? akanPackageJson.peerDependencies?.[lib];
504
+ if (!version) throw new Error(`Dependency ${lib} not found in package.json`);
505
+ return version;
527
506
  }
528
507
  #getProductionRuntimePackages() {
529
- return [...this.externalLibs, ...SSR_RUNTIME_PACKAGES, ...this.getDatabaseModeRuntimePackages()];
508
+ return [
509
+ ...this.externalLibs,
510
+ ...SSR_RUNTIME_PACKAGES,
511
+ ...this.database.modes.flatMap((mode) => this.getDatabaseModeRuntimePackages(mode)),
512
+ ];
530
513
  }
531
- getDatabaseModeRuntimePackages(databaseMode: DatabaseMode = this.defaultDatabaseMode) {
532
- return [...DATABASE_MODE_RUNTIME_PACKAGES[databaseMode]];
514
+ getDatabaseModeRuntimePackages(databaseMode: DatabaseMode) {
515
+ return [...DatabaseModes.drivers[databaseMode]];
533
516
  }
534
- getMissingDatabaseModeDependencySpecs(databaseMode: DatabaseMode = this.defaultDatabaseMode) {
517
+ getMissingDatabaseModeDependencySpecs(databaseMode: DatabaseMode) {
535
518
  return this.#getMissingDependencySpecs(this.getDatabaseModeRuntimePackages(databaseMode));
536
519
  }
537
- getMobileRuntimePackages() {
538
- // The app Capacitor plugins are installed at the workspace root too, so bun can resolve the
539
- // app's "*" declarations to a hoisted, peer-pinned version instead of fetching latest.
540
- return [...new Set([...MOBILE_RUNTIME_PACKAGES, ...MOBILE_APP_CAPACITOR_PLUGINS])];
541
- }
542
- getMissingMobileDependencySpecs() {
543
- return this.#getMissingDependencySpecs(this.getMobileRuntimePackages());
520
+ /** The mode a CLI command runs this app in: the shell's `AKAN_DATABASE_MODE` if the app declares it, else the first. */
521
+ resolveDatabaseMode() {
522
+ return DatabaseModes.resolve({
523
+ requested: process.env.AKAN_DATABASE_MODE,
524
+ declared: this.database.modes.join(","),
525
+ local: true,
526
+ });
544
527
  }
545
- getMobileAppCapacitorPlugins() {
546
- return [...MOBILE_APP_CAPACITOR_PLUGINS];
528
+ static #database(app: App, config: AppConfigDeclaration): AkanDatabaseConfig {
529
+ const declared = config?.database?.modes?.filter((mode): mode is DatabaseMode => !!mode);
530
+ const modes = declared?.length ? declared : ["single"];
531
+ return { modes: DatabaseModes.parseList(modes.join(","), `database.modes in apps/${app.name}/akan.config.ts`) };
547
532
  }
548
533
  #getMissingDependencySpecs(libs: readonly string[]) {
549
534
  const rootDependencies = {
@@ -552,11 +537,10 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
552
537
  };
553
538
  return libs
554
539
  .filter((lib) => !rootDependencies[lib])
555
- .map((lib) => {
556
- const version = this.#resolveProductionDependencyVersion(lib);
557
- if (!version) throw new Error(`Dependency ${lib} not found in package.json`);
558
- return `${lib}@${version}`;
559
- });
540
+ .map((lib) => `${lib}@${this.#resolveProductionDependencyVersion(lib)}`);
541
+ }
542
+ get akanVersion() {
543
+ return getAkanPackageJson().version;
560
544
  }
561
545
  getProductionPackageJson(data: Partial<PackageJson> = {}): PackageJson {
562
546
  return {
@@ -565,11 +549,10 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
565
549
  version: "1.0.0",
566
550
  main: "./main.js",
567
551
  dependencies: Object.fromEntries(
568
- [...new Set(this.#getProductionRuntimePackages())].map((lib) => {
569
- const version = this.#resolveProductionDependencyVersion(lib);
570
- if (!version) throw new Error(`Dependency ${lib} not found in package.json`);
571
- return [lib, version];
572
- }),
552
+ [...new Set(this.#getProductionRuntimePackages())].map((lib) => [
553
+ lib,
554
+ this.#resolveProductionDependencyVersion(lib),
555
+ ]),
573
556
  ),
574
557
  ...data,
575
558
  };
@@ -643,41 +626,14 @@ export class AkanLibConfig implements LibConfigResult {
643
626
  }
644
627
  }
645
628
 
646
- // export const getCapacitorConfig = (configImp: AppConfig, appInfo: AppScanResult, tsconfig: TsConfigJson) => {
647
- // const props: RunnerProps = {
648
- // type: "app",
649
- // name: appInfo.name,
650
- // repoName: appInfo.repoName,
651
- // serveDomain: appInfo.serveDomain,
652
- // env: (process.env.AKAN_PUBLIC_ENV ?? "debug") as "testing" | "local" | "debug" | "develop" | "main",
653
- // libs: appInfo.libDeps,
654
- // tsconfig,
655
- // };
656
- // const config = typeof configImp === "function" ? configImp(props) : configImp;
657
- // const akanConfig = makeAppConfig(config, props);
658
- // return akanConfig;
659
- // };
660
-
661
629
  //! need to refactor
662
- export const increaseBuildNum = async (app: App) => {
663
- const appConfig = await AkanAppConfig.from(app);
630
+ const shiftBuildNum = async (app: App, delta: number) => {
631
+ const { buildNum } = (await AkanAppConfig.from(app)).mobile;
664
632
  const akanConfigPath = path.join(app.cwdPath, "akan.config.ts");
665
633
  const akanConfig = fs.readFileSync(akanConfigPath, "utf8");
666
- const akanConfigContent = akanConfig.replace(
667
- `buildNum: ${appConfig.mobile.buildNum}`,
668
- `buildNum: ${appConfig.mobile.buildNum + 1}`,
669
- );
670
- //? 개선할 여지가 있는지 확인
671
- fs.writeFileSync(akanConfigPath, akanConfigContent);
634
+ fs.writeFileSync(akanConfigPath, akanConfig.replace(`buildNum: ${buildNum}`, `buildNum: ${buildNum + delta}`));
672
635
  };
673
636
 
674
- export const decreaseBuildNum = async (app: App) => {
675
- const appConfig = await AkanAppConfig.from(app);
676
- const akanConfigPath = path.join(app.cwdPath, "akan.config.ts");
677
- const akanConfig = fs.readFileSync(akanConfigPath, "utf8");
678
- const akanConfigContent = akanConfig.replace(
679
- `buildNum: ${appConfig.mobile.buildNum}`,
680
- `buildNum: ${appConfig.mobile.buildNum - 1}`,
681
- );
682
- fs.writeFileSync(akanConfigPath, akanConfigContent);
683
- };
637
+ export const increaseBuildNum = async (app: App) => await shiftBuildNum(app, 1);
638
+
639
+ export const decreaseBuildNum = async (app: App) => await shiftBuildNum(app, -1);
@@ -2,12 +2,14 @@ export type {
2
2
  AkanApiConfig,
3
3
  AkanAssetsConfig,
4
4
  AkanConfigFile,
5
+ AkanDatabaseConfig,
5
6
  AkanExecutor,
6
7
  AkanMobileConfig,
8
+ AkanMobileNativeConfig,
7
9
  AkanMobileTargetConfig,
8
- AkanNativeContext,
10
+ AkanNativeValue,
9
11
  AkanPlugin,
10
- AkanPluginCapacitorConfig,
12
+ AkanPluginNativeConfig,
11
13
  AkanRouteConfig,
12
14
  AkanScanInfo,
13
15
  AkanSyncContext,
@@ -34,7 +36,6 @@ export type {
34
36
  MobileEnv,
35
37
  MobilePermission,
36
38
  PkgScanResult,
37
- PluginRuntimeContext,
38
39
  ScanResult,
39
40
  WorkspaceScanResult,
40
41
  } from "akanjs";