@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.
- package/.build-stamp +1 -1
- package/{CodeAgent-kyprmy06.js → CodeAgent-ctk4fh2b.js} +2 -2
- package/{CodeTui-21mtze3j.js → CodeTui-mrxtrdzw.js} +1 -1
- package/TunnelShare-rj74jd6x.js +13 -0
- package/{agent.command-f3gsc1gd.js → agent.command-ncre6kwz.js} +5 -5
- package/akanCode.js +2 -2
- package/{application.command-5s780vnz.js → application.command-54mawreg.js} +52 -41
- package/{applicationBuildRunner-1yaqsrdq.js → applicationBuildRunner-8573zr2w.js} +16 -30
- package/buildBatch.proc.js +22 -13
- package/{cloud.command-yj6xb2a7.js → cloud.command-nyemv0m3.js} +57 -65
- package/cloud.script-ht6yb203.js +23 -0
- package/{code.command-3wkn4ja5.js → code.command-spsrzg63.js} +6 -6
- package/{context.command-9jjn3gcw.js → context.command-768zv7z4.js} +16 -13
- package/context.runner-tf1b53qq.js +24 -0
- package/{guideline.command-dtczrqpf.js → guideline.command-4ycwc51q.js} +2 -2
- package/guidelines/conventions/conventions.instruction.md +28 -15
- package/guidelines/cssRule/cssRule.instruction.md +12 -6
- package/guidelines/mcpRule/mcpRule.instruction.md +27 -11
- package/guidelines/runtimeRule/runtimeRule.instruction.md +24 -15
- package/guidelines/transportRule/transportRule.instruction.md +28 -5
- package/incrementalBuilder.proc.js +9 -6
- package/{index-2etcv0sc.js → index-00seamy5.js} +1 -1
- package/{index-jx4bzvwg.js → index-1a7nhq56.js} +92 -52
- package/{index-e0cvze1s.js → index-1nyxvz8j.js} +4 -4
- package/index-2z3kykvd.js +248 -0
- package/{index-rtct7d43.js → index-3675mvjw.js} +1 -1
- package/{index-56d2g8ms.js → index-3ddt3qjg.js} +1 -1
- package/{index-6jjtnhkw.js → index-3x7yeecy.js} +51 -9
- package/{index-ww9bhp67.js → index-4pf8g7ff.js} +1 -1
- package/index-8935h3n1.js +33 -0
- package/{index-v29746vb.js → index-8eqkxwsx.js} +3 -3
- package/{index-c2yrsxdh.js → index-91rt5bye.js} +96 -320
- package/{index-55mynnqs.js → index-bv210r6t.js} +459 -210
- package/{index-c76k723e.js → index-c4h5b5nq.js} +2 -2
- package/{index-qt22xstj.js → index-c9zjb3tw.js} +5 -3
- package/{index-c1x0be5j.js → index-dmsvd2rv.js} +2 -2
- package/index-ec080x99.js +1124 -0
- package/{index-ctanya41.js → index-fjqvd5mx.js} +4 -4
- package/{index-aprt7pkz.js → index-fvn6f5wx.js} +229 -1327
- package/{index-rc5rwyps.js → index-jj7yapwq.js} +71 -60
- package/index-kmamh5bv.js +241 -0
- package/{index-fm46xrf1.js → index-q5abh0jq.js} +3 -3
- package/{index-1w2qaee2.js → index-qf8g88j9.js} +361 -291
- package/{index-gnyf1fqy.js → index-qvghfv6v.js} +2 -2
- package/{index-ae5pwhgs.js → index-r5d6rq19.js} +10 -8
- package/{index-2mx692qq.js → index-vhfjzda3.js} +2 -2
- package/{index-8r4d7cmt.js → index-w9b71b6y.js} +4 -4
- package/{index-8ggztp8k.js → index-wanhh011.js} +42 -177
- package/{index-05g3jayg.js → index-wdze51wz.js} +1 -1
- package/index-wjqbc7sf.js +668 -0
- package/{index-rwq3ekqc.js → index-xf40a295.js} +7 -7
- package/{index-krq7btbt.js → index-xm5tmpv0.js} +3 -3
- package/index.js +22 -22
- package/{library.command-gaga5bmq.js → library.command-88ahgych.js} +3 -3
- package/{localRegistry.command-vsreyy42.js → localRegistry.command-ykea1m7b.js} +12 -9
- package/{module.command-7vpf6db4.js → module.command-zky4b7m9.js} +5 -5
- package/{package.command-twmvvf69.js → package.command-vh8pcedh.js} +3 -3
- package/package.json +2 -2
- package/{page.command-5asq7fdf.js → page.command-fyqeqxc3.js} +3 -3
- package/{pipeline.command-d0v38572.js → pipeline.command-r5t30py6.js} +220 -219
- package/{primitive.command-dyrs2fm8.js → primitive.command-a0516zfk.js} +6 -6
- package/{projectTypecheck-cvtkrzp2.js → projectTypecheck-7djd4z50.js} +1 -1
- package/{quality.command-6emsqpbg.js → quality.command-k7jcnfn0.js} +2 -2
- package/{repair.command-8t6aegv5.js → repair.command-85zg2an3.js} +5 -5
- package/{scalar.command-bnggy1x7.js → scalar.command-g5vmqwca.js} +4 -4
- package/{subspace.command-md2teygq.js → subspace.command-mp4evgsj.js} +421 -362
- package/{tunnel.command-jx3tdm2d.js → tunnel.command-kbnr99sj.js} +7 -4
- package/{workflow.command-jx0wag5r.js → workflow.command-9y9p1n8y.js} +10 -10
- package/{workspace.command-yxd7rr7g.js → workspace.command-jmec2kjg.js} +33 -30
- package/TunnelShare-q4jq08qg.js +0 -9
- package/cloud.script-h6pvcpa2.js +0 -20
- package/context.runner-atcrzz5b.js +0 -21
- package/index-6w0rbr9d.js +0 -68
- 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-
|
|
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({
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
LibExecutor,
|
|
11
11
|
PkgExecutor,
|
|
12
12
|
ModuleExecutor
|
|
13
|
-
} from "./index-
|
|
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) =>
|
|
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
|
-
|
|
363
|
-
|
|
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
|
-
}
|
|
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) => ({
|
|
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.
|
|
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-
|
|
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-
|
|
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-
|
|
23
|
+
} from "./index-vhfjzda3.js";
|
|
24
24
|
import {
|
|
25
25
|
Prompter2
|
|
26
26
|
} from "./index-zzvvc845.js";
|