@akanjs/cli 3.1.0-rc.1 → 3.1.0-rc.3

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 (74) hide show
  1. package/.build-stamp +1 -1
  2. package/{CodeAgent-kyprmy06.js → CodeAgent-ctk4fh2b.js} +2 -2
  3. package/{CodeTui-21mtze3j.js → CodeTui-mrxtrdzw.js} +1 -1
  4. package/TunnelShare-rj74jd6x.js +13 -0
  5. package/{agent.command-f3gsc1gd.js → agent.command-ncre6kwz.js} +5 -5
  6. package/akanCode.js +2 -2
  7. package/{application.command-5s780vnz.js → application.command-54mawreg.js} +52 -41
  8. package/{applicationBuildRunner-1yaqsrdq.js → applicationBuildRunner-8573zr2w.js} +16 -30
  9. package/buildBatch.proc.js +22 -13
  10. package/{cloud.command-yj6xb2a7.js → cloud.command-nyemv0m3.js} +57 -65
  11. package/cloud.script-ht6yb203.js +23 -0
  12. package/{code.command-3wkn4ja5.js → code.command-spsrzg63.js} +6 -6
  13. package/{context.command-9jjn3gcw.js → context.command-768zv7z4.js} +16 -13
  14. package/context.runner-tf1b53qq.js +24 -0
  15. package/{guideline.command-dtczrqpf.js → guideline.command-4ycwc51q.js} +2 -2
  16. package/guidelines/conventions/conventions.instruction.md +28 -15
  17. package/guidelines/cssRule/cssRule.instruction.md +12 -6
  18. package/guidelines/mcpRule/mcpRule.instruction.md +27 -11
  19. package/guidelines/runtimeRule/runtimeRule.instruction.md +24 -15
  20. package/guidelines/transportRule/transportRule.instruction.md +28 -5
  21. package/incrementalBuilder.proc.js +9 -6
  22. package/{index-2etcv0sc.js → index-00seamy5.js} +1 -1
  23. package/{index-jx4bzvwg.js → index-1a7nhq56.js} +92 -52
  24. package/{index-e0cvze1s.js → index-1nyxvz8j.js} +4 -4
  25. package/index-2z3kykvd.js +248 -0
  26. package/{index-rtct7d43.js → index-3675mvjw.js} +1 -1
  27. package/{index-56d2g8ms.js → index-3ddt3qjg.js} +1 -1
  28. package/{index-6jjtnhkw.js → index-3x7yeecy.js} +51 -9
  29. package/{index-ww9bhp67.js → index-4pf8g7ff.js} +1 -1
  30. package/index-8935h3n1.js +33 -0
  31. package/{index-v29746vb.js → index-8eqkxwsx.js} +3 -3
  32. package/{index-c2yrsxdh.js → index-91rt5bye.js} +96 -320
  33. package/{index-55mynnqs.js → index-bv210r6t.js} +459 -210
  34. package/{index-c76k723e.js → index-c4h5b5nq.js} +2 -2
  35. package/{index-qt22xstj.js → index-c9zjb3tw.js} +5 -3
  36. package/{index-c1x0be5j.js → index-dmsvd2rv.js} +2 -2
  37. package/index-ec080x99.js +1124 -0
  38. package/{index-ctanya41.js → index-fjqvd5mx.js} +4 -4
  39. package/{index-aprt7pkz.js → index-fvn6f5wx.js} +229 -1327
  40. package/{index-rc5rwyps.js → index-jj7yapwq.js} +71 -60
  41. package/index-kmamh5bv.js +241 -0
  42. package/{index-fm46xrf1.js → index-q5abh0jq.js} +3 -3
  43. package/{index-1w2qaee2.js → index-qf8g88j9.js} +361 -291
  44. package/{index-gnyf1fqy.js → index-qvghfv6v.js} +2 -2
  45. package/{index-ae5pwhgs.js → index-r5d6rq19.js} +10 -8
  46. package/{index-2mx692qq.js → index-vhfjzda3.js} +2 -2
  47. package/{index-8r4d7cmt.js → index-w9b71b6y.js} +4 -4
  48. package/{index-8ggztp8k.js → index-wanhh011.js} +42 -177
  49. package/{index-05g3jayg.js → index-wdze51wz.js} +1 -1
  50. package/index-wjqbc7sf.js +668 -0
  51. package/{index-rwq3ekqc.js → index-xf40a295.js} +7 -7
  52. package/{index-krq7btbt.js → index-xm5tmpv0.js} +3 -3
  53. package/index.js +22 -22
  54. package/{library.command-gaga5bmq.js → library.command-88ahgych.js} +3 -3
  55. package/{localRegistry.command-vsreyy42.js → localRegistry.command-ykea1m7b.js} +12 -9
  56. package/{module.command-7vpf6db4.js → module.command-zky4b7m9.js} +5 -5
  57. package/{package.command-twmvvf69.js → package.command-vh8pcedh.js} +3 -3
  58. package/package.json +2 -2
  59. package/{page.command-5asq7fdf.js → page.command-fyqeqxc3.js} +3 -3
  60. package/{pipeline.command-d0v38572.js → pipeline.command-r5t30py6.js} +220 -219
  61. package/{primitive.command-dyrs2fm8.js → primitive.command-a0516zfk.js} +6 -6
  62. package/{projectTypecheck-cvtkrzp2.js → projectTypecheck-7djd4z50.js} +1 -1
  63. package/{quality.command-6emsqpbg.js → quality.command-k7jcnfn0.js} +2 -2
  64. package/{repair.command-8t6aegv5.js → repair.command-85zg2an3.js} +5 -5
  65. package/{scalar.command-bnggy1x7.js → scalar.command-g5vmqwca.js} +4 -4
  66. package/{subspace.command-md2teygq.js → subspace.command-mp4evgsj.js} +421 -362
  67. package/{tunnel.command-jx3tdm2d.js → tunnel.command-kbnr99sj.js} +7 -4
  68. package/{workflow.command-jx0wag5r.js → workflow.command-9y9p1n8y.js} +10 -10
  69. package/{workspace.command-yxd7rr7g.js → workspace.command-jmec2kjg.js} +33 -30
  70. package/TunnelShare-q4jq08qg.js +0 -9
  71. package/cloud.script-h6pvcpa2.js +0 -20
  72. package/context.runner-atcrzz5b.js +0 -21
  73. package/index-6w0rbr9d.js +0 -68
  74. package/index-pgj2rt78.js +0 -404
@@ -0,0 +1,248 @@
1
+ // @bun
2
+ import {
3
+ resolveSsrPageEntriesForApp
4
+ } from "./index-bv210r6t.js";
5
+ import {
6
+ bundleDefine,
7
+ CsrEntryFiles,
8
+ PagesEntrySourceGenerator,
9
+ PagesBundleBuilder
10
+ } from "./index-ec080x99.js";
11
+
12
+ // pkgs/@akanjs/devkit/frontendBuild/csrArtifactBuilder.ts
13
+ import { mkdir, rm, unlink } from "fs/promises";
14
+ import path from "path";
15
+ class CsrArtifactBuilder {
16
+ #app;
17
+ #command;
18
+ #lang;
19
+ #cssAssets;
20
+ constructor(app, command = "start", lang = "en", { cssAssets = null } = {}) {
21
+ this.#app = app;
22
+ this.#command = command;
23
+ this.#lang = lang;
24
+ this.#cssAssets = cssAssets;
25
+ }
26
+ async build() {
27
+ const pageKeys = await this.#app.getPageKeys();
28
+ if (pageKeys.length === 0) {
29
+ this.#app.log(`[cli] no route files under ${this.#app.cwdPath}/page \u2014 skipping CSR build`);
30
+ return null;
31
+ }
32
+ const pageEntries = await resolveSsrPageEntriesForApp(this.#app, pageKeys);
33
+ const akanConfig = await this.#app.getConfig();
34
+ const cssAssets = await this.#loadCssAssets();
35
+ const basePaths = [...akanConfig.basePaths];
36
+ const htmlBasePaths = basePaths.length > 0 ? basePaths : [""];
37
+ await rm(this.#outputDir, { recursive: true, force: true });
38
+ await mkdir(this.#generatedDir, { recursive: true });
39
+ const generatedFiles = Object.fromEntries((await Promise.all(htmlBasePaths.map(async (basePath) => [
40
+ this.#createHtmlFile(basePath),
41
+ await this.#createEntryFile(basePath, CsrArtifactBuilder.pageEntriesForBasePath(pageEntries, basePath, basePaths))
42
+ ]))).flat());
43
+ const options = CsrArtifactBuilder.bundleOptions(this.#app, this.#command, akanConfig.optimizeImports);
44
+ const result = await Bun.build({
45
+ ...options,
46
+ entrypoints: htmlBasePaths.map((basePath) => this.#generatedPath(CsrArtifactBuilder.htmlFilename(basePath))),
47
+ files: generatedFiles,
48
+ root: this.#generatedDir,
49
+ outdir: this.#outputDir
50
+ });
51
+ if (!result.success) {
52
+ const logs = result.logs.map((log) => log.message).join(`
53
+ `);
54
+ throw new Error(`[csr-build] failed${logs ? `
55
+ ${logs}` : ""}`);
56
+ }
57
+ await this.#inlineCsrArtifacts(cssAssets);
58
+ if (this.#command === "build")
59
+ await CsrArtifactBuilder.writePublicEnv(this.#app, options.define);
60
+ this.#app.verbose(`[csr-build] output -> ${this.#outputDir}`);
61
+ return { outputDir: this.#outputDir };
62
+ }
63
+ static bundleOptions(app, command, optimizeImports = []) {
64
+ return {
65
+ target: "browser",
66
+ splitting: false,
67
+ minify: true,
68
+ define: bundleDefine(app, command, "csr"),
69
+ optimizeImports,
70
+ plugins: [PagesBundleBuilder.createCssStubPlugin()]
71
+ };
72
+ }
73
+ static publicEnvPath(app) {
74
+ return path.join(app.dist.cwdPath, ".akan", "artifact", "csr-public-env.json");
75
+ }
76
+ static async writePublicEnv(app, define) {
77
+ const prefix = "process.env.";
78
+ const publicEnv = Object.fromEntries(Object.entries(define).filter(([key]) => key.startsWith(`${prefix}AKAN_PUBLIC_`)).map(([key, value]) => [key.slice(prefix.length), JSON.parse(value)]));
79
+ await Bun.write(CsrArtifactBuilder.publicEnvPath(app), `${JSON.stringify(publicEnv, null, 2)}
80
+ `);
81
+ }
82
+ static pageEntriesForBasePath(pageEntries, basePath, basePaths) {
83
+ return CsrEntryFiles.pageEntriesForBasePath(pageEntries, basePath, basePaths);
84
+ }
85
+ static htmlFilename(basePath) {
86
+ return `${basePath || "index"}.html`;
87
+ }
88
+ static entryFilename(basePath) {
89
+ return CsrEntryFiles.entryFilename(basePath);
90
+ }
91
+ static basePathOfHtml(htmlPath) {
92
+ const name = path.basename(htmlPath, ".html");
93
+ return name === "index" ? "" : name;
94
+ }
95
+ get #outputDir() {
96
+ return path.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, this.#command === "build" ? "csr" : ".akan/artifact/csr");
97
+ }
98
+ get #generatedDir() {
99
+ return path.join(this.#app.cwdPath, ".akan/generated/csr");
100
+ }
101
+ get #artifactDir() {
102
+ return path.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact");
103
+ }
104
+ #generatedPath(filename) {
105
+ return path.join(this.#generatedDir, filename);
106
+ }
107
+ async#createEntryFile(basePath, pageEntries) {
108
+ return [
109
+ this.#generatedPath(CsrArtifactBuilder.entryFilename(basePath)),
110
+ `import { bootCsr } from "akanjs/webkit";
111
+ ${await PagesEntrySourceGenerator.generateStatic(pageEntries)}
112
+ void bootCsr(pages);
113
+ `
114
+ ];
115
+ }
116
+ #createHtmlFile(basePath) {
117
+ return [
118
+ this.#generatedPath(CsrArtifactBuilder.htmlFilename(basePath)),
119
+ `<!doctype html>
120
+ <html lang="${this.#lang}">
121
+ <head>
122
+ <meta charset="utf-8" />
123
+ <title>${this.#app.name}</title>
124
+ <base href="/" />
125
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
126
+ </head>
127
+ <body>
128
+ <div id="root"></div>
129
+ <script type="module" src="./${CsrArtifactBuilder.entryFilename(basePath)}"></script>
130
+ </body>
131
+ </html>
132
+ `
133
+ ];
134
+ }
135
+ async#loadCssAssets() {
136
+ if (this.#cssAssets)
137
+ return this.#cssAssets;
138
+ const artifactFile = Bun.file(path.join(this.#artifactDir, "base-artifact.json"));
139
+ if (!await artifactFile.exists())
140
+ return {};
141
+ const artifact = await artifactFile.json();
142
+ return artifact.cssAssets ?? {};
143
+ }
144
+ async#inlineCsrArtifacts(cssAssets) {
145
+ const jsFiles = new Set;
146
+ for (const htmlPath of await this.#listOutputFiles((filePath) => filePath.endsWith(".html"))) {
147
+ const htmlFile = Bun.file(htmlPath);
148
+ if (!await htmlFile.exists())
149
+ continue;
150
+ const basePath = CsrArtifactBuilder.basePathOfHtml(htmlPath);
151
+ const cssAsset = cssAssets[basePath];
152
+ if (!cssAsset) {
153
+ this.#app.logger.warn(`[csr-build] base-artifact.json has no compiled stylesheet for ${basePath || "root"}; ${path.basename(htmlPath)} ships without CSS`);
154
+ }
155
+ const inlined = await this.#inlineHtmlAssets(await htmlFile.text(), htmlPath, cssAsset);
156
+ for (const filePath of inlined.jsFiles)
157
+ jsFiles.add(filePath);
158
+ await Bun.write(htmlPath, inlined.html);
159
+ }
160
+ for (const filePath of jsFiles)
161
+ await unlink(filePath).catch(() => {
162
+ return;
163
+ });
164
+ const remainingAssets = await this.#listOutputFiles((filePath) => filePath.endsWith(".js") || filePath.endsWith(".css"));
165
+ if (remainingAssets.length > 0) {
166
+ throw new Error(`[csr-build] expected single-file HTML, but CSR assets remain:
167
+ ${remainingAssets.join(`
168
+ `)}`);
169
+ }
170
+ }
171
+ async#inlineHtmlAssets(html, htmlPath, cssAsset) {
172
+ let next = html;
173
+ if (cssAsset) {
174
+ const css = await Bun.file(path.join(this.#artifactDir, cssAsset.cssRelPath)).text();
175
+ next = CsrArtifactBuilder.injectBeforeHeadEnd(next, CsrArtifactBuilder.createInlineStyle(css));
176
+ }
177
+ const jsFiles = [];
178
+ next = await CsrArtifactBuilder.replaceModuleScriptSrc(next, async (src) => {
179
+ const jsPath = CsrArtifactBuilder.resolveHtmlAssetPath(htmlPath, src);
180
+ jsFiles.push(jsPath);
181
+ return await Bun.file(jsPath).text();
182
+ });
183
+ return { html: next, jsFiles };
184
+ }
185
+ async#listOutputFiles(predicate) {
186
+ const glob = new Bun.Glob("**/*");
187
+ const files = [];
188
+ for await (const filePath of glob.scan({ cwd: this.#outputDir, absolute: true })) {
189
+ if (predicate(filePath))
190
+ files.push(filePath);
191
+ }
192
+ return files.sort();
193
+ }
194
+ static injectBeforeHeadEnd(html, snippet) {
195
+ const scannable = CsrArtifactBuilder.blankEmbeddedContent(html);
196
+ const headEnd = scannable.search(/<\/head\s*>/i);
197
+ if (headEnd !== -1)
198
+ return `${html.slice(0, headEnd)}${snippet}
199
+ ${html.slice(headEnd)}`;
200
+ const bodyStart = scannable.search(/<body(?:\s|>)/i);
201
+ if (bodyStart !== -1)
202
+ return `${html.slice(0, bodyStart)}${snippet}
203
+ ${html.slice(bodyStart)}`;
204
+ return `${html}
205
+ ${snippet}`;
206
+ }
207
+ static blankEmbeddedContent(html) {
208
+ return html.replace(/<script\b[^>]*>[\s\S]*?<\/script\s*>|<style\b[^>]*>[\s\S]*?<\/style\s*>|<!--[\s\S]*?-->/gi, (match) => " ".repeat(match.length));
209
+ }
210
+ static createInlineStyle(css) {
211
+ return `<style data-akan-css="active">
212
+ ${css.replace(/<\/style/gi, "<\\/style")}
213
+ </style>`;
214
+ }
215
+ static async replaceModuleScriptSrc(html, loadScript) {
216
+ const scriptRe = /<script\b(?=[^>]*\btype=["']module["'])(?=[^>]*\bsrc=["']([^"']+)["'])[^>]*>\s*<\/script>/gi;
217
+ let result = "";
218
+ let lastIndex = 0;
219
+ let matched = false;
220
+ for (const match of html.matchAll(scriptRe)) {
221
+ const full = match[0];
222
+ const src = match[1];
223
+ if (match.index === undefined || !src)
224
+ continue;
225
+ matched = true;
226
+ result += html.slice(lastIndex, match.index);
227
+ result += `<script type="module">
228
+ ${CsrArtifactBuilder.escapeInlineScript(await loadScript(src))}
229
+ </script>`;
230
+ lastIndex = match.index + full.length;
231
+ }
232
+ if (!matched)
233
+ return html;
234
+ return result + html.slice(lastIndex);
235
+ }
236
+ static escapeInlineScript(source) {
237
+ return source.replace(/<\/script/gi, "<\\/script");
238
+ }
239
+ static resolveHtmlAssetPath(htmlPath, src) {
240
+ if (/^[a-z][a-z0-9+.-]*:/i.test(src) || src.startsWith("//")) {
241
+ throw new Error(`[csr-build] cannot inline external script: ${src}`);
242
+ }
243
+ const normalized = src.startsWith("/") ? src.slice(1) : src;
244
+ return path.resolve(path.dirname(htmlPath), normalized);
245
+ }
246
+ }
247
+
248
+ export { CsrArtifactBuilder };
@@ -116,7 +116,7 @@ class SubagentPool2 {
116
116
  }
117
117
  }
118
118
  async#run(id, kind, prompt, signal) {
119
- const { CodeAgent } = await import("./CodeAgent-kyprmy06.js");
119
+ const { CodeAgent } = await import("./CodeAgent-ctk4fh2b.js");
120
120
  const budget = this.#options.parent.tools.subagent;
121
121
  const child = SubagentPool2.childOf(this.#options.parent, kind);
122
122
  const agent = await CodeAgent.create({
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  GlobalConfig,
4
4
  CloudApi
5
- } from "./index-pgj2rt78.js";
5
+ } from "./index-wjqbc7sf.js";
6
6
 
7
7
  // pkgs/@akanjs/cli/tunnel/TunnelShare.ts
8
8
  import { TunnelAgent } from "akanjs/server/tunnel";
@@ -10,7 +10,7 @@ import {
10
10
  LibExecutor,
11
11
  PkgExecutor,
12
12
  ModuleExecutor
13
- } from "./index-55mynnqs.js";
13
+ } from "./index-bv210r6t.js";
14
14
 
15
15
  // pkgs/@akanjs/devkit/commandDecorators/camelToKebabCase.ts
16
16
  var camelToKebabCase = (str) => str.replace(/([A-Z])/g, "-$1").toLowerCase();
@@ -40,7 +40,7 @@ var getArgMetas = (command, key) => {
40
40
  const internalArgMetas = allArgMetas.filter((argMeta) => argMeta.type !== "Option");
41
41
  return [allArgMetas, argMetas, internalArgMetas];
42
42
  };
43
- var createInternalArgToken = (type) => ({ type });
43
+ var createInternalArgToken = (type, option) => option ? { type, option } : { type };
44
44
  var normalizePrimitiveArgType = (type) => {
45
45
  if (type === String)
46
46
  return "string";
@@ -54,6 +54,7 @@ var App = createInternalArgToken("App");
54
54
  var Apps = createInternalArgToken("Apps");
55
55
  var Lib = createInternalArgToken("Lib");
56
56
  var Sys = createInternalArgToken("Sys");
57
+ var SysOrOnlyApp = createInternalArgToken("Sys", { onlyApp: true });
57
58
  var Exec = createInternalArgToken("Exec");
58
59
  var Pkg = createInternalArgToken("Pkg");
59
60
  var Module = createInternalArgToken("Module");
@@ -160,6 +161,19 @@ class AppSelectionMemory {
160
161
  }
161
162
  }
162
163
 
164
+ // pkgs/@akanjs/devkit/commandDecorators/exitCodeError.ts
165
+ class ExitCodeError extends Error {
166
+ exitCode;
167
+ name = "ExitCodeError";
168
+ constructor(message, exitCode) {
169
+ super(message);
170
+ this.exitCode = exitCode;
171
+ }
172
+ static codeOf(error) {
173
+ return error instanceof ExitCodeError ? error.exitCode : null;
174
+ }
175
+ }
176
+
163
177
  // pkgs/@akanjs/devkit/commandDecorators/helpFormatter.ts
164
178
  import chalk from "chalk";
165
179
  var formatChoice = (choice) => typeof choice === "object" ? choice.label : choice.toString();
@@ -352,6 +366,7 @@ var select = (config, context) => prompts().then((m) => m.select(config, context
352
366
  var confirm = (config, context) => prompts().then((m) => m.confirm(config, context));
353
367
  var input = (config, context) => prompts().then((m) => m.input(config, context));
354
368
  var checkbox = (config, context) => prompts().then((m) => m.checkbox(config, context));
369
+ var argLabelOf = (argMeta) => argMeta.type === "Option" ? `option '--${camelToKebabCase(argMeta.name)}'` : `argument '${argMeta.name}'`;
355
370
  var assertEnumChoice = (argMeta, value) => {
356
371
  const enumChoices = argMeta.argsOption.enum;
357
372
  if (!enumChoices || typeof enumChoices === "function")
@@ -359,8 +374,12 @@ var assertEnumChoice = (argMeta, value) => {
359
374
  const choices = normalizeEnumChoices(enumChoices);
360
375
  if (choices.some((choice) => String(choice.value) === String(value)))
361
376
  return;
362
- const label = argMeta.type === "Option" ? `option '--${camelToKebabCase(argMeta.name)}'` : `argument '${argMeta.name}'`;
363
- throw new Error(`${label} argument '${String(value)}' is invalid. Allowed choices are ${choices.map((choice) => choice.name).join(", ")}.`);
377
+ throw new Error(`${argLabelOf(argMeta)} argument '${String(value)}' is invalid. Allowed choices are ${choices.map((choice) => choice.name).join(", ")}.`);
378
+ };
379
+ var assertPromptable = (problem, { choices = [], remedy = "pass it on the command line" } = {}) => {
380
+ if (process.stdin.isTTY)
381
+ return;
382
+ throw new Error(`${problem}: stdin is not a terminal to prompt on, so ${remedy}${choices.length ? ` (choices: ${choices.join(", ")})` : ""}.`);
364
383
  };
365
384
  var inputMessageOf = ({ name, argsOption: { desc, example, ask } }) => ask ? `${ask}: ` : desc ? `${desc}: ` : `Enter the ${name} value${example ? ` (example: ${example})` : ""}: `;
366
385
  var getOptionValue = async (argMeta, opt, context) => {
@@ -379,8 +398,11 @@ var getOptionValue = async (argMeta, opt, context) => {
379
398
  const choices = normalizeEnumChoices((typeof enumChoices === "function" ? await enumChoices(context) : enumChoices) ?? []);
380
399
  if (choices.length === 1)
381
400
  return choices[0]?.value;
401
+ assertPromptable(`Missing ${argLabelOf(argMeta)}`, { choices: choices.map((choice) => choice.value) });
382
402
  return await select({ message: ask ?? desc ?? `Select the ${name} value`, choices });
383
- } else if (type === "boolean") {
403
+ }
404
+ assertPromptable(`Missing ${argLabelOf(argMeta)}`);
405
+ if (type === "boolean") {
384
406
  const message = ask ?? desc ?? `Do you want to set ${name}? ${desc ? ` (${desc})` : ""}: `;
385
407
  return await confirm({ message });
386
408
  } else
@@ -395,6 +417,10 @@ var getArgumentValue = async (argMeta, value) => {
395
417
  return defaultValue;
396
418
  else if (nullable)
397
419
  return null;
420
+ const { enum: enumChoices } = argMeta.argsOption;
421
+ assertPromptable(`Missing ${argLabelOf(argMeta)}`, {
422
+ choices: enumChoices && typeof enumChoices !== "function" ? normalizeEnumChoices(enumChoices).map(({ value }) => value) : []
423
+ });
398
424
  return convertArgValue(await input({ message: inputMessageOf(argMeta) }), type ?? "string");
399
425
  };
400
426
  var assignCommandContext = (context, argMeta, value) => {
@@ -445,6 +471,7 @@ var getAppsArgumentValue = async (value, workspace) => {
445
471
  }
446
472
  if (appNames.length === 1 && appNames[0])
447
473
  return [AppExecutor.from(workspace, appNames[0])];
474
+ assertPromptable("Missing apps", { choices: [...appNames, "all"] });
448
475
  const remembered = new Set(await AppSelectionMemory.read(workspace.workspaceRoot));
449
476
  const picked = await checkbox({
450
477
  message: "Select the apps to run (space to toggle, enter to confirm)",
@@ -459,6 +486,7 @@ var getInternalArgumentValue = async (argMeta, value, workspace) => {
459
486
  return workspace;
460
487
  const sysType = argMeta.type.toLowerCase();
461
488
  const [appNames, libNames, pkgNames] = await workspace.getExecs();
489
+ const problemOf = (kind) => value ? `Unknown ${kind} '${value}'` : `Missing ${kind}`;
462
490
  if (sysType === "sys" || sysType === "exec") {
463
491
  const pkgChoices = sysType === "exec" ? pkgNames : [];
464
492
  const execOf = (name) => {
@@ -473,6 +501,11 @@ var getInternalArgumentValue = async (argMeta, value, workspace) => {
473
501
  const found = value ? execOf(value) : null;
474
502
  if (found)
475
503
  return found;
504
+ if (!value && argMeta.option?.onlyApp && appNames.length === 1 && appNames[0])
505
+ return AppExecutor.from(workspace, appNames[0]);
506
+ assertPromptable(problemOf(sysType === "exec" ? "app, lib or pkg" : "app or lib"), {
507
+ choices: [...appNames, ...libNames, ...pkgChoices]
508
+ });
476
509
  const name = await select({
477
510
  message: sysType === "exec" ? `Select the App or Lib or Pkg name` : `Select the App or Lib name`,
478
511
  choices: [...appNames, ...libNames, ...pkgChoices]
@@ -486,17 +519,20 @@ var getInternalArgumentValue = async (argMeta, value, workspace) => {
486
519
  return AppExecutor.from(workspace, value);
487
520
  if (!value && appNames.length === 1 && appNames[0])
488
521
  return AppExecutor.from(workspace, appNames[0]);
522
+ assertPromptable(problemOf("app"), { choices: appNames });
489
523
  const appName = await select({ message: `Select the ${sysType} name`, choices: appNames });
490
524
  return AppExecutor.from(workspace, appName);
491
525
  } else if (sysType === "lib") {
492
526
  if (value && libNames.includes(value))
493
527
  return LibExecutor.from(workspace, value);
528
+ assertPromptable(problemOf("lib"), { choices: libNames });
494
529
  const libName = await select({ message: `Select the ${sysType} name`, choices: libNames });
495
530
  return LibExecutor.from(workspace, libName);
496
531
  } else if (sysType === "pkg") {
497
532
  const pkgs = await workspace.getPkgs();
498
533
  if (value && pkgs.includes(value))
499
534
  return PkgExecutor.from(workspace, value);
535
+ assertPromptable(problemOf("pkg"), { choices: pkgs });
500
536
  const pkgName = await select({ message: `Select the ${sysType} name`, choices: pkgs });
501
537
  return PkgExecutor.from(workspace, pkgName);
502
538
  } else if (sysType === "module") {
@@ -519,6 +555,7 @@ var getInternalArgumentValue = async (argMeta, value, workspace) => {
519
555
  } else
520
556
  throw new Error(`Invalid system name: ${sysName}`);
521
557
  }
558
+ assertPromptable(problemOf("module"));
522
559
  const { type, name } = await select({
523
560
  message: `select the App or Lib name`,
524
561
  choices: [
@@ -540,7 +577,7 @@ var runCommands = async (...commands) => {
540
577
  let failureExitCode = 1;
541
578
  process.on("unhandledRejection", (error) => {
542
579
  printCliError(error);
543
- process.exit(failureExitCode);
580
+ process.exit(ExitCodeError.codeOf(error) ?? failureExitCode);
544
581
  });
545
582
  const __dirname2 = getDirname2(import.meta.url);
546
583
  const packageJsonCandidates = [`${path2.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
@@ -647,7 +684,7 @@ It may cause unexpected behavior. Run \`akan update\` to update latest akanjs.`)
647
684
  }
648
685
  await program.parseAsync(process.argv).catch((error) => {
649
686
  printCliError(error);
650
- process.exit(failureExitCode);
687
+ process.exit(ExitCodeError.codeOf(error) ?? failureExitCode);
651
688
  });
652
689
  };
653
690
 
@@ -671,7 +708,12 @@ class TargetBuilder {
671
708
  return this.#add(argMetaOf("Option", name, type, argsOption, this.#args.length));
672
709
  }
673
710
  with(...tokens) {
674
- return this.#add(...tokens.map((token, offset) => ({ key: "", idx: this.#args.length + offset, type: token.type })));
711
+ return this.#add(...tokens.map((token, offset) => ({
712
+ key: "",
713
+ idx: this.#args.length + offset,
714
+ type: token.type,
715
+ ...token.option ? { option: token.option } : {}
716
+ })));
675
717
  }
676
718
  exec(handler) {
677
719
  return {
@@ -718,4 +760,4 @@ function command(refName, depsOrBuilder, builder) {
718
760
  }
719
761
  return CommandBase;
720
762
  }
721
- export { getTargetMetas, getTargetCommandNames, App, Apps, Lib, Sys, Exec, Pkg, Module, Workspace, CommandContainer, runner, script, runCommands, command };
763
+ export { getTargetMetas, getTargetCommandNames, App, Apps, Lib, Sys, SysOrOnlyApp, Exec, Pkg, Module, Workspace, CommandContainer, runner, script, ExitCodeError, assertPromptable, runCommands, command };
@@ -55,7 +55,7 @@ class SubspaceConfig {
55
55
  assertPushable(branch) {
56
56
  if (this.pushableBranches.includes(branch))
57
57
  return;
58
- throw new Error(`Branch "${branch}" is not pushable. ${SubspaceConfig.source} allows: ${this.pushableBranches.join(", ")}`);
58
+ throw new Error(`Branch "${branch}" is not pushable. \`subspace.pushableBranches\` in the workspace root akan.config.ts allows: ${this.pushableBranches.join(", ")}`);
59
59
  }
60
60
  }
61
61
 
@@ -0,0 +1,33 @@
1
+ // @bun
2
+ import {
3
+ getMobileTargetChoices
4
+ } from "./index-q958tqqg.js";
5
+
6
+ // pkgs/@akanjs/cli/application/commandOptions.ts
7
+ var targetChoices = async ({ app }) => await getMobileTargetChoices(app);
8
+ var writeOption = { desc: "write code generation", default: true };
9
+ var nativeTargetOption = {
10
+ desc: "native target name (a key of native.targets) or all",
11
+ ask: "Select native target",
12
+ enum: targetChoices
13
+ };
14
+ var oneNativeTargetOption = {
15
+ desc: "native target name (a key of native.targets)",
16
+ ask: "Select native target",
17
+ enum: targetChoices
18
+ };
19
+ var nativeEnvs = ["debug", "develop", "main", "local"];
20
+ var releaseEnvOption = { enum: nativeEnvs, desc: "backend environment", default: "main" };
21
+ var allowLocalOption = (what) => ({ flag: "l", desc: `allow ${what} with --env local`, default: false });
22
+ var publicEnvOption = (what) => ({
23
+ flag: "u",
24
+ desc: `the AKAN_PUBLIC_* ${what} inlines, exactly: a JSON map of them, or a store build's bundle.json that recorded them`,
25
+ nullable: true
26
+ });
27
+ var hostOption = {
28
+ desc: "host of the cloud to target (default: cloud.host of the root akan.config.ts, else Akan Cloud)",
29
+ nullable: true
30
+ };
31
+ var subspaceOption = (whose) => ({ desc: `the subspace whose project ${whose}`, nullable: true });
32
+
33
+ export { writeOption, nativeTargetOption, oneNativeTargetOption, nativeEnvs, releaseEnvOption, allowLocalOption, publicEnvOption, hostOption, subspaceOption };
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  runner,
4
4
  script
5
- } from "./index-6jjtnhkw.js";
5
+ } from "./index-3x7yeecy.js";
6
6
  import {
7
7
  AGENT_BLOCK_START,
8
8
  AGENT_BLOCK_END,
@@ -13,14 +13,14 @@ import {
13
13
  CLAUDE_COMMENT_RULE,
14
14
  AppExecutor,
15
15
  LibExecutor
16
- } from "./index-55mynnqs.js";
16
+ } from "./index-bv210r6t.js";
17
17
  import {
18
18
  collectRecipeSources2,
19
19
  scanRecipes2
20
20
  } from "./index-hj6w4ka1.js";
21
21
  import {
22
22
  AkanContextAnalyzer
23
- } from "./index-2mx692qq.js";
23
+ } from "./index-vhfjzda3.js";
24
24
  import {
25
25
  Prompter2
26
26
  } from "./index-zzvvc845.js";