@thomasfosterau/effect-sveltekit 0.3.1 → 0.4.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 (95) hide show
  1. package/README.md +3 -3
  2. package/dist/Hooks.d.ts +4 -5
  3. package/dist/Hooks.js +3 -1
  4. package/dist/Hooks.js.map +1 -1
  5. package/dist/Navigation.d.ts +1 -3
  6. package/dist/Navigation.js +1 -1
  7. package/dist/Remote.d.ts +1 -3
  8. package/dist/Remote.js +1 -1
  9. package/dist/Remote.js.map +1 -1
  10. package/dist/State.d.ts +1 -3
  11. package/dist/State.js +1 -1
  12. package/dist/adapter/assets.d.ts +7 -5
  13. package/dist/adapter/assets.js +3 -3
  14. package/dist/adapter/assets.js.map +1 -1
  15. package/dist/adapter/handler.d.ts +4 -5
  16. package/dist/adapter/handler.js +12 -12
  17. package/dist/adapter/handler.js.map +1 -1
  18. package/dist/adapter/index.d.ts +1 -2
  19. package/dist/adapter/index.js +3 -3
  20. package/dist/adapter/index.js.map +1 -1
  21. package/dist/adapter/serve.d.ts +0 -1
  22. package/dist/adapter/serve.js +4 -4
  23. package/dist/adapter/serve.js.map +1 -1
  24. package/dist/api-client.d.ts +5 -6
  25. package/dist/api-client.js +2 -2
  26. package/dist/api-client.js.map +1 -1
  27. package/dist/app-runtime.d.ts +1 -2
  28. package/dist/app-runtime.js +3 -2
  29. package/dist/app-runtime.js.map +1 -1
  30. package/dist/client/Hooks.d.ts +1 -3
  31. package/dist/client/Hooks.js +1 -1
  32. package/dist/config.d.ts +2 -3
  33. package/dist/config.js +5 -5
  34. package/dist/config.js.map +1 -1
  35. package/dist/errors.d.ts +88 -0
  36. package/dist/errors.js +126 -0
  37. package/dist/errors.js.map +1 -0
  38. package/dist/forms.d.ts +2 -3
  39. package/dist/forms.js +1 -1
  40. package/dist/index.d.ts +2 -1
  41. package/dist/index.js +2 -1
  42. package/dist/internal/app-state.d.ts +1 -2
  43. package/dist/internal/app-state.js +1 -1
  44. package/dist/internal/auto.d.ts +0 -1
  45. package/dist/internal/auto.js.map +1 -1
  46. package/dist/internal/enhance.d.ts +0 -1
  47. package/dist/internal/enhance.js.map +1 -1
  48. package/dist/internal/error.js +1 -1
  49. package/dist/internal/remote-run.d.ts +2 -2
  50. package/dist/internal/remote-run.js.map +1 -1
  51. package/dist/internal/remote-validators.js +1 -1
  52. package/dist/internal/route-params.d.ts +0 -1
  53. package/dist/kit.d.ts +2 -3
  54. package/dist/realtime.d.ts +3 -5
  55. package/dist/realtime.js +1 -1
  56. package/dist/realtime.js.map +1 -1
  57. package/dist/remote-functions.d.ts +2 -3
  58. package/dist/remote-functions.js +2 -2
  59. package/dist/remote-functions.js.map +1 -1
  60. package/dist/remote-reactive.d.ts +1 -2
  61. package/dist/remote-reactive.js +1 -1
  62. package/dist/remote-reactive.js.map +1 -1
  63. package/dist/request-parse.d.ts +1 -2
  64. package/dist/request-parse.js.map +1 -1
  65. package/dist/request-runtime.d.ts +0 -1
  66. package/dist/request-runtime.js.map +1 -1
  67. package/dist/request-services.d.ts +0 -1
  68. package/dist/request-services.js.map +1 -1
  69. package/dist/response-headers.d.ts +24 -0
  70. package/dist/response-headers.js +35 -0
  71. package/dist/response-headers.js.map +1 -0
  72. package/dist/runtime.d.ts +2 -3
  73. package/dist/runtime.js +3 -3
  74. package/dist/runtime.js.map +1 -1
  75. package/dist/server/Endpoint.d.ts +18 -15
  76. package/dist/server/Endpoint.js +10 -9
  77. package/dist/server/Endpoint.js.map +1 -1
  78. package/dist/server/Hooks.d.ts +1 -3
  79. package/dist/server/Hooks.js +1 -1
  80. package/dist/server/Hooks.js.map +1 -1
  81. package/dist/server.d.ts +5 -4
  82. package/dist/server.js +5 -3
  83. package/dist/server.js.map +1 -1
  84. package/dist/streamed-load.d.ts +0 -1
  85. package/dist/streamed-load.js.map +1 -1
  86. package/dist/testing.d.ts +0 -1
  87. package/dist/testing.js.map +1 -1
  88. package/dist/transport.d.ts +0 -1
  89. package/dist/universal.d.ts +3 -4
  90. package/dist/universal.js +3 -3
  91. package/dist/universal.js.map +1 -1
  92. package/dist/vite.d.ts +0 -1
  93. package/dist/vite.js +2 -2
  94. package/dist/vite.js.map +1 -1
  95. package/package.json +8 -5
@@ -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 {\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":";;;;AAqDA,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,6 +1,5 @@
1
1
  import { Context, Effect, ManagedRuntime } from "effect";
2
2
  import { SubmitFunction } from "@sveltejs/kit";
3
-
4
3
  //#region src/internal/enhance.d.ts
5
4
  /** The input SvelteKit passes to a `SubmitFunction` before the request is sent. */
6
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,EAAE,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 \"@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"}
@@ -26,6 +26,6 @@ const causeToThrowable = (cause) => {
26
26
  return new EffectCauseError(Cause.pretty(cause), cause);
27
27
  };
28
28
  //#endregion
29
- export { causeToThrowable };
29
+ export { EffectCauseError, causeToThrowable };
30
30
 
31
31
  //# sourceMappingURL=error.js.map
@@ -1,6 +1,6 @@
1
+ import "../request-runtime.js";
1
2
  import { Effect, Exit } from "effect";
2
3
  import { InvalidField } from "@sveltejs/kit";
3
-
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
@@ -24,5 +24,5 @@ interface RunHelpers {
24
24
  readonly runForm: FormRunner;
25
25
  }
26
26
  //#endregion
27
- export { FormErrorMapper, RunHelpers };
27
+ export { FormErrorMapper, FormRunner, RunHelpers, Runner };
28
28
  //# sourceMappingURL=remote-run.d.ts.map
@@ -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\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;;AAkC3D,MAAa,kBACX,SACA,WACA,cACe;CACf,MAAM,OAAe,WAAW;EAC9B,MAAM,EAAE,SAAS,YAAY,QAAQ;EACrC,OAAO,QAAQ,MAAM,EAAE,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,EAAE,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 { 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\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;;AAkC3D,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"}
@@ -18,6 +18,6 @@ const isBareHandler = (value) => typeof value === "function" && !isStandardSchem
18
18
  */
19
19
  const toStandardValidator = (value) => Schema.isSchema(value) ? Schema.toStandardSchemaV1(value) : value;
20
20
  //#endregion
21
- export { isBareHandler, toStandardValidator };
21
+ export { isBareHandler, isStandardSchema, toStandardValidator };
22
22
 
23
23
  //# sourceMappingURL=remote-validators.js.map
@@ -1,5 +1,4 @@
1
1
  import { RequestEvent } from "@sveltejs/kit";
2
-
3
2
  //#region src/internal/route-params.d.ts
4
3
  /**
5
4
  * The route-parameter constraint SvelteKit uses for its own handler types
package/dist/kit.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Cause, Effect } from "effect";
2
-
3
2
  //#region src/kit.d.ts
4
3
  /**
5
4
  * An Effect-native redirect. Yield via {@link SvelteKit.redirect}; translated
@@ -17,9 +16,9 @@ declare class KitRedirect extends Error {
17
16
  */
18
17
  declare class KitError extends Error {
19
18
  readonly status: number;
20
- readonly body?: string | Record<string, unknown> | undefined;
19
+ readonly body?: (string | Record<string, unknown>) | undefined;
21
20
  readonly _tag: "KitError";
22
- constructor(status: number, body?: string | Record<string, unknown> | undefined);
21
+ constructor(status: number, body?: (string | Record<string, unknown>) | undefined);
23
22
  }
24
23
  /**
25
24
  * An Effect-native form-action failure. Yield via {@link SvelteKit.fail};
@@ -1,6 +1,4 @@
1
1
  import { Cause, Stream } from "effect";
2
-
3
- //#region src/realtime.d.ts
4
2
  declare namespace realtime_d_exports {
5
3
  export { EventSourceConstructor, EventSourceError, FromEventSourceOptions, FromWebSocketOptions, SseMessage, WebSocketConstructor, WebSocketError, fromEventSource, fromWebSocket };
6
4
  }
@@ -13,7 +11,7 @@ interface SseMessage {
13
11
  /** The last event id seen, or `""` if none. */
14
12
  readonly lastEventId: string;
15
13
  }
16
- declare const EventSourceError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => Cause.YieldableError & {
14
+ declare const EventSourceError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Cause.YieldableError & {
17
15
  readonly _tag: "EventSourceError";
18
16
  } & Readonly<A>;
19
17
  /** Raised when an `EventSource` connection fails fatally (its `readyState` is `CLOSED`). */
@@ -58,7 +56,7 @@ interface FromEventSourceOptions {
58
56
  * ```
59
57
  */
60
58
  declare const fromEventSource: (url: string, options?: FromEventSourceOptions) => Stream.Stream<SseMessage, EventSourceError>;
61
- declare const WebSocketError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => Cause.YieldableError & {
59
+ declare const WebSocketError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Cause.YieldableError & {
62
60
  readonly _tag: "WebSocketError";
63
61
  } & Readonly<A>;
64
62
  /** Raised when a `WebSocket` errors or closes uncleanly. */
@@ -101,5 +99,5 @@ interface FromWebSocketOptions {
101
99
  */
102
100
  declare const fromWebSocket: (url: string, options?: FromWebSocketOptions) => Stream.Stream<string | ArrayBuffer | Blob, WebSocketError>;
103
101
  //#endregion
104
- export { realtime_d_exports };
102
+ export { EventSourceConstructor, EventSourceError, FromEventSourceOptions, FromWebSocketOptions, SseMessage, WebSocketConstructor, WebSocketError, fromEventSource, fromWebSocket, realtime_d_exports };
105
103
  //# sourceMappingURL=realtime.d.ts.map
package/dist/realtime.js CHANGED
@@ -106,6 +106,6 @@ const fromWebSocket = (url, options) => {
106
106
  });
107
107
  };
108
108
  //#endregion
109
- export { realtime_exports };
109
+ export { EventSourceError, WebSocketError, fromEventSource, fromWebSocket, realtime_exports };
110
110
 
111
111
  //# sourceMappingURL=realtime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"realtime.js","names":[],"sources":["../src/realtime.ts"],"sourcesContent":["/**\n * Client-side realtime bridges: consume a Server-Sent-Events endpoint or a\n * WebSocket as an Effect `Stream`. The counterpart to `Endpoint.fromStream`\n * (server) on the `@thomasfosterau/effect-sveltekit/client` `Realtime` namespace.\n *\n * These use the browser globals `EventSource` / `WebSocket`; both can be\n * overridden (e.g. a Node polyfill, or a fake in tests) via the `implementation`\n * option. The source is opened when the stream is run and closed when its scope\n * closes, so a `Stream.take` / component teardown tears down the connection.\n */\n\nimport { Cause, Data, Effect, Queue, Stream } from \"effect\";\n\n// ---------------------------------------------------------------------------\n// EventSource\n// ---------------------------------------------------------------------------\n\n/** A decoded Server-Sent Event. */\nexport interface SseMessage {\n /** The event name (`\"message\"` for unnamed events). */\n readonly event: string;\n /** The event payload (the joined `data:` lines). */\n readonly data: string;\n /** The last event id seen, or `\"\"` if none. */\n readonly lastEventId: string;\n}\n\n/** Raised when an `EventSource` connection fails fatally (its `readyState` is `CLOSED`). */\nexport class EventSourceError extends Data.TaggedError(\"EventSourceError\")<{\n readonly url: string;\n}> {}\n\n/** The subset of the `EventSource` constructor this module relies on. */\nexport type EventSourceConstructor = new (\n url: string,\n eventSourceInitDict?: { withCredentials?: boolean },\n) => EventSource;\n\nexport interface FromEventSourceOptions {\n /** Send credentials (cookies) with the request. Defaults to `false`. */\n readonly withCredentials?: boolean;\n /**\n * Named events to listen for in addition to the default unnamed `message`\n * event. An `Endpoint.fromStream({ event: \"tick\" })` server needs\n * `events: [\"tick\"]` here.\n */\n readonly events?: ReadonlyArray<string>;\n /** Buffer size for the backing queue. Defaults to 16. */\n readonly bufferSize?: number;\n /** Backpressure strategy when the buffer is full. Defaults to `\"sliding\"`. */\n readonly strategy?: \"sliding\" | \"dropping\" | \"suspend\";\n /** Override the `EventSource` constructor (Node polyfill, tests). */\n readonly implementation?: EventSourceConstructor;\n}\n\n/**\n * Consume a Server-Sent-Events endpoint as a `Stream` of {@link SseMessage}.\n *\n * The browser's `EventSource` reconnects automatically after transient drops,\n * so the stream stays live across reconnects; it fails with\n * {@link EventSourceError} only when the connection closes fatally.\n *\n * @example\n * ```ts\n * import { Realtime } from \"@thomasfosterau/effect-sveltekit/client\";\n * import { Effect, Stream } from \"effect\";\n *\n * const program = Realtime.fromEventSource(\"/events\", { events: [\"tick\"] }).pipe(\n * Stream.runForEach((msg) => Effect.log(`${msg.event}: ${msg.data}`)),\n * );\n * ```\n */\nexport const fromEventSource = (\n url: string,\n options?: FromEventSourceOptions,\n): Stream.Stream<SseMessage, EventSourceError> => {\n const Impl = options?.implementation ?? (globalThis.EventSource as EventSourceConstructor);\n return Stream.callback<SseMessage, EventSourceError>(\n (queue) =>\n Effect.sync(() => {\n const source =\n options?.withCredentials === undefined\n ? new Impl(url)\n : new Impl(url, { withCredentials: options.withCredentials });\n\n const onMessage = (e: MessageEvent): void => {\n Queue.offerUnsafe(queue, { event: e.type, data: e.data, lastEventId: e.lastEventId });\n };\n\n source.addEventListener(\"message\", onMessage);\n for (const name of options?.events ?? []) source.addEventListener(name, onMessage);\n\n source.addEventListener(\"error\", () => {\n // EventSource reconnects on its own unless it has closed for good.\n if (source.readyState === 2 /* CLOSED */) {\n Queue.failCauseUnsafe(queue, Cause.fail(new EventSourceError({ url })));\n }\n });\n\n return Effect.sync(() => source.close());\n }),\n { bufferSize: options?.bufferSize ?? 16, strategy: options?.strategy ?? \"sliding\" },\n );\n};\n\n// ---------------------------------------------------------------------------\n// WebSocket\n// ---------------------------------------------------------------------------\n\n/** Raised when a `WebSocket` errors or closes uncleanly. */\nexport class WebSocketError extends Data.TaggedError(\"WebSocketError\")<{\n readonly url: string;\n readonly code?: number;\n readonly reason?: string;\n}> {}\n\n/** The subset of the `WebSocket` constructor this module relies on. */\nexport type WebSocketConstructor = new (\n url: string,\n protocols?: string | ReadonlyArray<string>,\n) => WebSocket;\n\nexport interface FromWebSocketOptions {\n /** Sub-protocols passed to the `WebSocket` constructor. */\n readonly protocols?: string | ReadonlyArray<string>;\n /** `arraybuffer` or `blob` for binary frames. Defaults to the platform default. */\n readonly binaryType?: BinaryType;\n /** Buffer size for the backing queue. Defaults to 16. */\n readonly bufferSize?: number;\n /** Backpressure strategy when the buffer is full. Defaults to `\"suspend\"`. */\n readonly strategy?: \"sliding\" | \"dropping\" | \"suspend\";\n /** Override the `WebSocket` constructor (Node polyfill, tests). */\n readonly implementation?: WebSocketConstructor;\n}\n\n/**\n * Consume a `WebSocket` as a `Stream` of its message payloads\n * (`string | ArrayBuffer | Blob`, depending on `binaryType`).\n *\n * The stream ends when the socket closes cleanly and fails with\n * {@link WebSocketError} on an error or unclean close. The socket is closed when\n * the stream's scope closes.\n *\n * @example\n * ```ts\n * import { Realtime } from \"@thomasfosterau/effect-sveltekit/client\";\n * import { Effect, Stream } from \"effect\";\n *\n * const program = Realtime.fromWebSocket(\"wss://example.com/ws\").pipe(\n * Stream.runForEach((data) => Effect.log(String(data))),\n * );\n * ```\n */\nexport const fromWebSocket = (\n url: string,\n options?: FromWebSocketOptions,\n): Stream.Stream<string | ArrayBuffer | Blob, WebSocketError> => {\n const Impl = options?.implementation ?? (globalThis.WebSocket as WebSocketConstructor);\n return Stream.callback<string | ArrayBuffer | Blob, WebSocketError>(\n (queue) =>\n Effect.sync(() => {\n const socket = new Impl(url, options?.protocols);\n if (options?.binaryType !== undefined) socket.binaryType = options.binaryType;\n\n socket.addEventListener(\"message\", (e: MessageEvent) => {\n Queue.offerUnsafe(queue, e.data);\n });\n\n socket.addEventListener(\"error\", () => {\n Queue.failCauseUnsafe(queue, Cause.fail(new WebSocketError({ url })));\n });\n\n socket.addEventListener(\"close\", (e: CloseEvent) => {\n if (e.wasClean) {\n Queue.endUnsafe(queue);\n } else {\n Queue.failCauseUnsafe(\n queue,\n Cause.fail(new WebSocketError({ url, code: e.code, reason: e.reason })),\n );\n }\n });\n\n return Effect.sync(() => {\n // Only close a socket that is still connecting/open.\n if (socket.readyState === 0 || socket.readyState === 1) socket.close();\n });\n }),\n { bufferSize: options?.bufferSize ?? 16, strategy: options?.strategy ?? \"suspend\" },\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA4BA,IAAa,mBAAb,cAAsC,KAAK,YAAY,kBAAkB,EAEtE,CAAC;;;;;;;;;;;;;;;;;;AA0CJ,MAAa,mBACX,KACA,YACgD;CAChD,MAAM,OAAO,SAAS,kBAAmB,WAAW;CACpD,OAAO,OAAO,UACX,UACC,OAAO,WAAW;EAChB,MAAM,SACJ,SAAS,oBAAoB,KAAA,IACzB,IAAI,KAAK,GAAG,IACZ,IAAI,KAAK,KAAK,EAAE,iBAAiB,QAAQ,gBAAgB,CAAC;EAEhE,MAAM,aAAa,MAA0B;GAC3C,MAAM,YAAY,OAAO;IAAE,OAAO,EAAE;IAAM,MAAM,EAAE;IAAM,aAAa,EAAE;GAAY,CAAC;EACtF;EAEA,OAAO,iBAAiB,WAAW,SAAS;EAC5C,KAAK,MAAM,QAAQ,SAAS,UAAU,CAAC,GAAG,OAAO,iBAAiB,MAAM,SAAS;EAEjF,OAAO,iBAAiB,eAAe;GAErC,IAAI,OAAO,eAAe,GACxB,MAAM,gBAAgB,OAAO,MAAM,KAAK,IAAI,iBAAiB,EAAE,IAAI,CAAC,CAAC,CAAC;EAE1E,CAAC;EAED,OAAO,OAAO,WAAW,OAAO,MAAM,CAAC;CACzC,CAAC,GACH;EAAE,YAAY,SAAS,cAAc;EAAI,UAAU,SAAS,YAAY;CAAU,CACpF;AACF;;AAOA,IAAa,iBAAb,cAAoC,KAAK,YAAY,gBAAgB,EAIlE,CAAC;;;;;;;;;;;;;;;;;;;AAuCJ,MAAa,iBACX,KACA,YAC+D;CAC/D,MAAM,OAAO,SAAS,kBAAmB,WAAW;CACpD,OAAO,OAAO,UACX,UACC,OAAO,WAAW;EAChB,MAAM,SAAS,IAAI,KAAK,KAAK,SAAS,SAAS;EAC/C,IAAI,SAAS,eAAe,KAAA,GAAW,OAAO,aAAa,QAAQ;EAEnE,OAAO,iBAAiB,YAAY,MAAoB;GACtD,MAAM,YAAY,OAAO,EAAE,IAAI;EACjC,CAAC;EAED,OAAO,iBAAiB,eAAe;GACrC,MAAM,gBAAgB,OAAO,MAAM,KAAK,IAAI,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC;EACtE,CAAC;EAED,OAAO,iBAAiB,UAAU,MAAkB;GAClD,IAAI,EAAE,UACJ,MAAM,UAAU,KAAK;QAErB,MAAM,gBACJ,OACA,MAAM,KAAK,IAAI,eAAe;IAAE;IAAK,MAAM,EAAE;IAAM,QAAQ,EAAE;GAAO,CAAC,CAAC,CACxE;EAEJ,CAAC;EAED,OAAO,OAAO,WAAW;GAEvB,IAAI,OAAO,eAAe,KAAK,OAAO,eAAe,GAAG,OAAO,MAAM;EACvE,CAAC;CACH,CAAC,GACH;EAAE,YAAY,SAAS,cAAc;EAAI,UAAU,SAAS,YAAY;CAAU,CACpF;AACF"}
1
+ {"version":3,"file":"realtime.js","names":[],"sources":["../src/realtime.ts"],"sourcesContent":["/**\n * Client-side realtime bridges: consume a Server-Sent-Events endpoint or a\n * WebSocket as an Effect `Stream`. The counterpart to `Endpoint.fromStream`\n * (server) on the `@thomasfosterau/effect-sveltekit/client` `Realtime` namespace.\n *\n * These use the browser globals `EventSource` / `WebSocket`; both can be\n * overridden (e.g. a Node polyfill, or a fake in tests) via the `implementation`\n * option. The source is opened when the stream is run and closed when its scope\n * closes, so a `Stream.take` / component teardown tears down the connection.\n */\n\nimport { Cause, Data, Effect, Queue, Stream } from \"effect\";\n\n// ---------------------------------------------------------------------------\n// EventSource\n// ---------------------------------------------------------------------------\n\n/** A decoded Server-Sent Event. */\nexport interface SseMessage {\n /** The event name (`\"message\"` for unnamed events). */\n readonly event: string;\n /** The event payload (the joined `data:` lines). */\n readonly data: string;\n /** The last event id seen, or `\"\"` if none. */\n readonly lastEventId: string;\n}\n\n/** Raised when an `EventSource` connection fails fatally (its `readyState` is `CLOSED`). */\nexport class EventSourceError extends Data.TaggedError(\"EventSourceError\")<{\n readonly url: string;\n}> {}\n\n/** The subset of the `EventSource` constructor this module relies on. */\nexport type EventSourceConstructor = new (\n url: string,\n eventSourceInitDict?: { withCredentials?: boolean },\n) => EventSource;\n\nexport interface FromEventSourceOptions {\n /** Send credentials (cookies) with the request. Defaults to `false`. */\n readonly withCredentials?: boolean;\n /**\n * Named events to listen for in addition to the default unnamed `message`\n * event. An `Endpoint.fromStream({ event: \"tick\" })` server needs\n * `events: [\"tick\"]` here.\n */\n readonly events?: ReadonlyArray<string>;\n /** Buffer size for the backing queue. Defaults to 16. */\n readonly bufferSize?: number;\n /** Backpressure strategy when the buffer is full. Defaults to `\"sliding\"`. */\n readonly strategy?: \"sliding\" | \"dropping\" | \"suspend\";\n /** Override the `EventSource` constructor (Node polyfill, tests). */\n readonly implementation?: EventSourceConstructor;\n}\n\n/**\n * Consume a Server-Sent-Events endpoint as a `Stream` of {@link SseMessage}.\n *\n * The browser's `EventSource` reconnects automatically after transient drops,\n * so the stream stays live across reconnects; it fails with\n * {@link EventSourceError} only when the connection closes fatally.\n *\n * @example\n * ```ts\n * import { Realtime } from \"@thomasfosterau/effect-sveltekit/client\";\n * import { Effect, Stream } from \"effect\";\n *\n * const program = Realtime.fromEventSource(\"/events\", { events: [\"tick\"] }).pipe(\n * Stream.runForEach((msg) => Effect.log(`${msg.event}: ${msg.data}`)),\n * );\n * ```\n */\nexport const fromEventSource = (\n url: string,\n options?: FromEventSourceOptions,\n): Stream.Stream<SseMessage, EventSourceError> => {\n const Impl = options?.implementation ?? (globalThis.EventSource as EventSourceConstructor);\n return Stream.callback<SseMessage, EventSourceError>(\n (queue) =>\n Effect.sync(() => {\n const source =\n options?.withCredentials === undefined\n ? new Impl(url)\n : new Impl(url, { withCredentials: options.withCredentials });\n\n const onMessage = (e: MessageEvent): void => {\n Queue.offerUnsafe(queue, { event: e.type, data: e.data, lastEventId: e.lastEventId });\n };\n\n source.addEventListener(\"message\", onMessage);\n for (const name of options?.events ?? []) source.addEventListener(name, onMessage);\n\n source.addEventListener(\"error\", () => {\n // EventSource reconnects on its own unless it has closed for good.\n if (source.readyState === 2 /* CLOSED */) {\n Queue.failCauseUnsafe(queue, Cause.fail(new EventSourceError({ url })));\n }\n });\n\n return Effect.sync(() => source.close());\n }),\n { bufferSize: options?.bufferSize ?? 16, strategy: options?.strategy ?? \"sliding\" },\n );\n};\n\n// ---------------------------------------------------------------------------\n// WebSocket\n// ---------------------------------------------------------------------------\n\n/** Raised when a `WebSocket` errors or closes uncleanly. */\nexport class WebSocketError extends Data.TaggedError(\"WebSocketError\")<{\n readonly url: string;\n readonly code?: number;\n readonly reason?: string;\n}> {}\n\n/** The subset of the `WebSocket` constructor this module relies on. */\nexport type WebSocketConstructor = new (\n url: string,\n protocols?: string | ReadonlyArray<string>,\n) => WebSocket;\n\nexport interface FromWebSocketOptions {\n /** Sub-protocols passed to the `WebSocket` constructor. */\n readonly protocols?: string | ReadonlyArray<string>;\n /** `arraybuffer` or `blob` for binary frames. Defaults to the platform default. */\n readonly binaryType?: BinaryType;\n /** Buffer size for the backing queue. Defaults to 16. */\n readonly bufferSize?: number;\n /** Backpressure strategy when the buffer is full. Defaults to `\"suspend\"`. */\n readonly strategy?: \"sliding\" | \"dropping\" | \"suspend\";\n /** Override the `WebSocket` constructor (Node polyfill, tests). */\n readonly implementation?: WebSocketConstructor;\n}\n\n/**\n * Consume a `WebSocket` as a `Stream` of its message payloads\n * (`string | ArrayBuffer | Blob`, depending on `binaryType`).\n *\n * The stream ends when the socket closes cleanly and fails with\n * {@link WebSocketError} on an error or unclean close. The socket is closed when\n * the stream's scope closes.\n *\n * @example\n * ```ts\n * import { Realtime } from \"@thomasfosterau/effect-sveltekit/client\";\n * import { Effect, Stream } from \"effect\";\n *\n * const program = Realtime.fromWebSocket(\"wss://example.com/ws\").pipe(\n * Stream.runForEach((data) => Effect.log(String(data))),\n * );\n * ```\n */\nexport const fromWebSocket = (\n url: string,\n options?: FromWebSocketOptions,\n): Stream.Stream<string | ArrayBuffer | Blob, WebSocketError> => {\n const Impl = options?.implementation ?? (globalThis.WebSocket as WebSocketConstructor);\n return Stream.callback<string | ArrayBuffer | Blob, WebSocketError>(\n (queue) =>\n Effect.sync(() => {\n const socket = new Impl(url, options?.protocols);\n if (options?.binaryType !== undefined) socket.binaryType = options.binaryType;\n\n socket.addEventListener(\"message\", (e: MessageEvent) => {\n Queue.offerUnsafe(queue, e.data);\n });\n\n socket.addEventListener(\"error\", () => {\n Queue.failCauseUnsafe(queue, Cause.fail(new WebSocketError({ url })));\n });\n\n socket.addEventListener(\"close\", (e: CloseEvent) => {\n if (e.wasClean) {\n Queue.endUnsafe(queue);\n } else {\n Queue.failCauseUnsafe(\n queue,\n Cause.fail(new WebSocketError({ url, code: e.code, reason: e.reason })),\n );\n }\n });\n\n return Effect.sync(() => {\n // Only close a socket that is still connecting/open.\n if (socket.readyState === 0 || socket.readyState === 1) socket.close();\n });\n }),\n { bufferSize: options?.bufferSize ?? 16, strategy: options?.strategy ?? \"suspend\" },\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA4BA,IAAa,mBAAb,cAAsC,KAAK,YAAY,kBAAkB,CAAC,CAEvE,CAAC;;;;;;;;;;;;;;;;;;AA0CJ,MAAa,mBACX,KACA,YACgD;CAChD,MAAM,OAAO,SAAS,kBAAmB,WAAW;CACpD,OAAO,OAAO,UACX,UACC,OAAO,WAAW;EAChB,MAAM,SACJ,SAAS,oBAAoB,KAAA,IACzB,IAAI,KAAK,GAAG,IACZ,IAAI,KAAK,KAAK,EAAE,iBAAiB,QAAQ,gBAAgB,CAAC;EAEhE,MAAM,aAAa,MAA0B;GAC3C,MAAM,YAAY,OAAO;IAAE,OAAO,EAAE;IAAM,MAAM,EAAE;IAAM,aAAa,EAAE;GAAY,CAAC;EACtF;EAEA,OAAO,iBAAiB,WAAW,SAAS;EAC5C,KAAK,MAAM,QAAQ,SAAS,UAAU,CAAC,GAAG,OAAO,iBAAiB,MAAM,SAAS;EAEjF,OAAO,iBAAiB,eAAe;GAErC,IAAI,OAAO,eAAe,GACxB,MAAM,gBAAgB,OAAO,MAAM,KAAK,IAAI,iBAAiB,EAAE,IAAI,CAAC,CAAC,CAAC;EAE1E,CAAC;EAED,OAAO,OAAO,WAAW,OAAO,MAAM,CAAC;CACzC,CAAC,GACH;EAAE,YAAY,SAAS,cAAc;EAAI,UAAU,SAAS,YAAY;CAAU,CACpF;AACF;;AAOA,IAAa,iBAAb,cAAoC,KAAK,YAAY,gBAAgB,CAAC,CAInE,CAAC;;;;;;;;;;;;;;;;;;;AAuCJ,MAAa,iBACX,KACA,YAC+D;CAC/D,MAAM,OAAO,SAAS,kBAAmB,WAAW;CACpD,OAAO,OAAO,UACX,UACC,OAAO,WAAW;EAChB,MAAM,SAAS,IAAI,KAAK,KAAK,SAAS,SAAS;EAC/C,IAAI,SAAS,eAAe,KAAA,GAAW,OAAO,aAAa,QAAQ;EAEnE,OAAO,iBAAiB,YAAY,MAAoB;GACtD,MAAM,YAAY,OAAO,EAAE,IAAI;EACjC,CAAC;EAED,OAAO,iBAAiB,eAAe;GACrC,MAAM,gBAAgB,OAAO,MAAM,KAAK,IAAI,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC;EACtE,CAAC;EAED,OAAO,iBAAiB,UAAU,MAAkB;GAClD,IAAI,EAAE,UACJ,MAAM,UAAU,KAAK;QAErB,MAAM,gBACJ,OACA,MAAM,KAAK,IAAI,eAAe;IAAE;IAAK,MAAM,EAAE;IAAM,QAAQ,EAAE;GAAO,CAAC,CAAC,CACxE;EAEJ,CAAC;EAED,OAAO,OAAO,WAAW;GAEvB,IAAI,OAAO,eAAe,KAAK,OAAO,eAAe,GAAG,OAAO,MAAM;EACvE,CAAC;CACH,CAAC,GACH;EAAE,YAAY,SAAS,cAAc;EAAI,UAAU,SAAS,YAAY;CAAU,CACpF;AACF"}
@@ -2,10 +2,9 @@ import { SvelteKitRequestEvent } from "./runtime.js";
2
2
  import { ErrorTranslator, RequestRuntimeProvider } from "./request-runtime.js";
3
3
  import { FormErrorMapper } from "./internal/remote-run.js";
4
4
  import { Effect, Schema } from "effect";
5
- import * as HttpClient from "effect/unstable/http/HttpClient";
5
+ import * as HttpClient from "effect/http/HttpClient";
6
6
  import { InvalidField, RemoteCommand, RemoteForm, RemoteFormInput, RemotePrerenderFunction, RemoteQueryFunction } from "@sveltejs/kit";
7
7
  import { StandardSchemaV1 } from "@standard-schema/spec";
8
-
9
8
  //#region src/remote-functions.d.ts
10
9
  type SvelteKitEffectEnv = HttpClient.HttpClient | SvelteKitRequestEvent;
11
10
  /** The public shape of the `query` helper, parameterised by its handler env. */
@@ -116,5 +115,5 @@ declare const RemoteFunction: {
116
115
  withRuntime: typeof withRuntime;
117
116
  };
118
117
  //#endregion
119
- export { RemoteFunction };
118
+ export { CommandFn, FormFn, PrerenderFn, QueryBatchFn, QueryFn, QueryLiveFn, QueryNamespace, RemoteFunction, RemoteFunctions, requested, withRuntime };
120
119
  //# sourceMappingURL=remote-functions.d.ts.map
@@ -2,7 +2,7 @@ import { SvelteKitRuntime } from "./runtime.js";
2
2
  import { isBareHandler as isBareHandler$1, toStandardValidator } from "./internal/remote-validators.js";
3
3
  import { defaultTranslate, makeRunHelpers } from "./internal/remote-run.js";
4
4
  import "effect";
5
- import "effect/unstable/http/HttpClient";
5
+ import "effect/http/HttpClient";
6
6
  import * as AppServer from "$app/server";
7
7
  //#region src/remote-functions.ts
8
8
  /** The default helpers: a fresh SvelteKit per-request runtime, passthrough translation. */
@@ -140,6 +140,6 @@ const RemoteFunction = {
140
140
  withRuntime
141
141
  };
142
142
  //#endregion
143
- export { RemoteFunction };
143
+ export { RemoteFunction, command, form, prerender, query, requested, withRuntime };
144
144
 
145
145
  //# sourceMappingURL=remote-functions.js.map
@@ -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/unstable/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\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\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\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\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\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\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\nexport const query: QueryNamespace<SvelteKitEffectEnv> = makeQueryNamespace(defaultHelpers.run);\nexport const queryBatch: QueryBatchFn<SvelteKitEffectEnv> = query.batch;\nexport const queryLive: QueryLiveFn<SvelteKitEffectEnv> = query.live;\nexport const form: FormFn<SvelteKitEffectEnv> = makeForm(defaultHelpers);\nexport const command: CommandFn<SvelteKitEffectEnv> = makeCommand(defaultHelpers.run);\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\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 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\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\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\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\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\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\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\nexport const query: QueryNamespace<SvelteKitEffectEnv> = makeQueryNamespace(defaultHelpers.run);\nexport const queryBatch: QueryBatchFn<SvelteKitEffectEnv> = query.batch;\nexport const queryLive: QueryLiveFn<SvelteKitEffectEnv> = query.live;\nexport const form: FormFn<SvelteKitEffectEnv> = makeForm(defaultHelpers);\nexport const command: CommandFn<SvelteKitEffectEnv> = makeCommand(defaultHelpers.run);\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\nexport const RemoteFunction = {\n query,\n form,\n command,\n prerender,\n requested,\n withRuntime,\n};\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { RemoteResource } from "@sveltejs/kit";
2
- import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
3
-
2
+ import * as AsyncResult from "effect/reactivity/AsyncResult";
4
3
  //#region src/remote-reactive.d.ts
5
4
  /**
6
5
  * Bridges a SvelteKit remote resource (`query(...)`, `query.live(...)`,
@@ -1,4 +1,4 @@
1
- import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
1
+ import * as AsyncResult from "effect/reactivity/AsyncResult";
2
2
  //#region src/remote-reactive.ts
3
3
  /**
4
4
  * Bridges a SvelteKit remote resource (`query(...)`, `query.live(...)`,
@@ -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/unstable/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 \"@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,7 +1,6 @@
1
1
  import { SvelteKitRequestEvent } from "./runtime.js";
2
2
  import { Effect, Schema } from "effect";
3
3
  import { StandardSchemaV1 } from "@standard-schema/spec";
4
-
5
4
  //#region src/request-parse.d.ts
6
5
  /** A single issue reported by a Standard Schema validator. */
7
6
  interface ParseIssue {
@@ -10,7 +9,7 @@ interface ParseIssue {
10
9
  readonly key: PropertyKey;
11
10
  }>;
12
11
  }
13
- declare const ParseError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }>) => import("effect/Cause").YieldableError & {
12
+ declare const ParseError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
14
13
  readonly _tag: "ParseError";
15
14
  } & Readonly<A>;
16
15
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"request-parse.js","names":[],"sources":["../src/request-parse.ts"],"sourcesContent":["/**\n * Schema-driven request parsing utilities for SvelteKit server handlers.\n *\n * Each helper reads a part of the current request (route params, search params,\n * JSON body, or form data), validates it against a schema (Effect `Schema` or\n * any Standard Schema V1 validator), and returns the typed output as an\n * `Effect`. A validation failure surfaces as {@link ParseError}.\n *\n * All four utilities require `SvelteKitRequestEvent` in the environment so they\n * compose naturally inside `serverLoad` / `action` / `endpoint` handlers.\n *\n * @example\n * ```ts\n * import { serverLoad } from '@thomasfosterau/effect-sveltekit/server';\n * import { decodeParams, decodeSearchParams } from '@thomasfosterau/effect-sveltekit/server';\n * import { Schema } from 'effect';\n *\n * const Params = Schema.Struct({ id: Schema.String });\n * const Query = Schema.Struct({ page: Schema.NumberFromString });\n *\n * export const load = serverLoad(() =>\n * Effect.gen(function* () {\n * const { id } = yield* decodeParams(Params);\n * const { page } = yield* decodeSearchParams(Query);\n * return { id, page };\n * }),\n * );\n * ```\n */\n\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { Data, Effect, Schema } from \"effect\";\nimport { SvelteKitRequestEvent } from \"./runtime.js\";\nimport { toStandardValidator } from \"./internal/remote-validators.js\";\n\n// ---------------------------------------------------------------------------\n// ParseError\n// ---------------------------------------------------------------------------\n\n/** A single issue reported by a Standard Schema validator. */\nexport interface ParseIssue {\n readonly message: string;\n readonly path?: ReadonlyArray<PropertyKey | { readonly key: PropertyKey }>;\n}\n\n/**\n * Raised when a schema validator rejects the request data.\n *\n * Carry the raw `issues` array from the Standard Schema validator so callers\n * can pattern-match on specific field failures.\n *\n * @example\n * ```ts\n * import { ParseError } from '@thomasfosterau/effect-sveltekit/server';\n * import { Effect } from 'effect';\n *\n * const result = yield* decodeJson(MySchema).pipe(\n * Effect.catchTag(\"ParseError\", (e) => Effect.succeed({ fallback: true })),\n * );\n * ```\n */\nexport class ParseError extends Data.TaggedError(\"ParseError\")<{\n readonly issues: ReadonlyArray<ParseIssue>;\n}> {}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Validate `value` against `schema` and return the typed output or fail. */\nconst validate = <O>(\n schema: StandardSchemaV1<unknown, O>,\n value: unknown,\n): Effect.Effect<O, ParseError> =>\n Effect.callback<O, ParseError>((resume) => {\n const resultOrPromise = schema[\"~standard\"].validate(value);\n const settle = (result: StandardSchemaV1.Result<O>) => {\n if (\"issues\" in result && result.issues !== undefined) {\n resume(Effect.fail(new ParseError({ issues: result.issues as ReadonlyArray<ParseIssue> })));\n } else {\n resume(Effect.succeed((result as StandardSchemaV1.SuccessResult<O>).value));\n }\n };\n if (resultOrPromise instanceof Promise) {\n resultOrPromise.then(settle, (err: unknown) => {\n resume(Effect.fail(new ParseError({ issues: [{ message: String(err) }] })));\n });\n } else {\n settle(resultOrPromise);\n }\n });\n\n/** Normalise an Effect Schema or Standard Schema V1 to Standard Schema V1. */\nconst normalise = <O>(schema: unknown): StandardSchemaV1<unknown, O> =>\n toStandardValidator(schema) as StandardSchemaV1<unknown, O>;\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Decode the route `params` object against `schema`.\n *\n * `params` is a plain `Record<string, string>` from the matched URL segments;\n * the schema is free to coerce values (e.g. `Schema.NumberFromString`).\n *\n * @example\n * ```ts\n * const Params = Schema.Struct({ id: Schema.String });\n * const { id } = yield* decodeParams(Params);\n * ```\n */\nexport const decodeParams = <O>(\n schema: Schema.Schema<O> | StandardSchemaV1<unknown, O>,\n): Effect.Effect<O, ParseError, SvelteKitRequestEvent> =>\n Effect.gen(function* () {\n const event = yield* SvelteKitRequestEvent;\n return yield* validate(normalise<O>(schema), event.params);\n });\n\n/**\n * Decode the URL search / query parameters against `schema`.\n *\n * The raw value passed to the validator is a plain object built from\n * `event.url.searchParams` (multiple values for the same key become an array).\n *\n * @example\n * ```ts\n * const Query = Schema.Struct({ page: Schema.NumberFromString });\n * const { page } = yield* decodeSearchParams(Query);\n * ```\n */\nexport const decodeSearchParams = <O>(\n schema: Schema.Schema<O> | StandardSchemaV1<unknown, O>,\n): Effect.Effect<O, ParseError, SvelteKitRequestEvent> =>\n Effect.gen(function* () {\n const event = yield* SvelteKitRequestEvent;\n const raw: Record<string, string | string[]> = {};\n for (const key of event.url.searchParams.keys()) {\n const values = event.url.searchParams.getAll(key);\n raw[key] = values.length === 1 ? values[0]! : values;\n }\n return yield* validate(normalise<O>(schema), raw);\n });\n\n/**\n * Parse the request body as JSON and decode it against `schema`.\n *\n * Fails with `ParseError` if the body is not valid JSON or if the schema\n * rejects the parsed value.\n *\n * @example\n * ```ts\n * const Body = Schema.Struct({ name: Schema.String });\n * const { name } = yield* decodeJson(Body);\n * ```\n */\nexport const decodeJson = <O>(\n schema: Schema.Schema<O> | StandardSchemaV1<unknown, O>,\n): Effect.Effect<O, ParseError, SvelteKitRequestEvent> =>\n Effect.gen(function* () {\n const event = yield* SvelteKitRequestEvent;\n const json = yield* Effect.tryPromise({\n try: () => event.request.json() as Promise<unknown>,\n catch: (err) => new ParseError({ issues: [{ message: `Invalid JSON: ${String(err)}` }] }),\n });\n return yield* validate(normalise<O>(schema), json);\n });\n\n/**\n * Parse the request body as `FormData` and decode it against `schema`.\n *\n * The raw value passed to the validator is a plain object; fields with\n * multiple values (same name) become arrays.\n *\n * @example\n * ```ts\n * const Form = Schema.Struct({ email: Schema.String });\n * const { email } = yield* decodeFormData(Form);\n * ```\n */\nexport const decodeFormData = <O>(\n schema: Schema.Schema<O> | StandardSchemaV1<unknown, O>,\n): Effect.Effect<O, ParseError, SvelteKitRequestEvent> =>\n Effect.gen(function* () {\n const event = yield* SvelteKitRequestEvent;\n const formData = yield* Effect.tryPromise({\n try: () => event.request.formData(),\n catch: (err) =>\n new ParseError({ issues: [{ message: `Failed to read form data: ${String(err)}` }] }),\n });\n const raw: Record<string, string | string[]> = {};\n for (const key of formData.keys()) {\n const values = formData.getAll(key).map(String);\n raw[key] = values.length === 1 ? values[0]! : values;\n }\n return yield* validate(normalise<O>(schema), raw);\n });\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA6DA,IAAa,aAAb,cAAgC,KAAK,YAAY,YAAY,EAE1D,CAAC;;AAOJ,MAAM,YACJ,QACA,UAEA,OAAO,UAAyB,WAAW;CACzC,MAAM,kBAAkB,OAAO,aAAa,SAAS,KAAK;CAC1D,MAAM,UAAU,WAAuC;EACrD,IAAI,YAAY,UAAU,OAAO,WAAW,KAAA,GAC1C,OAAO,OAAO,KAAK,IAAI,WAAW,EAAE,QAAQ,OAAO,OAAoC,CAAC,CAAC,CAAC;OAE1F,OAAO,OAAO,QAAS,OAA6C,KAAK,CAAC;CAE9E;CACA,IAAI,2BAA2B,SAC7B,gBAAgB,KAAK,SAAS,QAAiB;EAC7C,OAAO,OAAO,KAAK,IAAI,WAAW,EAAE,QAAQ,CAAC,EAAE,SAAS,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAC5E,CAAC;MAED,OAAO,eAAe;AAE1B,CAAC;;AAGH,MAAM,aAAgB,WACpB,oBAAoB,MAAM;;;;;;;;;;;;;AAkB5B,MAAa,gBACX,WAEA,OAAO,IAAI,aAAa;CACtB,MAAM,QAAQ,OAAO;CACrB,OAAO,OAAO,SAAS,UAAa,MAAM,GAAG,MAAM,MAAM;AAC3D,CAAC;;;;;;;;;;;;;AAcH,MAAa,sBACX,WAEA,OAAO,IAAI,aAAa;CACtB,MAAM,QAAQ,OAAO;CACrB,MAAM,MAAyC,CAAC;CAChD,KAAK,MAAM,OAAO,MAAM,IAAI,aAAa,KAAK,GAAG;EAC/C,MAAM,SAAS,MAAM,IAAI,aAAa,OAAO,GAAG;EAChD,IAAI,OAAO,OAAO,WAAW,IAAI,OAAO,KAAM;CAChD;CACA,OAAO,OAAO,SAAS,UAAa,MAAM,GAAG,GAAG;AAClD,CAAC;;;;;;;;;;;;;AAcH,MAAa,cACX,WAEA,OAAO,IAAI,aAAa;CACtB,MAAM,QAAQ,OAAO;CACrB,MAAM,OAAO,OAAO,OAAO,WAAW;EACpC,WAAW,MAAM,QAAQ,KAAK;EAC9B,QAAQ,QAAQ,IAAI,WAAW,EAAE,QAAQ,CAAC,EAAE,SAAS,iBAAiB,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;CAC1F,CAAC;CACD,OAAO,OAAO,SAAS,UAAa,MAAM,GAAG,IAAI;AACnD,CAAC;;;;;;;;;;;;;AAcH,MAAa,kBACX,WAEA,OAAO,IAAI,aAAa;CACtB,MAAM,QAAQ,OAAO;CACrB,MAAM,WAAW,OAAO,OAAO,WAAW;EACxC,WAAW,MAAM,QAAQ,SAAS;EAClC,QAAQ,QACN,IAAI,WAAW,EAAE,QAAQ,CAAC,EAAE,SAAS,6BAA6B,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;CACxF,CAAC;CACD,MAAM,MAAyC,CAAC;CAChD,KAAK,MAAM,OAAO,SAAS,KAAK,GAAG;EACjC,MAAM,SAAS,SAAS,OAAO,GAAG,EAAE,IAAI,MAAM;EAC9C,IAAI,OAAO,OAAO,WAAW,IAAI,OAAO,KAAM;CAChD;CACA,OAAO,OAAO,SAAS,UAAa,MAAM,GAAG,GAAG;AAClD,CAAC"}
1
+ {"version":3,"file":"request-parse.js","names":[],"sources":["../src/request-parse.ts"],"sourcesContent":["/**\n * Schema-driven request parsing utilities for SvelteKit server handlers.\n *\n * Each helper reads a part of the current request (route params, search params,\n * JSON body, or form data), validates it against a schema (Effect `Schema` or\n * any Standard Schema V1 validator), and returns the typed output as an\n * `Effect`. A validation failure surfaces as {@link ParseError}.\n *\n * All four utilities require `SvelteKitRequestEvent` in the environment so they\n * compose naturally inside `serverLoad` / `action` / `endpoint` handlers.\n *\n * @example\n * ```ts\n * import { serverLoad } from '@thomasfosterau/effect-sveltekit/server';\n * import { decodeParams, decodeSearchParams } from '@thomasfosterau/effect-sveltekit/server';\n * import { Schema } from 'effect';\n *\n * const Params = Schema.Struct({ id: Schema.String });\n * const Query = Schema.Struct({ page: Schema.NumberFromString });\n *\n * export const load = serverLoad(() =>\n * Effect.gen(function* () {\n * const { id } = yield* decodeParams(Params);\n * const { page } = yield* decodeSearchParams(Query);\n * return { id, page };\n * }),\n * );\n * ```\n */\n\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { Data, Effect, Schema } from \"effect\";\nimport { SvelteKitRequestEvent } from \"./runtime.js\";\nimport { toStandardValidator } from \"./internal/remote-validators.js\";\n\n// ---------------------------------------------------------------------------\n// ParseError\n// ---------------------------------------------------------------------------\n\n/** A single issue reported by a Standard Schema validator. */\nexport interface ParseIssue {\n readonly message: string;\n readonly path?: ReadonlyArray<PropertyKey | { readonly key: PropertyKey }>;\n}\n\n/**\n * Raised when a schema validator rejects the request data.\n *\n * Carry the raw `issues` array from the Standard Schema validator so callers\n * can pattern-match on specific field failures.\n *\n * @example\n * ```ts\n * import { ParseError } from '@thomasfosterau/effect-sveltekit/server';\n * import { Effect } from 'effect';\n *\n * const result = yield* decodeJson(MySchema).pipe(\n * Effect.catchTag(\"ParseError\", (e) => Effect.succeed({ fallback: true })),\n * );\n * ```\n */\nexport class ParseError extends Data.TaggedError(\"ParseError\")<{\n readonly issues: ReadonlyArray<ParseIssue>;\n}> {}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Validate `value` against `schema` and return the typed output or fail. */\nconst validate = <O>(\n schema: StandardSchemaV1<unknown, O>,\n value: unknown,\n): Effect.Effect<O, ParseError> =>\n Effect.callback<O, ParseError>((resume) => {\n const resultOrPromise = schema[\"~standard\"].validate(value);\n const settle = (result: StandardSchemaV1.Result<O>) => {\n if (\"issues\" in result && result.issues !== undefined) {\n resume(Effect.fail(new ParseError({ issues: result.issues as ReadonlyArray<ParseIssue> })));\n } else {\n resume(Effect.succeed((result as StandardSchemaV1.SuccessResult<O>).value));\n }\n };\n if (resultOrPromise instanceof Promise) {\n resultOrPromise.then(settle, (err: unknown) => {\n resume(Effect.fail(new ParseError({ issues: [{ message: String(err) }] })));\n });\n } else {\n settle(resultOrPromise);\n }\n });\n\n/** Normalise an Effect Schema or Standard Schema V1 to Standard Schema V1. */\nconst normalise = <O>(schema: unknown): StandardSchemaV1<unknown, O> =>\n toStandardValidator(schema) as StandardSchemaV1<unknown, O>;\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Decode the route `params` object against `schema`.\n *\n * `params` is a plain `Record<string, string>` from the matched URL segments;\n * the schema is free to coerce values (e.g. `Schema.NumberFromString`).\n *\n * @example\n * ```ts\n * const Params = Schema.Struct({ id: Schema.String });\n * const { id } = yield* decodeParams(Params);\n * ```\n */\nexport const decodeParams = <O>(\n schema: Schema.Schema<O> | StandardSchemaV1<unknown, O>,\n): Effect.Effect<O, ParseError, SvelteKitRequestEvent> =>\n Effect.gen(function* () {\n const event = yield* SvelteKitRequestEvent;\n return yield* validate(normalise<O>(schema), event.params);\n });\n\n/**\n * Decode the URL search / query parameters against `schema`.\n *\n * The raw value passed to the validator is a plain object built from\n * `event.url.searchParams` (multiple values for the same key become an array).\n *\n * @example\n * ```ts\n * const Query = Schema.Struct({ page: Schema.NumberFromString });\n * const { page } = yield* decodeSearchParams(Query);\n * ```\n */\nexport const decodeSearchParams = <O>(\n schema: Schema.Schema<O> | StandardSchemaV1<unknown, O>,\n): Effect.Effect<O, ParseError, SvelteKitRequestEvent> =>\n Effect.gen(function* () {\n const event = yield* SvelteKitRequestEvent;\n const raw: Record<string, string | string[]> = {};\n for (const key of event.url.searchParams.keys()) {\n const values = event.url.searchParams.getAll(key);\n raw[key] = values.length === 1 ? values[0]! : values;\n }\n return yield* validate(normalise<O>(schema), raw);\n });\n\n/**\n * Parse the request body as JSON and decode it against `schema`.\n *\n * Fails with `ParseError` if the body is not valid JSON or if the schema\n * rejects the parsed value.\n *\n * @example\n * ```ts\n * const Body = Schema.Struct({ name: Schema.String });\n * const { name } = yield* decodeJson(Body);\n * ```\n */\nexport const decodeJson = <O>(\n schema: Schema.Schema<O> | StandardSchemaV1<unknown, O>,\n): Effect.Effect<O, ParseError, SvelteKitRequestEvent> =>\n Effect.gen(function* () {\n const event = yield* SvelteKitRequestEvent;\n const json = yield* Effect.tryPromise({\n try: () => event.request.json() as Promise<unknown>,\n catch: (err) => new ParseError({ issues: [{ message: `Invalid JSON: ${String(err)}` }] }),\n });\n return yield* validate(normalise<O>(schema), json);\n });\n\n/**\n * Parse the request body as `FormData` and decode it against `schema`.\n *\n * The raw value passed to the validator is a plain object; fields with\n * multiple values (same name) become arrays.\n *\n * @example\n * ```ts\n * const Form = Schema.Struct({ email: Schema.String });\n * const { email } = yield* decodeFormData(Form);\n * ```\n */\nexport const decodeFormData = <O>(\n schema: Schema.Schema<O> | StandardSchemaV1<unknown, O>,\n): Effect.Effect<O, ParseError, SvelteKitRequestEvent> =>\n Effect.gen(function* () {\n const event = yield* SvelteKitRequestEvent;\n const formData = yield* Effect.tryPromise({\n try: () => event.request.formData(),\n catch: (err) =>\n new ParseError({ issues: [{ message: `Failed to read form data: ${String(err)}` }] }),\n });\n const raw: Record<string, string | string[]> = {};\n for (const key of formData.keys()) {\n const values = formData.getAll(key).map(String);\n raw[key] = values.length === 1 ? values[0]! : values;\n }\n return yield* validate(normalise<O>(schema), raw);\n });\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA6DA,IAAa,aAAb,cAAgC,KAAK,YAAY,YAAY,CAAC,CAE3D,CAAC;;AAOJ,MAAM,YACJ,QACA,UAEA,OAAO,UAAyB,WAAW;CACzC,MAAM,kBAAkB,OAAO,YAAY,CAAC,SAAS,KAAK;CAC1D,MAAM,UAAU,WAAuC;EACrD,IAAI,YAAY,UAAU,OAAO,WAAW,KAAA,GAC1C,OAAO,OAAO,KAAK,IAAI,WAAW,EAAE,QAAQ,OAAO,OAAoC,CAAC,CAAC,CAAC;OAE1F,OAAO,OAAO,QAAS,OAA6C,KAAK,CAAC;CAE9E;CACA,IAAI,2BAA2B,SAC7B,gBAAgB,KAAK,SAAS,QAAiB;EAC7C,OAAO,OAAO,KAAK,IAAI,WAAW,EAAE,QAAQ,CAAC,EAAE,SAAS,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAC5E,CAAC;MAED,OAAO,eAAe;AAE1B,CAAC;;AAGH,MAAM,aAAgB,WACpB,oBAAoB,MAAM;;;;;;;;;;;;;AAkB5B,MAAa,gBACX,WAEA,OAAO,IAAI,aAAa;CACtB,MAAM,QAAQ,OAAO;CACrB,OAAO,OAAO,SAAS,UAAa,MAAM,GAAG,MAAM,MAAM;AAC3D,CAAC;;;;;;;;;;;;;AAcH,MAAa,sBACX,WAEA,OAAO,IAAI,aAAa;CACtB,MAAM,QAAQ,OAAO;CACrB,MAAM,MAAyC,CAAC;CAChD,KAAK,MAAM,OAAO,MAAM,IAAI,aAAa,KAAK,GAAG;EAC/C,MAAM,SAAS,MAAM,IAAI,aAAa,OAAO,GAAG;EAChD,IAAI,OAAO,OAAO,WAAW,IAAI,OAAO,KAAM;CAChD;CACA,OAAO,OAAO,SAAS,UAAa,MAAM,GAAG,GAAG;AAClD,CAAC;;;;;;;;;;;;;AAcH,MAAa,cACX,WAEA,OAAO,IAAI,aAAa;CACtB,MAAM,QAAQ,OAAO;CACrB,MAAM,OAAO,OAAO,OAAO,WAAW;EACpC,WAAW,MAAM,QAAQ,KAAK;EAC9B,QAAQ,QAAQ,IAAI,WAAW,EAAE,QAAQ,CAAC,EAAE,SAAS,iBAAiB,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;CAC1F,CAAC;CACD,OAAO,OAAO,SAAS,UAAa,MAAM,GAAG,IAAI;AACnD,CAAC;;;;;;;;;;;;;AAcH,MAAa,kBACX,WAEA,OAAO,IAAI,aAAa;CACtB,MAAM,QAAQ,OAAO;CACrB,MAAM,WAAW,OAAO,OAAO,WAAW;EACxC,WAAW,MAAM,QAAQ,SAAS;EAClC,QAAQ,QACN,IAAI,WAAW,EAAE,QAAQ,CAAC,EAAE,SAAS,6BAA6B,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC;CACxF,CAAC;CACD,MAAM,MAAyC,CAAC;CAChD,KAAK,MAAM,OAAO,SAAS,KAAK,GAAG;EACjC,MAAM,SAAS,SAAS,OAAO,GAAG,CAAC,CAAC,IAAI,MAAM;EAC9C,IAAI,OAAO,OAAO,WAAW,IAAI,OAAO,KAAM;CAChD;CACA,OAAO,OAAO,SAAS,UAAa,MAAM,GAAG,GAAG;AAClD,CAAC"}
@@ -1,7 +1,6 @@
1
1
  import { SvelteRouteParams } from "./internal/route-params.js";
2
2
  import { Cause, Context, Effect, Exit, Fiber, Layer, ManagedRuntime } from "effect";
3
3
  import { Action, Actions, RequestEvent, RequestHandler, ServerLoad } from "@sveltejs/kit";
4
-
5
4
  //#region src/request-runtime.d.ts
6
5
  /**
7
6
  * The runners a {@link RequestRuntimeProvider} resolves for a single request: