lit-ui-router-ssr 0.8.0 → 0.9.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/README.md +122 -15
- package/dist/adopt-context.d.ts +7 -1
- package/dist/adopt-context.d.ts.map +1 -1
- package/dist/adopt-context.js.map +1 -1
- package/dist/boot-pending.d.ts +22 -0
- package/dist/boot-pending.d.ts.map +1 -0
- package/dist/boot-pending.js +2 -0
- package/dist/boot-pending.js.map +1 -0
- package/dist/client.d.ts +82 -7
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +94 -21
- package/dist/client.js.map +1 -1
- package/dist/dev-warn.js +0 -1
- package/dist/dev-warn.js.map +1 -1
- package/dist/development/adopt-context.js.map +1 -1
- package/dist/development/boot-pending.js +2 -0
- package/dist/development/boot-pending.js.map +1 -0
- package/dist/development/client.js +107 -20
- package/dist/development/client.js.map +1 -1
- package/dist/development/index.js +2 -1
- package/dist/development/index.js.map +1 -1
- package/dist/development/light-element-renderer.js.map +1 -1
- package/dist/development/prerender.js +22 -57
- package/dist/development/prerender.js.map +1 -1
- package/dist/development/render.js +91 -0
- package/dist/development/render.js.map +1 -0
- package/dist/development/respond.js.map +1 -1
- package/dist/development/served-view.js +12 -3
- package/dist/development/served-view.js.map +1 -1
- package/dist/development/shadow-fallback-renderer.js +23 -0
- package/dist/development/shadow-fallback-renderer.js.map +1 -0
- package/dist/development/signature.js +1 -1
- package/dist/development/signature.js.map +1 -1
- package/dist/development/ui-view-renderer.js +12 -0
- package/dist/development/ui-view-renderer.js.map +1 -1
- package/dist/development/vite.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/light-element-renderer.d.ts +11 -2
- package/dist/light-element-renderer.d.ts.map +1 -1
- package/dist/light-element-renderer.js.map +1 -1
- package/dist/prerender.d.ts +30 -50
- package/dist/prerender.d.ts.map +1 -1
- package/dist/prerender.js +23 -52
- package/dist/prerender.js.map +1 -1
- package/dist/render.d.ts +169 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +86 -0
- package/dist/render.js.map +1 -0
- package/dist/respond.d.ts +12 -0
- package/dist/respond.d.ts.map +1 -1
- package/dist/respond.js.map +1 -1
- package/dist/served-view.d.ts.map +1 -1
- package/dist/served-view.js +0 -1
- package/dist/served-view.js.map +1 -1
- package/dist/shadow-fallback-renderer.d.ts +24 -0
- package/dist/shadow-fallback-renderer.d.ts.map +1 -0
- package/dist/shadow-fallback-renderer.js +14 -0
- package/dist/shadow-fallback-renderer.js.map +1 -0
- package/dist/signature.d.ts +6 -0
- package/dist/signature.d.ts.map +1 -1
- package/dist/signature.js +1 -1
- package/dist/signature.js.map +1 -1
- package/dist/ui-view-renderer.d.ts +9 -0
- package/dist/ui-view-renderer.d.ts.map +1 -1
- package/dist/ui-view-renderer.js +12 -0
- package/dist/ui-view-renderer.js.map +1 -1
- package/dist/vite.d.ts +31 -9
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js.map +1 -1
- package/package.json +2 -2
- package/src/adopt-context.ts +7 -1
- package/src/boot-pending.ts +30 -0
- package/src/client.ts +293 -42
- package/src/index.ts +12 -2
- package/src/light-element-renderer.ts +11 -2
- package/src/prerender.ts +81 -148
- package/src/render.ts +337 -0
- package/src/respond.ts +12 -0
- package/src/served-view.ts +13 -5
- package/src/shadow-fallback-renderer.ts +73 -0
- package/src/signature.ts +6 -0
- package/src/ui-view-renderer.ts +25 -0
- package/src/vite.ts +33 -13
package/README.md
CHANGED
|
@@ -24,8 +24,9 @@ imports the pre-1.0 renderer or re-derives the incantation.
|
|
|
24
24
|
on the page carries `defer-hydration` and renders nothing until the client's walk reaches it.
|
|
25
25
|
- **The hydration signature.** A page rendered from a template opens on a JSON data block,
|
|
26
26
|
`<script type="application/json" data-lit-ui-router-ssr>`, naming this package's version, the
|
|
27
|
-
state the router stood on, that state's url parameter values,
|
|
28
|
-
|
|
27
|
+
state the router stood on, that state's url parameter values, the fully qualified name of each
|
|
28
|
+
`<ui-view>` it drew a routed component into, and the resolved values `dehydrate` or the
|
|
29
|
+
`payload` hook draws. A page `renderShell` returns as a string is written as-is, without one.
|
|
29
30
|
- **The lit render inside the emit loop.** The loop itself — verdict to file name, redirect to
|
|
30
31
|
rules line, the `_redirects` file, delegating states skipped, tally, warnings for paths that
|
|
31
32
|
matched nothing — is
|
|
@@ -33,6 +34,8 @@ imports the pre-1.0 renderer or re-derives the incantation.
|
|
|
33
34
|
supplies the lit one and takes the same options, plus `router`, `renderShell`, `document`,
|
|
34
35
|
`root`, `elementRenderers`, `dehydrate`, `payload`, `responses` and `origin`. No SPA catch-all is ever written: one
|
|
35
36
|
turns every 404 into a 200.
|
|
37
|
+
- **One page for a host that owns the request.** `renderToString` is that render alone, for a
|
|
38
|
+
framework route or a worker that settles the router itself.
|
|
36
39
|
- **Response states after settle.** `responder` runs the handler bound to a response state's name
|
|
37
40
|
with the resolves its transition landed with.
|
|
38
41
|
- **`<ui-view>` on both sides.** `UiViewRenderer` fills the element's light DOM on the server;
|
|
@@ -57,6 +60,9 @@ install it when you import `lit-ui-router-ssr/client`. `lit-ui-router-ssr/vite`
|
|
|
57
60
|
The `lit-ui-router` peer is `^1.19.0`: the server renders a view through the helper `<ui-view>`
|
|
58
61
|
renders through, and the client hands a served class element to the view it wakes.
|
|
59
62
|
|
|
63
|
+
The `ui-router-server` peer is `^0.9.0`: `prerender` asks its `redirectedTo` whether a page's
|
|
64
|
+
`redirectTo` fired, and reads the status from the redirecting state's `redirectStatusCode`.
|
|
65
|
+
|
|
60
66
|
## Quick Start
|
|
61
67
|
|
|
62
68
|
```typescript
|
|
@@ -95,7 +101,8 @@ virtual fs instead.
|
|
|
95
101
|
`ui-router-server/vite`'s, with the DOM shim and `lit-ui-router-ssr/register` loaded before the
|
|
96
102
|
prerender script, and its `definePrerender` calls this package's `prerender` with the options the
|
|
97
103
|
script returns; [Prerender with Vite](https://lit-ui-router.dev/guides/prerender-with-vite) shows
|
|
98
|
-
both files in full.
|
|
104
|
+
both files in full. [Prerender with Eleventy](https://lit-ui-router.dev/guides/prerender-with-eleventy)
|
|
105
|
+
calls `prerender` from an Eleventy data file instead, and lets Eleventy write the pages.
|
|
99
106
|
|
|
100
107
|
## Static hosts add a trailing slash
|
|
101
108
|
|
|
@@ -124,7 +131,7 @@ A server render reads the router only once its transition has landed, resolves i
|
|
|
124
131
|
`settle(router, path)`, the `ui-router-server/ssr` step this package re-exports, sets the url, syncs
|
|
125
132
|
the router to it, and resolves with the transition that landed, so the synchronous render after it
|
|
126
133
|
reads every resolve. A `redirectTo` chain settles on its final state, and a path the router already
|
|
127
|
-
stands on resolves at once.
|
|
134
|
+
stands on resolves at once. `redirectedTo` reports where a redirected transition landed.
|
|
128
135
|
|
|
129
136
|
A page fails to land in four ways, and each rejects rather than hangs:
|
|
130
137
|
|
|
@@ -140,6 +147,85 @@ A page fails to land in four ways, and each rejects rather than hangs:
|
|
|
140
147
|
`settle()` never calls `router.start()`, which runs once per router: it drives `urlService`
|
|
141
148
|
directly, so a page loop calls it once per path on the same router, started or not.
|
|
142
149
|
|
|
150
|
+
## Page, response state or redirect: which decides when
|
|
151
|
+
|
|
152
|
+
A url's answer is decided at one of two points:
|
|
153
|
+
|
|
154
|
+
- **The verdict**, from the url alone, before any of the app's code runs. A pattern rule or a data
|
|
155
|
+
`redirectTo` answers a redirect, a state marked `response: true` a response state, a `delegate` a
|
|
156
|
+
host handler, and any other state a page.
|
|
157
|
+
- **Settle**, once the page's transition runs its resolves, hooks and `redirectTo` functions. They
|
|
158
|
+
can change only a page's answer: a `redirectTo` function can move the transition elsewhere, and a
|
|
159
|
+
resolve that rejects fails `settle`, which the host maps to an error page.
|
|
160
|
+
|
|
161
|
+
A response state suits a url whose pattern alone says it is not a page. When urls of one pattern
|
|
162
|
+
are sometimes a page and sometimes a redirect, such as a compare page whose reversed pair redirects
|
|
163
|
+
to the forward one, only a `redirectTo` function tells them apart.
|
|
164
|
+
|
|
165
|
+
The state whose `redirectTo` fires, data or function, declares the status in `redirectStatusCode`:
|
|
166
|
+
`301`, `302`, `303`, `307` or `308`, `302` by default. A redirect function often depends on data,
|
|
167
|
+
and browsers cache a permanent redirect with no expiry, so a redirect that never changes opts into
|
|
168
|
+
`308`. A pattern rule's redirect answers `302`.
|
|
169
|
+
|
|
170
|
+
After `settle`, `redirectedTo(router, transition)` returns `{ url, status }` for a transition a
|
|
171
|
+
redirect moved, a change of params alone included: the url it landed on, relative to the mount,
|
|
172
|
+
query included, and the redirecting state's `redirectStatusCode`. A live host answers with it:
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
import { redirectedTo, settle } from 'lit-ui-router-ssr';
|
|
176
|
+
|
|
177
|
+
// A shell verdict under /releases, on a router built for this request.
|
|
178
|
+
const redirect = redirectedTo(router, await settle(router, subpath));
|
|
179
|
+
|
|
180
|
+
if (redirect)
|
|
181
|
+
return new Response(null, {
|
|
182
|
+
status: redirect.status,
|
|
183
|
+
headers: { Location: `/releases${redirect.url}` },
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
`prerender` does the same after each `renderShell`: when the transition the hook landed was
|
|
188
|
+
redirected, the path gets a rules line in place of a page, counted in `tally.redirect`. A url rule
|
|
189
|
+
that rewrites the url, `when('/old', '/new')`, starts a new transition rather than redirecting one,
|
|
190
|
+
so `redirectedTo` reports nothing for it; declare it in the mount's `redirects`. See
|
|
191
|
+
[page, response state or redirect](https://lit-ui-router.dev/packages/ssr#page-response-state-or-redirect-which-decides-when).
|
|
192
|
+
|
|
193
|
+
## Rendering one page per request
|
|
194
|
+
|
|
195
|
+
A host that owns the request, such as a framework route or a worker, renders one page with
|
|
196
|
+
`renderToString(template, { router })`. It is the render `prerender()` runs for each page, hydration
|
|
197
|
+
signature and `deferHydration` included, so its markup is byte for byte what `prerender()` hands
|
|
198
|
+
`document` for the same template and router. The host settles the router, decides the response and
|
|
199
|
+
writes the document around the markup:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { redirectedTo, renderToString, settle } from 'lit-ui-router-ssr';
|
|
203
|
+
|
|
204
|
+
// `router` serves the mount at /releases; `subpath` is the request's path within it.
|
|
205
|
+
const redirect = redirectedTo(router, await settle(router, subpath));
|
|
206
|
+
|
|
207
|
+
if (redirect)
|
|
208
|
+
return new Response(null, {
|
|
209
|
+
status: redirect.status,
|
|
210
|
+
headers: { Location: `/releases${redirect.url}` },
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const { html } = renderToString(page(router), { router, dehydrate: {} });
|
|
214
|
+
|
|
215
|
+
return new Response(shell(html), {
|
|
216
|
+
status: router.globals.current.name === 'notFound' ? 404 : 200,
|
|
217
|
+
headers: { 'Content-Type': 'text/html; charset=utf-8' },
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The router must stand on the page before the call. It is provided on `root`, a fresh `EventTarget`
|
|
222
|
+
unless one is passed, for the render alone. `elementRenderers` and `dehydrate` act as `prerender()`'s
|
|
223
|
+
options of the same name, and `payload` takes a payload drawn by hand rather than a hook. The result's
|
|
224
|
+
`payload` reports the bytes the resolve payload adds to the signature and, under `dehydrate`, the
|
|
225
|
+
resolves left to re-run on the client.
|
|
226
|
+
|
|
227
|
+
The markup is collected into one string, synchronously. A streamed render would be a separate export.
|
|
228
|
+
|
|
143
229
|
## Response states
|
|
144
230
|
|
|
145
231
|
A [response state](https://lit-ui-router.dev/packages/server#response-states) answers with a
|
|
@@ -244,7 +330,9 @@ Post-processing of prerendered HTML keys on the [hydration signature](#the-clien
|
|
|
244
330
|
The use site opts in with `uiViewSlot()`, which is what reaches the renderer's light-DOM render and
|
|
245
331
|
commits nothing on the client:
|
|
246
332
|
|
|
247
|
-
```typescript
|
|
333
|
+
```typescript check
|
|
334
|
+
import { html } from 'lit';
|
|
335
|
+
import type { UIRouterLit } from 'lit-ui-router';
|
|
248
336
|
import { uiViewSlot } from 'lit-ui-router-ssr/client';
|
|
249
337
|
|
|
250
338
|
const page = (router: UIRouterLit) => html`
|
|
@@ -259,7 +347,7 @@ same strings with the hole empty and each `<ui-view>` fills itself.
|
|
|
259
347
|
|
|
260
348
|
Take a card that receives a post by property and draws it in its own `render()`:
|
|
261
349
|
|
|
262
|
-
```typescript
|
|
350
|
+
```typescript check
|
|
263
351
|
import { html, LitElement } from 'lit';
|
|
264
352
|
|
|
265
353
|
type Post = { title: string; summary: string };
|
|
@@ -369,6 +457,13 @@ parses, and hydration adopts them there. `LitElementRenderer` does the same for
|
|
|
369
457
|
on the page, whether or not it has anything to show on the server, which is the cost the default
|
|
370
458
|
avoids.
|
|
371
459
|
|
|
460
|
+
A shell element needs that list too: a shadow-DOM component that holds `<ui-view>` in its own
|
|
461
|
+
template, such as an `<app-root>`. Under the default it renders as its bare tag, empty, and the
|
|
462
|
+
views inside it are missing with it. With `LitElementRenderer` after `LightElementRenderer`, the
|
|
463
|
+
`<ui-view>` in its shadow root renders, hydrates and adopts. In development, `prerender()` and
|
|
464
|
+
`renderToString()` warn once per tag when a shadow-DOM `LitElement` reaches no renderer that draws
|
|
465
|
+
it; `<ui-router>`, whose shadow root is a bare slot, is left out.
|
|
466
|
+
|
|
372
467
|
## Registering the elements
|
|
373
468
|
|
|
374
469
|
A prerendered page needs the served `<ui-view>`, and `lit-ui-router-ssr/register` is the one import
|
|
@@ -442,7 +537,7 @@ registry holds no `<ui-view>`.
|
|
|
442
537
|
It imports `lit-ui-router/pure`, which registers nothing, and defines the served class under a tag
|
|
443
538
|
of its own:
|
|
444
539
|
|
|
445
|
-
```typescript
|
|
540
|
+
```typescript check
|
|
446
541
|
import { UiView } from 'lit-ui-router/pure';
|
|
447
542
|
import { withServedRender } from 'lit-ui-router-ssr/client';
|
|
448
543
|
|
|
@@ -470,12 +565,23 @@ const { outcome } = await bootstrap(router, root, page(router));
|
|
|
470
565
|
signature, starts the router, waits for the boot transition to land — following redirects to the
|
|
471
566
|
one that succeeds — then runs `hydrateRoot()`. The walk commits `.uiRouter` onto `<ui-router>` and
|
|
472
567
|
each `<ui-view>` re-seeks the router before its own first render, so every view finds the settled
|
|
473
|
-
router rather than the placeholder it registered against.
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
568
|
+
router rather than the placeholder it registered against. It resolves with `outcome` — `adopted`
|
|
569
|
+
or `cold`, what the root hydrate came to — `signature` (`BootstrapSignature`): `matched` when the
|
|
570
|
+
boot landed on the state and url parameters the signature names, `elsewhere` when the document
|
|
571
|
+
carried a signature and the boot landed somewhere else or landed no transition, and `absent` when
|
|
572
|
+
it carried none — and `views`, described next. Nothing constrains when
|
|
573
|
+
`lit-ui-router-ssr/register` is imported.
|
|
574
|
+
- **`views` says what each view came to.** A read-only map keyed by a view's fully qualified name
|
|
575
|
+
(`$default`, `$default.$default`, `$default.aside`) to a `BootstrapViewReport`: `outcome`, an
|
|
576
|
+
`AdoptOutcome` or `pending`, with the reporting `view` and, on `fell-back`, its `error`. It lists
|
|
577
|
+
every view the signature says the document was drawn with, then any other view that woke and
|
|
578
|
+
requested the adopter. Views are tracked by what they report to the adopter, whose request is a
|
|
579
|
+
composed event, so a view in a shadow root counts like any other. The call
|
|
580
|
+
resolves once the views that woke have updated, nested ones and those in shadow roots their hosts
|
|
581
|
+
hydrated included, and lists a drawn view that has not woken as `pending`. The map is a snapshot:
|
|
582
|
+
the adopter stays installed until every drawn view has reported, so a view whose host hydrates
|
|
583
|
+
later still adopts and still reaches `onAdopt`. A document that booted where it was drawn and
|
|
584
|
+
adopted none of its drawn views warns once in development.
|
|
479
585
|
- **The cold path is the same call.** A container with nothing to adopt is emptied and `value`
|
|
480
586
|
rendered into it before the router starts. A boot transition that fails, a url that starts none,
|
|
481
587
|
and a root `hydrate()` that throws over a mutated document all empty the container and render
|
|
@@ -543,7 +649,8 @@ const { outcome } = await bootstrap(router, root, page(router));
|
|
|
543
649
|
served nodes are the live ones — `fell-back` — a mismatch or a lost pair, with `detail.error`
|
|
544
650
|
carrying the cause — or `none`, nothing to adopt. It fires once per view, parent first, in
|
|
545
651
|
production as in development. The `onAdopt(view, outcome, error)` option of `bootstrap()` and `hydrateRoot()` receives
|
|
546
|
-
the same reports for every view its walk reaches, a view the pin adopts after the release included
|
|
652
|
+
the same reports for every view its walk reaches, a view the pin adopts after the release included,
|
|
653
|
+
and a view in a shadow root its host hydrates after the walk.
|
|
547
654
|
- **A mutated document throws.** `hydrateRoot()` rethrows what `hydrate()` threw, over a container it
|
|
548
655
|
first empties. The caller renders into it.
|
|
549
656
|
|
|
@@ -554,7 +661,7 @@ cycle with `LightDomHydrating(Base)` from `lit-ui-router-ssr/client`. `LightElem
|
|
|
554
661
|
`lit-ui-router-ssr`, one of `prerender()`'s default renderers, draws it on the server, and
|
|
555
662
|
`lightSlot()` marks the hole at the use site:
|
|
556
663
|
|
|
557
|
-
```typescript
|
|
664
|
+
```typescript check
|
|
558
665
|
import { html, LitElement } from 'lit';
|
|
559
666
|
import { property } from 'lit/decorators.js';
|
|
560
667
|
import { LightDomHydrating, lightSlot } from 'lit-ui-router-ssr/client';
|
package/dist/adopt-context.d.ts
CHANGED
|
@@ -38,7 +38,13 @@ export type AdoptUiViewContext = Context<AdoptUiViewContextKey, (view: Adoptable
|
|
|
38
38
|
* @example
|
|
39
39
|
* ```ts
|
|
40
40
|
* import { provideContext } from 'lit-ui-router/context';
|
|
41
|
-
* import {
|
|
41
|
+
* import {
|
|
42
|
+
* adoptUiViewContext,
|
|
43
|
+
* type AdoptableView,
|
|
44
|
+
* } from 'lit-ui-router-ssr/client';
|
|
45
|
+
*
|
|
46
|
+
* declare const container: HTMLElement;
|
|
47
|
+
* declare function adopt(view: AdoptableView): void;
|
|
42
48
|
*
|
|
43
49
|
* const uninstall = provideContext(container, adoptUiViewContext, (view) =>
|
|
44
50
|
* adopt(view),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adopt-context.d.ts","mappings":"AACA,cAAc,qBAAqB;AACnC,cAAc,eAAe;;;;;AAM7B,iBAAiB,sBAAsB;;UAE5B,MAAM;AACjB;;;;;AAMA,iBAAiB,sBAAsB,YAAY;;CAGjD;;UAES,eAAe;AAC1B;;;;;;AAOA,YAAY,qBAAqB,QAC/B,wBACC,MAAM
|
|
1
|
+
{"version":3,"file":"adopt-context.d.ts","mappings":"AACA,cAAc,qBAAqB;AACnC,cAAc,eAAe;;;;;AAM7B,iBAAiB,sBAAsB;;UAE5B,MAAM;AACjB;;;;;AAMA,iBAAiB,sBAAsB,YAAY;;CAGjD;;UAES,eAAe;AAC1B;;;;;;AAOA,YAAY,qBAAqB,QAC/B,wBACC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BT,OAAO,cAAM,oBAAoB","names":[],"ignoreList":[],"sources":["../src/adopt-context.ts"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adopt-context.js","mappings":"
|
|
1
|
+
{"version":3,"file":"adopt-context.js","mappings":"AA+DA,OAAO,MAAM,qBAAyC,OAAO,OAAO,EAClE,MAAM,0CACR,CAAC","names":[],"ignoreList":[],"sources":["../src/adopt-context.ts"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Context } from "lit-ui-router/context";
|
|
2
|
+
/** The identity of {@link bootPendingContext}. */
|
|
3
|
+
interface BootPendingContextKey {
|
|
4
|
+
/** Names the key for a debugger; identity, not this string, is what matches. */
|
|
5
|
+
readonly name: "lit-ui-router-ssr/context#boot-pending";
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The boot-pending key: a pending `bootstrap()` answers with a function that
|
|
9
|
+
* takes the view's check and runs it again once its walk has settled.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export type BootPendingContext = Context<BootPendingContextKey, (recheck: () => void) => void>;
|
|
14
|
+
/**
|
|
15
|
+
* Answered under a container while a `bootstrap()` over it has yet to settle
|
|
16
|
+
* its walk, in development only.
|
|
17
|
+
*
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
export declare const bootPendingContext: BootPendingContext;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=boot-pending.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boot-pending.d.ts","mappings":"AACA,cAAc,eAAe;;UAGnB,sBAAsB;;UAErB,MAAM;AACjB;;;;;;;AAQA,YAAY,qBAAqB,QAC/B,wBACC;;;;;;;AAUH,OAAO,cAAM,oBAAoB","names":[],"ignoreList":[],"sources":["../src/boot-pending.ts"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boot-pending.js","mappings":"AA2BA,OAAO,MAAM,qBAAyC,OAAO,OAAO,EAClE,MAAM,yCACR,CAAC","names":[],"ignoreList":[],"sources":["../src/boot-pending.ts"]}
|
package/dist/client.d.ts
CHANGED
|
@@ -86,6 +86,12 @@ declare global {
|
|
|
86
86
|
*
|
|
87
87
|
* @example
|
|
88
88
|
* ```ts
|
|
89
|
+
* import { html } from 'lit';
|
|
90
|
+
* import type { UIRouterLit } from 'lit-ui-router';
|
|
91
|
+
* import { uiViewSlot } from 'lit-ui-router-ssr/client';
|
|
92
|
+
*
|
|
93
|
+
* declare const router: UIRouterLit;
|
|
94
|
+
*
|
|
89
95
|
* html`<ui-router .uiRouter=${router}><ui-view>${uiViewSlot()}</ui-view></ui-router>`;
|
|
90
96
|
* ```
|
|
91
97
|
*/
|
|
@@ -101,6 +107,11 @@ export declare const uiViewSlot: typeof renderLight;
|
|
|
101
107
|
*
|
|
102
108
|
* @example
|
|
103
109
|
* ```ts
|
|
110
|
+
* import { html } from 'lit';
|
|
111
|
+
* import { lightSlot } from 'lit-ui-router-ssr/client';
|
|
112
|
+
*
|
|
113
|
+
* declare const title: string;
|
|
114
|
+
*
|
|
104
115
|
* html`<app-card .title=${title}>${lightSlot()}</app-card>`;
|
|
105
116
|
* ```
|
|
106
117
|
*/
|
|
@@ -123,6 +134,13 @@ export declare const lightSlot: typeof renderLight;
|
|
|
123
134
|
* @example
|
|
124
135
|
* ```ts
|
|
125
136
|
* import { hydrateRoot, readHydrationSignature } from 'lit-ui-router-ssr/client';
|
|
137
|
+
* import type { TemplateResult } from 'lit';
|
|
138
|
+
* import type { UIRouterLit } from 'lit-ui-router';
|
|
139
|
+
*
|
|
140
|
+
* declare const booted: Promise<void>;
|
|
141
|
+
* declare const root: HTMLElement;
|
|
142
|
+
* declare const router: UIRouterLit;
|
|
143
|
+
* declare function page(router: UIRouterLit): TemplateResult;
|
|
126
144
|
*
|
|
127
145
|
* await booted;
|
|
128
146
|
* const { state } = readHydrationSignature(root) ?? {};
|
|
@@ -149,6 +167,10 @@ export declare function readHydrationSignature(container: ParentNode): Hydration
|
|
|
149
167
|
* ```ts
|
|
150
168
|
* import { readResolvePayload } from 'lit-ui-router-ssr/client';
|
|
151
169
|
* import { seed } from 'ui-router-server/ssr/client';
|
|
170
|
+
* import type { UIRouterLit } from 'lit-ui-router';
|
|
171
|
+
*
|
|
172
|
+
* declare const root: HTMLElement;
|
|
173
|
+
* declare const router: UIRouterLit;
|
|
152
174
|
*
|
|
153
175
|
* seed(router, readResolvePayload(root));
|
|
154
176
|
* router.start();
|
|
@@ -216,6 +238,13 @@ export declare function readResolvePayload(container: ParentNode): ResolvePayloa
|
|
|
216
238
|
* @example
|
|
217
239
|
* ```ts
|
|
218
240
|
* import { hydrateRoot } from 'lit-ui-router-ssr/client';
|
|
241
|
+
* import { render, type TemplateResult } from 'lit';
|
|
242
|
+
* import type { UIRouterLit } from 'lit-ui-router';
|
|
243
|
+
*
|
|
244
|
+
* declare const booted: Promise<void>;
|
|
245
|
+
* declare const root: HTMLElement;
|
|
246
|
+
* declare const router: UIRouterLit;
|
|
247
|
+
* declare function page(router: UIRouterLit): TemplateResult;
|
|
219
248
|
*
|
|
220
249
|
* await booted;
|
|
221
250
|
* const release = hydrateRoot(root, page(router));
|
|
@@ -246,17 +275,45 @@ export type BootstrapOutcome = "adopted" | "cold";
|
|
|
246
275
|
* still compared, though the container renders cold.
|
|
247
276
|
*/
|
|
248
277
|
export type BootstrapSignature = "matched" | "elsewhere" | "absent";
|
|
278
|
+
/**
|
|
279
|
+
* What one view came to, as {@link BootstrapResult.views} reports it: its
|
|
280
|
+
* {@link AdoptOutcome}, or `pending` for a view the document was drawn with
|
|
281
|
+
* that had not woken when {@link bootstrap} resolved.
|
|
282
|
+
*/
|
|
283
|
+
export type BootstrapViewOutcome = AdoptOutcome | "pending";
|
|
284
|
+
/** One view's entry in {@link BootstrapResult.views}. */
|
|
285
|
+
export interface BootstrapViewReport {
|
|
286
|
+
/** What the view came to; see {@link BootstrapViewOutcome}. */
|
|
287
|
+
readonly outcome: BootstrapViewOutcome;
|
|
288
|
+
/** The view that reported; absent on a `pending` one. */
|
|
289
|
+
readonly view?: Element;
|
|
290
|
+
/** What `hydrate()` threw, or why the view did not adopt; present only on `fell-back`. */
|
|
291
|
+
readonly error?: unknown;
|
|
292
|
+
}
|
|
249
293
|
/** What {@link bootstrap} resolves with. */
|
|
250
294
|
export interface BootstrapResult {
|
|
251
295
|
/**
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
296
|
+
* What the root hydrate came to, not each view. `adopted`: the served
|
|
297
|
+
* document was hydrated, and each served view reported its own {@link
|
|
298
|
+
* AdoptOutcome}, which {@link BootstrapResult.views} collects; a document
|
|
299
|
+
* whose views all rendered cold still reports `adopted` here. `cold`: the
|
|
300
|
+
* container was emptied and the template rendered into it.
|
|
255
301
|
*/
|
|
256
302
|
readonly outcome: BootstrapOutcome;
|
|
257
303
|
/** How the boot compares with the document's hydration signature; see {@link BootstrapSignature}. */
|
|
258
304
|
readonly signature: BootstrapSignature;
|
|
259
305
|
/**
|
|
306
|
+
* Each served view's outcome, keyed by the view's fully qualified name
|
|
307
|
+
* (`$default`, `$default.$default`, `$default.aside`): every view the
|
|
308
|
+
* signature says the document was drawn with, in the order it lists them,
|
|
309
|
+
* then any other view that woke and requested the adopter, such as one that
|
|
310
|
+
* woke with no served render. A drawn view not yet woken is `pending`; the
|
|
311
|
+
* first view to report under a name holds it. A snapshot taken as the call
|
|
312
|
+
* resolves: a view that adopts later still reports to `onAdopt` and its
|
|
313
|
+
* {@link UiViewAdoptEvent}. Empty on a cold boot.
|
|
314
|
+
*/
|
|
315
|
+
readonly views: ReadonlyMap<string, BootstrapViewReport>;
|
|
316
|
+
/**
|
|
260
317
|
* The boot transition's `Rejection`, or what the root `hydrate()` threw;
|
|
261
318
|
* present only on a cold boot that one of them caused.
|
|
262
319
|
*/
|
|
@@ -309,13 +366,31 @@ export interface BootstrapOptions extends HydrateRootOptions, SeedOptions {
|
|
|
309
366
|
* mutated document, does the same. The call resolves rather than rejects.
|
|
310
367
|
*
|
|
311
368
|
* Every served view still reports its own {@link AdoptOutcome}, as a {@link
|
|
312
|
-
* UiViewAdoptEvent} and to `options.onAdopt
|
|
313
|
-
*
|
|
314
|
-
* adopter
|
|
369
|
+
* UiViewAdoptEvent} and to `options.onAdopt`, and the result collects them in
|
|
370
|
+
* {@link BootstrapResult.views}. Views are tracked by what they report to the
|
|
371
|
+
* adopter, whose request is a composed event, so a view in a shadow root is
|
|
372
|
+
* reported like any other; nothing queries the document for views. The call
|
|
373
|
+
* waits until the views awake under the boot have
|
|
374
|
+
* updated, nested views and views in shadow roots their hosts hydrated
|
|
375
|
+
* included, and resolves then, reporting a view the signature lists that has
|
|
376
|
+
* not woken as `pending`. The adopter stays installed on `container` until
|
|
377
|
+
* every view the signature lists has reported, so a view whose host hydrates
|
|
378
|
+
* later still adopts and still reaches `onAdopt`; a view the app detached
|
|
379
|
+
* keeps its pin. A signed document that booted where it was drawn and adopted
|
|
380
|
+
* none of the views it was drawn with warns once in development.
|
|
381
|
+
*
|
|
382
|
+
* In development a sleeping view's "still asleep" warning stands down while
|
|
383
|
+
* the boot transition runs, and is checked again once the walk has settled.
|
|
315
384
|
*
|
|
316
385
|
* @example
|
|
317
386
|
* ```ts
|
|
318
387
|
* import { bootstrap } from 'lit-ui-router-ssr/client';
|
|
388
|
+
* import type { TemplateResult } from 'lit';
|
|
389
|
+
* import type { UIRouterLit } from 'lit-ui-router';
|
|
390
|
+
*
|
|
391
|
+
* declare const root: HTMLElement;
|
|
392
|
+
* declare const router: UIRouterLit;
|
|
393
|
+
* declare function page(router: UIRouterLit): TemplateResult;
|
|
319
394
|
*
|
|
320
395
|
* const { outcome } = await bootstrap(router, root, page(router));
|
|
321
396
|
* ```
|
|
@@ -324,7 +399,7 @@ export interface BootstrapOptions extends HydrateRootOptions, SeedOptions {
|
|
|
324
399
|
* @param container - the element the server's markup was written into, or an empty one
|
|
325
400
|
* @param value - the same template the server rendered, with every `<ui-view>` hole empty
|
|
326
401
|
* @param options - lit render options, `onAdopt`, and the boot transition's `payload` and `transport`
|
|
327
|
-
* @returns what the boot came to, once
|
|
402
|
+
* @returns what the boot came to, and what each view came to, once the awake views have updated
|
|
328
403
|
* @throws what `router.start()` throws, as on a router already started
|
|
329
404
|
* @throws the `TypeError` `seed` throws on a payload with no `resolves`, before the router starts
|
|
330
405
|
*/
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","mappings":"AAQA,SAAS,mBAAmB;AAK5B,cAAyB,qBAAqB;AAM9C,cAAc,mBAAmB;AAEjC,cAAc,gBAAgB,mBAAmB;
|
|
1
|
+
{"version":3,"file":"client.d.ts","mappings":"AAQA,SAAS,mBAAmB;AAK5B,cAAyB,qBAAqB;AAM9C,cAAc,mBAAmB;AAEjC,cAAc,gBAAgB,mBAAmB;AAajD,cAAc,0BAA0B;AAExC,SACE,yBACK,oBACA,yBACA,6BACA;AAEP,SACE,wBACK,mBACA,yBACL,iBACA,wBACK;AAEP,SACE,wBACK,mCACA,+BACA,6BACA;AAEP,cAAc,0BAA0B;;;;;;;;;;;AAexC,YAAY,eAAe,YAAY,cAAc;;;;;AAMrD,OAAO,cAAM,sBAAuB;;;;AAKpC,iBAAiB,kBAAkB;;UAExB,SAAS;;UAET;AACX;;;;;AAMA,YAAY,mBAAmB,YAAY;;;;;;AAO3C,OAAO,cAAM,wBAAyB;;AAGtC,YAAY,qBAAqB,YAAY;;;;AAK7C,YAAY,iBACV,MAAM,SACN,SAAS,cAET;;;;;AAOF,iBAAiB,2BAA2B,cAAc;;;;;;CAMxD,UAAU;AACZ;eAEe;WACH,oBAAoB;;EAE5B,iBAAiB;;EAEjB,mBAAmB;CACrB;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsEA,OAAO,cAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;AAqBhC,OAAO,cAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAka/B,OAAO,iBAAS,uBACd,WAAW,aACV;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCH,OAAO,iBAAS,mBACd,WAAW,aACV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkKH,OAAO,iBAAS,YACd,WAAW,aAEX,gBACA,UAAS,qBACR;;AAsCH,YAAY,mBAAmB,YAAY;;;;;;;;;;;;;;;;AAiB3C,YAAY,qBAAqB,YAAY,cAAc;;;;;;AAO3D,YAAY,uBAAuB,eAAe;;AAGlD,iBAAiB,oBAAoB;;UAE1B,SAAS;;UAET,OAAO;;UAEP;AACX;;AAGA,iBAAiB,gBAAgB;;;;;;;;UAQtB,SAAS;;UAET,WAAW;;;;;;;;;;;UAWX,OAAO,oBAAoB;;;;;UAK3B;AACX;;;;;AAMA,iBAAiB,yBAAyB,oBAAoB,YAAY;;;;;;;UAO/D,UAAU;AACrB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoUA,OAAO,iBAAe,UACpB,QAAQ,aACR,WAAW,aAEX,gBACA,UAAS,mBACR,QAAQ","names":[],"ignoreList":[],"sources":["../src/client.ts"]}
|
package/dist/client.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { hydrate } from "@lit-labs/ssr-client";
|
|
2
2
|
import { renderLight } from "@lit-labs/ssr-client/directives/render-light.js";
|
|
3
|
-
import { isFunction, RejectType } from "@uirouter/core";
|
|
3
|
+
import { isFunction, isString, RejectType } from "@uirouter/core";
|
|
4
4
|
import { noChange, render } from "lit";
|
|
5
5
|
import { directive } from "lit/directive.js";
|
|
6
6
|
import { getDirectiveClass } from "lit/directive-helpers.js";
|
|
7
|
-
import { provideContext } from "lit-ui-router/context";
|
|
7
|
+
import { provideContext, requestContext } from "lit-ui-router/context";
|
|
8
8
|
import { UiView } from "lit-ui-router/pure";
|
|
9
9
|
import { seed } from "ui-router-server/ssr/client";
|
|
10
|
-
import "#dev-gate";
|
|
11
10
|
import { adoptUiViewContext } from "./adopt-context.js";
|
|
12
11
|
import { isLightDomElement } from "./light-dom-brand.js";
|
|
13
12
|
import { servedMarkerPrefix } from "./served-markers.js";
|
|
@@ -37,7 +36,7 @@ class UiViewSlotDirective extends RenderLightDirective {
|
|
|
37
36
|
}
|
|
38
37
|
export const uiViewSlot = directive(UiViewSlotDirective);
|
|
39
38
|
export const lightSlot = uiViewSlot;
|
|
40
|
-
let walkPolicy
|
|
39
|
+
let walkPolicy;
|
|
41
40
|
const walkWith = (policy, walk) => {
|
|
42
41
|
const outer = walkPolicy;
|
|
43
42
|
walkPolicy = policy;
|
|
@@ -153,7 +152,10 @@ const pinAdopter = (view, policy) => {
|
|
|
153
152
|
let release = () => {};
|
|
154
153
|
release = provideContext(view, adoptUiViewContext, (woken) => {
|
|
155
154
|
if (woken === view) release();
|
|
156
|
-
adopt(woken, policy);
|
|
155
|
+
if (policy) return adopt(woken, policy);
|
|
156
|
+
const above = requestContext(view.parentNode, adoptUiViewContext);
|
|
157
|
+
if (above) return above(woken);
|
|
158
|
+
adopt(woken, {});
|
|
157
159
|
});
|
|
158
160
|
};
|
|
159
161
|
const isHydrationSignature = (value) => typeof value === "object" && value !== null && "version" in value && typeof value.version === "string";
|
|
@@ -257,15 +259,67 @@ const drawnView = (signature, router) => (view) => {
|
|
|
257
259
|
return Object.entries(urlParamsOf(state, router.globals.params)).every(([id, value]) => JSON.stringify(value) === JSON.stringify(drawnParams[id]));
|
|
258
260
|
};
|
|
259
261
|
const signatureMatches = (signature, router) => JSON.stringify([signature.state, signature.params]) === JSON.stringify(routeOf(router.globals));
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
262
|
+
const noneAdopted = (reports) => !reports.some(({ outcome }) => outcome === "adopted");
|
|
263
|
+
const checkSomeAdopted = (tracker) => {
|
|
264
|
+
const reports = tracker.drawnReports();
|
|
265
|
+
if (reports.length === 0 || !noneAdopted(reports)) return;
|
|
266
|
+
if (reports.some(({ outcome }) => outcome !== "pending")) return tracker.snapshot(), void 0;
|
|
267
|
+
tracker.whenDrawnReported(() => {
|
|
268
|
+
if (noneAdopted(tracker.drawnReports())) tracker.snapshot();
|
|
269
|
+
});
|
|
270
|
+
};
|
|
271
|
+
const drawnViewsOf = (signature) => Array.isArray(signature.views) ? signature.views.filter(isString) : [];
|
|
272
|
+
const trackViews = (drawn, onward) => {
|
|
273
|
+
const reports = new Map();
|
|
274
|
+
const waiting = new Set(drawn);
|
|
275
|
+
const awake = [];
|
|
276
|
+
const done = [];
|
|
277
|
+
const settle = () => {
|
|
278
|
+
if (waiting.size > 0) return;
|
|
279
|
+
for (const run of done.splice(0)) run();
|
|
280
|
+
};
|
|
281
|
+
const reporter = (view, outcome, error) => {
|
|
282
|
+
if (view instanceof UiView) awake.push(view);
|
|
283
|
+
const name = view instanceof UiView ? view.fqn : void 0;
|
|
284
|
+
if (name !== void 0 && !reports.has(name)) {
|
|
285
|
+
reports.set(name, outcome === "fell-back" ? {
|
|
286
|
+
outcome,
|
|
287
|
+
view,
|
|
288
|
+
error
|
|
289
|
+
} : {
|
|
290
|
+
outcome,
|
|
291
|
+
view
|
|
292
|
+
});
|
|
293
|
+
waiting.delete(name);
|
|
294
|
+
settle();
|
|
295
|
+
}
|
|
296
|
+
onward(view, outcome, error);
|
|
297
|
+
};
|
|
298
|
+
const drawnEntries = () => drawn.map((name) => [name, reports.get(name) ?? { outcome: "pending" }]);
|
|
299
|
+
return {
|
|
300
|
+
reporter,
|
|
301
|
+
awake: () => awake,
|
|
302
|
+
snapshot: () => new Map([...drawnEntries(), ...reports]),
|
|
303
|
+
drawnReports: () => drawnEntries().map(([, report]) => report),
|
|
304
|
+
whenDrawnReported: (run) => {
|
|
305
|
+
done.push(run);
|
|
306
|
+
settle();
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
};
|
|
310
|
+
const nextTask = () => new Promise((resolve) => {
|
|
311
|
+
setTimeout(resolve, 0);
|
|
312
|
+
});
|
|
313
|
+
const settleReports = async (tracker) => {
|
|
314
|
+
for (let seen = -1; seen !== tracker.awake().length;) {
|
|
315
|
+
seen = tracker.awake().length;
|
|
316
|
+
await nextTask();
|
|
317
|
+
await Promise.all(tracker.awake().map((view) => view.updateComplete));
|
|
267
318
|
}
|
|
268
319
|
};
|
|
320
|
+
const holdAsleepWarnings = (container) => {
|
|
321
|
+
return () => {};
|
|
322
|
+
};
|
|
269
323
|
const renderCold = (container, value, renderOptions) => {
|
|
270
324
|
makeCold(container);
|
|
271
325
|
render(value, container, renderOptions);
|
|
@@ -279,31 +333,46 @@ export async function bootstrap(router, container, value, options = {}) {
|
|
|
279
333
|
renderCold(container, value, renderOptions);
|
|
280
334
|
const landing = await startBoot(router);
|
|
281
335
|
disarm();
|
|
282
|
-
await
|
|
336
|
+
await nextTask();
|
|
283
337
|
return {
|
|
284
338
|
outcome: "cold",
|
|
285
339
|
signature: compareSignature(served, landing, router),
|
|
340
|
+
views: new Map(),
|
|
286
341
|
...pickError(landing)
|
|
287
342
|
};
|
|
288
343
|
}
|
|
344
|
+
const rearm = holdAsleepWarnings(container);
|
|
345
|
+
try {
|
|
346
|
+
return await bootServed(router, container, value, signature, {
|
|
347
|
+
onAdopt,
|
|
348
|
+
renderOptions,
|
|
349
|
+
disarm
|
|
350
|
+
});
|
|
351
|
+
} finally {
|
|
352
|
+
rearm();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
const bootServed = async (router, container, value, signature, { onAdopt, renderOptions, disarm }) => {
|
|
289
356
|
const landing = await startBoot(router);
|
|
290
357
|
disarm();
|
|
291
358
|
if (!("transition" in landing)) {
|
|
292
359
|
renderCold(container, value, renderOptions);
|
|
293
|
-
await
|
|
360
|
+
await nextTask();
|
|
294
361
|
return {
|
|
295
362
|
outcome: "cold",
|
|
296
363
|
signature: "elsewhere",
|
|
364
|
+
views: new Map(),
|
|
297
365
|
...pickError(landing)
|
|
298
366
|
};
|
|
299
367
|
}
|
|
300
368
|
const compared = compareSignature(signature, landing, router);
|
|
301
369
|
const drawn = compared === "matched";
|
|
302
370
|
let fellBack = 0;
|
|
303
|
-
const
|
|
371
|
+
const tracker = trackViews(drawnViewsOf(signature), (view, outcome, error) => {
|
|
304
372
|
if (outcome === "fell-back") fellBack += 1;
|
|
305
373
|
onAdopt?.(view, outcome, error);
|
|
306
|
-
};
|
|
374
|
+
});
|
|
375
|
+
const { reporter } = tracker;
|
|
307
376
|
let release;
|
|
308
377
|
try {
|
|
309
378
|
release = adoptRoot(container, value, renderOptions, drawn ? {
|
|
@@ -316,21 +385,25 @@ export async function bootstrap(router, container, value, options = {}) {
|
|
|
316
385
|
});
|
|
317
386
|
} catch (error) {
|
|
318
387
|
render(value, container, renderOptions);
|
|
319
|
-
await
|
|
388
|
+
await nextTask();
|
|
320
389
|
return {
|
|
321
390
|
outcome: "cold",
|
|
322
391
|
signature: compared,
|
|
392
|
+
views: new Map(),
|
|
323
393
|
error
|
|
324
394
|
};
|
|
325
395
|
}
|
|
326
|
-
await
|
|
327
|
-
release
|
|
396
|
+
await settleReports(tracker);
|
|
397
|
+
tracker.whenDrawnReported(release);
|
|
398
|
+
const views = tracker.snapshot();
|
|
328
399
|
if (fellBack > 0 && signature.state !== router.globals.current.name);
|
|
400
|
+
if (drawn) checkSomeAdopted(tracker);
|
|
329
401
|
return {
|
|
330
402
|
outcome: "adopted",
|
|
331
|
-
signature: compared
|
|
403
|
+
signature: compared,
|
|
404
|
+
views
|
|
332
405
|
};
|
|
333
|
-
}
|
|
406
|
+
};
|
|
334
407
|
const compareSignature = (signature, landing, router) => {
|
|
335
408
|
if (!signature) return "absent";
|
|
336
409
|
return "transition" in landing && signatureMatches(signature, router) ? "matched" : "elsewhere";
|