@thomasfosterau/effect-sveltekit 0.4.1 → 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 (54) hide show
  1. package/README.md +21 -15
  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 +1 -1
  8. package/dist/Remote.js.map +1 -1
  9. package/dist/State.d.ts +4 -4
  10. package/dist/State.js.map +1 -1
  11. package/dist/adapter/handler.d.ts +14 -12
  12. package/dist/adapter/handler.js +5 -7
  13. package/dist/adapter/handler.js.map +1 -1
  14. package/dist/adapter/index.js +25 -21
  15. package/dist/adapter/index.js.map +1 -1
  16. package/dist/api-client.js +1 -1
  17. package/dist/api-client.js.map +1 -1
  18. package/dist/app-runtime.d.ts +7 -6
  19. package/dist/app-runtime.js +5 -5
  20. package/dist/app-runtime.js.map +1 -1
  21. package/dist/client/Hooks.d.ts +1 -1
  22. package/dist/client/Hooks.js.map +1 -1
  23. package/dist/errors.js +3 -2
  24. package/dist/errors.js.map +1 -1
  25. package/dist/forms.d.ts +6 -6
  26. package/dist/forms.js.map +1 -1
  27. package/dist/internal/app-state.d.ts +1 -1
  28. package/dist/internal/app-state.js.map +1 -1
  29. package/dist/internal/auto.d.ts +2 -1
  30. package/dist/internal/auto.js.map +1 -1
  31. package/dist/internal/enhance.d.ts +1 -1
  32. package/dist/internal/enhance.js.map +1 -1
  33. package/dist/internal/error.js +23 -2
  34. package/dist/internal/error.js.map +1 -1
  35. package/dist/internal/remote-run.d.ts +3 -3
  36. package/dist/internal/remote-run.js.map +1 -1
  37. package/dist/kit.js +3 -3
  38. package/dist/kit.js.map +1 -1
  39. package/dist/remote-functions.d.ts +4 -4
  40. package/dist/remote-functions.js.map +1 -1
  41. package/dist/remote-reactive.d.ts +1 -1
  42. package/dist/remote-reactive.js.map +1 -1
  43. package/dist/response-headers.d.ts +1 -1
  44. package/dist/response-headers.js.map +1 -1
  45. package/dist/server/Endpoint.d.ts +2 -2
  46. package/dist/server/Endpoint.js +2 -2
  47. package/dist/server/Endpoint.js.map +1 -1
  48. package/dist/server/Hooks.d.ts +1 -1
  49. package/dist/server/Hooks.js.map +1 -1
  50. package/dist/transport.d.ts +1 -1
  51. package/dist/transport.js.map +1 -1
  52. package/dist/vite.d.ts +2 -2
  53. package/dist/vite.js.map +1 -1
  54. package/package.json +6 -4
@@ -1 +1 @@
1
- {"version":3,"file":"auto.js","names":[],"sources":["../../src/internal/auto.ts"],"sourcesContent":["/**\n * Runtime auto-wrappers used by the SvelteKit Vite plugin.\n *\n * The plugin replaces user-declared SvelteKit exports (`load`, `actions`,\n * `handle`, HTTP method handlers, etc.) with calls into the helpers in this\n * module. At runtime each helper detects whether the underlying value is an\n * Effect, a function returning an Effect, or a plain SvelteKit-compatible\n * function/value, and routes accordingly.\n *\n * When the plugin is configured with a `serverRuntime` / `clientRuntime`\n * module, that module's app-wide runtime (created with `makeServerRuntime` /\n * `makeUniversalRuntime`) is passed as the second argument to these helpers,\n * so plain-Effect exports get access to the application's services.\n *\n * This module is internal — the public Vite plugin generates references to it.\n */\n\nimport type {\n Action,\n Actions,\n Handle,\n HandleClientError,\n HandleFetch,\n HandleServerError,\n Load,\n RequestEvent,\n Reroute,\n ServerLoad,\n} from \"@sveltejs/kit\";\nimport { Effect, Exit } from \"effect\";\nimport {\n makeServerRuntime,\n makeUniversalRuntime,\n type ServerRuntime,\n type UniversalRuntime,\n} from \"../app-runtime.js\";\nimport { causeToThrowable } from \"./error.js\";\n\ntype AnyEffect = Effect.Effect<unknown, unknown, never>;\n\ntype AnyRuntime = ServerRuntime<any, any> | UniversalRuntime<any, any>;\n\n/**\n * Module shape accepted for the plugin's `serverRuntime` / `clientRuntime`\n * options: the runtime can be the default export or a named `runtime` export.\n */\nexport interface RuntimeModule {\n readonly runtime?: AnyRuntime;\n readonly default?: AnyRuntime;\n}\n\n// Default runtimes (no application layer), created lazily and shared across\n// all requests in the process.\nlet defaultServerRuntime: ServerRuntime<any, any> | undefined;\nlet defaultUniversalRuntime: UniversalRuntime<any, any> | undefined;\n\n/** Extract the runtime from a runtime module, if any. */\nconst runtimeOfModule = (mod?: RuntimeModule): AnyRuntime | undefined =>\n mod?.runtime ?? mod?.default;\n\n/** Distinguish a ServerRuntime from a UniversalRuntime structurally. */\nconst isServerRuntime = (runtime: AnyRuntime): runtime is ServerRuntime<any, any> =>\n \"serverLoad\" in runtime;\n\n/** The server runtime for a module, falling back to the shared default. */\nconst serverRuntimeOf = (mod?: RuntimeModule): ServerRuntime<any, any> => {\n const runtime = runtimeOfModule(mod);\n if (runtime !== undefined && isServerRuntime(runtime)) return runtime;\n return (defaultServerRuntime ??= makeServerRuntime<any, any>());\n};\n\n/** The universal runtime for a module, falling back to the shared default. */\nconst universalRuntimeOf = (mod?: RuntimeModule): UniversalRuntime<any, any> => {\n const runtime = runtimeOfModule(mod);\n if (runtime !== undefined && !isServerRuntime(runtime)) return runtime;\n return (defaultUniversalRuntime ??= makeUniversalRuntime<any, any>());\n};\n\n/** Run an effect without any request context (e.g. `init` hooks). */\nasync function runBare(effect: AnyEffect, runtime?: AnyRuntime): Promise<unknown> {\n const exit = runtime\n ? ((await runtime.runtime.runPromiseExit(effect)) as Exit.Exit<unknown, unknown>)\n : await Effect.runPromiseExit(effect);\n\n return Exit.match(exit, {\n onFailure: (cause) => {\n throw causeToThrowable(cause);\n },\n onSuccess: (value) => value,\n });\n}\n\nfunction isEffectValue(value: unknown): value is AnyEffect {\n return Effect.isEffect(value as never);\n}\n\ntype LoadLikeInput = undefined | AnyEffect | ((event: any) => unknown);\n\n/**\n * Wraps a value intended to be a SvelteKit universal `load` export.\n * Used by the Vite plugin for `+page.ts` / `+layout.ts`.\n */\nexport function wrapLoad<T extends LoadLikeInput>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : Load {\n if (value === undefined) return undefined as never;\n\n return (async (event: Parameters<Load>[0]) => {\n const result = isEffectValue(value) ? value : (value as (event: unknown) => unknown)(event);\n if (!isEffectValue(result)) return result;\n\n // Reuse the universal runtime's load wrapper so client/server detection\n // and per-request services stay in one place.\n return universalRuntimeOf(runtimeMod).load(\n () => result as Effect.Effect<Record<string, unknown>, unknown, never>,\n )(event);\n }) as never;\n}\n\n/** Shared implementation for server-side, event-based wrappers. */\nfunction wrapServerEvent<T extends LoadLikeInput>(\n value: T,\n runtimeMod?: RuntimeModule,\n): undefined | ((event: RequestEvent) => Promise<unknown>) {\n if (value === undefined) return undefined;\n\n return async (event: RequestEvent) => {\n const result = isEffectValue(value)\n ? value\n : (value as (event: RequestEvent) => unknown)(event);\n if (!isEffectValue(result)) return result;\n\n return serverRuntimeOf(runtimeMod).runPromise(event, result);\n };\n}\n\n/**\n * Wraps a value intended to be a SvelteKit server `load` export.\n * Used by the Vite plugin for `+page.server.ts` / `+layout.server.ts`.\n */\nexport function wrapServerLoad<T extends LoadLikeInput>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : ServerLoad {\n return wrapServerEvent(value, runtimeMod) as never;\n}\n\n/**\n * Wraps a single SvelteKit action handler.\n */\nexport function wrapAction<T extends LoadLikeInput>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : Action {\n return wrapServerEvent(value, runtimeMod) as never;\n}\n\n/**\n * Wraps a SvelteKit `actions` object, individually wrapping each entry.\n */\nexport function wrapActions<T extends Record<string, LoadLikeInput> | undefined>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : Actions {\n if (value === undefined) return undefined as never;\n if (typeof value !== \"object\" || value === null) return value as never;\n\n const wrapped: Actions = {};\n for (const [key, fn] of Object.entries(value)) {\n const wrappedAction = wrapAction(fn as LoadLikeInput, runtimeMod);\n if (wrappedAction !== undefined) {\n wrapped[key] = wrappedAction;\n }\n }\n return wrapped as never;\n}\n\n/**\n * Wraps a SvelteKit `handle` hook export.\n */\nexport function wrapHandle<\n T extends undefined | AnyEffect | ((args: Parameters<Handle>[0]) => unknown),\n>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : Handle {\n if (value === undefined) return undefined as never;\n\n const handle: Handle = (input) => {\n const result = isEffectValue(value)\n ? value\n : (value as (args: Parameters<Handle>[0]) => unknown)(input);\n if (!isEffectValue(result)) return result as Response | Promise<Response>;\n\n // Route through `handle` so the per-request runtime is installed on\n // `event.locals` for the rest of the request, like the explicit wrapper.\n return serverRuntimeOf(runtimeMod).handle(\n () => result as Effect.Effect<Response, unknown, never>,\n )(input) as Promise<Response>;\n };\n return handle as never;\n}\n\n/**\n * Wraps a SvelteKit `handleFetch` hook export.\n */\nexport function wrapHandleFetch<\n T extends undefined | AnyEffect | ((args: Parameters<HandleFetch>[0]) => unknown),\n>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : HandleFetch {\n if (value === undefined) return undefined as never;\n\n const handleFetch: HandleFetch = async (args) => {\n const result = isEffectValue(value)\n ? value\n : (value as (args: Parameters<HandleFetch>[0]) => unknown)(args);\n if (!isEffectValue(result)) return result as Response | Promise<Response>;\n\n return serverRuntimeOf(runtimeMod).runPromise(args.event, result) as Promise<Response>;\n };\n return handleFetch as never;\n}\n\ntype AnyHandleError = HandleServerError | HandleClientError;\n\n/**\n * Wraps a SvelteKit `handleError` hook export.\n */\nexport function wrapHandleError<\n T extends undefined | AnyEffect | ((args: Parameters<AnyHandleError>[0]) => unknown),\n>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : AnyHandleError {\n if (value === undefined) return undefined as never;\n\n return (async (args: Parameters<AnyHandleError>[0]) => {\n const result = isEffectValue(value)\n ? value\n : (value as (args: Parameters<AnyHandleError>[0]) => unknown)(args);\n if (!isEffectValue(result)) return result as ReturnType<AnyHandleError>;\n\n // Server errors carry a RequestEvent; client errors carry a NavigationEvent.\n const event = (args as { event?: RequestEvent }).event;\n const isServerEvent = event !== undefined && \"request\" in event;\n\n if (isServerEvent) {\n return serverRuntimeOf(runtimeMod).runPromise(event, result) as ReturnType<AnyHandleError>;\n }\n\n // Client-side: run on the bare app runtime (no request services).\n return runBare(result, runtimeOfModule(runtimeMod)) as ReturnType<AnyHandleError>;\n }) as never;\n}\n\n/**\n * Wraps a SvelteKit HTTP endpoint export (`GET`, `POST`, etc.).\n * Errors thrown by the underlying Effect propagate to SvelteKit's normal\n * error-handling pipeline (i.e. they are not silently swallowed). Use the\n * explicit `endpoint()` helper if you need the `exposeErrors` toggle.\n */\nexport function wrapEndpoint<T extends undefined | AnyEffect | ((event: RequestEvent) => unknown)>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : (event: RequestEvent) => Response | Promise<Response> {\n return wrapServerEvent(value as LoadLikeInput, runtimeMod) as never;\n}\n\ntype RerouteEvent = Parameters<Reroute>[0];\n\n/**\n * Wraps a SvelteKit universal `reroute` hook export. The effect runs on the\n * universal runtime with an `HttpClient` backed by the event's `fetch`, on both\n * the server and the client.\n */\nexport function wrapReroute<T extends undefined | AnyEffect | ((event: RerouteEvent) => unknown)>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : Reroute {\n if (value === undefined) return undefined as never;\n\n return ((event: RerouteEvent) => {\n const result = isEffectValue(value)\n ? value\n : (value as (event: RerouteEvent) => unknown)(event);\n if (!isEffectValue(result)) return result as ReturnType<Reroute>;\n\n return universalRuntimeOf(runtimeMod).runPromise(event.fetch, result) as ReturnType<Reroute>;\n }) as never;\n}\n\n/**\n * Wraps a SvelteKit `init` hook export (server or client).\n * `init` runs once at startup; there is no request event available, but the\n * application runtime's services (if configured) are.\n */\nexport function wrapInit<T extends undefined | AnyEffect | (() => unknown)>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : () => Promise<void> {\n if (value === undefined) return undefined as never;\n\n return (async () => {\n const result = isEffectValue(value) ? value : (value as () => unknown)();\n if (!isEffectValue(result)) {\n await result;\n return;\n }\n await runBare(result, runtimeOfModule(runtimeMod));\n }) as never;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"auto.js","names":[],"sources":["../../src/internal/auto.ts"],"sourcesContent":["/**\n * Runtime auto-wrappers used by the SvelteKit Vite plugin.\n *\n * The plugin replaces user-declared SvelteKit exports (`load`, `actions`,\n * `handle`, HTTP method handlers, etc.) with calls into the helpers in this\n * module. At runtime each helper detects whether the underlying value is an\n * Effect, a function returning an Effect, or a plain SvelteKit-compatible\n * function/value, and routes accordingly.\n *\n * When the plugin is configured with a `serverRuntime` / `clientRuntime`\n * module, that module's app-wide runtime (created with `makeServerRuntime` /\n * `makeUniversalRuntime`) is passed as the second argument to these helpers,\n * so plain-Effect exports get access to the application's services.\n *\n * This module is internal — the public Vite plugin generates references to it.\n */\n\nimport type { Action, Actions, Load, RequestEvent, ServerLoad } from \"@sveltejs/kit\";\nimport type {\n Handle,\n HandleClientError,\n HandleFetch,\n HandleServerError,\n Reroute,\n} from \"@sveltejs/kit/hooks\";\nimport { Effect, Exit } from \"effect\";\nimport {\n makeServerRuntime,\n makeUniversalRuntime,\n type ServerRuntime,\n type UniversalRuntime,\n} from \"../app-runtime.js\";\nimport { causeToThrowable } from \"./error.js\";\n\ntype AnyEffect = Effect.Effect<unknown, unknown, never>;\n\ntype AnyRuntime = ServerRuntime<any, any> | UniversalRuntime<any, any>;\n\n/**\n * Module shape accepted for the plugin's `serverRuntime` / `clientRuntime`\n * options: the runtime can be the default export or a named `runtime` export.\n */\nexport interface RuntimeModule {\n readonly runtime?: AnyRuntime;\n readonly default?: AnyRuntime;\n}\n\n// Default runtimes (no application layer), created lazily and shared across\n// all requests in the process.\nlet defaultServerRuntime: ServerRuntime<any, any> | undefined;\nlet defaultUniversalRuntime: UniversalRuntime<any, any> | undefined;\n\n/** Extract the runtime from a runtime module, if any. */\nconst runtimeOfModule = (mod?: RuntimeModule): AnyRuntime | undefined =>\n mod?.runtime ?? mod?.default;\n\n/** Distinguish a ServerRuntime from a UniversalRuntime structurally. */\nconst isServerRuntime = (runtime: AnyRuntime): runtime is ServerRuntime<any, any> =>\n \"serverLoad\" in runtime;\n\n/** The server runtime for a module, falling back to the shared default. */\nconst serverRuntimeOf = (mod?: RuntimeModule): ServerRuntime<any, any> => {\n const runtime = runtimeOfModule(mod);\n if (runtime !== undefined && isServerRuntime(runtime)) return runtime;\n return (defaultServerRuntime ??= makeServerRuntime<any, any>());\n};\n\n/** The universal runtime for a module, falling back to the shared default. */\nconst universalRuntimeOf = (mod?: RuntimeModule): UniversalRuntime<any, any> => {\n const runtime = runtimeOfModule(mod);\n if (runtime !== undefined && !isServerRuntime(runtime)) return runtime;\n return (defaultUniversalRuntime ??= makeUniversalRuntime<any, any>());\n};\n\n/** Run an effect without any request context (e.g. `init` hooks). */\nasync function runBare(effect: AnyEffect, runtime?: AnyRuntime): Promise<unknown> {\n const exit = runtime\n ? ((await runtime.runtime.runPromiseExit(effect)) as Exit.Exit<unknown, unknown>)\n : await Effect.runPromiseExit(effect);\n\n return Exit.match(exit, {\n onFailure: (cause) => {\n throw causeToThrowable(cause);\n },\n onSuccess: (value) => value,\n });\n}\n\nfunction isEffectValue(value: unknown): value is AnyEffect {\n return Effect.isEffect(value as never);\n}\n\ntype LoadLikeInput = undefined | AnyEffect | ((event: any) => unknown);\n\n/**\n * Wraps a value intended to be a SvelteKit universal `load` export.\n * Used by the Vite plugin for `+page.ts` / `+layout.ts`.\n */\nexport function wrapLoad<T extends LoadLikeInput>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : Load {\n if (value === undefined) return undefined as never;\n\n return (async (event: Parameters<Load>[0]) => {\n const result = isEffectValue(value) ? value : (value as (event: unknown) => unknown)(event);\n if (!isEffectValue(result)) return result;\n\n // Reuse the universal runtime's load wrapper so client/server detection\n // and per-request services stay in one place.\n return universalRuntimeOf(runtimeMod).load(\n () => result as Effect.Effect<Record<string, unknown>, unknown, never>,\n )(event);\n }) as never;\n}\n\n/** Shared implementation for server-side, event-based wrappers. */\nfunction wrapServerEvent<T extends LoadLikeInput>(\n value: T,\n runtimeMod?: RuntimeModule,\n): undefined | ((event: RequestEvent) => Promise<unknown>) {\n if (value === undefined) return undefined;\n\n return async (event: RequestEvent) => {\n const result = isEffectValue(value)\n ? value\n : (value as (event: RequestEvent) => unknown)(event);\n if (!isEffectValue(result)) return result;\n\n return serverRuntimeOf(runtimeMod).runPromise(event, result);\n };\n}\n\n/**\n * Wraps a value intended to be a SvelteKit server `load` export.\n * Used by the Vite plugin for `+page.server.ts` / `+layout.server.ts`.\n */\nexport function wrapServerLoad<T extends LoadLikeInput>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : ServerLoad {\n return wrapServerEvent(value, runtimeMod) as never;\n}\n\n/**\n * Wraps a single SvelteKit action handler.\n */\nexport function wrapAction<T extends LoadLikeInput>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : Action {\n return wrapServerEvent(value, runtimeMod) as never;\n}\n\n/**\n * Wraps a SvelteKit `actions` object, individually wrapping each entry.\n */\nexport function wrapActions<T extends Record<string, LoadLikeInput> | undefined>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : Actions {\n if (value === undefined) return undefined as never;\n if (typeof value !== \"object\" || value === null) return value as never;\n\n const wrapped: Actions = {};\n for (const [key, fn] of Object.entries(value)) {\n const wrappedAction = wrapAction(fn as LoadLikeInput, runtimeMod);\n if (wrappedAction !== undefined) {\n wrapped[key] = wrappedAction;\n }\n }\n return wrapped as never;\n}\n\n/**\n * Wraps a SvelteKit `handle` hook export.\n */\nexport function wrapHandle<\n T extends undefined | AnyEffect | ((args: Parameters<Handle>[0]) => unknown),\n>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : Handle {\n if (value === undefined) return undefined as never;\n\n const handle: Handle = (input) => {\n const result = isEffectValue(value)\n ? value\n : (value as (args: Parameters<Handle>[0]) => unknown)(input);\n if (!isEffectValue(result)) return result as Response | Promise<Response>;\n\n // Route through `handle` so the per-request runtime is installed on\n // `event.locals` for the rest of the request, like the explicit wrapper.\n return serverRuntimeOf(runtimeMod).handle(\n () => result as Effect.Effect<Response, unknown, never>,\n )(input) as Promise<Response>;\n };\n return handle as never;\n}\n\n/**\n * Wraps a SvelteKit `handleFetch` hook export.\n */\nexport function wrapHandleFetch<\n T extends undefined | AnyEffect | ((args: Parameters<HandleFetch>[0]) => unknown),\n>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : HandleFetch {\n if (value === undefined) return undefined as never;\n\n const handleFetch: HandleFetch = async (args) => {\n const result = isEffectValue(value)\n ? value\n : (value as (args: Parameters<HandleFetch>[0]) => unknown)(args);\n if (!isEffectValue(result)) return result as Response | Promise<Response>;\n\n return serverRuntimeOf(runtimeMod).runPromise(args.event, result) as Promise<Response>;\n };\n return handleFetch as never;\n}\n\ntype AnyHandleError = HandleServerError | HandleClientError;\n\n/**\n * Wraps a SvelteKit `handleError` hook export.\n */\nexport function wrapHandleError<\n T extends undefined | AnyEffect | ((args: Parameters<AnyHandleError>[0]) => unknown),\n>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : AnyHandleError {\n if (value === undefined) return undefined as never;\n\n return (async (args: Parameters<AnyHandleError>[0]) => {\n const result = isEffectValue(value)\n ? value\n : (value as (args: Parameters<AnyHandleError>[0]) => unknown)(args);\n if (!isEffectValue(result)) return result as ReturnType<AnyHandleError>;\n\n // Server errors carry a RequestEvent; client errors carry a NavigationEvent.\n const event = (args as { event?: RequestEvent }).event;\n const isServerEvent = event !== undefined && \"request\" in event;\n\n if (isServerEvent) {\n return serverRuntimeOf(runtimeMod).runPromise(event, result) as ReturnType<AnyHandleError>;\n }\n\n // Client-side: run on the bare app runtime (no request services).\n return runBare(result, runtimeOfModule(runtimeMod)) as ReturnType<AnyHandleError>;\n }) as never;\n}\n\n/**\n * Wraps a SvelteKit HTTP endpoint export (`GET`, `POST`, etc.).\n * Errors thrown by the underlying Effect propagate to SvelteKit's normal\n * error-handling pipeline (i.e. they are not silently swallowed). Use the\n * explicit `endpoint()` helper if you need the `exposeErrors` toggle.\n */\nexport function wrapEndpoint<T extends undefined | AnyEffect | ((event: RequestEvent) => unknown)>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : (event: RequestEvent) => Response | Promise<Response> {\n return wrapServerEvent(value as LoadLikeInput, runtimeMod) as never;\n}\n\ntype RerouteEvent = Parameters<Reroute>[0];\n\n/**\n * Wraps a SvelteKit universal `reroute` hook export. The effect runs on the\n * universal runtime with an `HttpClient` backed by the event's `fetch`, on both\n * the server and the client.\n */\nexport function wrapReroute<T extends undefined | AnyEffect | ((event: RerouteEvent) => unknown)>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : Reroute {\n if (value === undefined) return undefined as never;\n\n return ((event: RerouteEvent) => {\n const result = isEffectValue(value)\n ? value\n : (value as (event: RerouteEvent) => unknown)(event);\n if (!isEffectValue(result)) return result as ReturnType<Reroute>;\n\n return universalRuntimeOf(runtimeMod).runPromise(event.fetch, result) as ReturnType<Reroute>;\n }) as never;\n}\n\n/**\n * Wraps a SvelteKit `init` hook export (server or client).\n * `init` runs once at startup; there is no request event available, but the\n * application runtime's services (if configured) are.\n */\nexport function wrapInit<T extends undefined | AnyEffect | (() => unknown)>(\n value: T,\n runtimeMod?: RuntimeModule,\n): T extends undefined ? undefined : () => Promise<void> {\n if (value === undefined) return undefined as never;\n\n return (async () => {\n const result = isEffectValue(value) ? value : (value as () => unknown)();\n if (!isEffectValue(result)) {\n await result;\n return;\n }\n await runBare(result, runtimeOfModule(runtimeMod));\n }) as never;\n}\n"],"mappings":";;;;AAiDA,IAAI;AACJ,IAAI;;AAGJ,MAAM,mBAAmB,QACvB,KAAK,WAAW,KAAK;;AAGvB,MAAM,mBAAmB,YACvB,gBAAgB;;AAGlB,MAAM,mBAAmB,QAAiD;CACxE,MAAM,UAAU,gBAAgB,GAAG;CACnC,IAAI,YAAY,KAAA,KAAa,gBAAgB,OAAO,GAAG,OAAO;CAC9D,OAAQ,yBAAyB,kBAA4B;AAC/D;;AAGA,MAAM,sBAAsB,QAAoD;CAC9E,MAAM,UAAU,gBAAgB,GAAG;CACnC,IAAI,YAAY,KAAA,KAAa,CAAC,gBAAgB,OAAO,GAAG,OAAO;CAC/D,OAAQ,4BAA4B,qBAA+B;AACrE;;AAGA,eAAe,QAAQ,QAAmB,SAAwC;CAChF,MAAM,OAAO,UACP,MAAM,QAAQ,QAAQ,eAAe,MAAM,IAC7C,MAAM,OAAO,eAAe,MAAM;CAEtC,OAAO,KAAK,MAAM,MAAM;EACtB,YAAY,UAAU;GACpB,MAAM,iBAAiB,KAAK;EAC9B;EACA,YAAY,UAAU;CACxB,CAAC;AACH;AAEA,SAAS,cAAc,OAAoC;CACzD,OAAO,OAAO,SAAS,KAAc;AACvC;;;;;AAQA,SAAgB,SACd,OACA,YACwC;CACxC,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAEhC,QAAQ,OAAO,UAA+B;EAC5C,MAAM,SAAS,cAAc,KAAK,IAAI,QAAS,MAAsC,KAAK;EAC1F,IAAI,CAAC,cAAc,MAAM,GAAG,OAAO;EAInC,OAAO,mBAAmB,UAAU,CAAC,CAAC,WAC9B,MACR,CAAC,CAAC,KAAK;CACT;AACF;;AAGA,SAAS,gBACP,OACA,YACyD;CACzD,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAEhC,OAAO,OAAO,UAAwB;EACpC,MAAM,SAAS,cAAc,KAAK,IAC9B,QACC,MAA2C,KAAK;EACrD,IAAI,CAAC,cAAc,MAAM,GAAG,OAAO;EAEnC,OAAO,gBAAgB,UAAU,CAAC,CAAC,WAAW,OAAO,MAAM;CAC7D;AACF;;;;;AAMA,SAAgB,eACd,OACA,YAC8C;CAC9C,OAAO,gBAAgB,OAAO,UAAU;AAC1C;;;;AAKA,SAAgB,WACd,OACA,YAC0C;CAC1C,OAAO,gBAAgB,OAAO,UAAU;AAC1C;;;;AAKA,SAAgB,YACd,OACA,YAC2C;CAC3C,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CAExD,MAAM,UAAmB,CAAC;CAC1B,KAAK,MAAM,CAAC,KAAK,OAAO,OAAO,QAAQ,KAAK,GAAG;EAC7C,MAAM,gBAAgB,WAAW,IAAqB,UAAU;EAChE,IAAI,kBAAkB,KAAA,GACpB,QAAQ,OAAO;CAEnB;CACA,OAAO;AACT;;;;AAKA,SAAgB,WAEd,OAAU,YAAsE;CAChF,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAEhC,MAAM,UAAkB,UAAU;EAChC,MAAM,SAAS,cAAc,KAAK,IAC9B,QACC,MAAmD,KAAK;EAC7D,IAAI,CAAC,cAAc,MAAM,GAAG,OAAO;EAInC,OAAO,gBAAgB,UAAU,CAAC,CAAC,aAC3B,MACR,CAAC,CAAC,KAAK;CACT;CACA,OAAO;AACT;;;;AAKA,SAAgB,gBAEd,OAAU,YAA2E;CACrF,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAEhC,MAAM,cAA2B,OAAO,SAAS;EAC/C,MAAM,SAAS,cAAc,KAAK,IAC9B,QACC,MAAwD,IAAI;EACjE,IAAI,CAAC,cAAc,MAAM,GAAG,OAAO;EAEnC,OAAO,gBAAgB,UAAU,CAAC,CAAC,WAAW,KAAK,OAAO,MAAM;CAClE;CACA,OAAO;AACT;;;;AAOA,SAAgB,gBAEd,OAAU,YAA8E;CACxF,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAEhC,QAAQ,OAAO,SAAwC;EACrD,MAAM,SAAS,cAAc,KAAK,IAC9B,QACC,MAA2D,IAAI;EACpE,IAAI,CAAC,cAAc,MAAM,GAAG,OAAO;EAGnC,MAAM,QAAS,KAAkC;EAGjD,IAFsB,UAAU,KAAA,KAAa,aAAa,OAGxD,OAAO,gBAAgB,UAAU,CAAC,CAAC,WAAW,OAAO,MAAM;EAI7D,OAAO,QAAQ,QAAQ,gBAAgB,UAAU,CAAC;CACpD;AACF;;;;;;;AAQA,SAAgB,aACd,OACA,YACyF;CACzF,OAAO,gBAAgB,OAAwB,UAAU;AAC3D;;;;;;AASA,SAAgB,YACd,OACA,YAC2C;CAC3C,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAEhC,SAAS,UAAwB;EAC/B,MAAM,SAAS,cAAc,KAAK,IAC9B,QACC,MAA2C,KAAK;EACrD,IAAI,CAAC,cAAc,MAAM,GAAG,OAAO;EAEnC,OAAO,mBAAmB,UAAU,CAAC,CAAC,WAAW,MAAM,OAAO,MAAM;CACtE;AACF;;;;;;AAOA,SAAgB,SACd,OACA,YACuD;CACvD,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAEhC,QAAQ,YAAY;EAClB,MAAM,SAAS,cAAc,KAAK,IAAI,QAAS,MAAwB;EACvE,IAAI,CAAC,cAAc,MAAM,GAAG;GAC1B,MAAM;GACN;EACF;EACA,MAAM,QAAQ,QAAQ,gBAAgB,UAAU,CAAC;CACnD;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { Context, Effect, ManagedRuntime } from "effect";
2
- import { SubmitFunction } from "@sveltejs/kit";
2
+ import { SubmitFunction } from "$app/forms";
3
3
  //#region src/internal/enhance.d.ts
4
4
  /** The input SvelteKit passes to a `SubmitFunction` before the request is sent. */
5
5
  type SubmitInput = Parameters<SubmitFunction>[0];
@@ -1 +1 @@
1
- {"version":3,"file":"enhance.js","names":[],"sources":["../../src/internal/enhance.ts"],"sourcesContent":["/**\n * The runtime-agnostic core of the `use:enhance` bridge, kept free of any\n * `$app/*` import so it can be unit-tested outside a SvelteKit app build.\n */\n\nimport type { SubmitFunction } from \"@sveltejs/kit\";\nimport { Context, Effect, ManagedRuntime } from \"effect\";\n\n/** The input SvelteKit passes to a `SubmitFunction` before the request is sent. */\nexport type SubmitInput = Parameters<SubmitFunction>[0];\n\n/** The result callback a `SubmitFunction` may return, run once the action responds. */\ntype ResultCallback = Extract<Awaited<ReturnType<SubmitFunction>>, (...args: never) => unknown>;\n\n/** The options passed to the result callback (`result`, `update`, ...). */\nexport type ResultOptions = Parameters<ResultCallback>[0];\n\n/** A runtime the handler effects can run against (a `Context` or `ManagedRuntime`). */\nexport type EnhanceRuntime<R> = Context.Context<R> | ManagedRuntime.ManagedRuntime<R, never>;\n\n/** Effect-based handlers for the two phases of an enhanced form submission. */\nexport interface EnhanceHandlers<R = never> {\n /**\n * Runs before the request is sent. Call `input.cancel()` to abort the\n * submission (the result phase then never runs). Use for optimistic UI or\n * validation.\n */\n readonly onSubmit?: (input: SubmitInput) => Effect.Effect<void, never, R>;\n /**\n * Runs once the action responds, with the `ActionResult` and SvelteKit's\n * `update()` (which applies the default behaviour — updating `page.form`,\n * resetting the form, invalidating). If omitted, SvelteKit's default\n * behaviour applies automatically.\n */\n readonly onResult?: (options: ResultOptions) => Effect.Effect<void, never, R>;\n}\n\n/** Options for {@link makeSubmitFunction}. */\nexport interface EnhanceOptions<R = never> {\n /**\n * The runtime to run the handler effects against. Omit when the handlers\n * require no services (`R = never`); they then run on the default runtime.\n */\n readonly runtime?: EnhanceRuntime<R>;\n}\n\n/** Run an `Effect<A, never, R>` on the given runtime (or the default when none). */\nconst runPromiseWith =\n <R>(runtime: EnhanceRuntime<R> | undefined) =>\n <A>(effect: Effect.Effect<A, never, R>): Promise<A> => {\n if (runtime === undefined) return Effect.runPromise(effect as Effect.Effect<A, never, never>);\n return Context.isContext(runtime)\n ? Effect.runPromiseWith(runtime)(effect)\n : runtime.runPromise(effect);\n };\n\n/**\n * Build a SvelteKit `SubmitFunction` from Effect-based handlers. See\n * `Forms.enhance` for the public entry point and documentation.\n */\nexport const makeSubmitFunction = <R = never>(\n handlers: EnhanceHandlers<R>,\n options?: EnhanceOptions<R>,\n): SubmitFunction => {\n const run = runPromiseWith(options?.runtime);\n return async (input) => {\n if (handlers.onSubmit) await run(handlers.onSubmit(input));\n // Returning `undefined` lets SvelteKit apply its default result behaviour.\n if (!handlers.onResult) return undefined;\n const onResult = handlers.onResult;\n return (resultOptions) => run(onResult(resultOptions));\n };\n};\n"],"mappings":";;;AA+CA,MAAM,kBACA,aACA,WAAmD;CACrD,IAAI,YAAY,KAAA,GAAW,OAAO,OAAO,WAAW,MAAwC;CAC5F,OAAO,QAAQ,UAAU,OAAO,IAC5B,OAAO,eAAe,OAAO,CAAC,CAAC,MAAM,IACrC,QAAQ,WAAW,MAAM;AAC/B;;;;;AAMF,MAAa,sBACX,UACA,YACmB;CACnB,MAAM,MAAM,eAAe,SAAS,OAAO;CAC3C,OAAO,OAAO,UAAU;EACtB,IAAI,SAAS,UAAU,MAAM,IAAI,SAAS,SAAS,KAAK,CAAC;EAEzD,IAAI,CAAC,SAAS,UAAU,OAAO,KAAA;EAC/B,MAAM,WAAW,SAAS;EAC1B,QAAQ,kBAAkB,IAAI,SAAS,aAAa,CAAC;CACvD;AACF"}
1
+ {"version":3,"file":"enhance.js","names":[],"sources":["../../src/internal/enhance.ts"],"sourcesContent":["/**\n * The runtime-agnostic core of the `use:enhance` bridge, kept free of any\n * `$app/*` import so it can be unit-tested outside a SvelteKit app build.\n */\n\nimport type { SubmitFunction } from \"$app/forms\";\nimport { Context, Effect, ManagedRuntime } from \"effect\";\n\n/** The input SvelteKit passes to a `SubmitFunction` before the request is sent. */\nexport type SubmitInput = Parameters<SubmitFunction>[0];\n\n/** The result callback a `SubmitFunction` may return, run once the action responds. */\ntype ResultCallback = Extract<Awaited<ReturnType<SubmitFunction>>, (...args: never) => unknown>;\n\n/** The options passed to the result callback (`result`, `update`, ...). */\nexport type ResultOptions = Parameters<ResultCallback>[0];\n\n/** A runtime the handler effects can run against (a `Context` or `ManagedRuntime`). */\nexport type EnhanceRuntime<R> = Context.Context<R> | ManagedRuntime.ManagedRuntime<R, never>;\n\n/** Effect-based handlers for the two phases of an enhanced form submission. */\nexport interface EnhanceHandlers<R = never> {\n /**\n * Runs before the request is sent. Call `input.cancel()` to abort the\n * submission (the result phase then never runs). Use for optimistic UI or\n * validation.\n */\n readonly onSubmit?: (input: SubmitInput) => Effect.Effect<void, never, R>;\n /**\n * Runs once the action responds, with the `ActionResult` and SvelteKit's\n * `update()` (which applies the default behaviour — updating `page.form`,\n * resetting the form, invalidating). If omitted, SvelteKit's default\n * behaviour applies automatically.\n */\n readonly onResult?: (options: ResultOptions) => Effect.Effect<void, never, R>;\n}\n\n/** Options for {@link makeSubmitFunction}. */\nexport interface EnhanceOptions<R = never> {\n /**\n * The runtime to run the handler effects against. Omit when the handlers\n * require no services (`R = never`); they then run on the default runtime.\n */\n readonly runtime?: EnhanceRuntime<R>;\n}\n\n/** Run an `Effect<A, never, R>` on the given runtime (or the default when none). */\nconst runPromiseWith =\n <R>(runtime: EnhanceRuntime<R> | undefined) =>\n <A>(effect: Effect.Effect<A, never, R>): Promise<A> => {\n if (runtime === undefined) return Effect.runPromise(effect as Effect.Effect<A, never, never>);\n return Context.isContext(runtime)\n ? Effect.runPromiseWith(runtime)(effect)\n : runtime.runPromise(effect);\n };\n\n/**\n * Build a SvelteKit `SubmitFunction` from Effect-based handlers. See\n * `Forms.enhance` for the public entry point and documentation.\n */\nexport const makeSubmitFunction = <R = never>(\n handlers: EnhanceHandlers<R>,\n options?: EnhanceOptions<R>,\n): SubmitFunction => {\n const run = runPromiseWith(options?.runtime);\n return async (input) => {\n if (handlers.onSubmit) await run(handlers.onSubmit(input));\n // Returning `undefined` lets SvelteKit apply its default result behaviour.\n if (!handlers.onResult) return undefined;\n const onResult = handlers.onResult;\n return (resultOptions) => run(onResult(resultOptions));\n };\n};\n"],"mappings":";;;AA+CA,MAAM,kBACA,aACA,WAAmD;CACrD,IAAI,YAAY,KAAA,GAAW,OAAO,OAAO,WAAW,MAAwC;CAC5F,OAAO,QAAQ,UAAU,OAAO,IAC5B,OAAO,eAAe,OAAO,CAAC,CAAC,MAAM,IACrC,QAAQ,WAAW,MAAM;AAC/B;;;;;AAMF,MAAa,sBACX,UACA,YACmB;CACnB,MAAM,MAAM,eAAe,SAAS,OAAO;CAC3C,OAAO,OAAO,UAAU;EACtB,IAAI,SAAS,UAAU,MAAM,IAAI,SAAS,SAAS,KAAK,CAAC;EAEzD,IAAI,CAAC,SAAS,UAAU,OAAO,KAAA;EAC/B,MAAM,WAAW,SAAS;EAC1B,QAAQ,kBAAkB,IAAI,SAAS,aAAa,CAAC;CACvD;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { Cause } from "effect";
2
- import { isHttpError, isRedirect } from "@sveltejs/kit";
2
+ import { error, isHttpError, isRedirect } from "@sveltejs/kit";
3
3
  //#region src/internal/error.ts
4
4
  /**
5
5
  * Custom error type that preserves the original Effect Cause.
@@ -25,7 +25,28 @@ const causeToThrowable = (cause) => {
25
25
  if (isRedirect(squashed) || isHttpError(squashed)) return squashed;
26
26
  return new EffectCauseError(Cause.pretty(cause), cause);
27
27
  };
28
+ /**
29
+ * `error()` with the message and the extra `App.Error` properties as separate
30
+ * arguments. Kit's typed overloads only admit a third argument once the app
31
+ * augments `App.Error`, which this library cannot see.
32
+ */
33
+ const kitErrorWith = error;
34
+ /**
35
+ * Throw SvelteKit's `error()` for a string or `App.Error`-shaped body, without
36
+ * the `error(status, body)` overload Kit 3 deprecates (kit#16540): an object
37
+ * body is split into `error(status, message, properties)`.
38
+ *
39
+ * The resulting `HttpError` is the one the deprecated overload built: `status`
40
+ * always wins over a `status` field in the body, and a missing message becomes
41
+ * Kit's default `Error: <status>`. A non-string `message` field (outside the
42
+ * `App.Error` type) is dropped in favour of that default.
43
+ */
44
+ const throwKitError = (status, body) => {
45
+ if (body === void 0 || typeof body === "string") return kitErrorWith(status, body);
46
+ const { message, ...properties } = body;
47
+ return kitErrorWith(status, typeof message === "string" ? message : void 0, properties);
48
+ };
28
49
  //#endregion
29
- export { EffectCauseError, causeToThrowable };
50
+ export { EffectCauseError, causeToThrowable, throwKitError };
30
51
 
31
52
  //# sourceMappingURL=error.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","names":[],"sources":["../../src/internal/error.ts"],"sourcesContent":["import { isHttpError, isRedirect } from \"@sveltejs/kit\";\nimport { Cause } from \"effect\";\n\n/**\n * Custom error type that preserves the original Effect Cause.\n */\nexport class EffectCauseError extends Error {\n declare cause: Cause.Cause<unknown>;\n\n constructor(message: string, cause: Cause.Cause<unknown>) {\n super(message);\n this.name = \"EffectCauseError\";\n this.cause = cause;\n }\n}\n\n/**\n * Converts a failed Effect Cause into the value to `throw`.\n *\n * SvelteKit uses thrown `redirect()` and `error()` objects for control flow.\n * When one of those is raised inside an Effect (either thrown, surfacing as a\n * defect, or used as a typed failure) the original object is rethrown so\n * SvelteKit can handle it as intended. Anything else is wrapped in an\n * `EffectCauseError` that preserves the full Cause for debugging.\n */\nexport const causeToThrowable = (cause: Cause.Cause<unknown>): unknown => {\n const squashed = Cause.squash(cause);\n if (isRedirect(squashed) || isHttpError(squashed)) {\n return squashed;\n }\n return new EffectCauseError(Cause.pretty(cause), cause);\n};\n"],"mappings":";;;;;;AAMA,IAAa,mBAAb,cAAsC,MAAM;CAG1C,YAAY,SAAiB,OAA6B;EACxD,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,QAAQ;CACf;AACF;;;;;;;;;;AAWA,MAAa,oBAAoB,UAAyC;CACxE,MAAM,WAAW,MAAM,OAAO,KAAK;CACnC,IAAI,WAAW,QAAQ,KAAK,YAAY,QAAQ,GAC9C,OAAO;CAET,OAAO,IAAI,iBAAiB,MAAM,OAAO,KAAK,GAAG,KAAK;AACxD"}
1
+ {"version":3,"file":"error.js","names":["kitError"],"sources":["../../src/internal/error.ts"],"sourcesContent":["import { error as kitError, isHttpError, isRedirect } from \"@sveltejs/kit\";\nimport { Cause } from \"effect\";\n\n/**\n * Custom error type that preserves the original Effect Cause.\n */\nexport class EffectCauseError extends Error {\n declare cause: Cause.Cause<unknown>;\n\n constructor(message: string, cause: Cause.Cause<unknown>) {\n super(message);\n this.name = \"EffectCauseError\";\n this.cause = cause;\n }\n}\n\n/**\n * Converts a failed Effect Cause into the value to `throw`.\n *\n * SvelteKit uses thrown `redirect()` and `error()` objects for control flow.\n * When one of those is raised inside an Effect (either thrown, surfacing as a\n * defect, or used as a typed failure) the original object is rethrown so\n * SvelteKit can handle it as intended. Anything else is wrapped in an\n * `EffectCauseError` that preserves the full Cause for debugging.\n */\nexport const causeToThrowable = (cause: Cause.Cause<unknown>): unknown => {\n const squashed = Cause.squash(cause);\n if (isRedirect(squashed) || isHttpError(squashed)) {\n return squashed;\n }\n return new EffectCauseError(Cause.pretty(cause), cause);\n};\n\n/**\n * `error()` with the message and the extra `App.Error` properties as separate\n * arguments. Kit's typed overloads only admit a third argument once the app\n * augments `App.Error`, which this library cannot see.\n */\nconst kitErrorWith = kitError as (\n status: number,\n message?: string,\n properties?: Readonly<Record<string, unknown>>,\n) => never;\n\n/**\n * Throw SvelteKit's `error()` for a string or `App.Error`-shaped body, without\n * the `error(status, body)` overload Kit 3 deprecates (kit#16540): an object\n * body is split into `error(status, message, properties)`.\n *\n * The resulting `HttpError` is the one the deprecated overload built: `status`\n * always wins over a `status` field in the body, and a missing message becomes\n * Kit's default `Error: <status>`. A non-string `message` field (outside the\n * `App.Error` type) is dropped in favour of that default.\n */\nexport const throwKitError = (\n status: number,\n body?: string | Readonly<Record<string, unknown>>,\n): never => {\n if (body === undefined || typeof body === \"string\") return kitErrorWith(status, body);\n const { message, ...properties } = body;\n return kitErrorWith(status, typeof message === \"string\" ? message : undefined, properties);\n};\n"],"mappings":";;;;;;AAMA,IAAa,mBAAb,cAAsC,MAAM;CAG1C,YAAY,SAAiB,OAA6B;EACxD,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,QAAQ;CACf;AACF;;;;;;;;;;AAWA,MAAa,oBAAoB,UAAyC;CACxE,MAAM,WAAW,MAAM,OAAO,KAAK;CACnC,IAAI,WAAW,QAAQ,KAAK,YAAY,QAAQ,GAC9C,OAAO;CAET,OAAO,IAAI,iBAAiB,MAAM,OAAO,KAAK,GAAG,KAAK;AACxD;;;;;;AAOA,MAAM,eAAeA;;;;;;;;;;;AAgBrB,MAAa,iBACX,QACA,SACU;CACV,IAAI,SAAS,KAAA,KAAa,OAAO,SAAS,UAAU,OAAO,aAAa,QAAQ,IAAI;CACpF,MAAM,EAAE,SAAS,GAAG,eAAe;CACnC,OAAO,aAAa,QAAQ,OAAO,YAAY,WAAW,UAAU,KAAA,GAAW,UAAU;AAC3F"}
@@ -1,6 +1,6 @@
1
1
  import "../request-runtime.js";
2
2
  import { Effect, Exit } from "effect";
3
- import { InvalidField } from "@sveltejs/kit";
3
+ import { RemoteFormInvalidField } from "$app/server";
4
4
  //#region src/internal/remote-run.d.ts
5
5
  /**
6
6
  * Maps a remote *form* handler's failure into SvelteKit's field issues, given
@@ -9,14 +9,14 @@ import { InvalidField } from "@sveltejs/kit";
9
9
  * a generic failure. Receives the squashed handler failure.
10
10
  */
11
11
  type FormErrorMapper = (error: unknown, ctx: {
12
- readonly issue: InvalidField<any>;
12
+ readonly issue: RemoteFormInvalidField<any>;
13
13
  readonly data: unknown;
14
14
  }) => never;
15
15
  /** Runs a remote handler's effect and settles it (value or thrown via translator). */
16
16
  type Runner = <A>(effect: Effect.Effect<A, unknown, any>) => Promise<A>;
17
17
  /** Like {@link Runner}, but with the form's `issue` / `data` for error interop. */
18
18
  type FormRunner = <A>(effect: Effect.Effect<A, unknown, any>, ctx: {
19
- readonly issue: InvalidField<any>;
19
+ readonly issue: RemoteFormInvalidField<any>;
20
20
  readonly data: unknown;
21
21
  }) => Promise<A>;
22
22
  /** Runners that execute a remote-function handler's Effect on a request runtime, as `runRemote` returns them. */
@@ -1 +1 @@
1
- {"version":3,"file":"remote-run.js","names":[],"sources":["../../src/internal/remote-run.ts"],"sourcesContent":["/**\n * Run/settle helpers for the remote-function wrappers, factored out so they can\n * be unit-tested without importing `$app/server` (a SvelteKit virtual module\n * unavailable outside an app build). The `$app/server`-dependent resolvers live\n * in `remote-functions.ts`; this module only deals in `Exit`s.\n */\n\nimport type { InvalidField } from \"@sveltejs/kit\";\nimport { Cause, type Effect, Exit } from \"effect\";\nimport type { ErrorTranslator } from \"../request-runtime.js\";\nimport { SvelteKit } from \"../kit.js\";\n\n/** The default translator: Kit control-flow errors through, anything else a 500. */\nexport const defaultTranslate: ErrorTranslator = SvelteKit.translate;\n\n/**\n * Maps a remote *form* handler's failure into SvelteKit's field issues, given\n * the form's parsed `data` and the `issue` helper. It may call `invalid()` so a\n * structured/nested validation error drives field-level invalidation instead of\n * a generic failure. Receives the squashed handler failure.\n */\nexport type FormErrorMapper = (\n error: unknown,\n ctx: { readonly issue: InvalidField<any>; readonly data: unknown },\n) => never;\n\n/** Runs a remote handler's effect and settles it (value or thrown via translator). */\nexport type Runner = <A>(effect: Effect.Effect<A, unknown, any>) => Promise<A>;\n\n/** Like {@link Runner}, but with the form's `issue` / `data` for error interop. */\nexport type FormRunner = <A>(\n effect: Effect.Effect<A, unknown, any>,\n ctx: { readonly issue: InvalidField<any>; readonly data: unknown },\n) => Promise<A>;\n\n/** Runners that execute a remote-function handler's Effect on a request runtime, as `runRemote` returns them. */\nexport interface RunHelpers {\n readonly run: Runner;\n readonly runForm: FormRunner;\n}\n\n/** How to obtain an `Exit` for the current request, plus optional teardown. */\nexport type ExitResolver = () => {\n readonly runExit: <A>(effect: Effect.Effect<A, unknown, any>) => Promise<Exit.Exit<A, unknown>>;\n readonly dispose?: () => void;\n};\n\n/** Build the `run` / `runForm` helpers from an exit resolver and a translator. */\nexport const makeRunHelpers = (\n resolve: ExitResolver,\n translate: ErrorTranslator,\n formError?: FormErrorMapper,\n): RunHelpers => {\n const run: Runner = (effect) => {\n const { runExit, dispose } = resolve();\n return runExit(effect).then((exit) => {\n try {\n return Exit.isSuccess(exit) ? exit.value : translate(exit.cause);\n } finally {\n dispose?.();\n }\n });\n };\n const runForm: FormRunner = (effect, ctx) => {\n const { runExit, dispose } = resolve();\n return runExit(effect).then((exit) => {\n try {\n if (Exit.isSuccess(exit)) return exit.value;\n return formError ? formError(Cause.squash(exit.cause), ctx) : translate(exit.cause);\n } finally {\n dispose?.();\n }\n });\n };\n return { run, runForm };\n};\n"],"mappings":";;;;AAaA,MAAa,mBAAoC,UAAU;;AAmC3D,MAAa,kBACX,SACA,WACA,cACe;CACf,MAAM,OAAe,WAAW;EAC9B,MAAM,EAAE,SAAS,YAAY,QAAQ;EACrC,OAAO,QAAQ,MAAM,CAAC,CAAC,MAAM,SAAS;GACpC,IAAI;IACF,OAAO,KAAK,UAAU,IAAI,IAAI,KAAK,QAAQ,UAAU,KAAK,KAAK;GACjE,UAAU;IACR,UAAU;GACZ;EACF,CAAC;CACH;CACA,MAAM,WAAuB,QAAQ,QAAQ;EAC3C,MAAM,EAAE,SAAS,YAAY,QAAQ;EACrC,OAAO,QAAQ,MAAM,CAAC,CAAC,MAAM,SAAS;GACpC,IAAI;IACF,IAAI,KAAK,UAAU,IAAI,GAAG,OAAO,KAAK;IACtC,OAAO,YAAY,UAAU,MAAM,OAAO,KAAK,KAAK,GAAG,GAAG,IAAI,UAAU,KAAK,KAAK;GACpF,UAAU;IACR,UAAU;GACZ;EACF,CAAC;CACH;CACA,OAAO;EAAE;EAAK;CAAQ;AACxB"}
1
+ {"version":3,"file":"remote-run.js","names":[],"sources":["../../src/internal/remote-run.ts"],"sourcesContent":["/**\n * Run/settle helpers for the remote-function wrappers, factored out so they can\n * be unit-tested without importing `$app/server` (a SvelteKit virtual module\n * unavailable outside an app build). The `$app/server`-dependent resolvers live\n * in `remote-functions.ts`; this module only deals in `Exit`s.\n */\n\nimport type { RemoteFormInvalidField as InvalidField } from \"$app/server\";\nimport { Cause, type Effect, Exit } from \"effect\";\nimport type { ErrorTranslator } from \"../request-runtime.js\";\nimport { SvelteKit } from \"../kit.js\";\n\n/** The default translator: Kit control-flow errors through, anything else a 500. */\nexport const defaultTranslate: ErrorTranslator = SvelteKit.translate;\n\n/**\n * Maps a remote *form* handler's failure into SvelteKit's field issues, given\n * the form's parsed `data` and the `issue` helper. It may call `invalid()` so a\n * structured/nested validation error drives field-level invalidation instead of\n * a generic failure. Receives the squashed handler failure.\n */\nexport type FormErrorMapper = (\n error: unknown,\n ctx: { readonly issue: InvalidField<any>; readonly data: unknown },\n) => never;\n\n/** Runs a remote handler's effect and settles it (value or thrown via translator). */\nexport type Runner = <A>(effect: Effect.Effect<A, unknown, any>) => Promise<A>;\n\n/** Like {@link Runner}, but with the form's `issue` / `data` for error interop. */\nexport type FormRunner = <A>(\n effect: Effect.Effect<A, unknown, any>,\n ctx: { readonly issue: InvalidField<any>; readonly data: unknown },\n) => Promise<A>;\n\n/** Runners that execute a remote-function handler's Effect on a request runtime, as `runRemote` returns them. */\nexport interface RunHelpers {\n readonly run: Runner;\n readonly runForm: FormRunner;\n}\n\n/** How to obtain an `Exit` for the current request, plus optional teardown. */\nexport type ExitResolver = () => {\n readonly runExit: <A>(effect: Effect.Effect<A, unknown, any>) => Promise<Exit.Exit<A, unknown>>;\n readonly dispose?: () => void;\n};\n\n/** Build the `run` / `runForm` helpers from an exit resolver and a translator. */\nexport const makeRunHelpers = (\n resolve: ExitResolver,\n translate: ErrorTranslator,\n formError?: FormErrorMapper,\n): RunHelpers => {\n const run: Runner = (effect) => {\n const { runExit, dispose } = resolve();\n return runExit(effect).then((exit) => {\n try {\n return Exit.isSuccess(exit) ? exit.value : translate(exit.cause);\n } finally {\n dispose?.();\n }\n });\n };\n const runForm: FormRunner = (effect, ctx) => {\n const { runExit, dispose } = resolve();\n return runExit(effect).then((exit) => {\n try {\n if (Exit.isSuccess(exit)) return exit.value;\n return formError ? formError(Cause.squash(exit.cause), ctx) : translate(exit.cause);\n } finally {\n dispose?.();\n }\n });\n };\n return { run, runForm };\n};\n"],"mappings":";;;;AAaA,MAAa,mBAAoC,UAAU;;AAmC3D,MAAa,kBACX,SACA,WACA,cACe;CACf,MAAM,OAAe,WAAW;EAC9B,MAAM,EAAE,SAAS,YAAY,QAAQ;EACrC,OAAO,QAAQ,MAAM,CAAC,CAAC,MAAM,SAAS;GACpC,IAAI;IACF,OAAO,KAAK,UAAU,IAAI,IAAI,KAAK,QAAQ,UAAU,KAAK,KAAK;GACjE,UAAU;IACR,UAAU;GACZ;EACF,CAAC;CACH;CACA,MAAM,WAAuB,QAAQ,QAAQ;EAC3C,MAAM,EAAE,SAAS,YAAY,QAAQ;EACrC,OAAO,QAAQ,MAAM,CAAC,CAAC,MAAM,SAAS;GACpC,IAAI;IACF,IAAI,KAAK,UAAU,IAAI,GAAG,OAAO,KAAK;IACtC,OAAO,YAAY,UAAU,MAAM,OAAO,KAAK,KAAK,GAAG,GAAG,IAAI,UAAU,KAAK,KAAK;GACpF,UAAU;IACR,UAAU;GACZ;EACF,CAAC;CACH;CACA,OAAO;EAAE;EAAK;CAAQ;AACxB"}
package/dist/kit.js CHANGED
@@ -1,6 +1,6 @@
1
- import { causeToThrowable } from "./internal/error.js";
1
+ import { causeToThrowable, throwKitError } from "./internal/error.js";
2
2
  import { Cause, Effect } from "effect";
3
- import { error, fail, redirect } from "@sveltejs/kit";
3
+ import { fail, redirect } from "@sveltejs/kit";
4
4
  //#region src/kit.ts
5
5
  /**
6
6
  * Effect-native SvelteKit control-flow errors and a turnkey boundary translator.
@@ -93,7 +93,7 @@ var KitActionFailure = class extends Error {
93
93
  const baseTranslate = (cause) => {
94
94
  const squashed = Cause.squash(cause);
95
95
  if (squashed instanceof KitRedirect) redirect(squashed.status, squashed.location);
96
- if (squashed instanceof KitError) error(squashed.status, squashed.body);
96
+ if (squashed instanceof KitError) throwKitError(squashed.status, squashed.body);
97
97
  if (squashed instanceof KitActionFailure) return fail(squashed.status, squashed.data);
98
98
  throw causeToThrowable(cause);
99
99
  };
package/dist/kit.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"kit.js","names":["kitFail"],"sources":["../src/kit.ts"],"sourcesContent":["/**\n * Effect-native SvelteKit control-flow errors and a turnkey boundary translator.\n *\n * Every server consumer previously needed to hand-roll their own `translateError`\n * that mapped domain errors → `redirect()` / `error()` / `fail()`. This module\n * ships the catalogue those consumers all reinvented:\n *\n * - {@link KitRedirect}, {@link KitError}, {@link KitActionFailure} — tagged\n * Effect failure types for each SvelteKit control-flow call.\n * - {@link SvelteKit.redirect}, {@link SvelteKit.error}, {@link SvelteKit.fail}\n * — helpers that `yield*` a typed failure instead of throwing.\n * - {@link SvelteKit.translate} — the base `ErrorTranslator` that converts those\n * failures to the appropriate SvelteKit call at the request boundary.\n * - {@link SvelteKit.makeTranslator} — compose `translate` with your own\n * domain-error cases (consumer cases run first).\n *\n * @example\n * ```ts\n * import { SvelteKit, makeRuntimeAdapter, RequestRuntime } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Effect } from \"effect\";\n *\n * // Yield kit errors instead of throwing:\n * const load = serverLoad(() =>\n * Effect.gen(function* () {\n * const user = yield* getUser;\n * if (!user) yield* SvelteKit.redirect(303, \"/login\");\n * if (!user.active) yield* SvelteKit.error(403, \"Account disabled\");\n * return { user };\n * })\n * );\n *\n * // Compose with your own domain errors:\n * import { error } from \"@sveltejs/kit\";\n * const { serverLoad } = makeRuntimeAdapter(\n * RequestRuntime.fromLayer(AppLayer),\n * {\n * translateError: SvelteKit.makeTranslator([\n * (e) => { if (e instanceof NotFound) error(404, \"Not found\"); },\n * ]),\n * },\n * );\n * ```\n */\n\nimport { error as kitError, fail as kitFail, redirect as kitRedirect } from \"@sveltejs/kit\";\nimport { Cause, Effect } from \"effect\";\nimport { causeToThrowable } from \"./internal/error.js\";\n\n// ─── Tagged error classes ────────────────────────────────────────────────────\n\n/**\n * An Effect-native redirect. Yield via {@link SvelteKit.redirect}; translated\n * at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitRedirect extends Error {\n readonly _tag = \"KitRedirect\" as const;\n\n constructor(\n readonly status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308,\n readonly location: string | URL,\n ) {\n super(`Redirect to ${String(location)}`);\n this.name = \"KitRedirect\";\n }\n}\n\n/**\n * An Effect-native HTTP error. Yield via {@link SvelteKit.error}; translated\n * at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitError extends Error {\n readonly _tag = \"KitError\" as const;\n\n constructor(\n readonly status: number,\n readonly body?: string | Record<string, unknown>,\n ) {\n super(`HTTP ${status}`);\n this.name = \"KitError\";\n }\n}\n\n/**\n * An Effect-native form-action failure. Yield via {@link SvelteKit.fail};\n * translated at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitActionFailure<\n T extends Record<string, unknown> = Record<string, unknown>,\n> extends Error {\n readonly _tag = \"KitActionFailure\" as const;\n\n constructor(\n readonly status: number,\n readonly data: T,\n ) {\n super(`Action failure ${status}`);\n this.name = \"KitActionFailure\";\n }\n}\n\n// ─── Translator types ────────────────────────────────────────────────────────\n\n/**\n * A single domain-error case for {@link SvelteKit.makeTranslator}.\n *\n * Receives the squashed error value. Throw (e.g. `error()` / `redirect()`) to\n * handle the case; return normally to pass through to the next case.\n */\nexport type KitTranslatorCase = (error: unknown) => undefined | void;\n\n/**\n * A boundary translator: turn a failed `Cause` into thrown SvelteKit control\n * flow or an `ActionFailure` return value.\n *\n * The Kit base translator ({@link SvelteKit.translate}) handles\n * {@link KitRedirect}, {@link KitError}, and {@link KitActionFailure}. Build a\n * custom translator via {@link SvelteKit.makeTranslator}.\n */\nexport type KitErrorTranslator = (cause: Cause.Cause<unknown>) => never;\n\n// ─── Base translator ─────────────────────────────────────────────────────────\n\nconst baseTranslate: KitErrorTranslator = (cause) => {\n const squashed = Cause.squash(cause);\n\n if (squashed instanceof KitRedirect) {\n // redirect() is typed as () => never — throws internally.\n kitRedirect(squashed.status, squashed.location as string);\n }\n\n if (squashed instanceof KitError) {\n // error() is typed as () => never — throws internally.\n kitError(squashed.status as Parameters<typeof kitError>[0], squashed.body as any);\n }\n\n if (squashed instanceof KitActionFailure) {\n // fail() returns an ActionFailure (doesn't throw). SvelteKit detects it as\n // the action's return value. Typed as never to satisfy ErrorTranslator while\n // allowing makeRuntimeAdapter's `return translateError(cause)` to propagate\n // the ActionFailure to SvelteKit correctly at runtime.\n return kitFail(squashed.status, squashed.data) as never;\n }\n\n throw causeToThrowable(cause);\n};\n\n// ─── Public namespace ─────────────────────────────────────────────────────────\n\n/**\n * Effect-native SvelteKit control-flow helpers and the default boundary\n * translator.\n *\n * **Error types**: {@link KitRedirect}, {@link KitError}, {@link KitActionFailure}\n * are tagged Effect failures — use them with `Effect.catchTag`, `Match.tag`,\n * and `instanceof` checks.\n *\n * **Default translator**: `SvelteKit.translate` is wired in as the default\n * `translateError` for every server wrapper (`serverLoad`, `action`,\n * `makeRuntimeAdapter`, `RemoteFunction.withRuntime`, etc.).\n */\nexport const SvelteKit = {\n /**\n * Fail with a redirect. Equivalent to SvelteKit's `redirect()` but as an\n * Effect failure instead of a thrown exception.\n *\n * @example\n * ```ts\n * yield* SvelteKit.redirect(303, \"/login\");\n * ```\n */\n redirect: (\n status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308,\n location: string | URL,\n ): Effect.Effect<never, KitRedirect> => Effect.fail(new KitRedirect(status, location)),\n\n /**\n * Fail with an HTTP error. Equivalent to SvelteKit's `error()` but as an\n * Effect failure instead of a thrown exception.\n *\n * @example\n * ```ts\n * yield* SvelteKit.error(404, \"Not found\");\n * yield* SvelteKit.error(403, { message: \"Forbidden\" });\n * ```\n */\n error: (\n status: number,\n body?: string | Record<string, unknown>,\n ): Effect.Effect<never, KitError> => Effect.fail(new KitError(status, body)),\n\n /**\n * Fail with a form-action failure. Equivalent to SvelteKit's `fail()` but as\n * an Effect failure instead of a return value.\n *\n * @example\n * ```ts\n * yield* SvelteKit.fail(422, { email: \"already taken\" });\n * ```\n */\n fail: <T extends Record<string, unknown>>(\n status: number,\n data: T,\n ): Effect.Effect<never, KitActionFailure<T>> => Effect.fail(new KitActionFailure(status, data)),\n\n /**\n * The turnkey boundary translator. Converts {@link KitRedirect} →\n * `redirect()`, {@link KitError} → `error()`, {@link KitActionFailure} →\n * `fail()`, and anything else → `EffectCauseError` (500).\n *\n * This is the default `translateError` for every server wrapper. To extend it\n * with your own domain errors, use {@link SvelteKit.makeTranslator}.\n */\n translate: baseTranslate,\n\n /**\n * Build a custom boundary translator by prepending domain-error cases before\n * the Kit base cases.\n *\n * Each case function receives the squashed error value. Throw (e.g. call\n * `error()` / `redirect()` from `@sveltejs/kit`) to handle the case; return\n * normally to pass through to the next case or the Kit base translator.\n *\n * @example\n * ```ts\n * import { error } from \"@sveltejs/kit\";\n *\n * const translateError = SvelteKit.makeTranslator([\n * (e) => { if (e instanceof NotFound) error(404, \"Not found\"); },\n * (e) => { if (e instanceof Forbidden) error(403, \"Forbidden\"); },\n * ]);\n *\n * const { serverLoad } = makeRuntimeAdapter(\n * RequestRuntime.fromLayer(AppLayer),\n * { translateError },\n * );\n * ```\n */\n makeTranslator:\n (extraCases: ReadonlyArray<KitTranslatorCase>): KitErrorTranslator =>\n (cause) => {\n const squashed = Cause.squash(cause);\n for (const matcher of extraCases) {\n matcher(squashed);\n }\n return baseTranslate(cause);\n },\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,IAAa,cAAb,cAAiC,MAAM;CAI1B;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,UACA;EACA,MAAM,eAAe,OAAO,QAAQ,GAAG;EAH9B,KAAA,SAAA;EACA,KAAA,WAAA;EAGT,KAAK,OAAO;CACd;AACF;;;;;AAMA,IAAa,WAAb,cAA8B,MAAM;CAIvB;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,MACA;EACA,MAAM,QAAQ,QAAQ;EAHb,KAAA,SAAA;EACA,KAAA,OAAA;EAGT,KAAK,OAAO;CACd;AACF;;;;;AAMA,IAAa,mBAAb,cAEU,MAAM;CAIH;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,MACA;EACA,MAAM,kBAAkB,QAAQ;EAHvB,KAAA,SAAA;EACA,KAAA,OAAA;EAGT,KAAK,OAAO;CACd;AACF;AAwBA,MAAM,iBAAqC,UAAU;CACnD,MAAM,WAAW,MAAM,OAAO,KAAK;CAEnC,IAAI,oBAAoB,aAEtB,SAAY,SAAS,QAAQ,SAAS,QAAkB;CAG1D,IAAI,oBAAoB,UAEtB,MAAS,SAAS,QAA0C,SAAS,IAAW;CAGlF,IAAI,oBAAoB,kBAKtB,OAAOA,KAAQ,SAAS,QAAQ,SAAS,IAAI;CAG/C,MAAM,iBAAiB,KAAK;AAC9B;;;;;;;;;;;;;AAgBA,MAAa,YAAY;;;;;;;;;;CAUvB,WACE,QACA,aACsC,OAAO,KAAK,IAAI,YAAY,QAAQ,QAAQ,CAAC;;;;;;;;;;;CAYrF,QACE,QACA,SACmC,OAAO,KAAK,IAAI,SAAS,QAAQ,IAAI,CAAC;;;;;;;;;;CAW3E,OACE,QACA,SAC8C,OAAO,KAAK,IAAI,iBAAiB,QAAQ,IAAI,CAAC;;;;;;;;;CAU9F,WAAW;;;;;;;;;;;;;;;;;;;;;;;;CAyBX,iBACG,gBACA,UAAU;EACT,MAAM,WAAW,MAAM,OAAO,KAAK;EACnC,KAAK,MAAM,WAAW,YACpB,QAAQ,QAAQ;EAElB,OAAO,cAAc,KAAK;CAC5B;AACJ"}
1
+ {"version":3,"file":"kit.js","names":["kitFail"],"sources":["../src/kit.ts"],"sourcesContent":["/**\n * Effect-native SvelteKit control-flow errors and a turnkey boundary translator.\n *\n * Every server consumer previously needed to hand-roll their own `translateError`\n * that mapped domain errors → `redirect()` / `error()` / `fail()`. This module\n * ships the catalogue those consumers all reinvented:\n *\n * - {@link KitRedirect}, {@link KitError}, {@link KitActionFailure} — tagged\n * Effect failure types for each SvelteKit control-flow call.\n * - {@link SvelteKit.redirect}, {@link SvelteKit.error}, {@link SvelteKit.fail}\n * — helpers that `yield*` a typed failure instead of throwing.\n * - {@link SvelteKit.translate} — the base `ErrorTranslator` that converts those\n * failures to the appropriate SvelteKit call at the request boundary.\n * - {@link SvelteKit.makeTranslator} — compose `translate` with your own\n * domain-error cases (consumer cases run first).\n *\n * @example\n * ```ts\n * import { SvelteKit, makeRuntimeAdapter, RequestRuntime } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Effect } from \"effect\";\n *\n * // Yield kit errors instead of throwing:\n * const load = serverLoad(() =>\n * Effect.gen(function* () {\n * const user = yield* getUser;\n * if (!user) yield* SvelteKit.redirect(303, \"/login\");\n * if (!user.active) yield* SvelteKit.error(403, \"Account disabled\");\n * return { user };\n * })\n * );\n *\n * // Compose with your own domain errors:\n * import { error } from \"@sveltejs/kit\";\n * const { serverLoad } = makeRuntimeAdapter(\n * RequestRuntime.fromLayer(AppLayer),\n * {\n * translateError: SvelteKit.makeTranslator([\n * (e) => { if (e instanceof NotFound) error(404, \"Not found\"); },\n * ]),\n * },\n * );\n * ```\n */\n\nimport { fail as kitFail, redirect as kitRedirect } from \"@sveltejs/kit\";\nimport { Cause, Effect } from \"effect\";\nimport { causeToThrowable, throwKitError } from \"./internal/error.js\";\n\n// ─── Tagged error classes ────────────────────────────────────────────────────\n\n/**\n * An Effect-native redirect. Yield via {@link SvelteKit.redirect}; translated\n * at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitRedirect extends Error {\n readonly _tag = \"KitRedirect\" as const;\n\n constructor(\n readonly status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308,\n readonly location: string | URL,\n ) {\n super(`Redirect to ${String(location)}`);\n this.name = \"KitRedirect\";\n }\n}\n\n/**\n * An Effect-native HTTP error. Yield via {@link SvelteKit.error}; translated\n * at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitError extends Error {\n readonly _tag = \"KitError\" as const;\n\n constructor(\n readonly status: number,\n readonly body?: string | Record<string, unknown>,\n ) {\n super(`HTTP ${status}`);\n this.name = \"KitError\";\n }\n}\n\n/**\n * An Effect-native form-action failure. Yield via {@link SvelteKit.fail};\n * translated at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitActionFailure<\n T extends Record<string, unknown> = Record<string, unknown>,\n> extends Error {\n readonly _tag = \"KitActionFailure\" as const;\n\n constructor(\n readonly status: number,\n readonly data: T,\n ) {\n super(`Action failure ${status}`);\n this.name = \"KitActionFailure\";\n }\n}\n\n// ─── Translator types ────────────────────────────────────────────────────────\n\n/**\n * A single domain-error case for {@link SvelteKit.makeTranslator}.\n *\n * Receives the squashed error value. Throw (e.g. `error()` / `redirect()`) to\n * handle the case; return normally to pass through to the next case.\n */\nexport type KitTranslatorCase = (error: unknown) => undefined | void;\n\n/**\n * A boundary translator: turn a failed `Cause` into thrown SvelteKit control\n * flow or an `ActionFailure` return value.\n *\n * The Kit base translator ({@link SvelteKit.translate}) handles\n * {@link KitRedirect}, {@link KitError}, and {@link KitActionFailure}. Build a\n * custom translator via {@link SvelteKit.makeTranslator}.\n */\nexport type KitErrorTranslator = (cause: Cause.Cause<unknown>) => never;\n\n// ─── Base translator ─────────────────────────────────────────────────────────\n\nconst baseTranslate: KitErrorTranslator = (cause) => {\n const squashed = Cause.squash(cause);\n\n if (squashed instanceof KitRedirect) {\n // redirect() is typed as () => never — throws internally.\n kitRedirect(squashed.status, squashed.location as string);\n }\n\n if (squashed instanceof KitError) {\n // throwKitError() is typed as never: it always throws Kit's HttpError.\n throwKitError(squashed.status, squashed.body);\n }\n\n if (squashed instanceof KitActionFailure) {\n // fail() returns an ActionFailure (doesn't throw). SvelteKit detects it as\n // the action's return value. Typed as never to satisfy ErrorTranslator while\n // allowing makeRuntimeAdapter's `return translateError(cause)` to propagate\n // the ActionFailure to SvelteKit correctly at runtime.\n return kitFail(squashed.status, squashed.data) as never;\n }\n\n throw causeToThrowable(cause);\n};\n\n// ─── Public namespace ─────────────────────────────────────────────────────────\n\n/**\n * Effect-native SvelteKit control-flow helpers and the default boundary\n * translator.\n *\n * **Error types**: {@link KitRedirect}, {@link KitError}, {@link KitActionFailure}\n * are tagged Effect failures — use them with `Effect.catchTag`, `Match.tag`,\n * and `instanceof` checks.\n *\n * **Default translator**: `SvelteKit.translate` is wired in as the default\n * `translateError` for every server wrapper (`serverLoad`, `action`,\n * `makeRuntimeAdapter`, `RemoteFunction.withRuntime`, etc.).\n */\nexport const SvelteKit = {\n /**\n * Fail with a redirect. Equivalent to SvelteKit's `redirect()` but as an\n * Effect failure instead of a thrown exception.\n *\n * @example\n * ```ts\n * yield* SvelteKit.redirect(303, \"/login\");\n * ```\n */\n redirect: (\n status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308,\n location: string | URL,\n ): Effect.Effect<never, KitRedirect> => Effect.fail(new KitRedirect(status, location)),\n\n /**\n * Fail with an HTTP error. Equivalent to SvelteKit's `error()` but as an\n * Effect failure instead of a thrown exception.\n *\n * @example\n * ```ts\n * yield* SvelteKit.error(404, \"Not found\");\n * yield* SvelteKit.error(403, { message: \"Forbidden\" });\n * ```\n */\n error: (\n status: number,\n body?: string | Record<string, unknown>,\n ): Effect.Effect<never, KitError> => Effect.fail(new KitError(status, body)),\n\n /**\n * Fail with a form-action failure. Equivalent to SvelteKit's `fail()` but as\n * an Effect failure instead of a return value.\n *\n * @example\n * ```ts\n * yield* SvelteKit.fail(422, { email: \"already taken\" });\n * ```\n */\n fail: <T extends Record<string, unknown>>(\n status: number,\n data: T,\n ): Effect.Effect<never, KitActionFailure<T>> => Effect.fail(new KitActionFailure(status, data)),\n\n /**\n * The turnkey boundary translator. Converts {@link KitRedirect} →\n * `redirect()`, {@link KitError} → `error()`, {@link KitActionFailure} →\n * `fail()`, and anything else → `EffectCauseError` (500).\n *\n * This is the default `translateError` for every server wrapper. To extend it\n * with your own domain errors, use {@link SvelteKit.makeTranslator}.\n */\n translate: baseTranslate,\n\n /**\n * Build a custom boundary translator by prepending domain-error cases before\n * the Kit base cases.\n *\n * Each case function receives the squashed error value. Throw (e.g. call\n * `error()` / `redirect()` from `@sveltejs/kit`) to handle the case; return\n * normally to pass through to the next case or the Kit base translator.\n *\n * @example\n * ```ts\n * import { error } from \"@sveltejs/kit\";\n *\n * const translateError = SvelteKit.makeTranslator([\n * (e) => { if (e instanceof NotFound) error(404, \"Not found\"); },\n * (e) => { if (e instanceof Forbidden) error(403, \"Forbidden\"); },\n * ]);\n *\n * const { serverLoad } = makeRuntimeAdapter(\n * RequestRuntime.fromLayer(AppLayer),\n * { translateError },\n * );\n * ```\n */\n makeTranslator:\n (extraCases: ReadonlyArray<KitTranslatorCase>): KitErrorTranslator =>\n (cause) => {\n const squashed = Cause.squash(cause);\n for (const matcher of extraCases) {\n matcher(squashed);\n }\n return baseTranslate(cause);\n },\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,IAAa,cAAb,cAAiC,MAAM;CAI1B;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,UACA;EACA,MAAM,eAAe,OAAO,QAAQ,GAAG;EAH9B,KAAA,SAAA;EACA,KAAA,WAAA;EAGT,KAAK,OAAO;CACd;AACF;;;;;AAMA,IAAa,WAAb,cAA8B,MAAM;CAIvB;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,MACA;EACA,MAAM,QAAQ,QAAQ;EAHb,KAAA,SAAA;EACA,KAAA,OAAA;EAGT,KAAK,OAAO;CACd;AACF;;;;;AAMA,IAAa,mBAAb,cAEU,MAAM;CAIH;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,MACA;EACA,MAAM,kBAAkB,QAAQ;EAHvB,KAAA,SAAA;EACA,KAAA,OAAA;EAGT,KAAK,OAAO;CACd;AACF;AAwBA,MAAM,iBAAqC,UAAU;CACnD,MAAM,WAAW,MAAM,OAAO,KAAK;CAEnC,IAAI,oBAAoB,aAEtB,SAAY,SAAS,QAAQ,SAAS,QAAkB;CAG1D,IAAI,oBAAoB,UAEtB,cAAc,SAAS,QAAQ,SAAS,IAAI;CAG9C,IAAI,oBAAoB,kBAKtB,OAAOA,KAAQ,SAAS,QAAQ,SAAS,IAAI;CAG/C,MAAM,iBAAiB,KAAK;AAC9B;;;;;;;;;;;;;AAgBA,MAAa,YAAY;;;;;;;;;;CAUvB,WACE,QACA,aACsC,OAAO,KAAK,IAAI,YAAY,QAAQ,QAAQ,CAAC;;;;;;;;;;;CAYrF,QACE,QACA,SACmC,OAAO,KAAK,IAAI,SAAS,QAAQ,IAAI,CAAC;;;;;;;;;;CAW3E,OACE,QACA,SAC8C,OAAO,KAAK,IAAI,iBAAiB,QAAQ,IAAI,CAAC;;;;;;;;;CAU9F,WAAW;;;;;;;;;;;;;;;;;;;;;;;;CAyBX,iBACG,gBACA,UAAU;EACT,MAAM,WAAW,MAAM,OAAO,KAAK;EACnC,KAAK,MAAM,WAAW,YACpB,QAAQ,QAAQ;EAElB,OAAO,cAAc,KAAK;CAC5B;AACJ"}
@@ -3,7 +3,7 @@ import { ErrorTranslator, RequestRuntimeProvider } from "./request-runtime.js";
3
3
  import { FormErrorMapper } from "./internal/remote-run.js";
4
4
  import { Effect, Schema } from "effect";
5
5
  import * as HttpClient from "effect/http/HttpClient";
6
- import { InvalidField, RemoteCommand, RemoteForm, RemoteFormInput, RemotePrerenderFunction, RemoteQueryFunction } from "@sveltejs/kit";
6
+ import { RemoteCommand, RemoteForm, RemoteFormInput, RemoteFormInvalidField, RemotePrerenderFunction, RemoteQueryFunction } from "$app/server";
7
7
  import { StandardSchemaV1 } from "@standard-schema/spec";
8
8
  //#region src/remote-functions.d.ts
9
9
  type SvelteKitEffectEnv = HttpClient.HttpClient | SvelteKitRequestEvent;
@@ -29,9 +29,9 @@ interface QueryLiveFn<Env> {
29
29
  /** The public shape of the `form` helper, parameterised by its handler env. */
30
30
  interface FormFn<Env> {
31
31
  <Output>(fn: () => Effect.Effect<Output, unknown, Env>): RemoteForm<void, Output>;
32
- <Input, Output>(validate: "unchecked", fn: (data: Input, issue: InvalidField<Input & RemoteFormInput>) => Effect.Effect<Output, unknown, Env>): RemoteForm<Input & RemoteFormInput, Output>;
33
- <Sch extends StandardSchemaV1, Output>(validate: Sch, fn: (data: StandardSchemaV1.InferOutput<Sch>, issue: InvalidField<StandardSchemaV1.InferInput<Sch> & RemoteFormInput>) => Effect.Effect<Output, unknown, Env>): RemoteForm<StandardSchemaV1.InferInput<Sch> & RemoteFormInput, Output>;
34
- <S extends Schema.Top, Output>(validate: S, fn: (data: S["Type"], issue: InvalidField<S["Encoded"] & RemoteFormInput>) => Effect.Effect<Output, unknown, Env>): RemoteForm<S["Encoded"] & RemoteFormInput, Output>;
32
+ <Input, Output>(validate: "unchecked", fn: (data: Input, issue: RemoteFormInvalidField<Input & RemoteFormInput>) => Effect.Effect<Output, unknown, Env>): RemoteForm<Input & RemoteFormInput, Output>;
33
+ <Sch extends StandardSchemaV1, Output>(validate: Sch, fn: (data: StandardSchemaV1.InferOutput<Sch>, issue: RemoteFormInvalidField<StandardSchemaV1.InferInput<Sch> & RemoteFormInput>) => Effect.Effect<Output, unknown, Env>): RemoteForm<StandardSchemaV1.InferInput<Sch> & RemoteFormInput, Output>;
34
+ <S extends Schema.Top, Output>(validate: S, fn: (data: S["Type"], issue: RemoteFormInvalidField<S["Encoded"] & RemoteFormInput>) => Effect.Effect<Output, unknown, Env>): RemoteForm<S["Encoded"] & RemoteFormInput, Output>;
35
35
  }
36
36
  /** The public shape of the `command` helper, parameterised by its handler env. */
37
37
  interface CommandFn<Env> {
@@ -1 +1 @@
1
- {"version":3,"file":"remote-functions.js","names":["isBareHandlerValue"],"sources":["../src/remote-functions.ts"],"sourcesContent":["// NOTE: This module builds the `query` / `form` / `command` / `prerender`\n// *factories* that consumers call inside their own `*.remote.ts` files — it is\n// NOT itself a SvelteKit remote module, and its exports (e.g. `RemoteFunction`)\n// are deliberately not remote functions. Its filename must therefore never match\n// SvelteKit's remote-module matcher `/[/.]remote(\\.[^/]+)+$/`\n// (kit `src/exports/vite/utils.js`), or kit's build-time validation will reject\n// the built file with \"all exports from this file must be remote functions\".\n// That is why this is `remote-functions.ts` and never `remote.server.ts` /\n// `*.remote.ts`. See `tests/remote-module-naming.test.ts` for the guard.\nimport * as AppServer from \"$app/server\";\nimport type {\n RemoteCommand,\n RemoteForm,\n RemoteFormInput,\n RemotePrerenderFunction,\n RemoteQueryFunction,\n InvalidField,\n} from \"@sveltejs/kit\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport { Effect, type Schema } from \"effect\";\nimport { SvelteKitRuntime, SvelteKitRequestEvent } from \"./runtime.js\";\nimport {\n isBareHandler as isBareHandlerValue,\n toStandardValidator,\n} from \"./internal/remote-validators.js\";\nimport {\n defaultTranslate,\n makeRunHelpers,\n type FormErrorMapper,\n type RunHelpers,\n type Runner,\n} from \"./internal/remote-run.js\";\nimport type { ErrorTranslator, RequestRuntimeProvider } from \"./request-runtime.js\";\n\nexport type { FormErrorMapper } from \"./internal/remote-run.js\";\n\ntype SvelteKitEffectEnv = HttpClient.HttpClient | SvelteKitRequestEvent;\n\n/** The default helpers: a fresh SvelteKit per-request runtime, passthrough translation. */\nconst defaultHelpers: RunHelpers = makeRunHelpers(() => {\n const event = AppServer.getRequestEvent();\n return { runExit: (effect) => SvelteKitRuntime.forRequest(event).runPromiseExit(effect) };\n}, defaultTranslate);\n\n/** Build helpers from a {@link RequestRuntimeProvider}, translator, and form-error mapper. */\nconst helpersFromProvider = (\n provider: RequestRuntimeProvider<any, any>,\n translate: ErrorTranslator,\n formError?: FormErrorMapper,\n): RunHelpers =>\n makeRunHelpers(\n () => {\n const event = AppServer.getRequestEvent();\n return {\n runExit: (effect) => provider.run(event).runPromiseExit(effect),\n dispose: () => provider.disposeAfterResponse?.(event),\n };\n },\n translate,\n formError,\n );\n\nfunction unavailable(name: string): never {\n throw new Error(\n `${name} is not available in the installed SvelteKit version. Update @sveltejs/kit to use this API.`,\n );\n}\n\ntype EffectHandler<Env> = (arg: unknown) => Effect.Effect<unknown, unknown, Env>;\ntype EffectFormHandler<Env> = (\n data: unknown,\n issue: unknown,\n) => Effect.Effect<unknown, unknown, Env>;\ntype EffectVoidHandler<Env> = () => Effect.Effect<unknown, unknown, Env>;\n\n/** True when the argument is the no-validation handler overload (typed narrowing). */\nconst isBareHandler = <Env>(value: unknown): value is EffectVoidHandler<Env> =>\n isBareHandlerValue(value);\n\n/** The public shape of the `query` helper, parameterised by its handler env. */\nexport interface QueryFn<Env> {\n <Output>(fn: () => Effect.Effect<Output, unknown, Env>): RemoteQueryFunction<void, Output>;\n <Input, Output>(\n validate: \"unchecked\",\n fn: (arg: Input) => Effect.Effect<Output, unknown, Env>,\n ): RemoteQueryFunction<Input, Output>;\n <Sch extends StandardSchemaV1, Output>(\n schema: Sch,\n fn: (arg: StandardSchemaV1.InferOutput<Sch>) => Effect.Effect<Output, unknown, Env>,\n ): RemoteQueryFunction<StandardSchemaV1.InferInput<Sch>, Output>;\n <S extends Schema.Top, Output>(\n schema: S,\n fn: (arg: S[\"Type\"]) => Effect.Effect<Output, unknown, Env>,\n ): RemoteQueryFunction<S[\"Encoded\"], Output>;\n}\n\nconst makeQuery = <Env>(run: Runner): QueryFn<Env> =>\n ((arg1: unknown, arg2?: (arg: unknown) => Effect.Effect<unknown, unknown, Env>): any => {\n if (isBareHandler<Env>(arg1)) {\n const handler = arg1;\n return AppServer.query(() => run(handler()));\n }\n\n if (!arg2) {\n throw new Error(\"query requires a handler function when a schema is provided\");\n }\n\n return AppServer.query(toStandardValidator(arg1) as \"unchecked\", (arg: unknown) =>\n run(arg2(arg)),\n );\n }) as QueryFn<Env>;\n\n/** The public shape of `query.batch`, parameterised by its handler env. */\nexport interface QueryBatchFn<Env> {\n <Input, Output>(\n validate: \"unchecked\",\n fn: (args: Input[]) => Effect.Effect<(arg: Input, idx: number) => Output, unknown, Env>,\n ): RemoteQueryFunction<Input, Output>;\n <Sch extends StandardSchemaV1, Output>(\n schema: Sch,\n fn: (\n args: StandardSchemaV1.InferOutput<Sch>[],\n ) => Effect.Effect<\n (arg: StandardSchemaV1.InferOutput<Sch>, idx: number) => Output,\n unknown,\n Env\n >,\n ): RemoteQueryFunction<StandardSchemaV1.InferInput<Sch>, Output>;\n <S extends Schema.Top, Output>(\n schema: S,\n fn: (args: S[\"Type\"][]) => Effect.Effect<(arg: S[\"Type\"], idx: number) => Output, unknown, Env>,\n ): RemoteQueryFunction<S[\"Encoded\"], Output>;\n}\n\nconst makeQueryBatch = <Env>(run: Runner): QueryBatchFn<Env> =>\n ((\n validate: unknown,\n fn: (args: unknown[]) => Effect.Effect<(arg: unknown, idx: number) => unknown, unknown, Env>,\n ): any =>\n AppServer.query.batch(toStandardValidator(validate) as \"unchecked\", (args: unknown[]) =>\n run(fn(args)),\n )) as QueryBatchFn<Env>;\n\ntype QueryLiveFactory = (\n validate: unknown,\n fn: (arg: unknown) => Promise<AsyncIterable<unknown>> | AsyncIterable<unknown>,\n) => unknown;\n\ntype QueryWithCompat = typeof AppServer.query & {\n live?: QueryLiveFactory;\n};\n\ntype AppServerWithCompat = typeof AppServer & {\n requested?: (...args: unknown[]) => unknown;\n};\n\nconst appServerCompat = AppServer as AppServerWithCompat;\nconst queryCompat = AppServer.query as QueryWithCompat;\n\nfunction getQueryLive(): QueryLiveFactory {\n const live = queryCompat.live;\n\n if (typeof live !== \"function\") {\n unavailable(\"query.live\");\n }\n\n return live;\n}\n\nfunction getRequested(): (...args: unknown[]) => unknown {\n const requestedFn = appServerCompat.requested;\n\n if (typeof requestedFn !== \"function\") {\n unavailable(\"requested\");\n }\n\n return requestedFn;\n}\n\n/** The public shape of `query.live`, parameterised by its handler env. */\nexport interface QueryLiveFn<Env> {\n <Input, Output>(\n validate: \"unchecked\",\n fn: (arg: Input) => Effect.Effect<AsyncIterable<Output>, unknown, Env>,\n ): RemoteQueryFunction<Input, Output>;\n <Sch extends StandardSchemaV1, Output>(\n schema: Sch,\n fn: (\n arg: StandardSchemaV1.InferOutput<Sch>,\n ) => Effect.Effect<AsyncIterable<Output>, unknown, Env>,\n ): RemoteQueryFunction<StandardSchemaV1.InferInput<Sch>, Output>;\n <S extends Schema.Top, Output>(\n schema: S,\n fn: (arg: S[\"Type\"]) => Effect.Effect<AsyncIterable<Output>, unknown, Env>,\n ): RemoteQueryFunction<S[\"Encoded\"], Output>;\n}\n\nconst makeQueryLive = <Env>(run: Runner): QueryLiveFn<Env> =>\n ((\n validate: unknown,\n fn: (arg: unknown) => Effect.Effect<AsyncIterable<unknown>, unknown, Env>,\n ): any => {\n const live = getQueryLive();\n return live(toStandardValidator(validate), (arg) => run(fn(arg)));\n }) as QueryLiveFn<Env>;\n\n/** The public shape of the `form` helper, parameterised by its handler env. */\nexport interface FormFn<Env> {\n <Output>(fn: () => Effect.Effect<Output, unknown, Env>): RemoteForm<void, Output>;\n <Input, Output>(\n validate: \"unchecked\",\n fn: (\n data: Input,\n issue: InvalidField<Input & RemoteFormInput>,\n ) => Effect.Effect<Output, unknown, Env>,\n ): RemoteForm<Input & RemoteFormInput, Output>;\n <Sch extends StandardSchemaV1, Output>(\n validate: Sch,\n fn: (\n data: StandardSchemaV1.InferOutput<Sch>,\n issue: InvalidField<StandardSchemaV1.InferInput<Sch> & RemoteFormInput>,\n ) => Effect.Effect<Output, unknown, Env>,\n ): RemoteForm<StandardSchemaV1.InferInput<Sch> & RemoteFormInput, Output>;\n <S extends Schema.Top, Output>(\n validate: S,\n fn: (\n data: S[\"Type\"],\n issue: InvalidField<S[\"Encoded\"] & RemoteFormInput>,\n ) => Effect.Effect<Output, unknown, Env>,\n ): RemoteForm<S[\"Encoded\"] & RemoteFormInput, Output>;\n}\n\nconst makeForm = <Env>(helpers: RunHelpers): FormFn<Env> =>\n ((arg1: unknown, arg2?: unknown): any => {\n if (isBareHandler<Env>(arg1)) {\n const handler = arg1;\n return AppServer.form(() => helpers.run(handler()));\n }\n\n if (!arg2) {\n throw new Error(\"form requires a handler function when a schema is provided\");\n }\n\n return AppServer.form(\n toStandardValidator(arg1) as \"unchecked\",\n (data: unknown, issue: unknown) =>\n helpers.runForm((arg2 as EffectFormHandler<Env>)(data, issue), {\n issue: issue as InvalidField<any>,\n data,\n }),\n );\n }) as FormFn<Env>;\n\n/** The public shape of the `command` helper, parameterised by its handler env. */\nexport interface CommandFn<Env> {\n <Output>(fn: () => Effect.Effect<Output, unknown, Env>): RemoteCommand<void, Output>;\n <Input, Output>(\n validate: \"unchecked\",\n fn: (arg: Input) => Effect.Effect<Output, unknown, Env>,\n ): RemoteCommand<Input, Output>;\n <Sch extends StandardSchemaV1, Output>(\n validate: Sch,\n fn: (arg: StandardSchemaV1.InferOutput<Sch>) => Effect.Effect<Output, unknown, Env>,\n ): RemoteCommand<StandardSchemaV1.InferInput<Sch>, Output>;\n <S extends Schema.Top, Output>(\n validate: S,\n fn: (arg: S[\"Type\"]) => Effect.Effect<Output, unknown, Env>,\n ): RemoteCommand<S[\"Encoded\"], Output>;\n}\n\nconst makeCommand = <Env>(run: Runner): CommandFn<Env> =>\n ((arg1: unknown, arg2?: (arg: unknown) => Effect.Effect<unknown, unknown, Env>): any => {\n if (isBareHandler<Env>(arg1)) {\n const handler = arg1;\n return AppServer.command(() => run(handler()));\n }\n\n if (!arg2) {\n throw new Error(\"command requires a handler function when a schema is provided\");\n }\n\n return AppServer.command(toStandardValidator(arg1) as \"unchecked\", (arg: unknown) =>\n run(arg2(arg)),\n );\n }) as CommandFn<Env>;\n\n/** The public shape of the `prerender` helper, parameterised by its handler env. */\nexport interface PrerenderFn<Env> {\n <Output>(\n fn: () => Effect.Effect<Output, unknown, Env>,\n options?: {\n inputs?: () => Promise<void[]> | void[];\n dynamic?: boolean;\n },\n ): RemotePrerenderFunction<void, Output>;\n <Input, Output>(\n validate: \"unchecked\",\n fn: (arg: Input) => Effect.Effect<Output, unknown, Env>,\n options?: {\n inputs?: () => Promise<Input[]> | Input[];\n dynamic?: boolean;\n },\n ): RemotePrerenderFunction<Input, Output>;\n <Sch extends StandardSchemaV1, Output>(\n schema: Sch,\n fn: (arg: StandardSchemaV1.InferOutput<Sch>) => Effect.Effect<Output, unknown, Env>,\n options?: {\n inputs?: () =>\n | Promise<StandardSchemaV1.InferInput<Sch>[]>\n | StandardSchemaV1.InferInput<Sch>[];\n dynamic?: boolean;\n },\n ): RemotePrerenderFunction<StandardSchemaV1.InferInput<Sch>, Output>;\n <S extends Schema.Top, Output>(\n schema: S,\n fn: (arg: S[\"Type\"]) => Effect.Effect<Output, unknown, Env>,\n options?: {\n inputs?: () => Promise<S[\"Encoded\"][]> | S[\"Encoded\"][];\n dynamic?: boolean;\n },\n ): RemotePrerenderFunction<S[\"Encoded\"], Output>;\n}\n\nconst makePrerender = <Env>(run: Runner): PrerenderFn<Env> =>\n ((\n arg1: unknown,\n arg2?:\n | ((arg: unknown) => Effect.Effect<unknown, unknown, Env>)\n | {\n inputs?: () => Promise<unknown[]> | unknown[];\n dynamic?: boolean;\n },\n arg3?: {\n inputs?: () => Promise<unknown[]> | unknown[];\n dynamic?: boolean;\n },\n ): any => {\n if (isBareHandler<Env>(arg1)) {\n const handler = arg1;\n return AppServer.prerender(\n () => run(handler()),\n arg2 as { inputs?: () => Promise<void[]> | void[]; dynamic?: boolean } | undefined,\n );\n }\n\n if (typeof arg2 !== \"function\") {\n throw new Error(\"prerender requires a handler function when a schema is provided\");\n }\n\n return AppServer.prerender(\n toStandardValidator(arg1) as \"unchecked\",\n (arg: unknown) => run((arg2 as EffectHandler<Env>)(arg)),\n arg3,\n );\n }) as PrerenderFn<Env>;\n\n/**\n * SvelteKit's `requested` from `$app/server`, passed through. Throws when the\n * installed SvelteKit version does not provide it.\n */\nexport function requested<Result = unknown>(...args: unknown[]): Result {\n const requestedFn = getRequested();\n return requestedFn(...args) as Result;\n}\n\n/** A `query` with its `batch` / `live` helpers attached. */\nexport type QueryNamespace<Env> = QueryFn<Env> & {\n batch: QueryBatchFn<Env>;\n live: QueryLiveFn<Env>;\n};\n\nconst makeQueryNamespace = <Env>(run: Runner): QueryNamespace<Env> =>\n Object.assign(makeQuery<Env>(run), {\n batch: makeQueryBatch<Env>(run),\n live: makeQueryLive<Env>(run),\n }) as QueryNamespace<Env>;\n\n// ── Standalone exports (default SvelteKit per-request runtime) ──────────────\n\n/**\n * SvelteKit's remote `query` with an Effect handler. Accepts `\"unchecked\"`, a\n * Standard Schema or a bare Effect `Schema` as the validator; `query.batch`\n * and `query.live` are attached.\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const query: QueryNamespace<SvelteKitEffectEnv> = makeQueryNamespace(defaultHelpers.run);\n/**\n * SvelteKit's remote `query.batch` with an Effect handler (the same function\n * as `query.batch`).\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const queryBatch: QueryBatchFn<SvelteKitEffectEnv> = query.batch;\n/**\n * SvelteKit's remote `query.live` with an Effect handler that returns an\n * `AsyncIterable` (the same function as `query.live`).\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const queryLive: QueryLiveFn<SvelteKitEffectEnv> = query.live;\n/**\n * SvelteKit's remote `form` with an Effect handler.\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const form: FormFn<SvelteKitEffectEnv> = makeForm(defaultHelpers);\n/**\n * SvelteKit's remote `command` with an Effect handler.\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const command: CommandFn<SvelteKitEffectEnv> = makeCommand(defaultHelpers.run);\n/**\n * SvelteKit's remote `prerender` with an Effect handler.\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const prerender: PrerenderFn<SvelteKitEffectEnv> = makePrerender(defaultHelpers.run);\n\n/** The set of remote-function helpers bound to a particular runner. */\nexport interface RemoteFunctions<Env> {\n readonly query: QueryNamespace<Env>;\n readonly form: FormFn<Env>;\n readonly command: CommandFn<Env>;\n readonly prerender: PrerenderFn<Env>;\n}\n\n/**\n * Bind the remote-function helpers to a {@link RequestRuntimeProvider} (and an\n * optional boundary error translator), so their handlers run on the provider's\n * services `Env` — your own application catalogue — instead of the fixed\n * {@link SvelteKitServices}. The Standard-Schema / `\"unchecked\"` validation\n * argument and the native return types (`RemoteQueryFunction`, `RemoteForm`,\n * ...) are exactly as the standalone helpers.\n *\n * For remote forms, the failure path runs `opts.formError` when provided —\n * mapping a structured/nested error shape into SvelteKit's field issues (via the\n * `issue` helper / `invalid()`) so a domain validation failure drives\n * field-level invalidation rather than a generic failure. Otherwise the form\n * falls back to `translateError`.\n *\n * @example\n * ```ts\n * const { query, form, command } = RemoteFunction.withRuntime(\n * RequestRuntime.fromLocals((event) => event.locals.runtime),\n * {\n * translateError: toSvelteKit,\n * formError: (error, { issue }) => {\n * if (error instanceof ValidationFailure) issue.field(error.field, error.message);\n * invalid();\n * },\n * },\n * );\n *\n * export const items = query(() =>\n * Effect.gen(function* () {\n * const db = yield* Database;\n * return yield* db.list();\n * }),\n * );\n * ```\n */\nexport function withRuntime<R>(\n provider: RequestRuntimeProvider<R, any>,\n opts?: { translateError?: ErrorTranslator; formError?: FormErrorMapper },\n): RemoteFunctions<R> {\n const helpers = helpersFromProvider(\n provider,\n opts?.translateError ?? defaultTranslate,\n opts?.formError,\n );\n return {\n query: makeQueryNamespace<R>(helpers.run),\n form: makeForm<R>(helpers),\n command: makeCommand<R>(helpers.run),\n prerender: makePrerender<R>(helpers.run),\n };\n}\n\n/**\n * The remote-function helpers (`query`, `form`, `command`, `prerender`,\n * `requested`) bound to the default per-request runtime; `withRuntime` binds\n * them to your own services.\n */\nexport const RemoteFunction = {\n query,\n form,\n command,\n prerender,\n requested,\n withRuntime,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"remote-functions.js","names":["isBareHandlerValue"],"sources":["../src/remote-functions.ts"],"sourcesContent":["// NOTE: This module builds the `query` / `form` / `command` / `prerender`\n// *factories* that consumers call inside their own `*.remote.ts` files — it is\n// NOT itself a SvelteKit remote module, and its exports (e.g. `RemoteFunction`)\n// are deliberately not remote functions. Its filename must therefore never match\n// SvelteKit's remote-module matcher `/[/.]remote(\\.[^/]+)+$/`\n// (kit `src/exports/vite/utils.js`), or kit's build-time validation will reject\n// the built file with \"all exports from this file must be remote functions\".\n// That is why this is `remote-functions.ts` and never `remote.server.ts` /\n// `*.remote.ts`. See `tests/remote-module-naming.test.ts` for the guard.\nimport * as AppServer from \"$app/server\";\nimport type {\n RemoteCommand,\n RemoteForm,\n RemoteFormInput,\n RemotePrerenderFunction,\n RemoteQueryFunction,\n RemoteFormInvalidField as InvalidField,\n} from \"$app/server\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport * as HttpClient from \"effect/http/HttpClient\";\nimport { Effect, type Schema } from \"effect\";\nimport { SvelteKitRuntime, SvelteKitRequestEvent } from \"./runtime.js\";\nimport {\n isBareHandler as isBareHandlerValue,\n toStandardValidator,\n} from \"./internal/remote-validators.js\";\nimport {\n defaultTranslate,\n makeRunHelpers,\n type FormErrorMapper,\n type RunHelpers,\n type Runner,\n} from \"./internal/remote-run.js\";\nimport type { ErrorTranslator, RequestRuntimeProvider } from \"./request-runtime.js\";\n\nexport type { FormErrorMapper } from \"./internal/remote-run.js\";\n\ntype SvelteKitEffectEnv = HttpClient.HttpClient | SvelteKitRequestEvent;\n\n/** The default helpers: a fresh SvelteKit per-request runtime, passthrough translation. */\nconst defaultHelpers: RunHelpers = makeRunHelpers(() => {\n const event = AppServer.getRequestEvent();\n return { runExit: (effect) => SvelteKitRuntime.forRequest(event).runPromiseExit(effect) };\n}, defaultTranslate);\n\n/** Build helpers from a {@link RequestRuntimeProvider}, translator, and form-error mapper. */\nconst helpersFromProvider = (\n provider: RequestRuntimeProvider<any, any>,\n translate: ErrorTranslator,\n formError?: FormErrorMapper,\n): RunHelpers =>\n makeRunHelpers(\n () => {\n const event = AppServer.getRequestEvent();\n return {\n runExit: (effect) => provider.run(event).runPromiseExit(effect),\n dispose: () => provider.disposeAfterResponse?.(event),\n };\n },\n translate,\n formError,\n );\n\nfunction unavailable(name: string): never {\n throw new Error(\n `${name} is not available in the installed SvelteKit version. Update @sveltejs/kit to use this API.`,\n );\n}\n\ntype EffectHandler<Env> = (arg: unknown) => Effect.Effect<unknown, unknown, Env>;\ntype EffectFormHandler<Env> = (\n data: unknown,\n issue: unknown,\n) => Effect.Effect<unknown, unknown, Env>;\ntype EffectVoidHandler<Env> = () => Effect.Effect<unknown, unknown, Env>;\n\n/** True when the argument is the no-validation handler overload (typed narrowing). */\nconst isBareHandler = <Env>(value: unknown): value is EffectVoidHandler<Env> =>\n isBareHandlerValue(value);\n\n/** The public shape of the `query` helper, parameterised by its handler env. */\nexport interface QueryFn<Env> {\n <Output>(fn: () => Effect.Effect<Output, unknown, Env>): RemoteQueryFunction<void, Output>;\n <Input, Output>(\n validate: \"unchecked\",\n fn: (arg: Input) => Effect.Effect<Output, unknown, Env>,\n ): RemoteQueryFunction<Input, Output>;\n <Sch extends StandardSchemaV1, Output>(\n schema: Sch,\n fn: (arg: StandardSchemaV1.InferOutput<Sch>) => Effect.Effect<Output, unknown, Env>,\n ): RemoteQueryFunction<StandardSchemaV1.InferInput<Sch>, Output>;\n <S extends Schema.Top, Output>(\n schema: S,\n fn: (arg: S[\"Type\"]) => Effect.Effect<Output, unknown, Env>,\n ): RemoteQueryFunction<S[\"Encoded\"], Output>;\n}\n\nconst makeQuery = <Env>(run: Runner): QueryFn<Env> =>\n ((arg1: unknown, arg2?: (arg: unknown) => Effect.Effect<unknown, unknown, Env>): any => {\n if (isBareHandler<Env>(arg1)) {\n const handler = arg1;\n return AppServer.query(() => run(handler()));\n }\n\n if (!arg2) {\n throw new Error(\"query requires a handler function when a schema is provided\");\n }\n\n return AppServer.query(toStandardValidator(arg1) as \"unchecked\", (arg: unknown) =>\n run(arg2(arg)),\n );\n }) as QueryFn<Env>;\n\n/** The public shape of `query.batch`, parameterised by its handler env. */\nexport interface QueryBatchFn<Env> {\n <Input, Output>(\n validate: \"unchecked\",\n fn: (args: Input[]) => Effect.Effect<(arg: Input, idx: number) => Output, unknown, Env>,\n ): RemoteQueryFunction<Input, Output>;\n <Sch extends StandardSchemaV1, Output>(\n schema: Sch,\n fn: (\n args: StandardSchemaV1.InferOutput<Sch>[],\n ) => Effect.Effect<\n (arg: StandardSchemaV1.InferOutput<Sch>, idx: number) => Output,\n unknown,\n Env\n >,\n ): RemoteQueryFunction<StandardSchemaV1.InferInput<Sch>, Output>;\n <S extends Schema.Top, Output>(\n schema: S,\n fn: (args: S[\"Type\"][]) => Effect.Effect<(arg: S[\"Type\"], idx: number) => Output, unknown, Env>,\n ): RemoteQueryFunction<S[\"Encoded\"], Output>;\n}\n\nconst makeQueryBatch = <Env>(run: Runner): QueryBatchFn<Env> =>\n ((\n validate: unknown,\n fn: (args: unknown[]) => Effect.Effect<(arg: unknown, idx: number) => unknown, unknown, Env>,\n ): any =>\n AppServer.query.batch(toStandardValidator(validate) as \"unchecked\", (args: unknown[]) =>\n run(fn(args)),\n )) as QueryBatchFn<Env>;\n\ntype QueryLiveFactory = (\n validate: unknown,\n fn: (arg: unknown) => Promise<AsyncIterable<unknown>> | AsyncIterable<unknown>,\n) => unknown;\n\ntype QueryWithCompat = typeof AppServer.query & {\n live?: QueryLiveFactory;\n};\n\ntype AppServerWithCompat = typeof AppServer & {\n requested?: (...args: unknown[]) => unknown;\n};\n\nconst appServerCompat = AppServer as AppServerWithCompat;\nconst queryCompat = AppServer.query as QueryWithCompat;\n\nfunction getQueryLive(): QueryLiveFactory {\n const live = queryCompat.live;\n\n if (typeof live !== \"function\") {\n unavailable(\"query.live\");\n }\n\n return live;\n}\n\nfunction getRequested(): (...args: unknown[]) => unknown {\n const requestedFn = appServerCompat.requested;\n\n if (typeof requestedFn !== \"function\") {\n unavailable(\"requested\");\n }\n\n return requestedFn;\n}\n\n/** The public shape of `query.live`, parameterised by its handler env. */\nexport interface QueryLiveFn<Env> {\n <Input, Output>(\n validate: \"unchecked\",\n fn: (arg: Input) => Effect.Effect<AsyncIterable<Output>, unknown, Env>,\n ): RemoteQueryFunction<Input, Output>;\n <Sch extends StandardSchemaV1, Output>(\n schema: Sch,\n fn: (\n arg: StandardSchemaV1.InferOutput<Sch>,\n ) => Effect.Effect<AsyncIterable<Output>, unknown, Env>,\n ): RemoteQueryFunction<StandardSchemaV1.InferInput<Sch>, Output>;\n <S extends Schema.Top, Output>(\n schema: S,\n fn: (arg: S[\"Type\"]) => Effect.Effect<AsyncIterable<Output>, unknown, Env>,\n ): RemoteQueryFunction<S[\"Encoded\"], Output>;\n}\n\nconst makeQueryLive = <Env>(run: Runner): QueryLiveFn<Env> =>\n ((\n validate: unknown,\n fn: (arg: unknown) => Effect.Effect<AsyncIterable<unknown>, unknown, Env>,\n ): any => {\n const live = getQueryLive();\n return live(toStandardValidator(validate), (arg) => run(fn(arg)));\n }) as QueryLiveFn<Env>;\n\n/** The public shape of the `form` helper, parameterised by its handler env. */\nexport interface FormFn<Env> {\n <Output>(fn: () => Effect.Effect<Output, unknown, Env>): RemoteForm<void, Output>;\n <Input, Output>(\n validate: \"unchecked\",\n fn: (\n data: Input,\n issue: InvalidField<Input & RemoteFormInput>,\n ) => Effect.Effect<Output, unknown, Env>,\n ): RemoteForm<Input & RemoteFormInput, Output>;\n <Sch extends StandardSchemaV1, Output>(\n validate: Sch,\n fn: (\n data: StandardSchemaV1.InferOutput<Sch>,\n issue: InvalidField<StandardSchemaV1.InferInput<Sch> & RemoteFormInput>,\n ) => Effect.Effect<Output, unknown, Env>,\n ): RemoteForm<StandardSchemaV1.InferInput<Sch> & RemoteFormInput, Output>;\n <S extends Schema.Top, Output>(\n validate: S,\n fn: (\n data: S[\"Type\"],\n issue: InvalidField<S[\"Encoded\"] & RemoteFormInput>,\n ) => Effect.Effect<Output, unknown, Env>,\n ): RemoteForm<S[\"Encoded\"] & RemoteFormInput, Output>;\n}\n\nconst makeForm = <Env>(helpers: RunHelpers): FormFn<Env> =>\n ((arg1: unknown, arg2?: unknown): any => {\n if (isBareHandler<Env>(arg1)) {\n const handler = arg1;\n return AppServer.form(() => helpers.run(handler()));\n }\n\n if (!arg2) {\n throw new Error(\"form requires a handler function when a schema is provided\");\n }\n\n return AppServer.form(\n toStandardValidator(arg1) as \"unchecked\",\n (data: unknown, issue: unknown) =>\n helpers.runForm((arg2 as EffectFormHandler<Env>)(data, issue), {\n issue: issue as InvalidField<any>,\n data,\n }),\n );\n }) as FormFn<Env>;\n\n/** The public shape of the `command` helper, parameterised by its handler env. */\nexport interface CommandFn<Env> {\n <Output>(fn: () => Effect.Effect<Output, unknown, Env>): RemoteCommand<void, Output>;\n <Input, Output>(\n validate: \"unchecked\",\n fn: (arg: Input) => Effect.Effect<Output, unknown, Env>,\n ): RemoteCommand<Input, Output>;\n <Sch extends StandardSchemaV1, Output>(\n validate: Sch,\n fn: (arg: StandardSchemaV1.InferOutput<Sch>) => Effect.Effect<Output, unknown, Env>,\n ): RemoteCommand<StandardSchemaV1.InferInput<Sch>, Output>;\n <S extends Schema.Top, Output>(\n validate: S,\n fn: (arg: S[\"Type\"]) => Effect.Effect<Output, unknown, Env>,\n ): RemoteCommand<S[\"Encoded\"], Output>;\n}\n\nconst makeCommand = <Env>(run: Runner): CommandFn<Env> =>\n ((arg1: unknown, arg2?: (arg: unknown) => Effect.Effect<unknown, unknown, Env>): any => {\n if (isBareHandler<Env>(arg1)) {\n const handler = arg1;\n return AppServer.command(() => run(handler()));\n }\n\n if (!arg2) {\n throw new Error(\"command requires a handler function when a schema is provided\");\n }\n\n return AppServer.command(toStandardValidator(arg1) as \"unchecked\", (arg: unknown) =>\n run(arg2(arg)),\n );\n }) as CommandFn<Env>;\n\n/** The public shape of the `prerender` helper, parameterised by its handler env. */\nexport interface PrerenderFn<Env> {\n <Output>(\n fn: () => Effect.Effect<Output, unknown, Env>,\n options?: {\n inputs?: () => Promise<void[]> | void[];\n dynamic?: boolean;\n },\n ): RemotePrerenderFunction<void, Output>;\n <Input, Output>(\n validate: \"unchecked\",\n fn: (arg: Input) => Effect.Effect<Output, unknown, Env>,\n options?: {\n inputs?: () => Promise<Input[]> | Input[];\n dynamic?: boolean;\n },\n ): RemotePrerenderFunction<Input, Output>;\n <Sch extends StandardSchemaV1, Output>(\n schema: Sch,\n fn: (arg: StandardSchemaV1.InferOutput<Sch>) => Effect.Effect<Output, unknown, Env>,\n options?: {\n inputs?: () =>\n | Promise<StandardSchemaV1.InferInput<Sch>[]>\n | StandardSchemaV1.InferInput<Sch>[];\n dynamic?: boolean;\n },\n ): RemotePrerenderFunction<StandardSchemaV1.InferInput<Sch>, Output>;\n <S extends Schema.Top, Output>(\n schema: S,\n fn: (arg: S[\"Type\"]) => Effect.Effect<Output, unknown, Env>,\n options?: {\n inputs?: () => Promise<S[\"Encoded\"][]> | S[\"Encoded\"][];\n dynamic?: boolean;\n },\n ): RemotePrerenderFunction<S[\"Encoded\"], Output>;\n}\n\nconst makePrerender = <Env>(run: Runner): PrerenderFn<Env> =>\n ((\n arg1: unknown,\n arg2?:\n | ((arg: unknown) => Effect.Effect<unknown, unknown, Env>)\n | {\n inputs?: () => Promise<unknown[]> | unknown[];\n dynamic?: boolean;\n },\n arg3?: {\n inputs?: () => Promise<unknown[]> | unknown[];\n dynamic?: boolean;\n },\n ): any => {\n if (isBareHandler<Env>(arg1)) {\n const handler = arg1;\n return AppServer.prerender(\n () => run(handler()),\n arg2 as { inputs?: () => Promise<void[]> | void[]; dynamic?: boolean } | undefined,\n );\n }\n\n if (typeof arg2 !== \"function\") {\n throw new Error(\"prerender requires a handler function when a schema is provided\");\n }\n\n return AppServer.prerender(\n toStandardValidator(arg1) as \"unchecked\",\n (arg: unknown) => run((arg2 as EffectHandler<Env>)(arg)),\n arg3,\n );\n }) as PrerenderFn<Env>;\n\n/**\n * SvelteKit's `requested` from `$app/server`, passed through. Throws when the\n * installed SvelteKit version does not provide it.\n */\nexport function requested<Result = unknown>(...args: unknown[]): Result {\n const requestedFn = getRequested();\n return requestedFn(...args) as Result;\n}\n\n/** A `query` with its `batch` / `live` helpers attached. */\nexport type QueryNamespace<Env> = QueryFn<Env> & {\n batch: QueryBatchFn<Env>;\n live: QueryLiveFn<Env>;\n};\n\nconst makeQueryNamespace = <Env>(run: Runner): QueryNamespace<Env> =>\n Object.assign(makeQuery<Env>(run), {\n batch: makeQueryBatch<Env>(run),\n live: makeQueryLive<Env>(run),\n }) as QueryNamespace<Env>;\n\n// ── Standalone exports (default SvelteKit per-request runtime) ──────────────\n\n/**\n * SvelteKit's remote `query` with an Effect handler. Accepts `\"unchecked\"`, a\n * Standard Schema or a bare Effect `Schema` as the validator; `query.batch`\n * and `query.live` are attached.\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const query: QueryNamespace<SvelteKitEffectEnv> = makeQueryNamespace(defaultHelpers.run);\n/**\n * SvelteKit's remote `query.batch` with an Effect handler (the same function\n * as `query.batch`).\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const queryBatch: QueryBatchFn<SvelteKitEffectEnv> = query.batch;\n/**\n * SvelteKit's remote `query.live` with an Effect handler that returns an\n * `AsyncIterable` (the same function as `query.live`).\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const queryLive: QueryLiveFn<SvelteKitEffectEnv> = query.live;\n/**\n * SvelteKit's remote `form` with an Effect handler.\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const form: FormFn<SvelteKitEffectEnv> = makeForm(defaultHelpers);\n/**\n * SvelteKit's remote `command` with an Effect handler.\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const command: CommandFn<SvelteKitEffectEnv> = makeCommand(defaultHelpers.run);\n/**\n * SvelteKit's remote `prerender` with an Effect handler.\n *\n * Handlers run on the default per-request runtime (`HttpClient` plus\n * `SvelteKitRequestEvent`); a failure that is not a SvelteKit `error()` /\n * `redirect()` becomes a 500. Use {@link withRuntime} to run on your own\n * services.\n */\nexport const prerender: PrerenderFn<SvelteKitEffectEnv> = makePrerender(defaultHelpers.run);\n\n/** The set of remote-function helpers bound to a particular runner. */\nexport interface RemoteFunctions<Env> {\n readonly query: QueryNamespace<Env>;\n readonly form: FormFn<Env>;\n readonly command: CommandFn<Env>;\n readonly prerender: PrerenderFn<Env>;\n}\n\n/**\n * Bind the remote-function helpers to a {@link RequestRuntimeProvider} (and an\n * optional boundary error translator), so their handlers run on the provider's\n * services `Env` — your own application catalogue — instead of the fixed\n * {@link SvelteKitServices}. The Standard-Schema / `\"unchecked\"` validation\n * argument and the native return types (`RemoteQueryFunction`, `RemoteForm`,\n * ...) are exactly as the standalone helpers.\n *\n * For remote forms, the failure path runs `opts.formError` when provided —\n * mapping a structured/nested error shape into SvelteKit's field issues (via the\n * `issue` helper / `invalid()`) so a domain validation failure drives\n * field-level invalidation rather than a generic failure. Otherwise the form\n * falls back to `translateError`.\n *\n * @example\n * ```ts\n * const { query, form, command } = RemoteFunction.withRuntime(\n * RequestRuntime.fromLocals((event) => event.locals.runtime),\n * {\n * translateError: toSvelteKit,\n * formError: (error, { issue }) => {\n * if (error instanceof ValidationFailure) issue.field(error.field, error.message);\n * invalid();\n * },\n * },\n * );\n *\n * export const items = query(() =>\n * Effect.gen(function* () {\n * const db = yield* Database;\n * return yield* db.list();\n * }),\n * );\n * ```\n */\nexport function withRuntime<R>(\n provider: RequestRuntimeProvider<R, any>,\n opts?: { translateError?: ErrorTranslator; formError?: FormErrorMapper },\n): RemoteFunctions<R> {\n const helpers = helpersFromProvider(\n provider,\n opts?.translateError ?? defaultTranslate,\n opts?.formError,\n );\n return {\n query: makeQueryNamespace<R>(helpers.run),\n form: makeForm<R>(helpers),\n command: makeCommand<R>(helpers.run),\n prerender: makePrerender<R>(helpers.run),\n };\n}\n\n/**\n * The remote-function helpers (`query`, `form`, `command`, `prerender`,\n * `requested`) bound to the default per-request runtime; `withRuntime` binds\n * them to your own services.\n */\nexport const RemoteFunction = {\n query,\n form,\n command,\n prerender,\n requested,\n withRuntime,\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { RemoteResource } from "@sveltejs/kit";
1
+ import { RemoteResource } from "$app/server";
2
2
  import * as AsyncResult from "effect/reactivity/AsyncResult";
3
3
  //#region src/remote-reactive.d.ts
4
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"remote-reactive.js","names":[],"sources":["../src/remote-reactive.ts"],"sourcesContent":["import type { RemoteResource } from \"@sveltejs/kit\";\nimport * as AsyncResult from \"effect/reactivity/AsyncResult\";\n\n/**\n * Bridges a SvelteKit remote resource (`query(...)`, `query.live(...)`,\n * `prerender(...)`) into Effect's native\n * {@link AsyncResult.AsyncResult} — the same result type the Svelte hooks in\n * `@thomasfosterau/effect-svelte` expose — so remote-function data folds into\n * the same templates and combinators (`AsyncResult.match`, `isSuccess`, ...).\n *\n * A `RemoteResource<T>` is already reactive (`current` / `loading` / `error` /\n * `ready`); reading them inside the returned `current` getter tracks them, so\n * the result updates as the resource does. The `loading` flag is surfaced as\n * `AsyncResult`'s `waiting` (stale-while-revalidate): a refresh keeps the\n * previous `Success` on screen.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { useRemoteQuery } from '@thomasfosterau/effect-sveltekit/client';\n * import { AsyncResult } from '@thomasfosterau/effect-svelte';\n * import { getTodos } from './todos.remote';\n *\n * const todos = useRemoteQuery(getTodos());\n * </script>\n *\n * {#if AsyncResult.isSuccess(todos.current)}\n * <ul>{#each todos.current.value as todo}<li>{todo.text}</li>{/each}</ul>\n * {/if}\n * ```\n */\nexport function useRemoteQuery<T>(query: RemoteResource<T>): {\n readonly current: AsyncResult.AsyncResult<T, unknown>;\n} {\n return {\n get current() {\n // Read every reactive field so the consumer's effect tracks the resource.\n const loading = query.loading;\n const error = query.error;\n const ready = query.ready;\n\n if (error !== undefined && error !== null) {\n return AsyncResult.fail<unknown, T>(error, { waiting: loading });\n }\n if (ready) {\n return AsyncResult.success<T, unknown>(query.current as T, { waiting: loading });\n }\n return AsyncResult.initial<T, unknown>(loading);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,eAAkB,OAEhC;CACA,OAAO,EACL,IAAI,UAAU;EAEZ,MAAM,UAAU,MAAM;EACtB,MAAM,QAAQ,MAAM;EACpB,MAAM,QAAQ,MAAM;EAEpB,IAAI,UAAU,KAAA,KAAa,UAAU,MACnC,OAAO,YAAY,KAAiB,OAAO,EAAE,SAAS,QAAQ,CAAC;EAEjE,IAAI,OACF,OAAO,YAAY,QAAoB,MAAM,SAAc,EAAE,SAAS,QAAQ,CAAC;EAEjF,OAAO,YAAY,QAAoB,OAAO;CAChD,EACF;AACF"}
1
+ {"version":3,"file":"remote-reactive.js","names":[],"sources":["../src/remote-reactive.ts"],"sourcesContent":["import type { RemoteResource } from \"$app/server\";\nimport * as AsyncResult from \"effect/reactivity/AsyncResult\";\n\n/**\n * Bridges a SvelteKit remote resource (`query(...)`, `query.live(...)`,\n * `prerender(...)`) into Effect's native\n * {@link AsyncResult.AsyncResult} — the same result type the Svelte hooks in\n * `@thomasfosterau/effect-svelte` expose — so remote-function data folds into\n * the same templates and combinators (`AsyncResult.match`, `isSuccess`, ...).\n *\n * A `RemoteResource<T>` is already reactive (`current` / `loading` / `error` /\n * `ready`); reading them inside the returned `current` getter tracks them, so\n * the result updates as the resource does. The `loading` flag is surfaced as\n * `AsyncResult`'s `waiting` (stale-while-revalidate): a refresh keeps the\n * previous `Success` on screen.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { useRemoteQuery } from '@thomasfosterau/effect-sveltekit/client';\n * import { AsyncResult } from '@thomasfosterau/effect-svelte';\n * import { getTodos } from './todos.remote';\n *\n * const todos = useRemoteQuery(getTodos());\n * </script>\n *\n * {#if AsyncResult.isSuccess(todos.current)}\n * <ul>{#each todos.current.value as todo}<li>{todo.text}</li>{/each}</ul>\n * {/if}\n * ```\n */\nexport function useRemoteQuery<T>(query: RemoteResource<T>): {\n readonly current: AsyncResult.AsyncResult<T, unknown>;\n} {\n return {\n get current() {\n // Read every reactive field so the consumer's effect tracks the resource.\n const loading = query.loading;\n const error = query.error;\n const ready = query.ready;\n\n if (error !== undefined && error !== null) {\n return AsyncResult.fail<unknown, T>(error, { waiting: loading });\n }\n if (ready) {\n return AsyncResult.success<T, unknown>(query.current as T, { waiting: loading });\n }\n return AsyncResult.initial<T, unknown>(loading);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,eAAkB,OAEhC;CACA,OAAO,EACL,IAAI,UAAU;EAEZ,MAAM,UAAU,MAAM;EACtB,MAAM,QAAQ,MAAM;EACpB,MAAM,QAAQ,MAAM;EAEpB,IAAI,UAAU,KAAA,KAAa,UAAU,MACnC,OAAO,YAAY,KAAiB,OAAO,EAAE,SAAS,QAAQ,CAAC;EAEjE,IAAI,OACF,OAAO,YAAY,QAAoB,MAAM,SAAc,EAAE,SAAS,QAAQ,CAAC;EAEjF,OAAO,YAAY,QAAoB,OAAO;CAChD,EACF;AACF"}
@@ -1,4 +1,4 @@
1
- import { Transporter } from "@sveltejs/kit";
1
+ import { Transporter } from "@sveltejs/kit/hooks";
2
2
  //#region src/response-headers.d.ts
3
3
  /**
4
4
  * A `Headers` that serialises to `{}` and knows how to copy itself onto a
@@ -1 +1 @@
1
- {"version":3,"file":"response-headers.js","names":[],"sources":["../src/response-headers.ts"],"sourcesContent":["/**\n * A per-request **response-headers buffer** that can ride through `load` data.\n *\n * SvelteKit's `setHeaders` refuses `set-cookie` and throws when the same header\n * is set twice, and components rendering during SSR cannot reach it at all. The\n * pattern the applications converged on is a mutable `Headers` buffer on\n * `event.locals`: loads (and SSR components, via `page.data`) append to it, and\n * a server `handle` copies it onto the outgoing response after `resolve()`.\n *\n * Returning that buffer from a `load` needs a `transport` entry, or SvelteKit\n * refuses to serialise it (\"Cannot stringify arbitrary non-POJOs\"). Its contents\n * are deliberately *not* round-tripped — the server hook reads the live buffer\n * after rendering, so the client only needs a fresh, empty instance.\n * {@link ResponseHeaders} is the buffer, {@link responseHeadersTransporter} the\n * transport entry, and {@link ResponseHeaders.appendTo} the copy step.\n *\n * @example\n * ```ts\n * // src/hooks.ts\n * import { Hooks } from \"@thomasfosterau/effect-sveltekit\";\n *\n * export const transport = Hooks.transport({ ResponseHeaders: Hooks.responseHeadersTransporter });\n *\n * // src/hooks.server.ts\n * import { ResponseHeaders } from \"@thomasfosterau/effect-sveltekit\";\n * import type { Handle } from \"@sveltejs/kit\";\n *\n * export const handle: Handle = async ({ event, resolve }) => {\n * event.locals.headers = new ResponseHeaders();\n * const response = await resolve(event);\n * event.locals.headers.appendTo(response.headers);\n * return response;\n * };\n *\n * // src/routes/+layout.server.ts — expose the buffer to every page\n * export const load = ({ locals }) => ({ headers: locals.headers });\n * ```\n *\n * @module\n */\n\nimport type { Transporter } from \"@sveltejs/kit\";\nimport { markerTransporter } from \"./transport.js\";\n\n/**\n * A `Headers` that serialises to `{}` and knows how to copy itself onto a\n * response. Everything else is the platform `Headers`.\n */\nexport class ResponseHeaders extends globalThis.Headers {\n /**\n * Append every buffered header to `target` (typically `response.headers`\n * after `resolve()`). Appends rather than sets, so repeated headers such as\n * `set-cookie` all survive.\n */\n appendTo(target: globalThis.Headers): void {\n for (const cookie of this.getSetCookie()) target.append(\"set-cookie\", cookie);\n this.forEach((value, key) => {\n if (key !== \"set-cookie\") target.append(key, value);\n });\n }\n\n /** Serialises to an empty object: the contents never leave the server. */\n toJSON(): Record<string, never> {\n return {};\n }\n}\n\n/**\n * The `transport` entry for {@link ResponseHeaders}: detected on the server,\n * reconstructed on the client as a fresh, empty buffer.\n */\nexport const responseHeadersTransporter: Transporter<ResponseHeaders, unknown> = markerTransporter({\n guard: (value): value is ResponseHeaders => value instanceof ResponseHeaders,\n make: () => new ResponseHeaders(),\n});\n"],"mappings":";;;;;;AAgDA,IAAa,kBAAb,cAAqC,WAAW,QAAQ;;;;;;CAMtD,SAAS,QAAkC;EACzC,KAAK,MAAM,UAAU,KAAK,aAAa,GAAG,OAAO,OAAO,cAAc,MAAM;EAC5E,KAAK,SAAS,OAAO,QAAQ;GAC3B,IAAI,QAAQ,cAAc,OAAO,OAAO,KAAK,KAAK;EACpD,CAAC;CACH;;CAGA,SAAgC;EAC9B,OAAO,CAAC;CACV;AACF;;;;;AAMA,MAAa,6BAAoE,kBAAkB;CACjG,QAAQ,UAAoC,iBAAiB;CAC7D,YAAY,IAAI,gBAAgB;AAClC,CAAC"}
1
+ {"version":3,"file":"response-headers.js","names":[],"sources":["../src/response-headers.ts"],"sourcesContent":["/**\n * A per-request **response-headers buffer** that can ride through `load` data.\n *\n * SvelteKit's `setHeaders` refuses `set-cookie` and throws when the same header\n * is set twice, and components rendering during SSR cannot reach it at all. The\n * pattern the applications converged on is a mutable `Headers` buffer on\n * `event.locals`: loads (and SSR components, via `page.data`) append to it, and\n * a server `handle` copies it onto the outgoing response after `resolve()`.\n *\n * Returning that buffer from a `load` needs a `transport` entry, or SvelteKit\n * refuses to serialise it (\"Cannot stringify arbitrary non-POJOs\"). Its contents\n * are deliberately *not* round-tripped — the server hook reads the live buffer\n * after rendering, so the client only needs a fresh, empty instance.\n * {@link ResponseHeaders} is the buffer, {@link responseHeadersTransporter} the\n * transport entry, and {@link ResponseHeaders.appendTo} the copy step.\n *\n * @example\n * ```ts\n * // src/hooks.ts\n * import { Hooks } from \"@thomasfosterau/effect-sveltekit\";\n *\n * export const transport = Hooks.transport({ ResponseHeaders: Hooks.responseHeadersTransporter });\n *\n * // src/hooks.server.ts\n * import { ResponseHeaders } from \"@thomasfosterau/effect-sveltekit\";\n * import type { Handle } from \"@sveltejs/kit/hooks\";\n *\n * export const handle: Handle = async ({ event, resolve }) => {\n * event.locals.headers = new ResponseHeaders();\n * const response = await resolve(event);\n * event.locals.headers.appendTo(response.headers);\n * return response;\n * };\n *\n * // src/routes/+layout.server.ts — expose the buffer to every page\n * export const load = ({ locals }) => ({ headers: locals.headers });\n * ```\n *\n * @module\n */\n\nimport type { Transporter } from \"@sveltejs/kit/hooks\";\nimport { markerTransporter } from \"./transport.js\";\n\n/**\n * A `Headers` that serialises to `{}` and knows how to copy itself onto a\n * response. Everything else is the platform `Headers`.\n */\nexport class ResponseHeaders extends globalThis.Headers {\n /**\n * Append every buffered header to `target` (typically `response.headers`\n * after `resolve()`). Appends rather than sets, so repeated headers such as\n * `set-cookie` all survive.\n */\n appendTo(target: globalThis.Headers): void {\n for (const cookie of this.getSetCookie()) target.append(\"set-cookie\", cookie);\n this.forEach((value, key) => {\n if (key !== \"set-cookie\") target.append(key, value);\n });\n }\n\n /** Serialises to an empty object: the contents never leave the server. */\n toJSON(): Record<string, never> {\n return {};\n }\n}\n\n/**\n * The `transport` entry for {@link ResponseHeaders}: detected on the server,\n * reconstructed on the client as a fresh, empty buffer.\n */\nexport const responseHeadersTransporter: Transporter<ResponseHeaders, unknown> = markerTransporter({\n guard: (value): value is ResponseHeaders => value instanceof ResponseHeaders,\n make: () => new ResponseHeaders(),\n});\n"],"mappings":";;;;;;AAgDA,IAAa,kBAAb,cAAqC,WAAW,QAAQ;;;;;;CAMtD,SAAS,QAAkC;EACzC,KAAK,MAAM,UAAU,KAAK,aAAa,GAAG,OAAO,OAAO,cAAc,MAAM;EAC5E,KAAK,SAAS,OAAO,QAAQ;GAC3B,IAAI,QAAQ,cAAc,OAAO,OAAO,KAAK,KAAK;EACpD,CAAC;CACH;;CAGA,SAAgC;EAC9B,OAAO,CAAC;CACV;AACF;;;;;AAMA,MAAa,6BAAoE,kBAAkB;CACjG,QAAQ,UAAoC,iBAAiB;CAC7D,YAAY,IAAI,gBAAgB;AAClC,CAAC"}
@@ -49,8 +49,8 @@ interface EndpointOptions {
49
49
  * ```ts
50
50
  * // src/routes/api/[...path]/+server.ts
51
51
  * import { Endpoint } from "@thomasfosterau/effect-sveltekit/server";
52
- * import { api } from "$lib/server/api";
53
- * import { ApiLive } from "$lib/server/handlers";
52
+ * import { api } from "#lib/server/api.ts";
53
+ * import { ApiLive } from "#lib/server/handlers.ts";
54
54
  *
55
55
  * export const fallback = Endpoint.fromApi(api, ApiLive, { prefix: "/api" });
56
56
  * ```
@@ -55,8 +55,8 @@ const apiPlatform = Layer.mergeAll(Path.layer, Etag.layerWeak, HttpPlatform.laye
55
55
  * ```ts
56
56
  * // src/routes/api/[...path]/+server.ts
57
57
  * import { Endpoint } from "@thomasfosterau/effect-sveltekit/server";
58
- * import { api } from "$lib/server/api";
59
- * import { ApiLive } from "$lib/server/handlers";
58
+ * import { api } from "#lib/server/api.ts";
59
+ * import { ApiLive } from "#lib/server/handlers.ts";
60
60
  *
61
61
  * export const fallback = Endpoint.fromApi(api, ApiLive, { prefix: "/api" });
62
62
  * ```
@@ -1 +1 @@
1
- {"version":3,"file":"Endpoint.js","names":[],"sources":["../../src/server/Endpoint.ts"],"sourcesContent":["/**\n * Create SvelteKit server endpoints (`+server.ts`) backed by Effect — the\n * `Endpoint` namespace of `@thomasfosterau/effect-sveltekit/server`.\n *\n * A SvelteKit endpoint is a `RequestHandler` (`(event) => Response`). Effect can\n * turn an [`HttpApi`](https://effect.website), an `HttpRouter`, or a single\n * route effect into a Web `fetch` handler; these helpers wrap one as a SvelteKit\n * endpoint handler so a route can be served by Effect. Mount it on a catch-all\n * route (`[...path]`) and assign it to `fallback` so every method and sub-path\n * reaches it:\n *\n * @example\n * ```ts\n * // src/routes/api/[...path]/+server.ts\n * import { Endpoint } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { api } from \"$lib/server/api\";\n * import { ApiLive } from \"$lib/server/handlers\"; // HttpApiBuilder.group(...) + your services\n *\n * // `prefix` strips the SvelteKit mount path so the API's own paths\n * // (e.g. \"/users\") match.\n * export const fallback = Endpoint.fromApi(api, ApiLive, { prefix: \"/api\" });\n * ```\n *\n * The layer backing an endpoint is built once, lazily, on the first request and\n * shared across subsequent requests (like `makeServerRuntime`). The returned\n * handler carries a `dispose()` that closes the layer's scope — call it on\n * shutdown if the endpoint holds resources.\n *\n * The Effect handlers receive an Effect-native `HttpServerRequest` (built from\n * `event.request`), not the SvelteKit `RequestEvent`.\n */\n\nimport type { RequestHandler } from \"@sveltejs/kit\";\nimport { Context, type Duration, Effect, Layer, Schedule, Stream } from \"effect\";\nimport type { Scope } from \"effect\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as Path from \"effect/Path\";\nimport * as Etag from \"effect/http/Etag\";\nimport * as HttpEffect from \"effect/http/HttpEffect\";\nimport * as HttpPlatform from \"effect/http/HttpPlatform\";\nimport * as HttpRouter from \"effect/http/HttpRouter\";\nimport type * as HttpServerRequest from \"effect/http/HttpServerRequest\";\nimport type * as HttpServerResponse from \"effect/http/HttpServerResponse\";\nimport type * as HttpApi from \"effect/http-api/HttpApi\";\nimport * as HttpApiBuilder from \"effect/http-api/HttpApiBuilder\";\nimport type * as HttpApiGroup from \"effect/http-api/HttpApiGroup\";\nimport { encodeRetry, encodeSseFrame, HEARTBEAT_FRAME, SSE_HEADERS } from \"../internal/sse.js\";\n\n/** A Web `fetch`-style handler, as produced by Effect's `toWebHandler` family. */\ntype WebHandler = (request: Request) => Promise<Response>;\n\n/** A Web handler that also accepts a per-request service context. */\ntype WebHandlerWithContext = (\n request: Request,\n context?: Context.Context<never>,\n) => Promise<Response>;\n\n/**\n * Resolve a request-scoped service context, if a resolver was given. The\n * resolver may return a `Context` directly or an `Effect` producing one (run\n * with no requirements), so a consumer can read the request to build\n * session-aware services per dispatch.\n */\nexport type RequestContext<RequestServices> = (\n request: Request,\n) =>\n | Context.Context<RequestServices>\n | Effect.Effect<Context.Context<RequestServices>, never, never>;\n\nconst resolveRequestContext = async <RequestServices>(\n request: Request,\n context: RequestContext<RequestServices> | undefined,\n): Promise<Context.Context<RequestServices> | undefined> => {\n if (context === undefined) return undefined;\n const result = context(request);\n return Effect.isEffect(result) ? Effect.runPromise(result) : result;\n};\n\n/**\n * A SvelteKit endpoint handler — the built-in\n * [`RequestHandler`](https://svelte.dev/docs/kit/@sveltejs-kit#RequestHandler) —\n * backed by an Effect HTTP construct. Assign it to a `+server.ts` export\n * (`fallback`, `GET`, ...). `dispose()` closes the scope of the layer behind it.\n */\nexport type EndpointHandler = RequestHandler & {\n /** Close the scope of the layer backing the endpoint (runs its finalizers). */\n readonly dispose: () => Promise<void>;\n};\n\n/** Shared options for every `Endpoint.from*` helper. */\nexport interface EndpointOptions {\n /**\n * A leading path segment to strip from each request before it reaches the\n * Effect handler — the SvelteKit mount point. For an endpoint mounted at\n * `src/routes/api/[...path]/+server.ts` whose routes are defined relative to\n * the API root, pass `prefix: \"/api\"` so `/api/users` is dispatched as\n * `/users`. The match respects path boundaries (`/api` does not strip\n * `/apiary`). Defaults to no stripping.\n */\n readonly prefix?: string;\n}\n\nconst noopDispose = (): Promise<void> => Promise.resolve();\n\n/** Remove `prefix` from the request's path (respecting `/` boundaries). */\nconst stripPrefix = (request: Request, prefix: string): Request => {\n const normalized = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n if (normalized === \"\") return request;\n\n const url = new URL(request.url);\n const path = url.pathname;\n if (path === normalized) {\n url.pathname = \"/\";\n } else if (path.startsWith(`${normalized}/`)) {\n url.pathname = path.slice(normalized.length);\n } else {\n return request;\n }\n return new Request(url, request);\n};\n\n/** Wrap a Web handler (and its dispose) as a SvelteKit endpoint handler. */\nconst make = <RequestServices = never>(\n webHandler: WebHandler | WebHandlerWithContext,\n dispose: () => Promise<void>,\n prefix: string | undefined,\n context?: RequestContext<RequestServices>,\n): EndpointHandler => {\n const handler: RequestHandler = async (event) => {\n const request = prefix === undefined ? event.request : stripPrefix(event.request, prefix);\n if (context === undefined) return (webHandler as WebHandler)(request);\n const ctx = await resolveRequestContext(request, context);\n return (webHandler as WebHandlerWithContext)(\n request,\n ctx as Context.Context<never> | undefined,\n );\n };\n return Object.assign(handler, { dispose });\n};\n\n/** The platform services an `HttpApi` needs, with a no-op file system. */\nconst apiPlatform = Layer.mergeAll(Path.layer, Etag.layerWeak, HttpPlatform.layer).pipe(\n Layer.provideMerge(FileSystem.layerNoop({})),\n);\n\n/**\n * Create a SvelteKit endpoint that serves an Effect\n * [`HttpApi`](https://effect.website).\n *\n * `layer` implements the API's groups (built with `HttpApiBuilder.group`), with\n * any application services already provided. The platform services an `HttpApi`\n * requires (`HttpPlatform`, `FileSystem`, `Path`, `Etag`) are supplied for you.\n *\n * @example\n * ```ts\n * // src/routes/api/[...path]/+server.ts\n * import { Endpoint } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { api } from \"$lib/server/api\";\n * import { ApiLive } from \"$lib/server/handlers\";\n *\n * export const fallback = Endpoint.fromApi(api, ApiLive, { prefix: \"/api\" });\n * ```\n */\nexport const fromApi = <\n Id extends string,\n Groups extends HttpApiGroup.Constraint,\n E,\n LayerRequires = never,\n RequestServices = never,\n>(\n api: HttpApi.HttpApi<Id, Groups>,\n layer: Layer.Layer<HttpApiGroup.ToService<Id, Groups>, E, LayerRequires>,\n options?: EndpointOptions & {\n /** Serve the OpenAPI spec for the API at this path (e.g. `\"/openapi.json\"`). */\n readonly openapiPath?: `/${string}`;\n /** Add Effect's request logger middleware. Defaults to `false` (quiet). */\n readonly logger?: boolean;\n /**\n * Provide the request-scoped services the API groups require, per request.\n * The build-once platform layer (`HttpPlatform` / `FileSystem` / `Path` /\n * `Etag`) stays shared; only this slice is resolved and merged for each\n * dispatch — so a session-aware, request-pooled API can run on Workers\n * without rebuilding its platform layer.\n *\n * The resolver may return a `Context` or an `Effect` producing one. Leave\n * the matching services unprovided in `layer` and supply them here:\n *\n * ```ts\n * Endpoint.fromApi(api, ApiLive, {\n * prefix: \"/api\",\n * context: (request) => Context.make(CurrentUser, userFor(request)),\n * });\n * ```\n */\n readonly context?: RequestContext<RequestServices>;\n },\n): EndpointHandler => {\n const appLayer = HttpApiBuilder.layer(\n api,\n options?.openapiPath ? { openapiPath: options.openapiPath } : undefined,\n ).pipe(Layer.provide(layer), Layer.provide(apiPlatform));\n\n // The request-scoped services are supplied per dispatch via the web handler's\n // context argument, so they are hidden from the build-once layer here.\n const { handler, dispose } = HttpRouter.toWebHandler(\n appLayer as unknown as Layer.Layer<never, E, HttpRouter.HttpRouter>,\n { disableLogger: options?.logger !== true },\n );\n return make<RequestServices>(\n handler as WebHandlerWithContext,\n dispose,\n options?.prefix,\n options?.context,\n );\n};\n\n/**\n * Create a SvelteKit endpoint that serves an Effect `HttpRouter` (provided by\n * `layer`). The router's routes must be self-contained (any services they need\n * are provided within `layer`).\n *\n * @example\n * ```ts\n * // src/routes/api/[...path]/+server.ts\n * import { Endpoint } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Effect } from \"effect\";\n * import { HttpRouter, HttpServerResponse } from \"effect/http\";\n *\n * const RouterLive = HttpRouter.use((router) =>\n * router.add(\"GET\", \"/hello\", Effect.succeed(HttpServerResponse.text(\"hi\"))),\n * );\n *\n * export const fallback = Endpoint.fromRouter(RouterLive, { prefix: \"/api\" });\n * ```\n */\nexport const fromRouter = <\n A,\n E,\n R extends\n | HttpRouter.HttpRouter\n | HttpRouter.Request<\"Requires\", any>\n | HttpRouter.Request<\"GlobalRequires\", any>\n | HttpRouter.Request<\"Error\", any>\n | HttpRouter.Request<\"GlobalError\", any>,\n RequestServices = never,\n>(\n layer: Layer.Layer<A, E, R>,\n options?: EndpointOptions & {\n /** Add Effect's request logger middleware. Defaults to `false` (quiet). */\n readonly logger?: boolean;\n /**\n * Provide the request-scoped services the router's routes require, per\n * request (the routes' `HttpRouter.Request<\"Requires\", ...>` services). The\n * resolver may return a `Context` or an `Effect` producing one.\n */\n readonly context?: RequestContext<RequestServices>;\n },\n): EndpointHandler => {\n const { handler, dispose } = HttpRouter.toWebHandler(layer, {\n disableLogger: options?.logger !== true,\n });\n return make<RequestServices>(\n handler as WebHandlerWithContext,\n dispose,\n options?.prefix,\n options?.context,\n );\n};\n\n/**\n * Create a SvelteKit endpoint from a single Effect HTTP route — an effect\n * producing an `HttpServerResponse` for the current `HttpServerRequest`. Pass\n * `options.layer` to provide the route's services; the layer is built once and\n * shared.\n *\n * @example\n * ```ts\n * // src/routes/health/+server.ts\n * import { Endpoint } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Effect } from \"effect\";\n * import { HttpServerResponse } from \"effect/http\";\n *\n * export const GET = Endpoint.fromHttpEffect(\n * Effect.succeed(HttpServerResponse.text(\"ok\")),\n * );\n * ```\n */\nexport const fromHttpEffect = <E, R = never, ProvidedE = never>(\n effect: Effect.Effect<\n HttpServerResponse.HttpServerResponse,\n E,\n R | HttpServerRequest.HttpServerRequest | Scope.Scope\n >,\n options?: EndpointOptions & {\n /** A layer providing the route's services (`R`), built once and shared. */\n readonly layer?: Layer.Layer<R, ProvidedE>;\n },\n): EndpointHandler => {\n if (options?.layer) {\n const { handler, dispose } = HttpEffect.toWebHandlerLayer(effect, options.layer);\n return make(handler as WebHandler, dispose, options.prefix);\n }\n const handler = HttpEffect.toWebHandler(\n effect as Effect.Effect<\n HttpServerResponse.HttpServerResponse,\n E,\n HttpServerRequest.HttpServerRequest | Scope.Scope\n >,\n );\n return make(handler, noopDispose, options?.prefix);\n};\n\n/** Options for {@link fromStream}: how to frame each element as an SSE event. */\nexport interface FromStreamOptions<A, R = never> {\n /**\n * The event name (`event:` field). A string applies to every element, or a\n * function derives it per element (return `undefined` for an unnamed event).\n * Omit for the default unnamed `message` events.\n */\n readonly event?: string | ((value: A) => string | undefined);\n /**\n * Encode an element into the `data:` payload. Defaults to `JSON.stringify`.\n * Multi-line output is split across multiple `data:` lines automatically.\n */\n readonly data?: (value: A) => string;\n /** Derive an event id (`id:` field) the browser echoes on reconnect. */\n readonly id?: (value: A) => string | undefined;\n /**\n * The client reconnection delay in milliseconds, sent once as a leading\n * `retry:` field. The browser's `EventSource` reconnects automatically after\n * this delay when the connection drops.\n */\n readonly retry?: number;\n /**\n * Send a comment heartbeat on this interval to keep the connection alive\n * through proxies that time out idle streams. Accepts any `Duration.Input`\n * (e.g. `\"30 seconds\"`).\n */\n readonly heartbeat?: Duration.Input;\n /**\n * A layer (or context) providing the stream's services `R`, applied per\n * connection. Omit when the stream is self-contained (`R = never`).\n */\n readonly provide?: Layer.Layer<R> | Context.Context<R>;\n}\n\n/**\n * Create a SvelteKit endpoint that streams an Effect `Stream` to the browser as\n * [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)\n * (`text/event-stream`). Consume it client-side with `Realtime.fromEventSource`\n * (from `@thomasfosterau/effect-sveltekit/client`) or the native `EventSource`.\n *\n * Each element is framed as one SSE event (`event` / `id` optional, `data`\n * defaults to JSON). A `retry` sets the reconnect delay; a `heartbeat` keeps\n * idle connections alive. The response closes when the stream ends; the stream\n * is interrupted (running its finalizers) when the client disconnects.\n *\n * @example\n * ```ts\n * // src/routes/events/+server.ts\n * import { Endpoint } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Schedule, Stream } from \"effect\";\n *\n * const ticks = Stream.fromSchedule(Schedule.spaced(\"1 second\"));\n *\n * export const GET = Endpoint.fromStream(ticks, {\n * event: \"tick\",\n * heartbeat: \"30 seconds\",\n * retry: 3000,\n * });\n * ```\n */\nexport const fromStream = <A, E, R = never>(\n stream: Stream.Stream<A, E, R>,\n options?: FromStreamOptions<A, R>,\n): RequestHandler => {\n const encodeData = options?.data ?? ((value: A): string => JSON.stringify(value));\n const eventOf = (value: A): string | undefined =>\n typeof options?.event === \"function\" ? options.event(value) : options?.event;\n\n return (event) => {\n // Frame each element, then encode the resulting strings to bytes.\n const events = stream.pipe(\n Stream.map((value) =>\n encodeSseFrame({\n data: encodeData(value),\n event: eventOf(value),\n id: options?.id?.(value),\n }),\n ),\n );\n\n // A leading `retry:` field, if configured.\n const withRetry =\n options?.retry === undefined ? events : Stream.prepend(events, [encodeRetry(options.retry)]);\n\n // Merge in a heartbeat that halts as soon as the data stream ends.\n const framed =\n options?.heartbeat === undefined\n ? withRetry\n : Stream.merge(\n withRetry,\n Stream.fromSchedule(Schedule.spaced(options.heartbeat)).pipe(\n Stream.map(() => HEARTBEAT_FRAME),\n ),\n { haltStrategy: \"left\" },\n );\n\n const bytes = Stream.encodeText(framed);\n const provided =\n options?.provide === undefined ? bytes : Stream.provide(bytes, options.provide);\n\n const body = Stream.toReadableStream(provided as Stream.Stream<Uint8Array, E>);\n\n // SvelteKit forwards a streaming body Response as-is.\n void event;\n return new Response(body, { headers: { ...SSE_HEADERS } });\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"Endpoint.js","names":[],"sources":["../../src/server/Endpoint.ts"],"sourcesContent":["/**\n * Create SvelteKit server endpoints (`+server.ts`) backed by Effect — the\n * `Endpoint` namespace of `@thomasfosterau/effect-sveltekit/server`.\n *\n * A SvelteKit endpoint is a `RequestHandler` (`(event) => Response`). Effect can\n * turn an [`HttpApi`](https://effect.website), an `HttpRouter`, or a single\n * route effect into a Web `fetch` handler; these helpers wrap one as a SvelteKit\n * endpoint handler so a route can be served by Effect. Mount it on a catch-all\n * route (`[...path]`) and assign it to `fallback` so every method and sub-path\n * reaches it:\n *\n * @example\n * ```ts\n * // src/routes/api/[...path]/+server.ts\n * import { Endpoint } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { api } from \"#lib/server/api.ts\";\n * import { ApiLive } from \"#lib/server/handlers.ts\"; // HttpApiBuilder.group(...) + your services\n *\n * // `prefix` strips the SvelteKit mount path so the API's own paths\n * // (e.g. \"/users\") match.\n * export const fallback = Endpoint.fromApi(api, ApiLive, { prefix: \"/api\" });\n * ```\n *\n * The layer backing an endpoint is built once, lazily, on the first request and\n * shared across subsequent requests (like `makeServerRuntime`). The returned\n * handler carries a `dispose()` that closes the layer's scope — call it on\n * shutdown if the endpoint holds resources.\n *\n * The Effect handlers receive an Effect-native `HttpServerRequest` (built from\n * `event.request`), not the SvelteKit `RequestEvent`.\n */\n\nimport type { RequestHandler } from \"@sveltejs/kit\";\nimport { Context, type Duration, Effect, Layer, Schedule, Stream } from \"effect\";\nimport type { Scope } from \"effect\";\nimport * as FileSystem from \"effect/FileSystem\";\nimport * as Path from \"effect/Path\";\nimport * as Etag from \"effect/http/Etag\";\nimport * as HttpEffect from \"effect/http/HttpEffect\";\nimport * as HttpPlatform from \"effect/http/HttpPlatform\";\nimport * as HttpRouter from \"effect/http/HttpRouter\";\nimport type * as HttpServerRequest from \"effect/http/HttpServerRequest\";\nimport type * as HttpServerResponse from \"effect/http/HttpServerResponse\";\nimport type * as HttpApi from \"effect/http-api/HttpApi\";\nimport * as HttpApiBuilder from \"effect/http-api/HttpApiBuilder\";\nimport type * as HttpApiGroup from \"effect/http-api/HttpApiGroup\";\nimport { encodeRetry, encodeSseFrame, HEARTBEAT_FRAME, SSE_HEADERS } from \"../internal/sse.js\";\n\n/** A Web `fetch`-style handler, as produced by Effect's `toWebHandler` family. */\ntype WebHandler = (request: Request) => Promise<Response>;\n\n/** A Web handler that also accepts a per-request service context. */\ntype WebHandlerWithContext = (\n request: Request,\n context?: Context.Context<never>,\n) => Promise<Response>;\n\n/**\n * Resolve a request-scoped service context, if a resolver was given. The\n * resolver may return a `Context` directly or an `Effect` producing one (run\n * with no requirements), so a consumer can read the request to build\n * session-aware services per dispatch.\n */\nexport type RequestContext<RequestServices> = (\n request: Request,\n) =>\n | Context.Context<RequestServices>\n | Effect.Effect<Context.Context<RequestServices>, never, never>;\n\nconst resolveRequestContext = async <RequestServices>(\n request: Request,\n context: RequestContext<RequestServices> | undefined,\n): Promise<Context.Context<RequestServices> | undefined> => {\n if (context === undefined) return undefined;\n const result = context(request);\n return Effect.isEffect(result) ? Effect.runPromise(result) : result;\n};\n\n/**\n * A SvelteKit endpoint handler — the built-in\n * [`RequestHandler`](https://svelte.dev/docs/kit/@sveltejs-kit#RequestHandler) —\n * backed by an Effect HTTP construct. Assign it to a `+server.ts` export\n * (`fallback`, `GET`, ...). `dispose()` closes the scope of the layer behind it.\n */\nexport type EndpointHandler = RequestHandler & {\n /** Close the scope of the layer backing the endpoint (runs its finalizers). */\n readonly dispose: () => Promise<void>;\n};\n\n/** Shared options for every `Endpoint.from*` helper. */\nexport interface EndpointOptions {\n /**\n * A leading path segment to strip from each request before it reaches the\n * Effect handler — the SvelteKit mount point. For an endpoint mounted at\n * `src/routes/api/[...path]/+server.ts` whose routes are defined relative to\n * the API root, pass `prefix: \"/api\"` so `/api/users` is dispatched as\n * `/users`. The match respects path boundaries (`/api` does not strip\n * `/apiary`). Defaults to no stripping.\n */\n readonly prefix?: string;\n}\n\nconst noopDispose = (): Promise<void> => Promise.resolve();\n\n/** Remove `prefix` from the request's path (respecting `/` boundaries). */\nconst stripPrefix = (request: Request, prefix: string): Request => {\n const normalized = prefix.endsWith(\"/\") ? prefix.slice(0, -1) : prefix;\n if (normalized === \"\") return request;\n\n const url = new URL(request.url);\n const path = url.pathname;\n if (path === normalized) {\n url.pathname = \"/\";\n } else if (path.startsWith(`${normalized}/`)) {\n url.pathname = path.slice(normalized.length);\n } else {\n return request;\n }\n return new Request(url, request);\n};\n\n/** Wrap a Web handler (and its dispose) as a SvelteKit endpoint handler. */\nconst make = <RequestServices = never>(\n webHandler: WebHandler | WebHandlerWithContext,\n dispose: () => Promise<void>,\n prefix: string | undefined,\n context?: RequestContext<RequestServices>,\n): EndpointHandler => {\n const handler: RequestHandler = async (event) => {\n const request = prefix === undefined ? event.request : stripPrefix(event.request, prefix);\n if (context === undefined) return (webHandler as WebHandler)(request);\n const ctx = await resolveRequestContext(request, context);\n return (webHandler as WebHandlerWithContext)(\n request,\n ctx as Context.Context<never> | undefined,\n );\n };\n return Object.assign(handler, { dispose });\n};\n\n/** The platform services an `HttpApi` needs, with a no-op file system. */\nconst apiPlatform = Layer.mergeAll(Path.layer, Etag.layerWeak, HttpPlatform.layer).pipe(\n Layer.provideMerge(FileSystem.layerNoop({})),\n);\n\n/**\n * Create a SvelteKit endpoint that serves an Effect\n * [`HttpApi`](https://effect.website).\n *\n * `layer` implements the API's groups (built with `HttpApiBuilder.group`), with\n * any application services already provided. The platform services an `HttpApi`\n * requires (`HttpPlatform`, `FileSystem`, `Path`, `Etag`) are supplied for you.\n *\n * @example\n * ```ts\n * // src/routes/api/[...path]/+server.ts\n * import { Endpoint } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { api } from \"#lib/server/api.ts\";\n * import { ApiLive } from \"#lib/server/handlers.ts\";\n *\n * export const fallback = Endpoint.fromApi(api, ApiLive, { prefix: \"/api\" });\n * ```\n */\nexport const fromApi = <\n Id extends string,\n Groups extends HttpApiGroup.Constraint,\n E,\n LayerRequires = never,\n RequestServices = never,\n>(\n api: HttpApi.HttpApi<Id, Groups>,\n layer: Layer.Layer<HttpApiGroup.ToService<Id, Groups>, E, LayerRequires>,\n options?: EndpointOptions & {\n /** Serve the OpenAPI spec for the API at this path (e.g. `\"/openapi.json\"`). */\n readonly openapiPath?: `/${string}`;\n /** Add Effect's request logger middleware. Defaults to `false` (quiet). */\n readonly logger?: boolean;\n /**\n * Provide the request-scoped services the API groups require, per request.\n * The build-once platform layer (`HttpPlatform` / `FileSystem` / `Path` /\n * `Etag`) stays shared; only this slice is resolved and merged for each\n * dispatch — so a session-aware, request-pooled API can run on Workers\n * without rebuilding its platform layer.\n *\n * The resolver may return a `Context` or an `Effect` producing one. Leave\n * the matching services unprovided in `layer` and supply them here:\n *\n * ```ts\n * Endpoint.fromApi(api, ApiLive, {\n * prefix: \"/api\",\n * context: (request) => Context.make(CurrentUser, userFor(request)),\n * });\n * ```\n */\n readonly context?: RequestContext<RequestServices>;\n },\n): EndpointHandler => {\n const appLayer = HttpApiBuilder.layer(\n api,\n options?.openapiPath ? { openapiPath: options.openapiPath } : undefined,\n ).pipe(Layer.provide(layer), Layer.provide(apiPlatform));\n\n // The request-scoped services are supplied per dispatch via the web handler's\n // context argument, so they are hidden from the build-once layer here.\n const { handler, dispose } = HttpRouter.toWebHandler(\n appLayer as unknown as Layer.Layer<never, E, HttpRouter.HttpRouter>,\n { disableLogger: options?.logger !== true },\n );\n return make<RequestServices>(\n handler as WebHandlerWithContext,\n dispose,\n options?.prefix,\n options?.context,\n );\n};\n\n/**\n * Create a SvelteKit endpoint that serves an Effect `HttpRouter` (provided by\n * `layer`). The router's routes must be self-contained (any services they need\n * are provided within `layer`).\n *\n * @example\n * ```ts\n * // src/routes/api/[...path]/+server.ts\n * import { Endpoint } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Effect } from \"effect\";\n * import { HttpRouter, HttpServerResponse } from \"effect/http\";\n *\n * const RouterLive = HttpRouter.use((router) =>\n * router.add(\"GET\", \"/hello\", Effect.succeed(HttpServerResponse.text(\"hi\"))),\n * );\n *\n * export const fallback = Endpoint.fromRouter(RouterLive, { prefix: \"/api\" });\n * ```\n */\nexport const fromRouter = <\n A,\n E,\n R extends\n | HttpRouter.HttpRouter\n | HttpRouter.Request<\"Requires\", any>\n | HttpRouter.Request<\"GlobalRequires\", any>\n | HttpRouter.Request<\"Error\", any>\n | HttpRouter.Request<\"GlobalError\", any>,\n RequestServices = never,\n>(\n layer: Layer.Layer<A, E, R>,\n options?: EndpointOptions & {\n /** Add Effect's request logger middleware. Defaults to `false` (quiet). */\n readonly logger?: boolean;\n /**\n * Provide the request-scoped services the router's routes require, per\n * request (the routes' `HttpRouter.Request<\"Requires\", ...>` services). The\n * resolver may return a `Context` or an `Effect` producing one.\n */\n readonly context?: RequestContext<RequestServices>;\n },\n): EndpointHandler => {\n const { handler, dispose } = HttpRouter.toWebHandler(layer, {\n disableLogger: options?.logger !== true,\n });\n return make<RequestServices>(\n handler as WebHandlerWithContext,\n dispose,\n options?.prefix,\n options?.context,\n );\n};\n\n/**\n * Create a SvelteKit endpoint from a single Effect HTTP route — an effect\n * producing an `HttpServerResponse` for the current `HttpServerRequest`. Pass\n * `options.layer` to provide the route's services; the layer is built once and\n * shared.\n *\n * @example\n * ```ts\n * // src/routes/health/+server.ts\n * import { Endpoint } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Effect } from \"effect\";\n * import { HttpServerResponse } from \"effect/http\";\n *\n * export const GET = Endpoint.fromHttpEffect(\n * Effect.succeed(HttpServerResponse.text(\"ok\")),\n * );\n * ```\n */\nexport const fromHttpEffect = <E, R = never, ProvidedE = never>(\n effect: Effect.Effect<\n HttpServerResponse.HttpServerResponse,\n E,\n R | HttpServerRequest.HttpServerRequest | Scope.Scope\n >,\n options?: EndpointOptions & {\n /** A layer providing the route's services (`R`), built once and shared. */\n readonly layer?: Layer.Layer<R, ProvidedE>;\n },\n): EndpointHandler => {\n if (options?.layer) {\n const { handler, dispose } = HttpEffect.toWebHandlerLayer(effect, options.layer);\n return make(handler as WebHandler, dispose, options.prefix);\n }\n const handler = HttpEffect.toWebHandler(\n effect as Effect.Effect<\n HttpServerResponse.HttpServerResponse,\n E,\n HttpServerRequest.HttpServerRequest | Scope.Scope\n >,\n );\n return make(handler, noopDispose, options?.prefix);\n};\n\n/** Options for {@link fromStream}: how to frame each element as an SSE event. */\nexport interface FromStreamOptions<A, R = never> {\n /**\n * The event name (`event:` field). A string applies to every element, or a\n * function derives it per element (return `undefined` for an unnamed event).\n * Omit for the default unnamed `message` events.\n */\n readonly event?: string | ((value: A) => string | undefined);\n /**\n * Encode an element into the `data:` payload. Defaults to `JSON.stringify`.\n * Multi-line output is split across multiple `data:` lines automatically.\n */\n readonly data?: (value: A) => string;\n /** Derive an event id (`id:` field) the browser echoes on reconnect. */\n readonly id?: (value: A) => string | undefined;\n /**\n * The client reconnection delay in milliseconds, sent once as a leading\n * `retry:` field. The browser's `EventSource` reconnects automatically after\n * this delay when the connection drops.\n */\n readonly retry?: number;\n /**\n * Send a comment heartbeat on this interval to keep the connection alive\n * through proxies that time out idle streams. Accepts any `Duration.Input`\n * (e.g. `\"30 seconds\"`).\n */\n readonly heartbeat?: Duration.Input;\n /**\n * A layer (or context) providing the stream's services `R`, applied per\n * connection. Omit when the stream is self-contained (`R = never`).\n */\n readonly provide?: Layer.Layer<R> | Context.Context<R>;\n}\n\n/**\n * Create a SvelteKit endpoint that streams an Effect `Stream` to the browser as\n * [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)\n * (`text/event-stream`). Consume it client-side with `Realtime.fromEventSource`\n * (from `@thomasfosterau/effect-sveltekit/client`) or the native `EventSource`.\n *\n * Each element is framed as one SSE event (`event` / `id` optional, `data`\n * defaults to JSON). A `retry` sets the reconnect delay; a `heartbeat` keeps\n * idle connections alive. The response closes when the stream ends; the stream\n * is interrupted (running its finalizers) when the client disconnects.\n *\n * @example\n * ```ts\n * // src/routes/events/+server.ts\n * import { Endpoint } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Schedule, Stream } from \"effect\";\n *\n * const ticks = Stream.fromSchedule(Schedule.spaced(\"1 second\"));\n *\n * export const GET = Endpoint.fromStream(ticks, {\n * event: \"tick\",\n * heartbeat: \"30 seconds\",\n * retry: 3000,\n * });\n * ```\n */\nexport const fromStream = <A, E, R = never>(\n stream: Stream.Stream<A, E, R>,\n options?: FromStreamOptions<A, R>,\n): RequestHandler => {\n const encodeData = options?.data ?? ((value: A): string => JSON.stringify(value));\n const eventOf = (value: A): string | undefined =>\n typeof options?.event === \"function\" ? options.event(value) : options?.event;\n\n return (event) => {\n // Frame each element, then encode the resulting strings to bytes.\n const events = stream.pipe(\n Stream.map((value) =>\n encodeSseFrame({\n data: encodeData(value),\n event: eventOf(value),\n id: options?.id?.(value),\n }),\n ),\n );\n\n // A leading `retry:` field, if configured.\n const withRetry =\n options?.retry === undefined ? events : Stream.prepend(events, [encodeRetry(options.retry)]);\n\n // Merge in a heartbeat that halts as soon as the data stream ends.\n const framed =\n options?.heartbeat === undefined\n ? withRetry\n : Stream.merge(\n withRetry,\n Stream.fromSchedule(Schedule.spaced(options.heartbeat)).pipe(\n Stream.map(() => HEARTBEAT_FRAME),\n ),\n { haltStrategy: \"left\" },\n );\n\n const bytes = Stream.encodeText(framed);\n const provided =\n options?.provide === undefined ? bytes : Stream.provide(bytes, options.provide);\n\n const body = Stream.toReadableStream(provided as Stream.Stream<Uint8Array, E>);\n\n // SvelteKit forwards a streaming body Response as-is.\n void event;\n return new Response(body, { headers: { ...SSE_HEADERS } });\n };\n};\n"],"mappings":"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"}