@thomasfosterau/effect-sveltekit 0.4.1 → 0.6.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 (66) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +183 -85
  3. package/dist/Hooks.d.ts +1 -1
  4. package/dist/Hooks.js.map +1 -1
  5. package/dist/Navigation.d.ts +83 -19
  6. package/dist/Navigation.js +93 -20
  7. package/dist/Navigation.js.map +1 -1
  8. package/dist/Remote.d.ts +37 -19
  9. package/dist/Remote.js +20 -7
  10. package/dist/Remote.js.map +1 -1
  11. package/dist/State.d.ts +77 -8
  12. package/dist/State.js +116 -27
  13. package/dist/State.js.map +1 -1
  14. package/dist/adapter/handler.d.ts +14 -12
  15. package/dist/adapter/handler.js +5 -7
  16. package/dist/adapter/handler.js.map +1 -1
  17. package/dist/adapter/index.js +25 -21
  18. package/dist/adapter/index.js.map +1 -1
  19. package/dist/api-client.js +1 -1
  20. package/dist/api-client.js.map +1 -1
  21. package/dist/app-runtime.d.ts +7 -6
  22. package/dist/app-runtime.js +5 -5
  23. package/dist/app-runtime.js.map +1 -1
  24. package/dist/client/Hooks.d.ts +1 -1
  25. package/dist/client/Hooks.js.map +1 -1
  26. package/dist/errors.js +3 -2
  27. package/dist/errors.js.map +1 -1
  28. package/dist/forms.d.ts +72 -9
  29. package/dist/forms.js +66 -5
  30. package/dist/forms.js.map +1 -1
  31. package/dist/internal/app-state.d.ts +38 -3
  32. package/dist/internal/app-state.js +58 -15
  33. package/dist/internal/app-state.js.map +1 -1
  34. package/dist/internal/auto.d.ts +2 -1
  35. package/dist/internal/auto.js.map +1 -1
  36. package/dist/internal/enhance.d.ts +107 -9
  37. package/dist/internal/enhance.js +30 -6
  38. package/dist/internal/enhance.js.map +1 -1
  39. package/dist/internal/error.js +23 -2
  40. package/dist/internal/error.js.map +1 -1
  41. package/dist/internal/remote-run.d.ts +3 -3
  42. package/dist/internal/remote-run.js.map +1 -1
  43. package/dist/internal/watch.svelte.js +33 -0
  44. package/dist/internal/watch.svelte.js.map +1 -0
  45. package/dist/kit.js +3 -3
  46. package/dist/kit.js.map +1 -1
  47. package/dist/realtime.d.ts +28 -7
  48. package/dist/realtime.js +68 -43
  49. package/dist/realtime.js.map +1 -1
  50. package/dist/remote-functions.d.ts +4 -4
  51. package/dist/remote-functions.js.map +1 -1
  52. package/dist/remote-reactive.d.ts +1 -1
  53. package/dist/remote-reactive.js.map +1 -1
  54. package/dist/response-headers.d.ts +1 -1
  55. package/dist/response-headers.js.map +1 -1
  56. package/dist/server/Endpoint.d.ts +2 -2
  57. package/dist/server/Endpoint.js +2 -2
  58. package/dist/server/Endpoint.js.map +1 -1
  59. package/dist/server/Hooks.d.ts +1 -1
  60. package/dist/server/Hooks.js.map +1 -1
  61. package/dist/transport.d.ts +1 -1
  62. package/dist/transport.js.map +1 -1
  63. package/dist/vite.d.ts +2 -2
  64. package/dist/vite.js.map +1 -1
  65. package/package.json +10 -8
  66. package/LICENSE +0 -21
@@ -1,6 +1,6 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
2
  import { onNavigateWith, registeredStream } from "./internal/navigation-events.js";
3
- import { Effect } from "effect";
3
+ import { Data, Effect } from "effect";
4
4
  import { afterNavigate, beforeNavigate, goto, invalidate, invalidateAll, onNavigate, preloadCode, preloadData, refreshAll } from "$app/navigation";
5
5
  //#region src/Navigation.ts
6
6
  /**
@@ -11,8 +11,12 @@ import { afterNavigate, beforeNavigate, goto, invalidate, invalidateAll, onNavig
11
11
  * `Effect`, so navigation composes inside Effect pipelines (sequencing,
12
12
  * retries, `Effect.race`, tracing spans, ...). Alongside them sit the
13
13
  * client-side lifecycle callbacks (`beforeNavigate`, `afterNavigate`,
14
- * `onNavigate`) bridged to Effect. These run on the client only — calling them
15
- * during SSR throws, exactly as the underlying `$app/navigation` functions do.
14
+ * `onNavigate`) bridged to Effect. These run on the client only.
15
+ *
16
+ * When SvelteKit rejects (for example, `goto` to a URL outside the app) or
17
+ * throws (for example, any of them run during server rendering), the wrapper
18
+ * fails with a {@link NavigationError} that names the operation and carries
19
+ * SvelteKit's original reason as its `cause`.
16
20
  *
17
21
  * @example
18
22
  * ```svelte
@@ -26,7 +30,7 @@ import { afterNavigate, beforeNavigate, goto, invalidate, invalidateAll, onNavig
26
30
  * runtime.runPromise(
27
31
  * Effect.gen(function* () {
28
32
  * yield* doSave();
29
- * yield* Navigation.invalidateAll();
33
+ * yield* Navigation.refreshAll();
30
34
  * yield* Navigation.goto('/done');
31
35
  * }),
32
36
  * );
@@ -34,6 +38,7 @@ import { afterNavigate, beforeNavigate, goto, invalidate, invalidateAll, onNavig
34
38
  * ```
35
39
  */
36
40
  var Navigation_exports = /* @__PURE__ */ __exportAll({
41
+ NavigationError: () => NavigationError,
37
42
  afterNavigate: () => afterNavigate$1,
38
43
  beforeNavigate: () => beforeNavigate$1,
39
44
  goto: () => goto$1,
@@ -44,18 +49,86 @@ var Navigation_exports = /* @__PURE__ */ __exportAll({
44
49
  preloadData: () => preloadData$1,
45
50
  refreshAll: () => refreshAll$1
46
51
  });
47
- /** Navigate to `url`. Wraps `$app/navigation`'s `goto`. */
48
- const goto$1 = (...args) => Effect.promise(() => goto(...args));
49
- /** Re-run `load` functions that depend on `resource`. Wraps `invalidate`. */
50
- const invalidate$1 = (...args) => Effect.promise(() => invalidate(...args));
51
- /** Re-run every `load` function for the active page. Wraps `invalidateAll`. */
52
- const invalidateAll$1 = () => Effect.promise(() => invalidateAll());
53
- /** Refresh active remote functions (and, by default, `load`s). Wraps `refreshAll`. */
54
- const refreshAll$1 = (...args) => Effect.promise(() => refreshAll(...args));
55
- /** Preload the data for `href`. Wraps `preloadData`. */
56
- 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));
52
+ /**
53
+ * A `$app/navigation` promise wrapper ({@link goto}, {@link invalidate},
54
+ * {@link invalidateAll}, {@link refreshAll}, {@link preloadData},
55
+ * {@link preloadCode}) rejected or threw. `operation` names the wrapper and
56
+ * `cause` is SvelteKit's original reason, unchanged.
57
+ *
58
+ * SvelteKit 3 rejects `goto` with a URL outside the app (external, or matching
59
+ * no route) and `preloadData` with a URL outside the app; `invalidate` throws on
60
+ * a `resource` that cannot be parsed even relative to the current URL;
61
+ * `preloadCode` rejects when a route's code fails to load; a navigation (including one that follows a `load` redirect during
62
+ * `invalidate` / `refreshAll`) rejects when a `beforeNavigate` / `onNavigate`
63
+ * callback throws; and every one of them throws when called during server
64
+ * rendering. Recover with `Effect.catchTag("NavigationError", ...)`.
65
+ */
66
+ var NavigationError = class extends Data.TaggedError("NavigationError") {};
67
+ /**
68
+ * Runs a `$app/navigation` call as an Effect, so a rejection, or a synchronous
69
+ * throw, fails with a {@link NavigationError} instead of becoming a defect.
70
+ */
71
+ const fromNavigation = (operation, thunk) => Effect.tryPromise({
72
+ try: () => thunk(),
73
+ catch: (cause) => new NavigationError({
74
+ operation,
75
+ cause
76
+ })
77
+ });
78
+ /**
79
+ * Navigate to `url`. Wraps `$app/navigation`'s `goto`.
80
+ *
81
+ * Fails with a {@link NavigationError} if SvelteKit rejects: a URL outside the
82
+ * app (external, or not matching a route) rejects, as does a navigation whose
83
+ * `beforeNavigate` / `onNavigate` callback throws, or a call during server
84
+ * rendering. For an external URL, set `window.location` instead.
85
+ */
86
+ const goto$1 = (...args) => fromNavigation("goto", () => goto(...args));
87
+ /**
88
+ * Re-run `load` functions that depend on `resource`. Wraps `invalidate`.
89
+ *
90
+ * Fails with a {@link NavigationError} if SvelteKit rejects or throws: a
91
+ * `resource` string that cannot be parsed even relative to the current URL
92
+ * throws, as does a call during server rendering, and the navigation that
93
+ * follows a `load` redirect can reject.
94
+ */
95
+ const invalidate$1 = (...args) => fromNavigation("invalidate", () => invalidate(...args));
96
+ /**
97
+ * Re-run every `load` function for the active page. Wraps `invalidateAll`.
98
+ *
99
+ * Fails with a {@link NavigationError} if SvelteKit rejects or throws: for
100
+ * example, when the navigation that follows a `load` redirect fails, or when
101
+ * called during server rendering.
102
+ *
103
+ * @deprecated SvelteKit 3 deprecates `invalidateAll`; use {@link refreshAll},
104
+ * which also refreshes active remote functions and keeps `page.state`.
105
+ */
106
+ const invalidateAll$1 = () => fromNavigation("invalidateAll", () => invalidateAll());
107
+ /**
108
+ * Refresh active remote functions (and, by default, `load`s). Wraps `refreshAll`.
109
+ *
110
+ * Fails with a {@link NavigationError} if SvelteKit rejects or throws: for
111
+ * example, when the navigation that follows a `load` redirect fails, or when
112
+ * called during server rendering.
113
+ */
114
+ const refreshAll$1 = (...args) => fromNavigation("refreshAll", () => refreshAll(...args));
115
+ /**
116
+ * Preload the data for `href`. Wraps `preloadData`, succeeding with SvelteKit's
117
+ * result (`loaded`, `redirect`, or `error` when a `load` fails).
118
+ *
119
+ * Fails with a {@link NavigationError} if SvelteKit rejects: an `href` outside
120
+ * the app rejects, as does a call during server rendering.
121
+ */
122
+ const preloadData$1 = (href) => fromNavigation("preloadData", () => preloadData(href));
123
+ /**
124
+ * Preload the code for the route `id` (e.g. `/blog/[slug]`, without
125
+ * `paths.base`). Wraps `preloadCode`.
126
+ *
127
+ * Fails with a {@link NavigationError} if SvelteKit rejects: a route module
128
+ * that fails to load rejects, as does a call during server rendering (and, in
129
+ * development, an `id` not starting with `/`).
130
+ */
131
+ const preloadCode$1 = (...args) => fromNavigation("preloadCode", () => preloadCode(...args));
59
132
  /**
60
133
  * Registers a `beforeNavigate` callback and exposes every navigation about to
61
134
  * happen as an Effect `Stream`. Call during component initialization.
@@ -63,9 +136,9 @@ const preloadCode$1 = (pathname) => Effect.promise(() => preloadCode(pathname));
63
136
  * Unlike the promise-returning navigation functions above, this is a
64
137
  * **callback-registration** function: it must be called *synchronously during
65
138
  * component initialization* (SvelteKit wires it to the component's lifecycle).
66
- * It registers its callback eagerly and feeds an internal `Queue`, returning a
67
- * `Stream` backed by that queue — the same push-based bridge as `SignalEmitter`
68
- * in `@thomasfosterau/effect-svelte`. Call it at the top level of `<script>`,
139
+ * It registers its callback eagerly and feeds an internal unbounded `Queue`,
140
+ * returning a `Stream` backed by that queue: a push-based bridge that buffers
141
+ * every event for its single consumer. Call it at the top level of `<script>`,
69
142
  * exactly where you'd call the bare `beforeNavigate`.
70
143
  *
71
144
  * @example
@@ -150,6 +223,6 @@ function onNavigate$1(fn, runEffect = Effect.runPromise) {
150
223
  onNavigateWith(onNavigate, fn, runEffect);
151
224
  }
152
225
  //#endregion
153
- export { Navigation_exports, afterNavigate$1 as afterNavigate, beforeNavigate$1 as beforeNavigate, goto$1 as goto, invalidate$1 as invalidate, invalidateAll$1 as invalidateAll, onNavigate$1 as onNavigate, preloadCode$1 as preloadCode, preloadData$1 as preloadData, refreshAll$1 as refreshAll };
226
+ export { NavigationError, Navigation_exports, afterNavigate$1 as afterNavigate, beforeNavigate$1 as beforeNavigate, goto$1 as goto, invalidate$1 as invalidate, invalidateAll$1 as invalidateAll, onNavigate$1 as onNavigate, preloadCode$1 as preloadCode, preloadData$1 as preloadData, refreshAll$1 as refreshAll };
154
227
 
155
228
  //# sourceMappingURL=Navigation.js.map
@@ -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.\n *\n * When SvelteKit rejects (for example, `goto` to a URL outside the app) or\n * throws (for example, any of them run during server rendering), the wrapper\n * fails with a {@link NavigationError} that names the operation and carries\n * SvelteKit's original reason as its `cause`.\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 { Data, Effect } from \"effect\";\nimport type { Stream } from \"effect\";\nimport { onNavigateWith, registeredStream } from \"./internal/navigation-events.js\";\n\n/**\n * A `$app/navigation` promise wrapper ({@link goto}, {@link invalidate},\n * {@link invalidateAll}, {@link refreshAll}, {@link preloadData},\n * {@link preloadCode}) rejected or threw. `operation` names the wrapper and\n * `cause` is SvelteKit's original reason, unchanged.\n *\n * SvelteKit 3 rejects `goto` with a URL outside the app (external, or matching\n * no route) and `preloadData` with a URL outside the app; `invalidate` throws on\n * a `resource` that cannot be parsed even relative to the current URL;\n * `preloadCode` rejects when a route's code fails to load; a navigation (including one that follows a `load` redirect during\n * `invalidate` / `refreshAll`) rejects when a `beforeNavigate` / `onNavigate`\n * callback throws; and every one of them throws when called during server\n * rendering. Recover with `Effect.catchTag(\"NavigationError\", ...)`.\n */\nexport class NavigationError extends Data.TaggedError(\"NavigationError\")<{\n /** The wrapper whose SvelteKit call failed. */\n readonly operation:\n | \"goto\"\n | \"invalidate\"\n | \"invalidateAll\"\n | \"refreshAll\"\n | \"preloadData\"\n | \"preloadCode\";\n /** The rejection reason, or the value thrown, as SvelteKit produced it. */\n readonly cause: unknown;\n}> {}\n\n/**\n * Runs a `$app/navigation` call as an Effect, so a rejection, or a synchronous\n * throw, fails with a {@link NavigationError} instead of becoming a defect.\n */\nconst fromNavigation = <A>(\n operation: NavigationError[\"operation\"],\n thunk: () => Promise<A>,\n): Effect.Effect<A, NavigationError> =>\n Effect.tryPromise({\n try: () => thunk(),\n catch: (cause) => new NavigationError({ operation, cause }),\n });\n\n/**\n * Navigate to `url`. Wraps `$app/navigation`'s `goto`.\n *\n * Fails with a {@link NavigationError} if SvelteKit rejects: a URL outside the\n * app (external, or not matching a route) rejects, as does a navigation whose\n * `beforeNavigate` / `onNavigate` callback throws, or a call during server\n * rendering. For an external URL, set `window.location` instead.\n */\nexport const goto = (...args: Parameters<typeof kitGoto>): Effect.Effect<void, NavigationError> =>\n fromNavigation(\"goto\", () => kitGoto(...args));\n\n/**\n * Re-run `load` functions that depend on `resource`. Wraps `invalidate`.\n *\n * Fails with a {@link NavigationError} if SvelteKit rejects or throws: a\n * `resource` string that cannot be parsed even relative to the current URL\n * throws, as does a call during server rendering, and the navigation that\n * follows a `load` redirect can reject.\n */\nexport const invalidate = (\n ...args: Parameters<typeof kitInvalidate>\n): Effect.Effect<void, NavigationError> =>\n fromNavigation(\"invalidate\", () => kitInvalidate(...args));\n\n/**\n * Re-run every `load` function for the active page. Wraps `invalidateAll`.\n *\n * Fails with a {@link NavigationError} if SvelteKit rejects or throws: for\n * example, when the navigation that follows a `load` redirect fails, or when\n * called during server rendering.\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, NavigationError> =>\n fromNavigation(\"invalidateAll\", () => kitInvalidateAll());\n\n/**\n * Refresh active remote functions (and, by default, `load`s). Wraps `refreshAll`.\n *\n * Fails with a {@link NavigationError} if SvelteKit rejects or throws: for\n * example, when the navigation that follows a `load` redirect fails, or when\n * called during server rendering.\n */\nexport const refreshAll = (\n ...args: Parameters<typeof kitRefreshAll>\n): Effect.Effect<void, NavigationError> =>\n fromNavigation(\"refreshAll\", () => kitRefreshAll(...args));\n\n/**\n * Preload the data for `href`. Wraps `preloadData`, succeeding with SvelteKit's\n * result (`loaded`, `redirect`, or `error` when a `load` fails).\n *\n * Fails with a {@link NavigationError} if SvelteKit rejects: an `href` outside\n * the app rejects, as does a call during server rendering.\n */\nexport const preloadData = (\n href: string,\n): Effect.Effect<Awaited<ReturnType<typeof kitPreloadData>>, NavigationError> =>\n fromNavigation(\"preloadData\", () => kitPreloadData(href));\n\n/**\n * Preload the code for the route `id` (e.g. `/blog/[slug]`, without\n * `paths.base`). Wraps `preloadCode`.\n *\n * Fails with a {@link NavigationError} if SvelteKit rejects: a route module\n * that fails to load rejects, as does a call during server rendering (and, in\n * development, an `id` not starting with `/`).\n */\nexport const preloadCode = (\n ...args: Parameters<typeof kitPreloadCode>\n): Effect.Effect<void, NavigationError> =>\n fromNavigation(\"preloadCode\", () => 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 unbounded `Queue`,\n * returning a `Stream` backed by that queue: a push-based bridge that buffers\n * every event for its single consumer. 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiEA,IAAa,kBAAb,cAAqC,KAAK,YAAY,iBAAiB,CAAC,CAWrE,CAAC;;;;;AAMJ,MAAM,kBACJ,WACA,UAEA,OAAO,WAAW;CAChB,WAAW,MAAM;CACjB,QAAQ,UAAU,IAAI,gBAAgB;EAAE;EAAW;CAAM,CAAC;AAC5D,CAAC;;;;;;;;;AAUH,MAAaA,UAAQ,GAAG,SACtB,eAAe,cAAcC,KAAQ,GAAG,IAAI,CAAC;;;;;;;;;AAU/C,MAAaC,gBACX,GAAG,SAEH,eAAe,oBAAoBC,WAAc,GAAG,IAAI,CAAC;;;;;;;;;;;AAY3D,MAAaC,wBACX,eAAe,uBAAuBC,cAAiB,CAAC;;;;;;;;AAS1D,MAAaC,gBACX,GAAG,SAEH,eAAe,oBAAoBC,WAAc,GAAG,IAAI,CAAC;;;;;;;;AAS3D,MAAaC,iBACX,SAEA,eAAe,qBAAqBC,YAAe,IAAI,CAAC;;;;;;;;;AAU1D,MAAaC,iBACX,GAAG,SAEH,eAAe,qBAAqBC,YAAe,GAAG,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgC7D,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,37 +1,45 @@
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
6
  /**
7
7
  * Calls a SvelteKit remote `query` as an Effect that succeeds with its output.
8
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.
9
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
10
+ * through unchanged. On the client, a server-side `error()` arrives as
11
+ * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of
12
+ * failing.
11
13
  */
12
14
  declare function callQuery<Output>(query: RemoteQueryFunction<void, Output>): Effect.Effect<Output, unknown, never>;
13
15
  /**
14
16
  * Calls a SvelteKit remote `query` with `input` as an Effect that succeeds
15
17
  * with its output.
16
18
  *
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
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
20
+ * through unchanged. On the client, a server-side `error()` arrives as
21
+ * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of
22
+ * failing.
19
23
  */
20
24
  declare function callQuery<Input, Output>(query: RemoteQueryFunction<Input, Output>, input: Input): Effect.Effect<Output, unknown, never>;
21
25
  /**
22
26
  * Calls a SvelteKit remote `command` as an Effect that succeeds with its
23
27
  * output.
24
28
  *
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.
29
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
30
+ * through unchanged. On the client, a server-side `error()` arrives as
31
+ * SvelteKit's `HttpError`; commands may not `redirect()`, and SvelteKit
32
+ * rejects one with an `Error`.
27
33
  */
28
34
  declare function callCommand<Output>(command: RemoteCommand<void, Output>): Effect.Effect<Output, unknown, never>;
29
35
  /**
30
36
  * Calls a SvelteKit remote `command` with `input` as an Effect that succeeds
31
37
  * with its output.
32
38
  *
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.
39
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
40
+ * through unchanged. On the client, a server-side `error()` arrives as
41
+ * SvelteKit's `HttpError`; commands may not `redirect()`, and SvelteKit
42
+ * rejects one with an `Error`.
35
43
  */
36
44
  declare function callCommand<Input, Output>(command: RemoteCommand<Input, Output>, input: Input): Effect.Effect<Output, unknown, never>;
37
45
  /**
@@ -42,24 +50,30 @@ declare function callCommand<Input, Output>(command: RemoteCommand<Input, Output
42
50
  * changes data those queries depend on must list them here (or call
43
51
  * `query.refresh()` afterwards) for their cached values to update.
44
52
  *
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.
53
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
54
+ * through unchanged. On the client, a server-side `error()` arrives as
55
+ * SvelteKit's `HttpError`; commands may not `redirect()`, and SvelteKit
56
+ * rejects one with an `Error`.
47
57
  */
48
58
  declare function callCommandWithUpdates<Input, Output>(command: RemoteCommand<Input, Output>, input: Input, ...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Effect.Effect<Output, unknown, never>;
49
59
  /**
50
60
  * Calls a SvelteKit remote `prerender` function as an Effect that succeeds
51
61
  * with its output.
52
62
  *
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.
63
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
64
+ * through unchanged. On the client, a server-side `error()` arrives as
65
+ * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of
66
+ * failing.
55
67
  */
56
68
  declare function callPrerender<Output>(prerender: RemotePrerenderFunction<void, Output>): Effect.Effect<Output, unknown, never>;
57
69
  /**
58
70
  * Calls a SvelteKit remote `prerender` function with `input` as an Effect
59
71
  * that succeeds with its output.
60
72
  *
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.
73
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
74
+ * through unchanged. On the client, a server-side `error()` arrives as
75
+ * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of
76
+ * failing.
63
77
  */
64
78
  declare function callPrerender<Input, Output>(prerender: RemotePrerenderFunction<Input, Output>, input: Input): Effect.Effect<Output, unknown, never>;
65
79
  /**
@@ -73,16 +87,20 @@ type RemoteSubmit = () => PromiseLike<unknown> & {
73
87
  /**
74
88
  * Runs an enhanced remote form's `submit()` as an Effect.
75
89
  *
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.
90
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
91
+ * through unchanged. On the client, a server-side `error()` arrives as
92
+ * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of
93
+ * failing.
78
94
  */
79
95
  declare function submitForm(submit: () => PromiseLike<unknown>): Effect.Effect<void, unknown, never>;
80
96
  /**
81
97
  * Runs an enhanced remote form's `submit()` and refreshes the given queries in
82
98
  * the same round trip (SvelteKit's single-flight mutations).
83
99
  *
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.
100
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
101
+ * through unchanged. On the client, a server-side `error()` arrives as
102
+ * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of
103
+ * failing.
86
104
  */
87
105
  declare function submitFormWithUpdates(submit: RemoteSubmit, ...queries: Array<RemoteQuery<any> | RemoteQueryOverride>): Effect.Effect<void, unknown, never>;
88
106
  /**
package/dist/Remote.js CHANGED
@@ -10,8 +10,15 @@ var Remote_exports = /* @__PURE__ */ __exportAll({
10
10
  submitForm: () => submitForm,
11
11
  submitFormWithUpdates: () => submitFormWithUpdates
12
12
  });
13
+ /**
14
+ * Wraps a remote call so a rejection, or a synchronous throw from `thunk`,
15
+ * fails the Effect with the original reason instead of becoming a defect.
16
+ */
13
17
  function fromRemotePromise(thunk) {
14
- return Effect.promise(() => Promise.resolve(thunk()));
18
+ return Effect.tryPromise({
19
+ try: () => Promise.resolve(thunk()),
20
+ catch: (error) => error
21
+ });
15
22
  }
16
23
  function callQuery(query, input) {
17
24
  if (arguments.length === 1) return fromRemotePromise(() => query(void 0));
@@ -29,8 +36,10 @@ function callCommand(command, input) {
29
36
  * changes data those queries depend on must list them here (or call
30
37
  * `query.refresh()` afterwards) for their cached values to update.
31
38
  *
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.
39
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
40
+ * through unchanged. On the client, a server-side `error()` arrives as
41
+ * SvelteKit's `HttpError`; commands may not `redirect()`, and SvelteKit
42
+ * rejects one with an `Error`.
34
43
  */
35
44
  function callCommandWithUpdates(command, input, ...queries) {
36
45
  return fromRemotePromise(() => command(input).updates(...queries));
@@ -42,8 +51,10 @@ function callPrerender(prerender, input) {
42
51
  /**
43
52
  * Runs an enhanced remote form's `submit()` as an Effect.
44
53
  *
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.
54
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
55
+ * through unchanged. On the client, a server-side `error()` arrives as
56
+ * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of
57
+ * failing.
47
58
  */
48
59
  function submitForm(submit) {
49
60
  return Effect.asVoid(fromRemotePromise(() => submit()));
@@ -52,8 +63,10 @@ function submitForm(submit) {
52
63
  * Runs an enhanced remote form's `submit()` and refreshes the given queries in
53
64
  * the same round trip (SvelteKit's single-flight mutations).
54
65
  *
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.
66
+ * Fails with the remote call's rejection reason, typed `unknown` and passed
67
+ * through unchanged. On the client, a server-side `error()` arrives as
68
+ * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of
69
+ * failing.
57
70
  */
58
71
  function submitFormWithUpdates(submit, ...queries) {
59
72
  return Effect.asVoid(fromRemotePromise(() => submit().updates(...queries)));
@@ -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\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"}
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\n/**\n * Wraps a remote call so a rejection, or a synchronous throw from `thunk`,\n * fails the Effect with the original reason instead of becoming a defect.\n */\nfunction fromRemotePromise<A>(thunk: () => PromiseLike<A>): Effect.Effect<A, unknown, never> {\n return Effect.tryPromise({\n try: () => Promise.resolve(thunk()),\n catch: (error) => error,\n });\n}\n\n/**\n * Calls a SvelteKit remote `query` as an Effect that succeeds with its output.\n *\n * Fails with the remote call's rejection reason, typed `unknown` and passed\n * through unchanged. On the client, a server-side `error()` arrives as\n * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of\n * failing.\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 * Fails with the remote call's rejection reason, typed `unknown` and passed\n * through unchanged. On the client, a server-side `error()` arrives as\n * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of\n * failing.\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 * Fails with the remote call's rejection reason, typed `unknown` and passed\n * through unchanged. On the client, a server-side `error()` arrives as\n * SvelteKit's `HttpError`; commands may not `redirect()`, and SvelteKit\n * rejects one with an `Error`.\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 * Fails with the remote call's rejection reason, typed `unknown` and passed\n * through unchanged. On the client, a server-side `error()` arrives as\n * SvelteKit's `HttpError`; commands may not `redirect()`, and SvelteKit\n * rejects one with an `Error`.\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 * Fails with the remote call's rejection reason, typed `unknown` and passed\n * through unchanged. On the client, a server-side `error()` arrives as\n * SvelteKit's `HttpError`; commands may not `redirect()`, and SvelteKit\n * rejects one with an `Error`.\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 * Fails with the remote call's rejection reason, typed `unknown` and passed\n * through unchanged. On the client, a server-side `error()` arrives as\n * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of\n * failing.\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 * Fails with the remote call's rejection reason, typed `unknown` and passed\n * through unchanged. On the client, a server-side `error()` arrives as\n * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of\n * failing.\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 * Fails with the remote call's rejection reason, typed `unknown` and passed\n * through unchanged. On the client, a server-side `error()` arrives as\n * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of\n * failing.\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 * Fails with the remote call's rejection reason, typed `unknown` and passed\n * through unchanged. On the client, a server-side `error()` arrives as\n * SvelteKit's `HttpError`; a server-side `redirect()` navigates instead of\n * failing.\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":";;;;;;;;;;;;;;;;AAcA,SAAS,kBAAqB,OAA+D;CAC3F,OAAO,OAAO,WAAW;EACvB,WAAW,QAAQ,QAAQ,MAAM,CAAC;EAClC,QAAQ,UAAU;CACpB,CAAC;AACH;AA0BA,SAAgB,UACd,OACA,OACuC;CACvC,IAAI,UAAU,WAAW,GACvB,OAAO,wBACJ,MAAuD,KAAA,CAAS,CACnE;CAGF,OAAO,wBAAwB,MAAM,KAAc,CAAC;AACtD;AA2BA,SAAgB,YACd,SACA,OACuC;CACvC,IAAI,UAAU,WAAW,GACvB,OAAO,wBAAyB,QAAmD,KAAA,CAAS,CAAC;CAG/F,OAAO,wBAAwB,QAAQ,KAAc,CAAC;AACxD;;;;;;;;;;;;;;AAeA,SAAgB,uBACd,SACA,OACA,GAAG,SACoC;CACvC,OAAO,wBAAwB,QAAQ,KAAK,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC;AACnE;AA2BA,SAAgB,cACd,WACA,OACuC;CACvC,IAAI,UAAU,WAAW,GACvB,OAAO,wBACJ,UAA+D,KAAA,CAAS,CAC3E;CAGF,OAAO,wBAAwB,UAAU,KAAc,CAAC;AAC1D;;;;;;;;;AAmBA,SAAgB,WACd,QACqC;CACrC,OAAO,OAAO,OAAO,wBAAwB,OAAO,CAAC,CAAC;AACxD;;;;;;;;;;AAWA,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,84 @@
1
- import { PageSnapshot } from "./internal/app-state.js";
2
- import { Stream } from "effect";
3
- import { Page } from "@sveltejs/kit";
1
+ import { CurrentPageShape, NavigatingSnapshot, PageSnapshot, UpdateCheckError } from "./internal/app-state.js";
2
+ import { Context, Effect, Layer, Option, Stream } from "effect";
3
+ import { Page } from "$app/state";
4
4
  declare namespace State_d_exports {
5
- export { PageSnapshot, page };
5
+ export { CurrentPage, CurrentPageInterface, NavigatingSnapshot, PageSnapshot, UpdateCheckError, checkForUpdate, navigating$1 as navigating, page$1 as page, updated$1 as updated };
6
6
  }
7
7
  /**
8
8
  * A `Stream` of the current SvelteKit `page`, emitting a shallow snapshot
9
- * immediately and again after every navigation. Call during component
10
- * initialization.
9
+ * immediately and again after every navigation; never fails. Call during
10
+ * component initialization. It follows `afterNavigate`, so page changes
11
+ * without a navigation (shallow routing, form results) don't emit — use
12
+ * {@link CurrentPage}'s `changes` for those.
11
13
  */
12
- declare function page(): Stream.Stream<PageSnapshot<Page>>;
14
+ declare function page$1(): Stream.Stream<PageSnapshot<Page>>;
15
+ /**
16
+ * A `Stream` of SvelteKit's in-flight navigation: `Option.some` with a
17
+ * {@link NavigatingSnapshot} while a navigation is in progress, `Option.none()`
18
+ * when idle. Emits the current state on the next Svelte flush, then on every
19
+ * change; never fails. Client-only, but callable anywhere (not only during
20
+ * component initialization).
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * const spinner = Stream.runForEach(State.navigating(), (nav) =>
25
+ * Effect.sync(() => (busy = Option.isSome(nav))),
26
+ * );
27
+ * ```
28
+ */
29
+ declare function navigating$1(): Stream.Stream<Option.Option<NavigatingSnapshot>>;
30
+ /**
31
+ * A `Stream` of SvelteKit's `updated.current`: whether a new version of the app
32
+ * has been deployed since this one loaded. Emits the current value on the next
33
+ * Svelte flush, then on every change (SvelteKit only ever flips it from `false`
34
+ * to `true`); never fails. Client-only, but callable anywhere.
35
+ */
36
+ declare function updated$1(): Stream.Stream<boolean>;
37
+ /**
38
+ * Asks SvelteKit to check for a new app version now (`updated.check()`),
39
+ * succeeding with whether one is available; a positive result also flips
40
+ * {@link updated}. Always succeeds with `false` in development. Fails with
41
+ * {@link UpdateCheckError} if the check rejects. Client-only.
42
+ */
43
+ declare function checkForUpdate(): Effect.Effect<boolean, UpdateCheckError>;
44
+ /**
45
+ * The service shape of {@link CurrentPage}: `get` snapshots the current page
46
+ * and `changes` streams it. Neither fails on the client; see
47
+ * {@link CurrentPage} for the server.
48
+ */
49
+ interface CurrentPageInterface extends CurrentPageShape<Page> {}
50
+ declare const CurrentPage_base: Context.ServiceClass<CurrentPage, "@thomasfosterau/effect-sveltekit/CurrentPage", CurrentPageInterface>;
51
+ /**
52
+ * The current SvelteKit page as an Effect service, so any client Effect can read
53
+ * it with `yield* State.CurrentPage` instead of taking it as an argument.
54
+ * `get` snapshots the page when run; `changes` emits the current page on the
55
+ * next Svelte flush, then a fresh snapshot whenever any field changes
56
+ * (navigations, but also shallow routing and form results). Neither fails on
57
+ * the client; on the server, Kit's `page` throws outside synchronous component
58
+ * rendering (including after an async boundary in an Effect forked during
59
+ * render), so `get` dies with a defect there.
60
+ *
61
+ * Provide {@link CurrentPage.layer} (backed by `$app/state`) in your client
62
+ * runtime, or `Layer.succeed(State.CurrentPage, …)` in tests.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * const trackView = Effect.gen(function* () {
67
+ * const page = yield* (yield* State.CurrentPage).get;
68
+ * yield* analytics.view(page.url.pathname);
69
+ * });
70
+ *
71
+ * runtime.runFork(trackView.pipe(Effect.provide(State.CurrentPage.layer)));
72
+ * ```
73
+ */
74
+ declare class CurrentPage extends CurrentPage_base {
75
+ /**
76
+ * A layer providing {@link CurrentPage} from `$app/state`'s `page`. Builds
77
+ * instantly and never fails; client-only (during server rendering `changes`
78
+ * never emits, so consuming it there hangs).
79
+ */
80
+ static readonly layer: Layer.Layer<CurrentPage>;
81
+ }
13
82
  //#endregion
14
- export { type PageSnapshot, State_d_exports, page };
83
+ export { CurrentPage, CurrentPageInterface, type NavigatingSnapshot, type PageSnapshot, State_d_exports, UpdateCheckError, checkForUpdate, navigating$1 as navigating, page$1 as page, updated$1 as updated };
15
84
  //# sourceMappingURL=State.d.ts.map