@abide/abide 0.116.4 → 0.117.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/bin/abide.ts +16 -3
- package/docs/REGISTRY.md +19 -19
- package/docs/RULEBOOK.md +24 -1
- package/docs/abide.md +22 -22
- package/package.json +1 -1
- package/src/compiler/TypeSession.ts +7 -2
- package/src/compiler/emitComponent.ts +41 -11
- package/src/compiler/scaffold.ts +5 -3
- package/src/server/deferredBuilds.ts +2 -1
- package/src/server/renderComponent.ts +3 -2
- package/src/server/runtimeRefusal.ts +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @abide/abide
|
|
2
2
|
|
|
3
|
+
## 0.117.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3bb5cc9: `abide dev`, `build`, `start`, `check`, `routes`, `compile`, `bundle`, `openapi`, `mcp` and the shell now refuse to run on a bun outside abide's `engines.bun`, naming the bun running and the range it needs (RULEBOOK 38.123)
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 3bb5cc9: a component whose markup reads a bare `busy()` or `ready()` is now built on the server after the turn, once the siblings after it have started their loads, so it paints the arm the browser chooses at hydration rather than one that is rebuilt (RULEBOOK 41.28, 41.31)
|
|
12
|
+
- 3bb5cc9: the rulebook now states that the effects one turn wakes, a slot's own update among them, run in no guaranteed order (12.15) — a `watch` that post-processes what a sibling `{raw(...)}` slot renders cannot count on the slot having updated first
|
|
13
|
+
- 3bb5cc9: markdown imported `with { type: 'text' }` into an app's `.ts` now checks as a `string` under `abide check`, as it already did in a `.abide` — no more hand-written `declare module '*.md'`
|
|
14
|
+
- 3bb5cc9: the `bunfig.toml` `abide scaffold` writes now sets `[install] peer = false`, so a dependency's peer on `bun` (`bun-plugin-tailwind`'s) cannot install an older bun that shadows the system one inside `bun run` (RULEBOOK 38.122)
|
|
15
|
+
- 3bb5cc9: the rulebook states three things that held but were never written down: a `raw` slot writes its markup unchecked (32.77), a fragment-only step moves `route.url` (30.33), and a `refresh` over `tags` reruns no synchronous derivation that carries none of them (13.20) — and the registry says `route.params` is `Params` outside a page or layout
|
|
16
|
+
|
|
3
17
|
## 0.116.4
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/bin/abide.ts
CHANGED
|
@@ -41,12 +41,17 @@ import { executableName } from '#server/executableName.ts'
|
|
|
41
41
|
import { iconAccent } from '#server/iconAccent.ts'
|
|
42
42
|
import { namesUnder } from '#server/namesUnder.ts'
|
|
43
43
|
import { DEFAULT_DOCUMENT, intoHead } from '#server/render.ts'
|
|
44
|
+
import { runtimeRefusal } from '#server/runtimeRefusal.ts'
|
|
44
45
|
import { pathsUnder, serveBuild } from '#server/serveBuild.ts'
|
|
45
46
|
import { serveDev } from '#server/serveDev.ts'
|
|
46
47
|
import { escapeText } from '#shared/escapeText.ts'
|
|
47
48
|
import { ICON_ADDRESSES, LAUNCHER_PAGE } from '#shared/LAUNCHER_FILES.ts'
|
|
48
49
|
import abidePackage from '../package.json' with { type: 'json' }
|
|
49
50
|
|
|
51
|
+
// 38.123 — the bun this process runs on, held to abide's `engines.bun` before anything is built or
|
|
52
|
+
// booted. A compiled app carries the bun `abide compile` ran on, which this held already.
|
|
53
|
+
const RUNTIME_REFUSAL = runtimeRefusal(Bun.version, abidePackage.engines.bun)
|
|
54
|
+
|
|
50
55
|
/** Where the app a command builds or serves is, and where its build goes — both absolute. */
|
|
51
56
|
type AppDirectories = { root: string; out: string }
|
|
52
57
|
|
|
@@ -59,14 +64,18 @@ const DISK: Host = {
|
|
|
59
64
|
version: abidePackage.version,
|
|
60
65
|
// 38.100 — built in this process rather than a child, where nobody built it, and said on
|
|
61
66
|
// stderr: the command's stdout is its own — `openapi`'s document, `mcp`'s messages.
|
|
62
|
-
app: ({ values }) =>
|
|
63
|
-
appOnDisk(directoriesOf(values), async (root, out) =>
|
|
67
|
+
app: ({ values }) => {
|
|
68
|
+
const handle = appOnDisk(directoriesOf(values), async (root, out) =>
|
|
64
69
|
(await serveBuild(root, out, (root, out) =>
|
|
65
70
|
writeBuild({ root, out }, console.error),
|
|
66
71
|
))
|
|
67
72
|
? out
|
|
68
73
|
: undefined,
|
|
69
|
-
)
|
|
74
|
+
)
|
|
75
|
+
return RUNTIME_REFUSAL === undefined
|
|
76
|
+
? handle
|
|
77
|
+
: { ...handle, boot: async () => RUNTIME_REFUSAL }
|
|
78
|
+
},
|
|
70
79
|
source: {
|
|
71
80
|
scaffold: scaffoldCommand,
|
|
72
81
|
dev: inApp(dev),
|
|
@@ -645,6 +654,10 @@ function inApp<Answer>(
|
|
|
645
654
|
body: (app: AppDirectories, given: Given) => Promise<Answer>,
|
|
646
655
|
): (given: Given) => Promise<Answer | number> {
|
|
647
656
|
return async (given) => {
|
|
657
|
+
if (RUNTIME_REFUSAL !== undefined) {
|
|
658
|
+
console.error(`abide ${given.positionals[0]}: ${RUNTIME_REFUSAL}`)
|
|
659
|
+
return 1
|
|
660
|
+
}
|
|
648
661
|
const app = directoriesOf(given.values)
|
|
649
662
|
if (app === undefined) {
|
|
650
663
|
console.error(
|
package/docs/REGISTRY.md
CHANGED
|
@@ -160,7 +160,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
160
160
|
| --- | --- | --- | --- |
|
|
161
161
|
| `Disposer` | `() => void` | What tears down the previous run. | 12.1 |
|
|
162
162
|
| `Effect` | `() => void \| Disposer` | What runs on change. | 12.2, 12.8, 14.6 |
|
|
163
|
-
| `watch` | `(effect: Effect) => () => void` | Begins a watch over whatever the effect reads. | 12.2, 12.4, 12.5, 12.6, 12.7, 12.10, 12.13 |
|
|
163
|
+
| `watch` | `(effect: Effect) => () => void` | Begins a watch over whatever the effect reads. | 12.2, 12.4, 12.5, 12.6, 12.7, 12.10, 12.13, 12.15 |
|
|
164
164
|
| `watch` | `(sources: Reactive<unknown, never, unknown, unknown> \| Reactive<unknown, never, unknown, unknown>[], effect: Effect) => () => void` | The narrowed form, over named sources. | 12.3 |
|
|
165
165
|
| `flushSync` | `() => void` | Ends the turn: every `Effect` a write woke runs now. | 9.10, 12.11, 12.12 |
|
|
166
166
|
|
|
@@ -169,10 +169,10 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
169
169
|
| Name | Signature | Meaning | Rules |
|
|
170
170
|
| --- | --- | --- | --- |
|
|
171
171
|
| `Selection` | `Reactive<any, any, any, any> \| Keyed<any, any, any, any> \| Rpc<any, any, any, any> \| { tags: string[] }` | What is being asked about. | 13.1, 13.8, 13.9, 13.13, 31.14 |
|
|
172
|
-
| `busy` | `(selection?: Selection, pattern?: Partial<Args>) => boolean` | Whether any entry in the selection has work in flight. | 13.2, 13.3, 13.5, 13.12, 46.11 |
|
|
173
|
-
| `ready` | `(selection?: Selection, pattern?: Partial<Args>) => boolean` | Whether every entry in the selection has a value to serve. | 13.3, 13.5, 13.11, 13.12 |
|
|
172
|
+
| `busy` | `(selection?: Selection, pattern?: Partial<Args>) => boolean` | Whether any entry in the selection has work in flight. | 13.2, 13.3, 13.5, 13.12, 41.28, 41.31, 46.11 |
|
|
173
|
+
| `ready` | `(selection?: Selection, pattern?: Partial<Args>) => boolean` | Whether every entry in the selection has a value to serve. | 13.3, 13.5, 13.11, 13.12, 41.28, 41.31 |
|
|
174
174
|
| `synced` | `(selection?: Selection, pattern?: Partial<Args>) => boolean` | Whether every entry in the selection holds what its producer made. | 13.12, 13.18 |
|
|
175
|
-
| `refresh` | `(selection?: Selection, pattern?: Partial<Args>) => void` | Stale-while-revalidate over the selection. | 13.4, 13.7, 13.10, 13.12, 13.14, 13.15, 13.16, 13.17 |
|
|
175
|
+
| `refresh` | `(selection?: Selection, pattern?: Partial<Args>) => void` | Stale-while-revalidate over the selection. | 13.4, 13.7, 13.10, 13.12, 13.14, 13.15, 13.16, 13.17, 13.20 |
|
|
176
176
|
| `invalidate` | `(selection?: Selection, pattern?: Partial<Args>) => void` | Marks the selection stale. | 13.4, 13.6, 13.10, 13.12, 13.15, 13.17 |
|
|
177
177
|
|
|
178
178
|
|
|
@@ -380,8 +380,8 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
380
380
|
|
|
381
381
|
| Name | Signature | Meaning | Rules |
|
|
382
382
|
| --- | --- | --- | --- |
|
|
383
|
-
| `route.url` | `Reactive<URL>` | Where we are, fragment included. | 23.1, 23.2, 23.3, 23.4, 30.20, 30.21, 30.23, 19.16, 31.16 |
|
|
384
|
-
| `route.params` | `Reactive<Params>` | The matched route's segments. | 23.1, 23.5, 23.9, 30.23, 31.16 |
|
|
383
|
+
| `route.url` | `Reactive<URL>` | Where we are, fragment included. | 23.1, 23.2, 23.3, 23.4, 30.20, 30.21, 30.23, 30.33, 19.16, 31.16 |
|
|
384
|
+
| `route.params` | `Reactive<Params>` | The matched route's segments — typed by its own route in a page or a layout, and `Params` in any other file. | 23.1, 23.5, 23.9, 30.23, 31.16 |
|
|
385
385
|
| `Params` | `Record<string, string \| string[]>` | What a matched route's segments are. | 23.5 |
|
|
386
386
|
| `route.name` | `Reactive<string>` | The resolution path, the same under any mount path. | 23.1, 23.6, 23.14, 31.16 |
|
|
387
387
|
| `route.navigating` | `Reactive<boolean>` | Whether a navigation is in flight. | 23.1, 31.16 |
|
|
@@ -571,7 +571,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
571
571
|
|
|
572
572
|
| Name | Signature | Meaning | Rules |
|
|
573
573
|
| --- | --- | --- | --- |
|
|
574
|
-
| `raw` | `(value: unknown) => Raw` | The branding a value takes to render as markup rather than as text. | 32.2, 32.24, 32.26, 32.30, 32.31, 32.70 |
|
|
574
|
+
| `raw` | `(value: unknown) => Raw` | The branding a value takes to render as markup rather than as text. | 32.2, 32.24, 32.26, 32.30, 32.31, 32.70, 32.77 |
|
|
575
575
|
| `Raw` | `class Raw { html: string }` | What `raw` hands back. | 32.24 |
|
|
576
576
|
|
|
577
577
|
### Control flow
|
|
@@ -629,7 +629,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
629
629
|
| Name | Signature | Meaning | Rules |
|
|
630
630
|
| --- | --- | --- | --- |
|
|
631
631
|
| `Component` | `interface Component {}` | A component bound to its props. | 32.17, 34.16, 35.4 |
|
|
632
|
-
| `render` | `(component: Component) => Promise<Uint8Array>` | What produces a document. | 29.10, 35.4, 35.5, 35.6, 35.15, 35.16, 41.1, 41.2, 41.3, 41.4, 41.9, 41.13, 41.16, 41.17, 41.18, 41.19, 41.20, 41.28, 35.11, 41.29, 41.30 |
|
|
632
|
+
| `render` | `(component: Component) => Promise<Uint8Array>` | What produces a document. | 29.10, 35.4, 35.5, 35.6, 35.15, 35.16, 41.1, 41.2, 41.3, 41.4, 41.9, 41.13, 41.16, 41.17, 41.18, 41.19, 41.20, 41.28, 35.11, 41.29, 41.30, 41.31 |
|
|
633
633
|
|
|
634
634
|
## Sinks
|
|
635
635
|
|
|
@@ -849,20 +849,20 @@ rows a runner prints, and an adapter for an abide app.
|
|
|
849
849
|
|
|
850
850
|
| Command | Meaning | Rules |
|
|
851
851
|
| --- | --- | --- |
|
|
852
|
-
| `abide scaffold <name>` | Writes a starter project. | 38.1, 38.42, 38.103, 38.104, 38.106, 38.112 |
|
|
852
|
+
| `abide scaffold <name>` | Writes a starter project. | 38.1, 38.42, 38.103, 38.104, 38.106, 38.112, 38.122 |
|
|
853
853
|
| `abide run <file> [args…]` | Runs a script under the abide runtime. | 38.2, 38.57 |
|
|
854
|
-
| `abide check [dir…]` | The type-checker over a `.abide` tree. | 38.3, 38.31, 38.32, 38.33, 38.40, 38.105 |
|
|
855
|
-
| `abide routes [--json]` | Every address the app answers, the file answering it, and where each hook is filed. | 38.108 |
|
|
856
|
-
| `abide dev [--port <n>]` | Watches the project and keeps the app up. | 16.23, 16.56, 37.8, 37.9, 38.4, 38.14, 38.15, 38.16, 38.17, 38.19, 38.24, 38.25, 38.26, 38.28, 38.30, 38.35, 38.36, 38.37, 38.38, 38.41, 38.43, 38.58, 38.63, 38.64, 38.65, 38.94, 38.96, 38.97 |
|
|
857
|
-
| `abide build` | Builds the client into content-hashed chunks and a manifest. | 38.43, 38.5, 38.18, 38.25, 38.26, 38.27, 38.30, 38.66, 38.94 |
|
|
858
|
-
| `abide start [--port <n>]` | Boots the built app. | 37.8, 37.10, 37.11, 37.12, 38.6, 38.100, 38.20, 38.21, 38.22, 38.23, 38.25, 38.26, 38.27, 38.28, 38.29, 38.58, 38.67, 38.68, 38.95, 38.97, 38.110 |
|
|
859
|
-
| `abide [--url <origin>] [--port <n>]` | The interactive shell — on the built app it boots, or on the running app `--url` names. | 37.8, 37.10, 37.11, 37.12, 38.6, 38.7, 38.53, 38.54, 38.55, 38.58, 38.59, 38.60, 38.62 |
|
|
854
|
+
| `abide check [dir…]` | The type-checker over a `.abide` tree. | 38.3, 38.31, 38.32, 38.33, 38.40, 38.105, 38.123 |
|
|
855
|
+
| `abide routes [--json]` | Every address the app answers, the file answering it, and where each hook is filed. | 38.108, 38.123 |
|
|
856
|
+
| `abide dev [--port <n>]` | Watches the project and keeps the app up. | 16.23, 16.56, 37.8, 37.9, 38.4, 38.14, 38.15, 38.16, 38.17, 38.19, 38.24, 38.25, 38.26, 38.28, 38.30, 38.35, 38.36, 38.37, 38.38, 38.41, 38.43, 38.58, 38.63, 38.64, 38.65, 38.94, 38.96, 38.97, 38.123 |
|
|
857
|
+
| `abide build` | Builds the client into content-hashed chunks and a manifest. | 38.43, 38.5, 38.18, 38.25, 38.26, 38.27, 38.30, 38.66, 38.94, 38.123 |
|
|
858
|
+
| `abide start [--port <n>]` | Boots the built app. | 37.8, 37.10, 37.11, 37.12, 38.6, 38.100, 38.20, 38.21, 38.22, 38.23, 38.25, 38.26, 38.27, 38.28, 38.29, 38.58, 38.67, 38.68, 38.95, 38.97, 38.110, 38.123 |
|
|
859
|
+
| `abide [--url <origin>] [--port <n>]` | The interactive shell — on the built app it boots, or on the running app `--url` names. | 37.8, 37.10, 37.11, 37.12, 38.6, 38.7, 38.53, 38.54, 38.55, 38.58, 38.59, 38.60, 38.62, 38.123 |
|
|
860
860
|
| `abide call <address> [args]` | One call to one handler. | 38.8, 38.61, 38.110 |
|
|
861
|
-
| `abide openapi [--url <origin>]` | The OpenAPI document printed rather than served. | 38.9, 38.25, 38.110, 38.111 |
|
|
862
|
-
| `abide mcp [--url <origin>]` | The app's MCP server over stdio. | 38.9, 38.13, 38.25, 38.110 |
|
|
861
|
+
| `abide openapi [--url <origin>]` | The OpenAPI document printed rather than served. | 38.9, 38.25, 38.110, 38.111, 38.123 |
|
|
862
|
+
| `abide mcp [--url <origin>]` | The app's MCP server over stdio. | 38.9, 38.13, 38.25, 38.110, 38.123 |
|
|
863
863
|
| `abide watch <address> [args]` | A live subscription to one of the app's followed `GET`s. | 38.69 |
|
|
864
|
-
| `abide compile [--target] [--out] [--platforms]` | One standalone executable. | 37.8, 37.10, 37.11, 37.12, 38.10, 38.25, 38.26, 38.44, 38.45, 38.46, 38.47, 38.48, 38.49, 38.50, 38.51, 38.52, 38.56, 38.93, 38.97 |
|
|
865
|
-
| `abide bundle [--out]` | A desktop app for the host platform, with a window on the app. | 38.10, 38.25, 38.26, 38.70, 38.71, 38.72, 38.73, 38.74, 38.75, 38.76, 38.77, 38.78, 38.79, 38.80, 38.81, 38.82, 38.83, 38.84, 38.85, 38.86, 38.87, 38.88, 38.89, 38.90, 38.91, 38.92, 38.101, 38.102 |
|
|
864
|
+
| `abide compile [--target] [--out] [--platforms]` | One standalone executable. | 37.8, 37.10, 37.11, 37.12, 38.10, 38.25, 38.26, 38.44, 38.45, 38.46, 38.47, 38.48, 38.49, 38.50, 38.51, 38.52, 38.56, 38.93, 38.97, 38.123 |
|
|
865
|
+
| `abide bundle [--out]` | A desktop app for the host platform, with a window on the app. | 38.10, 38.25, 38.26, 38.70, 38.71, 38.72, 38.73, 38.74, 38.75, 38.76, 38.77, 38.78, 38.79, 38.80, 38.81, 38.82, 38.83, 38.84, 38.85, 38.86, 38.87, 38.88, 38.89, 38.90, 38.91, 38.92, 38.101, 38.102, 38.123 |
|
|
866
866
|
| `abide lsp` | The `.abide` language server, over stdio. | 38.11, 38.34, 38.39, 38.98, 38.116, 38.117, 38.118 |
|
|
867
867
|
| `--help` · `-h` · `abide help` | Usage, generated from the command list. | 38.12, 38.113, 38.114 |
|
|
868
868
|
| `--version` · `-v` | The version of abide, or of the app a compiled executable holds. | 38.115 |
|
package/docs/RULEBOOK.md
CHANGED
|
@@ -700,6 +700,9 @@ holding that arm or row is removed.
|
|
|
700
700
|
`watch`, MUST stop reading its sources once that owner stops and nothing else reads it, and MUST
|
|
701
701
|
answer a later read with what its body computes then.
|
|
702
702
|
|
|
703
|
+
12.15 The `Effect` values one turn wakes, a slot's own update among them, MAY run in any order,
|
|
704
|
+
save where a clause orders them.
|
|
705
|
+
|
|
703
706
|
# 13. Selections
|
|
704
707
|
|
|
705
708
|
13.1 A `Selection` MUST be one `Reactive`, one `Keyed`, one `Rpc`, or a set of `tags`.
|
|
@@ -757,6 +760,9 @@ where every value it sweeps is.
|
|
|
757
760
|
current scope MUST answer as over a `Selection` with no entries, and reading `busy`, `ready` or
|
|
758
761
|
`synced` there MUST subscribe the reader to the first call that reaches it in that scope.
|
|
759
762
|
|
|
763
|
+
13.20 `refresh` over a set of `tags` MUST NOT rerun a synchronous derivation that carries none of
|
|
764
|
+
them, which MUST recompute from the load it reads.
|
|
765
|
+
|
|
760
766
|
# 14. Tracking
|
|
761
767
|
|
|
762
768
|
14.1 A `Reactive` MUST be tracked only where something downstream will be rebuilt from it.
|
|
@@ -1819,6 +1825,9 @@ to `middleware`.
|
|
|
1819
1825
|
30.32 A `navigate` that is not a history step, whose request gets no answer while `online` is false,
|
|
1820
1826
|
MUST leave the page and the address where they stand, save where 45.12 holds.
|
|
1821
1827
|
|
|
1828
|
+
30.33 A history step under 30.20, and a `navigate` under 30.21, MUST move `route.url` to the address
|
|
1829
|
+
it steps to.
|
|
1830
|
+
|
|
1822
1831
|
# 31. Reading and writing by name
|
|
1823
1832
|
|
|
1824
1833
|
31.1 Inside a `.abide` file a name bound to a `Reactive` MUST be read wherever 31.3 does not hold it.
|
|
@@ -2099,6 +2108,9 @@ element, written or spread, runs for the same event, wherever the two are writte
|
|
|
2099
2108
|
32.76 A `bind:` whose operand is a path into a value that takes an optional step (`?.`) MUST be a
|
|
2100
2109
|
build error.
|
|
2101
2110
|
|
|
2111
|
+
32.77 A slot holding a value branded by `raw` MUST write its markup as given, with no element or
|
|
2112
|
+
attribute in it removed and no URL in it scheme-checked.
|
|
2113
|
+
|
|
2102
2114
|
# 33. Props
|
|
2103
2115
|
|
|
2104
2116
|
33.1 `props` MUST be callable from a `<script>` block only, and calling it from a `<script module>`
|
|
@@ -2766,6 +2778,12 @@ supplies, and `abide start` MUST NOT supply that secret.
|
|
|
2766
2778
|
38.121 Under `mount`, a call the component's browser module makes to a private handler MUST be
|
|
2767
2779
|
answered in the test's process by the handler the component's server module declares.
|
|
2768
2780
|
|
|
2781
|
+
38.122 The project `abide scaffold` writes MUST NOT install a dependency's peer dependencies.
|
|
2782
|
+
|
|
2783
|
+
38.123 A command `abide` builds, checks or boots the app for MUST be refused where the bun running it
|
|
2784
|
+
is outside the range abide's `engines.bun` names, and the refusal MUST name that bun's version and
|
|
2785
|
+
the range.
|
|
2786
|
+
|
|
2769
2787
|
# 39. Head and view transitions
|
|
2770
2788
|
|
|
2771
2789
|
39.1 A `<head>` element in a `.abide` file MUST contribute its children to the document head.
|
|
@@ -3031,13 +3049,18 @@ has answered or failed.
|
|
|
3031
3049
|
adopts the page, however early its answer arrived.
|
|
3032
3050
|
|
|
3033
3051
|
41.28 A `render` MUST let the turn's queued microtasks run between setting up a `<Name/>` whose setup
|
|
3034
|
-
made an `Rpc` call and building that component's
|
|
3052
|
+
made an `Rpc` call, or whose markup reads a bare `busy` or `ready`, and building that component's
|
|
3053
|
+
markup.
|
|
3035
3054
|
|
|
3036
3055
|
41.29 A `render` answering a request whose `sec-fetch-dest` is `empty` MUST NOT fill the seed buffer,
|
|
3037
3056
|
save one whose `abide-keep` header names `open`.
|
|
3038
3057
|
|
|
3039
3058
|
41.30 A `render` answering a request carrying `abide-keep` MUST write 41.20's script.
|
|
3040
3059
|
|
|
3060
|
+
41.31 On a server, a bare `busy` or `ready` MUST answer over the loads set up before its component's
|
|
3061
|
+
markup is built, and a load a component set up later, one only a pending value places, MAY have it
|
|
3062
|
+
choose another arm at hydration under 41.24.
|
|
3063
|
+
|
|
3041
3064
|
# 42. The app object
|
|
3042
3065
|
|
|
3043
3066
|
42.1 `createApp` MUST build the route table and compose every `Middleware` rung, per 16.14.
|
package/docs/abide.md
CHANGED
|
@@ -773,7 +773,7 @@ A hole is `{}` around an expression, and it updates the one thing it names and n
|
|
|
773
773
|
| You write | Where it lands |
|
|
774
774
|
| --- | --- |
|
|
775
775
|
| `{expr}` | a text node, escaped |
|
|
776
|
-
| `{raw(...)}` | markup, unescaped: `raw` brands a string as a `Raw
|
|
776
|
+
| `{raw(...)}` | markup, unescaped and unchecked (32.77): `raw` brands a string as a `Raw`, so hand it markup you wrote, never a model's reply or a fetched page as it came |
|
|
777
777
|
| `name={expr}` | one attribute, whole |
|
|
778
778
|
| `name="…{expr}…"` | one attribute, interpolated |
|
|
779
779
|
| `class:name={cond}` | one class, there while the condition holds |
|
|
@@ -2996,7 +2996,7 @@ test('one file answers for every company, reading its id', async () => {
|
|
|
2996
2996
|
| --- | --- |
|
|
2997
2997
|
| `route.name` | the pattern that matched, `/companies/[id]` for every company, so a log line keys on the page rather than on each address |
|
|
2998
2998
|
| `Params` | what the segments matched; a query string is never in it |
|
|
2999
|
-
| `RouteParams<P>` | the type `route.params` has in a page filed under `P`, so `id` is text and a key the route lacks is an error |
|
|
2999
|
+
| `RouteParams<P>` | the type `route.params` has in a page or layout filed under `P`, so `id` is text and a key the route lacks is an error. A component under `lib/` has no route of its own and reads the loose `Params`: pass it the value as a prop, or narrow it with `RouteParams<'/…'>` |
|
|
3000
3000
|
|
|
3001
3001
|
## A layout holds what the companies pages share
|
|
3002
3002
|
|
|
@@ -3888,7 +3888,7 @@ test('the server paints the density the cookie holds', async () => {
|
|
|
3888
3888
|
|
|
3889
3889
|
`cookies()` is the request's cookies on the server and the document's in the browser, as a `CookieMap`. Reading a cookie by name follows it, so the list changes on the click. The server render reads the same cookie off the request, so a reload paints compact rather than flashing comfortable first.
|
|
3890
3890
|
|
|
3891
|
-
The principal cookie is `HttpOnly`, so
|
|
3891
|
+
`cookies()` reads and writes any cookie the request carries: a density, a theme, or another system's session cookie your server checks. The principal cookie is `HttpOnly`, so in the browser `cookies()` never sees the seal.
|
|
3892
3892
|
|
|
3893
3893
|
## A handler decides which fields a caller may read
|
|
3894
3894
|
|
|
@@ -7112,7 +7112,7 @@ Arrive here knowing which name you want. Each page is read off the registry: the
|
|
|
7112
7112
|
|
|
7113
7113
|
| Name | Signature | Meaning | Rules |
|
|
7114
7114
|
| --- | --- | --- | --- |
|
|
7115
|
-
| `watch` | `(effect: Effect) => () => void` | Begins a watch over whatever the effect reads. | [12.2](/rulebook#12.2), [12.4](/rulebook#12.4), [12.5](/rulebook#12.5), [12.6](/rulebook#12.6), [12.7](/rulebook#12.7), [12.10](/rulebook#12.10), [12.13](/rulebook#12.13) |
|
|
7115
|
+
| `watch` | `(effect: Effect) => () => void` | Begins a watch over whatever the effect reads. | [12.2](/rulebook#12.2), [12.4](/rulebook#12.4), [12.5](/rulebook#12.5), [12.6](/rulebook#12.6), [12.7](/rulebook#12.7), [12.10](/rulebook#12.10), [12.13](/rulebook#12.13), [12.15](/rulebook#12.15) |
|
|
7116
7116
|
| `watch` | `(sources: Reactive<unknown, never, unknown, unknown> \| Reactive<unknown, never, unknown, unknown>[], effect: Effect) => () => void` | The narrowed form, over named sources. | [12.3](/rulebook#12.3) |
|
|
7117
7117
|
|
|
7118
7118
|
## Taught in
|
|
@@ -7167,7 +7167,7 @@ Arrive here knowing which name you want. Each page is read off the registry: the
|
|
|
7167
7167
|
|
|
7168
7168
|
| Name | Signature | Meaning | Rules |
|
|
7169
7169
|
| --- | --- | --- | --- |
|
|
7170
|
-
| `busy` | `(selection?: Selection, pattern?: Partial<Args>) => boolean` | Whether any entry in the selection has work in flight. | [13.2](/rulebook#13.2), [13.3](/rulebook#13.3), [13.5](/rulebook#13.5), [13.12](/rulebook#13.12), [46.11](/rulebook#46.11) |
|
|
7170
|
+
| `busy` | `(selection?: Selection, pattern?: Partial<Args>) => boolean` | Whether any entry in the selection has work in flight. | [13.2](/rulebook#13.2), [13.3](/rulebook#13.3), [13.5](/rulebook#13.5), [13.12](/rulebook#13.12), [41.28](/rulebook#41.28), [41.31](/rulebook#41.31), [46.11](/rulebook#46.11) |
|
|
7171
7171
|
|
|
7172
7172
|
## Taught in
|
|
7173
7173
|
|
|
@@ -7185,7 +7185,7 @@ Arrive here knowing which name you want. Each page is read off the registry: the
|
|
|
7185
7185
|
|
|
7186
7186
|
| Name | Signature | Meaning | Rules |
|
|
7187
7187
|
| --- | --- | --- | --- |
|
|
7188
|
-
| `ready` | `(selection?: Selection, pattern?: Partial<Args>) => boolean` | Whether every entry in the selection has a value to serve. | [13.3](/rulebook#13.3), [13.5](/rulebook#13.5), [13.11](/rulebook#13.11), [13.12](/rulebook#13.12) |
|
|
7188
|
+
| `ready` | `(selection?: Selection, pattern?: Partial<Args>) => boolean` | Whether every entry in the selection has a value to serve. | [13.3](/rulebook#13.3), [13.5](/rulebook#13.5), [13.11](/rulebook#13.11), [13.12](/rulebook#13.12), [41.28](/rulebook#41.28), [41.31](/rulebook#41.31) |
|
|
7189
7189
|
|
|
7190
7190
|
## Taught in
|
|
7191
7191
|
|
|
@@ -7221,7 +7221,7 @@ Arrive here knowing which name you want. Each page is read off the registry: the
|
|
|
7221
7221
|
|
|
7222
7222
|
| Name | Signature | Meaning | Rules |
|
|
7223
7223
|
| --- | --- | --- | --- |
|
|
7224
|
-
| `refresh` | `(selection?: Selection, pattern?: Partial<Args>) => void` | Stale-while-revalidate over the selection. | [13.4](/rulebook#13.4), [13.7](/rulebook#13.7), [13.10](/rulebook#13.10), [13.12](/rulebook#13.12), [13.14](/rulebook#13.14), [13.15](/rulebook#13.15), [13.16](/rulebook#13.16), [13.17](/rulebook#13.17) |
|
|
7224
|
+
| `refresh` | `(selection?: Selection, pattern?: Partial<Args>) => void` | Stale-while-revalidate over the selection. | [13.4](/rulebook#13.4), [13.7](/rulebook#13.7), [13.10](/rulebook#13.10), [13.12](/rulebook#13.12), [13.14](/rulebook#13.14), [13.15](/rulebook#13.15), [13.16](/rulebook#13.16), [13.17](/rulebook#13.17), [13.20](/rulebook#13.20) |
|
|
7225
7225
|
|
|
7226
7226
|
## Taught in
|
|
7227
7227
|
|
|
@@ -8196,8 +8196,8 @@ Generated surfaces: what is written in place rather than imported.
|
|
|
8196
8196
|
|
|
8197
8197
|
| Name | Signature | Meaning | Rules |
|
|
8198
8198
|
| --- | --- | --- | --- |
|
|
8199
|
-
| `route.url` | `Reactive<URL>` | Where we are, fragment included. | [23.1](/rulebook#23.1), [23.2](/rulebook#23.2), [23.3](/rulebook#23.3), [23.4](/rulebook#23.4), [30.20](/rulebook#30.20), [30.21](/rulebook#30.21), [30.23](/rulebook#30.23), [19.16](/rulebook#19.16), [31.16](/rulebook#31.16) |
|
|
8200
|
-
| `route.params` | `Reactive<Params>` | The matched route's segments. | [23.1](/rulebook#23.1), [23.5](/rulebook#23.5), [23.9](/rulebook#23.9), [30.23](/rulebook#30.23), [31.16](/rulebook#31.16) |
|
|
8199
|
+
| `route.url` | `Reactive<URL>` | Where we are, fragment included. | [23.1](/rulebook#23.1), [23.2](/rulebook#23.2), [23.3](/rulebook#23.3), [23.4](/rulebook#23.4), [30.20](/rulebook#30.20), [30.21](/rulebook#30.21), [30.23](/rulebook#30.23), [30.33](/rulebook#30.33), [19.16](/rulebook#19.16), [31.16](/rulebook#31.16) |
|
|
8200
|
+
| `route.params` | `Reactive<Params>` | The matched route's segments — typed by its own route in a page or a layout, and `Params` in any other file. | [23.1](/rulebook#23.1), [23.5](/rulebook#23.5), [23.9](/rulebook#23.9), [30.23](/rulebook#30.23), [31.16](/rulebook#31.16) |
|
|
8201
8201
|
| `route.name` | `Reactive<string>` | The resolution path, the same under any mount path. | [23.1](/rulebook#23.1), [23.6](/rulebook#23.6), [23.14](/rulebook#23.14), [31.16](/rulebook#31.16) |
|
|
8202
8202
|
| `route.navigating` | `Reactive<boolean>` | Whether a navigation is in flight. | [23.1](/rulebook#23.1), [31.16](/rulebook#31.16) |
|
|
8203
8203
|
|
|
@@ -8961,7 +8961,7 @@ Generated surfaces: what is written in place rather than imported.
|
|
|
8961
8961
|
|
|
8962
8962
|
| Name | Signature | Meaning | Rules |
|
|
8963
8963
|
| --- | --- | --- | --- |
|
|
8964
|
-
| `raw` | `(value: unknown) => Raw` | The branding a value takes to render as markup rather than as text. | [32.2](/rulebook#32.2), [32.24](/rulebook#32.24), [32.26](/rulebook#32.26), [32.30](/rulebook#32.30), [32.31](/rulebook#32.31), [32.70](/rulebook#32.70) |
|
|
8964
|
+
| `raw` | `(value: unknown) => Raw` | The branding a value takes to render as markup rather than as text. | [32.2](/rulebook#32.2), [32.24](/rulebook#32.24), [32.26](/rulebook#32.26), [32.30](/rulebook#32.30), [32.31](/rulebook#32.31), [32.70](/rulebook#32.70), [32.77](/rulebook#32.77) |
|
|
8965
8965
|
|
|
8966
8966
|
## Taught in
|
|
8967
8967
|
|
|
@@ -9084,7 +9084,7 @@ Pages and routing: what is written in place rather than imported.
|
|
|
9084
9084
|
|
|
9085
9085
|
| Name | Signature | Meaning | Rules |
|
|
9086
9086
|
| --- | --- | --- | --- |
|
|
9087
|
-
| `render` | `(component: Component) => Promise<Uint8Array>` | What produces a document. | [29.10](/rulebook#29.10), [35.4](/rulebook#35.4), [35.5](/rulebook#35.5), [35.6](/rulebook#35.6), [35.15](/rulebook#35.15), [35.16](/rulebook#35.16), [41.1](/rulebook#41.1), [41.2](/rulebook#41.2), [41.3](/rulebook#41.3), [41.4](/rulebook#41.4), [41.9](/rulebook#41.9), [41.13](/rulebook#41.13), [41.16](/rulebook#41.16), [41.17](/rulebook#41.17), [41.18](/rulebook#41.18), [41.19](/rulebook#41.19), [41.20](/rulebook#41.20), [41.28](/rulebook#41.28), [35.11](/rulebook#35.11), [41.29](/rulebook#41.29), [41.30](/rulebook#41.30) |
|
|
9087
|
+
| `render` | `(component: Component) => Promise<Uint8Array>` | What produces a document. | [29.10](/rulebook#29.10), [35.4](/rulebook#35.4), [35.5](/rulebook#35.5), [35.6](/rulebook#35.6), [35.15](/rulebook#35.15), [35.16](/rulebook#35.16), [41.1](/rulebook#41.1), [41.2](/rulebook#41.2), [41.3](/rulebook#41.3), [41.4](/rulebook#41.4), [41.9](/rulebook#41.9), [41.13](/rulebook#41.13), [41.16](/rulebook#41.16), [41.17](/rulebook#41.17), [41.18](/rulebook#41.18), [41.19](/rulebook#41.19), [41.20](/rulebook#41.20), [41.28](/rulebook#41.28), [35.11](/rulebook#35.11), [41.29](/rulebook#41.29), [41.30](/rulebook#41.30), [41.31](/rulebook#41.31) |
|
|
9088
9088
|
|
|
9089
9089
|
## Taught in
|
|
9090
9090
|
|
|
@@ -10375,20 +10375,20 @@ CLI: what is written in place rather than imported.
|
|
|
10375
10375
|
|
|
10376
10376
|
| Command | Meaning | Rules |
|
|
10377
10377
|
| --- | --- | --- |
|
|
10378
|
-
| `abide scaffold <name>` | Writes a starter project. | [38.1](/rulebook#38.1), [38.42](/rulebook#38.42), [38.103](/rulebook#38.103), [38.104](/rulebook#38.104), [38.106](/rulebook#38.106), [38.112](/rulebook#38.112) |
|
|
10378
|
+
| `abide scaffold <name>` | Writes a starter project. | [38.1](/rulebook#38.1), [38.42](/rulebook#38.42), [38.103](/rulebook#38.103), [38.104](/rulebook#38.104), [38.106](/rulebook#38.106), [38.112](/rulebook#38.112), [38.122](/rulebook#38.122) |
|
|
10379
10379
|
| `abide run <file> [args…]` | Runs a script under the abide runtime. | [38.2](/rulebook#38.2), [38.57](/rulebook#38.57) |
|
|
10380
|
-
| `abide check [dir…]` | The type-checker over a `.abide` tree. | [38.3](/rulebook#38.3), [38.31](/rulebook#38.31), [38.32](/rulebook#38.32), [38.33](/rulebook#38.33), [38.40](/rulebook#38.40), [38.105](/rulebook#38.105) |
|
|
10381
|
-
| `abide routes [--json]` | Every address the app answers, the file answering it, and where each hook is filed. | [38.108](/rulebook#38.108) |
|
|
10382
|
-
| `abide dev [--port <n>]` | Watches the project and keeps the app up. | [16.23](/rulebook#16.23), [16.56](/rulebook#16.56), [37.8](/rulebook#37.8), [37.9](/rulebook#37.9), [38.4](/rulebook#38.4), [38.14](/rulebook#38.14), [38.15](/rulebook#38.15), [38.16](/rulebook#38.16), [38.17](/rulebook#38.17), [38.19](/rulebook#38.19), [38.24](/rulebook#38.24), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.28](/rulebook#38.28), [38.30](/rulebook#38.30), [38.35](/rulebook#38.35), [38.36](/rulebook#38.36), [38.37](/rulebook#38.37), [38.38](/rulebook#38.38), [38.41](/rulebook#38.41), [38.43](/rulebook#38.43), [38.58](/rulebook#38.58), [38.63](/rulebook#38.63), [38.64](/rulebook#38.64), [38.65](/rulebook#38.65), [38.94](/rulebook#38.94), [38.96](/rulebook#38.96), [38.97](/rulebook#38.97) |
|
|
10383
|
-
| `abide build` | Builds the client into content-hashed chunks and a manifest. | [38.43](/rulebook#38.43), [38.5](/rulebook#38.5), [38.18](/rulebook#38.18), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.27](/rulebook#38.27), [38.30](/rulebook#38.30), [38.66](/rulebook#38.66), [38.94](/rulebook#38.94) |
|
|
10384
|
-
| `abide start [--port <n>]` | Boots the built app. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.6](/rulebook#38.6), [38.100](/rulebook#38.100), [38.20](/rulebook#38.20), [38.21](/rulebook#38.21), [38.22](/rulebook#38.22), [38.23](/rulebook#38.23), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.27](/rulebook#38.27), [38.28](/rulebook#38.28), [38.29](/rulebook#38.29), [38.58](/rulebook#38.58), [38.67](/rulebook#38.67), [38.68](/rulebook#38.68), [38.95](/rulebook#38.95), [38.97](/rulebook#38.97), [38.110](/rulebook#38.110) |
|
|
10385
|
-
| `abide [--url <origin>] [--port <n>]` | The interactive shell — on the built app it boots, or on the running app `--url` names. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.6](/rulebook#38.6), [38.7](/rulebook#38.7), [38.53](/rulebook#38.53), [38.54](/rulebook#38.54), [38.55](/rulebook#38.55), [38.58](/rulebook#38.58), [38.59](/rulebook#38.59), [38.60](/rulebook#38.60), [38.62](/rulebook#38.62) |
|
|
10380
|
+
| `abide check [dir…]` | The type-checker over a `.abide` tree. | [38.3](/rulebook#38.3), [38.31](/rulebook#38.31), [38.32](/rulebook#38.32), [38.33](/rulebook#38.33), [38.40](/rulebook#38.40), [38.105](/rulebook#38.105), [38.123](/rulebook#38.123) |
|
|
10381
|
+
| `abide routes [--json]` | Every address the app answers, the file answering it, and where each hook is filed. | [38.108](/rulebook#38.108), [38.123](/rulebook#38.123) |
|
|
10382
|
+
| `abide dev [--port <n>]` | Watches the project and keeps the app up. | [16.23](/rulebook#16.23), [16.56](/rulebook#16.56), [37.8](/rulebook#37.8), [37.9](/rulebook#37.9), [38.4](/rulebook#38.4), [38.14](/rulebook#38.14), [38.15](/rulebook#38.15), [38.16](/rulebook#38.16), [38.17](/rulebook#38.17), [38.19](/rulebook#38.19), [38.24](/rulebook#38.24), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.28](/rulebook#38.28), [38.30](/rulebook#38.30), [38.35](/rulebook#38.35), [38.36](/rulebook#38.36), [38.37](/rulebook#38.37), [38.38](/rulebook#38.38), [38.41](/rulebook#38.41), [38.43](/rulebook#38.43), [38.58](/rulebook#38.58), [38.63](/rulebook#38.63), [38.64](/rulebook#38.64), [38.65](/rulebook#38.65), [38.94](/rulebook#38.94), [38.96](/rulebook#38.96), [38.97](/rulebook#38.97), [38.123](/rulebook#38.123) |
|
|
10383
|
+
| `abide build` | Builds the client into content-hashed chunks and a manifest. | [38.43](/rulebook#38.43), [38.5](/rulebook#38.5), [38.18](/rulebook#38.18), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.27](/rulebook#38.27), [38.30](/rulebook#38.30), [38.66](/rulebook#38.66), [38.94](/rulebook#38.94), [38.123](/rulebook#38.123) |
|
|
10384
|
+
| `abide start [--port <n>]` | Boots the built app. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.6](/rulebook#38.6), [38.100](/rulebook#38.100), [38.20](/rulebook#38.20), [38.21](/rulebook#38.21), [38.22](/rulebook#38.22), [38.23](/rulebook#38.23), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.27](/rulebook#38.27), [38.28](/rulebook#38.28), [38.29](/rulebook#38.29), [38.58](/rulebook#38.58), [38.67](/rulebook#38.67), [38.68](/rulebook#38.68), [38.95](/rulebook#38.95), [38.97](/rulebook#38.97), [38.110](/rulebook#38.110), [38.123](/rulebook#38.123) |
|
|
10385
|
+
| `abide [--url <origin>] [--port <n>]` | The interactive shell — on the built app it boots, or on the running app `--url` names. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.6](/rulebook#38.6), [38.7](/rulebook#38.7), [38.53](/rulebook#38.53), [38.54](/rulebook#38.54), [38.55](/rulebook#38.55), [38.58](/rulebook#38.58), [38.59](/rulebook#38.59), [38.60](/rulebook#38.60), [38.62](/rulebook#38.62), [38.123](/rulebook#38.123) |
|
|
10386
10386
|
| `abide call <address> [args]` | One call to one handler. | [38.8](/rulebook#38.8), [38.61](/rulebook#38.61), [38.110](/rulebook#38.110) |
|
|
10387
|
-
| `abide openapi [--url <origin>]` | The OpenAPI document printed rather than served. | [38.9](/rulebook#38.9), [38.25](/rulebook#38.25), [38.110](/rulebook#38.110), [38.111](/rulebook#38.111) |
|
|
10388
|
-
| `abide mcp [--url <origin>]` | The app's MCP server over stdio. | [38.9](/rulebook#38.9), [38.13](/rulebook#38.13), [38.25](/rulebook#38.25), [38.110](/rulebook#38.110) |
|
|
10387
|
+
| `abide openapi [--url <origin>]` | The OpenAPI document printed rather than served. | [38.9](/rulebook#38.9), [38.25](/rulebook#38.25), [38.110](/rulebook#38.110), [38.111](/rulebook#38.111), [38.123](/rulebook#38.123) |
|
|
10388
|
+
| `abide mcp [--url <origin>]` | The app's MCP server over stdio. | [38.9](/rulebook#38.9), [38.13](/rulebook#38.13), [38.25](/rulebook#38.25), [38.110](/rulebook#38.110), [38.123](/rulebook#38.123) |
|
|
10389
10389
|
| `abide watch <address> [args]` | A live subscription to one of the app's followed `GET`s. | [38.69](/rulebook#38.69) |
|
|
10390
|
-
| `abide compile [--target] [--out] [--platforms]` | One standalone executable. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.10](/rulebook#38.10), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.44](/rulebook#38.44), [38.45](/rulebook#38.45), [38.46](/rulebook#38.46), [38.47](/rulebook#38.47), [38.48](/rulebook#38.48), [38.49](/rulebook#38.49), [38.50](/rulebook#38.50), [38.51](/rulebook#38.51), [38.52](/rulebook#38.52), [38.56](/rulebook#38.56), [38.93](/rulebook#38.93), [38.97](/rulebook#38.97) |
|
|
10391
|
-
| `abide bundle [--out]` | A desktop app for the host platform, with a window on the app. | [38.10](/rulebook#38.10), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.70](/rulebook#38.70), [38.71](/rulebook#38.71), [38.72](/rulebook#38.72), [38.73](/rulebook#38.73), [38.74](/rulebook#38.74), [38.75](/rulebook#38.75), [38.76](/rulebook#38.76), [38.77](/rulebook#38.77), [38.78](/rulebook#38.78), [38.79](/rulebook#38.79), [38.80](/rulebook#38.80), [38.81](/rulebook#38.81), [38.82](/rulebook#38.82), [38.83](/rulebook#38.83), [38.84](/rulebook#38.84), [38.85](/rulebook#38.85), [38.86](/rulebook#38.86), [38.87](/rulebook#38.87), [38.88](/rulebook#38.88), [38.89](/rulebook#38.89), [38.90](/rulebook#38.90), [38.91](/rulebook#38.91), [38.92](/rulebook#38.92), [38.101](/rulebook#38.101), [38.102](/rulebook#38.102) |
|
|
10390
|
+
| `abide compile [--target] [--out] [--platforms]` | One standalone executable. | [37.8](/rulebook#37.8), [37.10](/rulebook#37.10), [37.11](/rulebook#37.11), [37.12](/rulebook#37.12), [38.10](/rulebook#38.10), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.44](/rulebook#38.44), [38.45](/rulebook#38.45), [38.46](/rulebook#38.46), [38.47](/rulebook#38.47), [38.48](/rulebook#38.48), [38.49](/rulebook#38.49), [38.50](/rulebook#38.50), [38.51](/rulebook#38.51), [38.52](/rulebook#38.52), [38.56](/rulebook#38.56), [38.93](/rulebook#38.93), [38.97](/rulebook#38.97), [38.123](/rulebook#38.123) |
|
|
10391
|
+
| `abide bundle [--out]` | A desktop app for the host platform, with a window on the app. | [38.10](/rulebook#38.10), [38.25](/rulebook#38.25), [38.26](/rulebook#38.26), [38.70](/rulebook#38.70), [38.71](/rulebook#38.71), [38.72](/rulebook#38.72), [38.73](/rulebook#38.73), [38.74](/rulebook#38.74), [38.75](/rulebook#38.75), [38.76](/rulebook#38.76), [38.77](/rulebook#38.77), [38.78](/rulebook#38.78), [38.79](/rulebook#38.79), [38.80](/rulebook#38.80), [38.81](/rulebook#38.81), [38.82](/rulebook#38.82), [38.83](/rulebook#38.83), [38.84](/rulebook#38.84), [38.85](/rulebook#38.85), [38.86](/rulebook#38.86), [38.87](/rulebook#38.87), [38.88](/rulebook#38.88), [38.89](/rulebook#38.89), [38.90](/rulebook#38.90), [38.91](/rulebook#38.91), [38.92](/rulebook#38.92), [38.101](/rulebook#38.101), [38.102](/rulebook#38.102), [38.123](/rulebook#38.123) |
|
|
10392
10392
|
| `abide lsp` | The `.abide` language server, over stdio. | [38.11](/rulebook#38.11), [38.34](/rulebook#38.34), [38.39](/rulebook#38.39), [38.98](/rulebook#38.98), [38.116](/rulebook#38.116), [38.117](/rulebook#38.117), [38.118](/rulebook#38.118) |
|
|
10393
10393
|
| `--help` · `-h` · `abide help` | Usage, generated from the command list. | [38.12](/rulebook#38.12), [38.113](/rulebook#38.113), [38.114](/rulebook#38.114) |
|
|
10394
10394
|
| `--version` · `-v` | The version of abide, or of the app a compiled executable holds. | [38.115](/rulebook#38.115) |
|
package/package.json
CHANGED
|
@@ -915,8 +915,9 @@ export class TypeSession {
|
|
|
915
915
|
checked.push({ source, map, refusals: shadow.refusals })
|
|
916
916
|
}
|
|
917
917
|
// 34.6 — WHAT THE BUNDLER RESOLVES AND THE CHECKER CANNOT: a stylesheet imported for its
|
|
918
|
-
// effect.
|
|
919
|
-
//
|
|
918
|
+
// effect, and (34.21) markdown imported as text into a `.ts`, which bun's own types leave
|
|
919
|
+
// out where they declare `.txt`. Declared in a file of its own at the app's root, which is
|
|
920
|
+
// a script, because a pattern module can only be declared outside a module.
|
|
920
921
|
this.register(
|
|
921
922
|
`${this.canonical(within)}/${AMBIENT}`,
|
|
922
923
|
AMBIENT_DECLARATIONS,
|
|
@@ -1484,6 +1485,10 @@ function routesDeclaration(addresses: readonly string[]): string {
|
|
|
1484
1485
|
return `export {}\ndeclare module ${JSON.stringify(URL_SOURCE)} {\n interface Routes {\n${keys} }\n}\n`
|
|
1485
1486
|
}
|
|
1486
1487
|
const AMBIENT_DECLARATIONS = `declare module '*.css' {}
|
|
1488
|
+
declare module '*.md' {
|
|
1489
|
+
const text: string
|
|
1490
|
+
export default text
|
|
1491
|
+
}
|
|
1487
1492
|
`
|
|
1488
1493
|
|
|
1489
1494
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { JsonValue } from '#shared/JsonValue.ts'
|
|
2
|
-
import { SERVER_SPECIFIER } from '#shared/SPECIFIERS.ts'
|
|
2
|
+
import { SERVER_SPECIFIER, SHARED_SPECIFIER } from '#shared/SPECIFIERS.ts'
|
|
3
3
|
import { type CheckerAnswer, UNCHECKED } from './CheckerAnswer.ts'
|
|
4
4
|
import { Cursor, placeTemplate } from './Cursor.ts'
|
|
5
5
|
import { type LoweredChunk, Lowering, PROPS } from './Lowering.ts'
|
|
6
|
-
import type
|
|
6
|
+
import { type AbideFile, scriptBodies } from './parseAbide.ts'
|
|
7
7
|
import { privateExports } from './projectShadow.ts'
|
|
8
8
|
import {
|
|
9
9
|
concat,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
SERVER_LANE,
|
|
16
16
|
} from './renderMarkup.ts'
|
|
17
17
|
import { insideShare, SETTLED_AT, shareScope } from './shareScope.ts'
|
|
18
|
-
import { splitImports, withoutProps } from './splitImports.ts'
|
|
18
|
+
import { importStatements, splitImports, withoutProps } from './splitImports.ts'
|
|
19
19
|
import type { TemplateNode } from './TemplateNode.ts'
|
|
20
20
|
|
|
21
21
|
// The name the body is bound to while a component's head contributions land (`HEADS`).
|
|
@@ -41,7 +41,8 @@ const CALLS_BEFORE = '__callsBefore'
|
|
|
41
41
|
* `settles` IS A PAGE OR A LAYOUT, which `render` builds a level at a time (41.19): its setup runs
|
|
42
42
|
* at the call and its markup is built on the first read of `head` or `body`, so the calls the
|
|
43
43
|
* setup started are given the turn to answer. Every other component answers the same way only where
|
|
44
|
-
* its setup made a call (41.28), and builds where it is
|
|
44
|
+
* its setup made a call or its markup reads a bare `busy` or `ready` (41.28), and builds where it is
|
|
45
|
+
* called otherwise.
|
|
45
46
|
*/
|
|
46
47
|
export function emitComponent(
|
|
47
48
|
file: AbideFile,
|
|
@@ -144,16 +145,22 @@ ${heldToAnnotations(lowering, derived)}${privateExports(file.servers.join('\n'))
|
|
|
144
145
|
// made a call, and then answers as a page does, for `renderComponent` to build after the turn.
|
|
145
146
|
// THE BUILD IS WRITTEN TWICE rather than always run through `__build`: the closure measured ~4%
|
|
146
147
|
// a row on `bench:component`'s card under JSC, the second copy nothing but server module bytes.
|
|
147
|
-
// One with no setup cannot call, and is written once.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
// One with no setup cannot call, and is written once. One whose markup reads a bare `busy` or
|
|
149
|
+
// `ready` answers as a page does always: built where it is called, it would answer before the
|
|
150
|
+
// siblings after it had started a load, where the browser's answers once every setup has run.
|
|
151
|
+
const probes =
|
|
152
|
+
!settles &&
|
|
153
|
+
readsBareProbe(file, `${head}\n${declared}\n${body.join('\n')}`)
|
|
154
|
+
const waits = !settles && !probes && componentBody.trim() !== ''
|
|
155
|
+
const level =
|
|
156
|
+
settles || probes
|
|
157
|
+
? deferred()
|
|
158
|
+
: waits
|
|
159
|
+
? ` if (${lowering.use('callsInRender')}() !== ${CALLS_BEFORE}) {
|
|
153
160
|
${deferred()}
|
|
154
161
|
}
|
|
155
162
|
${build}`
|
|
156
|
-
|
|
163
|
+
: build
|
|
157
164
|
return `${moduleImports(lowering, () => SERVER_SPECIFIER, [moduleSetup, serverSetup, setup])}
|
|
158
165
|
${moduleSetup.body === '' ? '' : `${moduleSetup.body}\n`}${serverBody}export default function Component(${lowering.takesProps() ? `${PROPS} = {}` : ''}) {
|
|
159
166
|
${waits ? ` const ${CALLS_BEFORE} = ${lowering.use('callsInRender')}()\n` : ''}${opened}${componentBody}
|
|
@@ -162,6 +169,29 @@ ${level}${closed}
|
|
|
162
169
|
`
|
|
163
170
|
}
|
|
164
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Whether `markup`, a component's emitted head and body, calls `busy` or `ready` with no argument,
|
|
174
|
+
* under any name the file's scripts import either by from `@abide/abide`. A member's (`s.busy()`)
|
|
175
|
+
* is not bare.
|
|
176
|
+
*/
|
|
177
|
+
function readsBareProbe(file: AbideFile, markup: string): boolean {
|
|
178
|
+
let names = ''
|
|
179
|
+
for (const script of scriptBodies(file))
|
|
180
|
+
for (const statement of importStatements(script))
|
|
181
|
+
if (statement.specifier === SHARED_SPECIFIER && !statement.typeOnly)
|
|
182
|
+
for (const binding of statement.bindings)
|
|
183
|
+
if (
|
|
184
|
+
!binding.typeOnly &&
|
|
185
|
+
(binding.imported === 'busy' ||
|
|
186
|
+
binding.imported === 'ready')
|
|
187
|
+
)
|
|
188
|
+
names += `${names === '' ? '' : '|'}${binding.local}`
|
|
189
|
+
return (
|
|
190
|
+
names !== '' &&
|
|
191
|
+
new RegExp(`(?<![\\w$.])(?:${names})\\(\\s*\\)`).test(markup)
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
165
195
|
/**
|
|
166
196
|
* 15.8, 19.9 — each private handler held to the schema its annotation derives, once its server block
|
|
167
197
|
* has built it: the module is what the server mounts and what a component under `mount` calls
|
package/src/compiler/scaffold.ts
CHANGED
|
@@ -35,15 +35,17 @@ const SOURCE_ALIAS = { '#src/*': ['./src/*', './src/*.ts'] }
|
|
|
35
35
|
* 38.109, 38.119 — the starter's `bunfig.toml`: the harness's abide preload, which is a DOM a test
|
|
36
36
|
* can mount into and measure, then abide's own — the app's `.abide` files imported as modules, with
|
|
37
37
|
* nothing booted first. Its test root is `src`, so a browser test under `e2e` is playwright's alone.
|
|
38
|
+
* 38.122 — and no peer installed: `bun-plugin-tailwind` names `bun` as one, and an installed copy
|
|
39
|
+
* lands first on the PATH inside `bun run`, shadowing the bun that runs everything else.
|
|
38
40
|
*/
|
|
39
|
-
export const
|
|
40
|
-
'# 38.109, 38.119 — a DOM to mount into and measure, then the app\'s `.abide` files as modules.\n[test]\nroot = "src"\npreload = ["@abide/harness/abide/preload"]\n'
|
|
41
|
+
export const BUNFIG =
|
|
42
|
+
'# 38.122 — a peer is not installed: an installed `bun` would shadow this one inside `bun run`.\n[install]\npeer = false\n\n# 38.109, 38.119 — a DOM to mount into and measure, then the app\'s `.abide` files as modules.\n[test]\nroot = "src"\npreload = ["@abide/harness/abide/preload"]\n'
|
|
41
43
|
|
|
42
44
|
// WRITTEN, NOT COPIED, beside the manifests: a packer drops a `bunfig.toml` or a `.gitignore` from
|
|
43
45
|
// the tarball (`bun pm pack` both, `npm pack` the second), so neither survives as a starter file.
|
|
44
46
|
function filesFor(name: string): Record<string, string> {
|
|
45
47
|
return {
|
|
46
|
-
'bunfig.toml':
|
|
48
|
+
'bunfig.toml': BUNFIG,
|
|
47
49
|
'.gitignore': 'node_modules\n.abide\n',
|
|
48
50
|
'package.json': `${JSON.stringify(
|
|
49
51
|
{
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// 41.28 — A CHILD WHOSE SETUP MADE A CALL IS BUILT AS A PAGE IS: after the turn
|
|
1
|
+
// 41.28 — A CHILD WHOSE SETUP MADE A CALL IS BUILT AS A PAGE IS: after the turn — and so is one whose
|
|
2
|
+
// markup reads a bare `busy` or `ready`, which the compiler writes to answer as a page does always.
|
|
2
3
|
// A component is set up where its parent's markup invokes it, so its build cannot wait inline; it is
|
|
3
4
|
// left as a marker in the parent's head and body, built once the turn has run, and written in where
|
|
4
5
|
// its marker stands. A child whose setup made no call builds where it stands, as before, and pays a
|
|
@@ -30,8 +30,9 @@ export function renderComponent(
|
|
|
30
30
|
const rendered = (
|
|
31
31
|
component as (props: Record<string, () => unknown>) => Rendered
|
|
32
32
|
)(props)
|
|
33
|
-
// 41.28 — A CHILD WHOSE SETUP MADE A CALL
|
|
34
|
-
// left for the first read, and is built after the turn where a
|
|
33
|
+
// 41.28 — A CHILD WHOSE SETUP MADE A CALL, OR WHOSE MARKUP READS A BARE PROBE, ANSWERS AS A PAGE
|
|
34
|
+
// DOES, with a `scope` and its build left for the first read, and is built after the turn where a
|
|
35
|
+
// page is being built.
|
|
35
36
|
if ('scope' in rendered) {
|
|
36
37
|
const marker = deferBuild(rendered, heads, callsFrom)
|
|
37
38
|
if (marker !== undefined) return marker
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Why the bun at `version` cannot run abide, which asks for `range` — or `undefined` where it can.
|
|
3
|
+
*
|
|
4
|
+
* 38.123 — named in full, both versions and the way out, since an older bun fails later and
|
|
5
|
+
* somewhere unrelated, if at all.
|
|
6
|
+
*/
|
|
7
|
+
export function runtimeRefusal(
|
|
8
|
+
version: string,
|
|
9
|
+
range: string,
|
|
10
|
+
): string | undefined {
|
|
11
|
+
if (Bun.semver.satisfies(version, range)) return undefined
|
|
12
|
+
return `this is bun ${version}, and abide needs bun ${range}. Run \`bun upgrade\`, or install a bun in that range. RULEBOOK 38.123.`
|
|
13
|
+
}
|