@akanjs/devkit 3.0.0-beta.9 → 3.0.0

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 (341) hide show
  1. package/DEV_RUNTIME_KNOBS.md +44 -26
  2. package/README.ko.md +21 -7
  3. package/README.md +17 -8
  4. package/abstractDoc.test.ts +6 -15
  5. package/abstractDoc.ts +6 -8
  6. package/agentsIndex.test.ts +4 -7
  7. package/agentsIndex.ts +6 -22
  8. package/akanApp/BackendImportGraph.test.ts +8 -22
  9. package/akanApp/BackendImportGraph.ts +1 -20
  10. package/akanApp/akanApp.host.test.ts +56 -3
  11. package/akanApp/akanApp.host.ts +218 -278
  12. package/akanApp/devBootLatch.test.ts +39 -0
  13. package/akanApp/devBootLatch.ts +39 -0
  14. package/akanApp/devHostPolicy.test.ts +81 -35
  15. package/akanApp/devHostPolicy.ts +41 -102
  16. package/akanConfig/akanBin.test.ts +62 -0
  17. package/akanConfig/akanBin.ts +78 -0
  18. package/akanConfig/akanConfig.test.ts +439 -141
  19. package/akanConfig/akanConfig.ts +359 -275
  20. package/akanConfig/index.ts +1 -0
  21. package/akanConfig/types.ts +22 -8
  22. package/akanContext.ts +110 -160
  23. package/akanMcpContract.ts +28 -73
  24. package/appSelectionMemory.ts +1 -4
  25. package/applicationBuildReporter.ts +37 -5
  26. package/applicationBuildRunner.test.ts +41 -5
  27. package/applicationBuildRunner.ts +71 -63
  28. package/applicationTestPreload.ts +3 -12
  29. package/artifact/implicitRootLayout.test.ts +32 -30
  30. package/artifact/implicitRootLayout.ts +58 -106
  31. package/artifact/routeSeedIndex.test.ts +7 -6
  32. package/artifact/routeSeedIndex.ts +11 -44
  33. package/biome.base.json +35 -2
  34. package/biomeBase.ts +2 -5
  35. package/cloud/cloudApi.test.ts +202 -0
  36. package/cloud/cloudApi.ts +77 -39
  37. package/cloud/configLock.test.ts +64 -0
  38. package/cloud/configLock.ts +96 -0
  39. package/cloud/constants.ts +26 -5
  40. package/cloud/globalConfig.ts +71 -32
  41. package/codeAgent/agent/AkanCodeServices.ts +97 -0
  42. package/codeAgent/agent/AkanContextFiles.ts +94 -0
  43. package/codeAgent/agent/CodeAgent.ts +551 -0
  44. package/codeAgent/agent/CodeAgentAsks.ts +66 -0
  45. package/codeAgent/agent/CodeAgentEventMapper.ts +225 -0
  46. package/codeAgent/agent/CodeAgentGate.ts +93 -0
  47. package/codeAgent/agent/CodeAgentProxy.ts +82 -0
  48. package/codeAgent/agent/CodeAgentRpcHost.ts +103 -0
  49. package/codeAgent/agent/CodeAgentRpcListener.ts +109 -0
  50. package/codeAgent/agent/CodeAgentStreamPrinter.ts +86 -0
  51. package/codeAgent/agent/CodeAgentSuspended.ts +85 -0
  52. package/codeAgent/agent/CodeAgentUi.ts +47 -0
  53. package/codeAgent/agent/CodeMailbox.ts +148 -0
  54. package/codeAgent/agent/CodeSessionFork.ts +56 -0
  55. package/codeAgent/agent/CodeSessionIndex.ts +78 -0
  56. package/codeAgent/agent/SubagentPool.ts +214 -0
  57. package/codeAgent/agent/akanCodeModel.ts +47 -0
  58. package/codeAgent/agent/akanCodePaths.ts +31 -0
  59. package/codeAgent/agent/akanContextFiles.test.ts +114 -0
  60. package/codeAgent/agent/akanSystemPrompt.ts +46 -0
  61. package/codeAgent/agent/codeAgent.test.ts +178 -0
  62. package/codeAgent/agent/codeAgentContract.test.ts +523 -0
  63. package/codeAgent/agent/codeAgentProxy.test.ts +74 -0
  64. package/codeAgent/agent/codeAgentRpcListener.test.ts +113 -0
  65. package/codeAgent/agent/codeAgentSuspended.test.ts +47 -0
  66. package/codeAgent/agent/codeMailbox.test.ts +76 -0
  67. package/codeAgent/agent/codeSessionFork.test.ts +58 -0
  68. package/codeAgent/agent/codeSessionIndex.test.ts +77 -0
  69. package/codeAgent/agent/consoleToStderr.ts +8 -0
  70. package/codeAgent/agent/jsonLines.ts +29 -0
  71. package/codeAgent/agent/stringArg.ts +5 -0
  72. package/codeAgent/feedback/DevLogFeedback.ts +82 -0
  73. package/codeAgent/feedback/PreviewChrome.ts +82 -0
  74. package/codeAgent/feedback/PreviewFeedback.ts +46 -0
  75. package/codeAgent/feedback/PreviewView.ts +95 -0
  76. package/codeAgent/feedback/TurnFeedback.ts +98 -0
  77. package/codeAgent/feedback/VerifyFeedback.ts +40 -0
  78. package/codeAgent/feedback/previewChrome.test.ts +73 -0
  79. package/codeAgent/index.ts +34 -0
  80. package/codeAgent/skills/akan-code/SKILL.md +130 -0
  81. package/codeAgent/skills/akan-debug/SKILL.md +42 -0
  82. package/codeAgent/skills/akan-deps/SKILL.md +50 -0
  83. package/codeAgent/skills/akan-err/SKILL.md +39 -0
  84. package/codeAgent/skills/akan-module/SKILL.md +45 -0
  85. package/codeAgent/skills/akan-scaffold/SKILL.md +76 -0
  86. package/codeAgent/skills/akan-scalar/SKILL.md +52 -0
  87. package/codeAgent/skills/akan-service/SKILL.md +34 -0
  88. package/codeAgent/skills/akan-store/SKILL.md +67 -0
  89. package/codeAgent/skills/akan-ui/SKILL.md +63 -0
  90. package/codeAgent/skills/akan-validate/SKILL.md +44 -0
  91. package/codeAgent/tools/AkanCli.ts +50 -0
  92. package/codeAgent/tools/AkanCodePlugins.ts +136 -0
  93. package/codeAgent/tools/AkanEditScope.ts +48 -0
  94. package/codeAgent/tools/AkanEnvKeys.ts +50 -0
  95. package/codeAgent/tools/AkanToolPack.ts +92 -0
  96. package/codeAgent/tools/AkanVerifier.ts +48 -0
  97. package/codeAgent/tools/AskToolPack.ts +99 -0
  98. package/codeAgent/tools/MailToolPack.ts +76 -0
  99. package/codeAgent/tools/McpClient.ts +187 -0
  100. package/codeAgent/tools/McpOAuth.ts +233 -0
  101. package/codeAgent/tools/McpOAuthLoopback.ts +64 -0
  102. package/codeAgent/tools/McpServerConfig.ts +129 -0
  103. package/codeAgent/tools/McpSignIn.ts +158 -0
  104. package/codeAgent/tools/McpTokenStore.ts +81 -0
  105. package/codeAgent/tools/McpToolPack.ts +199 -0
  106. package/codeAgent/tools/SessionToolPack.ts +91 -0
  107. package/codeAgent/tools/WebToolPack.ts +147 -0
  108. package/codeAgent/tools/akanCodePlugins.test.ts +677 -0
  109. package/codeAgent/tools/askToolPack.test.ts +116 -0
  110. package/codeAgent/tools/mcpOAuth.test.ts +612 -0
  111. package/codeAgent/tools/mcpServerConfig.test.ts +212 -0
  112. package/codegenLock.test.ts +4 -13
  113. package/codegenLock.ts +3 -17
  114. package/commandDecorators/argMeta.ts +1 -5
  115. package/commandDecorators/camelToKebabCase.ts +1 -0
  116. package/commandDecorators/command.ts +46 -102
  117. package/commandDecorators/commandBuilder.ts +30 -61
  118. package/commandDecorators/commandDecorators.test.ts +2 -10
  119. package/commandDecorators/dependencyBuilder.ts +10 -1
  120. package/commandDecorators/helpFormatter.ts +68 -145
  121. package/commandDecorators/index.ts +0 -2
  122. package/commandDecorators/targetMeta.ts +9 -7
  123. package/createTunnel.ts +7 -14
  124. package/csrE2e/csrE2eHarness.fixture.ts +505 -0
  125. package/csrE2e/csrFastRefresh.e2e.test.ts +233 -0
  126. package/csrE2e/csrPageStack.e2e.test.ts +252 -0
  127. package/csrE2e/csrPatchFirst.e2e.test.ts +87 -0
  128. package/csrE2e/csrRootLayout.e2e.test.ts +134 -0
  129. package/csrE2e/devHmrLatency.e2e.test.ts +391 -0
  130. package/csrE2e/registryVendor.e2e.test.ts +221 -0
  131. package/csrE2e/ssrRegistry.e2e.test.ts +644 -0
  132. package/dependencyScanner.test.ts +4 -16
  133. package/dependencyScanner.ts +31 -80
  134. package/devkitUtils.test.ts +48 -20
  135. package/executors.linkFallback.test.ts +103 -0
  136. package/executors.test.ts +176 -106
  137. package/executors.ts +212 -498
  138. package/fileEditor.ts +9 -37
  139. package/{getDirname.test.ts → fileSys.test.ts} +5 -3
  140. package/fileSys.ts +22 -9
  141. package/formSetterScanner.ts +3 -16
  142. package/frontendBuild/allRoutesBuilder.ts +7 -21
  143. package/frontendBuild/autoImportSync.test.ts +27 -38
  144. package/frontendBuild/autoImportSync.ts +31 -65
  145. package/frontendBuild/buildRouteClient.test.ts +123 -37
  146. package/frontendBuild/bundleDefine.test.ts +12 -0
  147. package/frontendBuild/bundleDefine.ts +16 -0
  148. package/frontendBuild/clientBuildTypes.ts +5 -36
  149. package/frontendBuild/clientEntriesBundler.ts +9 -40
  150. package/frontendBuild/clientEntryDiscovery.test.ts +112 -0
  151. package/frontendBuild/clientEntryDiscovery.ts +122 -110
  152. package/frontendBuild/csrArtifactBuilder.ts +9 -31
  153. package/frontendBuild/csrDevArtifactWriter.test.ts +151 -0
  154. package/frontendBuild/csrDevArtifactWriter.ts +307 -0
  155. package/frontendBuild/csrDevBundler.test.ts +66 -0
  156. package/frontendBuild/csrDevBundler.ts +95 -0
  157. package/frontendBuild/csrDevFactoryCheck.test.ts +33 -0
  158. package/frontendBuild/csrDevFactoryCheck.ts +39 -0
  159. package/frontendBuild/csrDevModuleCompiler.test.ts +293 -0
  160. package/frontendBuild/csrDevModuleCompiler.ts +422 -0
  161. package/frontendBuild/csrDevPatcher.test.ts +572 -0
  162. package/frontendBuild/csrDevPatcher.ts +548 -0
  163. package/frontendBuild/csrDevPaths.ts +145 -0
  164. package/frontendBuild/csrDevResolver.test.ts +239 -0
  165. package/frontendBuild/csrDevResolver.ts +363 -0
  166. package/frontendBuild/csrDevTypes.ts +61 -0
  167. package/frontendBuild/csrEntryFiles.ts +24 -0
  168. package/frontendBuild/cssCandidateCache.test.ts +0 -6
  169. package/frontendBuild/cssCandidateCache.ts +6 -41
  170. package/frontendBuild/cssCompiler.ts +31 -82
  171. package/frontendBuild/cssImportResolver.ts +6 -19
  172. package/frontendBuild/devChangePlanner.ts +7 -10
  173. package/frontendBuild/devGeneratedIndexSync.test.ts +12 -27
  174. package/frontendBuild/devGeneratedIndexSync.ts +1 -4
  175. package/frontendBuild/devRegistryBundler.ts +192 -0
  176. package/frontendBuild/fontOptimizer.test.ts +6 -14
  177. package/frontendBuild/fontOptimizer.ts +15 -72
  178. package/frontendBuild/fontPruner.test.ts +5 -10
  179. package/frontendBuild/fontPruner.ts +5 -20
  180. package/frontendBuild/frontendBuild.test.ts +57 -70
  181. package/frontendBuild/hmrChangeClassifier.ts +2 -2
  182. package/frontendBuild/hmrWatcher.test.ts +59 -32
  183. package/frontendBuild/hmrWatcher.ts +31 -74
  184. package/frontendBuild/index.ts +4 -0
  185. package/frontendBuild/pagesBundleBuilder.ts +28 -30
  186. package/frontendBuild/pagesEntrySourceGenerator.ts +56 -6
  187. package/frontendBuild/precompressArtifacts.ts +5 -18
  188. package/frontendBuild/registryMetadataFingerprint.test.ts +63 -0
  189. package/frontendBuild/registryMetadataFingerprint.ts +28 -0
  190. package/frontendBuild/routeClientBuilder.ts +100 -62
  191. package/frontendBuild/routesManifestArtifactSerializer.ts +5 -36
  192. package/frontendBuild/serverGraphFile.test.ts +77 -0
  193. package/frontendBuild/serverGraphFile.ts +93 -0
  194. package/frontendBuild/sourceMtimeIndex.test.ts +41 -97
  195. package/frontendBuild/sourceMtimeIndex.ts +19 -130
  196. package/frontendBuild/ssrBaseArtifactBuilder.ts +19 -13
  197. package/frontendBuild/ssrDevBundler.ts +85 -0
  198. package/frontendBuild/styleContract.ts +1 -8
  199. package/frontendBuild/themeValidator.ts +4 -26
  200. package/frontendBuild/watchRootResolver.test.ts +23 -42
  201. package/frontendBuild/watchRootResolver.ts +5 -27
  202. package/getRelatedCnsts.ts +12 -92
  203. package/incrementalBuilder/buildBatch.proc.ts +147 -63
  204. package/incrementalBuilder/buildBatchProtocol.ts +13 -38
  205. package/incrementalBuilder/buildBatchRunner.test.ts +65 -0
  206. package/incrementalBuilder/buildBatchRunner.ts +26 -38
  207. package/incrementalBuilder/builderChannel.test.ts +24 -49
  208. package/incrementalBuilder/builderChannel.ts +6 -37
  209. package/incrementalBuilder/builderRequestRouter.test.ts +0 -8
  210. package/incrementalBuilder/builderRequestRouter.ts +5 -24
  211. package/incrementalBuilder/builderWorkQueue.test.ts +94 -0
  212. package/incrementalBuilder/builderWorkQueue.ts +126 -0
  213. package/incrementalBuilder/devWatchBatch.test.ts +21 -24
  214. package/incrementalBuilder/incrementalBuilder.host.test.ts +53 -56
  215. package/incrementalBuilder/incrementalBuilder.host.ts +68 -81
  216. package/incrementalBuilder/incrementalBuilder.proc.test.ts +270 -0
  217. package/incrementalBuilder/incrementalBuilder.proc.ts +596 -208
  218. package/index.ts +5 -19
  219. package/integration/devResourceProbe.ts +50 -56
  220. package/integration/devStability.integration.test.ts +105 -199
  221. package/integration/devStabilityHarness.test.ts +13 -28
  222. package/integration/devStabilityHarness.ts +65 -330
  223. package/integration/ssrMemoryProbe.ts +41 -167
  224. package/libSource.test.ts +4 -15
  225. package/libSource.ts +19 -31
  226. package/lint/__fixtures__/no-document-cookie/bad.tsx +4 -0
  227. package/lint/__fixtures__/no-document-cookie/good.tsx +7 -0
  228. package/lint/__fixtures__/no-web-only-api-outside-webkit/bad.tsx +7 -0
  229. package/lint/__fixtures__/no-web-only-api-outside-webkit/good.tsx +11 -0
  230. package/lint/__fixtures__/no-web-storage/bad.tsx +6 -0
  231. package/lint/__fixtures__/no-web-storage/good.tsx +7 -0
  232. package/lint/gritRules.test.ts +8 -24
  233. package/lint/no-deep-internal-import.grit +2 -2
  234. package/lint/no-document-cookie.grit +29 -0
  235. package/lint/no-redeclare-predefined-endpoint.grit +2 -1
  236. package/lint/no-web-only-api-outside-webkit.grit +44 -0
  237. package/lint/no-web-storage.grit +30 -0
  238. package/linter.test.ts +1 -2
  239. package/linter.ts +26 -116
  240. package/mobile/desktopBin.test.ts +182 -0
  241. package/mobile/desktopBin.ts +144 -0
  242. package/mobile/desktopServerStage.test.ts +252 -0
  243. package/mobile/desktopServerStage.ts +178 -0
  244. package/mobile/index.ts +9 -0
  245. package/mobile/mobileTarget.test.ts +57 -8
  246. package/mobile/mobileTarget.ts +45 -26
  247. package/mobile/nativeApi.test.ts +30 -0
  248. package/mobile/nativeApi.ts +40 -0
  249. package/mobile/nativeApp.test.ts +184 -0
  250. package/mobile/nativeApp.ts +454 -0
  251. package/mobile/nativeAppLine.test.ts +69 -0
  252. package/mobile/nativeAppLine.ts +71 -0
  253. package/mobile/nativeConfig.test.ts +438 -0
  254. package/mobile/nativeConfig.ts +294 -0
  255. package/mobile/nativePluginFolders.test.ts +81 -0
  256. package/mobile/nativePluginFolders.ts +60 -0
  257. package/mobile/nativeWebDir.test.ts +80 -0
  258. package/mobile/nativeWebDir.ts +66 -0
  259. package/mobile/placeholderAppId.test.ts +13 -0
  260. package/mobile/placeholderAppId.ts +16 -0
  261. package/mobile/usageDescriptions.test.ts +27 -0
  262. package/mobile/usageDescriptions.ts +24 -0
  263. package/package.json +11 -11
  264. package/packageExports.test.ts +3 -18
  265. package/packageExportsMap.ts +3 -19
  266. package/piDependencyPins.test.ts +46 -0
  267. package/platformTest/BunTestReport.test.ts +60 -0
  268. package/platformTest/BunTestReport.ts +65 -0
  269. package/platformTest/IdleWatchedProcess.test.ts +56 -0
  270. package/platformTest/IdleWatchedProcess.ts +73 -0
  271. package/platformTest/LinuxDockerTarget.ts +105 -0
  272. package/platformTest/PlatformTestRun.test.ts +64 -0
  273. package/platformTest/PlatformTestRun.ts +141 -0
  274. package/platformTest/PlatformTestTarget.ts +142 -0
  275. package/platformTest/TestSnapshot.test.ts +72 -0
  276. package/platformTest/TestSnapshot.ts +103 -0
  277. package/platformTest/WindowsSshTarget.ts +151 -0
  278. package/prompter.ts +3 -13
  279. package/qualityScanner.test.ts +9 -26
  280. package/qualityScanner.ts +200 -286
  281. package/recipeScanner.test.ts +7 -12
  282. package/recipeScanner.ts +9 -38
  283. package/repoIdentity.ts +2 -9
  284. package/routeSourceValidator.test.ts +0 -1
  285. package/routeSourceValidator.ts +7 -42
  286. package/scanInfo.ts +91 -225
  287. package/selectModel.ts +1 -2
  288. package/semver.ts +3 -5
  289. package/slicePlanner.test.ts +6 -24
  290. package/slicePlanner.ts +11 -32
  291. package/spinner.test.ts +3 -8
  292. package/spinner.ts +4 -16
  293. package/sshTunnel.ts +1 -6
  294. package/ssrScanner.test.ts +1 -6
  295. package/ssrScanner.ts +103 -113
  296. package/stripAnsi.ts +3 -0
  297. package/subspace.test.ts +9 -25
  298. package/subspace.ts +48 -115
  299. package/subspaceConfig.ts +3 -11
  300. package/testHelpers.ts +194 -0
  301. package/transforms/asyncDefaultExportDetector.ts +3 -11
  302. package/transforms/barrelAnalyzer.ts +43 -135
  303. package/transforms/barrelImportsPlugin.ts +38 -175
  304. package/transforms/externalizeFrameworkPlugin.test.ts +39 -118
  305. package/transforms/externalizeFrameworkPlugin.ts +13 -87
  306. package/transforms/moduleSyntax.ts +32 -0
  307. package/transforms/rscUseClientTransform.ts +42 -20
  308. package/transforms/serverEnvPlugin.test.ts +103 -0
  309. package/transforms/serverEnvPlugin.ts +41 -0
  310. package/transforms/transforms.test.ts +166 -44
  311. package/transforms/tsconfigPackageResolver.test.ts +6 -24
  312. package/transforms/useClientBundlePlugin.ts +6 -23
  313. package/typeChecker.ts +7 -63
  314. package/types.ts +2 -0
  315. package/uploadRelease.ts +10 -25
  316. package/workflow/artifacts.ts +18 -0
  317. package/workflow/executor.test.ts +1 -12
  318. package/workflow/executor.ts +101 -110
  319. package/workflow/index.ts +0 -1
  320. package/workflow/moduleIndex.test.ts +4 -15
  321. package/workflow/moduleIndex.ts +9 -49
  322. package/workflow/plan.ts +18 -25
  323. package/workflow/render.ts +80 -96
  324. package/workflow/rolloutGate.test.ts +1 -1
  325. package/workflow/source.ts +52 -69
  326. package/workflow/sourceAst.ts +50 -0
  327. package/workspaceLayout.test.ts +18 -3
  328. package/workspaceLayout.ts +22 -23
  329. package/abstractCompactor.ts +0 -112
  330. package/aiEditor.test.ts +0 -60
  331. package/aiEditor.ts +0 -387
  332. package/applicationReleasePackager.ts +0 -209
  333. package/capacitorApp.test.ts +0 -372
  334. package/capacitorApp.ts +0 -1648
  335. package/commandDecorators/commandMeta.ts +0 -7
  336. package/commandDecorators/types.ts +0 -10
  337. package/getDirname.ts +0 -4
  338. package/guideline.ts +0 -19
  339. package/local/optimize-resource/ipcprobe/child.ts +0 -1
  340. package/local/optimize-resource/ipcprobe/parent.ts +0 -11
  341. package/workflow/primitive.ts +0 -59
@@ -2,6 +2,7 @@ import type {
2
2
  App,
3
3
  ArgMeta,
4
4
  ArgsOption,
5
+ ArgType,
5
6
  CommandContext,
6
7
  Exec,
7
8
  InternalArgMeta,
@@ -13,9 +14,14 @@ import type {
13
14
  Sys,
14
15
  } from "./argMeta";
15
16
  import { normalizePrimitiveArgType } from "./argMeta";
16
- import { assertUniqueDependencies, type DependencyInstanceMap, injectDependencies } from "./dependencyBuilder";
17
+ import {
18
+ assertUniqueDependencies,
19
+ type DependencyCls,
20
+ type DependencyInstanceMap,
21
+ type DependencyKey,
22
+ injectDependencies,
23
+ } from "./dependencyBuilder";
17
24
  import { COMMAND_META, type CommandCls, type TargetMeta, type TargetOption } from "./targetMeta";
18
- import type { DependencyCls, DependencyKey } from "./types";
19
25
 
20
26
  type PrimitiveValue<T extends PrimitiveArgType> = T extends StringConstructor
21
27
  ? string
@@ -23,11 +29,7 @@ type PrimitiveValue<T extends PrimitiveArgType> = T extends StringConstructor
23
29
  ? number
24
30
  : boolean;
25
31
  type MaybeNullable<Value, Option> = Option extends { nullable: true } ? Value | null : Value;
26
- /**
27
- * The literal union a static `enum` declares, or `never` for a `DynamicEnum` — a function does not extend
28
- * a readonly array, so a runtime-resolved choice list falls back to the primitive type. `{ label, value }`
29
- * choices contribute their `value`.
30
- */
32
+ // A DynamicEnum yields never (a function is no readonly array), so ArgValue falls back to the primitive type.
31
33
  type EnumValue<Option> = Option extends { enum: infer Choices }
32
34
  ? Choices extends readonly (infer Choice)[]
33
35
  ? Choice extends { value: infer Value }
@@ -73,6 +75,14 @@ type CommandHandler<Deps extends readonly DependencyCls[], Params extends unknow
73
75
  ...args: Params
74
76
  ) => unknown | Promise<unknown>;
75
77
 
78
+ const argMetaOf = (
79
+ type: ArgType,
80
+ name: string,
81
+ primitive: PrimitiveArgType,
82
+ argsOption: object | undefined,
83
+ idx: number,
84
+ ): ArgMeta => ({ name, argsOption: { ...argsOption, type: normalizePrimitiveArgType(primitive) }, key: "", idx, type });
85
+
76
86
  class TargetBuilder<Deps extends readonly DependencyCls[], Params extends unknown[] = [], Context = object> {
77
87
  readonly #args: (ArgMeta | InternalArgMeta)[];
78
88
 
@@ -83,56 +93,29 @@ class TargetBuilder<Deps extends readonly DependencyCls[], Params extends unknow
83
93
  this.#args = args;
84
94
  }
85
95
 
96
+ #add<NextParams extends unknown[], NextContext = Context>(...argMetas: (ArgMeta | InternalArgMeta)[]) {
97
+ return new TargetBuilder<Deps, NextParams, NextContext>(this.targetOption, [...this.#args, ...argMetas]);
98
+ }
99
+
86
100
  arg<Type extends PrimitiveArgType, const Option extends ArgsOption<Context> = ArgsOption<Context>>(
87
101
  name: string,
88
102
  type: Type,
89
103
  argsOption: Option = {} as Option,
90
- ): TargetBuilder<Deps, AddArg<Params, Type, Option>, Context> {
91
- return new TargetBuilder<Deps, AddArg<Params, Type, Option>, Context>(this.targetOption, [
92
- ...this.#args,
93
- {
94
- name,
95
- argsOption: { ...argsOption, type: normalizePrimitiveArgType(type) },
96
- key: "",
97
- idx: this.#args.length,
98
- type: "Argument",
99
- } as ArgMeta<CommandContext>,
100
- ]);
104
+ ) {
105
+ return this.#add<AddArg<Params, Type, Option>>(argMetaOf("Argument", name, type, argsOption, this.#args.length));
101
106
  }
102
107
 
103
108
  option<Type extends PrimitiveArgType, const Option extends ArgsOption<Context> = ArgsOption<Context>>(
104
109
  name: string,
105
110
  type: Type,
106
111
  argsOption: Option = {} as Option,
107
- ): TargetBuilder<Deps, AddArg<Params, Type, Option>, Context> {
108
- return new TargetBuilder<Deps, AddArg<Params, Type, Option>, Context>(this.targetOption, [
109
- ...this.#args,
110
- {
111
- name,
112
- argsOption: { ...argsOption, type: normalizePrimitiveArgType(type) },
113
- key: "",
114
- idx: this.#args.length,
115
- type: "Option",
116
- } as ArgMeta<CommandContext>,
117
- ]);
112
+ ) {
113
+ return this.#add<AddArg<Params, Type, Option>>(argMetaOf("Option", name, type, argsOption, this.#args.length));
118
114
  }
119
115
 
120
- with<const Tokens extends readonly InternalArgToken[]>(
121
- ...tokens: Tokens
122
- ): TargetBuilder<Deps, AddInternalArgs<Params, Tokens>, AddInternalContext<Context, Tokens>> {
123
- return new TargetBuilder<Deps, AddInternalArgs<Params, Tokens>, AddInternalContext<Context, Tokens>>(
124
- this.targetOption,
125
- [
126
- ...this.#args,
127
- ...tokens.map(
128
- (token, offset) =>
129
- ({
130
- key: "",
131
- idx: this.#args.length + offset,
132
- type: token.type,
133
- }) satisfies InternalArgMeta,
134
- ),
135
- ],
116
+ with<const Tokens extends readonly InternalArgToken[]>(...tokens: Tokens) {
117
+ return this.#add<AddInternalArgs<Params, Tokens>, AddInternalContext<Context, Tokens>>(
118
+ ...tokens.map((token, offset) => ({ key: "", idx: this.#args.length + offset, type: token.type })),
136
119
  );
137
120
  }
138
121
 
@@ -174,22 +157,8 @@ const createContext = <Deps extends readonly DependencyCls[]>(): CommandBuilderC
174
157
  public: createTarget<Deps>("public"),
175
158
  cloud: createTarget<Deps>("cloud"),
176
159
  dev: createTarget<Deps>("dev"),
177
- arg: (name, type, argsOption) =>
178
- ({
179
- name,
180
- argsOption: { ...(argsOption ?? {}), type: normalizePrimitiveArgType(type) },
181
- key: "",
182
- idx: -1,
183
- type: "Argument",
184
- }) as ArgMeta<CommandContext>,
185
- option: (name, type, argsOption) =>
186
- ({
187
- name,
188
- argsOption: { ...(argsOption ?? {}), type: normalizePrimitiveArgType(type) },
189
- key: "",
190
- idx: -1,
191
- type: "Option",
192
- }) as ArgMeta<CommandContext>,
160
+ arg: (name, type, argsOption) => argMetaOf("Argument", name, type, argsOption, -1),
161
+ option: (name, type, argsOption) => argMetaOf("Option", name, type, argsOption, -1),
193
162
  });
194
163
 
195
164
  const buildCommandMeta = (definitions: Record<string, TargetDefinition>) => {
@@ -125,7 +125,7 @@ describe("command helper metadata", () => {
125
125
 
126
126
  const commandHelp = stripAnsi(formatCommandHelp(HelpCommand, "buildApp"));
127
127
  expect(commandHelp).toContain("akan build-app [app]");
128
- expect(commandHelp).toContain("--write");
128
+ expect(commandHelp).toContain("--write, --no-write");
129
129
  expect(commandHelp).toContain("[default: true]");
130
130
  expect(commandHelp).toContain("Fast, Full");
131
131
  });
@@ -243,8 +243,6 @@ describe("enum arg choices", () => {
243
243
  expect(await getOptionValue(optionMeta(["text", "json"]), { format: "json" }, context)).toBe("json");
244
244
  });
245
245
 
246
- // Before this check `akan quality --format yaml` reached the script as "yaml" while the declaration
247
- // claimed the parameter was "text" | "json".
248
246
  test("rejects an undeclared value in commander's wording", async () => {
249
247
  await expect(getOptionValue(optionMeta(["text", "json"]), { format: "yaml" }, context)).rejects.toThrow(
250
248
  "option '--format' argument 'yaml' is invalid. Allowed choices are text, json.",
@@ -269,8 +267,6 @@ describe("enum arg choices", () => {
269
267
  await expect(getOptionValue(labelled, { format: "JSON output" }, context)).rejects.toThrow("is invalid");
270
268
  });
271
269
 
272
- // A DynamicEnum resolves against a context that is not populated yet, and the interactive select is its
273
- // only consumer, so an explicit value passes through unchecked rather than being rejected wrongly.
274
270
  test("leaves a dynamic choice list unchecked", async () => {
275
271
  expect(
276
272
  await getOptionValue(
@@ -291,11 +287,7 @@ describe("enum arg type inference", () => {
291
287
  CommandContainer.clear();
292
288
  });
293
289
 
294
- /**
295
- * Compile-time only. Nothing here can fail at runtime: if `enum` stops narrowing, the parameter widens
296
- * to the primitive and these calls stop typechecking, so the regression surfaces in `akan typecheck`
297
- * rather than in fifteen `as "a" | "b"` casts creeping back into the command files.
298
- */
290
+ //? Compile-time only: if `enum` stops narrowing, the parameter widens and these calls stop typechecking.
299
291
  const expectLiteral = <Expected>(_value: Expected) => undefined;
300
292
 
301
293
  test("a static enum narrows the exec parameter to its declared choices", () => {
@@ -1,4 +1,13 @@
1
- import type { DependencyCls, DependencyKey, DependencyKind } from "./types";
1
+ export type Cls<T = unknown> = new (...args: unknown[]) => T;
2
+
3
+ export type DependencyKind = "command" | "script" | "runner";
4
+ export type DependencyKey<RefName extends string, Kind extends DependencyKind> = `${RefName}${Capitalize<Kind>}`;
5
+
6
+ export type DependencyCls<T = unknown, Key extends string = string> = (new () => T) & {
7
+ readonly dependencyKey: Key;
8
+ readonly dependencyKind: DependencyKind;
9
+ readonly refName: string;
10
+ };
2
11
 
3
12
  type UnionToIntersection<Union> = (Union extends unknown ? (value: Union) => void : never) extends (
4
13
  value: infer Intersection,
@@ -1,191 +1,119 @@
1
1
  import chalk from "chalk";
2
2
 
3
3
  import { type EnumChoice, getArgMetas } from "./argMeta";
4
+ import { camelToKebabCase } from "./camelToKebabCase";
4
5
  import { type CommandCls, getTargetMetas } from "./targetMeta";
5
6
 
6
- const camelToKebabCase = (str: string) => str.replace(/([A-Z])/g, "-$1").toLowerCase();
7
7
  const formatChoice = (choice: EnumChoice) => (typeof choice === "object" ? choice.label : choice.toString());
8
8
 
9
9
  const groupCommands = (commands: CommandCls[]) => {
10
- const groups = new Map<string, { name: string; commands: { key: string; args: string[]; desc?: string }[] }>();
11
-
10
+ const groups = new Map<string, { key: string; args: string[]; desc?: string }[]>();
12
11
  for (const command of commands) {
13
- const className = command.name.replace("Command", "");
14
- const groupName = className;
15
-
16
- if (!groups.has(groupName)) {
17
- groups.set(groupName, { name: groupName, commands: [] });
18
- }
19
-
20
- const targetMetas = getTargetMetas(command);
21
- for (const targetMeta of targetMetas) {
22
- // Skip devOnly commands in help
12
+ const group = groups.getOrInsert(command.name.replace("Command", ""), []);
13
+ for (const targetMeta of getTargetMetas(command)) {
23
14
  if (targetMeta.targetOption.devOnly) continue;
24
-
25
15
  const [allArgMetas] = getArgMetas(command, targetMeta.key);
26
16
  const args = allArgMetas
27
17
  .filter((arg) => arg.type !== "Option")
28
18
  .map((arg) => {
29
19
  if (arg.type === "Workspace") return "";
30
20
  if (arg.type === "Module") return "[sys:module]";
31
- if (arg.type === "Argument") {
32
- return `[${arg.name}]`;
33
- }
21
+ if (arg.type === "Argument") return `[${arg.name}]`;
34
22
  return `[${arg.type.toLowerCase()}]`;
35
23
  })
36
24
  .filter(Boolean);
37
-
38
- const group = groups.get(groupName);
39
- if (group) {
40
- group.commands.push({
41
- key: camelToKebabCase(targetMeta.key),
42
- args,
43
- desc: targetMeta.targetOption.desc,
44
- });
45
- }
25
+ group.push({ key: camelToKebabCase(targetMeta.key), args, desc: targetMeta.targetOption.desc });
46
26
  }
47
27
  }
48
-
49
28
  return groups;
50
29
  };
51
30
 
52
31
  export const formatHelp = (commands: CommandCls[], version: string) => {
53
- const groups = groupCommands(commands);
54
- const lines: string[] = [];
55
-
56
- // Header
57
- lines.push("");
58
- lines.push(chalk.bold.cyan(" ╔═══════════════════════════════════════════════════╗"));
59
- lines.push(
32
+ const lines = [
33
+ "",
34
+ chalk.bold.cyan(" ╔═══════════════════════════════════════════════════╗"),
60
35
  chalk.bold.cyan(" ║") +
61
36
  chalk.bold.white(" Akan.js Framework CLI ") +
62
37
  chalk.bold.cyan(" ║"),
63
- );
64
- lines.push(chalk.bold.cyan(" ╚═══════════════════════════════════════════════════╝"));
65
- lines.push("");
66
- lines.push(chalk.gray(` Version: ${version}`));
67
- lines.push("");
68
-
69
- // Usage
70
- lines.push(chalk.bold.yellow(" USAGE"));
71
- lines.push("");
72
- lines.push(chalk.gray(" $ ") + chalk.white("akan") + chalk.gray(" <command> [options]"));
73
- lines.push("");
74
-
75
- // Commands by category
76
- lines.push(chalk.bold.yellow(" COMMANDS"));
77
- lines.push("");
78
-
79
- for (const [groupName, group] of groups) {
80
- // Skip empty groups (all commands are devOnly)
81
- if (group.commands.length === 0) continue;
82
-
83
- lines.push(chalk.bold.magenta(` ${groupName}`));
84
- lines.push("");
85
-
86
- for (const cmd of group.commands) {
87
- const cmdName = chalk.green(cmd.key);
88
- const cmdArgs = cmd.args.length > 0 ? chalk.gray(` ${cmd.args.join(" ")}`) : "";
89
-
90
- // Format description: wrap if too long
91
- if (cmd.desc) {
92
- const maxLineLength = 70;
93
- const cmdPrefix = ` ${cmdName}${cmdArgs}`;
94
- const indent = " ";
95
-
96
- if (cmdPrefix.length + cmd.desc.length + 3 < maxLineLength) {
97
- // Single line
98
- lines.push(`${cmdPrefix} ${chalk.gray(cmd.desc)}`);
99
- } else {
100
- // Multi-line
101
- lines.push(cmdPrefix);
102
- lines.push(`${indent}${chalk.gray(cmd.desc)}`);
103
- }
104
- } else {
105
- lines.push(` ${cmdName}${cmdArgs}`);
106
- }
38
+ chalk.bold.cyan(" ╚═══════════════════════════════════════════════════╝"),
39
+ "",
40
+ chalk.gray(` Version: ${version}`),
41
+ "",
42
+ chalk.bold.yellow(" USAGE"),
43
+ "",
44
+ chalk.gray(" $ ") + chalk.white("akan") + chalk.gray(" <command> [options]"),
45
+ "",
46
+ chalk.bold.yellow(" COMMANDS"),
47
+ "",
48
+ ];
49
+ for (const [groupName, cmds] of groupCommands(commands)) {
50
+ if (cmds.length === 0) continue;
51
+ lines.push(chalk.bold.magenta(` ${groupName}`), "");
52
+ for (const cmd of cmds) {
53
+ const cmdPrefix = ` ${chalk.green(cmd.key)}${cmd.args.length > 0 ? chalk.gray(` ${cmd.args.join(" ")}`) : ""}`;
54
+ if (!cmd.desc) lines.push(cmdPrefix);
55
+ else if (cmdPrefix.length + cmd.desc.length + 3 < 70) lines.push(`${cmdPrefix} ${chalk.gray(cmd.desc)}`);
56
+ else lines.push(cmdPrefix, ` ${chalk.gray(cmd.desc)}`);
107
57
  }
108
58
  lines.push("");
109
59
  }
110
-
111
- // Global Options
112
- lines.push(chalk.bold.yellow(" OPTIONS"));
113
- lines.push("");
114
- lines.push(` ${chalk.green("-v, --verbose")} ${chalk.gray("Enable verbose output")}`);
115
- lines.push(` ${chalk.green("-h, --help")} ${chalk.gray("Display this help message")}`);
116
- lines.push(` ${chalk.green("-V, --version")} ${chalk.gray("Output version number")}`);
117
- lines.push("");
118
-
119
- // Examples
120
- lines.push(chalk.bold.yellow(" EXAMPLES"));
121
- lines.push("");
122
- lines.push(chalk.gray(" # Create a new workspace"));
123
- lines.push(chalk.white(" $ akan create-workspace myproject"));
124
- lines.push("");
125
- lines.push(chalk.gray(" # Start development server"));
126
- lines.push(chalk.white(" $ akan start myapp"));
127
- lines.push("");
128
- lines.push(chalk.gray(" # Create a new module"));
129
- lines.push(chalk.white(" $ akan create-module userProfile"));
130
- lines.push("");
131
-
132
- // Footer
133
- lines.push(chalk.gray(" Documentation: ") + chalk.cyan("https://akanjs.com/docs"));
134
- lines.push(chalk.gray(" Report issues: ") + chalk.cyan("https://github.com/akan-team/akanjs/issues"));
135
- lines.push("");
136
-
60
+ lines.push(
61
+ chalk.bold.yellow(" OPTIONS"),
62
+ "",
63
+ ` ${chalk.green("-v, --verbose")} ${chalk.gray("Enable verbose output")}`,
64
+ ` ${chalk.green("-h, --help")} ${chalk.gray("Display this help message")}`,
65
+ ` ${chalk.green("-V, --version")} ${chalk.gray("Output version number")}`,
66
+ "",
67
+ chalk.bold.yellow(" EXAMPLES"),
68
+ "",
69
+ chalk.gray(" # Create a new workspace"),
70
+ chalk.white(" $ akan create-workspace myproject"),
71
+ "",
72
+ chalk.gray(" # Start development server"),
73
+ chalk.white(" $ akan start myapp"),
74
+ "",
75
+ chalk.gray(" # Create a new module"),
76
+ chalk.white(" $ akan create-module userProfile"),
77
+ "",
78
+ chalk.gray(" Documentation: ") + chalk.cyan("https://akanjs.com/docs"),
79
+ chalk.gray(" Report issues: ") + chalk.cyan("https://github.com/akan-team/akanjs/issues"),
80
+ "",
81
+ );
137
82
  return lines.join("\n");
138
83
  };
139
84
 
140
85
  export const formatCommandHelp = (command: CommandCls, key: string) => {
141
- const [allArgMetas, argMetas] = getArgMetas(command, key);
86
+ const [allArgMetas, optionArgs] = getArgMetas(command, key);
142
87
  const kebabKey = camelToKebabCase(key);
143
- const lines: string[] = [];
144
-
145
- const targetMetas = getTargetMetas(command);
146
- const targetMeta = targetMetas.find((t) => t.key === key);
147
- const commandDesc = targetMeta?.targetOption.desc;
148
-
149
- lines.push("");
150
- lines.push(chalk.bold.cyan(` Command: ${kebabKey}`));
151
- if (commandDesc) {
152
- lines.push(chalk.gray(` ${commandDesc}`));
153
- }
154
- lines.push("");
155
-
156
- // Usage
157
- const args = allArgMetas
158
- .filter((arg) => arg.type !== "Option")
88
+ const commandDesc = getTargetMetas(command).find((t) => t.key === key)?.targetOption.desc;
89
+ const nonOptionArgs = allArgMetas.filter((arg) => arg.type !== "Option");
90
+ const args = nonOptionArgs
159
91
  .map((arg) => {
160
92
  if (arg.type === "Workspace") return "";
161
93
  if (arg.type === "Module") return "[sys:module]";
162
94
  if (arg.type === "Apps") return "[apps...]";
163
- if (arg.type === "Argument") {
164
- return `[${camelToKebabCase(arg.name)}]`;
165
- }
95
+ if (arg.type === "Argument") return `[${camelToKebabCase(arg.name)}]`;
166
96
  return `[${arg.type.toLowerCase()}]`;
167
97
  })
168
98
  .filter(Boolean)
169
99
  .join(" ");
170
100
 
171
- lines.push(chalk.bold.yellow(" USAGE"));
172
- lines.push("");
173
- lines.push(chalk.gray(" $ ") + chalk.white(`akan ${kebabKey}`) + (args ? chalk.gray(` ${args}`) : ""));
174
- lines.push("");
175
-
176
- // Arguments
177
- const nonOptionArgs = allArgMetas.filter((arg) => arg.type !== "Option");
101
+ const lines = ["", chalk.bold.cyan(` Command: ${kebabKey}`)];
102
+ if (commandDesc) lines.push(chalk.gray(` ${commandDesc}`));
103
+ lines.push(
104
+ "",
105
+ chalk.bold.yellow(" USAGE"),
106
+ "",
107
+ chalk.gray(" $ ") + chalk.white(`akan ${kebabKey}`) + (args ? chalk.gray(` ${args}`) : ""),
108
+ "",
109
+ );
178
110
  if (nonOptionArgs.length > 0) {
179
- lines.push(chalk.bold.yellow(" ARGUMENTS"));
180
- lines.push("");
181
-
111
+ lines.push(chalk.bold.yellow(" ARGUMENTS"), "");
182
112
  for (const arg of nonOptionArgs) {
183
113
  if (arg.type === "Workspace") continue;
184
-
185
114
  let argName: string;
186
115
  let argDesc: string;
187
116
  let example = "";
188
-
189
117
  if (arg.type === "Argument") {
190
118
  argName = camelToKebabCase(arg.name);
191
119
  argDesc = arg.argsOption.desc ?? "";
@@ -200,24 +128,19 @@ export const formatCommandHelp = (command: CommandCls, key: string) => {
200
128
  argName = arg.type.toLowerCase();
201
129
  argDesc = `${arg.type} name in this workspace`;
202
130
  }
203
-
204
131
  lines.push(` ${chalk.green(argName)} ${chalk.gray(argDesc)}${example}`);
205
132
  }
206
-
207
133
  lines.push("");
208
134
  }
209
135
 
210
- // Options
211
- const optionArgs = argMetas.filter((a) => a.type === "Option");
212
136
  if (optionArgs.length > 0) {
213
- lines.push(chalk.bold.yellow(" OPTIONS"));
214
- lines.push("");
215
-
137
+ lines.push(chalk.bold.yellow(" OPTIONS"), "");
216
138
  for (const arg of optionArgs) {
217
139
  const opt = arg.argsOption;
218
140
  const flag = opt.flag ? `-${opt.flag}, ` : "";
219
141
  const kebabName = camelToKebabCase(arg.name);
220
- const optName = `${flag}--${kebabName}`;
142
+ const negation = opt.type === "boolean" && opt.default === true ? `, --no-${kebabName}` : "";
143
+ const optName = `${flag}--${kebabName}${negation}`;
221
144
  const optDesc = opt.desc ?? "";
222
145
  const defaultVal = opt.default !== undefined ? chalk.gray(` [default: ${String(opt.default)}]`) : "";
223
146
  const choices = opt.enum
@@ -1,8 +1,6 @@
1
1
  export * from "./argMeta";
2
2
  export * from "./command";
3
3
  export * from "./commandBuilder";
4
- export * from "./commandMeta";
5
4
  export * from "./dependencyBuilder";
6
5
  export * from "./helpFormatter";
7
6
  export * from "./targetMeta";
8
- export * from "./types";
@@ -1,5 +1,6 @@
1
1
  import type { ArgMeta, InternalArgMeta } from "./argMeta";
2
- import type { DependencyCls } from "./types";
2
+ import { camelToKebabCase } from "./camelToKebabCase";
3
+ import type { Cls, DependencyCls } from "./dependencyBuilder";
3
4
 
4
5
  export const COMMAND_META: unique symbol = Symbol("akan.command.meta");
5
6
 
@@ -22,12 +23,7 @@ export const getTargetMetas = (command: CommandCls): TargetMeta[] => {
22
23
  return [...targetMetaMap.values()];
23
24
  };
24
25
 
25
- const camelToKebabCase = (str: string) => str.replace(/([A-Z])/g, "-$1").toLowerCase();
26
-
27
- /**
28
- * CLI names a target answers to. Shared with the command-manifest generator so a lazily-loaded CLI
29
- * resolves `argv[2]` to the same module that `runCommands` would have registered it under.
30
- */
26
+ /** Shared with the command-manifest generator, so a lazily loaded CLI maps argv[2] to the module runCommands would. */
31
27
  export const getTargetCommandNames = (targetMeta: TargetMeta): string[] => {
32
28
  const kebabKey = camelToKebabCase(targetMeta.key);
33
29
  if (targetMeta.targetOption.short !== true) return [kebabKey];
@@ -48,3 +44,9 @@ export interface TargetOption {
48
44
  runsOnWorkspaceRoot?: boolean;
49
45
  stdio?: boolean;
50
46
  }
47
+
48
+ export const Commands = () => {
49
+ return (target: Cls) => {
50
+ // not implemented yet
51
+ };
52
+ };
package/createTunnel.ts CHANGED
@@ -1,18 +1,6 @@
1
- import type { SshOptions } from "akanjs/base";
2
-
3
1
  import { type AppExecutor, WorkspaceExecutor } from "./executors";
4
2
  import { createSshTunnel } from "./sshTunnel";
5
3
 
6
- const getSshTunnelOptions = (app: AppExecutor, environment: string): SshOptions => {
7
- const { serveDomain, repoName } = WorkspaceExecutor.getBaseDevEnv();
8
- return {
9
- host: `${app.name}-${environment}.${serveDomain}`,
10
- port: process.env.SSH_TUNNEL_PORT ? parseInt(process.env.SSH_TUNNEL_PORT) : 32767,
11
- username: process.env.SSH_TUNNEL_USERNAME ?? "root",
12
- password: process.env.SSH_TUNNEL_PASSWORD ?? repoName,
13
- };
14
- };
15
-
16
4
  interface TunnelOption {
17
5
  app: AppExecutor;
18
6
  environment: string;
@@ -22,7 +10,7 @@ export const createTunnel = async (
22
10
  service: "redis" | "postgres",
23
11
  { app, environment, port = service === "postgres" ? 5432 : 6379 }: TunnelOption,
24
12
  ) => {
25
- const sshOptions: SshOptions = getSshTunnelOptions(app, environment);
13
+ const { serveDomain, repoName } = WorkspaceExecutor.getBaseDevEnv();
26
14
  await createSshTunnel({
27
15
  localHost: "0.0.0.0",
28
16
  localPort: port,
@@ -30,7 +18,12 @@ export const createTunnel = async (
30
18
  srcPort: port,
31
19
  dstHost: `${service}-0.${service}-svc.${app.name}-${environment}.svc.cluster.local`,
32
20
  dstPort: service === "postgres" ? 5432 : 6379,
33
- sshOptions,
21
+ sshOptions: {
22
+ host: `${app.name}-${environment}.${serveDomain}`,
23
+ port: process.env.SSH_TUNNEL_PORT ? parseInt(process.env.SSH_TUNNEL_PORT) : 32767,
24
+ username: process.env.SSH_TUNNEL_USERNAME ?? "root",
25
+ password: process.env.SSH_TUNNEL_PASSWORD ?? repoName,
26
+ },
34
27
  });
35
28
  return `localhost:${port}`;
36
29
  };