@akanjs/cli 3.1.0-rc.0 → 3.1.0-rc.2
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-q7a4srt6.js → CodeAgent-q50k4s45.js} +2 -2
- package/{CodeTui-ak23dxc9.js → CodeTui-62g35ztk.js} +1 -1
- package/TunnelShare-f1egrktx.js +13 -0
- package/{agent.command-f3gsc1gd.js → agent.command-adfd5299.js} +5 -5
- package/akanCode.js +2 -2
- package/{application.command-3v2d53gd.js → application.command-hj3gv1rx.js} +52 -41
- package/{applicationBuildRunner-1yaqsrdq.js → applicationBuildRunner-by10r9gf.js} +16 -30
- package/buildBatch.proc.js +22 -13
- package/{cloud.command-kk2rwkvw.js → cloud.command-k2fhaape.js} +60 -63
- package/cloud.script-z8p5dz7e.js +23 -0
- package/{code.command-30sca09d.js → code.command-kt5zgcc2.js} +6 -6
- package/{context.command-k7eqacq6.js → context.command-8fgn42jw.js} +16 -13
- package/context.runner-hnh0rg7m.js +24 -0
- package/{guideline.command-dtczrqpf.js → guideline.command-3yxxr2mm.js} +2 -2
- package/guidelines/conventions/conventions.instruction.md +30 -15
- package/guidelines/cssRule/cssRule.instruction.md +12 -6
- package/guidelines/mcpRule/mcpRule.instruction.md +32 -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-kjvrq3nc.js → index-0909wckt.js} +361 -282
- package/{index-p9ystjrp.js → index-20cebtth.js} +92 -52
- package/{index-55mynnqs.js → index-2etqq75t.js} +455 -206
- package/{index-6jjtnhkw.js → index-31ce9vhg.js} +51 -9
- package/{index-y8q31011.js → index-3reaaa1h.js} +42 -153
- package/{index-ww9bhp67.js → index-4pf8g7ff.js} +1 -1
- package/{index-qt22xstj.js → index-58vvz603.js} +5 -3
- package/index-6726qr1m.js +668 -0
- package/index-8935h3n1.js +33 -0
- package/{index-nz15k0b6.js → index-8zdwpxef.js} +1 -1
- package/{index-c2yrsxdh.js → index-azh29dc8.js} +96 -320
- package/{index-c1x0be5j.js → index-bea2gwc6.js} +2 -2
- package/{index-v29746vb.js → index-e9prnmyt.js} +3 -3
- package/{index-tn4rpqp1.js → index-fjsv10hd.js} +73 -49
- package/index-g0vwzy9m.js +241 -0
- package/{index-c76k723e.js → index-h85cxfkg.js} +2 -2
- package/{index-rwq3ekqc.js → index-hnby7p9n.js} +7 -7
- package/{index-2etcv0sc.js → index-jwqtchha.js} +1 -1
- package/index-kc8z134d.js +248 -0
- package/index-nq045px5.js +1124 -0
- package/{index-fm46xrf1.js → index-nq2ja5e0.js} +3 -3
- package/{index-0bm04n5g.js → index-pyxn1b53.js} +10 -8
- package/{index-05g3jayg.js → index-rhbabmja.js} +1 -1
- package/{index-2mx692qq.js → index-rk9sdys3.js} +2 -2
- package/{index-7bymavqk.js → index-sby8fe1p.js} +1 -1
- package/{index-ctanya41.js → index-sqfdmb5b.js} +4 -4
- package/{index-2t4tqd1c.js → index-t7nws9mx.js} +3 -3
- package/{index-jyv387qw.js → index-tv8fjaba.js} +4 -4
- package/{index-gnyf1fqy.js → index-tz5evhdr.js} +2 -2
- package/{index-aprt7pkz.js → index-xpdgxsj5.js} +229 -1327
- package/{index-e0cvze1s.js → index-z507nzhg.js} +4 -4
- package/index.js +22 -22
- package/{library.command-gaga5bmq.js → library.command-8tw59xzj.js} +3 -3
- package/{localRegistry.command-9e84e32q.js → localRegistry.command-tf3dmznd.js} +12 -9
- package/{module.command-7vpf6db4.js → module.command-9vm8hffy.js} +5 -5
- package/{package.command-twmvvf69.js → package.command-erbxe2tz.js} +3 -3
- package/package.json +2 -2
- package/{page.command-5asq7fdf.js → page.command-jpavcj0p.js} +3 -3
- package/{pipeline.command-d0v38572.js → pipeline.command-b8rzvjvv.js} +220 -219
- package/{primitive.command-dyrs2fm8.js → primitive.command-sm32chzk.js} +6 -6
- package/{projectTypecheck-cvtkrzp2.js → projectTypecheck-jamtx95x.js} +1 -1
- package/{quality.command-6emsqpbg.js → quality.command-pkd17n6y.js} +2 -2
- package/{repair.command-8t6aegv5.js → repair.command-8y4mq6hs.js} +5 -5
- package/{scalar.command-bnggy1x7.js → scalar.command-q8khmyx5.js} +4 -4
- package/{subspace.command-f02j5tge.js → subspace.command-51n0ykbx.js} +421 -362
- package/templates/app/env/env.client.type.ts +2 -3
- package/templates/app/page/styles.css.template +8 -0
- package/{tunnel.command-9x8nfn75.js → tunnel.command-7820vtxq.js} +7 -4
- package/{workflow.command-jx0wag5r.js → workflow.command-n5sv4wqz.js} +10 -10
- package/{workspace.command-cmj6mqyk.js → workspace.command-zdy60jh8.js} +33 -30
- package/TunnelShare-21mm6dr5.js +0 -9
- package/cloud.script-r7eyfey4.js +0 -20
- package/context.runner-hqd1ppqe.js +0 -21
- package/index-6w0rbr9d.js +0 -68
- package/index-r2tpeb3n.js +0 -392
|
@@ -257,9 +257,10 @@ const config: AppConfig = {
|
|
|
257
257
|
Intel Macs are not a target, so `--arch x64` on macOS is refused.
|
|
258
258
|
- **A release is signed only with `--sign` and notarized only with `--notarize`** (`build-desktop`,
|
|
259
259
|
`publish-update`); the environment names the identity and never decides to use it, so a shell exporting a Developer
|
|
260
|
-
ID signs and uploads nothing unasked.
|
|
261
|
-
|
|
262
|
-
the
|
|
260
|
+
ID signs and uploads nothing unasked. Every release build and every `publish-update` of a target that carries a
|
|
261
|
+
server, signed or not, first searches that server for every secret value of the workspace's server env files and
|
|
262
|
+
refuses with the paths; an env file it cannot evaluate stops the release too, and a debug build is not searched.
|
|
263
|
+
One line then names the identity and the service the app goes to.
|
|
263
264
|
- **A macOS release for download is signed with a Developer ID and notarized.**
|
|
264
265
|
`AKAN_NATIVE_MACOS_IDENTITY` names a keychain identity, or `AKAN_NATIVE_MACOS_CERTIFICATE` +
|
|
265
266
|
`_CERTIFICATE_PASSWORD` a `.p12` the build imports into a keychain of its own (a CI runner);
|
|
@@ -280,12 +281,15 @@ const config: AppConfig = {
|
|
|
280
281
|
key. List the online signing key first and offline spares after it (up to three): a phone binary trusts all of
|
|
281
282
|
them, and a key may revoke only the keys listed before it, so a leaked key cannot lock out its spares. A desktop
|
|
282
283
|
app trusts the first; `publicKey` is the one-key form. `akan publish-update <app>` builds and signs a release
|
|
283
|
-
into `updates/`: upload that
|
|
284
|
-
(credentials and endpoint from `S3_*` or `AWS_*`; a release file the bucket
|
|
285
|
-
|
|
284
|
+
into `updates/`: upload that release's files to `url` and its manifest last, or let
|
|
285
|
+
`--upload s3://<bucket>/<prefix>` do it (credentials and endpoint from `S3_*` or `AWS_*`; a release file the bucket
|
|
286
|
+
holds is skipped), which sends that release alone, and nothing when it is missing or fails a check. Never upload the
|
|
287
|
+
folder whole: a phone's is also where `pack-update` writes by default.
|
|
288
|
+
A phone reads only `<url>/<platform>/<channel>/<nativeApi>.json`, so each store generation on a channel takes its
|
|
289
|
+
own fixes.
|
|
286
290
|
`akan pack-update` writes an unsigned phone bundle for whoever holds the key to sign and records it in
|
|
287
291
|
`<out>/pack.json`, exiting 2 when `--against` says it needs a new store build; `akan push-update` packs and uploads to
|
|
288
|
-
|
|
292
|
+
the Akan Cloud project that holds the key, and `akan register-binary` registers a store build after `release-*`. A
|
|
289
293
|
release that hangs is rolled back while the app runs, and `report: { url }` has a phone post what became of each
|
|
290
294
|
release (applied, confirmed, rolled back and why) at its next launch, so rollback rates are visible. `devtools: true`
|
|
291
295
|
opens the web inspector of a release build for an internal test target. The channel is the backend env the binary was built for unless `channel` names one;
|
|
@@ -307,10 +311,11 @@ const config: AppConfig = {
|
|
|
307
311
|
their page paints, so a dark board never flashes white, and `desktop.publisher` names who publishes a Windows app in
|
|
308
312
|
Apps & features and its executable's company (the app name when unset, never Bun's own).
|
|
309
313
|
- **A third-party page shown first-party** — a scoreboard, a menu board — is the `external-view` plugin, listed in
|
|
310
|
-
`native.plugins`: a webview over the window with a browser profile of its own, held to the origins it
|
|
311
|
-
for
|
|
312
|
-
|
|
313
|
-
`
|
|
314
|
+
`native.plugins`: a webview over the window with a browser profile of its own, its top level held to the origins it
|
|
315
|
+
was opened for while its frames load web content from anywhere, with an init script that runs in the top document
|
|
316
|
+
only, `evaluate`, a trusted `sendKey`, `capture`, and `loadFailed` / `gone` (it reloads, or is rebuilt, by itself;
|
|
317
|
+
the reason is `terminated` on macOS, and `rebuildFailed` when a rebuild failed and the view is closed, to be opened
|
|
318
|
+
again) / `consoleMessage` events. Every method on Windows; macOS 14+ lacks `sendKey`, `setMuted` and `capture`.
|
|
314
319
|
|
|
315
320
|
## A Desktop App's Server — `bin` And `trustedDependencies`
|
|
316
321
|
|
|
@@ -416,10 +421,14 @@ in those alone, and `modules: ["@edge"]` (or `AKAN_MODULES=@edge`) names every m
|
|
|
416
421
|
inject, cascade to and hold a relation to. `desktop: { server: { profile: "edge", modules: ["@edge"] } }` builds the
|
|
417
422
|
carried server that way: `env/env.server.<env>.edge.ts` is bundled in place of `env/env.server.<env>.ts`, which never
|
|
418
423
|
enters it, and the build evaluates the profile file with no app env and refuses one whose secret-named keys hold a
|
|
419
|
-
value — a `process.env.X ?? "literal"` counts as the literal.
|
|
424
|
+
value — a `process.env.X ?? "literal"` counts as the literal. Signing, encryption, master and session keys, `pwd`, a
|
|
425
|
+
`…dsn` and a connection string are secret-named, and a URL holding a password or a secret-named query parameter is a
|
|
426
|
+
secret under any key. The profile may spread `libEnv`, and the lib defaults it reaches are checked as the bundle
|
|
427
|
+
carries them; a profile that imports the file it replaces is refused. Each lib's env defaults (`env.server.testing.ts`) are
|
|
420
428
|
swapped the same way: for the lib's `env/env.server.testing.edge.ts`, held to the same check, or for the defaults with
|
|
421
|
-
every secret-named value left out, which the build names in a warning
|
|
422
|
-
|
|
429
|
+
every secret-named value left out, which the build names in a warning — and a default a JSON snapshot cannot carry (a
|
|
430
|
+
function, Map, Set, Date, class instance, bigint or non-finite number) is refused unless the lib has its profile file.
|
|
431
|
+
`akan build <app> --profile edge` does the same for an image. A module listing only edge does not mount under `akan start` (local): list `local` too to develop
|
|
423
432
|
it there.
|
|
424
433
|
|
|
425
434
|
**A file the user picks reaches the server as a grant, never as a copy or a path.** With `"file-picker"` in
|
|
@@ -556,7 +565,7 @@ const config: AppConfig = { assets: { pruneFonts: false } }; // emergency valve,
|
|
|
556
565
|
|
|
557
566
|
Akan Cloud builds and deploys each app as `build` → `docker` → `deploy`, and `ota` after them when asked. **An app's own stages go in
|
|
558
567
|
`apps/<app>/akan.config.ts` under `pipeline`; stages around every app go in the workspace root's
|
|
559
|
-
`akan.config.ts`**, typed `WorkspaceConfig` (`before`, `after`, `post`, `env`, `timeout`). Both are `import type`
|
|
568
|
+
`akan.config.ts`**, typed `WorkspaceConfig`, under its own `pipeline` (`before`, `after`, `post`, `env`, `timeout`). Both are `import type`
|
|
560
569
|
objects (or `(ctx) => …`), and `akan pipeline dry-run | validate | plan` turns them into the plan Akan Cloud runs —
|
|
561
570
|
locally, running nothing.
|
|
562
571
|
|
|
@@ -47,14 +47,17 @@ mutation is mounted under. `conventions` carries the invariants — this is the
|
|
|
47
47
|
change revokes it, `disconnect` when the socket closes while still subscribed — so a room already left runs
|
|
48
48
|
neither again, and cleanup that must happen either way registers for both. From a `message` handler it belongs to
|
|
49
49
|
the socket and runs at close. A handler that throws is logged and never blocks the rest of the teardown.
|
|
50
|
+
- **A subscribe the client leaves before it finishes joins nothing.** When an `unsubscribe` for the room, or the
|
|
51
|
+
socket's close, arrives while the subscribe is still running, the subscribe answers `subscribe: false` and runs its
|
|
52
|
+
`unsubscribe` cleanup (and its `disconnect` one when the socket closed) instead of joining the room.
|
|
50
53
|
|
|
51
54
|
## Request Deadlines
|
|
52
55
|
|
|
53
56
|
- **`{ timeout: <ms> }` in an endpoint's signal option is the whole configuration surface**, and it reaches both
|
|
54
57
|
ends of the call. Server side, the `Timeout` middleware races the handler against it and answers
|
|
55
58
|
`base.error.gatewayTimeout` (504) once it is spent. Client side, `FetchSerializer` ships the value on the
|
|
56
|
-
serialized endpoint and `fetch.<endpoint>()` uses it as that
|
|
57
|
-
browser does not abandon a call the server is still allowed to be working on.
|
|
59
|
+
serialized endpoint and `fetch.<endpoint>()` uses it as that call's deadline — every retry of the call and every
|
|
60
|
+
wait between them included — so the browser does not abandon a call the server is still allowed to be working on.
|
|
58
61
|
- **The middleware is registered by default and has no default of its own.** An endpoint that declares no
|
|
59
62
|
`timeout` is passed straight through — a default here would put a deadline on every endpoint in the app that
|
|
60
63
|
nobody asked for, which is why the middleware used to be opt-in and, being opt-in, made the declared value
|
|
@@ -92,6 +95,11 @@ mutation is mounted under. `conventions` carries the invariants — this is the
|
|
|
92
95
|
- **The entry is the handler's result, not the response.** The lookup wraps the handler only, so `resolveReturn`
|
|
93
96
|
still runs per call on the cached value — field masking, `hidden`/`secret` stripping and relation resolution are
|
|
94
97
|
never cached, and a relation still costs its own load. The cache saves the handler, not the serialization.
|
|
98
|
+
- **A hit hands `resolveReturn` an instance of the declared return model**, rebuilt from an entry that keeps its
|
|
99
|
+
`Map`s, bytes and dates, so a `resolveField` reads the same methods and `Dayjs` values on a hit as on a miss. It is
|
|
100
|
+
the declared model, not the service's document: a method only the document has is not there on a hit, and a return
|
|
101
|
+
declared as a `Light` model shows `resolveField` its light fields only. The entry still holds `hidden` and `secret`
|
|
102
|
+
values for its TTL, as the handler returned them.
|
|
95
103
|
- **A cache backend that is down does not take the endpoint down.** A failed read is warned and the call runs
|
|
96
104
|
uncached; a failed write is warned and dropped.
|
|
97
105
|
- The default middleware chain is `Logging → Timeout → <lib middlewares>`, and the call inside it runs an
|
|
@@ -99,6 +107,21 @@ mutation is mounted under. `conventions` carries the invariants — this is the
|
|
|
99
107
|
handler: a hung cache backend is bounded by the same deadline as the handler it stands in for. **`Retry` was removed** — an automatic re-run of an endpoint
|
|
100
108
|
whose failure it cannot classify replays whatever the first attempt already did.
|
|
101
109
|
|
|
110
|
+
## Repeated Mutations
|
|
111
|
+
|
|
112
|
+
- **A mutation sent again under the same `Idempotency-Key` header runs once.** The key is checked after the
|
|
113
|
+
resource guards and the internal arguments, and it is scoped to the endpoint, the caller and a digest of the
|
|
114
|
+
arguments, so one caller's key never hands another caller its answer. A repeat while the first run is still going
|
|
115
|
+
answers 409 `base.error.idempotencyInFlight`.
|
|
116
|
+
- **A repeat answers the first response as it was sent** — resolved, masked and serialized — for 24 hours. What
|
|
117
|
+
is kept is that wire form, never the handler's result, so no `hidden` or `secret` field reaches the cache.
|
|
118
|
+
- A handler that throws frees the key, so a repeat runs it again. A failure after the handler returned is kept and
|
|
119
|
+
replayed instead, for the same 24 hours and a transient one (a relation read during a database blip) included:
|
|
120
|
+
the handler's writes stand, so running it again would repeat them.
|
|
121
|
+
- **Only an HTTP call is deduplicated.** A signed-out call, one whose handler returns a `Response` (whose headers,
|
|
122
|
+
such as a session's `Set-Cookie`, cannot be replayed), a websocket call, and a call through MCP all run every
|
|
123
|
+
time.
|
|
124
|
+
|
|
102
125
|
## Rate Limits
|
|
103
126
|
|
|
104
127
|
- **`{ rateLimit: { calls, windowMs?, by? } }` in an endpoint's signal option** counts calls per caller per window
|
|
@@ -107,9 +130,9 @@ mutation is mounted under. `conventions` carries the invariants — this is the
|
|
|
107
130
|
checked after the middlewares and before the guards, keyed by `accountKey(account)`; a caller it names nothing
|
|
108
131
|
for — an anonymous one — is counted by address. Leaving a pubsub room is never counted.
|
|
109
132
|
- **The answer is 429 `base.error.tooManyRequests` with `data: { seconds }`** and a `Retry-After` header; a WS
|
|
110
|
-
call gets the same payload as its error frame, and the HTTP client restores a proxy's own
|
|
111
|
-
same key (seconds from its `Retry-After`, else 60). The first
|
|
112
|
-
later ones log at `debug`, so a flood does not become a log flood.
|
|
133
|
+
call gets the same payload as its error frame, and the HTTP client restores a proxy's own 429 — a page, or JSON
|
|
134
|
+
naming no error key of ours — under the same key (seconds from its `Retry-After`, `0` included, else 60). The first
|
|
135
|
+
refusal per endpoint per process is warned once; later ones log at `debug`, so a flood does not become a log flood.
|
|
113
136
|
- **Keys and addresses.** The address is `context.getClientIp()` — the trusted-proxy answer, never a raw header
|
|
114
137
|
from an untrusted peer. Callers whose address is unknown share one `unknown` budget (fail closed), and the first
|
|
115
138
|
such call is warned about, since it usually means the proxy in front records no `X-Real-IP`/`X-Forwarded-For`
|
|
@@ -8,19 +8,21 @@ import {
|
|
|
8
8
|
CodegenLock,
|
|
9
9
|
WorkspaceExecutor,
|
|
10
10
|
AppExecutor
|
|
11
|
-
} from "./index-
|
|
11
|
+
} from "./index-2etqq75t.js";
|
|
12
12
|
import"./index-52w0fvh8.js";
|
|
13
13
|
import {
|
|
14
14
|
GraphClientEntryDiscovery,
|
|
15
15
|
RouteClientBuilder,
|
|
16
16
|
AutoImportSync,
|
|
17
|
-
ServerGraphFile,
|
|
18
17
|
CsrDevPatcher,
|
|
19
18
|
CsrDevBundler,
|
|
20
19
|
DevChangePlanner,
|
|
21
20
|
DevGeneratedIndexSync,
|
|
22
21
|
SsrDevBundler
|
|
23
|
-
} from "./index-
|
|
22
|
+
} from "./index-xpdgxsj5.js";
|
|
23
|
+
import {
|
|
24
|
+
ServerGraphFile
|
|
25
|
+
} from "./index-nq045px5.js";
|
|
24
26
|
import {
|
|
25
27
|
prepareDevWatchBatch
|
|
26
28
|
} from "./index-a5vmm6x4.js";
|
|
@@ -235,7 +237,7 @@ class IncrementalBuilder {
|
|
|
235
237
|
#autoImportSync;
|
|
236
238
|
#watcher = null;
|
|
237
239
|
#generation = 0;
|
|
238
|
-
#
|
|
240
|
+
#shellKey = null;
|
|
239
241
|
#discoveredThrough = 0;
|
|
240
242
|
#csrActive = IncrementalBuilder.#csrArmedByEnv();
|
|
241
243
|
#csrBundler;
|
|
@@ -948,13 +950,14 @@ class IncrementalBuilder {
|
|
|
948
950
|
async#buildShell(msg) {
|
|
949
951
|
await this.#workQueue.enqueue("build-shell", async () => {
|
|
950
952
|
const generation = this.#generation;
|
|
953
|
+
const shellKey = `${generation}:${JSON.stringify(this.#artifact.cssAssets)}`;
|
|
951
954
|
let error;
|
|
952
|
-
if (this.#
|
|
955
|
+
if (this.#shellKey !== shellKey)
|
|
953
956
|
try {
|
|
954
957
|
const result = await this.#batchRunner.run(await this.#batchRequest({ generation, needs: ["shell"], changedFiles: [] }));
|
|
955
958
|
error = result.errors.shell;
|
|
956
959
|
if (!error)
|
|
957
|
-
this.#
|
|
960
|
+
this.#shellKey = shellKey;
|
|
958
961
|
} catch (err) {
|
|
959
962
|
error = ApplicationBuildReporter.formatError(err, this.#app.workspace.workspaceRoot);
|
|
960
963
|
}
|