@thomasfosterau/effect-sveltekit 0.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/LICENSE +21 -0
- package/README.md +66 -0
- package/dist/Hooks.d.ts +33 -0
- package/dist/Hooks.js +34 -0
- package/dist/Hooks.js.map +1 -0
- package/dist/Navigation.d.ts +110 -0
- package/dist/Navigation.js +155 -0
- package/dist/Navigation.js.map +1 -0
- package/dist/Remote.d.ts +52 -0
- package/dist/Remote.js +67 -0
- package/dist/Remote.js.map +1 -0
- package/dist/State.d.ts +17 -0
- package/dist/State.js +65 -0
- package/dist/State.js.map +1 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/adapter/handler.d.ts +67 -0
- package/dist/adapter/handler.js +158 -0
- package/dist/adapter/handler.js.map +1 -0
- package/dist/adapter/index.d.ts +29 -0
- package/dist/adapter/index.js +105 -0
- package/dist/adapter/index.js.map +1 -0
- package/dist/adapter/serve.d.ts +46 -0
- package/dist/adapter/serve.js +57 -0
- package/dist/adapter/serve.js.map +1 -0
- package/dist/app-runtime.d.ts +212 -0
- package/dist/app-runtime.js +173 -0
- package/dist/app-runtime.js.map +1 -0
- package/dist/client/Hooks.d.ts +48 -0
- package/dist/client/Hooks.js +61 -0
- package/dist/client/Hooks.js.map +1 -0
- package/dist/client.d.ts +6 -0
- package/dist/client.js +6 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.js +51 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/internal/app-state.d.ts +39 -0
- package/dist/internal/app-state.js +52 -0
- package/dist/internal/app-state.js.map +1 -0
- package/dist/internal/auto.d.ts +70 -0
- package/dist/internal/auto.js +161 -0
- package/dist/internal/auto.js.map +1 -0
- package/dist/internal/default-runtime.js +21 -0
- package/dist/internal/default-runtime.js.map +1 -0
- package/dist/internal/error.js +31 -0
- package/dist/internal/error.js.map +1 -0
- package/dist/internal/navigation-events.js +41 -0
- package/dist/internal/navigation-events.js.map +1 -0
- package/dist/remote-reactive.d.ts +38 -0
- package/dist/remote-reactive.js +44 -0
- package/dist/remote-reactive.js.map +1 -0
- package/dist/remote.server.d.ts +48 -0
- package/dist/remote.server.js +90 -0
- package/dist/remote.server.js.map +1 -0
- package/dist/runtime.d.ts +130 -0
- package/dist/runtime.js +143 -0
- package/dist/runtime.js.map +1 -0
- package/dist/server/Endpoint.d.ts +101 -0
- package/dist/server/Endpoint.js +109 -0
- package/dist/server/Endpoint.js.map +1 -0
- package/dist/server/Hooks.d.ts +97 -0
- package/dist/server/Hooks.js +108 -0
- package/dist/server/Hooks.js.map +1 -0
- package/dist/server.d.ts +108 -0
- package/dist/server.js +131 -0
- package/dist/server.js.map +1 -0
- package/dist/transport.d.ts +23 -0
- package/dist/transport.js +34 -0
- package/dist/transport.js.map +1 -0
- package/dist/universal.d.ts +35 -0
- package/dist/universal.js +36 -0
- package/dist/universal.js.map +1 -0
- package/dist/vite.d.ts +42 -0
- package/dist/vite.js +242 -0
- package/dist/vite.js.map +1 -0
- package/package.json +101 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { SvelteKitServices } from "../app-runtime.js";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import { Handle, HandleFetch, HandleServerError, ServerInit } from "@sveltejs/kit";
|
|
4
|
+
|
|
5
|
+
//#region src/server/Hooks.d.ts
|
|
6
|
+
declare namespace Hooks_d_exports {
|
|
7
|
+
export { handle, handleError, handleFetch, init };
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Wraps an Effect-based function as a SvelteKit
|
|
11
|
+
* [`handle`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle) hook, which
|
|
12
|
+
* runs on every request and controls how the response is produced.
|
|
13
|
+
*
|
|
14
|
+
* SvelteKit control flow (`redirect()`, `error()`) raised inside the effect is
|
|
15
|
+
* passed through to SvelteKit.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* // src/hooks.server.ts
|
|
20
|
+
* import { Hooks } from '@thomasfosterau/effect-sveltekit/server';
|
|
21
|
+
* import { Effect } from 'effect';
|
|
22
|
+
*
|
|
23
|
+
* export const handle = Hooks.handle(({ event, resolve }) =>
|
|
24
|
+
* Effect.gen(function* () {
|
|
25
|
+
* // custom logic before resolve
|
|
26
|
+
* const response = yield* Effect.promise(() => resolve(event));
|
|
27
|
+
* // custom logic after resolve
|
|
28
|
+
* return response;
|
|
29
|
+
* })
|
|
30
|
+
* );
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
declare function handle(fn: (args: Parameters<Handle>[0]) => Effect.Effect<Response, unknown, SvelteKitServices>): Handle;
|
|
34
|
+
/**
|
|
35
|
+
* Wraps an Effect-based function as a SvelteKit
|
|
36
|
+
* [`handleFetch`](https://svelte.dev/docs/kit/hooks#Server-hooks-handleFetch)
|
|
37
|
+
* hook, which intercepts `event.fetch` calls made on the server (in `load`,
|
|
38
|
+
* actions, endpoints, ...). The effect produces the `Response` to use.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* // src/hooks.server.ts
|
|
43
|
+
* import { Hooks } from '@thomasfosterau/effect-sveltekit/server';
|
|
44
|
+
* import { Effect } from 'effect';
|
|
45
|
+
*
|
|
46
|
+
* export const handleFetch = Hooks.handleFetch(({ request, fetch }) =>
|
|
47
|
+
* Effect.gen(function* () {
|
|
48
|
+
* // Redirect internal API calls to the upstream service.
|
|
49
|
+
* const url = request.url.replace('https://api.internal', 'http://localhost:9999');
|
|
50
|
+
* return yield* Effect.promise(() => fetch(new Request(url, request)));
|
|
51
|
+
* })
|
|
52
|
+
* );
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
declare function handleFetch(fn: (args: Parameters<HandleFetch>[0]) => Effect.Effect<Response, unknown, SvelteKitServices>): HandleFetch;
|
|
56
|
+
/**
|
|
57
|
+
* Wraps an Effect-based function as the SvelteKit server
|
|
58
|
+
* [`handleError`](https://svelte.dev/docs/kit/hooks#Shared-hooks-handleError)
|
|
59
|
+
* hook, which runs when an unexpected error is thrown while responding to a
|
|
60
|
+
* request. The effect receives the error and request event and produces the
|
|
61
|
+
* shape exposed to the client (your `App.Error`, or nothing).
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* // src/hooks.server.ts
|
|
66
|
+
* import { Hooks } from '@thomasfosterau/effect-sveltekit/server';
|
|
67
|
+
* import { Effect } from 'effect';
|
|
68
|
+
*
|
|
69
|
+
* export const handleError = Hooks.handleError(({ error, event }) =>
|
|
70
|
+
* Effect.gen(function* () {
|
|
71
|
+
* const id = crypto.randomUUID();
|
|
72
|
+
* yield* Effect.logError(`${event.url.pathname} (${id})`, error);
|
|
73
|
+
* return { message: 'Internal Error', id };
|
|
74
|
+
* })
|
|
75
|
+
* );
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
declare function handleError(fn: (args: Parameters<HandleServerError>[0]) => Effect.Effect<Awaited<ReturnType<HandleServerError>>, unknown, SvelteKitServices>): HandleServerError;
|
|
79
|
+
/**
|
|
80
|
+
* Wraps an Effect as the SvelteKit server
|
|
81
|
+
* [`init`](https://svelte.dev/docs/kit/hooks#Shared-hooks-init) hook, which
|
|
82
|
+
* runs once before the server responds to its first request. There is no
|
|
83
|
+
* request event available, so the effect runs without per-request services.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* // src/hooks.server.ts
|
|
88
|
+
* import { Hooks } from '@thomasfosterau/effect-sveltekit/server';
|
|
89
|
+
* import { Effect } from 'effect';
|
|
90
|
+
*
|
|
91
|
+
* export const init = Hooks.init(Effect.logInfo('server starting up'));
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
declare function init(effect: Effect.Effect<void, unknown>): ServerInit;
|
|
95
|
+
//#endregion
|
|
96
|
+
export { Hooks_d_exports };
|
|
97
|
+
//# sourceMappingURL=Hooks.d.ts.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { defaultServerRuntime } from "../internal/default-runtime.js";
|
|
3
|
+
import "effect";
|
|
4
|
+
//#region src/server/Hooks.ts
|
|
5
|
+
var Hooks_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
handle: () => handle,
|
|
7
|
+
handleError: () => handleError,
|
|
8
|
+
handleFetch: () => handleFetch,
|
|
9
|
+
init: () => init
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Wraps an Effect-based function as a SvelteKit
|
|
13
|
+
* [`handle`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle) hook, which
|
|
14
|
+
* runs on every request and controls how the response is produced.
|
|
15
|
+
*
|
|
16
|
+
* SvelteKit control flow (`redirect()`, `error()`) raised inside the effect is
|
|
17
|
+
* passed through to SvelteKit.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* // src/hooks.server.ts
|
|
22
|
+
* import { Hooks } from '@thomasfosterau/effect-sveltekit/server';
|
|
23
|
+
* import { Effect } from 'effect';
|
|
24
|
+
*
|
|
25
|
+
* export const handle = Hooks.handle(({ event, resolve }) =>
|
|
26
|
+
* Effect.gen(function* () {
|
|
27
|
+
* // custom logic before resolve
|
|
28
|
+
* const response = yield* Effect.promise(() => resolve(event));
|
|
29
|
+
* // custom logic after resolve
|
|
30
|
+
* return response;
|
|
31
|
+
* })
|
|
32
|
+
* );
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
function handle(fn) {
|
|
36
|
+
return defaultServerRuntime().handle(fn);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Wraps an Effect-based function as a SvelteKit
|
|
40
|
+
* [`handleFetch`](https://svelte.dev/docs/kit/hooks#Server-hooks-handleFetch)
|
|
41
|
+
* hook, which intercepts `event.fetch` calls made on the server (in `load`,
|
|
42
|
+
* actions, endpoints, ...). The effect produces the `Response` to use.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* // src/hooks.server.ts
|
|
47
|
+
* import { Hooks } from '@thomasfosterau/effect-sveltekit/server';
|
|
48
|
+
* import { Effect } from 'effect';
|
|
49
|
+
*
|
|
50
|
+
* export const handleFetch = Hooks.handleFetch(({ request, fetch }) =>
|
|
51
|
+
* Effect.gen(function* () {
|
|
52
|
+
* // Redirect internal API calls to the upstream service.
|
|
53
|
+
* const url = request.url.replace('https://api.internal', 'http://localhost:9999');
|
|
54
|
+
* return yield* Effect.promise(() => fetch(new Request(url, request)));
|
|
55
|
+
* })
|
|
56
|
+
* );
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
function handleFetch(fn) {
|
|
60
|
+
return defaultServerRuntime().handleFetch(fn);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Wraps an Effect-based function as the SvelteKit server
|
|
64
|
+
* [`handleError`](https://svelte.dev/docs/kit/hooks#Shared-hooks-handleError)
|
|
65
|
+
* hook, which runs when an unexpected error is thrown while responding to a
|
|
66
|
+
* request. The effect receives the error and request event and produces the
|
|
67
|
+
* shape exposed to the client (your `App.Error`, or nothing).
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* // src/hooks.server.ts
|
|
72
|
+
* import { Hooks } from '@thomasfosterau/effect-sveltekit/server';
|
|
73
|
+
* import { Effect } from 'effect';
|
|
74
|
+
*
|
|
75
|
+
* export const handleError = Hooks.handleError(({ error, event }) =>
|
|
76
|
+
* Effect.gen(function* () {
|
|
77
|
+
* const id = crypto.randomUUID();
|
|
78
|
+
* yield* Effect.logError(`${event.url.pathname} (${id})`, error);
|
|
79
|
+
* return { message: 'Internal Error', id };
|
|
80
|
+
* })
|
|
81
|
+
* );
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
function handleError(fn) {
|
|
85
|
+
return defaultServerRuntime().handleError(fn);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Wraps an Effect as the SvelteKit server
|
|
89
|
+
* [`init`](https://svelte.dev/docs/kit/hooks#Shared-hooks-init) hook, which
|
|
90
|
+
* runs once before the server responds to its first request. There is no
|
|
91
|
+
* request event available, so the effect runs without per-request services.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* // src/hooks.server.ts
|
|
96
|
+
* import { Hooks } from '@thomasfosterau/effect-sveltekit/server';
|
|
97
|
+
* import { Effect } from 'effect';
|
|
98
|
+
*
|
|
99
|
+
* export const init = Hooks.init(Effect.logInfo('server starting up'));
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
function init(effect) {
|
|
103
|
+
return defaultServerRuntime().init(effect);
|
|
104
|
+
}
|
|
105
|
+
//#endregion
|
|
106
|
+
export { Hooks_exports };
|
|
107
|
+
|
|
108
|
+
//# sourceMappingURL=Hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Hooks.js","names":[],"sources":["../../src/server/Hooks.ts"],"sourcesContent":["/**\n * Effect wrappers for SvelteKit's server-side hooks (`src/hooks.server.ts`),\n * exposed as the `Hooks` namespace of `@thomasfosterau/effect-sveltekit/server`.\n *\n * Each helper turns an Effect (or a function returning one) into the\n * function-shaped export SvelteKit expects. Effects run on the SvelteKit server\n * runtime, so they have access to platform services (`HttpClient`, the\n * `RequestEvent`, ...). To additionally provide your application's services,\n * use the matching methods on an app-wide runtime from `makeServerRuntime`.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { Hooks } from '@thomasfosterau/effect-sveltekit/server';\n * import { Effect } from 'effect';\n *\n * export const handle = Hooks.handle(({ event, resolve }) =>\n * Effect.gen(function* () {\n * const response = yield* Effect.promise(() => resolve(event));\n * yield* Effect.logInfo(`${event.url.pathname} -> ${response.status}`);\n * return response;\n * })\n * );\n * ```\n */\n\nimport type { Handle, HandleFetch, HandleServerError, ServerInit } from \"@sveltejs/kit\";\nimport { Effect } from \"effect\";\nimport type { SvelteKitServices } from \"../app-runtime.js\";\nimport { defaultServerRuntime } from \"../internal/default-runtime.js\";\n\n/**\n * Wraps an Effect-based function as a SvelteKit\n * [`handle`](https://svelte.dev/docs/kit/hooks#Server-hooks-handle) hook, which\n * runs on every request and controls how the response is produced.\n *\n * SvelteKit control flow (`redirect()`, `error()`) raised inside the effect is\n * passed through to SvelteKit.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { Hooks } from '@thomasfosterau/effect-sveltekit/server';\n * import { Effect } from 'effect';\n *\n * export const handle = Hooks.handle(({ event, resolve }) =>\n * Effect.gen(function* () {\n * // custom logic before resolve\n * const response = yield* Effect.promise(() => resolve(event));\n * // custom logic after resolve\n * return response;\n * })\n * );\n * ```\n */\nexport function handle(\n fn: (args: Parameters<Handle>[0]) => Effect.Effect<Response, unknown, SvelteKitServices>,\n): Handle {\n return defaultServerRuntime().handle(fn);\n}\n\n/**\n * Wraps an Effect-based function as a SvelteKit\n * [`handleFetch`](https://svelte.dev/docs/kit/hooks#Server-hooks-handleFetch)\n * hook, which intercepts `event.fetch` calls made on the server (in `load`,\n * actions, endpoints, ...). The effect produces the `Response` to use.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { Hooks } from '@thomasfosterau/effect-sveltekit/server';\n * import { Effect } from 'effect';\n *\n * export const handleFetch = Hooks.handleFetch(({ request, fetch }) =>\n * Effect.gen(function* () {\n * // Redirect internal API calls to the upstream service.\n * const url = request.url.replace('https://api.internal', 'http://localhost:9999');\n * return yield* Effect.promise(() => fetch(new Request(url, request)));\n * })\n * );\n * ```\n */\nexport function handleFetch(\n fn: (args: Parameters<HandleFetch>[0]) => Effect.Effect<Response, unknown, SvelteKitServices>,\n): HandleFetch {\n return defaultServerRuntime().handleFetch(fn);\n}\n\n/**\n * Wraps an Effect-based function as the SvelteKit server\n * [`handleError`](https://svelte.dev/docs/kit/hooks#Shared-hooks-handleError)\n * hook, which runs when an unexpected error is thrown while responding to a\n * request. The effect receives the error and request event and produces the\n * shape exposed to the client (your `App.Error`, or nothing).\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { Hooks } from '@thomasfosterau/effect-sveltekit/server';\n * import { Effect } from 'effect';\n *\n * export const handleError = Hooks.handleError(({ error, event }) =>\n * Effect.gen(function* () {\n * const id = crypto.randomUUID();\n * yield* Effect.logError(`${event.url.pathname} (${id})`, error);\n * return { message: 'Internal Error', id };\n * })\n * );\n * ```\n */\nexport function handleError(\n fn: (\n args: Parameters<HandleServerError>[0],\n ) => Effect.Effect<Awaited<ReturnType<HandleServerError>>, unknown, SvelteKitServices>,\n): HandleServerError {\n return defaultServerRuntime().handleError(fn);\n}\n\n/**\n * Wraps an Effect as the SvelteKit server\n * [`init`](https://svelte.dev/docs/kit/hooks#Shared-hooks-init) hook, which\n * runs once before the server responds to its first request. There is no\n * request event available, so the effect runs without per-request services.\n *\n * @example\n * ```ts\n * // src/hooks.server.ts\n * import { Hooks } from '@thomasfosterau/effect-sveltekit/server';\n * import { Effect } from 'effect';\n *\n * export const init = Hooks.init(Effect.logInfo('server starting up'));\n * ```\n */\nexport function init(effect: Effect.Effect<void, unknown>): ServerInit {\n return defaultServerRuntime().init(effect);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuDA,SAAgB,OACd,IACQ;CACR,OAAO,qBAAqB,EAAE,OAAO,EAAE;AACzC;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,YACd,IACa;CACb,OAAO,qBAAqB,EAAE,YAAY,EAAE;AAC9C;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,YACd,IAGmB;CACnB,OAAO,qBAAqB,EAAE,YAAY,EAAE;AAC9C;;;;;;;;;;;;;;;;AAiBA,SAAgB,KAAK,QAAkD;CACrE,OAAO,qBAAqB,EAAE,KAAK,MAAM;AAC3C"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { SvelteKitRequestEvent, SvelteKitRuntime, runWithSvelteKitRuntime } from "./runtime.js";
|
|
2
|
+
import { RequestRuntime, ServerRuntime, SvelteKitServices, makeServerRuntime } from "./app-runtime.js";
|
|
3
|
+
import { sveltekitConfig, sveltekitConfigProvider } from "./config.js";
|
|
4
|
+
import { Hooks_d_exports } from "./server/Hooks.js";
|
|
5
|
+
import { Endpoint_d_exports } from "./server/Endpoint.js";
|
|
6
|
+
import { RemoteFunction } from "./remote.server.js";
|
|
7
|
+
import { Effect } from "effect";
|
|
8
|
+
import { Action, Actions, RequestEvent, ServerLoad } from "@sveltejs/kit";
|
|
9
|
+
|
|
10
|
+
//#region src/server.d.ts
|
|
11
|
+
/**
|
|
12
|
+
* Wraps an Effect-based function to work as a SvelteKit server load function.
|
|
13
|
+
* The effect has access to platform services (HttpClient, the RequestEvent, etc.)
|
|
14
|
+
* via the SvelteKit runtime.
|
|
15
|
+
*
|
|
16
|
+
* SvelteKit control flow (`redirect()`, `error()`) raised inside the effect is
|
|
17
|
+
* passed through to SvelteKit.
|
|
18
|
+
*
|
|
19
|
+
* To give effects access to your own application services, create an
|
|
20
|
+
* app-wide runtime with {@link makeServerRuntime} and use its `serverLoad`
|
|
21
|
+
* instead.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { serverLoad } from '@thomasfosterau/effect-sveltekit/server';
|
|
26
|
+
* import { Effect } from 'effect';
|
|
27
|
+
* import * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
28
|
+
*
|
|
29
|
+
* export const load = serverLoad((event) =>
|
|
30
|
+
* Effect.gen(function* () {
|
|
31
|
+
* const client = yield* HttpClient.HttpClient;
|
|
32
|
+
* const response = yield* client.get("https://api.example.com/data");
|
|
33
|
+
* return { data: yield* response.json };
|
|
34
|
+
* })
|
|
35
|
+
* );
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare function serverLoad<Params extends Record<string, string> = any, ParentData extends Record<string, any> = any, OutputData extends Record<string, any> | void = any, RouteId extends string | null = any>(fn: (event: RequestEvent<Params, RouteId>) => Effect.Effect<OutputData, unknown, SvelteKitServices>): ServerLoad<Params, ParentData, OutputData, RouteId>;
|
|
39
|
+
/**
|
|
40
|
+
* Wraps an Effect-based function to work as a SvelteKit action handler.
|
|
41
|
+
* The effect has access to platform services (HttpClient, the RequestEvent, etc.)
|
|
42
|
+
* via the SvelteKit runtime.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { action } from '@thomasfosterau/effect-sveltekit/server';
|
|
47
|
+
* import { Effect } from 'effect';
|
|
48
|
+
*
|
|
49
|
+
* export const actions = {
|
|
50
|
+
* default: action((event) =>
|
|
51
|
+
* Effect.gen(function* () {
|
|
52
|
+
* const formData = yield* Effect.promise(() => event.request.formData());
|
|
53
|
+
* // Process form data
|
|
54
|
+
* return { success: true };
|
|
55
|
+
* })
|
|
56
|
+
* )
|
|
57
|
+
* };
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare function action<Params extends Record<string, string> = any, OutputData extends Record<string, any> | void = any, RouteId extends string | null = any>(fn: (event: RequestEvent<Params, RouteId>) => Effect.Effect<OutputData, unknown, SvelteKitServices>): Action<Params, OutputData, RouteId>;
|
|
61
|
+
/**
|
|
62
|
+
* Creates SvelteKit actions from an object of Effect-based action handlers.
|
|
63
|
+
* Each action will have access to platform services via the SvelteKit runtime.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* import { actions } from '@thomasfosterau/effect-sveltekit/server';
|
|
68
|
+
* import { Effect } from 'effect';
|
|
69
|
+
*
|
|
70
|
+
* export const actions = actions({
|
|
71
|
+
* create: (event) => Effect.succeed({ created: true }),
|
|
72
|
+
* delete: (event) => Effect.succeed({ deleted: true })
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
declare function actions<Params extends Record<string, string> = any, OutputData extends Record<string, any> | void = any, RouteId extends string | null = any>(actionsMap: Record<string, (event: RequestEvent<Params, RouteId>) => Effect.Effect<OutputData, unknown, SvelteKitServices>>): Actions<Params, OutputData, RouteId>;
|
|
77
|
+
/**
|
|
78
|
+
* Wraps an Effect-based function to work as a SvelteKit API endpoint handler.
|
|
79
|
+
* The effect has access to platform services (HttpClient, the RequestEvent, etc.)
|
|
80
|
+
* via the SvelteKit runtime.
|
|
81
|
+
*
|
|
82
|
+
* SvelteKit control flow (`redirect()`, `error()`) raised inside the effect is
|
|
83
|
+
* passed through to SvelteKit. For any other failure, the error is logged
|
|
84
|
+
* server-side and a generic error message is returned to clients. For
|
|
85
|
+
* development/debugging, you can pass options to expose full error details.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* import { endpoint } from '@thomasfosterau/effect-sveltekit/server';
|
|
90
|
+
* import { Effect } from 'effect';
|
|
91
|
+
* import { json } from '@sveltejs/kit';
|
|
92
|
+
* import * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
93
|
+
*
|
|
94
|
+
* export const GET = endpoint((event) =>
|
|
95
|
+
* Effect.gen(function* () {
|
|
96
|
+
* const client = yield* HttpClient.HttpClient;
|
|
97
|
+
* const response = yield* client.get("https://api.example.com/data");
|
|
98
|
+
* return json(yield* response.json);
|
|
99
|
+
* })
|
|
100
|
+
* );
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
declare function endpoint<Params extends Record<string, string> = any, RouteId extends string | null = any>(fn: (event: RequestEvent<Params, RouteId>) => Effect.Effect<Response, unknown, SvelteKitServices>, options?: {
|
|
104
|
+
exposeErrors?: boolean;
|
|
105
|
+
}): (event: RequestEvent<Params, RouteId>) => Promise<Response>;
|
|
106
|
+
//#endregion
|
|
107
|
+
export { Endpoint_d_exports as Endpoint, Hooks_d_exports as Hooks, RemoteFunction, type RequestRuntime, type ServerRuntime, SvelteKitRequestEvent, SvelteKitRuntime, type SvelteKitServices, action, actions, endpoint, makeServerRuntime, runWithSvelteKitRuntime, serverLoad, sveltekitConfig, sveltekitConfigProvider };
|
|
108
|
+
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { SvelteKitRequestEvent, SvelteKitRuntime, runWithSvelteKitRuntime } from "./runtime.js";
|
|
2
|
+
import { makeServerRuntime } from "./app-runtime.js";
|
|
3
|
+
import { defaultServerRuntime } from "./internal/default-runtime.js";
|
|
4
|
+
import { sveltekitConfig, sveltekitConfigProvider } from "./config.js";
|
|
5
|
+
import { Hooks_exports } from "./server/Hooks.js";
|
|
6
|
+
import { Endpoint_exports } from "./server/Endpoint.js";
|
|
7
|
+
import { RemoteFunction } from "./remote.server.js";
|
|
8
|
+
import { Cause, Exit } from "effect";
|
|
9
|
+
import { isHttpError, isRedirect } from "@sveltejs/kit";
|
|
10
|
+
//#region src/server.ts
|
|
11
|
+
/**
|
|
12
|
+
* Wraps an Effect-based function to work as a SvelteKit server load function.
|
|
13
|
+
* The effect has access to platform services (HttpClient, the RequestEvent, etc.)
|
|
14
|
+
* via the SvelteKit runtime.
|
|
15
|
+
*
|
|
16
|
+
* SvelteKit control flow (`redirect()`, `error()`) raised inside the effect is
|
|
17
|
+
* passed through to SvelteKit.
|
|
18
|
+
*
|
|
19
|
+
* To give effects access to your own application services, create an
|
|
20
|
+
* app-wide runtime with {@link makeServerRuntime} and use its `serverLoad`
|
|
21
|
+
* instead.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* import { serverLoad } from '@thomasfosterau/effect-sveltekit/server';
|
|
26
|
+
* import { Effect } from 'effect';
|
|
27
|
+
* import * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
28
|
+
*
|
|
29
|
+
* export const load = serverLoad((event) =>
|
|
30
|
+
* Effect.gen(function* () {
|
|
31
|
+
* const client = yield* HttpClient.HttpClient;
|
|
32
|
+
* const response = yield* client.get("https://api.example.com/data");
|
|
33
|
+
* return { data: yield* response.json };
|
|
34
|
+
* })
|
|
35
|
+
* );
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
function serverLoad(fn) {
|
|
39
|
+
return defaultServerRuntime().serverLoad(fn);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Wraps an Effect-based function to work as a SvelteKit action handler.
|
|
43
|
+
* The effect has access to platform services (HttpClient, the RequestEvent, etc.)
|
|
44
|
+
* via the SvelteKit runtime.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* import { action } from '@thomasfosterau/effect-sveltekit/server';
|
|
49
|
+
* import { Effect } from 'effect';
|
|
50
|
+
*
|
|
51
|
+
* export const actions = {
|
|
52
|
+
* default: action((event) =>
|
|
53
|
+
* Effect.gen(function* () {
|
|
54
|
+
* const formData = yield* Effect.promise(() => event.request.formData());
|
|
55
|
+
* // Process form data
|
|
56
|
+
* return { success: true };
|
|
57
|
+
* })
|
|
58
|
+
* )
|
|
59
|
+
* };
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
function action(fn) {
|
|
63
|
+
return defaultServerRuntime().action(fn);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Creates SvelteKit actions from an object of Effect-based action handlers.
|
|
67
|
+
* Each action will have access to platform services via the SvelteKit runtime.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { actions } from '@thomasfosterau/effect-sveltekit/server';
|
|
72
|
+
* import { Effect } from 'effect';
|
|
73
|
+
*
|
|
74
|
+
* export const actions = actions({
|
|
75
|
+
* create: (event) => Effect.succeed({ created: true }),
|
|
76
|
+
* delete: (event) => Effect.succeed({ deleted: true })
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
function actions(actionsMap) {
|
|
81
|
+
return defaultServerRuntime().actions(actionsMap);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Wraps an Effect-based function to work as a SvelteKit API endpoint handler.
|
|
85
|
+
* The effect has access to platform services (HttpClient, the RequestEvent, etc.)
|
|
86
|
+
* via the SvelteKit runtime.
|
|
87
|
+
*
|
|
88
|
+
* SvelteKit control flow (`redirect()`, `error()`) raised inside the effect is
|
|
89
|
+
* passed through to SvelteKit. For any other failure, the error is logged
|
|
90
|
+
* server-side and a generic error message is returned to clients. For
|
|
91
|
+
* development/debugging, you can pass options to expose full error details.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { endpoint } from '@thomasfosterau/effect-sveltekit/server';
|
|
96
|
+
* import { Effect } from 'effect';
|
|
97
|
+
* import { json } from '@sveltejs/kit';
|
|
98
|
+
* import * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
99
|
+
*
|
|
100
|
+
* export const GET = endpoint((event) =>
|
|
101
|
+
* Effect.gen(function* () {
|
|
102
|
+
* const client = yield* HttpClient.HttpClient;
|
|
103
|
+
* const response = yield* client.get("https://api.example.com/data");
|
|
104
|
+
* return json(yield* response.json);
|
|
105
|
+
* })
|
|
106
|
+
* );
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
function endpoint(fn, options) {
|
|
110
|
+
const { exposeErrors = false } = options ?? {};
|
|
111
|
+
return async (event) => {
|
|
112
|
+
const exit = await defaultServerRuntime().runPromiseExit(event, fn(event));
|
|
113
|
+
return Exit.match(exit, {
|
|
114
|
+
onFailure: (cause) => {
|
|
115
|
+
const squashed = Cause.squash(cause);
|
|
116
|
+
if (isRedirect(squashed) || isHttpError(squashed)) throw squashed;
|
|
117
|
+
console.error("Endpoint error:", Cause.pretty(cause));
|
|
118
|
+
const clientMessage = exposeErrors ? Cause.pretty(cause) : "Internal server error";
|
|
119
|
+
return new Response(JSON.stringify({ error: clientMessage }), {
|
|
120
|
+
status: 500,
|
|
121
|
+
headers: { "Content-Type": "application/json" }
|
|
122
|
+
});
|
|
123
|
+
},
|
|
124
|
+
onSuccess: (value) => value
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//#endregion
|
|
129
|
+
export { Endpoint_exports as Endpoint, Hooks_exports as Hooks, RemoteFunction, SvelteKitRequestEvent, SvelteKitRuntime, action, actions, endpoint, makeServerRuntime, runWithSvelteKitRuntime, serverLoad, sveltekitConfig, sveltekitConfigProvider };
|
|
130
|
+
|
|
131
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","names":["runtime"],"sources":["../src/server.ts"],"sourcesContent":["import type { Action, Actions, RequestEvent, ServerLoad } from \"@sveltejs/kit\";\nimport { Effect, Exit, Cause } from \"effect\";\nimport { isHttpError, isRedirect } from \"@sveltejs/kit\";\nimport type { SvelteKitServices } from \"./app-runtime.js\";\nimport { defaultServerRuntime as runtime } from \"./internal/default-runtime.js\";\n\nexport type { SvelteKitServices };\n\n/**\n * Wraps an Effect-based function to work as a SvelteKit server load function.\n * The effect has access to platform services (HttpClient, the RequestEvent, etc.)\n * via the SvelteKit runtime.\n *\n * SvelteKit control flow (`redirect()`, `error()`) raised inside the effect is\n * passed through to SvelteKit.\n *\n * To give effects access to your own application services, create an\n * app-wide runtime with {@link makeServerRuntime} and use its `serverLoad`\n * instead.\n *\n * @example\n * ```ts\n * import { serverLoad } from '@thomasfosterau/effect-sveltekit/server';\n * import { Effect } from 'effect';\n * import * as HttpClient from 'effect/unstable/http/HttpClient';\n *\n * export const load = serverLoad((event) =>\n * Effect.gen(function* () {\n * const client = yield* HttpClient.HttpClient;\n * const response = yield* client.get(\"https://api.example.com/data\");\n * return { data: yield* response.json };\n * })\n * );\n * ```\n */\nexport function serverLoad<\n Params extends Record<string, string> = any,\n ParentData extends Record<string, any> = any,\n OutputData extends Record<string, any> | void = any,\n RouteId extends string | null = any,\n>(\n fn: (\n event: RequestEvent<Params, RouteId>,\n ) => Effect.Effect<OutputData, unknown, SvelteKitServices>,\n): ServerLoad<Params, ParentData, OutputData, RouteId> {\n return runtime().serverLoad(fn);\n}\n\n/**\n * Wraps an Effect-based function to work as a SvelteKit action handler.\n * The effect has access to platform services (HttpClient, the RequestEvent, etc.)\n * via the SvelteKit runtime.\n *\n * @example\n * ```ts\n * import { action } from '@thomasfosterau/effect-sveltekit/server';\n * import { Effect } from 'effect';\n *\n * export const actions = {\n * default: action((event) =>\n * Effect.gen(function* () {\n * const formData = yield* Effect.promise(() => event.request.formData());\n * // Process form data\n * return { success: true };\n * })\n * )\n * };\n * ```\n */\nexport function action<\n Params extends Record<string, string> = any,\n OutputData extends Record<string, any> | void = any,\n RouteId extends string | null = any,\n>(\n fn: (\n event: RequestEvent<Params, RouteId>,\n ) => Effect.Effect<OutputData, unknown, SvelteKitServices>,\n): Action<Params, OutputData, RouteId> {\n return runtime().action(fn);\n}\n\n/**\n * Creates SvelteKit actions from an object of Effect-based action handlers.\n * Each action will have access to platform services via the SvelteKit runtime.\n *\n * @example\n * ```ts\n * import { actions } from '@thomasfosterau/effect-sveltekit/server';\n * import { Effect } from 'effect';\n *\n * export const actions = actions({\n * create: (event) => Effect.succeed({ created: true }),\n * delete: (event) => Effect.succeed({ deleted: true })\n * });\n * ```\n */\nexport function actions<\n Params extends Record<string, string> = any,\n OutputData extends Record<string, any> | void = any,\n RouteId extends string | null = any,\n>(\n actionsMap: Record<\n string,\n (event: RequestEvent<Params, RouteId>) => Effect.Effect<OutputData, unknown, SvelteKitServices>\n >,\n): Actions<Params, OutputData, RouteId> {\n return runtime().actions(actionsMap);\n}\n\n/**\n * Wraps an Effect-based function to work as a SvelteKit API endpoint handler.\n * The effect has access to platform services (HttpClient, the RequestEvent, etc.)\n * via the SvelteKit runtime.\n *\n * SvelteKit control flow (`redirect()`, `error()`) raised inside the effect is\n * passed through to SvelteKit. For any other failure, the error is logged\n * server-side and a generic error message is returned to clients. For\n * development/debugging, you can pass options to expose full error details.\n *\n * @example\n * ```ts\n * import { endpoint } from '@thomasfosterau/effect-sveltekit/server';\n * import { Effect } from 'effect';\n * import { json } from '@sveltejs/kit';\n * import * as HttpClient from 'effect/unstable/http/HttpClient';\n *\n * export const GET = endpoint((event) =>\n * Effect.gen(function* () {\n * const client = yield* HttpClient.HttpClient;\n * const response = yield* client.get(\"https://api.example.com/data\");\n * return json(yield* response.json);\n * })\n * );\n * ```\n */\nexport function endpoint<\n Params extends Record<string, string> = any,\n RouteId extends string | null = any,\n>(\n fn: (event: RequestEvent<Params, RouteId>) => Effect.Effect<Response, unknown, SvelteKitServices>,\n options?: { exposeErrors?: boolean },\n): (event: RequestEvent<Params, RouteId>) => Promise<Response> {\n const { exposeErrors = false } = options ?? {};\n\n return async (event) => {\n const exit = await runtime().runPromiseExit(event as RequestEvent, fn(event));\n\n return Exit.match(exit, {\n onFailure: (cause) => {\n // Let SvelteKit handle its own control flow objects.\n const squashed = Cause.squash(cause);\n if (isRedirect(squashed) || isHttpError(squashed)) {\n throw squashed;\n }\n\n // Always log the full error server-side for debugging\n console.error(\"Endpoint error:\", Cause.pretty(cause));\n\n // Return generic error message to client unless explicitly enabled\n const clientMessage = exposeErrors ? Cause.pretty(cause) : \"Internal server error\";\n\n return new Response(JSON.stringify({ error: clientMessage }), {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n });\n },\n onSuccess: (value) => value,\n });\n };\n}\n\n/**\n * Effect wrappers for the server-side hooks (`hooks.server.ts`): the `Hooks`\n * namespace exposes `handle`, `handleFetch`, `handleError`, and `init`.\n */\nexport * as Hooks from \"./server/Hooks.js\";\n\n/**\n * Create SvelteKit `+server.ts` endpoints backed by Effect: the `Endpoint`\n * namespace exposes `fromApi` (an `HttpApi`), `fromRouter` (an `HttpRouter`),\n * and `fromHttpEffect` (a single HTTP route effect).\n */\nexport * as Endpoint from \"./server/Endpoint.js\";\n\n/**\n * App-wide runtime: define your application's Effect services once and share\n * them across every request.\n */\nexport { makeServerRuntime, type ServerRuntime, type RequestRuntime } from \"./app-runtime.js\";\n\n/**\n * Export the SvelteKit runtime utilities for advanced use cases.\n */\nexport { SvelteKitRuntime, runWithSvelteKitRuntime, SvelteKitRequestEvent } from \"./runtime.js\";\nexport { RemoteFunction } from \"./remote.server.js\";\n\n/**\n * SvelteKit `$env` ⇄ Effect `Config` (see {@link sveltekitConfig}). The\n * Effect Schema ⇄ SvelteKit `transport` hook lives on the universal `Hooks`\n * namespace (`Hooks.transport`) in `@thomasfosterau/effect-sveltekit`.\n */\nexport { sveltekitConfig, sveltekitConfigProvider } from \"./config.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,SAAgB,WAMd,IAGqD;CACrD,OAAOA,qBAAQ,EAAE,WAAW,EAAE;AAChC;;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,OAKd,IAGqC;CACrC,OAAOA,qBAAQ,EAAE,OAAO,EAAE;AAC5B;;;;;;;;;;;;;;;;AAiBA,SAAgB,QAKd,YAIsC;CACtC,OAAOA,qBAAQ,EAAE,QAAQ,UAAU;AACrC;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,SAId,IACA,SAC6D;CAC7D,MAAM,EAAE,eAAe,UAAU,WAAW,CAAC;CAE7C,OAAO,OAAO,UAAU;EACtB,MAAM,OAAO,MAAMA,qBAAQ,EAAE,eAAe,OAAuB,GAAG,KAAK,CAAC;EAE5E,OAAO,KAAK,MAAM,MAAM;GACtB,YAAY,UAAU;IAEpB,MAAM,WAAW,MAAM,OAAO,KAAK;IACnC,IAAI,WAAW,QAAQ,KAAK,YAAY,QAAQ,GAC9C,MAAM;IAIR,QAAQ,MAAM,mBAAmB,MAAM,OAAO,KAAK,CAAC;IAGpD,MAAM,gBAAgB,eAAe,MAAM,OAAO,KAAK,IAAI;IAE3D,OAAO,IAAI,SAAS,KAAK,UAAU,EAAE,OAAO,cAAc,CAAC,GAAG;KAC5D,QAAQ;KACR,SAAS,EAAE,gBAAgB,mBAAmB;IAChD,CAAC;GACH;GACA,YAAY,UAAU;EACxB,CAAC;CACH;AACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { Transport, Transporter } from "@sveltejs/kit";
|
|
3
|
+
|
|
4
|
+
//#region src/transport.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Builds a SvelteKit {@link Transporter} from an Effect {@link Schema.Codec}.
|
|
7
|
+
*
|
|
8
|
+
* The decoded `Type` is detected with `Schema.is`; matching values are encoded
|
|
9
|
+
* with `Schema.encodeSync` and wrapped in a single-element tuple. The wrapper
|
|
10
|
+
* guarantees the encoding is truthy — SvelteKit treats a falsy `encode` result
|
|
11
|
+
* (e.g. an encoded `0`, `""`, `false`, or `null`) as "not this type" — and is
|
|
12
|
+
* unwrapped again by `decode` on the client.
|
|
13
|
+
*/
|
|
14
|
+
declare const transporter: <T, E>(schema: Schema.Codec<T, E>) => Transporter<T, readonly [E]>;
|
|
15
|
+
/**
|
|
16
|
+
* Assembles a SvelteKit `transport` object from a record of Effect schemas,
|
|
17
|
+
* applying {@link transporter} to each. The keys are arbitrary labels (they
|
|
18
|
+
* only need to be stable between server and client).
|
|
19
|
+
*/
|
|
20
|
+
declare const transport: (schemas: Record<string, Schema.Codec<any, any>>) => Transport;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { transport, transporter };
|
|
23
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
//#region src/transport.ts
|
|
3
|
+
/**
|
|
4
|
+
* Builds a SvelteKit {@link Transporter} from an Effect {@link Schema.Codec}.
|
|
5
|
+
*
|
|
6
|
+
* The decoded `Type` is detected with `Schema.is`; matching values are encoded
|
|
7
|
+
* with `Schema.encodeSync` and wrapped in a single-element tuple. The wrapper
|
|
8
|
+
* guarantees the encoding is truthy — SvelteKit treats a falsy `encode` result
|
|
9
|
+
* (e.g. an encoded `0`, `""`, `false`, or `null`) as "not this type" — and is
|
|
10
|
+
* unwrapped again by `decode` on the client.
|
|
11
|
+
*/
|
|
12
|
+
const transporter = (schema) => {
|
|
13
|
+
const guard = Schema.is(schema);
|
|
14
|
+
const encode = Schema.encodeSync(schema);
|
|
15
|
+
const decode = Schema.decodeSync(schema);
|
|
16
|
+
return {
|
|
17
|
+
encode: (value) => guard(value) ? [encode(value)] : false,
|
|
18
|
+
decode: ([data]) => decode(data)
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Assembles a SvelteKit `transport` object from a record of Effect schemas,
|
|
23
|
+
* applying {@link transporter} to each. The keys are arbitrary labels (they
|
|
24
|
+
* only need to be stable between server and client).
|
|
25
|
+
*/
|
|
26
|
+
const transport = (schemas) => {
|
|
27
|
+
const result = {};
|
|
28
|
+
for (const [name, schema] of Object.entries(schemas)) result[name] = transporter(schema);
|
|
29
|
+
return result;
|
|
30
|
+
};
|
|
31
|
+
//#endregion
|
|
32
|
+
export { transport, transporter };
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","names":[],"sources":["../src/transport.ts"],"sourcesContent":["/**\n * Effect Schema ⇄ SvelteKit `transport` hook.\n *\n * SvelteKit's universal [`transport`](https://svelte.dev/docs/kit/hooks#Universal-hooks-transport)\n * hook moves custom (non-POJO) values across the server/client boundary — for\n * data returned from `load` functions and from remote functions. Each entry is\n * a {@link Transporter}: a sync `encode` (server) / `decode` (client) pair,\n * where `encode` returns `false` for values it does not handle.\n *\n * An Effect {@link Schema.Codec} is exactly such a pair. {@link transporter}\n * turns a schema into a `Transporter`, and {@link transport} assembles a whole\n * `transport` object from a record of schemas — so `Option`, `DateTime`,\n * branded types, `Schema.Class` instances, tagged errors, etc. round-trip with\n * no hand-written serialization.\n *\n * ```ts\n * // src/hooks.ts\n * import { Hooks } from \"@thomasfosterau/effect-sveltekit\";\n * import { Schema } from \"effect\";\n *\n * export const transport = Hooks.transport({\n * Option: Schema.Option(Schema.Number),\n * Date: Schema.Date,\n * });\n * ```\n */\n\nimport type { Transport, Transporter } from \"@sveltejs/kit\";\nimport { Schema } from \"effect\";\n\n/**\n * Builds a SvelteKit {@link Transporter} from an Effect {@link Schema.Codec}.\n *\n * The decoded `Type` is detected with `Schema.is`; matching values are encoded\n * with `Schema.encodeSync` and wrapped in a single-element tuple. The wrapper\n * guarantees the encoding is truthy — SvelteKit treats a falsy `encode` result\n * (e.g. an encoded `0`, `\"\"`, `false`, or `null`) as \"not this type\" — and is\n * unwrapped again by `decode` on the client.\n */\nexport const transporter = <T, E>(schema: Schema.Codec<T, E>): Transporter<T, readonly [E]> => {\n const guard = Schema.is(schema);\n const encode = Schema.encodeSync(schema);\n const decode = Schema.decodeSync(schema);\n return {\n encode: (value) => (guard(value) ? ([encode(value)] as const) : false),\n decode: ([data]) => decode(data),\n };\n};\n\n/**\n * Assembles a SvelteKit `transport` object from a record of Effect schemas,\n * applying {@link transporter} to each. The keys are arbitrary labels (they\n * only need to be stable between server and client).\n */\nexport const transport = (schemas: Record<string, Schema.Codec<any, any>>): Transport => {\n const result: Transport = {};\n for (const [name, schema] of Object.entries(schemas)) {\n result[name] = transporter(schema);\n }\n return result;\n};\n"],"mappings":";;;;;;;;;;;AAuCA,MAAa,eAAqB,WAA6D;CAC7F,MAAM,QAAQ,OAAO,GAAG,MAAM;CAC9B,MAAM,SAAS,OAAO,WAAW,MAAM;CACvC,MAAM,SAAS,OAAO,WAAW,MAAM;CACvC,OAAO;EACL,SAAS,UAAW,MAAM,KAAK,IAAK,CAAC,OAAO,KAAK,CAAC,IAAc;EAChE,SAAS,CAAC,UAAU,OAAO,IAAI;CACjC;AACF;;;;;;AAOA,MAAa,aAAa,YAA+D;CACvF,MAAM,SAAoB,CAAC;CAC3B,KAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,OAAO,GACjD,OAAO,QAAQ,YAAY,MAAM;CAEnC,OAAO;AACT"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { UniversalRuntime, makeUniversalRuntime } from "./app-runtime.js";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import * as HttpClient from "effect/unstable/http/HttpClient";
|
|
4
|
+
import { Load } from "@sveltejs/kit";
|
|
5
|
+
|
|
6
|
+
//#region src/universal.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* Wraps an Effect-based function to work as a SvelteKit universal load function.
|
|
9
|
+
*
|
|
10
|
+
* The effect has access to `HttpClient` on both the server and the client:
|
|
11
|
+
* it is backed by the load event's `fetch`, so relative URLs and SvelteKit's
|
|
12
|
+
* fetch behaviours (deduplication, cookies forwarding) work as expected.
|
|
13
|
+
*
|
|
14
|
+
* To give effects access to your own application services, create an
|
|
15
|
+
* app-wide runtime with `makeUniversalRuntime` and use its `load` instead.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { load as effectLoad } from '@thomasfosterau/effect-sveltekit';
|
|
20
|
+
* import * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
21
|
+
* import { Effect } from 'effect';
|
|
22
|
+
*
|
|
23
|
+
* export const load = effectLoad((event) =>
|
|
24
|
+
* Effect.gen(function* () {
|
|
25
|
+
* const client = yield* HttpClient.HttpClient;
|
|
26
|
+
* const response = yield* client.get(`/api/items/${event.params.id}`);
|
|
27
|
+
* return { item: yield* response.json };
|
|
28
|
+
* })
|
|
29
|
+
* );
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
declare function load<Params extends Record<string, string> = any, InputData extends Record<string, unknown> | null = any, ParentData extends Record<string, unknown> = any, OutputData extends Record<string, unknown> | void = any, RouteId extends string | null = any>(fn: (event: Parameters<Load<Params, InputData, ParentData, OutputData, RouteId>>[0]) => Effect.Effect<OutputData, unknown, HttpClient.HttpClient>): Load<Params, InputData, ParentData, OutputData, RouteId>;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { load };
|
|
35
|
+
//# sourceMappingURL=universal.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import "./app-runtime.js";
|
|
2
|
+
import { defaultUniversalRuntime } from "./internal/default-runtime.js";
|
|
3
|
+
import "effect";
|
|
4
|
+
//#region src/universal.ts
|
|
5
|
+
/**
|
|
6
|
+
* Wraps an Effect-based function to work as a SvelteKit universal load function.
|
|
7
|
+
*
|
|
8
|
+
* The effect has access to `HttpClient` on both the server and the client:
|
|
9
|
+
* it is backed by the load event's `fetch`, so relative URLs and SvelteKit's
|
|
10
|
+
* fetch behaviours (deduplication, cookies forwarding) work as expected.
|
|
11
|
+
*
|
|
12
|
+
* To give effects access to your own application services, create an
|
|
13
|
+
* app-wide runtime with `makeUniversalRuntime` and use its `load` instead.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { load as effectLoad } from '@thomasfosterau/effect-sveltekit';
|
|
18
|
+
* import * as HttpClient from 'effect/unstable/http/HttpClient';
|
|
19
|
+
* import { Effect } from 'effect';
|
|
20
|
+
*
|
|
21
|
+
* export const load = effectLoad((event) =>
|
|
22
|
+
* Effect.gen(function* () {
|
|
23
|
+
* const client = yield* HttpClient.HttpClient;
|
|
24
|
+
* const response = yield* client.get(`/api/items/${event.params.id}`);
|
|
25
|
+
* return { item: yield* response.json };
|
|
26
|
+
* })
|
|
27
|
+
* );
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
function load(fn) {
|
|
31
|
+
return defaultUniversalRuntime().load(fn);
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { load };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=universal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"universal.js","names":["runtime"],"sources":["../src/universal.ts"],"sourcesContent":["import type { Load } from \"@sveltejs/kit\";\nimport { Effect } from \"effect\";\nimport type * as HttpClient from \"effect/unstable/http/HttpClient\";\nimport { defaultUniversalRuntime as runtime } from \"./internal/default-runtime.js\";\n\n/**\n * Wraps an Effect-based function to work as a SvelteKit universal load function.\n *\n * The effect has access to `HttpClient` on both the server and the client:\n * it is backed by the load event's `fetch`, so relative URLs and SvelteKit's\n * fetch behaviours (deduplication, cookies forwarding) work as expected.\n *\n * To give effects access to your own application services, create an\n * app-wide runtime with `makeUniversalRuntime` and use its `load` instead.\n *\n * @example\n * ```ts\n * import { load as effectLoad } from '@thomasfosterau/effect-sveltekit';\n * import * as HttpClient from 'effect/unstable/http/HttpClient';\n * import { Effect } from 'effect';\n *\n * export const load = effectLoad((event) =>\n * Effect.gen(function* () {\n * const client = yield* HttpClient.HttpClient;\n * const response = yield* client.get(`/api/items/${event.params.id}`);\n * return { item: yield* response.json };\n * })\n * );\n * ```\n */\nexport function load<\n Params extends Record<string, string> = any,\n InputData extends Record<string, unknown> | null = any,\n ParentData extends Record<string, unknown> = any,\n OutputData extends Record<string, unknown> | void = any,\n RouteId extends string | null = any,\n>(\n fn: (\n event: Parameters<Load<Params, InputData, ParentData, OutputData, RouteId>>[0],\n ) => Effect.Effect<OutputData, unknown, HttpClient.HttpClient>,\n): Load<Params, InputData, ParentData, OutputData, RouteId> {\n return runtime().load(fn);\n}\n\n/**\n * App-wide runtime: define your application's (universal) Effect services\n * once and share them across every `load` invocation.\n */\nexport { makeUniversalRuntime, type UniversalRuntime } from \"./app-runtime.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,KAOd,IAG0D;CAC1D,OAAOA,wBAAQ,EAAE,KAAK,EAAE;AAC1B"}
|