@abide/abide 0.124.1 → 0.125.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.
Files changed (71) hide show
  1. package/ABIDE.md +4 -0
  2. package/CHANGELOG.md +36 -0
  3. package/bin/abide.ts +3 -2
  4. package/docs/REGISTRY.md +66 -40
  5. package/docs/RULEBOOK.md +202 -18
  6. package/docs/abide.md +391 -67
  7. package/package.json +1 -1
  8. package/src/compiler/appMap.ts +14 -1
  9. package/src/compiler/declaredExports.ts +41 -0
  10. package/src/compiler/handlersUnder.ts +1 -0
  11. package/src/compiler/hookCalls.ts +1 -0
  12. package/src/compiler/projectShadow.ts +52 -2
  13. package/src/compiler/readsIn.ts +39 -34
  14. package/src/server/PageRender.ts +7 -8
  15. package/src/server/abideModules.ts +6 -0
  16. package/src/server/answerRequest.ts +115 -52
  17. package/src/server/answerSocket.ts +6 -5
  18. package/src/server/answerWorker.ts +34 -23
  19. package/src/server/assistant.ts +141 -35
  20. package/src/server/banner.ts +9 -5
  21. package/src/server/bridgeRelay.ts +3 -3
  22. package/src/server/callerOf.ts +5 -0
  23. package/src/server/claudeCode.ts +20 -11
  24. package/src/server/commands.ts +14 -7
  25. package/src/server/createApp.ts +65 -12
  26. package/src/server/devWorker.ts +18 -16
  27. package/src/server/generatedSurfaces.ts +6 -5
  28. package/src/server/handlerFileMount.ts +2 -0
  29. package/src/server/hooks.ts +54 -8
  30. package/src/server/index.ts +18 -4
  31. package/src/server/invokeHandler.ts +1 -1
  32. package/src/server/mountHandlers.ts +6 -0
  33. package/src/server/principal.ts +3 -2
  34. package/src/server/render.ts +11 -2
  35. package/src/server/requestScope.ts +61 -1
  36. package/src/server/responseRelay.ts +9 -3
  37. package/src/server/serveDev.ts +18 -3
  38. package/src/server/sqliteStore.ts +65 -0
  39. package/src/server/testMount.ts +1 -0
  40. package/src/shared/AssistantEvent.ts +40 -0
  41. package/src/shared/BrowserHooks.ts +73 -0
  42. package/src/shared/CURRENT_ROUTER.ts +3 -1
  43. package/src/shared/Issues.ts +11 -3
  44. package/src/shared/Middleware.ts +9 -9
  45. package/src/shared/UNEXPECTED.ts +1 -1
  46. package/src/shared/answerOf.ts +9 -4
  47. package/src/shared/imagePiece.ts +85 -0
  48. package/src/shared/index.ts +17 -0
  49. package/src/shared/isServer.ts +15 -0
  50. package/src/shared/navigate.ts +10 -3
  51. package/src/shared/onError.ts +51 -0
  52. package/src/shared/onRefusal.ts +47 -0
  53. package/src/shared/online.ts +5 -1
  54. package/src/shared/reactive/Keyed.ts +12 -1
  55. package/src/shared/reactive/Reactive.ts +53 -25
  56. package/src/shared/reactive/cellShape.ts +4 -3
  57. package/src/shared/reactive/poll.ts +49 -0
  58. package/src/shared/reactive/scoped.ts +10 -1
  59. package/src/shared/reactive/scoping.ts +14 -0
  60. package/src/shared/reactive/watch.ts +19 -8
  61. package/src/shared/resultsOf.ts +21 -0
  62. package/src/shared/route.ts +18 -4
  63. package/src/shared/rpc.ts +112 -26
  64. package/src/shared/seededDocument.ts +5 -6
  65. package/src/shared/storedValue.ts +32 -0
  66. package/src/shared/webStore.ts +54 -0
  67. package/src/ui/Router.ts +42 -9
  68. package/src/ui/outboxQueue.ts +1 -1
  69. package/src/ui/wire.ts +4 -4
  70. package/src/shared/KEEP_OPENED.ts +0 -7
  71. /package/src/{server → shared}/IMAGE_TYPES.ts +0 -0
package/src/shared/rpc.ts CHANGED
@@ -183,9 +183,44 @@ export type RpcContext<Args = unknown> = { request: Request; args: () => Args }
183
183
  */
184
184
  const SENT: unique symbol = Symbol('abide.sent')
185
185
 
186
- export type RpcOptions<Args = unknown> = {
186
+ /**
187
+ * What a rung's `next` answers as a declaration types it: opaque, so what the rung answers in the
188
+ * handler's place is told apart from the answer it passes on.
189
+ */
190
+ declare const REACHED: unique symbol
191
+ type Reached = { readonly [REACHED]: true }
192
+
193
+ /**
194
+ * The refusals a declaration's rungs answer with, read off what each answers.
195
+ *
196
+ * 16.86 — A REFUSAL A RUNG NAMES IS THE `Rpc`'s, and one it does not name is not: a `Failed` whose
197
+ * name is `string` (a `Middleware` declaring no refusals) would widen every name the union narrows
198
+ * by, and a rung answering `unknown` names none.
199
+ */
200
+ type RungRefusals<Answers extends readonly unknown[]> =
201
+ Answers[number] extends infer Answer
202
+ ? Answer extends Failed<infer Name, unknown>
203
+ ? string extends Name
204
+ ? never
205
+ : Answer
206
+ : never
207
+ : never
208
+
209
+ export type RpcOptions<
210
+ Args = unknown,
211
+ Answers extends readonly unknown[] = unknown[],
212
+ > = {
187
213
  description?: string
188
- middleware?: Rung<RpcContext<Args>, unknown>[]
214
+ /**
215
+ * 16.86 — one rung per answer in `Answers`, each read in context: a rung's own refusals are
216
+ * inferred where the list is written at the declaration.
217
+ */
218
+ middleware?: {
219
+ [At in keyof Answers]: (
220
+ next: (ctx?: RpcContext<Args>) => Promise<Reached>,
221
+ ctx: RpcContext<Args>,
222
+ ) => Answers[At] | Promise<Answers[At]>
223
+ }
189
224
  timeout?: number
190
225
  clients?: Clients
191
226
  crossOrigin?: boolean | string[]
@@ -221,20 +256,34 @@ type Held<Accepted> = Accepted extends
221
256
  * which is why a value handed in takes the address's alone: it has decided its own.
222
257
  */
223
258
  type Declare = {
224
- <Stored, Args, Accepted, Failures, Produced>(
259
+ <
260
+ Stored,
261
+ Args,
262
+ Accepted,
263
+ Failures,
264
+ Produced,
265
+ Answers extends readonly unknown[] = unknown[],
266
+ >(
225
267
  handler: Keyed<Stored, Args, Accepted, Failures, Produced>,
226
- options?: RpcOptions<Args>,
227
- ): Rpc<Stored, Args, Failures, Produced>
228
- <Stored, Accepted, Failures, Produced>(
268
+ options?: RpcOptions<Args, Answers>,
269
+ ): Rpc<Stored, Args, Failures | RungRefusals<Answers>, Produced>
270
+ <
271
+ Stored,
272
+ Accepted,
273
+ Failures,
274
+ Produced,
275
+ Answers extends readonly unknown[] = unknown[],
276
+ >(
229
277
  handler: Reactive<Stored, Accepted, Failures, Produced>,
230
- options?: RpcOptions<undefined>,
231
- ): Rpc<Stored, undefined, Failures, Produced>
278
+ options?: RpcOptions<undefined, Answers>,
279
+ ): Rpc<Stored, undefined, Failures | RungRefusals<Answers>, Produced>
232
280
  // 11.2 — a stream whose parameter is optional is keyed, for `reactive`'s reason.
233
281
  <
234
282
  Body extends (args?: never) => unknown,
235
283
  Shaped = ChunkOf<Body>[],
236
284
  Gate = Schema<ChunkOf<Body>[]>,
237
285
  ArgsGate = Schema<Parameters<Body>[0]>,
286
+ Answers extends readonly unknown[] = unknown[],
238
287
  >(
239
288
  handler: Body & OptionalParameter<Body> & Streams<Body> & Plain,
240
289
  options?: Shaping<
@@ -244,36 +293,49 @@ type Declare = {
244
293
  Gate,
245
294
  ArgsGate
246
295
  > &
247
- RpcOptions<Parameters<Body>[0]>,
296
+ RpcOptions<Parameters<Body>[0], Answers>,
248
297
  ): Rpc<
249
298
  Kept<Shaped>,
250
299
  Parameters<Body>[0],
251
- Refusals<Shaped, Gate, ChunkOf<Body>[], ArgsGate, Parameters<Body>[0]>,
300
+ | Refusals<Shaped, Gate, ChunkOf<Body>[], ArgsGate, Parameters<Body>[0]>
301
+ | RungRefusals<Answers>,
252
302
  ChunkOf<Body>
253
303
  >
254
- <Chunk, Shaped = Chunk[], Gate = Schema<Chunk[]>>(
304
+ <
305
+ Chunk,
306
+ Shaped = Chunk[],
307
+ Gate = Schema<Chunk[]>,
308
+ Answers extends readonly unknown[] = unknown[],
309
+ >(
255
310
  handler: (() =>
256
311
  AsyncGenerator<Chunk> | Promise<AsyncGenerator<Chunk>>) &
257
312
  Plain,
258
- options?: Shaping<Chunk[], Shaped, never, Gate> & RpcOptions<undefined>,
259
- ): Rpc<Kept<Shaped>, undefined, Refusals<Shaped, Gate, Chunk[]>, Chunk>
313
+ options?: Shaping<Chunk[], Shaped, never, Gate> &
314
+ RpcOptions<undefined, Answers>,
315
+ ): Rpc<
316
+ Kept<Shaped>,
317
+ undefined,
318
+ Refusals<Shaped, Gate, Chunk[]> | RungRefusals<Answers>,
319
+ Chunk
320
+ >
260
321
  <
261
322
  Chunk,
262
323
  Args,
263
324
  Shaped = Chunk[],
264
325
  Gate = Schema<Chunk[]>,
265
326
  ArgsGate = Schema<Args>,
327
+ Answers extends readonly unknown[] = unknown[],
266
328
  >(
267
329
  handler: ((
268
330
  args: Args,
269
331
  ) => AsyncGenerator<Chunk> | Promise<AsyncGenerator<Chunk>>) &
270
332
  Plain,
271
333
  options?: Shaping<Chunk[], Shaped, Args, Gate, ArgsGate> &
272
- RpcOptions<Args>,
334
+ RpcOptions<Args, Answers>,
273
335
  ): Rpc<
274
336
  Kept<Shaped>,
275
337
  Args,
276
- Refusals<Shaped, Gate, Chunk[], ArgsGate, Args>,
338
+ Refusals<Shaped, Gate, Chunk[], ArgsGate, Args> | RungRefusals<Answers>,
277
339
  Chunk
278
340
  >
279
341
  // 11.2 — an optional parameter is keyed, and ahead of the arm below for `reactive`'s reason.
@@ -282,6 +344,7 @@ type Declare = {
282
344
  Shaped = Awaited<ReturnType<Body>>,
283
345
  Gate = Schema<Awaited<ReturnType<Body>>>,
284
346
  ArgsGate = Schema<Parameters<Body>[0]>,
347
+ Answers extends readonly unknown[] = unknown[],
285
348
  >(
286
349
  handler: Body & OptionalParameter<Body> & Plain,
287
350
  options?: Shaping<
@@ -291,7 +354,7 @@ type Declare = {
291
354
  Gate,
292
355
  ArgsGate
293
356
  > &
294
- RpcOptions<Parameters<Body>[0]>,
357
+ RpcOptions<Parameters<Body>[0], Answers>,
295
358
  ): Rpc<
296
359
  Kept<Shaped>,
297
360
  Parameters<Body>[0],
@@ -302,17 +365,25 @@ type Declare = {
302
365
  Awaited<ReturnType<Body>>,
303
366
  ArgsGate,
304
367
  Parameters<Body>[0]
305
- >,
368
+ >
369
+ | RungRefusals<Answers>,
306
370
  AdoptedProduced<ReturnType<Body>, Kept<Shaped>>
307
371
  >
308
- <Computed, Shaped = Awaited<Computed>, Gate = Schema<Awaited<Computed>>>(
372
+ <
373
+ Computed,
374
+ Shaped = Awaited<Computed>,
375
+ Gate = Schema<Awaited<Computed>>,
376
+ Answers extends readonly unknown[] = unknown[],
377
+ >(
309
378
  handler: (() => Computed) & Plain,
310
379
  options?: Shaping<Awaited<Computed>, Shaped, never, Gate> &
311
- RpcOptions<undefined>,
380
+ RpcOptions<undefined, Answers>,
312
381
  ): Rpc<
313
382
  Kept<Shaped>,
314
383
  undefined,
315
- AdoptedFailures<Computed> | Refusals<Shaped, Gate, Awaited<Computed>>,
384
+ | AdoptedFailures<Computed>
385
+ | Refusals<Shaped, Gate, Awaited<Computed>>
386
+ | RungRefusals<Answers>,
316
387
  AdoptedProduced<Computed, Kept<Shaped>>
317
388
  >
318
389
  <
@@ -321,23 +392,34 @@ type Declare = {
321
392
  Shaped = Awaited<Computed>,
322
393
  Gate = Schema<Awaited<Computed>>,
323
394
  ArgsGate = Schema<Args>,
395
+ Answers extends readonly unknown[] = unknown[],
324
396
  >(
325
397
  handler: ((args: Args) => Computed) & Plain,
326
398
  options?: Shaping<Awaited<Computed>, Shaped, Args, Gate, ArgsGate> &
327
- RpcOptions<Args>,
399
+ RpcOptions<Args, Answers>,
328
400
  ): Rpc<
329
401
  Kept<Shaped>,
330
402
  Args,
331
403
  | AdoptedFailures<Computed>
332
- | Refusals<Shaped, Gate, Awaited<Computed>, ArgsGate, Args>,
404
+ | Refusals<Shaped, Gate, Awaited<Computed>, ArgsGate, Args>
405
+ | RungRefusals<Answers>,
333
406
  AdoptedProduced<Computed, Kept<Shaped>>
334
407
  >
335
408
  // 16.1 — a value, `reactive`'s value overload given an address. Last, so a function is a body.
336
- <Accepted, Shaped = Accepted, Gate = Schema<Accepted>>(
409
+ <
410
+ Accepted,
411
+ Shaped = Accepted,
412
+ Gate = Schema<Accepted>,
413
+ Answers extends readonly unknown[] = unknown[],
414
+ >(
337
415
  handler: Held<Accepted>,
338
416
  options?: Shaping<Accepted, Shaped, never, Gate> &
339
- RpcOptions<undefined>,
340
- ): Rpc<Kept<Shaped>, undefined, Refusals<Shaped, Gate, Accepted>>
417
+ RpcOptions<undefined, Answers>,
418
+ ): Rpc<
419
+ Kept<Shaped>,
420
+ undefined,
421
+ Refusals<Shaped, Gate, Accepted> | RungRefusals<Answers>
422
+ >
341
423
  }
342
424
 
343
425
  /** What a handler's selection members answer before a call has built its value: no entries' answers. */
@@ -379,7 +461,11 @@ export function declare(method: Method): Declare {
379
461
  // 16.11, 16.12 — THE RUNGS, IN REGISTRATION ORDER, around the reach. Built once, at the
380
462
  // declaration (16.14); a value keyed by args, so a second call with the same args in one
381
463
  // request joins the first (1.8) and a server files one per request (11.32).
382
- const rungs = options?.middleware ?? []
464
+ // `Reached` is the declaration's view of `next`; at run time it answers the handler's value.
465
+ const rungs = (options?.middleware ?? []) as readonly Rung<
466
+ RpcContext,
467
+ unknown
468
+ >[]
383
469
  // A rung that handed `next` a context of its own making chose those args.
384
470
  const argsOf = (ctx: RpcContext): unknown =>
385
471
  SENT in ctx ? (ctx as { [SENT]: unknown })[SENT] : ctx.args()
@@ -22,13 +22,12 @@ export function seededDocument<Document>(
22
22
  | Document
23
23
  | Failed<string, unknown>
24
24
  | Promise<Document | Failed<string, unknown>> {
25
- const answer = answerOf(
26
- rpcRequest('GET', mounted(address), undefined),
27
- false,
28
- undefined,
29
- )
25
+ const request = rpcRequest('GET', mounted(address), undefined)
26
+ const answer = answerOf(request, false, undefined)
30
27
  return (
31
- answer instanceof Promise ? answer.then(answered) : answered(answer)
28
+ answer instanceof Promise
29
+ ? answer.then((settled) => answered(settled, request))
30
+ : answered(answer, request)
32
31
  ) as
33
32
  | Document
34
33
  | Failed<string, unknown>
@@ -0,0 +1,32 @@
1
+ import { isRecord } from './isRecord.ts'
2
+ import { runSchema, type Schema } from './Schema.ts'
3
+
4
+ /** The deadline a value written now with `ttl` runs out at, `null` where it never does (8.26). */
5
+ export function expiresAfter(ttl: number): number | null {
6
+ return Number.isFinite(ttl) ? Date.now() + ttl : null
7
+ }
8
+
9
+ /**
10
+ * The value a shipped store read back, `undefined` where its `ttl` has passed.
11
+ *
12
+ * 8.27 — THE `schema` A RESTORE SKIPS (8.5) RUNS HERE, on what was read: a refusal throws, which
13
+ * the value takes as a miss and warns about (8.15) — an entry an older build wrote is one an app
14
+ * wants to hear about rather than serve. Shared by `webStore` and the server's `sqliteStore`.
15
+ */
16
+ export function storedValue(
17
+ kept: unknown,
18
+ schema: Schema<unknown> | undefined,
19
+ where: string,
20
+ ): unknown {
21
+ if (!isRecord(kept) || !('value' in kept))
22
+ throw new Error(`${where} holds something no abide store wrote.`)
23
+ const expires = kept.expires
24
+ if (typeof expires === 'number' && expires <= Date.now()) return undefined
25
+ if (schema === undefined) return kept.value
26
+ const checked = runSchema(schema, kept.value)
27
+ if (checked.issues !== null)
28
+ throw new Error(
29
+ `${where} holds a value its schema refuses: ${JSON.stringify(checked.issues)}`,
30
+ )
31
+ return checked.value
32
+ }
@@ -0,0 +1,54 @@
1
+ import type { Store } from './reactive/index.ts'
2
+ import type { Schema } from './Schema.ts'
3
+ import { expiresAfter, storedValue } from './storedValue.ts'
4
+
5
+ /**
6
+ * A `Store` kept in this browser's `localStorage`, or its `sessionStorage`, under `key`.
7
+ *
8
+ * 8.23 — WHERE THERE IS NO WEB STORAGE, A SERVER, THE STORE IS INERT: every `get` a miss and every
9
+ * `set` nothing, so the value a server renders is the one it would render with no store (8.3).
10
+ * The storage is looked up on each call rather than held, since a browser that refuses storage
11
+ * throws on the lookup — and a throw there is 8.15's miss and 8.12's warning, not a broken module.
12
+ */
13
+ export function webStore<Stored>(
14
+ key: string,
15
+ options?: { area?: 'local' | 'session'; schema?: Schema<Stored> },
16
+ ): Store<Stored> {
17
+ const name = options?.area === 'session' ? 'sessionStorage' : 'localStorage'
18
+ const schema = options?.schema as Schema<unknown> | undefined
19
+ const where = `${name}[${JSON.stringify(key)}]`
20
+ const area = (): Storage | undefined =>
21
+ (globalThis as unknown as Record<string, Storage | undefined>)[name]
22
+ return {
23
+ get: () => {
24
+ const storage = area()
25
+ if (storage === undefined) return undefined
26
+ const text = storage.getItem(key)
27
+ if (text === null) return undefined
28
+ const value = storedValue(JSON.parse(text), schema, where)
29
+ // 8.26 — an entry past its deadline is gone, not merely skipped.
30
+ if (value === undefined) storage.removeItem(key)
31
+ return value as Stored | undefined
32
+ },
33
+ set: (value, retention) => {
34
+ area()?.setItem(
35
+ key,
36
+ JSON.stringify({ value, expires: expiresAfter(retention.ttl) }),
37
+ )
38
+ },
39
+ // 8.24 — another document's write arrives as a `storage` event; this document's own never does.
40
+ watch: (changed) => {
41
+ if (typeof globalThis.addEventListener !== 'function')
42
+ return () => {}
43
+ const listener = (event: StorageEvent): void => {
44
+ if (
45
+ event.storageArea === area() &&
46
+ (event.key === key || event.key === null)
47
+ )
48
+ changed()
49
+ }
50
+ globalThis.addEventListener('storage', listener)
51
+ return () => globalThis.removeEventListener('storage', listener)
52
+ },
53
+ }
54
+ }
package/src/ui/Router.ts CHANGED
@@ -105,7 +105,12 @@ export class Router {
105
105
  * nothing hydrates over it, and leaving it is a document load.
106
106
  */
107
107
  private readonly errorPage: boolean
108
- /** The place in this document's history of the entry the address bar stands at (`Entry`). */
108
+ /**
109
+ * The place in this document's history of the entry the address bar stands at (`Entry`).
110
+ *
111
+ * 23.28 — `route.index` IS THIS, moved where `route.url` is (`arrive`) rather than here: a back
112
+ * step moves this before the page it arrives at has loaded.
113
+ */
109
114
  private index: number
110
115
  /**
111
116
  * 30.29 — the scroll each entry was left at, by its `index`.
@@ -127,6 +132,14 @@ export class Router {
127
132
  * Read off the compiled `<style>` blocks. Nothing here looks at the document's stylesheets.
128
133
  */
129
134
  private readonly transitions: boolean
135
+ /**
136
+ * 30.38 — what settles each `step` still waiting on the browser to say it has arrived.
137
+ *
138
+ * Settled ALL AT ONCE by the next arrival, rather than one per `popstate`: a browser that folds
139
+ * two queued `history.go`s into one traversal fires one event, and a step waiting for a second
140
+ * would never settle.
141
+ */
142
+ private readonly stepping: (() => void)[]
130
143
 
131
144
  constructor(region: Region, routes: Compiled[], transitions: boolean) {
132
145
  this.region = region
@@ -146,6 +159,7 @@ export class Router {
146
159
  this.scrolls = []
147
160
  this.prefetched = new Set()
148
161
  this.transitions = transitions
162
+ this.stepping = []
149
163
  }
150
164
 
151
165
  /**
@@ -199,12 +213,31 @@ export class Router {
199
213
  * within the standing page, back over an in-page `#anchor` jump, is `follow`'s: nothing asked,
200
214
  * nothing remounted. 30.29 — the scroll is put back once the page it belongs to is mounted.
201
215
  */
202
- popped(): Promise<void> {
203
- return this.travel(
204
- location.href,
205
- { replace: true, keepScroll: true },
206
- this.stepped(),
207
- )
216
+ async popped(): Promise<void> {
217
+ try {
218
+ await this.travel(
219
+ location.href,
220
+ { replace: true, keepScroll: true },
221
+ this.stepped(),
222
+ )
223
+ } finally {
224
+ for (const arrived of this.stepping.splice(0)) arrived()
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Steps the history by `by` entries, settling once the entry stepped to is arrived at.
230
+ *
231
+ * 30.38 — THE BROWSER MOVES THE BAR LATER and says so only by `popstate`, so the step settles in
232
+ * `popped`, once the arriving page is mounted and its scroll put back. 30.39 — `history.go(0)`
233
+ * reloads the document, which no `navigate` does, so a step of none is over before it starts.
234
+ */
235
+ step(by: number): Promise<void> {
236
+ if (by === 0) return Promise.resolve()
237
+ return new Promise((arrived) => {
238
+ this.stepping.push(arrived)
239
+ history.go(by)
240
+ })
208
241
  }
209
242
 
210
243
  /** `go`, arriving as `step` says: a push, or a history step with the scroll it restores. */
@@ -313,7 +346,7 @@ export class Router {
313
346
  options.replace === true || target.href === location.href,
314
347
  [scrollX, scrollY],
315
348
  )
316
- arrive(target.href, found.route.pattern, found.params)
349
+ arrive(target.href, found.route.pattern, found.params, this.index)
317
350
  this.mounted = target.pathname
318
351
  if (step.scroll !== undefined) scrollTo(step.scroll[0], step.scroll[1])
319
352
  else if (options.keepScroll !== true && target.hash !== '')
@@ -500,7 +533,7 @@ export class Router {
500
533
  * 23.1 — WRITTEN BEFORE THE ARRIVING PAGE'S SETUP, which reads it.
501
534
  */
502
535
  private arriveAt(target: URL, found: Found<Compiled>): void {
503
- arrive(target.href, found.route.pattern, found.params)
536
+ arrive(target.href, found.route.pattern, found.params, this.index)
504
537
  this.standing = found.route
505
538
  this.mounted = target.pathname
506
539
  }
@@ -186,7 +186,7 @@ async function sendLine(): Promise<void> {
186
186
  retryLater()
187
187
  return
188
188
  }
189
- const value = answeredValue(answer)
189
+ const value = answeredValue(answer, call)
190
190
  if (isFailed(value)) {
191
191
  call.error = problemOf(value)
192
192
  await shelf.put(call)
package/src/ui/wire.ts CHANGED
@@ -101,7 +101,7 @@ export function wire(
101
101
  return standIn(value)
102
102
  }
103
103
  return enqueue(queued, standing as { value: unknown }, value).then(
104
- (kept) => (kept ? standIn(value) : answered(failed)),
104
+ (kept) => (kept ? standIn(value) : answered(failed, request)),
105
105
  )
106
106
  }
107
107
  // 16.83 — BEHIND CALLS NOT YET DELIVERED A CALL WAITS ITS TURN, rather than overtaking them.
@@ -120,9 +120,9 @@ export function wire(
120
120
  // asked of the network once there is one.
121
121
  if (answer.kept) {
122
122
  whenOnline(args, 0)
123
- return standIn(answered(answer))
123
+ return standIn(answered(answer, request))
124
124
  }
125
- return answered(answer)
125
+ return answered(answer, request)
126
126
  }
127
127
  const answer = answerOf(request, false, signal)
128
128
  return answer instanceof Promise ? answer.then(settle) : settle(answer)
@@ -153,7 +153,7 @@ export function wire(
153
153
  yield* answerChunks(answer.body, answer.framing)
154
154
  return
155
155
  }
156
- const value = answered(answer)
156
+ const value = answered(answer, request)
157
157
  if (isFailed(value)) throw value
158
158
  if (Array.isArray(value)) yield* value
159
159
  }
@@ -1,7 +0,0 @@
1
- /**
2
- * The value of the offline worker's `abide-keep` header on the page a navigation opens, which then
3
- * hydrates and so is seeded as one (41.29, 45.23) — a page saved behind the one opened is not.
4
- *
5
- * A leaf, because the server writes it into the worker's script and reads it off the request.
6
- */
7
- export const KEEP_OPENED = 'open'
File without changes