@abide/abide 0.121.1 → 0.123.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/ABIDE.md +4 -0
- package/CHANGELOG.md +17 -0
- package/docs/REGISTRY.md +15 -15
- package/docs/RULEBOOK.md +36 -14
- package/docs/abide.md +33 -33
- package/package.json +1 -1
- package/src/compiler/Lowering.ts +4 -2
- package/src/compiler/REACTIVE_MEMBERS.ts +2 -3
- package/src/compiler/SHARED_NAMES.ts +2 -0
- package/src/compiler/TypeSession.ts +1 -1
- package/src/compiler/classifyRead.ts +18 -4
- package/src/compiler/projectShadow.ts +1 -0
- package/src/compiler/reactiveTypes.ts +2 -2
- package/src/compiler/readsIn.ts +144 -49
- package/src/server/BRIDGE_VERSION.ts +1 -1
- package/src/server/answerFailure.ts +16 -0
- package/src/server/answerRequest.ts +16 -21
- package/src/server/answerRpc.ts +4 -3
- package/src/server/assistant.ts +25 -4
- package/src/server/createApp.ts +5 -1
- package/src/server/csp.ts +2 -2
- package/src/server/hooks.ts +39 -8
- package/src/shared/Middleware.ts +24 -4
- package/src/shared/csp.ts +2 -2
- package/src/shared/index.ts +2 -1
- package/src/shared/propCell.ts +18 -0
- package/src/shared/rpc.ts +2 -2
- package/src/shared/writePath.ts +1 -1
package/ABIDE.md
CHANGED
|
@@ -57,6 +57,10 @@ affected code saying what it did, and tell the user.
|
|
|
57
57
|
scripts, the CLI and MCP alike.
|
|
58
58
|
- A `.abide` cannot export. A `<script server>` in one holds that file's private handlers
|
|
59
59
|
(`const save = POST(…)`), callable by that file alone, and its hooks (`onStart`, `middleware`, …).
|
|
60
|
+
- A rung shared between handlers or layouts is typed `Middleware` and nothing else:
|
|
61
|
+
`export const signedIn: Middleware = async (next) => (await principal.authenticated) ? next() : refuse(401)`
|
|
62
|
+
fits a handler's `middleware: […]` and a layout's `middleware(…)` alike (RULEBOOK 37.14). No
|
|
63
|
+
`<Ctx, Result>` of its own, and no `as` on a `refuse`.
|
|
60
64
|
- A directory holds addresses, tests, benches, `.d.ts` declarations and two fenced directories
|
|
61
65
|
alone: `lib/` for components and modules, and `public/` for files served as they are. Anything
|
|
62
66
|
else beside the pages is a build error.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @abide/abide
|
|
2
2
|
|
|
3
|
+
## 0.123.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 0e5f83e: an unfinished conversation's log line says why — aborted, failed with the throw, or stopped (RULEBOOK 44.31) ([`042aea3`](https://github.com/briancray/abide/commit/042aea3150ae0fd29959bbe1346d1595b86617bc))
|
|
8
|
+
- 0e5f83e: Breaking: a member the value's type declares is the value's, and a read prop holds a Reactive where one is due (RULEBOOK 31.5, 31.6, 33.27) ([`50b1151`](https://github.com/briancray/abide/commit/50b1151d46389185df0b61d0dd82241566446275))
|
|
9
|
+
|
|
10
|
+
## 0.122.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- a2144de: `Middleware` is one type for a rung shared between handlers and layouts: `const signedIn: Middleware = async (next) => …` fits a handler's `middleware: […]` and a layout's `middleware(…)` alike, with no `<Ctx, Result>` of its own. `Middleware<Response>` is a rung that answers with a `Response` of its own, and `Middleware<never, { args: () => unknown }>` one that reads a handler's args. A `refuse(…)` a layout's rung returns is now answered in its lane — the nearest error page over a page, Problem Details over a handler, and by what the request accepts before routing — and the rung outside it is handed that `Response` (RULEBOOK 37.14, 37.15). BREAKING: `Middleware<Ctx, Result>` written with a context type first no longer reads that way; annotate `next` instead, or use the forms above.
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- 44e9f1d: ABIDE.md names the one-word Middleware form for a shared rung (RULEBOOK 37.14) ([`0699004`](https://github.com/briancray/abide/commit/0699004266bf8174263d1820cee2e9946eeee8a3))
|
|
19
|
+
|
|
3
20
|
## 0.121.1
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/docs/REGISTRY.md
CHANGED
|
@@ -168,7 +168,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
168
168
|
|
|
169
169
|
| Name | Signature | Meaning | Rules |
|
|
170
170
|
| --- | --- | --- | --- |
|
|
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.
|
|
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.13 |
|
|
172
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
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 |
|
|
@@ -218,7 +218,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
218
218
|
| `Value` | `unknown` | What the addressed `Reactive` holds. | 16.3, 16.30 |
|
|
219
219
|
| `Produced` | `unknown` | What it yields, per the unit rule. | 1.2, 16.3 |
|
|
220
220
|
| `Args` | `Record<string, JsonValue> \| undefined` | The arguments, in the body on a mutation and in the URL on a `GET` or `DELETE`. | 11.24, 16.18, 19.15 |
|
|
221
|
-
| `Middleware` |
|
|
221
|
+
| `Middleware` | `Middleware<Answer = never, Extra extends object = object> = <Given extends { request: Request } & Extra, Result>(next: (ctx?: Given) => Promise<Result>, ctx: Given) => Result \| Answer \| Failed<string, unknown> \| Promise<Result \| Answer \| Failed<string, unknown>>` | One rung, written once for every lane whose context carries `Extra`. | 16.14, 16.15, 16.16, 16.21, 37.14, 37.15 |
|
|
222
222
|
| `GET` | `<Value, Args, Failures, RungFailures, Produced = Value>(handler: Reactive<Value, Value, Failures, Produced> \| Keyed<Value, Args, Value, Failures, Produced>, options?: RpcOptions<Args, RungFailures>) => Rpc<Value, Args, Failures \| RungFailures, Produced>` | Declares a read any surface may call. | 16.1, 16.2, 16.5, 16.6, 16.30, 16.31, 16.32, 16.68, 16.76, 16.34, 16.35, 16.36, 16.37, 16.39, 16.44, 16.45, 16.46, 16.47, 16.75, 16.50, 16.51, 16.52, 16.64, 18.1, 18.3, 18.6, 18.8, 18.10, 18.12, 18.21, 18.24, 18.27 |
|
|
223
223
|
| `GET` | `<Value, Args, Failures, RungFailures, Produced = Value>(handler: (args?: Args) => Value, options?: RpcOptions<Args, RungFailures> & ReactiveOptions<Value, Value, Failures, Args>) => Rpc<Value, Args, Failures \| RungFailures, Produced>` | The plain-function overload, whose `ReactiveOptions` (`ttl`, `global`, `debounce` and the rest) build the value it becomes beside its address. | 16.1, 16.6, 16.7 |
|
|
224
224
|
| `GET` | `<Value, Failures, RungFailures>(handler: Value \| PromiseLike<Value>, options?: RpcOptions<undefined, RungFailures> & ReactiveOptions<Value, Value, Failures>) => Rpc<Value, undefined, Failures \| RungFailures>` | The value overload, for what the handler owns outright, whose `ReactiveOptions` build the value it becomes. | 16.1, 16.6, 16.7 |
|
|
@@ -240,7 +240,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
240
240
|
| Name | Signature | Meaning | Rules |
|
|
241
241
|
| --- | --- | --- | --- |
|
|
242
242
|
| `description` | `string` | The human description carried onto every generated surface. | 16.28 |
|
|
243
|
-
| `middleware` | `
|
|
243
|
+
| `middleware` | `((next: (ctx?: { request: Request; args: () => Args }) => Promise<unknown>, ctx: { request: Request; args: () => Args }) => unknown)[]` | The rungs run per call. | 16.11, 16.12, 16.16, 16.17, 16.18, 16.19, 16.20 |
|
|
244
244
|
| `timeout` | `number` | How long the call may go without progress. | 16.22, 16.58, 16.59, 16.60, 16.61, 16.77 |
|
|
245
245
|
| `clients` | `Clients` | Which surfaces carry this handler. | 16.37, 20.3 |
|
|
246
246
|
| `crossOrigin` | `boolean \| string[]` | Whether other origins may call it, or follow it over the mux. | 16.24, 18.2, 21.19 |
|
|
@@ -349,9 +349,9 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
349
349
|
|
|
350
350
|
| Name | Signature | Meaning | Rules |
|
|
351
351
|
| --- | --- | --- | --- |
|
|
352
|
-
| `claudeCode` | `(config?: ClaudeCodeConfig) => Provider` | The visitor's own Claude Code, reached through the bridge paired with their browser, as a provider. | 44.5, 44.13, 44.17, 44.18, 44.19, 44.24, 44.25, 44.27, 44.30, 44.33 |
|
|
352
|
+
| `claudeCode` | `(config?: ClaudeCodeConfig) => Provider` | The visitor's own Claude Code, reached through the bridge paired with their browser, as a provider. | 44.5, 44.13, 44.17, 44.18, 44.19, 44.24, 44.25, 44.27, 44.30, 44.33, 44.45, 44.46 |
|
|
353
353
|
| `ClaudeCodeConfig` | `{ model?: string; fallbackModel?: string; systemPrompt?: string; appendSystemPrompt?: string; effort?: 'low' \| 'medium' \| 'high' \| 'xhigh' \| 'max'; maxBudgetUsd?: number; betas?: string[]; disallowedTools?: string[]; tools?: string[] }` | The Claude Code options a site may set for a turn, and the built-in tools it asks the visitor for. | 44.16, 44.29 |
|
|
354
|
-
| `claudeCode.bridgeCommand` | `(options?: { tools?: string[] }) => { command: string; link: string; expires: number }` | The command and the link that pair a bridge with this browser, granting the built-in tools it is given. | 44.14, 44.32, 44.33, 44.40, 44.41, 44.42, 44.43 |
|
|
354
|
+
| `claudeCode.bridgeCommand` | `(options?: { tools?: string[] }) => { command: string; link: string; expires: number }` | The command and the link that pair a bridge with this browser, granting the built-in tools it is given. | 44.14, 44.32, 44.33, 44.40, 44.41, 44.42, 44.43, 44.44 |
|
|
355
355
|
| `claudeCode.bridge` | `(options?: { tools?: string[] }) => AsyncGenerator<BridgeStatus>` | This browser's pairing, as it changes. | 44.20, 44.22, 44.32, 44.33, 44.34, 44.40 |
|
|
356
356
|
| `BridgeStatus` | `{ paired: boolean; command: string \| undefined; link: string \| undefined }` | Whether a bridge is paired, and the command and the link that pair one where none is. | 44.20, 44.40 |
|
|
357
357
|
| `/__abide/bridge` | `GET`, `POST` | Where a bridge pairs, and is relayed its turns. | 36.7, 44.14, 44.15, 44.19, 44.23, 44.26, 16.57, 16.78 |
|
|
@@ -380,11 +380,11 @@ 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, 30.33, 19.16, 31.
|
|
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.
|
|
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.15 |
|
|
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.15 |
|
|
385
385
|
| `Params` | `Record<string, string \| string[]>` | What a matched route's segments are. | 23.5 |
|
|
386
|
-
| `route.name` | `Reactive<string>` | The resolution path, the same under any mount path. | 23.1, 23.6, 23.14, 31.
|
|
387
|
-
| `route.navigating` | `Reactive<boolean>` | Whether a navigation is in flight. | 23.1, 31.
|
|
386
|
+
| `route.name` | `Reactive<string>` | The resolution path, the same under any mount path. | 23.1, 23.6, 23.14, 31.15 |
|
|
387
|
+
| `route.navigating` | `Reactive<boolean>` | Whether a navigation is in flight. | 23.1, 31.15 |
|
|
388
388
|
|
|
389
389
|
## `online`
|
|
390
390
|
|
|
@@ -499,7 +499,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
499
499
|
|
|
500
500
|
| Name | Signature | Meaning | Rules |
|
|
501
501
|
| --- | --- | --- | --- |
|
|
502
|
-
| `csp` | `(sources?: Record<string, string[]>) =>
|
|
502
|
+
| `csp` | `(sources?: Record<string, string[]>) => (next: (ctx?: { request: Request }) => Promise<Response>, ctx: { request: Request }) => Promise<Response>` | The rung that sets `content-security-policy`. | 29.1, 29.2, 29.5, 29.6, 29.7, 29.8 |
|
|
503
503
|
| `csp.nonce` | `() => string` | This response's nonce, for the app's own inline script. | 29.3, 29.4, 29.9, 29.11 |
|
|
504
504
|
|
|
505
505
|
## `url`
|
|
@@ -533,12 +533,12 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
533
533
|
| `foo` wherever the declared type of its position is not a `Reactive` | a live read | 31.1, 31.2, 31.10 |
|
|
534
534
|
| `const x: Reactive<…> = foo` / a `Reactive<…>`-typed parameter, return or `bind:` operand | the `Reactive` | 31.3 |
|
|
535
535
|
| `await foo` | the settling of the `Reactive`, which is its value | 1.4, 2.7, 31.3 |
|
|
536
|
-
| `refresh(foo)` / a `Selection`-typed parameter | the `Reactive` | 31.
|
|
536
|
+
| `refresh(foo)` / a `Selection`-typed parameter | the `Reactive` | 31.13 |
|
|
537
537
|
| `foo = bar` | a write | 31.4, 11.61 |
|
|
538
|
-
| `foo.bar = v` | a write through a path | 31.8, 31.
|
|
538
|
+
| `foo.bar = v` | a write through a path | 31.8, 31.14 |
|
|
539
539
|
| `foo.push(v)` | the same | 31.8, 31.9 |
|
|
540
540
|
| `const [a, b] = foo` / `...foo` | one read of the value | 31.12 |
|
|
541
|
-
| `foo.bar` | the value's `bar`, or the `Reactive`'s own `bar` where it declares one | 31.5
|
|
541
|
+
| `foo.bar` | the value's `bar`, or the `Reactive`'s own `bar` where it declares one the value does not | 31.5 |
|
|
542
542
|
| `foo.bar(…)` | the `Reactive` API where `bar` is a member | 31.6 |
|
|
543
543
|
| `foo()` / `foo.set(v)` | the explicit forms | 31.7, 31.11 |
|
|
544
544
|
|
|
@@ -596,7 +596,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
596
596
|
|
|
597
597
|
| Name | Signature | Meaning | Rules |
|
|
598
598
|
| --- | --- | --- | --- |
|
|
599
|
-
| `props` | `<Props>() => { [K in keyof Props]: Props[K] }` | One live accessor per prop the component declares. | 33.1, 33.2, 33.3, 33.4, 33.5, 33.6, 33.7, 33.8, 33.9, 33.10, 33.11, 33.14, 33.15, 33.20, 33.22, 33.25 |
|
|
599
|
+
| `props` | `<Props>() => { [K in keyof Props]: Props[K] }` | One live accessor per prop the component declares. | 33.1, 33.2, 33.3, 33.4, 33.5, 33.6, 33.7, 33.8, 33.9, 33.10, 33.11, 33.14, 33.15, 33.20, 33.22, 33.25, 33.27 |
|
|
600
600
|
| `Attributes<Tag>` | `Attributes<Tag extends keyof HTMLElementTagNameMap \| keyof SVGElementTagNameMap>` | The attributes an HTML or SVG element takes, typed as a component's props. | 33.23, 33.24, 33.26 |
|
|
601
601
|
| `children` | always accepted | What a caller passes between the tags. | 33.16, 32.18 |
|
|
602
602
|
|
|
@@ -702,7 +702,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
702
702
|
|
|
703
703
|
| Name | Signature | Meaning | Rules |
|
|
704
704
|
| --- | --- | --- | --- |
|
|
705
|
-
| `middleware` | `(...rungs:
|
|
705
|
+
| `middleware` | `(...rungs: ((next: (ctx?: { request: Request }) => Promise<Response>, ctx: { request: Request }) => Response \| Failed<string, unknown> \| Promise<Response \| Failed<string, unknown>>)[]) => () => void` | The per-request lane at the calling file's route. | 18.26, 37.2, 37.3, 37.13, 37.14, 37.15 |
|
|
706
706
|
| `onStart` | `(fn: (start: () => Promise<void>) => void \| Promise<void>) => () => void` | Wraps the boot. | 37.4, 37.6, 37.13 |
|
|
707
707
|
| `onStop` | `(fn: (stop: () => Promise<void>) => void \| Promise<void>) => () => void` | Mirrors it for teardown. | 37.4, 37.6, 37.13 |
|
|
708
708
|
| `onError` | `(fn: (error: unknown) => unknown) => () => void` | Runs on an unexpected error at the calling file's route. | 37.5, 37.8, 37.13 |
|
package/docs/RULEBOOK.md
CHANGED
|
@@ -1871,16 +1871,17 @@ the routes 30.9 ranks after that route.
|
|
|
1871
1871
|
|
|
1872
1872
|
31.3 A name MUST hold the `Reactive` only where the declared type of its position is a `Reactive`: an
|
|
1873
1873
|
annotated binding, an annotated return, a `Reactive`-typed parameter, a `bind:` operand, an `await`
|
|
1874
|
-
operand — or where 31.
|
|
1874
|
+
operand — or where 31.13 holds it.
|
|
1875
1875
|
|
|
1876
1876
|
31.4 Assignment to such a name MUST be a write, and the assigned value MAY be settled, a load, or a
|
|
1877
1877
|
`Reactive`.
|
|
1878
1878
|
|
|
1879
1879
|
31.5 A property access on such a name MUST reach the value, except a member declared on the
|
|
1880
|
-
`Reactive` type, which MUST reach that member bound to the
|
|
1880
|
+
`Reactive` type that the value's type does not declare, which MUST reach that member bound to the
|
|
1881
|
+
`Reactive`.
|
|
1881
1882
|
|
|
1882
|
-
31.6 A call on such a name MUST reach the `Reactive` API where
|
|
1883
|
-
|
|
1883
|
+
31.6 A call on such a name MUST reach the `Reactive` API where 31.5 reaches the `Reactive`'s
|
|
1884
|
+
member, and the value's method otherwise.
|
|
1884
1885
|
|
|
1885
1886
|
31.7 `s` and `s.set` MUST keep compiling inside a `.abide` file.
|
|
1886
1887
|
|
|
@@ -1896,17 +1897,14 @@ the member name.
|
|
|
1896
1897
|
|
|
1897
1898
|
31.12 A destructuring pattern or a spread over such a name MUST read it once.
|
|
1898
1899
|
|
|
1899
|
-
31.13
|
|
1900
|
-
naming the explicit read.
|
|
1901
|
-
|
|
1902
|
-
31.14 A name MUST hold the `Reactive` where the declared type of its position is a `Selection`, or a
|
|
1900
|
+
31.13 A name MUST hold the `Reactive` where the declared type of its position is a `Selection`, or a
|
|
1903
1901
|
type parameter constrained by one.
|
|
1904
1902
|
|
|
1905
|
-
31.
|
|
1903
|
+
31.14 A write through a member path that reaches a value which is not plain data — an array, or an
|
|
1906
1904
|
object whose prototype is `Object.prototype` or `null` — MUST assign on that value itself, MUST NOT
|
|
1907
1905
|
copy it or any level above it, and MUST NOT wake a reader.
|
|
1908
1906
|
|
|
1909
|
-
31.
|
|
1907
|
+
31.15 `route.url`, `route.params`, `route.name` and `route.navigating` MUST each be read and written
|
|
1910
1908
|
as a name bound to a `Reactive` is, per 31.1 to 31.7.
|
|
1911
1909
|
|
|
1912
1910
|
# 32. Templating
|
|
@@ -2219,6 +2217,10 @@ that element as its `currentTarget`.
|
|
|
2219
2217
|
included, under the names SVG spells them, and a tag both HTML and SVG name MUST be typed as the HTML
|
|
2220
2218
|
element.
|
|
2221
2219
|
|
|
2220
|
+
33.27 A name `props` binds MUST hold a `Reactive` wherever 31.3 or 31.13 has a name hold its
|
|
2221
|
+
`Reactive` or 31.5 has it reach its `Reactive`'s member, and that `Reactive`'s probes MUST answer for
|
|
2222
|
+
every `Reactive` the caller's expression read.
|
|
2223
|
+
|
|
2222
2224
|
# 34. Script and style blocks
|
|
2223
2225
|
|
|
2224
2226
|
34.1 A `<script>` block MUST be per-instance component setup.
|
|
@@ -2454,6 +2456,13 @@ through `App.stop`, and the process MUST then exit with 0.
|
|
|
2454
2456
|
37.13 A lifecycle hook called in a module of the app's own that is neither a `.abide` nor a handler
|
|
2455
2457
|
file MUST be a build error naming the module and the hook.
|
|
2456
2458
|
|
|
2459
|
+
37.14 A `Failed` a `middleware` rung returns MUST be answered in the lane the rung is filed over: by
|
|
2460
|
+
the nearest `error.abide` per 35.2 over a page, as 15.21 states over a handler, and as 15.22 paints
|
|
2461
|
+
a 405 for a rung filed at the root route.
|
|
2462
|
+
|
|
2463
|
+
37.15 A `middleware` rung outside one that returned a `Failed` MUST be handed 37.14's answer from
|
|
2464
|
+
`next`, and MUST NOT be handed the `Failed`.
|
|
2465
|
+
|
|
2457
2466
|
# 38. Commands
|
|
2458
2467
|
|
|
2459
2468
|
## The commands
|
|
@@ -3348,8 +3357,8 @@ run no turn for 30 seconds.
|
|
|
3348
3357
|
44.23 A post to `/__abide/bridge` carrying a line that is not JSON MUST be refused 400, and none of
|
|
3349
3358
|
its lines MUST be relayed.
|
|
3350
3359
|
|
|
3351
|
-
44.24 A bridge MUST answer an MCP request its Claude Code made with a failure where
|
|
3352
|
-
|
|
3360
|
+
44.24 A bridge MUST answer an MCP request its Claude Code made with a failure where
|
|
3361
|
+
`/__abide/bridge` sent no reply within 120 seconds.
|
|
3353
3362
|
|
|
3354
3363
|
44.25 A bridge whose stream from `/__abide/bridge` ends unasked MUST redial it with its pairing's
|
|
3355
3364
|
token, each wait twice the last, until it is refused or 60 seconds have passed.
|
|
@@ -3372,7 +3381,9 @@ before it exits.
|
|
|
3372
3381
|
|
|
3373
3382
|
44.31 A conversation MUST write one `debug` line on `abide:assistant` when its events end, naming
|
|
3374
3383
|
its stop reason, the transcript's length, the tool calls it made, its usage and how long it took,
|
|
3375
|
-
and naming it `unfinished` where it ended without a `done
|
|
3384
|
+
and naming it `unfinished` where it ended without a `done`, followed by why — `aborted` where the
|
|
3385
|
+
request's signal aborted, else `failed` where its provider threw, with the throw's message ending the
|
|
3386
|
+
line, else `stopped` where its caller stopped reading.
|
|
3376
3387
|
|
|
3377
3388
|
44.32 A command `claudeCode.bridgeCommand` or `claudeCode.bridge` mints with `tools` MUST grant
|
|
3378
3389
|
those built-in tools after its `--` as `--tools`, and one minted without `tools` MUST carry no `--`.
|
|
@@ -3409,12 +3420,23 @@ a link in the `abide-bridge` scheme naming the same site, code, bridge release a
|
|
|
3409
3420
|
whose release is a version alone, and MUST run the release it names.
|
|
3410
3421
|
|
|
3411
3422
|
44.42 A bridge opening an `abide-bridge` link MUST ask the visitor before it pairs, every time, naming
|
|
3412
|
-
the site, the built-in tools and the bridge release the link asks for
|
|
3423
|
+
the site, the built-in tools and the bridge release the link asks for, and the options and the names
|
|
3424
|
+
of the variables `abide-bridge install` kept (44.44).
|
|
3413
3425
|
|
|
3414
3426
|
44.43 `abide-bridge install` MUST write the app that opens links under the visitor's own Application
|
|
3415
3427
|
Support and register it there, and `abide-bridge uninstall` MUST unregister it and remove all
|
|
3416
3428
|
install wrote.
|
|
3417
3429
|
|
|
3430
|
+
44.44 `abide-bridge install` MUST keep the Claude Code options after its `--` and each `--env
|
|
3431
|
+
NAME=VALUE` it is given, and a bridge opening an `abide-bridge` link MUST run Claude Code with those
|
|
3432
|
+
options ahead of the link's built-in tools and with those variables set, and a link MUST NOT set either.
|
|
3433
|
+
|
|
3434
|
+
44.45 A bridge MUST say that `/__abide/bridge` did not take a report once, and not again until a
|
|
3435
|
+
report is taken, and MUST NOT say it while it redials per 44.25.
|
|
3436
|
+
|
|
3437
|
+
44.46 A bridge MUST end a turn once `/__abide/bridge` did not take a report carrying it, and MUST
|
|
3438
|
+
report that turn failed.
|
|
3439
|
+
|
|
3418
3440
|
# 45. Offline
|
|
3419
3441
|
|
|
3420
3442
|
45.1 Where `ABIDE_OFFLINE` is on, a page `abide build` built MUST register the worker
|
package/docs/abide.md
CHANGED
|
@@ -625,7 +625,7 @@ test('typing writes the value, and the value fills the field', async () => {
|
|
|
625
625
|
| `const [a, b] = foo` / `...foo` | one read, taken apart |
|
|
626
626
|
| `foo = bar` | a write |
|
|
627
627
|
| `foo.bar` | the value's `bar` |
|
|
628
|
-
| `foo.bar(…)` | the value's method,
|
|
628
|
+
| `foo.bar(…)` | the value's method where it has one, and otherwise a member of the `Reactive` such as `busy` |
|
|
629
629
|
| `foo()` / `foo.set(v)` | the explicit read and write |
|
|
630
630
|
| `await foo` | the value, once it has settled |
|
|
631
631
|
| `refresh(foo)` / a `Selection`-typed parameter | the `Reactive` itself |
|
|
@@ -4227,24 +4227,28 @@ async function exportAll() {
|
|
|
4227
4227
|
```
|
|
4228
4228
|
|
|
4229
4229
|
```ts src/account/exportContacts.handler.ts
|
|
4230
|
-
import { principal, refuse } from '@abide/abide'
|
|
4231
4230
|
import { POST } from '@abide/abide/server'
|
|
4232
4231
|
|
|
4233
4232
|
import { CONTACTS } from '../contacts/lib/CONTACTS.server.ts'
|
|
4233
|
+
import { adminsOnly } from './lib/adminsOnly.ts'
|
|
4234
4234
|
|
|
4235
4235
|
export default POST(async () => CONTACTS, {
|
|
4236
4236
|
description: 'Every contact, for an admin to export.',
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
async (next, ctx) => {
|
|
4240
|
-
const { role } = await principal.resolved
|
|
4241
|
-
if (role !== 'admin') return refuse(403, 'Admins only.')
|
|
4242
|
-
return next(ctx)
|
|
4243
|
-
},
|
|
4244
|
-
],
|
|
4237
|
+
// Runs before the handler, on every call, in process or not.
|
|
4238
|
+
middleware: [adminsOnly],
|
|
4245
4239
|
})
|
|
4246
4240
|
```
|
|
4247
4241
|
|
|
4242
|
+
```ts src/account/lib/adminsOnly.ts
|
|
4243
|
+
import { type Middleware, principal, refuse } from '@abide/abide'
|
|
4244
|
+
|
|
4245
|
+
// One rung for a handler's `middleware` and a layout's alike.
|
|
4246
|
+
export const adminsOnly: Middleware = async (next) => {
|
|
4247
|
+
const { role } = await principal.resolved
|
|
4248
|
+
return role === 'admin' ? next() : refuse(403, 'Admins only.')
|
|
4249
|
+
}
|
|
4250
|
+
```
|
|
4251
|
+
|
|
4248
4252
|
```ts src/account/lib/ExportContacts.test.ts
|
|
4249
4253
|
import { expect, test } from 'bun:test'
|
|
4250
4254
|
|
|
@@ -4278,22 +4282,18 @@ test('sales and a signed-out caller are refused 403', async () => {
|
|
|
4278
4282
|
})
|
|
4279
4283
|
```
|
|
4280
4284
|
|
|
4281
|
-
A rung is a `Middleware`: it is handed `next` and the call's context, and either returns `next(
|
|
4285
|
+
A rung is a `Middleware`: it is handed `next` and the call's context, and either returns `next()` or answers in the handler's place. Returning `refuse(403, …)` refuses, and neither the handler nor any rung after it runs. A throw escapes every rung rather than unwinding through them.
|
|
4282
4286
|
|
|
4283
4287
|
The rung sits on the handler, so it runs on every call: from a browser, from another handler, and from a page rendering on the server. It reads arguments through `ctx.args()`, which parses the body on its first call. So a rung that never asks refuses a signed-out caller before their body is parsed or checked.
|
|
4284
4288
|
|
|
4285
|
-
To guard a whole section, call `middleware(…)` in its `layout.abide`, such as `src/account/admin/layout.abide`. That rung runs over every page and handler below it, and it has the request and nothing else:
|
|
4289
|
+
To guard a whole section, call `middleware(…)` in its `layout.abide`, such as `src/account/admin/layout.abide`. That rung runs over every page and handler below it, and it has the request and nothing else. The same `adminsOnly` fits there, and its refusal is painted by the section's `error.abide` over a page and answered as Problem Details over a handler:
|
|
4286
4290
|
|
|
4287
4291
|
```abide abide
|
|
4288
4292
|
<script server>
|
|
4289
|
-
import { principal } from '@abide/abide'
|
|
4290
4293
|
import { middleware } from '@abide/abide/server'
|
|
4294
|
+
import { adminsOnly } from '#src/account/lib/adminsOnly.ts'
|
|
4291
4295
|
|
|
4292
|
-
middleware(
|
|
4293
|
-
const { role } = await principal.resolved
|
|
4294
|
-
if (role !== 'admin') return new Response('Admins only.', { status: 403 })
|
|
4295
|
-
return next()
|
|
4296
|
-
})
|
|
4296
|
+
middleware(adminsOnly)
|
|
4297
4297
|
</script>
|
|
4298
4298
|
|
|
4299
4299
|
<slot/>
|
|
@@ -7482,7 +7482,7 @@ Arrive here knowing which name you want. Each page is read off the registry: the
|
|
|
7482
7482
|
|
|
7483
7483
|
| Name | Signature | Meaning | Rules |
|
|
7484
7484
|
| --- | --- | --- | --- |
|
|
7485
|
-
| `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](/rulebook#13.1), [13.8](/rulebook#13.8), [13.9](/rulebook#13.9), [13.13](/rulebook#13.13), [31.
|
|
7485
|
+
| `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](/rulebook#13.1), [13.8](/rulebook#13.8), [13.9](/rulebook#13.9), [13.13](/rulebook#13.13), [31.13](/rulebook#31.13) |
|
|
7486
7486
|
|
|
7487
7487
|
## Taught in
|
|
7488
7488
|
|
|
@@ -7776,7 +7776,7 @@ Reactive primitives: what is written in place rather than imported.
|
|
|
7776
7776
|
|
|
7777
7777
|
| Name | Signature | Meaning | Rules |
|
|
7778
7778
|
| --- | --- | --- | --- |
|
|
7779
|
-
| `Middleware` |
|
|
7779
|
+
| `Middleware` | `Middleware<Answer = never, Extra extends object = object> = <Given extends { request: Request } & Extra, Result>(next: (ctx?: Given) => Promise<Result>, ctx: Given) => Result \| Answer \| Failed<string, unknown> \| Promise<Result \| Answer \| Failed<string, unknown>>` | One rung, written once for every lane whose context carries `Extra`. | [16.14](/rulebook#16.14), [16.15](/rulebook#16.15), [16.16](/rulebook#16.16), [16.21](/rulebook#16.21), [37.14](/rulebook#37.14), [37.15](/rulebook#37.15) |
|
|
7780
7780
|
|
|
7781
7781
|
## Taught in
|
|
7782
7782
|
|
|
@@ -7851,7 +7851,7 @@ Reactive primitives: what is written in place rather than imported.
|
|
|
7851
7851
|
| Name | Signature | Meaning | Rules |
|
|
7852
7852
|
| --- | --- | --- | --- |
|
|
7853
7853
|
| `description` | `string` | The human description carried onto every generated surface. | [16.28](/rulebook#16.28) |
|
|
7854
|
-
| `middleware` | `
|
|
7854
|
+
| `middleware` | `((next: (ctx?: { request: Request; args: () => Args }) => Promise<unknown>, ctx: { request: Request; args: () => Args }) => unknown)[]` | The rungs run per call. | [16.11](/rulebook#16.11), [16.12](/rulebook#16.12), [16.16](/rulebook#16.16), [16.17](/rulebook#16.17), [16.18](/rulebook#16.18), [16.19](/rulebook#16.19), [16.20](/rulebook#16.20) |
|
|
7855
7855
|
| `timeout` | `number` | How long the call may go without progress. | [16.22](/rulebook#16.22), [16.58](/rulebook#16.58), [16.59](/rulebook#16.59), [16.60](/rulebook#16.60), [16.61](/rulebook#16.61), [16.77](/rulebook#16.77) |
|
|
7856
7856
|
| `clients` | `Clients` | Which surfaces carry this handler. | [16.37](/rulebook#16.37), [20.3](/rulebook#20.3) |
|
|
7857
7857
|
| `crossOrigin` | `boolean \| string[]` | Whether other origins may call it, or follow it over the mux. | [16.24](/rulebook#16.24), [18.2](/rulebook#18.2), [21.19](/rulebook#21.19) |
|
|
@@ -8418,8 +8418,8 @@ Generated surfaces: what is written in place rather than imported.
|
|
|
8418
8418
|
|
|
8419
8419
|
| Name | Signature | Meaning | Rules |
|
|
8420
8420
|
| --- | --- | --- | --- |
|
|
8421
|
-
| `claudeCode` | `(config?: ClaudeCodeConfig) => Provider` | The visitor's own Claude Code, reached through the bridge paired with their browser, as a provider. | [44.5](/rulebook#44.5), [44.13](/rulebook#44.13), [44.17](/rulebook#44.17), [44.18](/rulebook#44.18), [44.19](/rulebook#44.19), [44.24](/rulebook#44.24), [44.25](/rulebook#44.25), [44.27](/rulebook#44.27), [44.30](/rulebook#44.30), [44.33](/rulebook#44.33) |
|
|
8422
|
-
| `claudeCode.bridgeCommand` | `(options?: { tools?: string[] }) => { command: string; link: string; expires: number }` | The command and the link that pair a bridge with this browser, granting the built-in tools it is given. | [44.14](/rulebook#44.14), [44.32](/rulebook#44.32), [44.33](/rulebook#44.33), [44.40](/rulebook#44.40), [44.41](/rulebook#44.41), [44.42](/rulebook#44.42), [44.43](/rulebook#44.43) |
|
|
8421
|
+
| `claudeCode` | `(config?: ClaudeCodeConfig) => Provider` | The visitor's own Claude Code, reached through the bridge paired with their browser, as a provider. | [44.5](/rulebook#44.5), [44.13](/rulebook#44.13), [44.17](/rulebook#44.17), [44.18](/rulebook#44.18), [44.19](/rulebook#44.19), [44.24](/rulebook#44.24), [44.25](/rulebook#44.25), [44.27](/rulebook#44.27), [44.30](/rulebook#44.30), [44.33](/rulebook#44.33), [44.45](/rulebook#44.45), [44.46](/rulebook#44.46) |
|
|
8422
|
+
| `claudeCode.bridgeCommand` | `(options?: { tools?: string[] }) => { command: string; link: string; expires: number }` | The command and the link that pair a bridge with this browser, granting the built-in tools it is given. | [44.14](/rulebook#44.14), [44.32](/rulebook#44.32), [44.33](/rulebook#44.33), [44.40](/rulebook#44.40), [44.41](/rulebook#44.41), [44.42](/rulebook#44.42), [44.43](/rulebook#44.43), [44.44](/rulebook#44.44) |
|
|
8423
8423
|
| `claudeCode.bridge` | `(options?: { tools?: string[] }) => AsyncGenerator<BridgeStatus>` | This browser's pairing, as it changes. | [44.20](/rulebook#44.20), [44.22](/rulebook#44.22), [44.32](/rulebook#44.32), [44.33](/rulebook#44.33), [44.34](/rulebook#44.34), [44.40](/rulebook#44.40) |
|
|
8424
8424
|
| `/__abide/bridge` | `GET`, `POST` | Where a bridge pairs, and is relayed its turns. | [36.7](/rulebook#36.7), [44.14](/rulebook#44.14), [44.15](/rulebook#44.15), [44.19](/rulebook#44.19), [44.23](/rulebook#44.23), [44.26](/rulebook#44.26), [16.57](/rulebook#16.57), [16.78](/rulebook#16.78) |
|
|
8425
8425
|
|
|
@@ -8529,10 +8529,10 @@ Generated surfaces: what is written in place rather than imported.
|
|
|
8529
8529
|
|
|
8530
8530
|
| Name | Signature | Meaning | Rules |
|
|
8531
8531
|
| --- | --- | --- | --- |
|
|
8532
|
-
| `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.
|
|
8533
|
-
| `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.
|
|
8534
|
-
| `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.
|
|
8535
|
-
| `route.navigating` | `Reactive<boolean>` | Whether a navigation is in flight. | [23.1](/rulebook#23.1), [31.
|
|
8532
|
+
| `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.15](/rulebook#31.15) |
|
|
8533
|
+
| `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.15](/rulebook#31.15) |
|
|
8534
|
+
| `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.15](/rulebook#31.15) |
|
|
8535
|
+
| `route.navigating` | `Reactive<boolean>` | Whether a navigation is in flight. | [23.1](/rulebook#23.1), [31.15](/rulebook#31.15) |
|
|
8536
8536
|
|
|
8537
8537
|
## Taught in
|
|
8538
8538
|
|
|
@@ -8977,7 +8977,7 @@ Generated surfaces: what is written in place rather than imported.
|
|
|
8977
8977
|
|
|
8978
8978
|
| Name | Signature | Meaning | Rules |
|
|
8979
8979
|
| --- | --- | --- | --- |
|
|
8980
|
-
| `csp` | `(sources?: Record<string, string[]>) =>
|
|
8980
|
+
| `csp` | `(sources?: Record<string, string[]>) => (next: (ctx?: { request: Request }) => Promise<Response>, ctx: { request: Request }) => Promise<Response>` | The rung that sets `content-security-policy`. | [29.1](/rulebook#29.1), [29.2](/rulebook#29.2), [29.5](/rulebook#29.5), [29.6](/rulebook#29.6), [29.7](/rulebook#29.7), [29.8](/rulebook#29.8) |
|
|
8981
8981
|
| `csp.nonce` | `() => string` | This response's nonce, for the app's own inline script. | [29.3](/rulebook#29.3), [29.4](/rulebook#29.4), [29.9](/rulebook#29.9), [29.11](/rulebook#29.11) |
|
|
8982
8982
|
|
|
8983
8983
|
## Taught in
|
|
@@ -9215,12 +9215,12 @@ Generated surfaces: what is written in place rather than imported.
|
|
|
9215
9215
|
| `foo` wherever the declared type of its position is not a `Reactive` | a live read | [31.1](/rulebook#31.1), [31.2](/rulebook#31.2), [31.10](/rulebook#31.10) |
|
|
9216
9216
|
| `const x: Reactive<…> = foo` / a `Reactive<…>`-typed parameter, return or `bind:` operand | the `Reactive` | [31.3](/rulebook#31.3) |
|
|
9217
9217
|
| `await foo` | the settling of the `Reactive`, which is its value | [1.4](/rulebook#1.4), [2.7](/rulebook#2.7), [31.3](/rulebook#31.3) |
|
|
9218
|
-
| `refresh(foo)` / a `Selection`-typed parameter | the `Reactive` | [31.
|
|
9218
|
+
| `refresh(foo)` / a `Selection`-typed parameter | the `Reactive` | [31.13](/rulebook#31.13) |
|
|
9219
9219
|
| `foo = bar` | a write | [31.4](/rulebook#31.4), [11.61](/rulebook#11.61) |
|
|
9220
|
-
| `foo.bar = v` | a write through a path | [31.8](/rulebook#31.8), [31.
|
|
9220
|
+
| `foo.bar = v` | a write through a path | [31.8](/rulebook#31.8), [31.14](/rulebook#31.14) |
|
|
9221
9221
|
| `foo.push(v)` | the same | [31.8](/rulebook#31.8), [31.9](/rulebook#31.9) |
|
|
9222
9222
|
| `const [a, b] = foo` / `...foo` | one read of the value | [31.12](/rulebook#31.12) |
|
|
9223
|
-
| `foo.bar` | the value's `bar`, or the `Reactive`'s own `bar` where it declares one | [31.5](/rulebook#31.5)
|
|
9223
|
+
| `foo.bar` | the value's `bar`, or the `Reactive`'s own `bar` where it declares one the value does not | [31.5](/rulebook#31.5) |
|
|
9224
9224
|
| `foo.bar(…)` | the `Reactive` API where `bar` is a member | [31.6](/rulebook#31.6) |
|
|
9225
9225
|
| `foo()` / `foo.set(v)` | the explicit forms | [31.7](/rulebook#31.7), [31.11](/rulebook#31.11) |
|
|
9226
9226
|
|
|
@@ -9330,7 +9330,7 @@ Generated surfaces: what is written in place rather than imported.
|
|
|
9330
9330
|
|
|
9331
9331
|
| Name | Signature | Meaning | Rules |
|
|
9332
9332
|
| --- | --- | --- | --- |
|
|
9333
|
-
| `props` | `<Props>() => { [K in keyof Props]: Props[K] }` | One live accessor per prop the component declares. | [33.1](/rulebook#33.1), [33.2](/rulebook#33.2), [33.3](/rulebook#33.3), [33.4](/rulebook#33.4), [33.5](/rulebook#33.5), [33.6](/rulebook#33.6), [33.7](/rulebook#33.7), [33.8](/rulebook#33.8), [33.9](/rulebook#33.9), [33.10](/rulebook#33.10), [33.11](/rulebook#33.11), [33.14](/rulebook#33.14), [33.15](/rulebook#33.15), [33.20](/rulebook#33.20), [33.22](/rulebook#33.22), [33.25](/rulebook#33.25) |
|
|
9333
|
+
| `props` | `<Props>() => { [K in keyof Props]: Props[K] }` | One live accessor per prop the component declares. | [33.1](/rulebook#33.1), [33.2](/rulebook#33.2), [33.3](/rulebook#33.3), [33.4](/rulebook#33.4), [33.5](/rulebook#33.5), [33.6](/rulebook#33.6), [33.7](/rulebook#33.7), [33.8](/rulebook#33.8), [33.9](/rulebook#33.9), [33.10](/rulebook#33.10), [33.11](/rulebook#33.11), [33.14](/rulebook#33.14), [33.15](/rulebook#33.15), [33.20](/rulebook#33.20), [33.22](/rulebook#33.22), [33.25](/rulebook#33.25), [33.27](/rulebook#33.27) |
|
|
9334
9334
|
| `children` | always accepted | What a caller passes between the tags. | [33.16](/rulebook#33.16), [32.18](/rulebook#32.18) |
|
|
9335
9335
|
|
|
9336
9336
|
## Taught in
|
|
@@ -9511,7 +9511,7 @@ Configuration: what is written in place rather than imported.
|
|
|
9511
9511
|
|
|
9512
9512
|
| Name | Signature | Meaning | Rules |
|
|
9513
9513
|
| --- | --- | --- | --- |
|
|
9514
|
-
| `middleware` | `(...rungs:
|
|
9514
|
+
| `middleware` | `(...rungs: ((next: (ctx?: { request: Request }) => Promise<Response>, ctx: { request: Request }) => Response \| Failed<string, unknown> \| Promise<Response \| Failed<string, unknown>>)[]) => () => void` | The per-request lane at the calling file's route. | [18.26](/rulebook#18.26), [37.2](/rulebook#37.2), [37.3](/rulebook#37.3), [37.13](/rulebook#37.13), [37.14](/rulebook#37.14), [37.15](/rulebook#37.15) |
|
|
9515
9515
|
|
|
9516
9516
|
## Taught in
|
|
9517
9517
|
|
package/package.json
CHANGED
package/src/compiler/Lowering.ts
CHANGED
|
@@ -686,7 +686,8 @@ export class Lowering {
|
|
|
686
686
|
/**
|
|
687
687
|
* The read's name as emitted: `name()` for a written prop, whose cell its accessor hands back.
|
|
688
688
|
*
|
|
689
|
-
* 33.6 — a written prop's cell is reached through its accessor.
|
|
689
|
+
* 33.6 — a written prop's cell is reached through its accessor. 33.27 — a read prop where a
|
|
690
|
+
* `Reactive` is due, a cell over its accessor.
|
|
690
691
|
*/
|
|
691
692
|
private nameOf(read: Read): string {
|
|
692
693
|
const spelled = this.projection.text.slice(read.start, read.end)
|
|
@@ -694,6 +695,7 @@ export class Lowering {
|
|
|
694
695
|
// reads the one `route` every page shares.
|
|
695
696
|
if (this.routed !== undefined && read.routeParams)
|
|
696
697
|
return `(${spelled} as unknown as () => __RouteParams<${JSON.stringify(this.routed.route)}, ${JSON.stringify(this.routed.kind)}>)`
|
|
698
|
+
if (read.held) return `${this.use('heldProp')}(${spelled})`
|
|
697
699
|
return read.through ? `${spelled}()` : spelled
|
|
698
700
|
}
|
|
699
701
|
|
|
@@ -734,7 +736,7 @@ export class Lowering {
|
|
|
734
736
|
const name = this.nameOf(read)
|
|
735
737
|
switch (read.shape) {
|
|
736
738
|
case 'asWritten':
|
|
737
|
-
return read.through ? name : undefined
|
|
739
|
+
return read.through || read.held ? name : undefined
|
|
738
740
|
// 31.5 — the member BOUND to the `Reactive`, arguments and all.
|
|
739
741
|
case 'member':
|
|
740
742
|
return this.checking
|
|
@@ -8,9 +8,8 @@
|
|
|
8
8
|
* `Reactive` itself, which reaches that. Without the list every `n.foo` reads as the API and the
|
|
9
9
|
* value's own members are unreachable, which is what `regions.join is not a function` was.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* resolves to the `Reactive`'s, and 31.13 asks for a warning naming exactly that case.
|
|
11
|
+
* The list names the candidates; the value's TYPE decides (`declaresMember` in `readsIn`): a value
|
|
12
|
+
* whose own type declares `set` or `error` keeps its own, so a `Map`'s `set` is the map's.
|
|
14
13
|
*
|
|
15
14
|
* WHICH IS WHY A NAME THE `Reactive` DOES NOT DECLARE MUST NOT BE HERE: it takes a member the
|
|
16
15
|
* value really has and resolves it to nothing. This list is exactly `MEMBERS` in
|
|
@@ -29,6 +29,8 @@ export const SHARED_NAMES: ReadonlySet<string> = new Set([
|
|
|
29
29
|
// 32.6, 33.6, 33.7 — a component's `bind:`, and the cell a child writing that prop builds.
|
|
30
30
|
'boundProp',
|
|
31
31
|
'propCell',
|
|
32
|
+
// 33.27 — a read prop where its position holds the `Reactive`.
|
|
33
|
+
'heldProp',
|
|
32
34
|
'propCells',
|
|
33
35
|
// 33.20 — a default answering where the caller's accessor reads `undefined`.
|
|
34
36
|
'propOr',
|
|
@@ -625,7 +625,7 @@ export class TypeSession {
|
|
|
625
625
|
* shadow is asked is `readsIn`'s.
|
|
626
626
|
*
|
|
627
627
|
* WHAT IT HAS TO SAY THAT IS NOT A TYPE ERROR comes back beside the reads: the compiler's own
|
|
628
|
-
* warnings (14.14 to 14.17,
|
|
628
|
+
* warnings (14.14 to 14.17, 32.14), each on the `.abide` line where the source's text
|
|
629
629
|
* was handed in.
|
|
630
630
|
*/
|
|
631
631
|
async readsFor(
|
|
@@ -52,8 +52,7 @@ export type Read = {
|
|
|
52
52
|
* that brackets a binding element's initializer, which together make a default an accessor;
|
|
53
53
|
* `absent`, which gives a binding with no default an accessor of `undefined` (33.4); and
|
|
54
54
|
* `restMember`, a member of the rest element, which calls that key's accessor (33.15), beside
|
|
55
|
-
* `restWhole`, the rest element handed on as one value (33.22). The
|
|
56
|
-
* pair and `absent` are INSERTIONS — zero-width, so what stands between the pair goes on being
|
|
55
|
+
* `restWhole`, the rest element handed on as one value (33.22). The pair and `absent` are INSERTIONS — zero-width, so what stands between the pair goes on being
|
|
57
56
|
* lowered by the same walk, and a default reading a `Reactive` still reads it.
|
|
58
57
|
*/
|
|
59
58
|
shape:
|
|
@@ -96,6 +95,12 @@ export type Read = {
|
|
|
96
95
|
* pair, that the default is one too.
|
|
97
96
|
*/
|
|
98
97
|
through: boolean
|
|
98
|
+
/**
|
|
99
|
+
* 33.27 — the name is a prop the child only reads, standing where a `Reactive` is due.
|
|
100
|
+
*
|
|
101
|
+
* So the `Reactive` every rewrite reaches is a cell over its accessor, `heldProp(name)`.
|
|
102
|
+
*/
|
|
103
|
+
held: boolean
|
|
99
104
|
/** 32.32 — the name is bound to a `reactive(…)` whose options declare `by`. */
|
|
100
105
|
byValue: boolean
|
|
101
106
|
/** 14.8 — the name is declared by a branch-local `<script>`, inside the body it scopes. */
|
|
@@ -136,6 +141,7 @@ export function newRead(
|
|
|
136
141
|
path: [],
|
|
137
142
|
value: undefined,
|
|
138
143
|
through: false,
|
|
144
|
+
held: false,
|
|
139
145
|
byValue: false,
|
|
140
146
|
local: false,
|
|
141
147
|
keys: [],
|
|
@@ -235,7 +241,10 @@ export function classifyPropRead(node: Node): Read | undefined {
|
|
|
235
241
|
* `undefined` for an occurrence that is not a read at all: the declaration itself, an import or
|
|
236
242
|
* export specifier, and a `typeof n` in a type.
|
|
237
243
|
*/
|
|
238
|
-
export function classifyRead(
|
|
244
|
+
export function classifyRead(
|
|
245
|
+
node: Node,
|
|
246
|
+
valueMember = false,
|
|
247
|
+
): Read | undefined {
|
|
239
248
|
const parent = node.parent
|
|
240
249
|
if (isNotARead(parent)) return undefined
|
|
241
250
|
if (
|
|
@@ -278,7 +287,12 @@ export function classifyRead(node: Node): Read | undefined {
|
|
|
278
287
|
if (isPropertyAccessExpression(up) && up.expression === top) {
|
|
279
288
|
// 31.5 — the `Reactive`'s own member is the API, and no path. Called, it stays as
|
|
280
289
|
// written; REFERENCED, it is handed over bound, so `promise.then(n.set)` writes `n`.
|
|
281
|
-
|
|
290
|
+
// `valueMember` where the value's own type declares one of that name (31.5).
|
|
291
|
+
if (
|
|
292
|
+
top === node &&
|
|
293
|
+
!valueMember &&
|
|
294
|
+
REACTIVE_MEMBERS.has(up.name.text)
|
|
295
|
+
) {
|
|
282
296
|
const outer = up.parent
|
|
283
297
|
if (
|
|
284
298
|
(isCallExpression(outer) && outer.expression === up) ||
|
|
@@ -697,6 +697,7 @@ declare function ${BOUND}<Value>(value: ${REACTIVE}<Value, any, any, any>): Valu
|
|
|
697
697
|
declare function ${BOUND}<Value>(value: { get(): Value; set(value: Value): unknown }): Value
|
|
698
698
|
declare function __restValues<Accessors>(record: Accessors): { [Key in keyof Accessors]: NonNullable<Accessors[Key]> extends () => infer Value ? Value : never }
|
|
699
699
|
declare function __propCell<Value>(read: () => Value): () => ${REACTIVE}<Value>
|
|
700
|
+
declare function __heldProp<Value>(read: () => Value): ${REACTIVE}<Value, Value, any, any>
|
|
700
701
|
declare function __raw(value: unknown): unknown
|
|
701
702
|
declare function __writePath<Root>(root: Root, path: readonly PropertyKey[], value: unknown): Root
|
|
702
703
|
declare type __RouteParams<Pattern extends string, Kind extends string> = Kind extends 'layout' ? ${ROUTE_PARAMS}<Pattern> & { [name: string]: string | string[] | undefined } : ${ROUTE_PARAMS}<Pattern>
|
|
@@ -111,7 +111,7 @@ export type Abide = {
|
|
|
111
111
|
route: string | undefined
|
|
112
112
|
reactive: CheckedSymbol | undefined
|
|
113
113
|
/**
|
|
114
|
-
* 31.
|
|
114
|
+
* 31.13 — abide's `Selection` alias, which a position may be typed as rather than as a `Reactive`.
|
|
115
115
|
*/
|
|
116
116
|
selection: CheckedSymbol | undefined
|
|
117
117
|
props: string | undefined
|
|
@@ -185,7 +185,7 @@ export async function isReactiveType(
|
|
|
185
185
|
/**
|
|
186
186
|
* Whether a type is abide's `Selection`, or a type parameter constrained by one.
|
|
187
187
|
*
|
|
188
|
-
* 31.
|
|
188
|
+
* 31.13 — A POSITION TYPED AS A `Selection`, or as a type parameter constrained by one (the free
|
|
189
189
|
* `refresh`, `invalidate`, `busy` and `ready` take `Chosen extends Selection`). A value is never a
|
|
190
190
|
* selection of itself, so a read there hands `refresh` the invoice rather than the thing to reload.
|
|
191
191
|
*/
|