@weftui/dom 0.27.1 → 1.0.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 +1 -3
- package/docs/explanation/boundaries-and-suspense.md +2 -2
- package/docs/explanation/services-and-context.md +1 -1
- package/docs/how-to/add-routing.md +1 -1
- package/docs/how-to/provide-services.md +1 -1
- package/docs/reference/router.md +1 -1
- package/docs/tutorial/01-your-first-app.md +1 -3
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -9,11 +9,9 @@ Two entry points: `@weftui/dom/client` for the browser, `@weftui/dom/server` for
|
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npm install @weftui/core @weftui/dom effect
|
|
12
|
+
npm install @weftui/core @weftui/dom effect
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
Weft tracks Effect 4's beta line. This release is built and tested against `effect@4.0.0-beta.98`; the peer range accepts newer 4.0 betas, which may contain upstream breaking changes.
|
|
16
|
-
|
|
17
15
|
`effect` is a peer dependency; `@weftui/core` is required to author the tree.
|
|
18
16
|
|
|
19
17
|
## Key exports
|
|
@@ -38,9 +38,9 @@ The channel algebra is the whole reason they exist: `catchTag("Foo", …)` remov
|
|
|
38
38
|
|
|
39
39
|
The routing above describes what happens while a node is being built. Once mounted, a reactive region — an attribute, child, or list stream, or a hydrated equivalent — keeps running for the lifetime of its scope, and it can still fail later: a `Stream` backing a `Boundary.rpc` resource might raise `RouterNotFound` after a client-side navigation, for instance. If a `BoundaryContext` encloses the region, the failure routes to it exactly as above, and the boundary's fallback swaps in.
|
|
40
40
|
|
|
41
|
-
If no boundary encloses it, there is nothing to swap to. Weft does not synthesize one: the region's DOM keeps its last rendered content, and
|
|
41
|
+
If no boundary encloses it, there is nothing to swap to. Weft does not synthesize one: the region's DOM keeps its last rendered content, and the subscription fiber's failure exit is left **unobserved**. The Effect runtime itself then reports it — `"Fiber terminated with an unhandled error"` — because Weft raises that fiber's `FiberRef.unhandledErrorLogLevel` from the ambient default (`Debug`) to `LogLevel.Error` and annotates the log with `weft.region`, identifying the failing region by kind and identity (e.g. `attribute:class`, `child:stream-3`, `list:stream-2`, `hydrate:stream-1 (/products/42)`). This fires for typed failures and defects alike, in both dev and prod, exactly once per failing region. Interruption — the ordinary case of unmount tearing down the region's scope — is never reported; only genuine failures are.
|
|
42
42
|
|
|
43
|
-
This is deliberate: rather than
|
|
43
|
+
This is deliberate: rather than a Weft-specific error-reporting config, visibility is controlled by the same knobs any Effect program uses — `Logger.withMinimumLogLevel` to filter it, `Effect.withUnhandledErrorLogLevel` to change how loudly (or quietly) unhandled fiber exits are reported elsewhere in your program. A stream that can fail and has no enclosing boundary is a stream whose failures you've chosen not to route into the UI — the log is what tells you that decision has consequences at runtime.
|
|
44
44
|
|
|
45
45
|
## Suspense boundaries
|
|
46
46
|
|
|
@@ -29,7 +29,7 @@ Services flow **down** from that provide point to every reader, including across
|
|
|
29
29
|
|
|
30
30
|
## Layer lifetime at the mount
|
|
31
31
|
|
|
32
|
-
The `ThemeServiceLive` example above works because `mount`'s effect and the service's lifetime coincide by accident: `ThemeServiceLive` is a plain value layer with nothing to release, so it makes no difference whether it is "alive" for one tick or the whole session. That accident stops holding the moment the layer is **scoped** — built
|
|
32
|
+
The `ThemeServiceLive` example above works because `mount`'s effect and the service's lifetime coincide by accident: `ThemeServiceLive` is a plain value layer with nothing to release, so it makes no difference whether it is "alive" for one tick or the whole session. That accident stops holding the moment the layer is **scoped** — built with `Layer.scoped`, backed by an `acquireRelease` — because `mount`'s effect resolves right after the tree's **initial render**, not when the app stops running. Streams, event handlers, and forked work all keep running on the mount's runtime long after that Effect has settled.
|
|
33
33
|
|
|
34
34
|
`Effect.provide(scopedLayer)` is `acquireUseRelease` sugar: acquire, run the wrapped effect, then release **when that effect completes**. Wrap it directly around `mount`, and the release runs at mount-resolve — while the mounted tree is still reading from the now-disposed service:
|
|
35
35
|
|
|
@@ -280,7 +280,7 @@ export const handler = RouterServer.toWebHandler(App, { document: documentShell
|
|
|
280
280
|
|
|
281
281
|
### `effect/unstable/httpapi` is the spine
|
|
282
282
|
|
|
283
|
-
The tree is the authoring surface, but `effect/unstable/httpapi`'s `HttpApi` is the **single source of truth** for paths and schemas. Sealing the tree with `Router.router(...)` builds it once (`buildHttpApi`) and stamps it onto `def.httpApi`: a single `"pages"` group with one GET endpoint per leaf at its full path pattern, carrying `
|
|
283
|
+
The tree is the authoring surface, but `effect/unstable/httpapi`'s `HttpApi` is the **single source of truth** for paths and schemas. Sealing the tree with `Router.router(...)` builds it once (`buildHttpApi`) and stamps it onto `def.httpApi`: a single `"pages"` group with one GET endpoint per leaf at its full path pattern, carrying `setPath(pathSchema)`, `setUrlParams(querySchema)`, and a `RouterNotFound → 404` error. Both sides read that one definition, so they always agree:
|
|
284
284
|
|
|
285
285
|
- **Server** — `RouterServer` dispatches through `HttpApiBuilder` (platform owns request→leaf matching, path/query decode, and the 404 status).
|
|
286
286
|
- **Client** — `RouterLive` derives a real `HttpApiClient` from the same `def.httpApi` (exposed as `Router.httpApiClient`) for network work. SPA URL→leaf resolution stays **local** (there is no public client-side "match this URL against my `HttpApi`" utility in platform), fed from the same endpoint definitions so it never drifts from the server.
|
|
@@ -9,7 +9,7 @@ description: Provide plain and scoped Layers to a mounted app — the direct mou
|
|
|
9
9
|
|
|
10
10
|
**Goal:** provide a `Layer` to the mounted app so its components can read services with `yield* Service`.
|
|
11
11
|
|
|
12
|
-
Which recipe to reach for depends on whether the layer has anything to release.
|
|
12
|
+
Which recipe to reach for depends on whether the layer has anything to release. A plain value layer (`Layer.succeed`, `Layer.effect` with no `acquireRelease`) can be provided directly at the mount — there is nothing to leak. A **scoped** layer (`Layer.scoped`, anything backed by `acquireRelease`) needs the mount to outlive the effect's own resolution — see [Layer lifetime at the mount](https://weftui.dev/docs/explanation/services-and-context#layer-lifetime-at-the-mount) for why.
|
|
13
13
|
|
|
14
14
|
## Recipe 1 — plain value layers with `mount`
|
|
15
15
|
|
package/docs/reference/router.md
CHANGED
|
@@ -323,7 +323,7 @@ These power the runtime and are exported for tooling/tests; most apps never touc
|
|
|
323
323
|
| Export | Description |
|
|
324
324
|
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
325
325
|
| `compile(def)` | Walks a tree into flat `CompiledLeaf`s with merged path/query schemas and layout chains. |
|
|
326
|
-
| `buildHttpApi(leaves)` | Builds the authoritative `HttpApi` (one `"pages"` group, a GET endpoint per leaf with `
|
|
326
|
+
| `buildHttpApi(leaves)` | Builds the authoritative `HttpApi` (one `"pages"` group, a GET endpoint per leaf with `setPath`/`setUrlParams` + 404). Called by `Router.router`; the result is `def.httpApi`. |
|
|
327
327
|
| `leafRegistry` | `WeakMap<RouteNode, CompiledLeaf>` read by `href` to resolve a leaf's pattern/schemas. |
|
|
328
328
|
| `match(compiled, url)` | Resolves a URL to a `RouteMatch` (`Matched` with decoded `path`/`query`, or `NotFound`). |
|
|
329
329
|
| `compileMatchers(compiled)` | Precompiles per-leaf regex matchers. |
|
|
@@ -14,11 +14,9 @@ We assume you know [Effect](https://effect.website/docs/getting-started/introduc
|
|
|
14
14
|
## Install
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
npm install @weftui/core @weftui/dom effect
|
|
17
|
+
npm install @weftui/core @weftui/dom effect
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Weft tracks Effect 4's beta line. This release is built and tested against `effect@4.0.0-beta.98`; the peer range accepts newer 4.0 betas, which may contain upstream breaking changes.
|
|
21
|
-
|
|
22
20
|
`@weftui/core` gives you the element builders and combinators; `@weftui/dom` renders them (its `./client` entry mounts in the browser). `effect` is the peer everything is built on.
|
|
23
21
|
|
|
24
22
|
## Build a component
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weftui/dom",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "DOM renderer for Weft — mount and hydrate in the browser, render to string or stream on the server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dom",
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@weftui/core": "0.
|
|
47
|
+
"@weftui/core": "1.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/jsdom": "^28.0.3",
|
|
51
51
|
"@types/node": "^25.9.2",
|
|
52
|
-
"effect": "4.0.0-beta.
|
|
52
|
+
"effect": "4.0.0-beta.93",
|
|
53
53
|
"jsdom": "^29.1.1",
|
|
54
54
|
"tsx": "^4.22.4",
|
|
55
55
|
"typescript": "^6.0.3",
|
|
@@ -57,6 +57,6 @@
|
|
|
57
57
|
"vite-plus": "0.2.2"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"effect": "
|
|
60
|
+
"effect": "4.0.0-beta.93"
|
|
61
61
|
}
|
|
62
62
|
}
|