@weftui/router 0.27.0 → 0.27.1

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 CHANGED
@@ -9,9 +9,11 @@ Three entry points mirror `@weftui/dom`: `@weftui/router` (authoring + universal
9
9
  ## Installation
10
10
 
11
11
  ```bash
12
- npm install @weftui/core @weftui/dom @weftui/router effect
12
+ npm install @weftui/core @weftui/dom @weftui/router effect@beta
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
+
15
17
  `effect` is a peer dependency; `@weftui/core` and `@weftui/dom` provide the tree and renderer.
16
18
 
17
19
  ## Key exports
@@ -1,5 +1,5 @@
1
- import { S as Router, b as NavState, i as RouterDef, m as RouteNode, u as Fields, x as NavigateOptions } from "../compile-DWdMZiMt.js";
2
- import { n as outletNode, r as HrefArgs, t as RouterApp } from "../outlet-BiFb5gdK.js";
1
+ import { S as Router, b as NavState, i as RouterDef, m as RouteNode, u as Fields, x as NavigateOptions } from "../compile-BJFIgBbE.js";
2
+ import { n as outletNode, r as HrefArgs, t as RouterApp } from "../outlet-eoUQ-W0k.js";
3
3
  import { Effect, Layer, Scope } from "effect";
4
4
  import { AppRpcClientTag } from "@weftui/core";
5
5
  import { RpcGroup } from "effect/unstable/rpc";
@@ -1,5 +1,5 @@
1
- import { a as Router, i as setResolvedCommit, n as outletNode, o as getPreload, r as preRunLeaf, t as RouterApp } from "../outlet-ty5ZYKBW.js";
2
- import { r as match, t as href } from "../href-DD8PoCGO.js";
1
+ import { a as Router, i as setResolvedCommit, n as outletNode, o as getPreload, r as preRunLeaf, t as RouterApp } from "../outlet-C9N4a4_F.js";
2
+ import { r as match, t as href } from "../href-uvJ6b7zz.js";
3
3
  import { HttpApiClient } from "effect/unstable/httpapi";
4
4
  import { Context, Effect, Exit, Fiber, Layer, Option, Schema, Scope, Stream, SubscriptionRef } from "effect";
5
5
  import { AppRpcClientTag, Subscribable } from "@weftui/core";
@@ -66,9 +66,9 @@ interface MatcherEntry {
66
66
  readonly leaf: CompiledLeaf;
67
67
  readonly regex: RegExp;
68
68
  readonly paramNames: readonly string[];
69
- /** Path-param schema, read from the endpoint's `setPath` slot. */
69
+ /** Path-param schema, read from the endpoint's `params` slot. */
70
70
  readonly pathSchema: ParamSchema;
71
- /** Query schema, read from the endpoint's `setUrlParams` slot. */
71
+ /** Query schema, read from the endpoint's `query` slot. */
72
72
  readonly querySchema: ParamSchema;
73
73
  }
74
74
  /**
@@ -111,7 +111,7 @@ declare function match(def: RouterDef, url: string): RouteMatch;
111
111
  */
112
112
  /**
113
113
  * The platform `HttpApiClient` derived from a router's `HttpApi` spine. Typed
114
- * opaquely (`Client<any, …>`) because the spine is `HttpApi.Any` — its
114
+ * opaquely (`Client<any, …>`) because the spine is `HttpApi.Top` — its
115
115
  * group/endpoint shapes are assembled in a runtime loop by `buildHttpApi`, so a
116
116
  * precise client type is not recoverable. Present (`Option.some`) on the client
117
117
  * (`RouterLive`), absent (`Option.none`) on the server, which is itself the origin.
@@ -452,14 +452,14 @@ interface CompiledLeaf {
452
452
  /**
453
453
  * Path-param schema. Its **encoded** side is typed string-encodeable
454
454
  * (`Record<string, string | undefined>`) so it satisfies platform's
455
- * `HttpApiEndpoint.setPath` constraint without an `as any` cast — param schemas
455
+ * `HttpApiEndpoint` `params` constraint without an `as any` cast — param schemas
456
456
  * round-trip strings, so the `Schema.Struct` value is asserted to this shape.
457
457
  */
458
458
  readonly pathSchema: Schema.Codec<Record<string, unknown>, Readonly<Record<string, string | undefined>>>;
459
459
  /**
460
460
  * Query schema. Its **encoded** side is typed string-encodeable
461
461
  * (`Record<string, string | ReadonlyArray<string> | undefined>`) so it satisfies
462
- * platform's `HttpApiEndpoint.setUrlParams` constraint without a cast.
462
+ * platform's `HttpApiEndpoint` `query` constraint without a cast.
463
463
  */
464
464
  readonly querySchema: Schema.Codec<Record<string, unknown>, Readonly<Record<string, string | ReadonlyArray<string> | undefined>>>;
465
465
  /** The page's component slot; invoked per render, reads params via `Router.params` / `Router.query`. */
@@ -489,7 +489,7 @@ interface RouterDef<E = any, R = any> {
489
489
  * nesting/render metadata platform's flat API can't represent. Built by
490
490
  * {@link buildHttpApi} during {@link makeRouter}.
491
491
  */
492
- readonly httpApi: HttpApi.Any;
492
+ readonly httpApi: HttpApi.Top;
493
493
  /**
494
494
  * Phantom marker for the tree's aggregate error channel. Covariant (stores `E`
495
495
  * directly) so a fully-static `RouterDef<never, never>` stays assignable to the
@@ -527,20 +527,20 @@ declare function compile(def: {
527
527
  /**
528
528
  * Builds the authoritative `HttpApi` for a compiled tree (S4): a single `"pages"`
529
529
  * group whose endpoints are GET endpoints — one per leaf — at each leaf's full path
530
- * pattern, carrying `setPath(pathSchema)`, `setUrlParams(querySchema)`, a
530
+ * pattern, carrying `params: pathSchema`, `query: querySchema`, a
531
531
  * `Schema.String` (text/HTML) success, and a `RouterNotFound → 404` error. The tree
532
532
  * (not `HttpApi`) is the authoring surface; this is the single source of truth the
533
533
  * server dispatch (`HttpApiBuilder`) and the client matcher / derived `HttpApiClient`
534
534
  * read from, so both sides agree on paths and schemas.
535
535
  *
536
536
  * Each leaf's `pathSchema`/`querySchema` are typed string-encodeable (see
537
- * {@link CompiledLeaf}), so `setPath`/`setUrlParams` need no `as any` casts.
537
+ * {@link CompiledLeaf}), so the `params`/`query` options need no `as any` casts.
538
538
  *
539
539
  * `Boundary.rpc` data no longer rides this spine: it resolves through the app's
540
540
  * merged `RpcGroup` over the ambient `AppRpcClient` (`POST /_eui/rpc`), wired
541
541
  * explicitly into `RouterServer`/`RouterLive`. The matcher reads only `"pages"`.
542
542
  */
543
- declare function buildHttpApi(leaves: readonly CompiledLeaf[]): HttpApi.Any;
543
+ declare function buildHttpApi(leaves: readonly CompiledLeaf[]): HttpApi.Top;
544
544
  /**
545
545
  * Seals a route tree into a {@link RouterDef}, compiling it eagerly (so leaf
546
546
  * references are stamped for `href`), building its authoritative {@link buildHttpApi}
@@ -1,4 +1,4 @@
1
- import { l as leafRegistry } from "./outlet-ty5ZYKBW.js";
1
+ import { l as leafRegistry } from "./outlet-C9N4a4_F.js";
2
2
  import { Result, Schema } from "effect";
3
3
  //#region src/matcher.ts
4
4
  /** Escapes a literal path segment for inclusion in a `RegExp`. */
@@ -50,7 +50,7 @@ function compileMatchers(def) {
50
50
  const endpoints = def.httpApi.groups["pages"]?.endpoints ?? {};
51
51
  const entries = [];
52
52
  for (const endpoint of Object.values(endpoints)) {
53
- const leaf = leafById.get(endpoint.name);
53
+ const leaf = leafById.get(endpoint.identifier);
54
54
  if (leaf === void 0) continue;
55
55
  entries.push({
56
56
  leaf,
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { A as notFound, C as RouterHttpApiClient, D as RouterNotFound, E as match, O as RouterParamsError, S as Router, T as compileMatchers, _ as TreeE, a as RouterOptions, b as NavState, c as leafRegistry, d as FieldsType, f as LayoutNode, g as SubtreeR, h as SubtreeE, i as RouterDef, k as isRouterNotFound, l as ComponentSlot, m as RouteNode, n as CompiledLayout, o as buildHttpApi, p as RouteHandlerProps, r as CompiledLeaf, s as compile, t as Compiled, u as Fields, v as TreeNode, w as RouteMatch, x as NavigateOptions, y as TreeR } from "./compile-DWdMZiMt.js";
2
- import { i as href, n as outletNode, r as HrefArgs, t as RouterApp } from "./outlet-BiFb5gdK.js";
1
+ import { A as notFound, C as RouterHttpApiClient, D as RouterNotFound, E as match, O as RouterParamsError, S as Router, T as compileMatchers, _ as TreeE, a as RouterOptions, b as NavState, c as leafRegistry, d as FieldsType, f as LayoutNode, g as SubtreeR, h as SubtreeE, i as RouterDef, k as isRouterNotFound, l as ComponentSlot, m as RouteNode, n as CompiledLayout, o as buildHttpApi, p as RouteHandlerProps, r as CompiledLeaf, s as compile, t as Compiled, u as Fields, v as TreeNode, w as RouteMatch, x as NavigateOptions, y as TreeR } from "./compile-BJFIgBbE.js";
2
+ import { i as href, n as outletNode, r as HrefArgs, t as RouterApp } from "./outlet-eoUQ-W0k.js";
3
3
  export { type Compiled, type CompiledLayout, type CompiledLeaf, type ComponentSlot, type Fields, type FieldsType, type HrefArgs, type LayoutNode, type NavState, type NavigateOptions, type RouteHandlerProps, type RouteMatch, type RouteNode, Router, RouterApp, type RouterDef, type RouterHttpApiClient, RouterNotFound, type RouterOptions, RouterParamsError, type SubtreeE, type SubtreeR, type TreeE, type TreeNode, type TreeR, buildHttpApi, compile, compileMatchers, href, isRouterNotFound, leafRegistry, match, notFound, outletNode };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- import { a as Router, c as compile, d as RouterParamsError, f as isRouterNotFound, l as leafRegistry, n as outletNode, p as notFound, s as buildHttpApi, t as RouterApp, u as RouterNotFound } from "./outlet-ty5ZYKBW.js";
2
- import { n as compileMatchers, r as match, t as href } from "./href-DD8PoCGO.js";
1
+ import { a as Router, c as compile, d as RouterParamsError, f as isRouterNotFound, l as leafRegistry, n as outletNode, p as notFound, s as buildHttpApi, t as RouterApp, u as RouterNotFound } from "./outlet-C9N4a4_F.js";
2
+ import { n as compileMatchers, r as match, t as href } from "./href-uvJ6b7zz.js";
3
3
  export { Router, RouterApp, RouterNotFound, RouterParamsError, buildHttpApi, compile, compileMatchers, href, isRouterNotFound, leafRegistry, match, notFound, outletNode };
@@ -157,14 +157,14 @@ function compile(def) {
157
157
  /**
158
158
  * Builds the authoritative `HttpApi` for a compiled tree (S4): a single `"pages"`
159
159
  * group whose endpoints are GET endpoints — one per leaf — at each leaf's full path
160
- * pattern, carrying `setPath(pathSchema)`, `setUrlParams(querySchema)`, a
160
+ * pattern, carrying `params: pathSchema`, `query: querySchema`, a
161
161
  * `Schema.String` (text/HTML) success, and a `RouterNotFound → 404` error. The tree
162
162
  * (not `HttpApi`) is the authoring surface; this is the single source of truth the
163
163
  * server dispatch (`HttpApiBuilder`) and the client matcher / derived `HttpApiClient`
164
164
  * read from, so both sides agree on paths and schemas.
165
165
  *
166
166
  * Each leaf's `pathSchema`/`querySchema` are typed string-encodeable (see
167
- * {@link CompiledLeaf}), so `setPath`/`setUrlParams` need no `as any` casts.
167
+ * {@link CompiledLeaf}), so the `params`/`query` options need no `as any` casts.
168
168
  *
169
169
  * `Boundary.rpc` data no longer rides this spine: it resolves through the app's
170
170
  * merged `RpcGroup` over the ambient `AppRpcClient` (`POST /_eui/rpc`), wired
@@ -1,4 +1,4 @@
1
- import { D as RouterNotFound, S as Router, d as FieldsType, i as RouterDef, m as RouteNode, u as Fields } from "./compile-DWdMZiMt.js";
1
+ import { D as RouterNotFound, S as Router, d as FieldsType, i as RouterDef, m as RouteNode, u as Fields } from "./compile-BJFIgBbE.js";
2
2
  import { Node } from "@weftui/core";
3
3
 
4
4
  //#region src/href.d.ts
@@ -1,4 +1,4 @@
1
- import { S as Router, i as RouterDef, l as ComponentSlot } from "../compile-DWdMZiMt.js";
1
+ import { S as Router, i as RouterDef, l as ComponentSlot } from "../compile-BJFIgBbE.js";
2
2
  import { Effect, Layer } from "effect";
3
3
  import { AppRpcClientTag } from "@weftui/core";
4
4
  import { RpcGroup } from "effect/unstable/rpc";
@@ -1,4 +1,4 @@
1
- import { a as Router, f as isRouterNotFound, n as outletNode, u as RouterNotFound } from "../outlet-ty5ZYKBW.js";
1
+ import { a as Router, f as isRouterNotFound, n as outletNode, u as RouterNotFound } from "../outlet-C9N4a4_F.js";
2
2
  import { HttpApiBuilder, HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
3
3
  import { Cause, Effect, Exit, Layer, Option, Schema, Scope, Stream } from "effect";
4
4
  import { AppRpcClientTag, Subscribable } from "@weftui/core";
@@ -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 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.
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 a watcher fiber forked into the same scope alongside the subscription itself observes its exit directly. When that exit is a failure whose cause is not interruption-only, Weft reports it explicitly via `Effect.logError(exit.cause)`, annotated with `weft.region` to identify 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, at the `"Error"` level. 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 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.
43
+ This is deliberate: rather than leaving the failure to whatever the Effect runtime would otherwise do with an unobserved fiber exit, Weft observes and logs it itself, so visibility is controlled by the same knobs any Effect program uses — `References.MinimumLogLevel` (provided via `Effect.provideService`) to filter it, or a custom `Logger` to route it elsewhere. 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 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.
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 from an `acquireRelease`-backed `Layer.effect` — 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 `setPath(pathSchema)`, `setUrlParams(querySchema)`, and a `RouterNotFound → 404` error. Both sides read that one definition, so they always agree:
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 `params: pathSchema`, `query: 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. 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.
12
+ Which recipe to reach for depends on whether the layer has anything to release. Both plain and scoped layers are built with `Layer.succeed` or `Layer.effect` — the distinction is whether the layer's effect acquires releasable resources (`acquireRelease`, or a scope finalizer added directly). A plain value layer (`Layer.succeed`, or `Layer.effect` whose effect has no `acquireRelease`) can be provided directly at the mount — there is nothing to leak. A **scoped** layer (`Layer.effect` whose effect is 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
 
@@ -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 `setPath`/`setUrlParams` + 404). Called by `Router.router`; the result is `def.httpApi`. |
326
+ | `buildHttpApi(leaves)` | Builds the authoritative `HttpApi` (one `"pages"` group, a GET endpoint per leaf with `params`/`query` schemas + 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,9 +14,11 @@ 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@beta
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
+
20
22
  `@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.
21
23
 
22
24
  ## Build a component
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weftui/router",
3
- "version": "0.27.0",
3
+ "version": "0.27.1",
4
4
  "description": "Universal nested router for Weft — one route tree, server and client, with type-safe params and href",
5
5
  "keywords": [
6
6
  "effect",
@@ -44,13 +44,13 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "@weftui/core": "0.27.0",
48
- "@weftui/dom": "0.27.0"
47
+ "@weftui/core": "0.27.1",
48
+ "@weftui/dom": "0.27.1"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/jsdom": "^28.0.3",
52
52
  "@types/node": "^25.9.2",
53
- "effect": "4.0.0-beta.93",
53
+ "effect": "4.0.0-beta.98",
54
54
  "jsdom": "^29.1.1",
55
55
  "tsx": "^4.22.4",
56
56
  "typescript": "^6.0.3",
@@ -58,6 +58,6 @@
58
58
  "vite-plus": "0.2.2"
59
59
  },
60
60
  "peerDependencies": {
61
- "effect": "4.0.0-beta.93"
61
+ "effect": ">=4.0.0-beta.98 <4.0.0"
62
62
  }
63
63
  }