@akanjs/cli 3.0.2 → 3.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.build-stamp +1 -1
- package/{CodeAgent-szbjv4gv.js → CodeAgent-kyprmy06.js} +2 -2
- package/{CodeTui-5nw86ab6.js → CodeTui-21mtze3j.js} +1 -1
- package/{TunnelShare-cwh9ezsm.js → TunnelShare-q4jq08qg.js} +2 -2
- package/{agent.command-np1dffkb.js → agent.command-f3gsc1gd.js} +5 -5
- package/akanCode.js +2 -2
- package/{application.command-gk69v1xs.js → application.command-5s780vnz.js} +37 -15
- package/{applicationBuildRunner-wx09n9g6.js → applicationBuildRunner-1yaqsrdq.js} +115 -103
- package/buildBatch.proc.js +16 -5
- package/cloud.command-yj6xb2a7.js +192 -0
- package/cloud.script-h6pvcpa2.js +20 -0
- package/{code.command-hmtx14b2.js → code.command-3wkn4ja5.js} +6 -6
- package/commandManifest.json +1 -1
- package/{context.command-6aqvdx43.js → context.command-9jjn3gcw.js} +13 -13
- package/context.runner-atcrzz5b.js +21 -0
- package/{guideline.command-axvf68gc.js → guideline.command-dtczrqpf.js} +2 -2
- package/guidelines/agentRule/agentRule.instruction.md +10 -2
- package/guidelines/conventions/conventions.instruction.md +70 -25
- package/guidelines/cssRule/cssRule.instruction.md +19 -0
- package/guidelines/mcpRule/mcpRule.instruction.md +72 -12
- package/guidelines/queryRule/queryRule.instruction.md +11 -1
- package/guidelines/runtimeRule/runtimeRule.instruction.md +97 -16
- package/guidelines/ssrRule/ssrRule.instruction.md +10 -7
- package/guidelines/transportRule/transportRule.instruction.md +19 -0
- package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +6 -6
- package/incrementalBuilder.proc.js +24 -3
- package/{index-h9ht6s60.js → index-05g3jayg.js} +1 -1
- package/{index-jk9xnck6.js → index-1w2qaee2.js} +240 -133
- package/{index-g38nhv87.js → index-2etcv0sc.js} +1 -1
- package/{index-zyw622y1.js → index-2mx692qq.js} +3 -3
- package/{index-50wb2a26.js → index-55mynnqs.js} +354 -129
- package/{index-2wc41k5w.js → index-56d2g8ms.js} +2 -2
- package/{index-q6ft9fkc.js → index-6jjtnhkw.js} +8 -3
- package/index-6w0rbr9d.js +68 -0
- package/{index-hxnnfy57.js → index-8ggztp8k.js} +204 -8
- package/{index-zwd84m0w.js → index-8r4d7cmt.js} +4 -4
- package/{index-j38qkvkk.js → index-ae5pwhgs.js} +12 -10
- package/{index-gtjgnv36.js → index-aprt7pkz.js} +6 -9
- package/{index-1bjkfvm9.js → index-c1x0be5j.js} +2 -2
- package/{index-z750gk1j.js → index-c2yrsxdh.js} +13 -7
- package/{index-cb6yc5mb.js → index-c76k723e.js} +2 -2
- package/{index-6keyf4sg.js → index-ctanya41.js} +4 -4
- package/{index-f4e08ptp.js → index-e0cvze1s.js} +4 -4
- package/{index-hp3stk1m.js → index-fm46xrf1.js} +3 -3
- package/{index-3xmzr1p1.js → index-gnyf1fqy.js} +2 -2
- package/{index-nwd6qzvv.js → index-jx4bzvwg.js} +138 -55
- package/{index-jb0hmt3k.js → index-krq7btbt.js} +3 -3
- package/{index-94s080qm.js → index-pgj2rt78.js} +139 -1
- package/index-q958tqqg.js +77 -0
- package/{index-50jjwg8y.js → index-qt22xstj.js} +1 -1
- package/index-rc5rwyps.js +201 -0
- package/{index-xwprn9nr.js → index-rtct7d43.js} +1 -1
- package/{index-bsv901fd.js → index-rwq3ekqc.js} +7 -7
- package/{index-1gs9g12n.js → index-v29746vb.js} +4 -4
- package/index-ww9bhp67.js +62 -0
- package/index.js +22 -21
- package/{library.command-9m2rdwwz.js → library.command-gaga5bmq.js} +3 -3
- package/{localRegistry.command-kda81jyk.js → localRegistry.command-vsreyy42.js} +9 -9
- package/{module.command-q63dffya.js → module.command-7vpf6db4.js} +5 -5
- package/{package.command-y2jh0m99.js → package.command-twmvvf69.js} +3 -3
- package/package.json +2 -2
- package/{page.command-f3e4cwhh.js → page.command-5asq7fdf.js} +3 -3
- package/pipeline.command-d0v38572.js +1334 -0
- package/{primitive.command-r4kq75qj.js → primitive.command-dyrs2fm8.js} +6 -6
- package/projectTypecheck-cvtkrzp2.js +7 -0
- package/{quality.command-f7gzh26z.js → quality.command-6emsqpbg.js} +5 -4
- package/{repair.command-0qmyr6qa.js → repair.command-8t6aegv5.js} +5 -5
- package/{scalar.command-kddn7av4.js → scalar.command-bnggy1x7.js} +4 -4
- package/{subspace.command-ft65qvc4.js → subspace.command-md2teygq.js} +158 -91
- package/templates/app/env/env.client.type.ts +2 -3
- package/templates/app/page/styles.css.template +8 -0
- package/templates/appSample/page/task/[taskId]/_index.tsx +2 -2
- package/templates/appSample/page/task/[taskId]/edit.tsx +2 -2
- package/templates/appSample/page/task/_index.tsx +2 -2
- package/templates/crudPages/[__model__Id]/edit/page.tsx +2 -2
- package/templates/crudPages/[__model__Id]/page.tsx +3 -3
- package/templates/crudPages/page.tsx +2 -2
- package/templates/crudSinglePage/page.tsx +3 -3
- package/templates/lib/cnst.ts +2 -2
- package/templates/lib/sig.ts +3 -3
- package/{tunnel.command-b3ymdk4f.js → tunnel.command-jx3tdm2d.js} +16 -13
- package/{workflow.command-z1srcdfw.js → workflow.command-jx0wag5r.js} +10 -10
- package/{workspace.command-vp6vmx3z.js → workspace.command-yxd7rr7g.js} +57 -27
- package/cloud.command-tw06613r.js +0 -95
- package/cloud.script-64gzba8r.js +0 -20
- package/context.runner-hnkvv3z3.js +0 -21
- package/index-t91a7339.js +0 -104
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
writeGeneratedSyncState,
|
|
6
6
|
createRepairReport,
|
|
7
7
|
renderRepairReport
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-05g3jayg.js";
|
|
9
9
|
import {
|
|
10
10
|
AkanContextAnalyzer
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-2mx692qq.js";
|
|
12
12
|
import {
|
|
13
13
|
runner
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-6jjtnhkw.js";
|
|
15
15
|
|
|
16
16
|
// pkgs/@akanjs/cli/repair/repair.runner.ts
|
|
17
17
|
var spawnShell = async (workspace, command) => await workspace.spawn("bash", ["-lc", command.startsWith("akan ") ? `bun run ${command}` : command], {
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runner,
|
|
4
4
|
script
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-6jjtnhkw.js";
|
|
6
6
|
import {
|
|
7
7
|
FileSys2
|
|
8
8
|
} from "./index-52w0fvh8.js";
|
|
9
9
|
import {
|
|
10
10
|
PkgExecutor
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-55mynnqs.js";
|
|
12
12
|
import {
|
|
13
13
|
TypeScriptDependencyScanner2
|
|
14
14
|
} from "./index-2ahj896a.js";
|
|
@@ -39,29 +39,32 @@ import {
|
|
|
39
39
|
import {
|
|
40
40
|
runner,
|
|
41
41
|
script
|
|
42
|
-
} from "./index-
|
|
42
|
+
} from "./index-6jjtnhkw.js";
|
|
43
43
|
import {
|
|
44
44
|
WorkspaceExecutor,
|
|
45
45
|
AppExecutor,
|
|
46
46
|
LibExecutor,
|
|
47
47
|
PkgExecutor
|
|
48
|
-
} from "./index-
|
|
48
|
+
} from "./index-55mynnqs.js";
|
|
49
49
|
import {
|
|
50
50
|
DesktopServerStage,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
} from "./index-jk9xnck6.js";
|
|
51
|
+
NativeApp,
|
|
52
|
+
UpdateUploader
|
|
53
|
+
} from "./index-1w2qaee2.js";
|
|
55
54
|
import {
|
|
56
55
|
LibraryScript
|
|
57
|
-
} from "./index-
|
|
56
|
+
} from "./index-c1x0be5j.js";
|
|
58
57
|
import {
|
|
59
58
|
stripAnsi
|
|
60
59
|
} from "./index-7md2g9vw.js";
|
|
61
60
|
import {
|
|
62
61
|
SlicePlanner,
|
|
63
62
|
formatSlicePlan
|
|
64
|
-
} from "./index-
|
|
63
|
+
} from "./index-qt22xstj.js";
|
|
64
|
+
import {
|
|
65
|
+
resolveMobileTargets,
|
|
66
|
+
resolveAppId
|
|
67
|
+
} from "./index-q958tqqg.js";
|
|
65
68
|
import {
|
|
66
69
|
openBrowser
|
|
67
70
|
} from "./index-9dp031by.js";
|
|
@@ -1832,7 +1835,7 @@ ${this.#backendStderrTail.join(`
|
|
|
1832
1835
|
this.#wakeFromIdle(`${message.type} arrived while suspended`);
|
|
1833
1836
|
return;
|
|
1834
1837
|
}
|
|
1835
|
-
if (message.type === "build-csr" && this.env.AKAN_DEV_CSR_REBUILD !== "1") {
|
|
1838
|
+
if (message.type === "build-csr" && !message.shell && this.env.AKAN_DEV_CSR_REBUILD !== "1") {
|
|
1836
1839
|
Object.assign(this.env, { AKAN_DEV_CSR_REBUILD: "1" });
|
|
1837
1840
|
this.logger.verbose(`[csr] armed dev CSR rebuilds (${message.reason})`);
|
|
1838
1841
|
}
|
|
@@ -1886,7 +1889,7 @@ ${uniqueCandidates.map((candidate) => ` - ${candidate}`).join(`
|
|
|
1886
1889
|
|
|
1887
1890
|
// pkgs/@akanjs/cli/application/application.runner.ts
|
|
1888
1891
|
import { Logger as Logger3 } from "akanjs/common";
|
|
1889
|
-
var loadBuildRunner = async () => (await import("./applicationBuildRunner-
|
|
1892
|
+
var loadBuildRunner = async () => (await import("./applicationBuildRunner-1yaqsrdq.js")).ApplicationBuildRunner;
|
|
1890
1893
|
var loadPrompts = async () => await import("@inquirer/prompts");
|
|
1891
1894
|
|
|
1892
1895
|
class ApplicationRunner extends runner("application") {
|
|
@@ -2043,6 +2046,18 @@ try {
|
|
|
2043
2046
|
async typecheck(app, options = {}) {
|
|
2044
2047
|
await new (await loadBuildRunner())(app).typecheck(options);
|
|
2045
2048
|
}
|
|
2049
|
+
async typecheckLibrary(lib, options = {}) {
|
|
2050
|
+
const { ProjectTypecheck } = await import("./projectTypecheck-cvtkrzp2.js");
|
|
2051
|
+
const root = lib.workspace.workspaceRoot;
|
|
2052
|
+
await new ProjectTypecheck(lib.cwdPath, root, { ...process.env, AKAN_WORKSPACE_ROOT: root }).run([
|
|
2053
|
+
"../../server.ts",
|
|
2054
|
+
"../../client.ts",
|
|
2055
|
+
"../../index.ts",
|
|
2056
|
+
"../../page/**/*.ts",
|
|
2057
|
+
"../../page/**/*.tsx",
|
|
2058
|
+
"../../../../pkgs/akanjs/*/types/**/*.d.ts"
|
|
2059
|
+
], options);
|
|
2060
|
+
}
|
|
2046
2061
|
async test(exec) {
|
|
2047
2062
|
const isSignalTarget = exec instanceof AppExecutor || exec instanceof LibExecutor;
|
|
2048
2063
|
const preloadPath = isSignalTarget ? await resolveSignalTestPreloadPath(exec) : null;
|
|
@@ -2062,9 +2077,10 @@ try {
|
|
|
2062
2077
|
async build(app, {
|
|
2063
2078
|
fast = false,
|
|
2064
2079
|
reporter,
|
|
2065
|
-
spinner = false
|
|
2080
|
+
spinner = false,
|
|
2081
|
+
profile
|
|
2066
2082
|
} = {}) {
|
|
2067
|
-
return new (await loadBuildRunner())(app, { fast, reporter }).build({ spinner });
|
|
2083
|
+
return new (await loadBuildRunner())(app, { fast, reporter, profile }).build({ spinner });
|
|
2068
2084
|
}
|
|
2069
2085
|
async start(app, {
|
|
2070
2086
|
open = false,
|
|
@@ -2079,7 +2095,15 @@ try {
|
|
|
2079
2095
|
setTimeout(() => openBrowser(`http://localhost:${env.AKAN_PUBLIC_CLIENT_PORT ?? env.PORT ?? "8282"}`), 3000);
|
|
2080
2096
|
return appHost;
|
|
2081
2097
|
}
|
|
2082
|
-
async buildMobile(app, platform, {
|
|
2098
|
+
async buildMobile(app, platform, {
|
|
2099
|
+
target,
|
|
2100
|
+
env = "debug",
|
|
2101
|
+
profile = "release",
|
|
2102
|
+
installer = false,
|
|
2103
|
+
arch,
|
|
2104
|
+
sign = false,
|
|
2105
|
+
notarize = false
|
|
2106
|
+
} = {}) {
|
|
2083
2107
|
const targets = await resolveMobileTargets(app, target);
|
|
2084
2108
|
NativeApp.assertInstaller(platform, installer);
|
|
2085
2109
|
if (arch && platform !== "macos" && platform !== "windows" && platform !== "linux")
|
|
@@ -2092,7 +2116,9 @@ try {
|
|
|
2092
2116
|
profile,
|
|
2093
2117
|
...carried && ApplicationRunner.carriesServer(mobileTarget, platform) ? { server: carried } : {},
|
|
2094
2118
|
...installer ? { installer } : {},
|
|
2095
|
-
...arch ? { arch } : {}
|
|
2119
|
+
...arch ? { arch } : {},
|
|
2120
|
+
sign,
|
|
2121
|
+
notarize
|
|
2096
2122
|
}));
|
|
2097
2123
|
});
|
|
2098
2124
|
}
|
|
@@ -2182,20 +2208,26 @@ try {
|
|
|
2182
2208
|
if (!mobileTarget || targets.length > 1)
|
|
2183
2209
|
throw new Error("pack-update packs one native target at a time; pass --target <name>.");
|
|
2184
2210
|
await this.#buildMobileCsr(app, env);
|
|
2185
|
-
const
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
const compat = await NativeApp.compareBundles(app.cwdPath, against, bundle);
|
|
2192
|
-
await Bun.write(path5.join(packed.out, "compat.json"), `${JSON.stringify({ against, ...compat }, null, 2)}
|
|
2211
|
+
const { pack } = await new NativeApp(app, mobileTarget, env).packUpdate(platform, { out });
|
|
2212
|
+
app.logger.info(`packed ${mobileTarget.name} ${platform} for channel '${pack.channel}' to ${pack.out}: ${pack.files} files, ${(pack.size / 1024).toFixed(0)} KiB, native API ${pack.nativeApi}`);
|
|
2213
|
+
if (against) {
|
|
2214
|
+
const compat = await NativeApp.compareBundles(app.cwdPath, against, path5.join(pack.out, "bundle.json"));
|
|
2215
|
+
pack.compat = { against, ...compat };
|
|
2216
|
+
await Bun.write(path5.join(pack.out, "compat.json"), `${JSON.stringify(pack.compat, null, 2)}
|
|
2193
2217
|
`);
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2218
|
+
}
|
|
2219
|
+
await NativeApp.writePack(pack);
|
|
2220
|
+
if (!pack.compat)
|
|
2221
|
+
return pack;
|
|
2222
|
+
if (pack.compat.compatible) {
|
|
2223
|
+
app.logger.info(`runs in the store build of ${against}`);
|
|
2224
|
+
return pack;
|
|
2225
|
+
}
|
|
2226
|
+
app.logger.error(`This bundle needs a new store build; it differs from the one ${against} came from:
|
|
2227
|
+
- ${pack.compat.problems.join(`
|
|
2197
2228
|
- `)}`);
|
|
2198
|
-
|
|
2229
|
+
process.exitCode = 2;
|
|
2230
|
+
return pack;
|
|
2199
2231
|
}
|
|
2200
2232
|
async updateKeygen(app, platform, target) {
|
|
2201
2233
|
const nativePlatform = platform === "desktop" ? NativeApp.desktopPlatform() : platform;
|
|
@@ -2207,30 +2239,47 @@ try {
|
|
|
2207
2239
|
seen.add(appId);
|
|
2208
2240
|
const { publicKey, keyPath, created } = await new NativeApp(app, mobileTarget).updateKeygen(nativePlatform);
|
|
2209
2241
|
app.log(`${appId}: ${created ? "made" : "read"} ${keyPath}${created ? " (keep it private and backed up: without it, installed apps take no more updates)" : ""}`);
|
|
2210
|
-
app.log(` native: { updates: { url: "https://\u2026/${app.name}",
|
|
2211
|
-
const
|
|
2212
|
-
|
|
2213
|
-
|
|
2242
|
+
app.log(` native: { updates: { url: "https://\u2026/${app.name}", publicKeys: [${JSON.stringify(publicKey)}] } }`);
|
|
2243
|
+
const { publicKey: one, publicKeys } = mobileTarget.config.updates ?? {};
|
|
2244
|
+
const declared = publicKeys ?? (one ? [one] : null);
|
|
2245
|
+
if (declared && !declared.includes(publicKey))
|
|
2246
|
+
app.logger.warn(`native.targets.${mobileTarget.name}.updates.publicKeys does not hold this key; releases it signs would not verify.`);
|
|
2214
2247
|
}
|
|
2215
2248
|
}
|
|
2216
|
-
async publishUpdate(app, platform, { target, env = "main", channel } = {}) {
|
|
2249
|
+
async publishUpdate(app, platform, { target, env = "main", channel, upload, arch, sign = false, notarize = false } = {}) {
|
|
2250
|
+
if (arch && platform !== "desktop")
|
|
2251
|
+
throw new Error(`--arch picks a desktop release's CPU; ${platform} publishes its web bundle.`);
|
|
2217
2252
|
const targets = await resolveMobileTargets(app, target);
|
|
2253
|
+
if (upload && targets.length > 1)
|
|
2254
|
+
throw new Error(`--upload takes one target's release; name it with --target (${targets.map(({ name }) => name).join(", ")}).`);
|
|
2255
|
+
const uploader = upload ? UpdateUploader.forTarget(upload) : null;
|
|
2218
2256
|
const nativePlatform = platform === "desktop" ? NativeApp.desktopPlatform() : platform;
|
|
2257
|
+
if (arch === "x64" && nativePlatform === "macos")
|
|
2258
|
+
throw new Error("A macOS app is built for Apple silicon (arm64) only.");
|
|
2219
2259
|
for (const mobileTarget of targets)
|
|
2220
2260
|
await new NativeApp(app, mobileTarget, env).assertPublishable(nativePlatform, {
|
|
2221
2261
|
server: ApplicationRunner.carriesServer(mobileTarget, nativePlatform),
|
|
2222
|
-
...channel ? { channel } : {}
|
|
2262
|
+
...channel ? { channel } : {},
|
|
2263
|
+
...arch ? { arch } : {}
|
|
2223
2264
|
});
|
|
2224
|
-
const carried = await this.#stageMobile(app, nativePlatform, targets, env);
|
|
2265
|
+
const carried = await this.#stageMobile(app, nativePlatform, targets, env, arch);
|
|
2225
2266
|
for (const mobileTarget of targets) {
|
|
2226
2267
|
const nativeApp = new NativeApp(app, mobileTarget, env);
|
|
2227
2268
|
const published = await nativeApp.publishUpdate(nativePlatform, {
|
|
2228
2269
|
...channel ? { channel } : {},
|
|
2270
|
+
...arch ? { arch } : {},
|
|
2271
|
+
sign,
|
|
2272
|
+
notarize,
|
|
2229
2273
|
...carried && ApplicationRunner.carriesServer(mobileTarget, nativePlatform) ? { server: carried } : {}
|
|
2230
2274
|
});
|
|
2231
2275
|
this.#reportBuild(app, mobileTarget, published.build);
|
|
2232
2276
|
app.log(`${app.name}/${mobileTarget.name} ${published.bundle}: ${published.dir}/${published.channel}.json, ${published.files} files, ${Math.round(published.size / 1024)} KiB`);
|
|
2233
|
-
|
|
2277
|
+
if (!uploader) {
|
|
2278
|
+
app.log(`Upload ${nativeApp.updatesDir} to ${mobileTarget.config.updates?.url}, the manifests last.`);
|
|
2279
|
+
continue;
|
|
2280
|
+
}
|
|
2281
|
+
const { uploaded, skipped } = await uploader.upload(nativeApp.updatesDir);
|
|
2282
|
+
app.log(`Uploaded ${uploaded} file(s) to ${upload}, the manifests last; ${skipped} the bucket already held. Installed apps read ${mobileTarget.config.updates?.url}.`);
|
|
2234
2283
|
}
|
|
2235
2284
|
}
|
|
2236
2285
|
#reportBuild(app, mobileTarget, { artifacts, warnings, signing }) {
|
|
@@ -2244,24 +2293,45 @@ try {
|
|
|
2244
2293
|
static carriesServer({ config }, platform = NativeApp.desktopPlatform()) {
|
|
2245
2294
|
return platform !== "ios" && platform !== "android" && !!config.desktop?.server;
|
|
2246
2295
|
}
|
|
2247
|
-
static
|
|
2296
|
+
static carriedServer(targets, platform) {
|
|
2248
2297
|
const carrying = targets.filter((target) => ApplicationRunner.carriesServer(target, platform));
|
|
2249
|
-
const
|
|
2298
|
+
const servers = carrying.map(({ config }) => {
|
|
2250
2299
|
const server = config.desktop?.server;
|
|
2251
|
-
|
|
2300
|
+
if (typeof server !== "object")
|
|
2301
|
+
return { omit: [], modules: [] };
|
|
2302
|
+
const { omit = [], modules = [], profile, env, restart, watchdog } = server;
|
|
2303
|
+
return {
|
|
2304
|
+
omit,
|
|
2305
|
+
modules,
|
|
2306
|
+
...profile ? { profile } : {},
|
|
2307
|
+
...env ? { env } : {},
|
|
2308
|
+
...restart !== undefined ? { restart } : {},
|
|
2309
|
+
...typeof watchdog === "object" ? { watchdog } : {}
|
|
2310
|
+
};
|
|
2252
2311
|
});
|
|
2253
|
-
const [first = [], ...rest] =
|
|
2254
|
-
|
|
2255
|
-
|
|
2312
|
+
const [first = { omit: [], modules: [] }, ...rest] = servers;
|
|
2313
|
+
const agree = (what, of) => {
|
|
2314
|
+
if (rest.every((server) => of(server) === of(first)))
|
|
2315
|
+
return;
|
|
2316
|
+
throw new Error(`The targets that carry the server ${what} (${carrying.map(({ name }, idx) => `${name}: ${servers[idx] && of(servers[idx]) || "none"}`).join("; ")}); build them one --target at a time.`);
|
|
2317
|
+
};
|
|
2318
|
+
agree("omit different packages", ({ omit }) => omit.join(", "));
|
|
2319
|
+
agree("name different env profiles", ({ profile }) => profile ?? "");
|
|
2320
|
+
agree("mount different modules", ({ modules }) => modules.join(", "));
|
|
2321
|
+
agree("set a different env", ({ env }) => env ? JSON.stringify(env) : "");
|
|
2322
|
+
agree("restart differently", ({ restart }) => String(restart ?? ""));
|
|
2323
|
+
agree("watch it differently", ({ watchdog }) => watchdog ? JSON.stringify(watchdog) : "");
|
|
2256
2324
|
return first;
|
|
2257
2325
|
}
|
|
2258
2326
|
async#stageMobile(app, platform, targets, env, arch) {
|
|
2259
2327
|
const stage = targets.some((mobileTarget) => ApplicationRunner.carriesServer(mobileTarget, platform)) ? new DesktopServerStage(app) : null;
|
|
2260
|
-
|
|
2261
|
-
await
|
|
2262
|
-
|
|
2328
|
+
const server = ApplicationRunner.carriedServer(targets, platform);
|
|
2329
|
+
await stage?.install(arch, server.omit);
|
|
2330
|
+
await this.#buildMobileCsr(app, env, stage ? server.profile : undefined);
|
|
2331
|
+
const { modules, env: serverEnv, restart, watchdog } = server;
|
|
2332
|
+
return await stage?.prepare(env, { modules, env: serverEnv, restart, watchdog });
|
|
2263
2333
|
}
|
|
2264
|
-
async#buildMobileCsr(app, env) {
|
|
2334
|
+
async#buildMobileCsr(app, env, profile) {
|
|
2265
2335
|
const prevEnv = {
|
|
2266
2336
|
AKAN_PUBLIC_ENV: process.env.AKAN_PUBLIC_ENV,
|
|
2267
2337
|
AKAN_PUBLIC_OPERATION_MODE: process.env.AKAN_PUBLIC_OPERATION_MODE,
|
|
@@ -2273,7 +2343,7 @@ try {
|
|
|
2273
2343
|
APP_OPERATION_MODE: "release"
|
|
2274
2344
|
});
|
|
2275
2345
|
try {
|
|
2276
|
-
await new (await loadBuildRunner())(app, { environment: env }).build({ spinner: true });
|
|
2346
|
+
await new (await loadBuildRunner())(app, { environment: env, profile }).build({ spinner: true });
|
|
2277
2347
|
} finally {
|
|
2278
2348
|
for (const [key, value] of Object.entries(prevEnv)) {
|
|
2279
2349
|
if (value === undefined)
|
|
@@ -3232,12 +3302,17 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3232
3302
|
async logs(app, options) {
|
|
3233
3303
|
await this.applicationRunner.runLogs(app, options);
|
|
3234
3304
|
}
|
|
3235
|
-
async build(app, {
|
|
3305
|
+
async build(app, {
|
|
3306
|
+
write = true,
|
|
3307
|
+
fast = false,
|
|
3308
|
+
quiet = false,
|
|
3309
|
+
profile
|
|
3310
|
+
} = {}) {
|
|
3236
3311
|
await app.scanSync({ write });
|
|
3237
3312
|
if (!quiet)
|
|
3238
3313
|
Logger6.rawLog(`Creating an optimized production build for ${app.name}...`);
|
|
3239
3314
|
try {
|
|
3240
|
-
const result = await this.applicationRunner.build(app, { fast, spinner: !quiet });
|
|
3315
|
+
const result = await this.applicationRunner.build(app, { fast, spinner: !quiet, profile });
|
|
3241
3316
|
Logger6.rawLog(`${app.name} built in dist/apps/${app.name}`);
|
|
3242
3317
|
if (!quiet)
|
|
3243
3318
|
ApplicationBuildReporter.printSummary(result);
|
|
@@ -3247,14 +3322,22 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3247
3322
|
throw error;
|
|
3248
3323
|
}
|
|
3249
3324
|
}
|
|
3250
|
-
async typecheck(
|
|
3251
|
-
|
|
3252
|
-
|
|
3325
|
+
async typecheck(exec, { write = true, clean = false, incremental = true, tests = false } = {}) {
|
|
3326
|
+
if (!(exec instanceof AppExecutor) && !(exec instanceof LibExecutor))
|
|
3327
|
+
throw new Error(`akan typecheck takes an app or a library; ${exec.name} is a package, checked by its own tsconfig.`);
|
|
3328
|
+
if (exec instanceof LibExecutor)
|
|
3329
|
+
await this.libraryScript.syncLibrary(exec);
|
|
3330
|
+
else
|
|
3331
|
+
await exec.scanSync({ write });
|
|
3332
|
+
const spinner = exec.spinning(`Typechecking ${exec.name}${tests ? " with its tests" : ""}...`);
|
|
3253
3333
|
try {
|
|
3254
|
-
|
|
3255
|
-
|
|
3334
|
+
if (exec instanceof LibExecutor)
|
|
3335
|
+
await this.applicationRunner.typecheckLibrary(exec, { clean, incremental, tests });
|
|
3336
|
+
else
|
|
3337
|
+
await this.applicationRunner.typecheck(exec, { clean, incremental, tests });
|
|
3338
|
+
spinner.succeed(`${exec.name} typechecked`);
|
|
3256
3339
|
} catch (error) {
|
|
3257
|
-
spinner.fail(`${
|
|
3340
|
+
spinner.fail(`${exec.name} typecheck failed`);
|
|
3258
3341
|
Logger6.rawLog(ApplicationBuildReporter.formatError(error), undefined, "error");
|
|
3259
3342
|
throw error;
|
|
3260
3343
|
}
|
|
@@ -3456,7 +3539,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3456
3539
|
} = {}) {
|
|
3457
3540
|
await app.scanSync({ write });
|
|
3458
3541
|
ApplicationScript.#assertReleaseEnv("packUpdate", options.env ?? "main", allowLocalRelease);
|
|
3459
|
-
await this.applicationRunner.packUpdate(app, platform, options);
|
|
3542
|
+
return await this.applicationRunner.packUpdate(app, platform, options);
|
|
3460
3543
|
}
|
|
3461
3544
|
async updateKeygen(app, platform, { target } = {}) {
|
|
3462
3545
|
await this.applicationRunner.updateKeygen(app, platform, target);
|
|
@@ -3510,7 +3593,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
|
|
|
3510
3593
|
await Promise.all(shares.map(async (share) => await share.close()));
|
|
3511
3594
|
}, "Abandoning the tunnel release; the shares expire on their own.");
|
|
3512
3595
|
await Promise.all(apps.map(async (app) => {
|
|
3513
|
-
const { TunnelShare } = await import("./TunnelShare-
|
|
3596
|
+
const { TunnelShare } = await import("./TunnelShare-q4jq08qg.js");
|
|
3514
3597
|
const share = await TunnelShare.open(app, { workspace: app.workspace });
|
|
3515
3598
|
shares.push(share);
|
|
3516
3599
|
urls.set(app.name, share.url);
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
akanCodePaths2,
|
|
5
5
|
McpServerConfig,
|
|
6
6
|
McpSignIn
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-rtct7d43.js";
|
|
8
8
|
import {
|
|
9
9
|
stripAnsi
|
|
10
10
|
} from "./index-7md2g9vw.js";
|
|
@@ -511,7 +511,7 @@ class AkanToolPack2 {
|
|
|
511
511
|
return { name: "akan-tools", factory: async (pi) => await this.#register(pi) };
|
|
512
512
|
}
|
|
513
513
|
async names() {
|
|
514
|
-
const { ContextRunner } = await import("./context.runner-
|
|
514
|
+
const { ContextRunner } = await import("./context.runner-atcrzz5b.js");
|
|
515
515
|
return [
|
|
516
516
|
...new ContextRunner().listMcpTools(this.#options.mode).map((tool) => tool.name),
|
|
517
517
|
AkanToolPack2.verifyToolName
|
|
@@ -519,7 +519,7 @@ class AkanToolPack2 {
|
|
|
519
519
|
}
|
|
520
520
|
static verifyToolName = "akan_verify";
|
|
521
521
|
async#register(pi) {
|
|
522
|
-
const { ContextRunner } = await import("./context.runner-
|
|
522
|
+
const { ContextRunner } = await import("./context.runner-atcrzz5b.js");
|
|
523
523
|
const runner = new ContextRunner;
|
|
524
524
|
const guidelineNames = await AkanToolPack2.#guidelineNames();
|
|
525
525
|
for (const tool of runner.listMcpTools(this.#options.mode, { guidelineNames })) {
|
|
@@ -52,6 +52,11 @@ class GlobalConfig {
|
|
|
52
52
|
await GlobalConfig.#setAkanGlobalConfig(mutate(await GlobalConfig.#getAkanGlobalConfig()));
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
|
+
static async hostFor(workspace, host) {
|
|
56
|
+
if (host)
|
|
57
|
+
return host;
|
|
58
|
+
return (await workspace.getConfig()).cloudHost ?? GlobalConfig.akanCloudHost;
|
|
59
|
+
}
|
|
55
60
|
static async getHostConfig(host = GlobalConfig.akanCloudHost) {
|
|
56
61
|
const akanConfig = await GlobalConfig.#getAkanGlobalConfig();
|
|
57
62
|
return GlobalConfig.toHostConfig(akanConfig.cloudHost[host] ?? getDefaultHostConfig(host));
|
|
@@ -197,6 +202,10 @@ class HttpClient {
|
|
|
197
202
|
}
|
|
198
203
|
|
|
199
204
|
class CloudApi {
|
|
205
|
+
static statusOf(error) {
|
|
206
|
+
const status = Number(/(?:^|: )(\d{3}) /.exec(error instanceof Error ? error.message : String(error))?.[1]);
|
|
207
|
+
return Number.isNaN(status) ? null : status;
|
|
208
|
+
}
|
|
200
209
|
#api;
|
|
201
210
|
#accessToken = null;
|
|
202
211
|
#workspace;
|
|
@@ -231,6 +240,36 @@ class CloudApi {
|
|
|
231
240
|
formData.append("file", file);
|
|
232
241
|
return await this.#api.post(`/uploadEnv/${devProjectId}`, formData);
|
|
233
242
|
}
|
|
243
|
+
async uploadSecret(devProjectId, secret) {
|
|
244
|
+
return await this.#api.post(`/uploadSecret/${encodeURIComponent(devProjectId)}`, secret);
|
|
245
|
+
}
|
|
246
|
+
async listSecrets(devProjectId) {
|
|
247
|
+
return await this.#api.get(`/listSecrets/${encodeURIComponent(devProjectId)}`);
|
|
248
|
+
}
|
|
249
|
+
async removeSecret(devProjectId, secret) {
|
|
250
|
+
return await this.#api.post(`/removeSecret/${encodeURIComponent(devProjectId)}`, secret);
|
|
251
|
+
}
|
|
252
|
+
async requestUpdateUpload(devProjectId, upload) {
|
|
253
|
+
return await this.#api.post(`/requestUpdateUpload/${encodeURIComponent(devProjectId)}`, upload);
|
|
254
|
+
}
|
|
255
|
+
async commitUpdateUpload(devProjectId, uploadId) {
|
|
256
|
+
return await this.#api.post(`/commitUpdateUpload/${encodeURIComponent(devProjectId)}`, { uploadId }, { signal: AbortSignal.timeout(11 * 60000) });
|
|
257
|
+
}
|
|
258
|
+
async registerAppBinary(devProjectId, binary) {
|
|
259
|
+
const formData = new FormData;
|
|
260
|
+
for (const key of ["appName", "target", "distribution"])
|
|
261
|
+
formData.append(key, binary[key]);
|
|
262
|
+
if (binary.channel)
|
|
263
|
+
formData.append("channel", binary.channel);
|
|
264
|
+
formData.append("bundle", binary.bundle, "bundle.json");
|
|
265
|
+
if (binary.packUploadId)
|
|
266
|
+
formData.append("packUploadId", binary.packUploadId);
|
|
267
|
+
if (binary.pack)
|
|
268
|
+
formData.append("pack", binary.pack, "pack.tgz");
|
|
269
|
+
return await this.#api.post(`/registerAppBinary/${encodeURIComponent(devProjectId)}`, formData, {
|
|
270
|
+
signal: AbortSignal.timeout(11 * 60000)
|
|
271
|
+
});
|
|
272
|
+
}
|
|
234
273
|
async downloadEnv(devProjectId) {
|
|
235
274
|
const localPath = `${this.#workspace.workspaceRoot}/local/env.tar`;
|
|
236
275
|
await this.#api.getFile(`/downloadEnv/${devProjectId}`, localPath);
|
|
@@ -263,4 +302,103 @@ class CloudApi {
|
|
|
263
302
|
}
|
|
264
303
|
}
|
|
265
304
|
}
|
|
266
|
-
|
|
305
|
+
// pkgs/@akanjs/devkit/cloud/updatePackUpload.ts
|
|
306
|
+
import { Logger, sleep } from "akanjs/common";
|
|
307
|
+
class UpdatePackUpload {
|
|
308
|
+
static maxBytes = 200 * 1024 * 1024;
|
|
309
|
+
static #transientPut = new Set([0, 408, 429, 500, 502, 503, 504]);
|
|
310
|
+
#api;
|
|
311
|
+
#devProjectId;
|
|
312
|
+
#putRetryMs;
|
|
313
|
+
#commitRetryMs;
|
|
314
|
+
#cutOffWindowMs;
|
|
315
|
+
#commitLimitMs;
|
|
316
|
+
constructor(api, devProjectId, {
|
|
317
|
+
putRetryMs = 1000,
|
|
318
|
+
commitRetryMs = 1e4,
|
|
319
|
+
cutOffWindowMs = 15 * 60000,
|
|
320
|
+
commitLimitMs = 60 * 60000
|
|
321
|
+
} = {}) {
|
|
322
|
+
this.#api = api;
|
|
323
|
+
this.#devProjectId = devProjectId;
|
|
324
|
+
this.#putRetryMs = putRetryMs;
|
|
325
|
+
this.#commitRetryMs = commitRetryMs;
|
|
326
|
+
this.#cutOffWindowMs = cutOffWindowMs;
|
|
327
|
+
this.#commitLimitMs = commitLimitMs;
|
|
328
|
+
}
|
|
329
|
+
async send(archive, fields) {
|
|
330
|
+
const uploadId = await this.stage(archive, fields);
|
|
331
|
+
return await this.settle(() => this.#api.commitUpdateUpload(this.#devProjectId, uploadId));
|
|
332
|
+
}
|
|
333
|
+
async stage(archive, fields) {
|
|
334
|
+
const file = Bun.file(archive);
|
|
335
|
+
if (file.size < 1 || file.size > UpdatePackUpload.maxBytes)
|
|
336
|
+
throw new Error(`The pack archive is ${file.size} bytes; a project takes 1 byte to 200 MiB.`);
|
|
337
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
338
|
+
for await (const chunk of file.stream())
|
|
339
|
+
hasher.update(chunk);
|
|
340
|
+
const upload = { ...fields, size: file.size, sha256: hasher.digest("hex") };
|
|
341
|
+
for (let ticket = 1;; ticket++) {
|
|
342
|
+
const { uploadId, uploadUrl, contentType } = await this.#request(upload);
|
|
343
|
+
const status = await this.#put(uploadUrl, contentType, file);
|
|
344
|
+
if (status >= 200 && status < 300)
|
|
345
|
+
return uploadId;
|
|
346
|
+
if (status !== 403 || ticket === 2)
|
|
347
|
+
throw new Error(`The storage refused the pack upload (${status ? `HTTP ${status}` : "no response"}).`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
async#request(upload) {
|
|
351
|
+
return await this.#api.requestUpdateUpload(this.#devProjectId, upload).catch((error) => {
|
|
352
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
353
|
+
if (CloudApi.statusOf(error) === 404 && !/"error"\s*:\s*"[\w$-]+\.error\.[\w$-]+"/.test(message))
|
|
354
|
+
throw new Error("The project's server does not take direct pack uploads yet: update akasys and try again, or upload the pack from the project's release screen.");
|
|
355
|
+
throw error;
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
async#put(url, contentType, file) {
|
|
359
|
+
for (let retry = 0;; retry++) {
|
|
360
|
+
const status = await fetch(url, { method: "PUT", body: file, headers: { "Content-Type": contentType } }).then(async (response) => {
|
|
361
|
+
await response.arrayBuffer().catch(() => {
|
|
362
|
+
return;
|
|
363
|
+
});
|
|
364
|
+
return response.status;
|
|
365
|
+
}).catch(() => 0);
|
|
366
|
+
if (retry === 3 || !UpdatePackUpload.#transientPut.has(status))
|
|
367
|
+
return status;
|
|
368
|
+
await sleep(this.#putRetryMs * (retry + 1));
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
async settle(call) {
|
|
372
|
+
const limit = performance.now() + this.#commitLimitMs;
|
|
373
|
+
let cutOffSince = null;
|
|
374
|
+
for (;; ) {
|
|
375
|
+
try {
|
|
376
|
+
return await call();
|
|
377
|
+
} catch (error) {
|
|
378
|
+
const now = performance.now();
|
|
379
|
+
if (UpdatePackUpload.#inProgress(error))
|
|
380
|
+
cutOffSince = null;
|
|
381
|
+
else if (UpdatePackUpload.#cutOff(error))
|
|
382
|
+
cutOffSince ??= now;
|
|
383
|
+
else
|
|
384
|
+
throw error;
|
|
385
|
+
const deadline = cutOffSince === null ? limit : Math.min(limit, cutOffSince + this.#cutOffWindowMs);
|
|
386
|
+
if (now + this.#commitRetryMs > deadline)
|
|
387
|
+
throw error;
|
|
388
|
+
Logger.rawLog(`The project is still taking the pack; asking again in ${Math.round(this.#commitRetryMs / 1000)}s.`);
|
|
389
|
+
await sleep(this.#commitRetryMs);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
static #inProgress(error) {
|
|
394
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
395
|
+
return CloudApi.statusOf(error) === 409 && message.includes("uploadCommitInProgress");
|
|
396
|
+
}
|
|
397
|
+
static #cutOff(error) {
|
|
398
|
+
const status = CloudApi.statusOf(error);
|
|
399
|
+
if (status === null)
|
|
400
|
+
return !(error instanceof SyntaxError);
|
|
401
|
+
return status === 502 || status === 504 || status >= 520 && status <= 527;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
export { getDefaultHostConfig, GlobalConfig, CloudApi, UpdatePackUpload };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// pkgs/@akanjs/devkit/mobile/mobileTarget.ts
|
|
3
|
+
var trimSlashes = (value) => value.replace(/^\/+|\/+$/g, "");
|
|
4
|
+
var getMobileTargets = async (app) => {
|
|
5
|
+
const config = await app.getConfig();
|
|
6
|
+
return Object.entries(config.native.targets).map(([name, target]) => ({ name, config: target }));
|
|
7
|
+
};
|
|
8
|
+
var isTemplateOnly = ({ basePaths, native }) => basePaths.size > 0 && Object.values(native.targets).every((target) => !target.basePath);
|
|
9
|
+
var getMobileTargetChoices = async (app) => {
|
|
10
|
+
const config = await app.getConfig();
|
|
11
|
+
const targetNames = Object.keys(config.native.targets);
|
|
12
|
+
if (targetNames.length > 0 && !isTemplateOnly(config))
|
|
13
|
+
return targetNames;
|
|
14
|
+
return [...config.basePaths];
|
|
15
|
+
};
|
|
16
|
+
var resolveMobileTargetByBasePath = (targets, basePath) => {
|
|
17
|
+
const normalizedBasePath = trimSlashes(basePath);
|
|
18
|
+
const byBasePath = targets.find(({ config }) => config.basePath !== undefined && trimSlashes(config.basePath) === normalizedBasePath);
|
|
19
|
+
if (byBasePath)
|
|
20
|
+
return byBasePath;
|
|
21
|
+
const [template] = targets;
|
|
22
|
+
if (!template)
|
|
23
|
+
return;
|
|
24
|
+
return {
|
|
25
|
+
name: normalizedBasePath,
|
|
26
|
+
config: { ...template.config, name: normalizedBasePath, basePath: normalizedBasePath }
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
var resolveMobileTargets = async (app, selection) => {
|
|
30
|
+
const config = await app.getConfig();
|
|
31
|
+
const targets = await getMobileTargets(app);
|
|
32
|
+
if (targets.length === 0)
|
|
33
|
+
throw new Error(`No native targets configured for ${app.name}`);
|
|
34
|
+
if (!selection && targets.length === 1 && !isTemplateOnly(config))
|
|
35
|
+
return targets;
|
|
36
|
+
if (!selection) {
|
|
37
|
+
const choices = await getMobileTargetChoices(app);
|
|
38
|
+
if (choices.length === 1)
|
|
39
|
+
return resolveMobileTargets(app, choices[0]);
|
|
40
|
+
throw new Error(`Multiple native targets found for ${app.name}. Pass --target <${choices.join("|")}|all>.`);
|
|
41
|
+
}
|
|
42
|
+
if (selection === "all") {
|
|
43
|
+
if (Object.keys(config.native.targets).length > 1)
|
|
44
|
+
return targets;
|
|
45
|
+
const basePaths = [...config.basePaths];
|
|
46
|
+
if (basePaths.length > 1 || isTemplateOnly(config)) {
|
|
47
|
+
return basePaths.flatMap((basePath) => {
|
|
48
|
+
const resolved = resolveMobileTargetByBasePath(targets, basePath);
|
|
49
|
+
return resolved ? [resolved] : [];
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return targets;
|
|
53
|
+
}
|
|
54
|
+
const target = targets.find((candidate) => candidate.name === selection);
|
|
55
|
+
if (target)
|
|
56
|
+
return [target];
|
|
57
|
+
const basePathTarget = resolveMobileTargetByBasePath(targets, selection);
|
|
58
|
+
if (basePathTarget && config.basePaths.has(trimSlashes(selection)))
|
|
59
|
+
return [basePathTarget];
|
|
60
|
+
const choices = await getMobileTargetChoices(app);
|
|
61
|
+
throw new Error(`Native target '${selection}' was not found. Available: ${choices.join(", ")}`);
|
|
62
|
+
};
|
|
63
|
+
var resolveAppId = (appId, platform) => {
|
|
64
|
+
if (typeof appId === "string")
|
|
65
|
+
return appId;
|
|
66
|
+
const id = appId[platform] ?? appId.default;
|
|
67
|
+
if (!id)
|
|
68
|
+
throw new Error(`native.appId names no id for ${platform}; give it ${platform} or default.`);
|
|
69
|
+
return id;
|
|
70
|
+
};
|
|
71
|
+
var appIdsOf = (appId) => typeof appId === "string" ? [appId] : Object.values(appId).filter((id) => !!id);
|
|
72
|
+
var targetHtmlFilename = (target) => {
|
|
73
|
+
const basePath = trimSlashes(target.basePath ?? "");
|
|
74
|
+
return basePath ? `${basePath}.html` : "index.html";
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export { getMobileTargets, getMobileTargetChoices, resolveMobileTargets, resolveAppId, appIdsOf, targetHtmlFilename };
|