@thomasfosterau/effect-sveltekit 0.4.0 → 0.5.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.
Files changed (61) hide show
  1. package/README.md +515 -30
  2. package/dist/Hooks.d.ts +1 -1
  3. package/dist/Hooks.js.map +1 -1
  4. package/dist/Navigation.d.ts +17 -6
  5. package/dist/Navigation.js +17 -5
  6. package/dist/Navigation.js.map +1 -1
  7. package/dist/Remote.d.ts +58 -1
  8. package/dist/Remote.js +16 -0
  9. package/dist/Remote.js.map +1 -1
  10. package/dist/State.d.ts +4 -4
  11. package/dist/State.js.map +1 -1
  12. package/dist/adapter/handler.d.ts +15 -12
  13. package/dist/adapter/handler.js +5 -7
  14. package/dist/adapter/handler.js.map +1 -1
  15. package/dist/adapter/index.d.ts +1 -0
  16. package/dist/adapter/index.js +25 -21
  17. package/dist/adapter/index.js.map +1 -1
  18. package/dist/adapter/serve.d.ts +1 -0
  19. package/dist/adapter/serve.js.map +1 -1
  20. package/dist/api-client.js +1 -1
  21. package/dist/api-client.js.map +1 -1
  22. package/dist/app-runtime.d.ts +7 -6
  23. package/dist/app-runtime.js +5 -5
  24. package/dist/app-runtime.js.map +1 -1
  25. package/dist/client/Hooks.d.ts +1 -1
  26. package/dist/client/Hooks.js.map +1 -1
  27. package/dist/errors.js +3 -2
  28. package/dist/errors.js.map +1 -1
  29. package/dist/forms.d.ts +6 -6
  30. package/dist/forms.js.map +1 -1
  31. package/dist/internal/app-state.d.ts +1 -1
  32. package/dist/internal/app-state.js.map +1 -1
  33. package/dist/internal/auto.d.ts +2 -1
  34. package/dist/internal/auto.js.map +1 -1
  35. package/dist/internal/enhance.d.ts +1 -1
  36. package/dist/internal/enhance.js.map +1 -1
  37. package/dist/internal/error.js +23 -2
  38. package/dist/internal/error.js.map +1 -1
  39. package/dist/internal/remote-run.d.ts +4 -3
  40. package/dist/internal/remote-run.js.map +1 -1
  41. package/dist/kit.js +3 -3
  42. package/dist/kit.js.map +1 -1
  43. package/dist/realtime.d.ts +2 -0
  44. package/dist/realtime.js.map +1 -1
  45. package/dist/remote-functions.d.ts +18 -4
  46. package/dist/remote-functions.js +43 -0
  47. package/dist/remote-functions.js.map +1 -1
  48. package/dist/remote-reactive.d.ts +1 -1
  49. package/dist/remote-reactive.js.map +1 -1
  50. package/dist/response-headers.d.ts +1 -1
  51. package/dist/response-headers.js.map +1 -1
  52. package/dist/server/Endpoint.d.ts +2 -2
  53. package/dist/server/Endpoint.js +2 -2
  54. package/dist/server/Endpoint.js.map +1 -1
  55. package/dist/server/Hooks.d.ts +1 -1
  56. package/dist/server/Hooks.js.map +1 -1
  57. package/dist/transport.d.ts +1 -1
  58. package/dist/transport.js.map +1 -1
  59. package/dist/vite.d.ts +4 -2
  60. package/dist/vite.js.map +1 -1
  61. package/package.json +7 -4
@@ -26,7 +26,7 @@ import { afterNavigate, beforeNavigate, goto, invalidate, invalidateAll, onNavig
26
26
  * runtime.runPromise(
27
27
  * Effect.gen(function* () {
28
28
  * yield* doSave();
29
- * yield* Navigation.invalidateAll();
29
+ * yield* Navigation.refreshAll();
30
30
  * yield* Navigation.goto('/done');
31
31
  * }),
32
32
  * );
@@ -44,18 +44,30 @@ var Navigation_exports = /* @__PURE__ */ __exportAll({
44
44
  preloadData: () => preloadData$1,
45
45
  refreshAll: () => refreshAll$1
46
46
  });
47
- /** Navigate to `url`. Wraps `$app/navigation`'s `goto`. */
47
+ /**
48
+ * Navigate to `url`. Wraps `$app/navigation`'s `goto`. SvelteKit rejects a URL
49
+ * outside the app (external, or not matching a route); a rejection surfaces as
50
+ * a defect.
51
+ */
48
52
  const goto$1 = (...args) => Effect.promise(() => goto(...args));
49
53
  /** Re-run `load` functions that depend on `resource`. Wraps `invalidate`. */
50
54
  const invalidate$1 = (...args) => Effect.promise(() => invalidate(...args));
51
- /** Re-run every `load` function for the active page. Wraps `invalidateAll`. */
55
+ /**
56
+ * Re-run every `load` function for the active page. Wraps `invalidateAll`.
57
+ *
58
+ * @deprecated SvelteKit 3 deprecates `invalidateAll`; use {@link refreshAll},
59
+ * which also refreshes active remote functions and keeps `page.state`.
60
+ */
52
61
  const invalidateAll$1 = () => Effect.promise(() => invalidateAll());
53
62
  /** Refresh active remote functions (and, by default, `load`s). Wraps `refreshAll`. */
54
63
  const refreshAll$1 = (...args) => Effect.promise(() => refreshAll(...args));
55
64
  /** Preload the data for `href`. Wraps `preloadData`. */
56
65
  const preloadData$1 = (href) => Effect.promise(() => preloadData(href));
57
- /** Preload the code for routes matching `pathname`. Wraps `preloadCode`. */
58
- const preloadCode$1 = (pathname) => Effect.promise(() => preloadCode(pathname));
66
+ /**
67
+ * Preload the code for the route `id` (e.g. `/blog/[slug]`, without
68
+ * `paths.base`). Wraps `preloadCode`.
69
+ */
70
+ const preloadCode$1 = (...args) => Effect.promise(() => preloadCode(...args));
59
71
  /**
60
72
  * Registers a `beforeNavigate` callback and exposes every navigation about to
61
73
  * happen as an Effect `Stream`. Call during component initialization.
@@ -1 +1 @@
1
- {"version":3,"file":"Navigation.js","names":["goto","kitGoto","invalidate","kitInvalidate","invalidateAll","kitInvalidateAll","refreshAll","kitRefreshAll","preloadData","kitPreloadData","preloadCode","kitPreloadCode","beforeNavigate","kitBeforeNavigate","afterNavigate","kitAfterNavigate","onNavigate","kitOnNavigate"],"sources":["../src/Navigation.ts"],"sourcesContent":["/**\n * Effect wrappers for SvelteKit's client-side\n * [`$app/navigation`](https://svelte.dev/docs/kit/$app-navigation) API.\n *\n * Each of SvelteKit's promise-returning navigation functions is wrapped as an\n * `Effect`, so navigation composes inside Effect pipelines (sequencing,\n * retries, `Effect.race`, tracing spans, ...). Alongside them sit the\n * client-side lifecycle callbacks (`beforeNavigate`, `afterNavigate`,\n * `onNavigate`) bridged to Effect. These run on the client only — calling them\n * during SSR throws, exactly as the underlying `$app/navigation` functions do.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { Navigation } from '@thomasfosterau/effect-sveltekit/client';\n * import { Effect } from 'effect';\n * import { getRuntime } from '@thomasfosterau/effect-svelte';\n *\n * const runtime = getRuntime();\n * const save = () =>\n * runtime.runPromise(\n * Effect.gen(function* () {\n * yield* doSave();\n * yield* Navigation.invalidateAll();\n * yield* Navigation.goto('/done');\n * }),\n * );\n * </script>\n * ```\n */\n\nimport {\n afterNavigate as kitAfterNavigate,\n beforeNavigate as kitBeforeNavigate,\n goto as kitGoto,\n invalidate as kitInvalidate,\n invalidateAll as kitInvalidateAll,\n onNavigate as kitOnNavigate,\n preloadCode as kitPreloadCode,\n preloadData as kitPreloadData,\n refreshAll as kitRefreshAll,\n} from \"$app/navigation\";\nimport type { AfterNavigate, BeforeNavigate, OnNavigate } from \"@sveltejs/kit\";\nimport { Effect } from \"effect\";\nimport type { Stream } from \"effect\";\nimport { onNavigateWith, registeredStream } from \"./internal/navigation-events.js\";\n\n/** Navigate to `url`. Wraps `$app/navigation`'s `goto`. */\nexport const goto = (...args: Parameters<typeof kitGoto>): Effect.Effect<void> =>\n Effect.promise(() => kitGoto(...args));\n\n/** Re-run `load` functions that depend on `resource`. Wraps `invalidate`. */\nexport const invalidate = (...args: Parameters<typeof kitInvalidate>): Effect.Effect<void> =>\n Effect.promise(() => kitInvalidate(...args));\n\n/** Re-run every `load` function for the active page. Wraps `invalidateAll`. */\nexport const invalidateAll = (): Effect.Effect<void> => Effect.promise(() => kitInvalidateAll());\n\n/** Refresh active remote functions (and, by default, `load`s). Wraps `refreshAll`. */\nexport const refreshAll = (...args: Parameters<typeof kitRefreshAll>): Effect.Effect<void> =>\n Effect.promise(() => kitRefreshAll(...args));\n\n/** Preload the data for `href`. Wraps `preloadData`. */\nexport const preloadData = (\n href: string,\n): Effect.Effect<Awaited<ReturnType<typeof kitPreloadData>>> =>\n Effect.promise(() => kitPreloadData(href));\n\n/** Preload the code for routes matching `pathname`. Wraps `preloadCode`. */\nexport const preloadCode = (pathname: string): Effect.Effect<void> =>\n Effect.promise(() => kitPreloadCode(pathname));\n\n/**\n * Registers a `beforeNavigate` callback and exposes every navigation about to\n * happen as an Effect `Stream`. Call during component initialization.\n *\n * Unlike the promise-returning navigation functions above, this is a\n * **callback-registration** function: it must be called *synchronously during\n * component initialization* (SvelteKit wires it to the component's lifecycle).\n * It registers its callback eagerly and feeds an internal `Queue`, returning a\n * `Stream` backed by that queue — the same push-based bridge as `SignalEmitter`\n * in `@thomasfosterau/effect-svelte`. Call it at the top level of `<script>`,\n * exactly where you'd call the bare `beforeNavigate`.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { Navigation } from '@thomasfosterau/effect-sveltekit/client';\n * import { Stream, Effect } from 'effect';\n * import { getRuntime } from '@thomasfosterau/effect-svelte';\n *\n * // Register at init so the callback is wired to the component lifecycle.\n * const navigations = Navigation.beforeNavigate();\n *\n * getRuntime().runFork(\n * Stream.runForEach(navigations, (nav) =>\n * Effect.logInfo(`leaving: ${nav.from?.url.pathname}`),\n * ),\n * );\n * </script>\n * ```\n */\nexport function beforeNavigate(): Stream.Stream<BeforeNavigate> {\n return registeredStream<BeforeNavigate>(kitBeforeNavigate);\n}\n\n/**\n * Registers an `afterNavigate` callback and exposes every completed navigation\n * (including the initial one) as an Effect `Stream`. Call during component\n * initialization.\n *\n * Like {@link beforeNavigate}, this is a **callback-registration** function:\n * call it at the top level of `<script>`, exactly where you'd call the bare\n * `afterNavigate`.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { Navigation } from '@thomasfosterau/effect-sveltekit/client';\n * import { Stream, Effect } from 'effect';\n * import { getRuntime } from '@thomasfosterau/effect-svelte';\n *\n * // Register at init so the callback is wired to the component lifecycle.\n * const navigations = Navigation.afterNavigate();\n *\n * getRuntime().runFork(\n * Stream.runForEach(navigations, (nav) =>\n * Effect.logInfo(`navigated: ${nav.to?.url.pathname}`),\n * ),\n * );\n * </script>\n * ```\n */\nexport function afterNavigate(): Stream.Stream<AfterNavigate> {\n return registeredStream<AfterNavigate>(kitAfterNavigate);\n}\n\n/**\n * Runs an `Effect` for each navigation, registered via `$app/navigation`'s\n * `onNavigate`. Call during component initialization.\n *\n * SvelteKit's `onNavigate` callback may return a cleanup function (or a promise\n * of one) that runs once the navigation completes and the DOM has updated; to\n * support that, `fn`'s Effect may succeed with a `() => void` cleanup, which is\n * forwarded to SvelteKit. The Effect is run with `runEffect` (default\n * {@link Effect.runPromise}); pass a managed runtime's `runPromise` to supply\n * services to `fn`.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { Navigation } from '@thomasfosterau/effect-sveltekit/client';\n * import { Effect } from 'effect';\n *\n * Navigation.onNavigate((nav) =>\n * Effect.gen(function* () {\n * yield* Effect.logInfo(`navigating to ${nav.to?.url.pathname}`);\n * // Optionally return a cleanup that runs after the navigation:\n * return () => console.log(\"navigation done\");\n * }),\n * );\n * </script>\n * ```\n */\nexport function onNavigate(\n fn: (navigation: OnNavigate) => Effect.Effect<(() => void) | void>,\n runEffect: <X>(effect: Effect.Effect<X>) => Promise<X> = Effect.runPromise,\n): void {\n onNavigateWith<OnNavigate>(kitOnNavigate, fn, runEffect);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDA,MAAaA,UAAQ,GAAG,SACtB,OAAO,cAAcC,KAAQ,GAAG,IAAI,CAAC;;AAGvC,MAAaC,gBAAc,GAAG,SAC5B,OAAO,cAAcC,WAAc,GAAG,IAAI,CAAC;;AAG7C,MAAaC,wBAA2C,OAAO,cAAcC,cAAiB,CAAC;;AAG/F,MAAaC,gBAAc,GAAG,SAC5B,OAAO,cAAcC,WAAc,GAAG,IAAI,CAAC;;AAG7C,MAAaC,iBACX,SAEA,OAAO,cAAcC,YAAe,IAAI,CAAC;;AAG3C,MAAaC,iBAAe,aAC1B,OAAO,cAAcC,YAAe,QAAQ,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgC/C,SAAgBC,mBAAgD;CAC9D,OAAO,iBAAiCC,cAAiB;AAC3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgBC,kBAA8C;CAC5D,OAAO,iBAAgCC,aAAgB;AACzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgBC,aACd,IACA,YAAyD,OAAO,YAC1D;CACN,eAA2BC,YAAe,IAAI,SAAS;AACzD"}
1
+ {"version":3,"file":"Navigation.js","names":["goto","kitGoto","invalidate","kitInvalidate","invalidateAll","kitInvalidateAll","refreshAll","kitRefreshAll","preloadData","kitPreloadData","preloadCode","kitPreloadCode","beforeNavigate","kitBeforeNavigate","afterNavigate","kitAfterNavigate","onNavigate","kitOnNavigate"],"sources":["../src/Navigation.ts"],"sourcesContent":["/**\n * Effect wrappers for SvelteKit's client-side\n * [`$app/navigation`](https://svelte.dev/docs/kit/$app-navigation) API.\n *\n * Each of SvelteKit's promise-returning navigation functions is wrapped as an\n * `Effect`, so navigation composes inside Effect pipelines (sequencing,\n * retries, `Effect.race`, tracing spans, ...). Alongside them sit the\n * client-side lifecycle callbacks (`beforeNavigate`, `afterNavigate`,\n * `onNavigate`) bridged to Effect. These run on the client only — calling them\n * during SSR throws, exactly as the underlying `$app/navigation` functions do.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { Navigation } from '@thomasfosterau/effect-sveltekit/client';\n * import { Effect } from 'effect';\n * import { getRuntime } from '@thomasfosterau/effect-svelte';\n *\n * const runtime = getRuntime();\n * const save = () =>\n * runtime.runPromise(\n * Effect.gen(function* () {\n * yield* doSave();\n * yield* Navigation.refreshAll();\n * yield* Navigation.goto('/done');\n * }),\n * );\n * </script>\n * ```\n */\n\nimport {\n afterNavigate as kitAfterNavigate,\n beforeNavigate as kitBeforeNavigate,\n goto as kitGoto,\n invalidate as kitInvalidate,\n invalidateAll as kitInvalidateAll,\n onNavigate as kitOnNavigate,\n preloadCode as kitPreloadCode,\n preloadData as kitPreloadData,\n refreshAll as kitRefreshAll,\n} from \"$app/navigation\";\nimport type { AfterNavigate, BeforeNavigate, OnNavigate } from \"$app/navigation\";\nimport { Effect } from \"effect\";\nimport type { Stream } from \"effect\";\nimport { onNavigateWith, registeredStream } from \"./internal/navigation-events.js\";\n\n/**\n * Navigate to `url`. Wraps `$app/navigation`'s `goto`. SvelteKit rejects a URL\n * outside the app (external, or not matching a route); a rejection surfaces as\n * a defect.\n */\nexport const goto = (...args: Parameters<typeof kitGoto>): Effect.Effect<void> =>\n Effect.promise(() => kitGoto(...args));\n\n/** Re-run `load` functions that depend on `resource`. Wraps `invalidate`. */\nexport const invalidate = (...args: Parameters<typeof kitInvalidate>): Effect.Effect<void> =>\n Effect.promise(() => kitInvalidate(...args));\n\n/**\n * Re-run every `load` function for the active page. Wraps `invalidateAll`.\n *\n * @deprecated SvelteKit 3 deprecates `invalidateAll`; use {@link refreshAll},\n * which also refreshes active remote functions and keeps `page.state`.\n */\nexport const invalidateAll = (): Effect.Effect<void> => Effect.promise(() => kitInvalidateAll());\n\n/** Refresh active remote functions (and, by default, `load`s). Wraps `refreshAll`. */\nexport const refreshAll = (...args: Parameters<typeof kitRefreshAll>): Effect.Effect<void> =>\n Effect.promise(() => kitRefreshAll(...args));\n\n/** Preload the data for `href`. Wraps `preloadData`. */\nexport const preloadData = (\n href: string,\n): Effect.Effect<Awaited<ReturnType<typeof kitPreloadData>>> =>\n Effect.promise(() => kitPreloadData(href));\n\n/**\n * Preload the code for the route `id` (e.g. `/blog/[slug]`, without\n * `paths.base`). Wraps `preloadCode`.\n */\nexport const preloadCode = (...args: Parameters<typeof kitPreloadCode>): Effect.Effect<void> =>\n Effect.promise(() => kitPreloadCode(...args));\n\n/**\n * Registers a `beforeNavigate` callback and exposes every navigation about to\n * happen as an Effect `Stream`. Call during component initialization.\n *\n * Unlike the promise-returning navigation functions above, this is a\n * **callback-registration** function: it must be called *synchronously during\n * component initialization* (SvelteKit wires it to the component's lifecycle).\n * It registers its callback eagerly and feeds an internal `Queue`, returning a\n * `Stream` backed by that queue — the same push-based bridge as `SignalEmitter`\n * in `@thomasfosterau/effect-svelte`. Call it at the top level of `<script>`,\n * exactly where you'd call the bare `beforeNavigate`.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { Navigation } from '@thomasfosterau/effect-sveltekit/client';\n * import { Stream, Effect } from 'effect';\n * import { getRuntime } from '@thomasfosterau/effect-svelte';\n *\n * // Register at init so the callback is wired to the component lifecycle.\n * const navigations = Navigation.beforeNavigate();\n *\n * getRuntime().runFork(\n * Stream.runForEach(navigations, (nav) =>\n * Effect.logInfo(`leaving: ${nav.from?.url.pathname}`),\n * ),\n * );\n * </script>\n * ```\n */\nexport function beforeNavigate(): Stream.Stream<BeforeNavigate> {\n return registeredStream<BeforeNavigate>(kitBeforeNavigate);\n}\n\n/**\n * Registers an `afterNavigate` callback and exposes every completed navigation\n * (including the initial one) as an Effect `Stream`. Call during component\n * initialization.\n *\n * Like {@link beforeNavigate}, this is a **callback-registration** function:\n * call it at the top level of `<script>`, exactly where you'd call the bare\n * `afterNavigate`.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { Navigation } from '@thomasfosterau/effect-sveltekit/client';\n * import { Stream, Effect } from 'effect';\n * import { getRuntime } from '@thomasfosterau/effect-svelte';\n *\n * // Register at init so the callback is wired to the component lifecycle.\n * const navigations = Navigation.afterNavigate();\n *\n * getRuntime().runFork(\n * Stream.runForEach(navigations, (nav) =>\n * Effect.logInfo(`navigated: ${nav.to?.url.pathname}`),\n * ),\n * );\n * </script>\n * ```\n */\nexport function afterNavigate(): Stream.Stream<AfterNavigate> {\n return registeredStream<AfterNavigate>(kitAfterNavigate);\n}\n\n/**\n * Runs an `Effect` for each navigation, registered via `$app/navigation`'s\n * `onNavigate`. Call during component initialization.\n *\n * SvelteKit's `onNavigate` callback may return a cleanup function (or a promise\n * of one) that runs once the navigation completes and the DOM has updated; to\n * support that, `fn`'s Effect may succeed with a `() => void` cleanup, which is\n * forwarded to SvelteKit. The Effect is run with `runEffect` (default\n * {@link Effect.runPromise}); pass a managed runtime's `runPromise` to supply\n * services to `fn`.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { Navigation } from '@thomasfosterau/effect-sveltekit/client';\n * import { Effect } from 'effect';\n *\n * Navigation.onNavigate((nav) =>\n * Effect.gen(function* () {\n * yield* Effect.logInfo(`navigating to ${nav.to?.url.pathname}`);\n * // Optionally return a cleanup that runs after the navigation:\n * return () => console.log(\"navigation done\");\n * }),\n * );\n * </script>\n * ```\n */\nexport function onNavigate(\n fn: (navigation: OnNavigate) => Effect.Effect<(() => void) | void>,\n runEffect: <X>(effect: Effect.Effect<X>) => Promise<X> = Effect.runPromise,\n): void {\n onNavigateWith<OnNavigate>(kitOnNavigate, fn, runEffect);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAaA,UAAQ,GAAG,SACtB,OAAO,cAAcC,KAAQ,GAAG,IAAI,CAAC;;AAGvC,MAAaC,gBAAc,GAAG,SAC5B,OAAO,cAAcC,WAAc,GAAG,IAAI,CAAC;;;;;;;AAQ7C,MAAaC,wBAA2C,OAAO,cAAcC,cAAiB,CAAC;;AAG/F,MAAaC,gBAAc,GAAG,SAC5B,OAAO,cAAcC,WAAc,GAAG,IAAI,CAAC;;AAG7C,MAAaC,iBACX,SAEA,OAAO,cAAcC,YAAe,IAAI,CAAC;;;;;AAM3C,MAAaC,iBAAe,GAAG,SAC7B,OAAO,cAAcC,YAAe,GAAG,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgC9C,SAAgBC,mBAAgD;CAC9D,OAAO,iBAAiCC,cAAiB;AAC3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgBC,kBAA8C;CAC5D,OAAO,iBAAgCC,aAAgB;AACzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgBC,aACd,IACA,YAAyD,OAAO,YAC1D;CACN,eAA2BC,YAAe,IAAI,SAAS;AACzD"}
package/dist/Remote.d.ts CHANGED
@@ -1,11 +1,38 @@
1
1
  import { Effect, Stream } from "effect";
2
- import { RemoteCommand, RemoteLiveQuery, RemotePrerenderFunction, RemoteQuery, RemoteQueryFunction, RemoteQueryOverride } from "@sveltejs/kit";
2
+ import { RemoteCommand, RemoteLiveQuery, RemotePrerenderFunction, RemoteQuery, RemoteQueryFunction, RemoteQueryOverride } from "$app/server";
3
3
  declare namespace Remote_d_exports {
4
4
  export { RemoteSubmit, callCommand, callCommandWithUpdates, callPrerender, callQuery, liveQueryStream, submitForm, submitFormWithUpdates };
5
5
  }
6
+ /**
7
+ * Calls a SvelteKit remote `query` as an Effect that succeeds with its output.
8
+ *
9
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
10
+ * defect, not on the error channel, despite the declared `unknown` error type.
11
+ */
6
12
  declare function callQuery<Output>(query: RemoteQueryFunction<void, Output>): Effect.Effect<Output, unknown, never>;
13
+ /**
14
+ * Calls a SvelteKit remote `query` with `input` as an Effect that succeeds
15
+ * with its output.
16
+ *
17
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
18
+ * defect, not on the error channel, despite the declared `unknown` error type.
19
+ */
7
20
  declare function callQuery<Input, Output>(query: RemoteQueryFunction<Input, Output>, input: Input): Effect.Effect<Output, unknown, never>;
21
+ /**
22
+ * Calls a SvelteKit remote `command` as an Effect that succeeds with its
23
+ * output.
24
+ *
25
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
26
+ * defect, not on the error channel, despite the declared `unknown` error type.
27
+ */
8
28
  declare function callCommand<Output>(command: RemoteCommand<void, Output>): Effect.Effect<Output, unknown, never>;
29
+ /**
30
+ * Calls a SvelteKit remote `command` with `input` as an Effect that succeeds
31
+ * with its output.
32
+ *
33
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
34
+ * defect, not on the error channel, despite the declared `unknown` error type.
35
+ */
9
36
  declare function callCommand<Input, Output>(command: RemoteCommand<Input, Output>, input: Input): Effect.Effect<Output, unknown, never>;
10
37
  /**
11
38
  * Calls a remote command and refreshes the given queries in the same round
@@ -14,9 +41,26 @@ declare function callCommand<Input, Output>(command: RemoteCommand<Input, Output
14
41
  * Newer SvelteKit versions cache remote query instances, so a command that
15
42
  * changes data those queries depend on must list them here (or call
16
43
  * `query.refresh()` afterwards) for their cached values to update.
44
+ *
45
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
46
+ * defect, not on the error channel, despite the declared `unknown` error type.
17
47
  */
18
48
  declare function callCommandWithUpdates<Input, Output>(command: RemoteCommand<Input, Output>, input: Input, ...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Effect.Effect<Output, unknown, never>;
49
+ /**
50
+ * Calls a SvelteKit remote `prerender` function as an Effect that succeeds
51
+ * with its output.
52
+ *
53
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
54
+ * defect, not on the error channel, despite the declared `unknown` error type.
55
+ */
19
56
  declare function callPrerender<Output>(prerender: RemotePrerenderFunction<void, Output>): Effect.Effect<Output, unknown, never>;
57
+ /**
58
+ * Calls a SvelteKit remote `prerender` function with `input` as an Effect
59
+ * that succeeds with its output.
60
+ *
61
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
62
+ * defect, not on the error channel, despite the declared `unknown` error type.
63
+ */
20
64
  declare function callPrerender<Input, Output>(prerender: RemotePrerenderFunction<Input, Output>, input: Input): Effect.Effect<Output, unknown, never>;
21
65
  /**
22
66
  * The shape of an enhanced remote form `submit` function. The promise result
@@ -26,7 +70,20 @@ declare function callPrerender<Input, Output>(prerender: RemotePrerenderFunction
26
70
  type RemoteSubmit = () => PromiseLike<unknown> & {
27
71
  updates: (...queries: Array<RemoteQuery<any> | RemoteQueryOverride>) => PromiseLike<unknown>;
28
72
  };
73
+ /**
74
+ * Runs an enhanced remote form's `submit()` as an Effect.
75
+ *
76
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
77
+ * defect, not on the error channel, despite the declared `unknown` error type.
78
+ */
29
79
  declare function submitForm(submit: () => PromiseLike<unknown>): Effect.Effect<void, unknown, never>;
80
+ /**
81
+ * Runs an enhanced remote form's `submit()` and refreshes the given queries in
82
+ * the same round trip (SvelteKit's single-flight mutations).
83
+ *
84
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
85
+ * defect, not on the error channel, despite the declared `unknown` error type.
86
+ */
30
87
  declare function submitFormWithUpdates(submit: RemoteSubmit, ...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Effect.Effect<void, unknown, never>;
31
88
  /**
32
89
  * Consumes a SvelteKit live query (`query.live(...)`) as an Effect `Stream`.
package/dist/Remote.js CHANGED
@@ -28,6 +28,9 @@ function callCommand(command, input) {
28
28
  * Newer SvelteKit versions cache remote query instances, so a command that
29
29
  * changes data those queries depend on must list them here (or call
30
30
  * `query.refresh()` afterwards) for their cached values to update.
31
+ *
32
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
33
+ * defect, not on the error channel, despite the declared `unknown` error type.
31
34
  */
32
35
  function callCommandWithUpdates(command, input, ...queries) {
33
36
  return fromRemotePromise(() => command(input).updates(...queries));
@@ -36,9 +39,22 @@ function callPrerender(prerender, input) {
36
39
  if (arguments.length === 1) return fromRemotePromise(() => prerender(void 0));
37
40
  return fromRemotePromise(() => prerender(input));
38
41
  }
42
+ /**
43
+ * Runs an enhanced remote form's `submit()` as an Effect.
44
+ *
45
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
46
+ * defect, not on the error channel, despite the declared `unknown` error type.
47
+ */
39
48
  function submitForm(submit) {
40
49
  return Effect.asVoid(fromRemotePromise(() => submit()));
41
50
  }
51
+ /**
52
+ * Runs an enhanced remote form's `submit()` and refreshes the given queries in
53
+ * the same round trip (SvelteKit's single-flight mutations).
54
+ *
55
+ * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a
56
+ * defect, not on the error channel, despite the declared `unknown` error type.
57
+ */
42
58
  function submitFormWithUpdates(submit, ...queries) {
43
59
  return Effect.asVoid(fromRemotePromise(() => submit().updates(...queries)));
44
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Remote.js","names":[],"sources":["../src/Remote.ts"],"sourcesContent":["import type {\n RemoteCommand,\n RemoteLiveQuery,\n RemotePrerenderFunction,\n RemoteQuery,\n RemoteQueryFunction,\n RemoteQueryOverride,\n} from \"@sveltejs/kit\";\nimport { Effect, Stream } from \"effect\";\n\nfunction fromRemotePromise<A>(thunk: () => PromiseLike<A>): Effect.Effect<A, unknown, never> {\n return Effect.promise(() => Promise.resolve(thunk()));\n}\n\nexport function callQuery<Output>(\n query: RemoteQueryFunction<void, Output>,\n): Effect.Effect<Output, unknown, never>;\nexport function callQuery<Input, Output>(\n query: RemoteQueryFunction<Input, Output>,\n input: Input,\n): Effect.Effect<Output, unknown, never>;\nexport function callQuery<Input, Output>(\n query: RemoteQueryFunction<Input, Output>,\n input?: Input,\n): Effect.Effect<Output, unknown, never> {\n if (arguments.length === 1) {\n return fromRemotePromise(() =>\n (query as unknown as RemoteQueryFunction<void, Output>)(undefined),\n );\n }\n\n return fromRemotePromise(() => query(input as Input));\n}\n\nexport function callCommand<Output>(\n command: RemoteCommand<void, Output>,\n): Effect.Effect<Output, unknown, never>;\nexport function callCommand<Input, Output>(\n command: RemoteCommand<Input, Output>,\n input: Input,\n): Effect.Effect<Output, unknown, never>;\nexport function callCommand<Input, Output>(\n command: RemoteCommand<Input, Output>,\n input?: Input,\n): Effect.Effect<Output, unknown, never> {\n if (arguments.length === 1) {\n return fromRemotePromise(() => (command as unknown as RemoteCommand<void, Output>)(undefined));\n }\n\n return fromRemotePromise(() => command(input as Input));\n}\n\n/**\n * Calls a remote command and refreshes the given queries in the same round\n * trip (SvelteKit's single-flight mutations).\n *\n * Newer SvelteKit versions cache remote query instances, so a command that\n * changes data those queries depend on must list them here (or call\n * `query.refresh()` afterwards) for their cached values to update.\n */\nexport function callCommandWithUpdates<Input, Output>(\n command: RemoteCommand<Input, Output>,\n input: Input,\n ...queries: Array<RemoteQuery<any> | RemoteQueryOverride>\n): Effect.Effect<Output, unknown, never> {\n return fromRemotePromise(() => command(input).updates(...queries));\n}\n\nexport function callPrerender<Output>(\n prerender: RemotePrerenderFunction<void, Output>,\n): Effect.Effect<Output, unknown, never>;\nexport function callPrerender<Input, Output>(\n prerender: RemotePrerenderFunction<Input, Output>,\n input: Input,\n): Effect.Effect<Output, unknown, never>;\nexport function callPrerender<Input, Output>(\n prerender: RemotePrerenderFunction<Input, Output>,\n input?: Input,\n): Effect.Effect<Output, unknown, never> {\n if (arguments.length === 1) {\n return fromRemotePromise(() =>\n (prerender as unknown as RemotePrerenderFunction<void, Output>)(undefined),\n );\n }\n\n return fromRemotePromise(() => prerender(input as Input));\n}\n\n/**\n * The shape of an enhanced remote form `submit` function. The promise result\n * is left open (SvelteKit returns `Promise<void>` in older versions and\n * `Promise<boolean>` in newer ones).\n */\nexport type RemoteSubmit = () => PromiseLike<unknown> & {\n updates: (...queries: Array<RemoteQuery<any> | RemoteQueryOverride>) => PromiseLike<unknown>;\n};\n\nexport function submitForm(\n submit: () => PromiseLike<unknown>,\n): Effect.Effect<void, unknown, never> {\n return Effect.asVoid(fromRemotePromise(() => submit()));\n}\n\nexport function submitFormWithUpdates(\n submit: RemoteSubmit,\n ...queries: Array<RemoteQuery<any> | RemoteQueryOverride>\n): Effect.Effect<void, unknown, never> {\n return Effect.asVoid(fromRemotePromise(() => submit().updates(...queries)));\n}\n\n/**\n * Consumes a SvelteKit live query (`query.live(...)`) as an Effect `Stream`.\n *\n * A `RemoteLiveQuery<T>` is an `AsyncIterable<T>` that yields every update\n * pushed from the server; this turns it into a `Stream` so live data can drive\n * Effect pipelines (and, via `useStream`, Svelte runes).\n *\n * @example\n * ```ts\n * import { Remote } from '@thomasfosterau/effect-sveltekit';\n * import { messages } from './chat.remote';\n * import { useStream } from '@thomasfosterau/effect-svelte';\n *\n * const feed = useStream(Remote.liveQueryStream(messages()));\n * ```\n */\nexport function liveQueryStream<Output>(\n query: RemoteLiveQuery<Output>,\n): Stream.Stream<Output, unknown> {\n return Stream.fromAsyncIterable(query, (error) => error);\n}\n"],"mappings":";;;;;;;;;;;;AAUA,SAAS,kBAAqB,OAA+D;CAC3F,OAAO,OAAO,cAAc,QAAQ,QAAQ,MAAM,CAAC,CAAC;AACtD;AASA,SAAgB,UACd,OACA,OACuC;CACvC,IAAI,UAAU,WAAW,GACvB,OAAO,wBACJ,MAAuD,KAAA,CAAS,CACnE;CAGF,OAAO,wBAAwB,MAAM,KAAc,CAAC;AACtD;AASA,SAAgB,YACd,SACA,OACuC;CACvC,IAAI,UAAU,WAAW,GACvB,OAAO,wBAAyB,QAAmD,KAAA,CAAS,CAAC;CAG/F,OAAO,wBAAwB,QAAQ,KAAc,CAAC;AACxD;;;;;;;;;AAUA,SAAgB,uBACd,SACA,OACA,GAAG,SACoC;CACvC,OAAO,wBAAwB,QAAQ,KAAK,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC;AACnE;AASA,SAAgB,cACd,WACA,OACuC;CACvC,IAAI,UAAU,WAAW,GACvB,OAAO,wBACJ,UAA+D,KAAA,CAAS,CAC3E;CAGF,OAAO,wBAAwB,UAAU,KAAc,CAAC;AAC1D;AAWA,SAAgB,WACd,QACqC;CACrC,OAAO,OAAO,OAAO,wBAAwB,OAAO,CAAC,CAAC;AACxD;AAEA,SAAgB,sBACd,QACA,GAAG,SACkC;CACrC,OAAO,OAAO,OAAO,wBAAwB,OAAO,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC;AAC5E;;;;;;;;;;;;;;;;;AAkBA,SAAgB,gBACd,OACgC;CAChC,OAAO,OAAO,kBAAkB,QAAQ,UAAU,KAAK;AACzD"}
1
+ {"version":3,"file":"Remote.js","names":[],"sources":["../src/Remote.ts"],"sourcesContent":["import type {\n RemoteCommand,\n RemoteLiveQuery,\n RemotePrerenderFunction,\n RemoteQuery,\n RemoteQueryFunction,\n RemoteQueryOverride,\n} from \"$app/server\";\nimport { Effect, Stream } from \"effect\";\n\nfunction fromRemotePromise<A>(thunk: () => PromiseLike<A>): Effect.Effect<A, unknown, never> {\n return Effect.promise(() => Promise.resolve(thunk()));\n}\n\n/**\n * Calls a SvelteKit remote `query` as an Effect that succeeds with its output.\n *\n * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a\n * defect, not on the error channel, despite the declared `unknown` error type.\n */\nexport function callQuery<Output>(\n query: RemoteQueryFunction<void, Output>,\n): Effect.Effect<Output, unknown, never>;\n/**\n * Calls a SvelteKit remote `query` with `input` as an Effect that succeeds\n * with its output.\n *\n * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a\n * defect, not on the error channel, despite the declared `unknown` error type.\n */\nexport function callQuery<Input, Output>(\n query: RemoteQueryFunction<Input, Output>,\n input: Input,\n): Effect.Effect<Output, unknown, never>;\nexport function callQuery<Input, Output>(\n query: RemoteQueryFunction<Input, Output>,\n input?: Input,\n): Effect.Effect<Output, unknown, never> {\n if (arguments.length === 1) {\n return fromRemotePromise(() =>\n (query as unknown as RemoteQueryFunction<void, Output>)(undefined),\n );\n }\n\n return fromRemotePromise(() => query(input as Input));\n}\n\n/**\n * Calls a SvelteKit remote `command` as an Effect that succeeds with its\n * output.\n *\n * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a\n * defect, not on the error channel, despite the declared `unknown` error type.\n */\nexport function callCommand<Output>(\n command: RemoteCommand<void, Output>,\n): Effect.Effect<Output, unknown, never>;\n/**\n * Calls a SvelteKit remote `command` with `input` as an Effect that succeeds\n * with its output.\n *\n * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a\n * defect, not on the error channel, despite the declared `unknown` error type.\n */\nexport function callCommand<Input, Output>(\n command: RemoteCommand<Input, Output>,\n input: Input,\n): Effect.Effect<Output, unknown, never>;\nexport function callCommand<Input, Output>(\n command: RemoteCommand<Input, Output>,\n input?: Input,\n): Effect.Effect<Output, unknown, never> {\n if (arguments.length === 1) {\n return fromRemotePromise(() => (command as unknown as RemoteCommand<void, Output>)(undefined));\n }\n\n return fromRemotePromise(() => command(input as Input));\n}\n\n/**\n * Calls a remote command and refreshes the given queries in the same round\n * trip (SvelteKit's single-flight mutations).\n *\n * Newer SvelteKit versions cache remote query instances, so a command that\n * changes data those queries depend on must list them here (or call\n * `query.refresh()` afterwards) for their cached values to update.\n *\n * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a\n * defect, not on the error channel, despite the declared `unknown` error type.\n */\nexport function callCommandWithUpdates<Input, Output>(\n command: RemoteCommand<Input, Output>,\n input: Input,\n ...queries: Array<RemoteQuery<any> | RemoteQueryOverride>\n): Effect.Effect<Output, unknown, never> {\n return fromRemotePromise(() => command(input).updates(...queries));\n}\n\n/**\n * Calls a SvelteKit remote `prerender` function as an Effect that succeeds\n * with its output.\n *\n * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a\n * defect, not on the error channel, despite the declared `unknown` error type.\n */\nexport function callPrerender<Output>(\n prerender: RemotePrerenderFunction<void, Output>,\n): Effect.Effect<Output, unknown, never>;\n/**\n * Calls a SvelteKit remote `prerender` function with `input` as an Effect\n * that succeeds with its output.\n *\n * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a\n * defect, not on the error channel, despite the declared `unknown` error type.\n */\nexport function callPrerender<Input, Output>(\n prerender: RemotePrerenderFunction<Input, Output>,\n input: Input,\n): Effect.Effect<Output, unknown, never>;\nexport function callPrerender<Input, Output>(\n prerender: RemotePrerenderFunction<Input, Output>,\n input?: Input,\n): Effect.Effect<Output, unknown, never> {\n if (arguments.length === 1) {\n return fromRemotePromise(() =>\n (prerender as unknown as RemotePrerenderFunction<void, Output>)(undefined),\n );\n }\n\n return fromRemotePromise(() => prerender(input as Input));\n}\n\n/**\n * The shape of an enhanced remote form `submit` function. The promise result\n * is left open (SvelteKit returns `Promise<void>` in older versions and\n * `Promise<boolean>` in newer ones).\n */\nexport type RemoteSubmit = () => PromiseLike<unknown> & {\n updates: (...queries: Array<RemoteQuery<any> | RemoteQueryOverride>) => PromiseLike<unknown>;\n};\n\n/**\n * Runs an enhanced remote form's `submit()` as an Effect.\n *\n * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a\n * defect, not on the error channel, despite the declared `unknown` error type.\n */\nexport function submitForm(\n submit: () => PromiseLike<unknown>,\n): Effect.Effect<void, unknown, never> {\n return Effect.asVoid(fromRemotePromise(() => submit()));\n}\n\n/**\n * Runs an enhanced remote form's `submit()` and refreshes the given queries in\n * the same round trip (SvelteKit's single-flight mutations).\n *\n * A rejected call (including a thrown `error()` / `redirect()`) surfaces as a\n * defect, not on the error channel, despite the declared `unknown` error type.\n */\nexport function submitFormWithUpdates(\n submit: RemoteSubmit,\n ...queries: Array<RemoteQuery<any> | RemoteQueryOverride>\n): Effect.Effect<void, unknown, never> {\n return Effect.asVoid(fromRemotePromise(() => submit().updates(...queries)));\n}\n\n/**\n * Consumes a SvelteKit live query (`query.live(...)`) as an Effect `Stream`.\n *\n * A `RemoteLiveQuery<T>` is an `AsyncIterable<T>` that yields every update\n * pushed from the server; this turns it into a `Stream` so live data can drive\n * Effect pipelines (and, via `useStream`, Svelte runes).\n *\n * @example\n * ```ts\n * import { Remote } from '@thomasfosterau/effect-sveltekit';\n * import { messages } from './chat.remote';\n * import { useStream } from '@thomasfosterau/effect-svelte';\n *\n * const feed = useStream(Remote.liveQueryStream(messages()));\n * ```\n */\nexport function liveQueryStream<Output>(\n query: RemoteLiveQuery<Output>,\n): Stream.Stream<Output, unknown> {\n return Stream.fromAsyncIterable(query, (error) => error);\n}\n"],"mappings":";;;;;;;;;;;;AAUA,SAAS,kBAAqB,OAA+D;CAC3F,OAAO,OAAO,cAAc,QAAQ,QAAQ,MAAM,CAAC,CAAC;AACtD;AAsBA,SAAgB,UACd,OACA,OACuC;CACvC,IAAI,UAAU,WAAW,GACvB,OAAO,wBACJ,MAAuD,KAAA,CAAS,CACnE;CAGF,OAAO,wBAAwB,MAAM,KAAc,CAAC;AACtD;AAuBA,SAAgB,YACd,SACA,OACuC;CACvC,IAAI,UAAU,WAAW,GACvB,OAAO,wBAAyB,QAAmD,KAAA,CAAS,CAAC;CAG/F,OAAO,wBAAwB,QAAQ,KAAc,CAAC;AACxD;;;;;;;;;;;;AAaA,SAAgB,uBACd,SACA,OACA,GAAG,SACoC;CACvC,OAAO,wBAAwB,QAAQ,KAAK,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC;AACnE;AAuBA,SAAgB,cACd,WACA,OACuC;CACvC,IAAI,UAAU,WAAW,GACvB,OAAO,wBACJ,UAA+D,KAAA,CAAS,CAC3E;CAGF,OAAO,wBAAwB,UAAU,KAAc,CAAC;AAC1D;;;;;;;AAiBA,SAAgB,WACd,QACqC;CACrC,OAAO,OAAO,OAAO,wBAAwB,OAAO,CAAC,CAAC;AACxD;;;;;;;;AASA,SAAgB,sBACd,QACA,GAAG,SACkC;CACrC,OAAO,OAAO,OAAO,wBAAwB,OAAO,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC;AAC5E;;;;;;;;;;;;;;;;;AAkBA,SAAgB,gBACd,OACgC;CAChC,OAAO,OAAO,kBAAkB,QAAQ,UAAU,KAAK;AACzD"}
package/dist/State.d.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  import { PageSnapshot } from "./internal/app-state.js";
2
2
  import { Stream } from "effect";
3
- import { Page } from "@sveltejs/kit";
3
+ import { Page } from "$app/state";
4
4
  declare namespace State_d_exports {
5
- export { PageSnapshot, page };
5
+ export { PageSnapshot, page$1 as page };
6
6
  }
7
7
  /**
8
8
  * A `Stream` of the current SvelteKit `page`, emitting a shallow snapshot
9
9
  * immediately and again after every navigation. Call during component
10
10
  * initialization.
11
11
  */
12
- declare function page(): Stream.Stream<PageSnapshot<Page>>;
12
+ declare function page$1(): Stream.Stream<PageSnapshot<Page>>;
13
13
  //#endregion
14
- export { type PageSnapshot, State_d_exports, page };
14
+ export { type PageSnapshot, State_d_exports, page$1 as page };
15
15
  //# sourceMappingURL=State.d.ts.map
package/dist/State.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"State.js","names":["page","kitPage"],"sources":["../src/State.ts"],"sourcesContent":["/**\n * A minimal Effect-side bridge for SvelteKit's\n * [`$app/state`](https://svelte.dev/docs/kit/$app-state) `page`.\n *\n * `$app/state` exposes rune-reactive `page` / `navigating` / `updated` for use\n * inside components. This bridges `page` to an Effect `Stream` so navigation can\n * drive Effect pipelines without touching Svelte runes: it emits the current\n * `page` immediately, then again after each navigation, by registering\n * `afterNavigate` (from `$app/navigation`) and reading `page` (from\n * `$app/state`) at callback time.\n *\n * Each emission is a *shallow snapshot* (`url`, `params`, `route`, `data`,\n * `status`, `error`, `form`, `state`) rather than the live `$app/state` proxy:\n * the proxy mutates in place on every navigation, so a captured reference is\n * unreliable for downstream consumers — the snapshot gives each emission a\n * stable value. Reading at `afterNavigate` time also avoids needing a `.svelte`\n * runes file.\n *\n * Like the navigation-event helpers, `page` registers its callback during\n * component initialization (where `$app/navigation` requires), so call it at the\n * top level of `<script>`. Client-only.\n *\n * NOTE: this is intentionally minimal. A richer reactive bridge (a `CurrentPage`\n * service readable from any Effect, `navigating` / `updated` streams) may later\n * compose with the official `@effect/atom-svelte` integration (see issue #23)\n * rather than re-implementing runes plumbing here.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { State } from '@thomasfosterau/effect-sveltekit/client';\n * import { Stream, Effect } from 'effect';\n * import { getRuntime } from '@thomasfosterau/effect-svelte';\n *\n * const pages = State.page();\n * getRuntime().runFork(\n * Stream.runForEach(pages, (page) =>\n * Effect.logInfo(`page: ${page.url.pathname}`),\n * ),\n * );\n * </script>\n * ```\n */\n\nimport { afterNavigate as kitAfterNavigate } from \"$app/navigation\";\nimport { page as kitPage } from \"$app/state\";\nimport type { Page } from \"@sveltejs/kit\";\nimport type { Stream } from \"effect\";\nimport { type PageSnapshot, pageSnapshotStream } from \"./internal/app-state.js\";\n\n/** A shallow snapshot of SvelteKit's `page` — see {@link page}. */\nexport type { PageSnapshot } from \"./internal/app-state.js\";\n\n/**\n * A `Stream` of the current SvelteKit `page`, emitting a shallow snapshot\n * immediately and again after every navigation. Call during component\n * initialization.\n */\nexport function page(): Stream.Stream<PageSnapshot<Page>> {\n return pageSnapshotStream<Page>(\n (callback) => {\n kitAfterNavigate(() => {\n callback();\n });\n },\n () => kitPage,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,SAAgBA,SAA0C;CACxD,OAAO,oBACJ,aAAa;EACZ,oBAAuB;GACrB,SAAS;EACX,CAAC;CACH,SACMC,IACR;AACF"}
1
+ {"version":3,"file":"State.js","names":["page","kitPage"],"sources":["../src/State.ts"],"sourcesContent":["/**\n * A minimal Effect-side bridge for SvelteKit's\n * [`$app/state`](https://svelte.dev/docs/kit/$app-state) `page`.\n *\n * `$app/state` exposes rune-reactive `page` / `navigating` / `updated` for use\n * inside components. This bridges `page` to an Effect `Stream` so navigation can\n * drive Effect pipelines without touching Svelte runes: it emits the current\n * `page` immediately, then again after each navigation, by registering\n * `afterNavigate` (from `$app/navigation`) and reading `page` (from\n * `$app/state`) at callback time.\n *\n * Each emission is a *shallow snapshot* (`url`, `params`, `route`, `data`,\n * `status`, `error`, `form`, `state`) rather than the live `$app/state` proxy:\n * the proxy mutates in place on every navigation, so a captured reference is\n * unreliable for downstream consumers — the snapshot gives each emission a\n * stable value. Reading at `afterNavigate` time also avoids needing a `.svelte`\n * runes file.\n *\n * Like the navigation-event helpers, `page` registers its callback during\n * component initialization (where `$app/navigation` requires), so call it at the\n * top level of `<script>`. Client-only.\n *\n * NOTE: this is intentionally minimal. A richer reactive bridge (a `CurrentPage`\n * service readable from any Effect, `navigating` / `updated` streams) may later\n * compose with the official `@effect/atom-svelte` integration (see issue #23)\n * rather than re-implementing runes plumbing here.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { State } from '@thomasfosterau/effect-sveltekit/client';\n * import { Stream, Effect } from 'effect';\n * import { getRuntime } from '@thomasfosterau/effect-svelte';\n *\n * const pages = State.page();\n * getRuntime().runFork(\n * Stream.runForEach(pages, (page) =>\n * Effect.logInfo(`page: ${page.url.pathname}`),\n * ),\n * );\n * </script>\n * ```\n */\n\nimport { afterNavigate as kitAfterNavigate } from \"$app/navigation\";\nimport { page as kitPage } from \"$app/state\";\nimport type { Page } from \"$app/state\";\nimport type { Stream } from \"effect\";\nimport { type PageSnapshot, pageSnapshotStream } from \"./internal/app-state.js\";\n\n/** A shallow snapshot of SvelteKit's `page` — see {@link page}. */\nexport type { PageSnapshot } from \"./internal/app-state.js\";\n\n/**\n * A `Stream` of the current SvelteKit `page`, emitting a shallow snapshot\n * immediately and again after every navigation. Call during component\n * initialization.\n */\nexport function page(): Stream.Stream<PageSnapshot<Page>> {\n return pageSnapshotStream<Page>(\n (callback) => {\n kitAfterNavigate(() => {\n callback();\n });\n },\n () => kitPage,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,SAAgBA,SAA0C;CACxD,OAAO,oBACJ,aAAa;EACZ,oBAAuB;GACrB,SAAS;EACX,CAAC;CACH,SACMC,IACR;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { AssetSource, FileSystemAssetServices } from "./assets.js";
2
2
  import { Effect, Layer } from "effect";
3
- import { SSRManifest, Server } from "@sveltejs/kit";
3
+ import { Server } from "@sveltejs/kit";
4
4
  import * as HttpServerRequest from "effect/http/HttpServerRequest";
5
5
  import * as HttpServerResponse from "effect/http/HttpServerResponse";
6
6
  //#region src/adapter/handler.d.ts
@@ -17,11 +17,17 @@ type SvelteKitHttpAppServices = FileSystemAssetServices;
17
17
  * is the asset source's services (defaults to the file-system services).
18
18
  */
19
19
  type SvelteKitHttpApp<R = SvelteKitHttpAppServices> = Effect.Effect<HttpServerResponse.HttpServerResponse, never, R | HttpServerRequest.HttpServerRequest>;
20
+ /** The SvelteKit build output {@link makeHandler} serves. */
20
21
  interface SvelteKitHandlerOptions {
21
- /** The SvelteKit `Server` class exported by the build output (`./server/index.js`). */
22
- readonly Server: typeof Server;
23
- /** The SSR manifest exported by the build output (`./manifest.js`). */
24
- readonly manifest: SSRManifest;
22
+ /** The SvelteKit `server` instance exported by the build output (`./server.js`). */
23
+ readonly server: Server;
24
+ /**
25
+ * The application path, including any `paths.base` without its leading
26
+ * slash (`"_app"`, or `"my-app/_app"` under a base), exported by the build
27
+ * output (`./manifest.js`). Its `immutable/` subtree gets immutable cache
28
+ * headers.
29
+ */
30
+ readonly appPath: string;
25
31
  /** The set of prerendered paths exported by the build output (`./manifest.js`). */
26
32
  readonly prerendered: ReadonlySet<string>;
27
33
  /** The configured `paths.base`, exported by the build output (`./manifest.js`). */
@@ -35,10 +41,8 @@ interface SvelteKitHandlerOptions {
35
41
  }
36
42
  /** Options for the platform-neutral SSR core, {@link makeHandlerWith}. */
37
43
  interface SvelteKitNeutralHandlerOptions<RAssets> {
38
- /** The SvelteKit `Server` class exported by the build output. */
39
- readonly Server: typeof Server;
40
- /** The SSR manifest exported by the build output. */
41
- readonly manifest: SSRManifest;
44
+ /** The SvelteKit `server` instance exported by the build output (`./server.js`). */
45
+ readonly server: Server;
42
46
  /** Environment variables passed to the SvelteKit server. */
43
47
  readonly env?: Record<string, string | undefined> | undefined;
44
48
  /** Prefix for the runtime configuration environment variables (ORIGIN, ...). */
@@ -96,14 +100,13 @@ declare const makeHandler: (options: SvelteKitHandlerOptions) => Effect.Effect<S
96
100
  * ```ts
97
101
  * // Workers: a fetch handler with assets from env.ASSETS
98
102
  * import { makeHandlerWith, AssetSource, toWebHandler } from "...adapter/handler";
99
- * import { Server } from "./server/index.js";
100
- * import { manifest } from "./manifest.js";
103
+ * import { server } from "./server.js";
101
104
  *
102
105
  * export default {
103
106
  * fetch: (request, env, ctx) =>
104
107
  * toWebHandler(
105
108
  * makeHandlerWith({
106
- * Server, manifest, env,
109
+ * server, env,
107
110
  * assets: AssetSource.cloudflareAssets(env.ASSETS),
108
111
  * read: () => { throw new Error("read() not supported on this deployment"); },
109
112
  * }),
@@ -89,14 +89,13 @@ const makeHandler = (options) => Effect.gen(function* () {
89
89
  const context = yield* Effect.context();
90
90
  const serverDir = path.join(options.dir, "server");
91
91
  return yield* makeHandlerWith({
92
- Server: options.Server,
93
- manifest: options.manifest,
92
+ server: options.server,
94
93
  env: options.env,
95
94
  envPrefix: options.envPrefix,
96
95
  read: (file) => Stream.toReadableStreamWith(fs.stream(path.join(serverDir, file)), context),
97
96
  assets: AssetSource.fileSystem({
98
97
  dir: options.dir,
99
- appPath: options.manifest.appPath,
98
+ appPath: options.appPath,
100
99
  prerendered: options.prerendered
101
100
  })
102
101
  });
@@ -117,14 +116,13 @@ const makeHandler = (options) => Effect.gen(function* () {
117
116
  * ```ts
118
117
  * // Workers: a fetch handler with assets from env.ASSETS
119
118
  * import { makeHandlerWith, AssetSource, toWebHandler } from "...adapter/handler";
120
- * import { Server } from "./server/index.js";
121
- * import { manifest } from "./manifest.js";
119
+ * import { server } from "./server.js";
122
120
  *
123
121
  * export default {
124
122
  * fetch: (request, env, ctx) =>
125
123
  * toWebHandler(
126
124
  * makeHandlerWith({
127
- * Server, manifest, env,
125
+ * server, env,
128
126
  * assets: AssetSource.cloudflareAssets(env.ASSETS),
129
127
  * read: () => { throw new Error("read() not supported on this deployment"); },
130
128
  * }),
@@ -134,7 +132,7 @@ const makeHandler = (options) => Effect.gen(function* () {
134
132
  */
135
133
  const makeHandlerWith = (options) => Effect.gen(function* () {
136
134
  const config = yield* handlerConfig(options.envPrefix ?? "").pipe(Effect.orDie);
137
- const server = new options.Server(options.manifest);
135
+ const server = options.server;
138
136
  yield* Effect.promise(() => server.init({
139
137
  env: options.env ?? {},
140
138
  read: options.read
@@ -1 +1 @@
1
- {"version":3,"file":"handler.js","names":[],"sources":["../../src/adapter/handler.ts"],"sourcesContent":["/**\n * Runtime handler for the Effect SvelteKit adapter.\n *\n * `makeHandler` turns a built SvelteKit app (the `Server` class and manifest\n * emitted by `vite build`) into an Effect HTTP application that serves\n * static client assets, prerendered pages, and server-side rendered routes from\n * disk — the Node default.\n *\n * {@link makeHandlerWith} is the platform-neutral core: it takes an injected\n * {@link AssetSource} (where assets come from) and a `read` capability (how to\n * read server assets), so the same SvelteKit `HttpApp` can run on a Node server\n * or on Cloudflare Workers (assets from `env.ASSETS`).\n *\n * The returned app is an ordinary Effect value: it can be served with the\n * generated `build/index.js` entry (see `./serve.js`), mounted inside any\n * existing `effect/http` HTTP server, or converted to a `fetch` handler\n * (see {@link toWebHandler}).\n */\n\nimport type { SSRManifest, Server as SvelteKitServer } from \"@sveltejs/kit\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as HttpMethod from \"effect/http/HttpMethod\";\nimport * as HttpEffect from \"effect/http/HttpEffect\";\nimport * as HttpServerRequest from \"effect/http/HttpServerRequest\";\nimport * as HttpServerResponse from \"effect/http/HttpServerResponse\";\nimport * as Path from \"effect/Path\";\nimport { Config, Context, Effect, Layer, Option, Stream } from \"effect\";\nimport { AssetSource, type FileSystemAssetServices } from \"./assets.js\";\n\nexport { AssetSource, type FileSystemAssetServices } from \"./assets.js\";\n\n/**\n * The services required by the SvelteKit HTTP application when serving assets\n * from the file system (the Node default). All of them are provided by\n * `NodeHttpServer.layer` from `@effect/platform-node`.\n */\nexport type SvelteKitHttpAppServices = FileSystemAssetServices;\n\n/**\n * The SvelteKit application as a composable Effect HTTP handler: an effect that\n * produces an {@link HttpServerResponse.HttpServerResponse} for the current\n * request. The `HttpServerRequest` is supplied per request by the server. `R`\n * is the asset source's services (defaults to the file-system services).\n */\nexport type SvelteKitHttpApp<R = SvelteKitHttpAppServices> = Effect.Effect<\n HttpServerResponse.HttpServerResponse,\n never,\n R | HttpServerRequest.HttpServerRequest\n>;\n\nexport interface SvelteKitHandlerOptions {\n /** The SvelteKit `Server` class exported by the build output (`./server/index.js`). */\n readonly Server: typeof SvelteKitServer;\n /** The SSR manifest exported by the build output (`./manifest.js`). */\n readonly manifest: SSRManifest;\n /** The set of prerendered paths exported by the build output (`./manifest.js`). */\n readonly prerendered: ReadonlySet<string>;\n /** The configured `paths.base`, exported by the build output (`./manifest.js`). */\n readonly base: string;\n /** Absolute path of the build output directory (contains `client/`, `server/`, `prerendered/`). */\n readonly dir: string;\n /** Environment variables passed to the SvelteKit server (e.g. `process.env`). */\n readonly env?: Record<string, string | undefined>;\n /** Prefix for the runtime configuration environment variables (ORIGIN, ...). */\n readonly envPrefix?: string;\n}\n\n/** Options for the platform-neutral SSR core, {@link makeHandlerWith}. */\nexport interface SvelteKitNeutralHandlerOptions<RAssets> {\n /** The SvelteKit `Server` class exported by the build output. */\n readonly Server: typeof SvelteKitServer;\n /** The SSR manifest exported by the build output. */\n readonly manifest: SSRManifest;\n /** Environment variables passed to the SvelteKit server. */\n readonly env?: Record<string, string | undefined> | undefined;\n /** Prefix for the runtime configuration environment variables (ORIGIN, ...). */\n readonly envPrefix?: string | undefined;\n /** Where static client assets and prerendered pages come from. */\n readonly assets: AssetSource<RAssets>;\n /**\n * How to read a server asset (backs `read()` from `$app/server`). On Node\n * this streams from `<dir>/server`; on Workers, back it with the platform's\n * own mechanism.\n */\n readonly read: (file: string) => ReadableStream<Uint8Array>;\n}\n\n/** Runtime configuration, read from the environment (compatible with adapter-node). */\nconst handlerConfig = (prefix: string) =>\n Config.all({\n origin: Config.option(Config.String(`${prefix}ORIGIN`)),\n protocolHeader: Config.option(Config.String(`${prefix}PROTOCOL_HEADER`)),\n hostHeader: Config.option(Config.String(`${prefix}HOST_HEADER`)),\n portHeader: Config.option(Config.String(`${prefix}PORT_HEADER`)),\n addressHeader: Config.option(Config.String(`${prefix}ADDRESS_HEADER`)),\n xffDepth: Config.Int(`${prefix}XFF_DEPTH`).pipe(Config.withDefault(1)),\n });\n\ntype HandlerConfig = Effect.Success<ReturnType<typeof handlerConfig>>;\n\n/** Compute the request origin from configuration and headers (adapter-node semantics). */\nconst originOf = (request: HttpServerRequest.HttpServerRequest, config: HandlerConfig): string => {\n if (Option.isSome(config.origin)) return config.origin.value;\n\n const headers = request.headers;\n const protocolHeader = Option.getOrUndefined(config.protocolHeader)?.toLowerCase();\n const hostHeader = Option.getOrUndefined(config.hostHeader)?.toLowerCase() ?? \"host\";\n const portHeader = Option.getOrUndefined(config.portHeader)?.toLowerCase();\n\n const protocol = (protocolHeader && headers[protocolHeader]) || \"http\";\n const host = headers[hostHeader] ?? \"localhost\";\n const port = portHeader ? headers[portHeader] : undefined;\n\n return port ? `${protocol}://${host.split(\":\")[0]}:${port}` : `${protocol}://${host}`;\n};\n\n/** Resolve the client address, honouring ADDRESS_HEADER / XFF_DEPTH if configured. */\nconst clientAddressOf = (\n request: HttpServerRequest.HttpServerRequest,\n config: HandlerConfig,\n): string => {\n const addressHeader = Option.getOrUndefined(config.addressHeader)?.toLowerCase();\n if (addressHeader) {\n const value = request.headers[addressHeader];\n if (value) {\n if (addressHeader === \"x-forwarded-for\") {\n const addresses = value.split(\",\").map((address) => address.trim());\n if (config.xffDepth < 1 || config.xffDepth > addresses.length) {\n return addresses[0] ?? \"\";\n }\n return addresses[addresses.length - config.xffDepth]!;\n }\n return value;\n }\n }\n return Option.getOrElse(request.remoteAddress, () => \"\");\n};\n\n/** Build a web `Request` for SvelteKit from an `HttpServerRequest`. */\nconst toWebRequest = (\n request: HttpServerRequest.HttpServerRequest,\n url: URL,\n context: Context.Context<never>,\n): Request => {\n // `Headers` is a redactable record-like value; copy the enumerable string\n // entries into a plain record for the web `Request` constructor.\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers: { ...request.headers },\n };\n if (HttpMethod.hasBody(request.method)) {\n init.body = Stream.toReadableStreamWith(request.stream, context);\n init.duplex = \"half\";\n }\n return new Request(url, init);\n};\n\n/**\n * Creates the SvelteKit HTTP handler.\n *\n * The returned effect initialises the SvelteKit server (running your app's\n * server `init` hook) and yields an HTTP handler that:\n *\n * 1. serves static client assets from `<dir>/client` (with immutable cache\n * headers for hashed build assets),\n * 2. serves prerendered pages from `<dir>/prerendered`,\n * 3. falls back to server-side rendering via the SvelteKit server.\n *\n * @example\n * ```ts\n * // Mounting SvelteKit inside an existing effect/http server:\n * import { handler } from \"./build/handler.js\";\n * import * as HttpServer from \"effect/http/HttpServer\";\n * import { NodeHttpServer, NodeRuntime } from \"@effect/platform-node\";\n * import { Effect, Layer } from \"effect\";\n * import { createServer } from \"node:http\";\n *\n * const serverLayer = Layer.unwrap(\n * Effect.map(handler, (app) => HttpServer.serve(app))\n * ).pipe(Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })));\n *\n * NodeRuntime.runMain(Layer.launch(serverLayer));\n * ```\n */\nexport const makeHandler = (\n options: SvelteKitHandlerOptions,\n): Effect.Effect<SvelteKitHttpApp, never, SvelteKitHttpAppServices> =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const context = yield* Effect.context<never>();\n\n const serverDir = path.join(options.dir, \"server\");\n\n return yield* makeHandlerWith<SvelteKitHttpAppServices>({\n Server: options.Server,\n manifest: options.manifest,\n env: options.env,\n envPrefix: options.envPrefix,\n // `read` backs the `read()` helper from `$app/server`, streaming server\n // assets from the build output.\n read: (file) => Stream.toReadableStreamWith(fs.stream(path.join(serverDir, file)), context),\n assets: AssetSource.fileSystem({\n dir: options.dir,\n appPath: options.manifest.appPath,\n prerendered: options.prerendered,\n }),\n });\n });\n\n/**\n * The platform-neutral SSR core. Like {@link makeHandler}, but the asset source\n * and the server-asset `read` capability are injected, so the same SvelteKit\n * `HttpApp` can run on Node (file-system assets) or on Cloudflare Workers\n * (`AssetSource.cloudflareAssets(env.ASSETS)`).\n *\n * The returned app:\n *\n * 1. falls through to the injected {@link AssetSource} for static client assets\n * and prerendered pages (GET/HEAD), then\n * 2. server-side renders via the SvelteKit server.\n *\n * @example\n * ```ts\n * // Workers: a fetch handler with assets from env.ASSETS\n * import { makeHandlerWith, AssetSource, toWebHandler } from \"...adapter/handler\";\n * import { Server } from \"./server/index.js\";\n * import { manifest } from \"./manifest.js\";\n *\n * export default {\n * fetch: (request, env, ctx) =>\n * toWebHandler(\n * makeHandlerWith({\n * Server, manifest, env,\n * assets: AssetSource.cloudflareAssets(env.ASSETS),\n * read: () => { throw new Error(\"read() not supported on this deployment\"); },\n * }),\n * )(request),\n * };\n * ```\n */\nexport const makeHandlerWith = <RAssets = never>(\n options: SvelteKitNeutralHandlerOptions<RAssets>,\n): Effect.Effect<SvelteKitHttpApp<RAssets>, never, never> =>\n Effect.gen(function* () {\n const config = yield* handlerConfig(options.envPrefix ?? \"\").pipe(Effect.orDie);\n\n // Initialise the SvelteKit server. `read` backs `read()` from `$app/server`.\n const server = new options.Server(options.manifest);\n yield* Effect.promise(() =>\n server.init({\n env: (options.env ?? {}) as Record<string, string>,\n read: options.read,\n }),\n );\n\n // The HTTP handler itself, evaluated once per request.\n return Effect.gen(function* () {\n const request = yield* HttpServerRequest.HttpServerRequest;\n const requestContext = yield* Effect.context<never>();\n\n const origin = originOf(request, config);\n const url = new URL(request.url, origin);\n\n let pathname: string;\n try {\n pathname = decodeURIComponent(url.pathname);\n } catch {\n return HttpServerResponse.empty({ status: 400 });\n }\n\n // 1. Static client assets / prerendered pages, via the injected source.\n // Only GET/HEAD reach assets; build a body-less request for the source.\n if (request.method === \"GET\" || request.method === \"HEAD\") {\n const assetRequest = new Request(url, {\n method: request.method,\n headers: { ...request.headers },\n });\n const asset = yield* options.assets.serveAsset(assetRequest, pathname);\n if (Option.isSome(asset)) return asset.value;\n }\n\n // 2. Server-side rendering.\n const webRequest = toWebRequest(request, url, requestContext);\n const response = yield* Effect.promise(() =>\n server.respond(webRequest, {\n getClientAddress: () => clientAddressOf(request, config),\n }),\n );\n return HttpServerResponse.fromWeb(response);\n });\n });\n\n/**\n * Convert a SvelteKit `HttpApp` to a Web `fetch` handler, providing the asset\n * source's services with `layer`. Use this for a Workers `fetch` export or any\n * runtime that speaks the Web platform.\n *\n * @example\n * ```ts\n * const fetchHandler = toWebHandler(\n * makeHandlerWith({ ..., assets: AssetSource.cloudflareAssets(env.ASSETS) }),\n * Layer.empty,\n * );\n * ```\n */\nexport const toWebHandler = <RAssets, E>(\n app: Effect.Effect<SvelteKitHttpApp<RAssets>, never, never>,\n layer: Layer.Layer<RAssets, E>,\n): ((request: Request) => Promise<Response>) => {\n // Build the app (server.init) and the per-request web handler once, lazily on\n // the first request, then dispatch each request through it.\n let built: Promise<(request: Request) => Promise<Response>> | undefined;\n const build = (): Promise<(request: Request) => Promise<Response>> =>\n (built ??= Effect.runPromise(app).then(\n (inner) =>\n HttpEffect.toWebHandlerLayer(inner, layer).handler as (\n request: Request,\n ) => Promise<Response>,\n ));\n return async (request) => (await build())(request);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"handler.js","names":[],"sources":["../../src/adapter/handler.ts"],"sourcesContent":["/**\n * Runtime handler for the Effect SvelteKit adapter.\n *\n * `makeHandler` turns a built SvelteKit app (the `server` instance the adapter\n * generates with `builder.generateServerInstance`) into an Effect HTTP application that serves\n * static client assets, prerendered pages, and server-side rendered routes from\n * disk — the Node default.\n *\n * {@link makeHandlerWith} is the platform-neutral core: it takes an injected\n * {@link AssetSource} (where assets come from) and a `read` capability (how to\n * read server assets), so the same SvelteKit `HttpApp` can run on a Node server\n * or on Cloudflare Workers (assets from `env.ASSETS`).\n *\n * The returned app is an ordinary Effect value: it can be served with the\n * generated `build/index.js` entry (see `./serve.js`), mounted inside any\n * existing `effect/http` HTTP server, or converted to a `fetch` handler\n * (see {@link toWebHandler}).\n */\n\nimport type { Server as SvelteKitServer } from \"@sveltejs/kit\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as HttpMethod from \"effect/http/HttpMethod\";\nimport * as HttpEffect from \"effect/http/HttpEffect\";\nimport * as HttpServerRequest from \"effect/http/HttpServerRequest\";\nimport * as HttpServerResponse from \"effect/http/HttpServerResponse\";\nimport * as Path from \"effect/Path\";\nimport { Config, Context, Effect, Layer, Option, Stream } from \"effect\";\nimport { AssetSource, type FileSystemAssetServices } from \"./assets.js\";\n\nexport { AssetSource, type FileSystemAssetServices } from \"./assets.js\";\n\n/**\n * The services required by the SvelteKit HTTP application when serving assets\n * from the file system (the Node default). All of them are provided by\n * `NodeHttpServer.layer` from `@effect/platform-node`.\n */\nexport type SvelteKitHttpAppServices = FileSystemAssetServices;\n\n/**\n * The SvelteKit application as a composable Effect HTTP handler: an effect that\n * produces an {@link HttpServerResponse.HttpServerResponse} for the current\n * request. The `HttpServerRequest` is supplied per request by the server. `R`\n * is the asset source's services (defaults to the file-system services).\n */\nexport type SvelteKitHttpApp<R = SvelteKitHttpAppServices> = Effect.Effect<\n HttpServerResponse.HttpServerResponse,\n never,\n R | HttpServerRequest.HttpServerRequest\n>;\n\n/** The SvelteKit build output {@link makeHandler} serves. */\nexport interface SvelteKitHandlerOptions {\n /** The SvelteKit `server` instance exported by the build output (`./server.js`). */\n readonly server: SvelteKitServer;\n /**\n * The application path, including any `paths.base` without its leading\n * slash (`\"_app\"`, or `\"my-app/_app\"` under a base), exported by the build\n * output (`./manifest.js`). Its `immutable/` subtree gets immutable cache\n * headers.\n */\n readonly appPath: string;\n /** The set of prerendered paths exported by the build output (`./manifest.js`). */\n readonly prerendered: ReadonlySet<string>;\n /** The configured `paths.base`, exported by the build output (`./manifest.js`). */\n readonly base: string;\n /** Absolute path of the build output directory (contains `client/`, `server/`, `prerendered/`). */\n readonly dir: string;\n /** Environment variables passed to the SvelteKit server (e.g. `process.env`). */\n readonly env?: Record<string, string | undefined>;\n /** Prefix for the runtime configuration environment variables (ORIGIN, ...). */\n readonly envPrefix?: string;\n}\n\n/** Options for the platform-neutral SSR core, {@link makeHandlerWith}. */\nexport interface SvelteKitNeutralHandlerOptions<RAssets> {\n /** The SvelteKit `server` instance exported by the build output (`./server.js`). */\n readonly server: SvelteKitServer;\n /** Environment variables passed to the SvelteKit server. */\n readonly env?: Record<string, string | undefined> | undefined;\n /** Prefix for the runtime configuration environment variables (ORIGIN, ...). */\n readonly envPrefix?: string | undefined;\n /** Where static client assets and prerendered pages come from. */\n readonly assets: AssetSource<RAssets>;\n /**\n * How to read a server asset (backs `read()` from `$app/server`). On Node\n * this streams from `<dir>/server`; on Workers, back it with the platform's\n * own mechanism.\n */\n readonly read: (file: string) => ReadableStream<Uint8Array>;\n}\n\n/** Runtime configuration, read from the environment (compatible with adapter-node). */\nconst handlerConfig = (prefix: string) =>\n Config.all({\n origin: Config.option(Config.String(`${prefix}ORIGIN`)),\n protocolHeader: Config.option(Config.String(`${prefix}PROTOCOL_HEADER`)),\n hostHeader: Config.option(Config.String(`${prefix}HOST_HEADER`)),\n portHeader: Config.option(Config.String(`${prefix}PORT_HEADER`)),\n addressHeader: Config.option(Config.String(`${prefix}ADDRESS_HEADER`)),\n xffDepth: Config.Int(`${prefix}XFF_DEPTH`).pipe(Config.withDefault(1)),\n });\n\ntype HandlerConfig = Effect.Success<ReturnType<typeof handlerConfig>>;\n\n/** Compute the request origin from configuration and headers (adapter-node semantics). */\nconst originOf = (request: HttpServerRequest.HttpServerRequest, config: HandlerConfig): string => {\n if (Option.isSome(config.origin)) return config.origin.value;\n\n const headers = request.headers;\n const protocolHeader = Option.getOrUndefined(config.protocolHeader)?.toLowerCase();\n const hostHeader = Option.getOrUndefined(config.hostHeader)?.toLowerCase() ?? \"host\";\n const portHeader = Option.getOrUndefined(config.portHeader)?.toLowerCase();\n\n const protocol = (protocolHeader && headers[protocolHeader]) || \"http\";\n const host = headers[hostHeader] ?? \"localhost\";\n const port = portHeader ? headers[portHeader] : undefined;\n\n return port ? `${protocol}://${host.split(\":\")[0]}:${port}` : `${protocol}://${host}`;\n};\n\n/** Resolve the client address, honouring ADDRESS_HEADER / XFF_DEPTH if configured. */\nconst clientAddressOf = (\n request: HttpServerRequest.HttpServerRequest,\n config: HandlerConfig,\n): string => {\n const addressHeader = Option.getOrUndefined(config.addressHeader)?.toLowerCase();\n if (addressHeader) {\n const value = request.headers[addressHeader];\n if (value) {\n if (addressHeader === \"x-forwarded-for\") {\n const addresses = value.split(\",\").map((address) => address.trim());\n if (config.xffDepth < 1 || config.xffDepth > addresses.length) {\n return addresses[0] ?? \"\";\n }\n return addresses[addresses.length - config.xffDepth]!;\n }\n return value;\n }\n }\n return Option.getOrElse(request.remoteAddress, () => \"\");\n};\n\n/** Build a web `Request` for SvelteKit from an `HttpServerRequest`. */\nconst toWebRequest = (\n request: HttpServerRequest.HttpServerRequest,\n url: URL,\n context: Context.Context<never>,\n): Request => {\n // `Headers` is a redactable record-like value; copy the enumerable string\n // entries into a plain record for the web `Request` constructor.\n const init: RequestInit & { duplex?: \"half\" } = {\n method: request.method,\n headers: { ...request.headers },\n };\n if (HttpMethod.hasBody(request.method)) {\n init.body = Stream.toReadableStreamWith(request.stream, context);\n init.duplex = \"half\";\n }\n return new Request(url, init);\n};\n\n/**\n * Creates the SvelteKit HTTP handler.\n *\n * The returned effect initialises the SvelteKit server (running your app's\n * server `init` hook) and yields an HTTP handler that:\n *\n * 1. serves static client assets from `<dir>/client` (with immutable cache\n * headers for hashed build assets),\n * 2. serves prerendered pages from `<dir>/prerendered`,\n * 3. falls back to server-side rendering via the SvelteKit server.\n *\n * @example\n * ```ts\n * // Mounting SvelteKit inside an existing effect/http server:\n * import { handler } from \"./build/handler.js\";\n * import * as HttpServer from \"effect/http/HttpServer\";\n * import { NodeHttpServer, NodeRuntime } from \"@effect/platform-node\";\n * import { Effect, Layer } from \"effect\";\n * import { createServer } from \"node:http\";\n *\n * const serverLayer = Layer.unwrap(\n * Effect.map(handler, (app) => HttpServer.serve(app))\n * ).pipe(Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })));\n *\n * NodeRuntime.runMain(Layer.launch(serverLayer));\n * ```\n */\nexport const makeHandler = (\n options: SvelteKitHandlerOptions,\n): Effect.Effect<SvelteKitHttpApp, never, SvelteKitHttpAppServices> =>\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n const context = yield* Effect.context<never>();\n\n const serverDir = path.join(options.dir, \"server\");\n\n return yield* makeHandlerWith<SvelteKitHttpAppServices>({\n server: options.server,\n env: options.env,\n envPrefix: options.envPrefix,\n // `read` backs the `read()` helper from `$app/server`, streaming server\n // assets from the build output.\n read: (file) => Stream.toReadableStreamWith(fs.stream(path.join(serverDir, file)), context),\n assets: AssetSource.fileSystem({\n dir: options.dir,\n appPath: options.appPath,\n prerendered: options.prerendered,\n }),\n });\n });\n\n/**\n * The platform-neutral SSR core. Like {@link makeHandler}, but the asset source\n * and the server-asset `read` capability are injected, so the same SvelteKit\n * `HttpApp` can run on Node (file-system assets) or on Cloudflare Workers\n * (`AssetSource.cloudflareAssets(env.ASSETS)`).\n *\n * The returned app:\n *\n * 1. falls through to the injected {@link AssetSource} for static client assets\n * and prerendered pages (GET/HEAD), then\n * 2. server-side renders via the SvelteKit server.\n *\n * @example\n * ```ts\n * // Workers: a fetch handler with assets from env.ASSETS\n * import { makeHandlerWith, AssetSource, toWebHandler } from \"...adapter/handler\";\n * import { server } from \"./server.js\";\n *\n * export default {\n * fetch: (request, env, ctx) =>\n * toWebHandler(\n * makeHandlerWith({\n * server, env,\n * assets: AssetSource.cloudflareAssets(env.ASSETS),\n * read: () => { throw new Error(\"read() not supported on this deployment\"); },\n * }),\n * )(request),\n * };\n * ```\n */\nexport const makeHandlerWith = <RAssets = never>(\n options: SvelteKitNeutralHandlerOptions<RAssets>,\n): Effect.Effect<SvelteKitHttpApp<RAssets>, never, never> =>\n Effect.gen(function* () {\n const config = yield* handlerConfig(options.envPrefix ?? \"\").pipe(Effect.orDie);\n\n // Initialise the SvelteKit server. `read` backs `read()` from `$app/server`.\n const server = options.server;\n yield* Effect.promise(() =>\n server.init({\n env: options.env ?? {},\n read: options.read,\n }),\n );\n\n // The HTTP handler itself, evaluated once per request.\n return Effect.gen(function* () {\n const request = yield* HttpServerRequest.HttpServerRequest;\n const requestContext = yield* Effect.context<never>();\n\n const origin = originOf(request, config);\n const url = new URL(request.url, origin);\n\n let pathname: string;\n try {\n pathname = decodeURIComponent(url.pathname);\n } catch {\n return HttpServerResponse.empty({ status: 400 });\n }\n\n // 1. Static client assets / prerendered pages, via the injected source.\n // Only GET/HEAD reach assets; build a body-less request for the source.\n if (request.method === \"GET\" || request.method === \"HEAD\") {\n const assetRequest = new Request(url, {\n method: request.method,\n headers: { ...request.headers },\n });\n const asset = yield* options.assets.serveAsset(assetRequest, pathname);\n if (Option.isSome(asset)) return asset.value;\n }\n\n // 2. Server-side rendering.\n const webRequest = toWebRequest(request, url, requestContext);\n const response = yield* Effect.promise(() =>\n server.respond(webRequest, {\n getClientAddress: () => clientAddressOf(request, config),\n }),\n );\n return HttpServerResponse.fromWeb(response);\n });\n });\n\n/**\n * Convert a SvelteKit `HttpApp` to a Web `fetch` handler, providing the asset\n * source's services with `layer`. Use this for a Workers `fetch` export or any\n * runtime that speaks the Web platform.\n *\n * @example\n * ```ts\n * const fetchHandler = toWebHandler(\n * makeHandlerWith({ ..., assets: AssetSource.cloudflareAssets(env.ASSETS) }),\n * Layer.empty,\n * );\n * ```\n */\nexport const toWebHandler = <RAssets, E>(\n app: Effect.Effect<SvelteKitHttpApp<RAssets>, never, never>,\n layer: Layer.Layer<RAssets, E>,\n): ((request: Request) => Promise<Response>) => {\n // Build the app (server.init) and the per-request web handler once, lazily on\n // the first request, then dispatch each request through it.\n let built: Promise<(request: Request) => Promise<Response>> | undefined;\n const build = (): Promise<(request: Request) => Promise<Response>> =>\n (built ??= Effect.runPromise(app).then(\n (inner) =>\n HttpEffect.toWebHandlerLayer(inner, layer).handler as (\n request: Request,\n ) => Promise<Response>,\n ));\n return async (request) => (await build())(request);\n};\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { Adapter } from "@sveltejs/kit";
2
2
  //#region src/adapter/index.d.ts
3
+ /** Options for {@link effectAdapter}. */
3
4
  interface EffectAdapterOptions {
4
5
  /**
5
6
  * The directory to write the production build to.
@@ -1,4 +1,4 @@
1
- import { writeFileSync } from "node:fs";
1
+ import { mkdirSync, rmSync, writeFileSync } from "node:fs";
2
2
  //#region src/adapter/index.ts
3
3
  /**
4
4
  * Effect deployment adapter for SvelteKit.
@@ -10,14 +10,14 @@ import { writeFileSync } from "node:fs";
10
10
  * shutdown that runs all finalizers).
11
11
  *
12
12
  * ```js
13
- * // svelte.config.js
13
+ * // vite.config.ts
14
+ * import { sveltekit } from "@sveltejs/kit/vite";
14
15
  * import adapter from "@thomasfosterau/effect-sveltekit/adapter";
16
+ * import { defineConfig } from "vite";
15
17
  *
16
- * const config = {
17
- * kit: { adapter: adapter() },
18
- * };
19
- *
20
- * export default config;
18
+ * export default defineConfig({
19
+ * plugins: [sveltekit({ adapter: adapter() })],
20
+ * });
21
21
  * ```
22
22
  *
23
23
  * The build output (`build/` by default) contains:
@@ -25,7 +25,9 @@ import { writeFileSync } from "node:fs";
25
25
  * - `index.js` — runs the production server: `node build`
26
26
  * - `handler.js` — exports the SvelteKit app as a composable Effect HTTP
27
27
  * handler, for mounting inside an existing `effect/http` server
28
- * - `client/`, `server/`, `prerendered/`, `manifest.js` — the built app
28
+ * - `client/`, `server/`, `prerendered/`, `server.js` (the SvelteKit
29
+ * `server` instance), `manifest.js` (prerendered paths, base and app path) —
30
+ * the built app
29
31
  *
30
32
  * Unlike `adapter-node`, the server output is not bundled: the deployment
31
33
  * needs `node_modules` with the app's production dependencies installed
@@ -39,8 +41,8 @@ import { dirname } from "node:path";
39
41
  import { fileURLToPath } from "node:url";
40
42
  import process from "node:process";
41
43
  import { makeHandler } from "${PACKAGE}/adapter/handler";
42
- import { Server } from "./server/index.js";
43
- import { manifest, prerendered, base } from "./manifest.js";
44
+ import { server } from "./server.js";
45
+ import { prerendered, base, appPath } from "./manifest.js";
44
46
 
45
47
  const dir = dirname(fileURLToPath(import.meta.url));
46
48
 
@@ -51,8 +53,8 @@ const dir = dirname(fileURLToPath(import.meta.url));
51
53
  * \`effect/http\` HTTP server.
52
54
  */
53
55
  export const handler = makeHandler({
54
- Server,
55
- manifest,
56
+ server,
57
+ appPath,
56
58
  prerendered,
57
59
  base,
58
60
  dir,
@@ -77,8 +79,7 @@ serve(handler, { envPrefix: ${JSON.stringify(envPrefix)} });
77
79
  const fetchEntryTemplate = (envPrefix) => `\
78
80
  import { Layer } from "effect";
79
81
  import { makeHandlerWith, AssetSource, toWebHandler } from "${PACKAGE}/adapter/handler";
80
- import { Server } from "./server/index.js";
81
- import { manifest } from "./manifest.js";
82
+ import { server } from "./server.js";
82
83
 
83
84
  let fetchHandler;
84
85
 
@@ -87,8 +88,7 @@ export default {
87
88
  fetch(request, env, ctx) {
88
89
  fetchHandler ??= toWebHandler(
89
90
  makeHandlerWith({
90
- Server,
91
- manifest,
91
+ server,
92
92
  env,
93
93
  envPrefix: ${JSON.stringify(envPrefix)},
94
94
  // Static assets come from the Workers ASSETS binding (configure it to
@@ -113,9 +113,12 @@ function effectAdapter(options = {}) {
113
113
  return {
114
114
  name: `${PACKAGE}/adapter`,
115
115
  async adapt(builder) {
116
- const base = builder.config.kit.paths.base;
117
- builder.rimraf(out);
118
- builder.mkdirp(out);
116
+ const base = builder.config.paths.base;
117
+ rmSync(out, {
118
+ recursive: true,
119
+ force: true
120
+ });
121
+ mkdirSync(out, { recursive: true });
119
122
  builder.log.minor("Copying assets");
120
123
  builder.writeClient(`${out}/client${base}`);
121
124
  builder.writePrerendered(`${out}/prerendered${base}`);
@@ -125,10 +128,11 @@ function effectAdapter(options = {}) {
125
128
  }
126
129
  builder.log.minor("Building server");
127
130
  builder.writeServer(`${out}/server`);
131
+ builder.generateServerInstance(`${out}/server.js`, { serverDirectory: `${out}/server` });
128
132
  writeFileSync(`${out}/manifest.js`, [
129
- `export const manifest = ${builder.generateManifest({ relativePath: "./server" })};`,
130
133
  `export const prerendered = new Set(${JSON.stringify(builder.prerendered.paths)});`,
131
- `export const base = ${JSON.stringify(base)};`
134
+ `export const base = ${JSON.stringify(base)};`,
135
+ `export const appPath = ${JSON.stringify(builder.getAppPath())};`
132
136
  ].join("\n\n"));
133
137
  builder.log.minor("Writing server entry");
134
138
  writeFileSync(`${out}/handler.js`, handlerTemplate(envPrefix));