@thomasfosterau/effect-sveltekit 0.3.1 → 0.4.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 +510 -31
- package/dist/Hooks.d.ts +4 -5
- package/dist/Hooks.js +3 -1
- package/dist/Hooks.js.map +1 -1
- package/dist/Navigation.d.ts +1 -3
- package/dist/Navigation.js +1 -1
- package/dist/Remote.d.ts +58 -3
- package/dist/Remote.js +17 -1
- package/dist/Remote.js.map +1 -1
- package/dist/State.d.ts +1 -3
- package/dist/State.js +1 -1
- package/dist/adapter/assets.d.ts +7 -5
- package/dist/adapter/assets.js +3 -3
- package/dist/adapter/assets.js.map +1 -1
- package/dist/adapter/handler.d.ts +5 -5
- package/dist/adapter/handler.js +12 -12
- package/dist/adapter/handler.js.map +1 -1
- package/dist/adapter/index.d.ts +2 -2
- package/dist/adapter/index.js +3 -3
- package/dist/adapter/index.js.map +1 -1
- package/dist/adapter/serve.d.ts +1 -1
- package/dist/adapter/serve.js +4 -4
- package/dist/adapter/serve.js.map +1 -1
- package/dist/api-client.d.ts +5 -6
- package/dist/api-client.js +2 -2
- package/dist/api-client.js.map +1 -1
- package/dist/app-runtime.d.ts +1 -2
- package/dist/app-runtime.js +3 -2
- package/dist/app-runtime.js.map +1 -1
- package/dist/client/Hooks.d.ts +1 -3
- package/dist/client/Hooks.js +1 -1
- package/dist/config.d.ts +2 -3
- package/dist/config.js +5 -5
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +88 -0
- package/dist/errors.js +126 -0
- package/dist/errors.js.map +1 -0
- package/dist/forms.d.ts +2 -3
- package/dist/forms.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/app-state.d.ts +1 -2
- package/dist/internal/app-state.js +1 -1
- package/dist/internal/auto.d.ts +0 -1
- package/dist/internal/auto.js.map +1 -1
- package/dist/internal/enhance.d.ts +0 -1
- package/dist/internal/enhance.js.map +1 -1
- package/dist/internal/error.js +1 -1
- package/dist/internal/remote-run.d.ts +3 -2
- package/dist/internal/remote-run.js.map +1 -1
- package/dist/internal/remote-validators.js +1 -1
- package/dist/internal/route-params.d.ts +0 -1
- package/dist/kit.d.ts +2 -3
- package/dist/realtime.d.ts +5 -5
- package/dist/realtime.js +1 -1
- package/dist/realtime.js.map +1 -1
- package/dist/remote-functions.d.ts +16 -3
- package/dist/remote-functions.js +45 -2
- package/dist/remote-functions.js.map +1 -1
- package/dist/remote-reactive.d.ts +1 -2
- package/dist/remote-reactive.js +1 -1
- package/dist/remote-reactive.js.map +1 -1
- package/dist/request-parse.d.ts +1 -2
- package/dist/request-parse.js.map +1 -1
- package/dist/request-runtime.d.ts +0 -1
- package/dist/request-runtime.js.map +1 -1
- package/dist/request-services.d.ts +0 -1
- package/dist/request-services.js.map +1 -1
- package/dist/response-headers.d.ts +24 -0
- package/dist/response-headers.js +35 -0
- package/dist/response-headers.js.map +1 -0
- package/dist/runtime.d.ts +2 -3
- package/dist/runtime.js +3 -3
- package/dist/runtime.js.map +1 -1
- package/dist/server/Endpoint.d.ts +18 -15
- package/dist/server/Endpoint.js +10 -9
- package/dist/server/Endpoint.js.map +1 -1
- package/dist/server/Hooks.d.ts +1 -3
- package/dist/server/Hooks.js +1 -1
- package/dist/server/Hooks.js.map +1 -1
- package/dist/server.d.ts +5 -4
- package/dist/server.js +5 -3
- package/dist/server.js.map +1 -1
- package/dist/streamed-load.d.ts +0 -1
- package/dist/streamed-load.js.map +1 -1
- package/dist/testing.d.ts +0 -1
- package/dist/testing.js.map +1 -1
- package/dist/transport.d.ts +0 -1
- package/dist/universal.d.ts +3 -4
- package/dist/universal.js +3 -3
- package/dist/universal.js.map +1 -1
- package/dist/vite.d.ts +2 -1
- package/dist/vite.js +2 -2
- package/dist/vite.js.map +1 -1
- package/package.json +9 -5
package/README.md
CHANGED
|
@@ -1,50 +1,60 @@
|
|
|
1
1
|
# @thomasfosterau/effect-sveltekit
|
|
2
2
|
|
|
3
|
-
Effect
|
|
4
|
-
|
|
5
|
-
across the server/client boundary with Effect Schema; and deploy on an Effect
|
|
6
|
-
HTTP server.
|
|
3
|
+
Effect integration for SvelteKit: load/action/endpoint wrappers, remote
|
|
4
|
+
functions, an `effectKit()` Vite plugin, and an Effect HTTP deployment adapter.
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
monorepo. Depends on
|
|
6
|
+
It depends on
|
|
10
7
|
[`@thomasfosterau/effect-svelte`](https://www.npmjs.com/package/@thomasfosterau/effect-svelte)
|
|
11
8
|
for the Svelte runes hooks.
|
|
12
9
|
|
|
13
|
-
##
|
|
10
|
+
## Install
|
|
14
11
|
|
|
15
12
|
```bash
|
|
16
|
-
|
|
13
|
+
pnpm add @thomasfosterau/effect-sveltekit effect@rc svelte @sveltejs/kit
|
|
17
14
|
# the Effect deployment adapter additionally needs:
|
|
18
|
-
|
|
15
|
+
pnpm add @effect/platform-node@rc
|
|
19
16
|
```
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
`effect` (`>=4.0.0-rc.118`) and `svelte` (`^5.40.0`) are required peers;
|
|
19
|
+
`@sveltejs/kit` (`^2.0.0 || ^3.0.0-next.0`), `vite` (for `./vite`) and
|
|
20
|
+
`@effect/platform-node` (`>=4.0.0-rc.118`, for `./adapter`) are optional. The
|
|
21
|
+
HTTP modules that lived in `@effect/platform` in v3 are part of `effect` itself
|
|
22
|
+
in v4 (`effect/http`), so no other Effect package is needed. Keep a single copy
|
|
23
|
+
of `effect`, and keep `effect` and `@effect/platform-node` on the same
|
|
24
|
+
exact version.
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
25
|
-
| `@thomasfosterau/effect-sveltekit` | universal helpers (`load`, the `Remote` call namespace, `transport`, `sveltekitConfig`, `reroute`) |
|
|
26
|
-
| `…/server` | server wrappers (`serverLoad`, `action`, `actions`, `handle`, `endpoint`), app runtimes (`makeServerRuntime` / `makeUniversalRuntime`), the per-request runtime seam (`makeRuntimeAdapter` / `RequestRuntime`), `RemoteFunction` |
|
|
27
|
-
| `…/client` | browser-only `Navigation` / `State` / `Remote` namespaces and `useRemoteQuery` |
|
|
28
|
-
| `…/vite` | the `effectKit()` Vite plugin (auto-wrap bare-Effect route exports) |
|
|
29
|
-
| `…/adapter` | the Effect HTTP deployment adapter |
|
|
26
|
+
## Usage
|
|
30
27
|
|
|
31
|
-
|
|
28
|
+
Wrap a route's `load` so it returns an Effect:
|
|
32
29
|
|
|
33
30
|
```ts
|
|
34
|
-
//
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
31
|
+
// src/routes/items/[id]/+page.server.ts
|
|
32
|
+
import { serverLoad } from "@thomasfosterau/effect-sveltekit/server";
|
|
33
|
+
import { Effect } from "effect";
|
|
37
34
|
|
|
38
|
-
export
|
|
35
|
+
export const load = serverLoad((event) => Effect.succeed({ id: event.params.id }));
|
|
39
36
|
```
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
The same wrappers exist for actions, endpoints and hooks, on the default
|
|
39
|
+
per-request runtime or on your own services (see
|
|
40
|
+
[App-wide runtime](#app-wide-runtime-share-your-services-across-requests)); the
|
|
41
|
+
`effectKit()` Vite plugin lets route files export bare Effects instead.
|
|
42
|
+
|
|
43
|
+
## API
|
|
44
|
+
|
|
45
|
+
| Entry point | What it provides |
|
|
46
|
+
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
47
|
+
| `@thomasfosterau/effect-sveltekit` | Universal helpers: `load` / `makeUniversalRuntime`, the `Remote` call namespace, `Hooks` (`reroute`, `transport`), `ResponseHeaders`, `sveltekitConfig` / `readConfig`, `apiClient` |
|
|
48
|
+
| `…/server` | Server wrappers (`serverLoad`, `action`, `actions`, `endpoint`), `Hooks`, `Endpoint`, `makeServerRuntime`, the per-request runtime seam (`makeRuntimeAdapter` / `RequestRuntime`), `Errors`, `RemoteFunction`, request decoding (`decodeParams`, `decodeJson`, …) |
|
|
49
|
+
| `…/client` | Browser-only `Navigation`, `State`, `Remote`, `Realtime`, `Forms` and `Hooks` namespaces, and `useRemoteQuery` |
|
|
50
|
+
| `…/vite` | The `effectKit()` Vite plugin (auto-wraps bare-Effect route exports) |
|
|
51
|
+
| `…/adapter` | The Effect HTTP deployment adapter (`effectAdapter`) |
|
|
52
|
+
| `…/adapter/handler` | The SvelteKit app as an Effect HTTP app (`makeHandler`, `makeHandlerWith`, `AssetSource`, `toWebHandler`) |
|
|
53
|
+
| `…/adapter/serve` | The Node server the adapter's `index.js` runs (`serve`, `layer`) |
|
|
54
|
+
| `…/testing` | A fake `RequestEvent` and runners for unit-testing server wrappers and remote functions (`TestRequestEvent`, `runServerLoad`, `runAction`, `runEndpoint`, `runRemote`) |
|
|
55
|
+
| `…/internal/auto` | Referenced by `effectKit()`'s generated code; not a public API |
|
|
46
56
|
|
|
47
|
-
|
|
57
|
+
### At a glance
|
|
48
58
|
|
|
49
59
|
- **Effects as route exports** — explicit wrappers, app-wide runtimes (services
|
|
50
60
|
built once per process), or the `effectKit()` plugin.
|
|
@@ -75,14 +85,483 @@ export const load = (event) => Effect.succeed({ id: event.params.id });
|
|
|
75
85
|
namespaces.
|
|
76
86
|
- **Effect deployment adapter** — the generated app is a platform-neutral
|
|
77
87
|
Effect `HttpApp` (`makeHandlerWith`): serve it as a production Node HTTP server
|
|
78
|
-
(`effect/
|
|
88
|
+
(`effect/http` + `@effect/platform-node`, the default) or as a Web
|
|
79
89
|
`fetch` handler on Cloudflare Workers (`effectAdapter({ target: "fetch" })` /
|
|
80
90
|
`toWebHandler`). Asset serving is a pluggable `AssetSource`
|
|
81
91
|
(`AssetSource.fileSystem` for Node, `AssetSource.cloudflareAssets(env.ASSETS)`
|
|
82
92
|
for Workers, or any custom source — R2, KV, a CDN passthrough).
|
|
83
93
|
|
|
84
|
-
|
|
85
|
-
|
|
94
|
+
### SvelteKit Vite plugin (recommended)
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
// vite.config.ts
|
|
98
|
+
import { sveltekit } from "@sveltejs/kit/vite";
|
|
99
|
+
import { effectKit } from "@thomasfosterau/effect-sveltekit/vite";
|
|
100
|
+
|
|
101
|
+
export default {
|
|
102
|
+
plugins: [effectKit(), sveltekit()],
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
With the plugin installed, you can return an Effect (or a function returning
|
|
107
|
+
an Effect) directly from any standard SvelteKit route file (`+page.ts`,
|
|
108
|
+
`+page.server.ts`, `+layout(.server).ts`, `+server.ts`,
|
|
109
|
+
`hooks.(server|client).ts`):
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
// +page.server.ts
|
|
113
|
+
import { Effect } from "effect";
|
|
114
|
+
|
|
115
|
+
export const load = (event) => Effect.succeed({ id: event.params.id });
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The plugin rewrites the export so it goes through the same runtime as the
|
|
119
|
+
explicit wrappers below; plain promise/value-returning functions pass through
|
|
120
|
+
unchanged.
|
|
121
|
+
|
|
122
|
+
#### Supported exports
|
|
123
|
+
|
|
124
|
+
| File | Exports auto-wrapped |
|
|
125
|
+
| ------------------- | ---------------------------------------------------------------------- |
|
|
126
|
+
| `+page.ts` | `load` |
|
|
127
|
+
| `+page.server.ts` | `load`, `actions` |
|
|
128
|
+
| `+layout.ts` | `load` |
|
|
129
|
+
| `+layout.server.ts` | `load` |
|
|
130
|
+
| `+server.ts` | `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`, `HEAD`, `fallback` |
|
|
131
|
+
| `hooks.ts` | `reroute` |
|
|
132
|
+
| `hooks.server.ts` | `handle`, `handleFetch`, `handleError`, `init` |
|
|
133
|
+
| `hooks.client.ts` | `handleError`, `init` |
|
|
134
|
+
|
|
135
|
+
Config exports like `prerender`, `ssr`, `csr`, and `trailingSlash` — and the
|
|
136
|
+
universal `transport` hook (which is plain data, not a function) — are never
|
|
137
|
+
touched.
|
|
138
|
+
|
|
139
|
+
### App-wide runtime (share your services across requests)
|
|
140
|
+
|
|
141
|
+
Define your application's Effect services once as a `Layer`; the layer is
|
|
142
|
+
built lazily on the first request and shared for the lifetime of the server
|
|
143
|
+
process:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
// src/lib/server/runtime.ts
|
|
147
|
+
import { makeServerRuntime } from "@thomasfosterau/effect-sveltekit/server";
|
|
148
|
+
import { Layer } from "effect";
|
|
149
|
+
import { Database } from "./database";
|
|
150
|
+
|
|
151
|
+
export const runtime = makeServerRuntime(Database.layer);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
// src/routes/items/+page.server.ts
|
|
156
|
+
import { runtime } from "$lib/server/runtime";
|
|
157
|
+
import { Effect } from "effect";
|
|
158
|
+
import { Database } from "$lib/server/database";
|
|
159
|
+
|
|
160
|
+
export const load = runtime.serverLoad((event) =>
|
|
161
|
+
Effect.gen(function* () {
|
|
162
|
+
const db = yield* Database;
|
|
163
|
+
return { items: yield* db.listItems() };
|
|
164
|
+
}),
|
|
165
|
+
);
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The runtime exposes `serverLoad`, `action`, `actions`, `handle`, `handleFetch`,
|
|
169
|
+
`handleError`, `init`, `endpoint`, `requestRuntime`, `runPromise`, and `dispose`.
|
|
170
|
+
For universal `load` functions there is a browser-safe counterpart,
|
|
171
|
+
`makeUniversalRuntime`, in `@thomasfosterau/effect-sveltekit`.
|
|
172
|
+
|
|
173
|
+
To make the same services available to bare-Effect exports handled by the
|
|
174
|
+
Vite plugin, point the plugin at the runtime module:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
// vite.config.ts
|
|
178
|
+
effectKit({ serverRuntime: "$lib/server/runtime" });
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### One runtime per request
|
|
182
|
+
|
|
183
|
+
Wire the runtime's `handle` hook (or the auto-wrapped `handle` from the Vite
|
|
184
|
+
plugin) in `src/hooks.server.ts`. It creates a **per-request runtime** — the
|
|
185
|
+
application layer's services plus the request's `HttpClient`/`SvelteKitRequestEvent`,
|
|
186
|
+
built once and sharing a single request scope — and stores it on `event.locals`:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
// src/hooks.server.ts
|
|
190
|
+
import { runtime } from "$lib/server/runtime";
|
|
191
|
+
import { Effect } from "effect";
|
|
192
|
+
|
|
193
|
+
export const handle = runtime.handle(({ event, resolve }) =>
|
|
194
|
+
Effect.promise(async () => resolve(event)),
|
|
195
|
+
);
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
With `handle` wired, every other wrapper for that runtime (`serverLoad`,
|
|
199
|
+
`action`, `endpoint`, ...) runs each request's effects on the same per-request
|
|
200
|
+
runtime — one `HttpClient`, one request scope — instead of rebuilding the request
|
|
201
|
+
services per call. Reach the runtime yourself with `runtime.requestRuntime(event)`
|
|
202
|
+
(for example from another hook in a `sequence`, to populate `event.locals`):
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
// e.g. authenticate once per request
|
|
206
|
+
export const handle = runtime.handle(({ event, resolve }) =>
|
|
207
|
+
Effect.gen(function* () {
|
|
208
|
+
const rt = runtime.requestRuntime(event)!;
|
|
209
|
+
event.locals.user = yield* Effect.promise(() => rt.runPromise(Auth.currentUser));
|
|
210
|
+
return yield* Effect.promise(async () => resolve(event));
|
|
211
|
+
}),
|
|
212
|
+
);
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Wrappers from a _different_ runtime, or requests without `handle` wired, fall
|
|
216
|
+
back to building the request services per call, so this is backward compatible.
|
|
217
|
+
|
|
218
|
+
### Effect deployment adapter
|
|
219
|
+
|
|
220
|
+
A SvelteKit [adapter](https://svelte.dev/docs/kit/adapters) (like
|
|
221
|
+
`@sveltejs/adapter-node`) whose production server is an Effect HTTP server
|
|
222
|
+
(`effect/http` + `@effect/platform-node`) — `Config`-based
|
|
223
|
+
configuration, request tracing spans, and graceful shutdown through Effect
|
|
224
|
+
scopes:
|
|
225
|
+
|
|
226
|
+
```js
|
|
227
|
+
// svelte.config.js
|
|
228
|
+
import adapter from "@thomasfosterau/effect-sveltekit/adapter";
|
|
229
|
+
|
|
230
|
+
export default {
|
|
231
|
+
kit: { adapter: adapter() },
|
|
232
|
+
};
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
vite build
|
|
237
|
+
node build # PORT, HOST, ORIGIN, PROTOCOL_HEADER, ... read from the env
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The build also emits `build/handler.js`, which exports the whole SvelteKit
|
|
241
|
+
app as a composable Effect HTTP app — mount it inside an existing
|
|
242
|
+
`effect/http` server alongside your other routes:
|
|
243
|
+
|
|
244
|
+
```ts
|
|
245
|
+
import { handler } from "./build/handler.js";
|
|
246
|
+
import { HttpServer } from "effect/http";
|
|
247
|
+
import { NodeHttpServer, NodeRuntime } from "@effect/platform-node";
|
|
248
|
+
import { Effect, Layer } from "effect";
|
|
249
|
+
import { createServer } from "node:http";
|
|
250
|
+
|
|
251
|
+
const server = Layer.unwrap(Effect.map(handler, (app) => HttpServer.serve(app))).pipe(
|
|
252
|
+
Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })),
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
NodeRuntime.runMain(Layer.launch(server));
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Unlike `adapter-node`, the server output is not bundled: deploy `build/`
|
|
259
|
+
together with `package.json` and production `node_modules` (which must
|
|
260
|
+
include `@thomasfosterau/effect-sveltekit`, `effect`, and
|
|
261
|
+
`@effect/platform-node`).
|
|
262
|
+
|
|
263
|
+
### SvelteKit universal load
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
import { load, makeUniversalRuntime } from "@thomasfosterau/effect-sveltekit";
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### SvelteKit server helpers
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
import {
|
|
273
|
+
serverLoad,
|
|
274
|
+
action,
|
|
275
|
+
actions,
|
|
276
|
+
endpoint,
|
|
277
|
+
// hooks.server.ts hooks as Effects: Hooks.handle / handleFetch / handleError / init
|
|
278
|
+
Hooks,
|
|
279
|
+
// create a +server.ts endpoint from an Effect HttpApi / HttpRouter / route
|
|
280
|
+
Endpoint,
|
|
281
|
+
makeServerRuntime,
|
|
282
|
+
} from "@thomasfosterau/effect-sveltekit/server";
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Boundary error translation from a catalogue (`Errors.toSvelteKit`)
|
|
286
|
+
|
|
287
|
+
Every server wrapper takes a `translateError` that turns a failed `Cause` into
|
|
288
|
+
SvelteKit control flow. Rather than hand-writing that switch, pass your tagged
|
|
289
|
+
error catalogue as data — keyed by `_tag` — and the app's `kit.ts` becomes one
|
|
290
|
+
call:
|
|
291
|
+
|
|
292
|
+
```ts
|
|
293
|
+
// src/lib/server/effect/kit.ts
|
|
294
|
+
import {
|
|
295
|
+
Errors,
|
|
296
|
+
makeRuntimeAdapter,
|
|
297
|
+
RequestRuntime,
|
|
298
|
+
} from "@thomasfosterau/effect-sveltekit/server";
|
|
299
|
+
import { error } from "@sveltejs/kit";
|
|
300
|
+
import type { AppError } from "$lib/errors"; // NotFound | Unauthorized | Forbidden | Redirect | HttpError | JsonapiError
|
|
301
|
+
|
|
302
|
+
export const { serverLoad, endpoint } = makeRuntimeAdapter(
|
|
303
|
+
RequestRuntime.fromLocals((event) => event.locals.runtime),
|
|
304
|
+
{
|
|
305
|
+
translateError: Errors.toSvelteKit<AppError>({
|
|
306
|
+
NotFound: { status: 404, message: (e) => `${e.resource} ${e.id} not found` },
|
|
307
|
+
Unauthorized: 401, // body: the error's own `message`, else its tag
|
|
308
|
+
Forbidden: 403,
|
|
309
|
+
Redirect: "redirect", // redirect(e.status, e.to)
|
|
310
|
+
HttpError: "status", // error(e.status, e.message)
|
|
311
|
+
JsonapiError: (e) => error(e.status, JSON.stringify(e.toDocument())), // full control
|
|
312
|
+
}),
|
|
313
|
+
},
|
|
314
|
+
);
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The squashed cause is matched, so a tagged error that surfaced as a defect is
|
|
318
|
+
translated too. Anything outside the catalogue goes to `fallback` — by default
|
|
319
|
+
`SvelteKit.translate` (Kit control-flow errors pass through; everything else is
|
|
320
|
+
an `EffectCauseError` 500 carrying the full `Cause`); pass
|
|
321
|
+
`{ fallback: Errors.rethrowSquashed }` to rethrow the original value unchanged
|
|
322
|
+
for `handleError`. With the error union as the type argument, catalogue keys and
|
|
323
|
+
each entry's callback are checked against it.
|
|
324
|
+
|
|
325
|
+
### SvelteKit endpoints backed by Effect
|
|
326
|
+
|
|
327
|
+
Create a `+server.ts` endpoint from an Effect [`HttpApi`](https://effect.website),
|
|
328
|
+
an `HttpRouter`, or a single route effect. Effect turns each of these into a Web
|
|
329
|
+
`fetch` handler; the `Endpoint` helpers wrap one as a SvelteKit `RequestHandler`.
|
|
330
|
+
Put it on a catch-all route and assign it to `fallback` so every method and
|
|
331
|
+
sub-path reaches it — `prefix` strips the SvelteKit mount path so the route's own
|
|
332
|
+
paths line up:
|
|
333
|
+
|
|
334
|
+
```ts
|
|
335
|
+
// src/routes/api/[...path]/+server.ts
|
|
336
|
+
import { Endpoint } from "@thomasfosterau/effect-sveltekit/server";
|
|
337
|
+
import { api } from "$lib/server/api";
|
|
338
|
+
import { ApiLive } from "$lib/server/handlers"; // HttpApiBuilder.group(...) + your services
|
|
339
|
+
|
|
340
|
+
export const fallback = Endpoint.fromApi(api, ApiLive, { prefix: "/api" });
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
`Endpoint.fromApi` supplies the platform services an `HttpApi` needs
|
|
344
|
+
(`HttpPlatform`, `FileSystem`, `Path`, `Etag`); `Endpoint.fromRouter` and
|
|
345
|
+
`Endpoint.fromHttpEffect` cover hand-built routers and single routes. The backing
|
|
346
|
+
layer is built once on the first request and shared; the returned handler carries
|
|
347
|
+
a `dispose()` for shutdown. Handlers receive an Effect-native `HttpServerRequest`
|
|
348
|
+
(built from `event.request`).
|
|
349
|
+
|
|
350
|
+
### SvelteKit client helpers
|
|
351
|
+
|
|
352
|
+
Effect wrappers for `$app/navigation` (browser-only), plus the remote-function
|
|
353
|
+
call helpers:
|
|
354
|
+
|
|
355
|
+
```ts
|
|
356
|
+
import {
|
|
357
|
+
// $app/navigation: promise wrappers (goto, invalidate, ...) and lifecycle
|
|
358
|
+
// events as Effect Streams (beforeNavigate/afterNavigate/onNavigate)
|
|
359
|
+
Navigation,
|
|
360
|
+
// $app/state: the current page as a Stream of snapshots
|
|
361
|
+
State,
|
|
362
|
+
// remote-function helpers (callQuery, callCommand, liveQueryStream, ...)
|
|
363
|
+
Remote,
|
|
364
|
+
// a reactive remote resource as an AsyncResult
|
|
365
|
+
useRemoteQuery,
|
|
366
|
+
// hooks.client.ts hooks as Effects: Hooks.handleError / Hooks.init
|
|
367
|
+
Hooks,
|
|
368
|
+
} from "@thomasfosterau/effect-sveltekit/client";
|
|
369
|
+
|
|
370
|
+
// e.g. Navigation.goto('/done'), Navigation.invalidateAll(),
|
|
371
|
+
// Remote.callQuery(getTodos), State.page()
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
`Navigation.beforeNavigate()` / `Navigation.afterNavigate()` bridge
|
|
375
|
+
`$app/navigation`'s callback-registration functions to `Stream`s,
|
|
376
|
+
`Navigation.onNavigate(fn => Effect)` runs an Effect per navigation (forwarding
|
|
377
|
+
any cleanup the Effect yields), and `State.page()` emits a shallow snapshot of
|
|
378
|
+
`$app/state`'s `page` initially and after each navigation. Like the bare
|
|
379
|
+
SvelteKit functions they wrap, these must be called during component
|
|
380
|
+
initialization (at the top of `<script>`).
|
|
381
|
+
|
|
382
|
+
### `transport` hook from Effect Schema
|
|
383
|
+
|
|
384
|
+
Move custom types (`Option`, `DateTime`, branded types, `Schema.Class`
|
|
385
|
+
instances, tagged errors, ...) across the server/client boundary — for `load`
|
|
386
|
+
data and remote functions — by building SvelteKit's universal `transport` hook
|
|
387
|
+
from Effect schemas (part of the universal `Hooks` namespace):
|
|
388
|
+
|
|
389
|
+
```ts
|
|
390
|
+
// src/hooks.ts
|
|
391
|
+
import { Hooks } from "@thomasfosterau/effect-sveltekit";
|
|
392
|
+
import { Schema } from "effect";
|
|
393
|
+
|
|
394
|
+
export const transport = Hooks.transport({
|
|
395
|
+
Option: Schema.Option(Schema.Number),
|
|
396
|
+
Date: Schema.Date,
|
|
397
|
+
});
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Response-headers buffer (`ResponseHeaders`)
|
|
401
|
+
|
|
402
|
+
SvelteKit's `setHeaders` refuses `set-cookie`, throws when a header is set
|
|
403
|
+
twice, and is out of reach of components rendering during SSR. The usual answer
|
|
404
|
+
is a mutable headers buffer on `event.locals` that loads (and SSR components,
|
|
405
|
+
via `page.data`) append to and a `handle` copies onto the response.
|
|
406
|
+
`ResponseHeaders` is that buffer: a real `Headers` that serialises to `{}`, with
|
|
407
|
+
a transport entry that reconstructs it empty on the client (its contents never
|
|
408
|
+
leave the server):
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
// src/app.d.ts
|
|
412
|
+
declare global {
|
|
413
|
+
namespace App {
|
|
414
|
+
interface Locals {
|
|
415
|
+
headers: import("@thomasfosterau/effect-sveltekit").ResponseHeaders;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// src/hooks.ts
|
|
421
|
+
import { Hooks } from "@thomasfosterau/effect-sveltekit";
|
|
422
|
+
export const transport = Hooks.transport({ ResponseHeaders: Hooks.responseHeadersTransporter });
|
|
423
|
+
|
|
424
|
+
// src/hooks.server.ts
|
|
425
|
+
import { ResponseHeaders } from "@thomasfosterau/effect-sveltekit";
|
|
426
|
+
import type { Handle } from "@sveltejs/kit";
|
|
427
|
+
|
|
428
|
+
export const handle: Handle = async ({ event, resolve }) => {
|
|
429
|
+
event.locals.headers = new ResponseHeaders();
|
|
430
|
+
const response = await resolve(event);
|
|
431
|
+
event.locals.headers.appendTo(response.headers); // appends, so every set-cookie survives
|
|
432
|
+
return response;
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
// src/routes/+layout.server.ts — expose the same buffer to every page
|
|
436
|
+
export const load = ({ locals }) => ({ headers: locals.headers });
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
(`SvelteKitResponseHeaders`, the per-request _service_, wraps `setHeaders` for
|
|
440
|
+
handler effects; `ResponseHeaders` is the buffer for everything `setHeaders`
|
|
441
|
+
cannot do.)
|
|
442
|
+
|
|
443
|
+
### `$env` as an Effect `Config` source
|
|
444
|
+
|
|
445
|
+
Back Effect's `Config` with SvelteKit's environment, so app-layer services read
|
|
446
|
+
configuration from `$env`:
|
|
447
|
+
|
|
448
|
+
```ts
|
|
449
|
+
// src/lib/server/runtime.ts
|
|
450
|
+
import { env } from "$env/dynamic/private";
|
|
451
|
+
import { makeServerRuntime, sveltekitConfig } from "@thomasfosterau/effect-sveltekit/server";
|
|
452
|
+
import { Layer } from "effect";
|
|
453
|
+
import { Database } from "./database"; // its layer reads Config.String("DATABASE_URL")
|
|
454
|
+
|
|
455
|
+
export const runtime = makeServerRuntime(Database.layer.pipe(Layer.provide(sveltekitConfig(env))));
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### SvelteKit hooks as Effects (`Hooks`)
|
|
459
|
+
|
|
460
|
+
Every SvelteKit hook has an explicit Effect wrapper, grouped into a `Hooks`
|
|
461
|
+
namespace per hook file (mirroring the auto-wrap table above):
|
|
462
|
+
|
|
463
|
+
| Import path | `Hooks` members | Runs on |
|
|
464
|
+
| ----------------------------------------- | ---------------------------------------------- | ------------------------------------------------ |
|
|
465
|
+
| `@thomasfosterau/effect-sveltekit` | `reroute`, `transport`, `transporter` | universal runtime (`HttpClient` via event fetch) |
|
|
466
|
+
| `@thomasfosterau/effect-sveltekit/server` | `handle`, `handleFetch`, `handleError`, `init` | server runtime (`HttpClient` + `RequestEvent`) |
|
|
467
|
+
| `@thomasfosterau/effect-sveltekit/client` | `handleError`, `init` | a bare Effect runtime |
|
|
468
|
+
|
|
469
|
+
```ts
|
|
470
|
+
// src/hooks.ts
|
|
471
|
+
import { Hooks } from "@thomasfosterau/effect-sveltekit";
|
|
472
|
+
import { Effect } from "effect";
|
|
473
|
+
|
|
474
|
+
export const reroute = Hooks.reroute((event) =>
|
|
475
|
+
Effect.succeed(event.url.pathname === "/old" ? "/new" : undefined),
|
|
476
|
+
);
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
```ts
|
|
480
|
+
// src/hooks.server.ts
|
|
481
|
+
import { Hooks } from "@thomasfosterau/effect-sveltekit/server";
|
|
482
|
+
import { Effect } from "effect";
|
|
483
|
+
|
|
484
|
+
export const init = Hooks.init(Effect.logInfo("server starting up"));
|
|
485
|
+
|
|
486
|
+
export const handle = Hooks.handle(({ event, resolve }) =>
|
|
487
|
+
Effect.gen(function* () {
|
|
488
|
+
const start = Date.now();
|
|
489
|
+
const response = yield* Effect.promise(async () => resolve(event));
|
|
490
|
+
yield* Effect.logInfo(`${event.url.pathname} -> ${response.status} (${Date.now() - start}ms)`);
|
|
491
|
+
return response;
|
|
492
|
+
}),
|
|
493
|
+
);
|
|
494
|
+
|
|
495
|
+
export const handleError = Hooks.handleError(({ error, event }) =>
|
|
496
|
+
Effect.gen(function* () {
|
|
497
|
+
const id = crypto.randomUUID();
|
|
498
|
+
yield* Effect.logError(`${event.url.pathname} (${id})`, error);
|
|
499
|
+
return { message: "Internal Error", id };
|
|
500
|
+
}),
|
|
501
|
+
);
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
```ts
|
|
505
|
+
// src/hooks.client.ts
|
|
506
|
+
import { Hooks } from "@thomasfosterau/effect-sveltekit/client";
|
|
507
|
+
import { Effect } from "effect";
|
|
508
|
+
|
|
509
|
+
export const handleError = Hooks.handleError(({ error }) =>
|
|
510
|
+
Effect.as(Effect.logError("client navigation failed", error), {
|
|
511
|
+
message: "Something went wrong",
|
|
512
|
+
}),
|
|
513
|
+
);
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
To additionally provide your application's services to the server hooks, use the
|
|
517
|
+
matching methods on an app-wide runtime (`runtime.handle`, `runtime.handleFetch`,
|
|
518
|
+
`runtime.handleError`, `runtime.init`). The same exports also work as bare
|
|
519
|
+
Effects (no explicit wrapper) when the `effectKit()` Vite plugin is enabled.
|
|
520
|
+
|
|
521
|
+
### Native form actions
|
|
522
|
+
|
|
523
|
+
For SvelteKit page `actions`, the `Forms` namespace
|
|
524
|
+
(`@thomasfosterau/effect-sveltekit/client`) expresses progressive enhancement
|
|
525
|
+
with Effects: `Forms.enhance({ onSubmit, onResult })` builds a `SubmitFunction`
|
|
526
|
+
for `use:enhance`, and `Forms.applyAction` / `Forms.deserialize` wrap the
|
|
527
|
+
`$app/forms` helpers. (This complements `Remote.submitForm`, which covers remote
|
|
528
|
+
forms.)
|
|
529
|
+
|
|
530
|
+
## Recipes
|
|
531
|
+
|
|
532
|
+
### App-side patterns
|
|
533
|
+
|
|
534
|
+
Two SvelteKit app patterns are recipes rather than APIs:
|
|
535
|
+
|
|
536
|
+
- **Leaving an error page.** After an error page renders, client-side
|
|
537
|
+
navigation can re-run loads against a stale context; the apps force a full
|
|
538
|
+
reload instead:
|
|
539
|
+
|
|
540
|
+
```svelte
|
|
541
|
+
<script lang="ts">
|
|
542
|
+
import { beforeNavigate } from "$app/navigation";
|
|
543
|
+
import { page } from "$app/state";
|
|
544
|
+
|
|
545
|
+
beforeNavigate((navigation) => {
|
|
546
|
+
if (page.error) {
|
|
547
|
+
navigation.cancel();
|
|
548
|
+
window.location.href = navigation.to?.url.href ?? "/";
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
</script>
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
- **Paraglide.** The paraglide wiring (plugin shim, compile step, the
|
|
555
|
+
`paraglide` handle and the `fillPattern` workaround) is SvelteKit/Vite-specific
|
|
556
|
+
and not Effect, so it stays an app template rather than a `./paraglide` entry
|
|
557
|
+
here.
|
|
558
|
+
|
|
559
|
+
### Cookbook
|
|
560
|
+
|
|
561
|
+
See the [cookbook](../../docs/cookbook.md) for recipes — consuming an
|
|
562
|
+
`Endpoint.fromApi` with a typed `apiClient`, reading build-time vs runtime
|
|
563
|
+
`$env` config with `readConfig` / `sveltekitConfig`, loading/error chrome around
|
|
564
|
+
an atom query, and a typeahead on `useDebouncedSearch`.
|
|
86
565
|
|
|
87
566
|
## License
|
|
88
567
|
|
package/dist/Hooks.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { MarkerTransporterOptions, TransportEntry, markerTransporter, transport, transporter } from "./transport.js";
|
|
2
|
+
import { responseHeadersTransporter } from "./response-headers.js";
|
|
2
3
|
import { Effect } from "effect";
|
|
3
|
-
import * as HttpClient from "effect/
|
|
4
|
+
import * as HttpClient from "effect/http/HttpClient";
|
|
4
5
|
import { Reroute } from "@sveltejs/kit";
|
|
5
|
-
|
|
6
|
-
//#region src/Hooks.d.ts
|
|
7
6
|
declare namespace Hooks_d_exports {
|
|
8
|
-
export { MarkerTransporterOptions, TransportEntry, markerTransporter, reroute, transport, transporter };
|
|
7
|
+
export { MarkerTransporterOptions, TransportEntry, markerTransporter, reroute, responseHeadersTransporter, transport, transporter };
|
|
9
8
|
}
|
|
10
9
|
/**
|
|
11
10
|
* Wraps an Effect-based function as the SvelteKit universal
|
|
@@ -29,5 +28,5 @@ declare function reroute(fn: (event: {
|
|
|
29
28
|
fetch: typeof globalThis.fetch;
|
|
30
29
|
}) => Effect.Effect<string | void, unknown, HttpClient.HttpClient>): Reroute;
|
|
31
30
|
//#endregion
|
|
32
|
-
export { Hooks_d_exports };
|
|
31
|
+
export { Hooks_d_exports, type MarkerTransporterOptions, type TransportEntry, markerTransporter, reroute, responseHeadersTransporter, transport, transporter };
|
|
33
32
|
//# sourceMappingURL=Hooks.d.ts.map
|
package/dist/Hooks.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { defaultUniversalRuntime } from "./internal/default-runtime.js";
|
|
3
3
|
import { markerTransporter, transport, transporter } from "./transport.js";
|
|
4
|
+
import { responseHeadersTransporter } from "./response-headers.js";
|
|
4
5
|
import "effect";
|
|
5
6
|
//#region src/Hooks.ts
|
|
6
7
|
var Hooks_exports = /* @__PURE__ */ __exportAll({
|
|
7
8
|
markerTransporter: () => markerTransporter,
|
|
8
9
|
reroute: () => reroute,
|
|
10
|
+
responseHeadersTransporter: () => responseHeadersTransporter,
|
|
9
11
|
transport: () => transport,
|
|
10
12
|
transporter: () => transporter
|
|
11
13
|
});
|
|
@@ -30,6 +32,6 @@ function reroute(fn) {
|
|
|
30
32
|
return (event) => defaultUniversalRuntime().runPromise(event.fetch, fn(event));
|
|
31
33
|
}
|
|
32
34
|
//#endregion
|
|
33
|
-
export { Hooks_exports };
|
|
35
|
+
export { Hooks_exports, markerTransporter, reroute, responseHeadersTransporter, transport, transporter };
|
|
34
36
|
|
|
35
37
|
//# sourceMappingURL=Hooks.js.map
|
package/dist/Hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Hooks.js","names":[],"sources":["../src/Hooks.ts"],"sourcesContent":["/**\n * Effect helpers for SvelteKit's universal hooks (`src/hooks.ts`), exposed as\n * the `Hooks` namespace of `@thomasfosterau/effect-sveltekit`.\n *\n * The `reroute` hook is expressed as an Effect (running on the universal\n * runtime, with an `HttpClient` backed by the event's `fetch`), and the\n * universal `transport` hook is built from Effect schemas via {@link transport}\n * / {@link transporter}.\n *\n * @example\n * ```ts\n * // src/hooks.ts\n * import { Hooks } from '@thomasfosterau/effect-sveltekit';\n * import { Effect, Schema } from 'effect';\n *\n * export const reroute = Hooks.reroute((event) =>\n * Effect.succeed(event.url.pathname === '/old' ? '/new' : undefined),\n * );\n *\n * export const transport = Hooks.transport({\n * Option: Schema.Option(Schema.Number),\n * Date: Schema.Date,\n * });\n * ```\n */\n\nimport type { Reroute } from \"@sveltejs/kit\";\nimport { Effect } from \"effect\";\nimport type * as HttpClient from \"effect/
|
|
1
|
+
{"version":3,"file":"Hooks.js","names":[],"sources":["../src/Hooks.ts"],"sourcesContent":["/**\n * Effect helpers for SvelteKit's universal hooks (`src/hooks.ts`), exposed as\n * the `Hooks` namespace of `@thomasfosterau/effect-sveltekit`.\n *\n * The `reroute` hook is expressed as an Effect (running on the universal\n * runtime, with an `HttpClient` backed by the event's `fetch`), and the\n * universal `transport` hook is built from Effect schemas via {@link transport}\n * / {@link transporter}.\n *\n * @example\n * ```ts\n * // src/hooks.ts\n * import { Hooks } from '@thomasfosterau/effect-sveltekit';\n * import { Effect, Schema } from 'effect';\n *\n * export const reroute = Hooks.reroute((event) =>\n * Effect.succeed(event.url.pathname === '/old' ? '/new' : undefined),\n * );\n *\n * export const transport = Hooks.transport({\n * Option: Schema.Option(Schema.Number),\n * Date: Schema.Date,\n * });\n * ```\n */\n\nimport type { Reroute } from \"@sveltejs/kit\";\nimport { Effect } from \"effect\";\nimport type * as HttpClient from \"effect/http/HttpClient\";\nimport { defaultUniversalRuntime } from \"./internal/default-runtime.js\";\n\n/**\n * Wraps an Effect-based function as the SvelteKit universal\n * [`reroute`](https://svelte.dev/docs/kit/hooks#Universal-hooks-reroute) hook,\n * which rewrites the URL before routing. The effect runs on both the server and\n * the client and gets an `HttpClient` backed by the event's `fetch`.\n *\n * @example\n * ```ts\n * // src/hooks.ts\n * import { Hooks } from '@thomasfosterau/effect-sveltekit';\n * import { Effect } from 'effect';\n *\n * export const reroute = Hooks.reroute((event) =>\n * Effect.succeed(event.url.pathname === '/old' ? '/new' : undefined),\n * );\n * ```\n */\nexport function reroute(\n fn: (event: {\n url: URL;\n fetch: typeof globalThis.fetch;\n }) => Effect.Effect<string | void, unknown, HttpClient.HttpClient>,\n): Reroute {\n return (event) => defaultUniversalRuntime().runPromise(event.fetch, fn(event));\n}\n\n/**\n * The universal `transport` hook built from Effect schemas: `transport`\n * assembles a whole `transport` object from a record of entries, `transporter`\n * builds a single round-tripping entry from a `Schema.Codec`, and\n * `markerTransporter` builds a deliberately-lossy entry for a non-POJO wrapper\n * whose contents should not round-trip. See {@link transport} for details.\n */\nexport {\n transport,\n transporter,\n markerTransporter,\n type MarkerTransporterOptions,\n type TransportEntry,\n} from \"./transport.js\";\n\n/**\n * The `transport` entry for the {@link ResponseHeaders} response-headers buffer\n * (`Hooks.transport({ ResponseHeaders: Hooks.responseHeadersTransporter })`).\n */\nexport { responseHeadersTransporter } from \"./response-headers.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,SAAgB,QACd,IAIS;CACT,QAAQ,UAAU,wBAAwB,CAAC,CAAC,WAAW,MAAM,OAAO,GAAG,KAAK,CAAC;AAC/E"}
|
package/dist/Navigation.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Effect, Stream } from "effect";
|
|
2
2
|
import { AfterNavigate, BeforeNavigate, OnNavigate } from "@sveltejs/kit";
|
|
3
3
|
import { goto, invalidate, preloadData, refreshAll } from "$app/navigation";
|
|
4
|
-
|
|
5
|
-
//#region src/Navigation.d.ts
|
|
6
4
|
declare namespace Navigation_d_exports {
|
|
7
5
|
export { afterNavigate$1 as afterNavigate, beforeNavigate$1 as beforeNavigate, goto$1 as goto, invalidate$1 as invalidate, invalidateAll$1 as invalidateAll, onNavigate$1 as onNavigate, preloadCode$1 as preloadCode, preloadData$1 as preloadData, refreshAll$1 as refreshAll };
|
|
8
6
|
}
|
|
@@ -106,5 +104,5 @@ declare function afterNavigate$1(): Stream.Stream<AfterNavigate>;
|
|
|
106
104
|
*/
|
|
107
105
|
declare function onNavigate$1(fn: (navigation: OnNavigate) => Effect.Effect<(() => void) | void>, runEffect?: <X>(effect: Effect.Effect<X>) => Promise<X>): void;
|
|
108
106
|
//#endregion
|
|
109
|
-
export { Navigation_d_exports };
|
|
107
|
+
export { Navigation_d_exports, afterNavigate$1 as afterNavigate, beforeNavigate$1 as beforeNavigate, goto$1 as goto, invalidate$1 as invalidate, invalidateAll$1 as invalidateAll, onNavigate$1 as onNavigate, preloadCode$1 as preloadCode, preloadData$1 as preloadData, refreshAll$1 as refreshAll };
|
|
110
108
|
//# sourceMappingURL=Navigation.d.ts.map
|
package/dist/Navigation.js
CHANGED
|
@@ -150,6 +150,6 @@ function onNavigate$1(fn, runEffect = Effect.runPromise) {
|
|
|
150
150
|
onNavigateWith(onNavigate, fn, runEffect);
|
|
151
151
|
}
|
|
152
152
|
//#endregion
|
|
153
|
-
export { Navigation_exports };
|
|
153
|
+
export { Navigation_exports, afterNavigate$1 as afterNavigate, beforeNavigate$1 as beforeNavigate, goto$1 as goto, invalidate$1 as invalidate, invalidateAll$1 as invalidateAll, onNavigate$1 as onNavigate, preloadCode$1 as preloadCode, preloadData$1 as preloadData, refreshAll$1 as refreshAll };
|
|
154
154
|
|
|
155
155
|
//# sourceMappingURL=Navigation.js.map
|