@thomasfosterau/effect-sveltekit 0.6.0 → 0.8.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 (119) hide show
  1. package/README.md +37 -21
  2. package/dist/Hooks.d.ts +3 -3
  3. package/dist/Hooks.js +1 -1
  4. package/dist/Hooks.js.map +1 -1
  5. package/dist/Navigation.d.ts +11 -11
  6. package/dist/Navigation.js +15 -2
  7. package/dist/Navigation.js.map +1 -1
  8. package/dist/Remote.d.ts +18 -17
  9. package/dist/Remote.js +2 -4
  10. package/dist/Remote.js.map +1 -1
  11. package/dist/State.d.ts +10 -6
  12. package/dist/State.js +2 -1
  13. package/dist/State.js.map +1 -1
  14. package/dist/adapter/assets.d.ts +24 -7
  15. package/dist/adapter/assets.js +58 -37
  16. package/dist/adapter/assets.js.map +1 -1
  17. package/dist/adapter/handler.d.ts +27 -12
  18. package/dist/adapter/handler.js +53 -26
  19. package/dist/adapter/handler.js.map +1 -1
  20. package/dist/adapter/index.d.ts +3 -3
  21. package/dist/adapter/index.js +1 -1
  22. package/dist/adapter/index.js.map +1 -1
  23. package/dist/adapter/serve.d.ts +6 -5
  24. package/dist/adapter/serve.js +3 -1
  25. package/dist/adapter/serve.js.map +1 -1
  26. package/dist/api-client.d.ts +3 -4
  27. package/dist/api-client.js +2 -1
  28. package/dist/api-client.js.map +1 -1
  29. package/dist/app-runtime.d.ts +12 -9
  30. package/dist/app-runtime.js +23 -14
  31. package/dist/app-runtime.js.map +1 -1
  32. package/dist/client/Hooks.d.ts +4 -4
  33. package/dist/client/Hooks.js +2 -1
  34. package/dist/client/Hooks.js.map +1 -1
  35. package/dist/client.d.ts +2 -2
  36. package/dist/config.d.ts +7 -5
  37. package/dist/config.js +5 -34
  38. package/dist/config.js.map +1 -1
  39. package/dist/errors.d.ts +14 -16
  40. package/dist/errors.js +20 -12
  41. package/dist/errors.js.map +1 -1
  42. package/dist/forms.d.ts +9 -10
  43. package/dist/forms.js +5 -2
  44. package/dist/forms.js.map +1 -1
  45. package/dist/index.d.ts +5 -4
  46. package/dist/index.js +5 -4
  47. package/dist/internal/app-state.d.ts +16 -14
  48. package/dist/internal/app-state.js +9 -3
  49. package/dist/internal/app-state.js.map +1 -1
  50. package/dist/internal/auto.d.ts +23 -14
  51. package/dist/internal/auto.js +50 -40
  52. package/dist/internal/auto.js.map +1 -1
  53. package/dist/internal/enhance.d.ts +20 -18
  54. package/dist/internal/enhance.js +3 -1
  55. package/dist/internal/enhance.js.map +1 -1
  56. package/dist/internal/error.d.ts +13 -0
  57. package/dist/internal/error.js +4 -3
  58. package/dist/internal/error.js.map +1 -1
  59. package/dist/internal/navigation-events.js +3 -1
  60. package/dist/internal/navigation-events.js.map +1 -1
  61. package/dist/internal/remote-run.d.ts +6 -6
  62. package/dist/internal/remote-run.js +13 -16
  63. package/dist/internal/remote-run.js.map +1 -1
  64. package/dist/internal/remote-validators.js +4 -3
  65. package/dist/internal/remote-validators.js.map +1 -1
  66. package/dist/internal/route-params.d.ts +1 -2
  67. package/dist/internal/sse.js +2 -1
  68. package/dist/internal/sse.js.map +1 -1
  69. package/dist/kit.d.ts +12 -11
  70. package/dist/kit.js +6 -2
  71. package/dist/kit.js.map +1 -1
  72. package/dist/realtime.d.ts +29 -31
  73. package/dist/realtime.js +23 -4
  74. package/dist/realtime.js.map +1 -1
  75. package/dist/remote-functions.d.ts +34 -18
  76. package/dist/remote-functions.js +78 -46
  77. package/dist/remote-functions.js.map +1 -1
  78. package/dist/remote-reactive.d.ts +8 -4
  79. package/dist/remote-reactive.js.map +1 -1
  80. package/dist/request-parse.d.ts +13 -13
  81. package/dist/request-parse.js +29 -15
  82. package/dist/request-parse.js.map +1 -1
  83. package/dist/request-runtime.d.ts +16 -11
  84. package/dist/request-runtime.js +28 -29
  85. package/dist/request-runtime.js.map +1 -1
  86. package/dist/request-services.d.ts +10 -8
  87. package/dist/request-services.js +3 -1
  88. package/dist/request-services.js.map +1 -1
  89. package/dist/response-headers.d.ts +2 -3
  90. package/dist/response-headers.js +2 -1
  91. package/dist/response-headers.js.map +1 -1
  92. package/dist/runtime.d.ts +8 -5
  93. package/dist/runtime.js +4 -1
  94. package/dist/runtime.js.map +1 -1
  95. package/dist/server/Endpoint.d.ts +17 -11
  96. package/dist/server/Endpoint.js +18 -4
  97. package/dist/server/Endpoint.js.map +1 -1
  98. package/dist/server/Hooks.d.ts +6 -6
  99. package/dist/server/Hooks.js +1 -1
  100. package/dist/server/Hooks.js.map +1 -1
  101. package/dist/server.d.ts +8 -7
  102. package/dist/server.js +8 -8
  103. package/dist/server.js.map +1 -1
  104. package/dist/streamed-load.d.ts +2 -3
  105. package/dist/streamed-load.js +1 -1
  106. package/dist/streamed-load.js.map +1 -1
  107. package/dist/testing.d.ts +15 -14
  108. package/dist/testing.js +27 -7
  109. package/dist/testing.js.map +1 -1
  110. package/dist/transport.d.ts +6 -7
  111. package/dist/transport.js +3 -6
  112. package/dist/transport.js.map +1 -1
  113. package/dist/universal.d.ts +3 -3
  114. package/dist/universal.js +1 -1
  115. package/dist/universal.js.map +1 -1
  116. package/dist/vite.d.ts +4 -4
  117. package/dist/vite.js +102 -103
  118. package/dist/vite.js.map +1 -1
  119. package/package.json +12 -9
@@ -1,4 +1,5 @@
1
- import { Schema } from "effect";
1
+ import * as Predicate from "effect/Predicate";
2
+ import * as Schema from "effect/Schema";
2
3
  //#region src/internal/remote-validators.ts
3
4
  /**
4
5
  * Detects a Standard Schema validator via its `~standard` marker property.
@@ -8,9 +9,9 @@ import { Schema } from "effect";
8
9
  * `Schema.toStandardSchemaV1`) return callable class values, which would be
9
10
  * mistaken for handler functions.
10
11
  */
11
- const isStandardSchema = (value) => value !== null && (typeof value === "object" || typeof value === "function") && "~standard" in value;
12
+ const isStandardSchema = (value) => Predicate.hasProperty(value, "~standard");
12
13
  /** True when the argument is the no-validation (bare handler) overload. */
13
- const isBareHandler = (value) => typeof value === "function" && !isStandardSchema(value) && !Schema.isSchema(value);
14
+ const isBareHandler = (value) => Predicate.isFunction(value) && !isStandardSchema(value) && !Schema.isSchema(value);
14
15
  /**
15
16
  * Normalise a validator argument: a bare Effect `Schema` is wrapped with
16
17
  * `Schema.toStandardSchemaV1` so callers can pass it directly; a Standard Schema
@@ -1 +1 @@
1
- {"version":3,"file":"remote-validators.js","names":[],"sources":["../../src/internal/remote-validators.ts"],"sourcesContent":["/**\n * Validator-argument helpers for the remote-function wrappers, factored out so\n * they can be unit-tested without importing `$app/server` (which is a SvelteKit\n * virtual module unavailable outside an app build).\n */\n\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { Schema } from \"effect\";\n\n/**\n * Detects a Standard Schema validator via its `~standard` marker property.\n *\n * This cannot be a simple `typeof value === \"function\"` check on the handler\n * position: some Standard Schema implementations (such as Effect's\n * `Schema.toStandardSchemaV1`) return callable class values, which would be\n * mistaken for handler functions.\n */\nexport const isStandardSchema = (value: unknown): value is StandardSchemaV1 =>\n value !== null &&\n (typeof value === \"object\" || typeof value === \"function\") &&\n \"~standard\" in value;\n\n/** True when the argument is the no-validation (bare handler) overload. */\nexport const isBareHandler = (value: unknown): boolean =>\n typeof value === \"function\" && !isStandardSchema(value) && !Schema.isSchema(value);\n\n/**\n * Normalise a validator argument: a bare Effect `Schema` is wrapped with\n * `Schema.toStandardSchemaV1` so callers can pass it directly; a Standard Schema\n * or the `\"unchecked\"` marker passes through untouched.\n */\nexport const toStandardValidator = (value: unknown): unknown =>\n Schema.isSchema(value)\n ? (Schema.toStandardSchemaV1 as (schema: Schema.Top) => StandardSchemaV1)(value)\n : value;\n"],"mappings":";;;;;;;;;;AAiBA,MAAa,oBAAoB,UAC/B,UAAU,SACT,OAAO,UAAU,YAAY,OAAO,UAAU,eAC/C,eAAe;;AAGjB,MAAa,iBAAiB,UAC5B,OAAO,UAAU,cAAc,CAAC,iBAAiB,KAAK,KAAK,CAAC,OAAO,SAAS,KAAK;;;;;;AAOnF,MAAa,uBAAuB,UAClC,OAAO,SAAS,KAAK,IAChB,OAAO,mBAAgE,KAAK,IAC7E"}
1
+ {"version":3,"file":"remote-validators.js","names":[],"sources":["../../src/internal/remote-validators.ts"],"sourcesContent":["/**\n * Validator-argument helpers for the remote-function wrappers, factored out so\n * they can be unit-tested without importing `$app/server` (which is a SvelteKit\n * virtual module unavailable outside an app build).\n */\n\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport * as Predicate from \"effect/Predicate\";\nimport * as Schema from \"effect/Schema\";\n\n/**\n * Detects a Standard Schema validator via its `~standard` marker property.\n *\n * This cannot be a simple `typeof value === \"function\"` check on the handler\n * position: some Standard Schema implementations (such as Effect's\n * `Schema.toStandardSchemaV1`) return callable class values, which would be\n * mistaken for handler functions.\n */\nexport const isStandardSchema = <V>(value: V): value is V & StandardSchemaV1 =>\n Predicate.hasProperty(value, \"~standard\");\n\n/** True when the argument is the no-validation (bare handler) overload. */\nexport const isBareHandler = <V>(value: V): boolean =>\n Predicate.isFunction(value) && !isStandardSchema(value) && !Schema.isSchema(value);\n\n/**\n * Normalise a validator argument: a bare Effect `Schema` is wrapped with\n * `Schema.toStandardSchemaV1` so callers can pass it directly; a Standard Schema\n * or the `\"unchecked\"` marker passes through untouched.\n */\nexport const toStandardValidator = <V>(value: V): StandardValidator<V> =>\n // SAFETY: the inner cast only drops `toStandardSchemaV1`'s compile-time\n // `DecodingServices: never` constraint (the runtime conversion is the same\n // for every schema, and the remote helpers' callers pass schemas whose\n // decoding needs no services); the outer one restates the branch\n // `Schema.isSchema` took, which TypeScript cannot carry into the conditional\n // return type.\n (Schema.isSchema(value)\n ? (Schema.toStandardSchemaV1 as (schema: Schema.Top) => StandardSchemaV1)(value)\n : value) as StandardValidator<V>;\n\n/**\n * What {@link toStandardValidator} returns for `V`: a Standard Schema for an\n * Effect `Schema`, else `V` unchanged.\n */\nexport type StandardValidator<V> = V extends Schema.Top\n ? StandardSchemaV1<V[\"Encoded\"], V[\"Type\"]>\n : V;\n"],"mappings":";;;;;;;;;;;AAkBA,MAAa,oBAAuB,UAClC,UAAU,YAAY,OAAO,WAAW;;AAG1C,MAAa,iBAAoB,UAC/B,UAAU,WAAW,KAAK,KAAK,CAAC,iBAAiB,KAAK,KAAK,CAAC,OAAO,SAAS,KAAK;;;;;;AAOnF,MAAa,uBAA0B,UAOpC,OAAO,SAAS,KAAK,IACjB,OAAO,mBAAgE,KAAK,IAC7E"}
@@ -16,7 +16,6 @@ import { RequestEvent } from "@sveltejs/kit";
16
16
  * bare type-check (no generated types) it falls back to `Record<string, string>`,
17
17
  * exactly as SvelteKit's own `AppLayoutParams<'/'>` does.
18
18
  */
19
- type SvelteRouteParams = RequestEvent["params"];
19
+ export type SvelteRouteParams = RequestEvent["params"];
20
20
  //#endregion
21
- export { SvelteRouteParams };
22
21
  //# sourceMappingURL=route-params.d.ts.map
@@ -1,3 +1,4 @@
1
+ import * as Arr from "effect/Array";
1
2
  //#region src/internal/sse.ts
2
3
  /**
3
4
  * Server-Sent Events framing helpers, factored out of the endpoint wrapper so
@@ -23,7 +24,7 @@ const encodeSseFrame = (frame) => {
23
24
  let out = "";
24
25
  if (frame.id !== void 0) out += `id: ${frame.id}\n`;
25
26
  if (frame.event !== void 0) out += `event: ${frame.event}\n`;
26
- for (const line of frame.data.split("\n")) out += `data: ${line}\n`;
27
+ out += Arr.map(frame.data.split("\n"), (line) => `data: ${line}\n`).join("");
27
28
  out += "\n";
28
29
  return out;
29
30
  };
@@ -1 +1 @@
1
- {"version":3,"file":"sse.js","names":[],"sources":["../../src/internal/sse.ts"],"sourcesContent":["/**\n * Server-Sent Events framing helpers, factored out of the endpoint wrapper so\n * the wire format can be unit-tested in isolation.\n *\n * See the [SSE specification](https://html.spec.whatwg.org/multipage/server-sent-events.html).\n */\n\n/** The response headers required for a `text/event-stream` body. */\nexport const SSE_HEADERS: Readonly<Record<string, string>> = {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n};\n\n/** The fields of a single SSE event. */\nexport interface SseFrame {\n /** The event payload. Multi-line strings are split into multiple `data:` lines. */\n readonly data: string;\n /** Optional event name (`event:` field). */\n readonly event?: string | undefined;\n /** Optional event id (`id:` field), which the browser echoes on reconnect. */\n readonly id?: string | undefined;\n}\n\n/**\n * Encode a single SSE event as its wire representation, terminated by the\n * blank line that dispatches it.\n *\n * `data` is split on newlines into one `data:` line each (per the spec, a bare\n * newline in a value would otherwise be ambiguous). `event` / `id` are emitted\n * only when present.\n */\nexport const encodeSseFrame = (frame: SseFrame): string => {\n let out = \"\";\n if (frame.id !== undefined) out += `id: ${frame.id}\\n`;\n if (frame.event !== undefined) out += `event: ${frame.event}\\n`;\n // Split into per-line `data:` fields so embedded newlines survive.\n for (const line of frame.data.split(\"\\n\")) out += `data: ${line}\\n`;\n out += \"\\n\";\n return out;\n};\n\n/** Encode the one-shot `retry:` field that sets the client reconnection delay. */\nexport const encodeRetry = (milliseconds: number): string => `retry: ${milliseconds}\\n\\n`;\n\n/** A comment line used as a heartbeat/keepalive (ignored by the client). */\nexport const HEARTBEAT_FRAME = \": heartbeat\\n\\n\";\n"],"mappings":";;;;;;;;AAQA,MAAa,cAAgD;CAC3D,gBAAgB;CAChB,iBAAiB;CACjB,YAAY;AACd;;;;;;;;;AAoBA,MAAa,kBAAkB,UAA4B;CACzD,IAAI,MAAM;CACV,IAAI,MAAM,OAAO,KAAA,GAAW,OAAO,OAAO,MAAM,GAAG;CACnD,IAAI,MAAM,UAAU,KAAA,GAAW,OAAO,UAAU,MAAM,MAAM;CAE5D,KAAK,MAAM,QAAQ,MAAM,KAAK,MAAM,IAAI,GAAG,OAAO,SAAS,KAAK;CAChE,OAAO;CACP,OAAO;AACT;;AAGA,MAAa,eAAe,iBAAiC,UAAU,aAAa;;AAGpF,MAAa,kBAAkB"}
1
+ {"version":3,"file":"sse.js","names":[],"sources":["../../src/internal/sse.ts"],"sourcesContent":["/**\n * Server-Sent Events framing helpers, factored out of the endpoint wrapper so\n * the wire format can be unit-tested in isolation.\n *\n * See the [SSE specification](https://html.spec.whatwg.org/multipage/server-sent-events.html).\n */\n\nimport * as Arr from \"effect/Array\";\n\n/** The response headers required for a `text/event-stream` body. */\nexport const SSE_HEADERS = {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n} as const satisfies Readonly<Record<string, string>>;\n\n/** The fields of a single SSE event. */\nexport interface SseFrame {\n /** The event payload. Multi-line strings are split into multiple `data:` lines. */\n readonly data: string;\n /** Optional event name (`event:` field). */\n readonly event?: string | undefined;\n /** Optional event id (`id:` field), which the browser echoes on reconnect. */\n readonly id?: string | undefined;\n}\n\n/**\n * Encode a single SSE event as its wire representation, terminated by the\n * blank line that dispatches it.\n *\n * `data` is split on newlines into one `data:` line each (per the spec, a bare\n * newline in a value would otherwise be ambiguous). `event` / `id` are emitted\n * only when present.\n */\nexport const encodeSseFrame = (frame: SseFrame): string => {\n let out = \"\";\n if (frame.id !== undefined) out += `id: ${frame.id}\\n`;\n if (frame.event !== undefined) out += `event: ${frame.event}\\n`;\n // Split into per-line `data:` fields so embedded newlines survive.\n out += Arr.map(frame.data.split(\"\\n\"), (line) => `data: ${line}\\n`).join(\"\");\n out += \"\\n\";\n return out;\n};\n\n/** Encode the one-shot `retry:` field that sets the client reconnection delay. */\nexport const encodeRetry = (milliseconds: number): string => `retry: ${milliseconds}\\n\\n`;\n\n/** A comment line used as a heartbeat/keepalive (ignored by the client). */\nexport const HEARTBEAT_FRAME = \": heartbeat\\n\\n\";\n"],"mappings":";;;;;;;;;AAUA,MAAa,cAAc;CACzB,gBAAgB;CAChB,iBAAiB;CACjB,YAAY;AACd;;;;;;;;;AAoBA,MAAa,kBAAkB,UAA4B;CACzD,IAAI,MAAM;CACV,IAAI,MAAM,OAAO,KAAA,GAAW,OAAO,OAAO,MAAM,GAAG;CACnD,IAAI,MAAM,UAAU,KAAA,GAAW,OAAO,UAAU,MAAM,MAAM;CAE5D,OAAO,IAAI,IAAI,MAAM,KAAK,MAAM,IAAI,IAAI,SAAS,SAAS,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE;CAC3E,OAAO;CACP,OAAO;AACT;;AAGA,MAAa,eAAe,iBAAiC,UAAU,aAAa;;AAGpF,MAAa,kBAAkB"}
package/dist/kit.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- import { Cause, Effect } from "effect";
1
+ import { KitErrorBody } from "./internal/error.js";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Cause from "effect/Cause";
2
4
  //#region src/kit.d.ts
3
5
  /**
4
6
  * An Effect-native redirect. Yield via {@link SvelteKit.redirect}; translated
5
7
  * at the request boundary by {@link SvelteKit.translate}.
6
8
  */
7
- declare class KitRedirect extends Error {
9
+ export declare class KitRedirect extends Error {
8
10
  readonly status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308;
9
11
  readonly location: string | URL;
10
12
  readonly _tag: "KitRedirect";
@@ -14,17 +16,17 @@ declare class KitRedirect extends Error {
14
16
  * An Effect-native HTTP error. Yield via {@link SvelteKit.error}; translated
15
17
  * at the request boundary by {@link SvelteKit.translate}.
16
18
  */
17
- declare class KitError extends Error {
19
+ export declare class KitError extends Error {
18
20
  readonly status: number;
19
- readonly body?: (string | Record<string, unknown>) | undefined;
21
+ readonly body?: KitErrorBody | undefined;
20
22
  readonly _tag: "KitError";
21
- constructor(status: number, body?: (string | Record<string, unknown>) | undefined);
23
+ constructor(status: number, body?: KitErrorBody | undefined);
22
24
  }
23
25
  /**
24
26
  * An Effect-native form-action failure. Yield via {@link SvelteKit.fail};
25
27
  * translated at the request boundary by {@link SvelteKit.translate}.
26
28
  */
27
- declare class KitActionFailure<T extends Record<string, unknown> = Record<string, unknown>> extends Error {
29
+ export declare class KitActionFailure<T = undefined> extends Error {
28
30
  readonly status: number;
29
31
  readonly data: T;
30
32
  readonly _tag: "KitActionFailure";
@@ -36,7 +38,7 @@ declare class KitActionFailure<T extends Record<string, unknown> = Record<string
36
38
  * Receives the squashed error value. Throw (e.g. `error()` / `redirect()`) to
37
39
  * handle the case; return normally to pass through to the next case.
38
40
  */
39
- type KitTranslatorCase = (error: unknown) => undefined | void;
41
+ export type KitTranslatorCase = (error: unknown) => undefined | void;
40
42
  /**
41
43
  * A boundary translator: turn a failed `Cause` into thrown SvelteKit control
42
44
  * flow or an `ActionFailure` return value.
@@ -45,7 +47,7 @@ type KitTranslatorCase = (error: unknown) => undefined | void;
45
47
  * {@link KitRedirect}, {@link KitError}, and {@link KitActionFailure}. Build a
46
48
  * custom translator via {@link SvelteKit.makeTranslator}.
47
49
  */
48
- type KitErrorTranslator = (cause: Cause.Cause<unknown>) => never;
50
+ export type KitErrorTranslator = (cause: Cause.Cause<unknown>) => never;
49
51
  /**
50
52
  * Effect-native SvelteKit control-flow helpers and the default boundary
51
53
  * translator.
@@ -58,7 +60,7 @@ type KitErrorTranslator = (cause: Cause.Cause<unknown>) => never;
58
60
  * `translateError` for every server wrapper (`serverLoad`, `action`,
59
61
  * `makeRuntimeAdapter`, `RemoteFunction.withRuntime`, etc.).
60
62
  */
61
- declare const SvelteKit: {
63
+ export declare const SvelteKit: {
62
64
  /**
63
65
  * Fail with a redirect. Equivalent to SvelteKit's `redirect()` but as an
64
66
  * Effect failure instead of a thrown exception.
@@ -79,7 +81,7 @@ declare const SvelteKit: {
79
81
  * yield* SvelteKit.error(403, { message: "Forbidden" });
80
82
  * ```
81
83
  */
82
- readonly error: (status: number, body?: string | Record<string, unknown>) => Effect.Effect<never, KitError>;
84
+ readonly error: (status: number, body?: KitErrorBody) => Effect.Effect<never, KitError>;
83
85
  /**
84
86
  * Fail with a form-action failure. Equivalent to SvelteKit's `fail()` but as
85
87
  * an Effect failure instead of a return value.
@@ -125,5 +127,4 @@ declare const SvelteKit: {
125
127
  readonly makeTranslator: (extraCases: ReadonlyArray<KitTranslatorCase>) => KitErrorTranslator;
126
128
  };
127
129
  //#endregion
128
- export { KitActionFailure, KitError, KitErrorTranslator, KitRedirect, KitTranslatorCase, SvelteKit };
129
130
  //# sourceMappingURL=kit.d.ts.map
package/dist/kit.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { causeToThrowable, throwKitError } from "./internal/error.js";
2
- import { Cause, Effect } from "effect";
2
+ import * as Effect from "effect/Effect";
3
3
  import { fail, redirect } from "@sveltejs/kit";
4
+ import * as Arr from "effect/Array";
5
+ import * as Cause from "effect/Cause";
4
6
  //#region src/kit.ts
5
7
  /**
6
8
  * Effect-native SvelteKit control-flow errors and a turnkey boundary translator.
@@ -175,7 +177,9 @@ const SvelteKit = {
175
177
  */
176
178
  makeTranslator: (extraCases) => (cause) => {
177
179
  const squashed = Cause.squash(cause);
178
- for (const matcher of extraCases) matcher(squashed);
180
+ Arr.forEach(extraCases, (matcher) => {
181
+ matcher(squashed);
182
+ });
179
183
  return baseTranslate(cause);
180
184
  }
181
185
  };
package/dist/kit.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"kit.js","names":["kitFail"],"sources":["../src/kit.ts"],"sourcesContent":["/**\n * Effect-native SvelteKit control-flow errors and a turnkey boundary translator.\n *\n * Every server consumer previously needed to hand-roll their own `translateError`\n * that mapped domain errors → `redirect()` / `error()` / `fail()`. This module\n * ships the catalogue those consumers all reinvented:\n *\n * - {@link KitRedirect}, {@link KitError}, {@link KitActionFailure} — tagged\n * Effect failure types for each SvelteKit control-flow call.\n * - {@link SvelteKit.redirect}, {@link SvelteKit.error}, {@link SvelteKit.fail}\n * — helpers that `yield*` a typed failure instead of throwing.\n * - {@link SvelteKit.translate} — the base `ErrorTranslator` that converts those\n * failures to the appropriate SvelteKit call at the request boundary.\n * - {@link SvelteKit.makeTranslator} — compose `translate` with your own\n * domain-error cases (consumer cases run first).\n *\n * @example\n * ```ts\n * import { SvelteKit, makeRuntimeAdapter, RequestRuntime } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Effect } from \"effect\";\n *\n * // Yield kit errors instead of throwing:\n * const load = serverLoad(() =>\n * Effect.gen(function* () {\n * const user = yield* getUser;\n * if (!user) yield* SvelteKit.redirect(303, \"/login\");\n * if (!user.active) yield* SvelteKit.error(403, \"Account disabled\");\n * return { user };\n * })\n * );\n *\n * // Compose with your own domain errors:\n * import { error } from \"@sveltejs/kit\";\n * const { serverLoad } = makeRuntimeAdapter(\n * RequestRuntime.fromLayer(AppLayer),\n * {\n * translateError: SvelteKit.makeTranslator([\n * (e) => { if (e instanceof NotFound) error(404, \"Not found\"); },\n * ]),\n * },\n * );\n * ```\n */\n\nimport { fail as kitFail, redirect as kitRedirect } from \"@sveltejs/kit\";\nimport { Cause, Effect } from \"effect\";\nimport { causeToThrowable, throwKitError } from \"./internal/error.js\";\n\n// ─── Tagged error classes ────────────────────────────────────────────────────\n\n/**\n * An Effect-native redirect. Yield via {@link SvelteKit.redirect}; translated\n * at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitRedirect extends Error {\n readonly _tag = \"KitRedirect\" as const;\n\n constructor(\n readonly status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308,\n readonly location: string | URL,\n ) {\n super(`Redirect to ${String(location)}`);\n this.name = \"KitRedirect\";\n }\n}\n\n/**\n * An Effect-native HTTP error. Yield via {@link SvelteKit.error}; translated\n * at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitError extends Error {\n readonly _tag = \"KitError\" as const;\n\n constructor(\n readonly status: number,\n readonly body?: string | Record<string, unknown>,\n ) {\n super(`HTTP ${status}`);\n this.name = \"KitError\";\n }\n}\n\n/**\n * An Effect-native form-action failure. Yield via {@link SvelteKit.fail};\n * translated at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitActionFailure<\n T extends Record<string, unknown> = Record<string, unknown>,\n> extends Error {\n readonly _tag = \"KitActionFailure\" as const;\n\n constructor(\n readonly status: number,\n readonly data: T,\n ) {\n super(`Action failure ${status}`);\n this.name = \"KitActionFailure\";\n }\n}\n\n// ─── Translator types ────────────────────────────────────────────────────────\n\n/**\n * A single domain-error case for {@link SvelteKit.makeTranslator}.\n *\n * Receives the squashed error value. Throw (e.g. `error()` / `redirect()`) to\n * handle the case; return normally to pass through to the next case.\n */\nexport type KitTranslatorCase = (error: unknown) => undefined | void;\n\n/**\n * A boundary translator: turn a failed `Cause` into thrown SvelteKit control\n * flow or an `ActionFailure` return value.\n *\n * The Kit base translator ({@link SvelteKit.translate}) handles\n * {@link KitRedirect}, {@link KitError}, and {@link KitActionFailure}. Build a\n * custom translator via {@link SvelteKit.makeTranslator}.\n */\nexport type KitErrorTranslator = (cause: Cause.Cause<unknown>) => never;\n\n// ─── Base translator ─────────────────────────────────────────────────────────\n\nconst baseTranslate: KitErrorTranslator = (cause) => {\n const squashed = Cause.squash(cause);\n\n if (squashed instanceof KitRedirect) {\n // redirect() is typed as () => never — throws internally.\n kitRedirect(squashed.status, squashed.location as string);\n }\n\n if (squashed instanceof KitError) {\n // throwKitError() is typed as never: it always throws Kit's HttpError.\n throwKitError(squashed.status, squashed.body);\n }\n\n if (squashed instanceof KitActionFailure) {\n // fail() returns an ActionFailure (doesn't throw). SvelteKit detects it as\n // the action's return value. Typed as never to satisfy ErrorTranslator while\n // allowing makeRuntimeAdapter's `return translateError(cause)` to propagate\n // the ActionFailure to SvelteKit correctly at runtime.\n return kitFail(squashed.status, squashed.data) as never;\n }\n\n throw causeToThrowable(cause);\n};\n\n// ─── Public namespace ─────────────────────────────────────────────────────────\n\n/**\n * Effect-native SvelteKit control-flow helpers and the default boundary\n * translator.\n *\n * **Error types**: {@link KitRedirect}, {@link KitError}, {@link KitActionFailure}\n * are tagged Effect failures — use them with `Effect.catchTag`, `Match.tag`,\n * and `instanceof` checks.\n *\n * **Default translator**: `SvelteKit.translate` is wired in as the default\n * `translateError` for every server wrapper (`serverLoad`, `action`,\n * `makeRuntimeAdapter`, `RemoteFunction.withRuntime`, etc.).\n */\nexport const SvelteKit = {\n /**\n * Fail with a redirect. Equivalent to SvelteKit's `redirect()` but as an\n * Effect failure instead of a thrown exception.\n *\n * @example\n * ```ts\n * yield* SvelteKit.redirect(303, \"/login\");\n * ```\n */\n redirect: (\n status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308,\n location: string | URL,\n ): Effect.Effect<never, KitRedirect> => Effect.fail(new KitRedirect(status, location)),\n\n /**\n * Fail with an HTTP error. Equivalent to SvelteKit's `error()` but as an\n * Effect failure instead of a thrown exception.\n *\n * @example\n * ```ts\n * yield* SvelteKit.error(404, \"Not found\");\n * yield* SvelteKit.error(403, { message: \"Forbidden\" });\n * ```\n */\n error: (\n status: number,\n body?: string | Record<string, unknown>,\n ): Effect.Effect<never, KitError> => Effect.fail(new KitError(status, body)),\n\n /**\n * Fail with a form-action failure. Equivalent to SvelteKit's `fail()` but as\n * an Effect failure instead of a return value.\n *\n * @example\n * ```ts\n * yield* SvelteKit.fail(422, { email: \"already taken\" });\n * ```\n */\n fail: <T extends Record<string, unknown>>(\n status: number,\n data: T,\n ): Effect.Effect<never, KitActionFailure<T>> => Effect.fail(new KitActionFailure(status, data)),\n\n /**\n * The turnkey boundary translator. Converts {@link KitRedirect} →\n * `redirect()`, {@link KitError} → `error()`, {@link KitActionFailure} →\n * `fail()`, and anything else → `EffectCauseError` (500).\n *\n * This is the default `translateError` for every server wrapper. To extend it\n * with your own domain errors, use {@link SvelteKit.makeTranslator}.\n */\n translate: baseTranslate,\n\n /**\n * Build a custom boundary translator by prepending domain-error cases before\n * the Kit base cases.\n *\n * Each case function receives the squashed error value. Throw (e.g. call\n * `error()` / `redirect()` from `@sveltejs/kit`) to handle the case; return\n * normally to pass through to the next case or the Kit base translator.\n *\n * @example\n * ```ts\n * import { error } from \"@sveltejs/kit\";\n *\n * const translateError = SvelteKit.makeTranslator([\n * (e) => { if (e instanceof NotFound) error(404, \"Not found\"); },\n * (e) => { if (e instanceof Forbidden) error(403, \"Forbidden\"); },\n * ]);\n *\n * const { serverLoad } = makeRuntimeAdapter(\n * RequestRuntime.fromLayer(AppLayer),\n * { translateError },\n * );\n * ```\n */\n makeTranslator:\n (extraCases: ReadonlyArray<KitTranslatorCase>): KitErrorTranslator =>\n (cause) => {\n const squashed = Cause.squash(cause);\n for (const matcher of extraCases) {\n matcher(squashed);\n }\n return baseTranslate(cause);\n },\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,IAAa,cAAb,cAAiC,MAAM;CAI1B;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,UACA;EACA,MAAM,eAAe,OAAO,QAAQ,GAAG;EAH9B,KAAA,SAAA;EACA,KAAA,WAAA;EAGT,KAAK,OAAO;CACd;AACF;;;;;AAMA,IAAa,WAAb,cAA8B,MAAM;CAIvB;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,MACA;EACA,MAAM,QAAQ,QAAQ;EAHb,KAAA,SAAA;EACA,KAAA,OAAA;EAGT,KAAK,OAAO;CACd;AACF;;;;;AAMA,IAAa,mBAAb,cAEU,MAAM;CAIH;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,MACA;EACA,MAAM,kBAAkB,QAAQ;EAHvB,KAAA,SAAA;EACA,KAAA,OAAA;EAGT,KAAK,OAAO;CACd;AACF;AAwBA,MAAM,iBAAqC,UAAU;CACnD,MAAM,WAAW,MAAM,OAAO,KAAK;CAEnC,IAAI,oBAAoB,aAEtB,SAAY,SAAS,QAAQ,SAAS,QAAkB;CAG1D,IAAI,oBAAoB,UAEtB,cAAc,SAAS,QAAQ,SAAS,IAAI;CAG9C,IAAI,oBAAoB,kBAKtB,OAAOA,KAAQ,SAAS,QAAQ,SAAS,IAAI;CAG/C,MAAM,iBAAiB,KAAK;AAC9B;;;;;;;;;;;;;AAgBA,MAAa,YAAY;;;;;;;;;;CAUvB,WACE,QACA,aACsC,OAAO,KAAK,IAAI,YAAY,QAAQ,QAAQ,CAAC;;;;;;;;;;;CAYrF,QACE,QACA,SACmC,OAAO,KAAK,IAAI,SAAS,QAAQ,IAAI,CAAC;;;;;;;;;;CAW3E,OACE,QACA,SAC8C,OAAO,KAAK,IAAI,iBAAiB,QAAQ,IAAI,CAAC;;;;;;;;;CAU9F,WAAW;;;;;;;;;;;;;;;;;;;;;;;;CAyBX,iBACG,gBACA,UAAU;EACT,MAAM,WAAW,MAAM,OAAO,KAAK;EACnC,KAAK,MAAM,WAAW,YACpB,QAAQ,QAAQ;EAElB,OAAO,cAAc,KAAK;CAC5B;AACJ"}
1
+ {"version":3,"file":"kit.js","names":["kitFail"],"sources":["../src/kit.ts"],"sourcesContent":["/**\n * Effect-native SvelteKit control-flow errors and a turnkey boundary translator.\n *\n * Every server consumer previously needed to hand-roll their own `translateError`\n * that mapped domain errors → `redirect()` / `error()` / `fail()`. This module\n * ships the catalogue those consumers all reinvented:\n *\n * - {@link KitRedirect}, {@link KitError}, {@link KitActionFailure} — tagged\n * Effect failure types for each SvelteKit control-flow call.\n * - {@link SvelteKit.redirect}, {@link SvelteKit.error}, {@link SvelteKit.fail}\n * — helpers that `yield*` a typed failure instead of throwing.\n * - {@link SvelteKit.translate} — the base `ErrorTranslator` that converts those\n * failures to the appropriate SvelteKit call at the request boundary.\n * - {@link SvelteKit.makeTranslator} — compose `translate` with your own\n * domain-error cases (consumer cases run first).\n *\n * @example\n * ```ts\n * import { SvelteKit, makeRuntimeAdapter, RequestRuntime } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Effect } from \"effect\";\n *\n * // Yield kit errors instead of throwing:\n * const load = serverLoad(() =>\n * Effect.gen(function* () {\n * const user = yield* getUser;\n * if (!user) yield* SvelteKit.redirect(303, \"/login\");\n * if (!user.active) yield* SvelteKit.error(403, \"Account disabled\");\n * return { user };\n * })\n * );\n *\n * // Compose with your own domain errors:\n * import { error } from \"@sveltejs/kit\";\n * const { serverLoad } = makeRuntimeAdapter(\n * RequestRuntime.fromLayer(AppLayer),\n * {\n * translateError: SvelteKit.makeTranslator([\n * (e) => { if (e instanceof NotFound) error(404, \"Not found\"); },\n * ]),\n * },\n * );\n * ```\n */\n\nimport { fail as kitFail, redirect as kitRedirect } from \"@sveltejs/kit\";\nimport * as Arr from \"effect/Array\";\nimport * as Cause from \"effect/Cause\";\nimport * as Effect from \"effect/Effect\";\nimport { causeToThrowable, throwKitError, type KitErrorBody } from \"./internal/error.js\";\n\n// ─── Tagged error classes ────────────────────────────────────────────────────\n\n/**\n * An Effect-native redirect. Yield via {@link SvelteKit.redirect}; translated\n * at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitRedirect extends Error {\n readonly _tag = \"KitRedirect\" as const;\n\n constructor(\n readonly status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308,\n readonly location: string | URL,\n ) {\n super(`Redirect to ${String(location)}`);\n this.name = \"KitRedirect\";\n }\n}\n\n/**\n * An Effect-native HTTP error. Yield via {@link SvelteKit.error}; translated\n * at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitError extends Error {\n readonly _tag = \"KitError\" as const;\n\n constructor(\n readonly status: number,\n readonly body?: KitErrorBody,\n ) {\n super(`HTTP ${status}`);\n this.name = \"KitError\";\n }\n}\n\n/**\n * An Effect-native form-action failure. Yield via {@link SvelteKit.fail};\n * translated at the request boundary by {@link SvelteKit.translate}.\n */\nexport class KitActionFailure<T = undefined> extends Error {\n readonly _tag = \"KitActionFailure\" as const;\n\n constructor(\n readonly status: number,\n readonly data: T,\n ) {\n super(`Action failure ${status}`);\n this.name = \"KitActionFailure\";\n }\n}\n\n// ─── Translator types ────────────────────────────────────────────────────────\n\n/**\n * A single domain-error case for {@link SvelteKit.makeTranslator}.\n *\n * Receives the squashed error value. Throw (e.g. `error()` / `redirect()`) to\n * handle the case; return normally to pass through to the next case.\n */\nexport type KitTranslatorCase = (error: unknown) => undefined | void;\n\n/**\n * A boundary translator: turn a failed `Cause` into thrown SvelteKit control\n * flow or an `ActionFailure` return value.\n *\n * The Kit base translator ({@link SvelteKit.translate}) handles\n * {@link KitRedirect}, {@link KitError}, and {@link KitActionFailure}. Build a\n * custom translator via {@link SvelteKit.makeTranslator}.\n */\nexport type KitErrorTranslator = (cause: Cause.Cause<unknown>) => never;\n\n// ─── Base translator ─────────────────────────────────────────────────────────\n\nconst baseTranslate: KitErrorTranslator = (cause) => {\n const squashed = Cause.squash(cause);\n\n if (squashed instanceof KitRedirect) {\n // redirect() is typed as () => never — throws internally.\n kitRedirect(squashed.status, squashed.location);\n }\n\n if (squashed instanceof KitError) {\n // throwKitError() is typed as never: it always throws Kit's HttpError.\n throwKitError(squashed.status, squashed.body);\n }\n\n if (squashed instanceof KitActionFailure) {\n // fail() returns an ActionFailure (doesn't throw). SvelteKit detects it as\n // the action's return value. Typed as never to satisfy ErrorTranslator while\n // allowing makeRuntimeAdapter's `return translateError(cause)` to propagate\n // the ActionFailure to SvelteKit correctly at runtime.\n // SAFETY: the `never` only satisfies the `KitErrorTranslator` contract;\n // every caller returns the translator's result straight to SvelteKit, which\n // treats a returned `ActionFailure` as the action's failure response.\n return kitFail(squashed.status, squashed.data) as never;\n }\n\n throw causeToThrowable(cause);\n};\n\n// ─── Public namespace ─────────────────────────────────────────────────────────\n\n/**\n * Effect-native SvelteKit control-flow helpers and the default boundary\n * translator.\n *\n * **Error types**: {@link KitRedirect}, {@link KitError}, {@link KitActionFailure}\n * are tagged Effect failures — use them with `Effect.catchTag`, `Match.tag`,\n * and `instanceof` checks.\n *\n * **Default translator**: `SvelteKit.translate` is wired in as the default\n * `translateError` for every server wrapper (`serverLoad`, `action`,\n * `makeRuntimeAdapter`, `RemoteFunction.withRuntime`, etc.).\n */\nexport const SvelteKit = {\n /**\n * Fail with a redirect. Equivalent to SvelteKit's `redirect()` but as an\n * Effect failure instead of a thrown exception.\n *\n * @example\n * ```ts\n * yield* SvelteKit.redirect(303, \"/login\");\n * ```\n */\n redirect: (\n status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308,\n location: string | URL,\n ): Effect.Effect<never, KitRedirect> => Effect.fail(new KitRedirect(status, location)),\n\n /**\n * Fail with an HTTP error. Equivalent to SvelteKit's `error()` but as an\n * Effect failure instead of a thrown exception.\n *\n * @example\n * ```ts\n * yield* SvelteKit.error(404, \"Not found\");\n * yield* SvelteKit.error(403, { message: \"Forbidden\" });\n * ```\n */\n error: (status: number, body?: KitErrorBody): Effect.Effect<never, KitError> =>\n Effect.fail(new KitError(status, body)),\n\n /**\n * Fail with a form-action failure. Equivalent to SvelteKit's `fail()` but as\n * an Effect failure instead of a return value.\n *\n * @example\n * ```ts\n * yield* SvelteKit.fail(422, { email: \"already taken\" });\n * ```\n */\n fail: <T extends Record<string, unknown>>(\n status: number,\n data: T,\n ): Effect.Effect<never, KitActionFailure<T>> => Effect.fail(new KitActionFailure(status, data)),\n\n /**\n * The turnkey boundary translator. Converts {@link KitRedirect} →\n * `redirect()`, {@link KitError} → `error()`, {@link KitActionFailure} →\n * `fail()`, and anything else → `EffectCauseError` (500).\n *\n * This is the default `translateError` for every server wrapper. To extend it\n * with your own domain errors, use {@link SvelteKit.makeTranslator}.\n */\n translate: baseTranslate,\n\n /**\n * Build a custom boundary translator by prepending domain-error cases before\n * the Kit base cases.\n *\n * Each case function receives the squashed error value. Throw (e.g. call\n * `error()` / `redirect()` from `@sveltejs/kit`) to handle the case; return\n * normally to pass through to the next case or the Kit base translator.\n *\n * @example\n * ```ts\n * import { error } from \"@sveltejs/kit\";\n *\n * const translateError = SvelteKit.makeTranslator([\n * (e) => { if (e instanceof NotFound) error(404, \"Not found\"); },\n * (e) => { if (e instanceof Forbidden) error(403, \"Forbidden\"); },\n * ]);\n *\n * const { serverLoad } = makeRuntimeAdapter(\n * RequestRuntime.fromLayer(AppLayer),\n * { translateError },\n * );\n * ```\n */\n makeTranslator:\n (extraCases: ReadonlyArray<KitTranslatorCase>): KitErrorTranslator =>\n (cause) => {\n const squashed = Cause.squash(cause);\n Arr.forEach(extraCases, (matcher) => {\n matcher(squashed);\n });\n return baseTranslate(cause);\n },\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDA,IAAa,cAAb,cAAiC,MAAM;CAI1B;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,UACA;EACA,MAAM,eAAe,OAAO,QAAQ,GAAG;EAH9B,KAAA,SAAA;EACA,KAAA,WAAA;EAGT,KAAK,OAAO;CACd;AACF;;;;;AAMA,IAAa,WAAb,cAA8B,MAAM;CAIvB;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,MACA;EACA,MAAM,QAAQ,QAAQ;EAHb,KAAA,SAAA;EACA,KAAA,OAAA;EAGT,KAAK,OAAO;CACd;AACF;;;;;AAMA,IAAa,mBAAb,cAAqD,MAAM;CAI9C;CACA;CAJX,OAAgB;CAEhB,YACE,QACA,MACA;EACA,MAAM,kBAAkB,QAAQ;EAHvB,KAAA,SAAA;EACA,KAAA,OAAA;EAGT,KAAK,OAAO;CACd;AACF;AAwBA,MAAM,iBAAqC,UAAU;CACnD,MAAM,WAAW,MAAM,OAAO,KAAK;CAEnC,IAAI,oBAAoB,aAEtB,SAAY,SAAS,QAAQ,SAAS,QAAQ;CAGhD,IAAI,oBAAoB,UAEtB,cAAc,SAAS,QAAQ,SAAS,IAAI;CAG9C,IAAI,oBAAoB,kBAQtB,OAAOA,KAAQ,SAAS,QAAQ,SAAS,IAAI;CAG/C,MAAM,iBAAiB,KAAK;AAC9B;;;;;;;;;;;;;AAgBA,MAAa,YAAY;;;;;;;;;;CAUvB,WACE,QACA,aACsC,OAAO,KAAK,IAAI,YAAY,QAAQ,QAAQ,CAAC;;;;;;;;;;;CAYrF,QAAQ,QAAgB,SACtB,OAAO,KAAK,IAAI,SAAS,QAAQ,IAAI,CAAC;;;;;;;;;;CAWxC,OACE,QACA,SAC8C,OAAO,KAAK,IAAI,iBAAiB,QAAQ,IAAI,CAAC;;;;;;;;;CAU9F,WAAW;;;;;;;;;;;;;;;;;;;;;;;;CAyBX,iBACG,gBACA,UAAU;EACT,MAAM,WAAW,MAAM,OAAO,KAAK;EACnC,IAAI,QAAQ,aAAa,YAAY;GACnC,QAAQ,QAAQ;EAClB,CAAC;EACD,OAAO,cAAc,KAAK;CAC5B;AACJ"}
@@ -1,9 +1,11 @@
1
- import { Cause, Stream } from "effect";
1
+ import * as Cause from "effect/Cause";
2
+ import * as Stream from "effect/Stream";
3
+ import * as Schema from "effect/Schema";
2
4
  declare namespace realtime_d_exports {
3
5
  export { EventSourceConstructor, EventSourceError, FromEventSourceOptions, FromWebSocketOptions, SseMessage, WebSocketConstructor, WebSocketError, fromEventSource, fromWebSocket };
4
6
  }
5
7
  /** A decoded Server-Sent Event. */
6
- interface SseMessage {
8
+ export interface SseMessage {
7
9
  /** The event name (`"message"` for unnamed events). */
8
10
  readonly event: string;
9
11
  /** The event payload (the joined `data:` lines). */
@@ -11,26 +13,24 @@ interface SseMessage {
11
13
  /** The last event id seen, or `""` if none. */
12
14
  readonly lastEventId: string;
13
15
  }
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 & {
15
- readonly _tag: "EventSourceError";
16
- } & Readonly<A>;
16
+ declare const EventSourceError_base: Schema.Class<EventSourceError, Schema.TaggedStruct<"EventSourceError", {
17
+ /** The URL the `EventSource` was opened with. */
18
+ readonly url: Schema.String;
19
+ /** What the `EventSource` constructor threw, when that is why the stream failed. */
20
+ readonly cause: Schema.optionalKey<Schema.Defect>;
21
+ }>, Cause.YieldableError>;
17
22
  /**
18
23
  * Raised when an `EventSource` cannot be opened (its constructor throws, e.g.
19
24
  * for an invalid URL; `cause` holds the thrown value) or its connection fails
20
25
  * fatally (its `readyState` is `CLOSED`; `cause` is absent).
21
26
  */
22
- declare class EventSourceError extends EventSourceError_base<{
23
- /** The URL the `EventSource` was opened with. */
24
- readonly url: string;
25
- /** What the `EventSource` constructor threw, when that is why the stream failed. */
26
- readonly cause?: unknown;
27
- }> {}
27
+ export declare class EventSourceError extends EventSourceError_base {}
28
28
  /** The subset of the `EventSource` constructor this module relies on. */
29
- type EventSourceConstructor = new (url: string, eventSourceInitDict?: {
29
+ export type EventSourceConstructor = new (url: string, eventSourceInitDict?: {
30
30
  withCredentials?: boolean;
31
31
  }) => EventSource;
32
32
  /** Options for {@link fromEventSource}. */
33
- interface FromEventSourceOptions {
33
+ export interface FromEventSourceOptions {
34
34
  /** Send credentials (cookies) with the request. Defaults to `false`. */
35
35
  readonly withCredentials?: boolean;
36
36
  /**
@@ -66,29 +66,27 @@ interface FromEventSourceOptions {
66
66
  * );
67
67
  * ```
68
68
  */
69
- declare const fromEventSource: (url: string, options?: FromEventSourceOptions) => Stream.Stream<SseMessage, EventSourceError>;
70
- 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 & {
71
- readonly _tag: "WebSocketError";
72
- } & Readonly<A>;
69
+ export declare const fromEventSource: (url: string, options?: FromEventSourceOptions) => Stream.Stream<SseMessage, EventSourceError>;
70
+ declare const WebSocketError_base: Schema.Class<WebSocketError, Schema.TaggedStruct<"WebSocketError", {
71
+ /** The URL the `WebSocket` was opened with. */
72
+ readonly url: Schema.String;
73
+ /** The close code, when an unclean close is why the stream failed. */
74
+ readonly code: Schema.optionalKey<Schema.Number>;
75
+ /** The close reason, when an unclean close is why the stream failed. */
76
+ readonly reason: Schema.optionalKey<Schema.String>;
77
+ /** What the `WebSocket` constructor threw, when that is why the stream failed. */
78
+ readonly cause: Schema.optionalKey<Schema.Defect>;
79
+ }>, Cause.YieldableError>;
73
80
  /**
74
81
  * Raised when a `WebSocket` cannot be opened (its constructor throws, e.g. for
75
82
  * an invalid URL or protocol list; `cause` holds the thrown value), errors, or
76
83
  * closes uncleanly (`code` and `reason` come from the close event).
77
84
  */
78
- declare class WebSocketError extends WebSocketError_base<{
79
- /** The URL the `WebSocket` was opened with. */
80
- readonly url: string;
81
- /** The close code, when an unclean close is why the stream failed. */
82
- readonly code?: number;
83
- /** The close reason, when an unclean close is why the stream failed. */
84
- readonly reason?: string;
85
- /** What the `WebSocket` constructor threw, when that is why the stream failed. */
86
- readonly cause?: unknown;
87
- }> {}
85
+ export declare class WebSocketError extends WebSocketError_base {}
88
86
  /** The subset of the `WebSocket` constructor this module relies on. */
89
- type WebSocketConstructor = new (url: string, protocols?: string | ReadonlyArray<string>) => WebSocket;
87
+ export type WebSocketConstructor = new (url: string, protocols?: string | ReadonlyArray<string>) => WebSocket;
90
88
  /** Options for {@link fromWebSocket}. */
91
- interface FromWebSocketOptions {
89
+ export interface FromWebSocketOptions {
92
90
  /** Sub-protocols passed to the `WebSocket` constructor. */
93
91
  readonly protocols?: string | ReadonlyArray<string>;
94
92
  /** `arraybuffer` or `blob` for binary frames. Defaults to the platform default. */
@@ -120,7 +118,7 @@ interface FromWebSocketOptions {
120
118
  * );
121
119
  * ```
122
120
  */
123
- declare const fromWebSocket: (url: string, options?: FromWebSocketOptions) => Stream.Stream<string | ArrayBuffer | Blob, WebSocketError>;
121
+ export declare const fromWebSocket: (url: string, options?: FromWebSocketOptions) => Stream.Stream<string | ArrayBuffer | Blob, WebSocketError>;
124
122
  //#endregion
125
- export { EventSourceConstructor, EventSourceError, FromEventSourceOptions, FromWebSocketOptions, SseMessage, WebSocketConstructor, WebSocketError, fromEventSource, fromWebSocket, realtime_d_exports };
123
+ export { realtime_d_exports };
126
124
  //# sourceMappingURL=realtime.d.ts.map
package/dist/realtime.js CHANGED
@@ -1,5 +1,10 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
- import { Cause, Data, Effect, Queue, Stream } from "effect";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Arr from "effect/Array";
4
+ import * as Cause from "effect/Cause";
5
+ import * as Stream from "effect/Stream";
6
+ import * as Schema from "effect/Schema";
7
+ import * as Queue from "effect/Queue";
3
8
  //#region src/realtime.ts
4
9
  /**
5
10
  * Client-side realtime bridges: consume a Server-Sent-Events endpoint or a
@@ -22,7 +27,12 @@ var realtime_exports = /* @__PURE__ */ __exportAll({
22
27
  * for an invalid URL; `cause` holds the thrown value) or its connection fails
23
28
  * fatally (its `readyState` is `CLOSED`; `cause` is absent).
24
29
  */
25
- var EventSourceError = class extends Data.TaggedError("EventSourceError") {};
30
+ var EventSourceError = class extends Schema.TaggedError()("EventSourceError", {
31
+ /** The URL the `EventSource` was opened with. */
32
+ url: Schema.String,
33
+ /** What the `EventSource` constructor threw, when that is why the stream failed. */
34
+ cause: Schema.optionalKey(Schema.Defect())
35
+ }) {};
26
36
  /**
27
37
  * Consume a Server-Sent-Events endpoint as a `Stream` of {@link SseMessage}.
28
38
  *
@@ -56,7 +66,7 @@ const fromEventSource = (url, options) => {
56
66
  });
57
67
  };
58
68
  source.addEventListener("message", onMessage);
59
- for (const name of options?.events ?? []) source.addEventListener(name, onMessage);
69
+ Arr.forEach(options?.events ?? [], (name) => source.addEventListener(name, onMessage));
60
70
  source.addEventListener("error", () => {
61
71
  if (source.readyState === 2) Queue.failCauseUnsafe(queue, Cause.fail(new EventSourceError({ url })));
62
72
  });
@@ -76,7 +86,16 @@ const fromEventSource = (url, options) => {
76
86
  * an invalid URL or protocol list; `cause` holds the thrown value), errors, or
77
87
  * closes uncleanly (`code` and `reason` come from the close event).
78
88
  */
79
- var WebSocketError = class extends Data.TaggedError("WebSocketError") {};
89
+ var WebSocketError = class extends Schema.TaggedError()("WebSocketError", {
90
+ /** The URL the `WebSocket` was opened with. */
91
+ url: Schema.String,
92
+ /** The close code, when an unclean close is why the stream failed. */
93
+ code: Schema.optionalKey(Schema.Number),
94
+ /** The close reason, when an unclean close is why the stream failed. */
95
+ reason: Schema.optionalKey(Schema.String),
96
+ /** What the `WebSocket` constructor threw, when that is why the stream failed. */
97
+ cause: Schema.optionalKey(Schema.Defect())
98
+ }) {};
80
99
  /**
81
100
  * Consume a `WebSocket` as a `Stream` of its message payloads
82
101
  * (`string | ArrayBuffer | Blob`, depending on `binaryType`).
@@ -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/**\n * Raised when an `EventSource` cannot be opened (its constructor throws, e.g.\n * for an invalid URL; `cause` holds the thrown value) or its connection fails\n * fatally (its `readyState` is `CLOSED`; `cause` is absent).\n */\nexport class EventSourceError extends Data.TaggedError(\"EventSourceError\")<{\n /** The URL the `EventSource` was opened with. */\n readonly url: string;\n /** What the `EventSource` constructor threw, when that is why the stream failed. */\n readonly cause?: unknown;\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\n/** Options for {@link fromEventSource}. */\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} when the connection closes fatally, or, with the\n * thrown value as its `cause`, when the `EventSource` constructor throws (e.g.\n * a `SyntaxError` for an invalid URL). The source is closed when the stream's\n * scope closes; one that failed to construct has nothing to close.\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 // Effect v4's `Stream.callback` runs the returned Effect as the stream's\n // setup, inside the stream's scope; it is not a cleanup. Open the source\n // with `acquireRelease` so it is closed when that scope closes.\n return Stream.callback<SseMessage, EventSourceError>(\n (queue) =>\n Effect.acquireRelease(\n // Construct and attach the listeners in one synchronous step, so no\n // event can be dispatched in between; a throw from either (in practice\n // the constructor) becomes the typed error. A failed acquire registers\n // no release: a source that failed to construct has nothing to close.\n Effect.try({\n try: () => {\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 source;\n },\n catch: (cause) => new EventSourceError({ url, cause }),\n }),\n (source) => Effect.sync(() => source.close()),\n ),\n { bufferSize: options?.bufferSize ?? 16, strategy: options?.strategy ?? \"sliding\" },\n );\n};\n\n// ---------------------------------------------------------------------------\n// WebSocket\n// ---------------------------------------------------------------------------\n\n/**\n * Raised when a `WebSocket` cannot be opened (its constructor throws, e.g. for\n * an invalid URL or protocol list; `cause` holds the thrown value), errors, or\n * closes uncleanly (`code` and `reason` come from the close event).\n */\nexport class WebSocketError extends Data.TaggedError(\"WebSocketError\")<{\n /** The URL the `WebSocket` was opened with. */\n readonly url: string;\n /** The close code, when an unclean close is why the stream failed. */\n readonly code?: number;\n /** The close reason, when an unclean close is why the stream failed. */\n readonly reason?: string;\n /** What the `WebSocket` constructor threw, when that is why the stream failed. */\n readonly cause?: unknown;\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\n/** Options for {@link fromWebSocket}. */\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. It fails with\n * {@link WebSocketError} on an error or unclean close, or, with the thrown\n * value as its `cause`, when the `WebSocket` constructor throws (e.g. a\n * `SyntaxError` for an invalid URL or protocol list). The socket is closed when\n * the stream's scope closes; one that failed to construct has nothing to close.\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.acquireRelease(\n // See `fromEventSource`: construct and attach the listeners in one\n // synchronous step, mapping a throw to the typed error; a failed\n // acquire registers no release.\n Effect.try({\n try: () => {\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 socket;\n },\n catch: (cause) => new WebSocketError({ url, cause }),\n }),\n (socket) =>\n 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":";;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAa,mBAAb,cAAsC,KAAK,YAAY,kBAAkB,CAAC,CAKvE,CAAC;;;;;;;;;;;;;;;;;;;;;AA8CJ,MAAa,mBACX,KACA,YACgD;CAChD,MAAM,OAAO,SAAS,kBAAmB,WAAW;CAIpD,OAAO,OAAO,UACX,UACC,OAAO,eAKL,OAAO,IAAI;EACT,WAAW;GACT,MAAM,SACJ,SAAS,oBAAoB,KAAA,IACzB,IAAI,KAAK,GAAG,IACZ,IAAI,KAAK,KAAK,EAAE,iBAAiB,QAAQ,gBAAgB,CAAC;GAEhE,MAAM,aAAa,MAA0B;IAC3C,MAAM,YAAY,OAAO;KAAE,OAAO,EAAE;KAAM,MAAM,EAAE;KAAM,aAAa,EAAE;IAAY,CAAC;GACtF;GAEA,OAAO,iBAAiB,WAAW,SAAS;GAC5C,KAAK,MAAM,QAAQ,SAAS,UAAU,CAAC,GAAG,OAAO,iBAAiB,MAAM,SAAS;GAEjF,OAAO,iBAAiB,eAAe;IAErC,IAAI,OAAO,eAAe,GACxB,MAAM,gBAAgB,OAAO,MAAM,KAAK,IAAI,iBAAiB,EAAE,IAAI,CAAC,CAAC,CAAC;GAE1E,CAAC;GAED,OAAO;EACT;EACA,QAAQ,UAAU,IAAI,iBAAiB;GAAE;GAAK;EAAM,CAAC;CACvD,CAAC,IACA,WAAW,OAAO,WAAW,OAAO,MAAM,CAAC,CAC9C,GACF;EAAE,YAAY,SAAS,cAAc;EAAI,UAAU,SAAS,YAAY;CAAU,CACpF;AACF;;;;;;AAWA,IAAa,iBAAb,cAAoC,KAAK,YAAY,gBAAgB,CAAC,CASnE,CAAC;;;;;;;;;;;;;;;;;;;;;AA0CJ,MAAa,iBACX,KACA,YAC+D;CAC/D,MAAM,OAAO,SAAS,kBAAmB,WAAW;CACpD,OAAO,OAAO,UACX,UACC,OAAO,eAIL,OAAO,IAAI;EACT,WAAW;GACT,MAAM,SAAS,IAAI,KAAK,KAAK,SAAS,SAAS;GAC/C,IAAI,SAAS,eAAe,KAAA,GAAW,OAAO,aAAa,QAAQ;GAEnE,OAAO,iBAAiB,YAAY,MAAoB;IACtD,MAAM,YAAY,OAAO,EAAE,IAAI;GACjC,CAAC;GAED,OAAO,iBAAiB,eAAe;IACrC,MAAM,gBAAgB,OAAO,MAAM,KAAK,IAAI,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC;GACtE,CAAC;GAED,OAAO,iBAAiB,UAAU,MAAkB;IAClD,IAAI,EAAE,UACJ,MAAM,UAAU,KAAK;SAErB,MAAM,gBACJ,OACA,MAAM,KAAK,IAAI,eAAe;KAAE;KAAK,MAAM,EAAE;KAAM,QAAQ,EAAE;IAAO,CAAC,CAAC,CACxE;GAEJ,CAAC;GAED,OAAO;EACT;EACA,QAAQ,UAAU,IAAI,eAAe;GAAE;GAAK;EAAM,CAAC;CACrD,CAAC,IACA,WACC,OAAO,WAAW;EAEhB,IAAI,OAAO,eAAe,KAAK,OAAO,eAAe,GAAG,OAAO,MAAM;CACvE,CAAC,CACL,GACF;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 * as Arr from \"effect/Array\";\nimport * as Cause from \"effect/Cause\";\nimport * as Schema from \"effect/Schema\";\nimport * as Effect from \"effect/Effect\";\nimport * as Queue from \"effect/Queue\";\nimport * as Stream from \"effect/Stream\";\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/**\n * Raised when an `EventSource` cannot be opened (its constructor throws, e.g.\n * for an invalid URL; `cause` holds the thrown value) or its connection fails\n * fatally (its `readyState` is `CLOSED`; `cause` is absent).\n */\nexport class EventSourceError extends Schema.TaggedError<EventSourceError>()(\"EventSourceError\", {\n /** The URL the `EventSource` was opened with. */\n url: Schema.String,\n /** What the `EventSource` constructor threw, when that is why the stream failed. */\n cause: Schema.optionalKey(Schema.Defect()),\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\n/** Options for {@link fromEventSource}. */\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} when the connection closes fatally, or, with the\n * thrown value as its `cause`, when the `EventSource` constructor throws (e.g.\n * a `SyntaxError` for an invalid URL). The source is closed when the stream's\n * scope closes; one that failed to construct has nothing to close.\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: EventSourceConstructor = options?.implementation ?? globalThis.EventSource;\n // Effect v4's `Stream.callback` runs the returned Effect as the stream's\n // setup, inside the stream's scope; it is not a cleanup. Open the source\n // with `acquireRelease` so it is closed when that scope closes.\n return Stream.callback<SseMessage, EventSourceError>(\n (queue) =>\n Effect.acquireRelease(\n // Construct and attach the listeners in one synchronous step, so no\n // event can be dispatched in between; a throw from either (in practice\n // the constructor) becomes the typed error. A failed acquire registers\n // no release: a source that failed to construct has nothing to close.\n Effect.try({\n try: () => {\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 Arr.forEach(options?.events ?? [], (name) => 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 source;\n },\n catch: (cause) => new EventSourceError({ url, cause }),\n }),\n (source) => Effect.sync(() => source.close()),\n ),\n { bufferSize: options?.bufferSize ?? 16, strategy: options?.strategy ?? \"sliding\" },\n );\n};\n\n// ---------------------------------------------------------------------------\n// WebSocket\n// ---------------------------------------------------------------------------\n\n/**\n * Raised when a `WebSocket` cannot be opened (its constructor throws, e.g. for\n * an invalid URL or protocol list; `cause` holds the thrown value), errors, or\n * closes uncleanly (`code` and `reason` come from the close event).\n */\nexport class WebSocketError extends Schema.TaggedError<WebSocketError>()(\"WebSocketError\", {\n /** The URL the `WebSocket` was opened with. */\n url: Schema.String,\n /** The close code, when an unclean close is why the stream failed. */\n code: Schema.optionalKey(Schema.Number),\n /** The close reason, when an unclean close is why the stream failed. */\n reason: Schema.optionalKey(Schema.String),\n /** What the `WebSocket` constructor threw, when that is why the stream failed. */\n cause: Schema.optionalKey(Schema.Defect()),\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\n/** Options for {@link fromWebSocket}. */\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. It fails with\n * {@link WebSocketError} on an error or unclean close, or, with the thrown\n * value as its `cause`, when the `WebSocket` constructor throws (e.g. a\n * `SyntaxError` for an invalid URL or protocol list). The socket is closed when\n * the stream's scope closes; one that failed to construct has nothing to close.\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 // SAFETY: the platform `WebSocket` constructor only reads `protocols`; it is\n // typed as a mutable `string[]`, but a `ReadonlyArray` is equally valid input.\n const Impl = options?.implementation ?? (globalThis.WebSocket as WebSocketConstructor);\n return Stream.callback<string | ArrayBuffer | Blob, WebSocketError>(\n (queue) =>\n Effect.acquireRelease(\n // See `fromEventSource`: construct and attach the listeners in one\n // synchronous step, mapping a throw to the typed error; a failed\n // acquire registers no release.\n Effect.try({\n try: () => {\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 socket;\n },\n catch: (cause) => new WebSocketError({ url, cause }),\n }),\n (socket) =>\n 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,IAAa,mBAAb,cAAsC,OAAO,YAA8B,CAAC,CAAC,oBAAoB;;CAE/F,KAAK,OAAO;;CAEZ,OAAO,OAAO,YAAY,OAAO,OAAO,CAAC;AAC3C,CAAC,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;AA8CJ,MAAa,mBACX,KACA,YACgD;CAChD,MAAM,OAA+B,SAAS,kBAAkB,WAAW;CAI3E,OAAO,OAAO,UACX,UACC,OAAO,eAKL,OAAO,IAAI;EACT,WAAW;GACT,MAAM,SACJ,SAAS,oBAAoB,KAAA,IACzB,IAAI,KAAK,GAAG,IACZ,IAAI,KAAK,KAAK,EAAE,iBAAiB,QAAQ,gBAAgB,CAAC;GAEhE,MAAM,aAAa,MAA0B;IAC3C,MAAM,YAAY,OAAO;KAAE,OAAO,EAAE;KAAM,MAAM,EAAE;KAAM,aAAa,EAAE;IAAY,CAAC;GACtF;GAEA,OAAO,iBAAiB,WAAW,SAAS;GAC5C,IAAI,QAAQ,SAAS,UAAU,CAAC,IAAI,SAAS,OAAO,iBAAiB,MAAM,SAAS,CAAC;GAErF,OAAO,iBAAiB,eAAe;IAErC,IAAI,OAAO,eAAe,GACxB,MAAM,gBAAgB,OAAO,MAAM,KAAK,IAAI,iBAAiB,EAAE,IAAI,CAAC,CAAC,CAAC;GAE1E,CAAC;GAED,OAAO;EACT;EACA,QAAQ,UAAU,IAAI,iBAAiB;GAAE;GAAK;EAAM,CAAC;CACvD,CAAC,IACA,WAAW,OAAO,WAAW,OAAO,MAAM,CAAC,CAC9C,GACF;EAAE,YAAY,SAAS,cAAc;EAAI,UAAU,SAAS,YAAY;CAAU,CACpF;AACF;;;;;;AAWA,IAAa,iBAAb,cAAoC,OAAO,YAA4B,CAAC,CAAC,kBAAkB;;CAEzF,KAAK,OAAO;;CAEZ,MAAM,OAAO,YAAY,OAAO,MAAM;;CAEtC,QAAQ,OAAO,YAAY,OAAO,MAAM;;CAExC,OAAO,OAAO,YAAY,OAAO,OAAO,CAAC;AAC3C,CAAC,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;AA0CJ,MAAa,iBACX,KACA,YAC+D;CAG/D,MAAM,OAAO,SAAS,kBAAmB,WAAW;CACpD,OAAO,OAAO,UACX,UACC,OAAO,eAIL,OAAO,IAAI;EACT,WAAW;GACT,MAAM,SAAS,IAAI,KAAK,KAAK,SAAS,SAAS;GAC/C,IAAI,SAAS,eAAe,KAAA,GAAW,OAAO,aAAa,QAAQ;GAEnE,OAAO,iBAAiB,YAAY,MAAoB;IACtD,MAAM,YAAY,OAAO,EAAE,IAAI;GACjC,CAAC;GAED,OAAO,iBAAiB,eAAe;IACrC,MAAM,gBAAgB,OAAO,MAAM,KAAK,IAAI,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC;GACtE,CAAC;GAED,OAAO,iBAAiB,UAAU,MAAkB;IAClD,IAAI,EAAE,UACJ,MAAM,UAAU,KAAK;SAErB,MAAM,gBACJ,OACA,MAAM,KAAK,IAAI,eAAe;KAAE;KAAK,MAAM,EAAE;KAAM,QAAQ,EAAE;IAAO,CAAC,CAAC,CACxE;GAEJ,CAAC;GAED,OAAO;EACT;EACA,QAAQ,UAAU,IAAI,eAAe;GAAE;GAAK;EAAM,CAAC;CACrD,CAAC,IACA,WACC,OAAO,WAAW;EAEhB,IAAI,OAAO,eAAe,KAAK,OAAO,eAAe,GAAG,OAAO,MAAM;CACvE,CAAC,CACL,GACF;EAAE,YAAY,SAAS,cAAc;EAAI,UAAU,SAAS,YAAY;CAAU,CACpF;AACF"}
@@ -1,47 +1,63 @@
1
1
  import { SvelteKitRequestEvent } from "./runtime.js";
2
2
  import { ErrorTranslator, RequestRuntimeProvider } from "./request-runtime.js";
3
3
  import { FormErrorMapper } from "./internal/remote-run.js";
4
- import { Effect, Schema } from "effect";
4
+ import * as Effect from "effect/Effect";
5
5
  import * as HttpClient from "effect/http/HttpClient";
6
- import { RemoteCommand, RemoteForm, RemoteFormInput, RemoteFormInvalidField, RemotePrerenderFunction, RemoteQueryFunction } from "$app/server";
6
+ import * as Schema from "effect/Schema";
7
+ import { RemoteCommand, RemoteForm, RemoteFormInput, RemoteFormInvalidField, RemoteLiveQueryFunction, RemotePrerenderFunction, RemoteQueryFunction } from "$app/server";
7
8
  import { StandardSchemaV1 } from "@standard-schema/spec";
8
9
  //#region src/remote-functions.d.ts
9
10
  type SvelteKitEffectEnv = HttpClient.HttpClient | SvelteKitRequestEvent;
11
+ declare const RemoteFunctionUsageError_base: Schema.Class<RemoteFunctionUsageError, Schema.TaggedStruct<"RemoteFunctionUsageError", {
12
+ readonly message: Schema.String;
13
+ }>, import("effect/Cause").YieldableError>;
14
+ /**
15
+ * Thrown synchronously, when a remote function is DEFINED, by a
16
+ * `RemoteFunction` factory called with arguments no overload accepts (a
17
+ * schema with no handler), or that needs an API the installed SvelteKit lacks.
18
+ * It is a programming error in the `*.remote.ts` module, never a request
19
+ * failure.
20
+ */
21
+ export declare class RemoteFunctionUsageError extends RemoteFunctionUsageError_base {}
10
22
  /** The public shape of the `query` helper, parameterised by its handler env. */
11
- interface QueryFn<Env> {
23
+ export interface QueryFn<Env> {
12
24
  <Output>(fn: () => Effect.Effect<Output, unknown, Env>): RemoteQueryFunction<void, Output>;
13
25
  <Input, Output>(validate: "unchecked", fn: (arg: Input) => Effect.Effect<Output, unknown, Env>): RemoteQueryFunction<Input, Output>;
14
26
  <Sch extends StandardSchemaV1, Output>(schema: Sch, fn: (arg: StandardSchemaV1.InferOutput<Sch>) => Effect.Effect<Output, unknown, Env>): RemoteQueryFunction<StandardSchemaV1.InferInput<Sch>, Output>;
15
27
  <S extends Schema.Top, Output>(schema: S, fn: (arg: S["Type"]) => Effect.Effect<Output, unknown, Env>): RemoteQueryFunction<S["Encoded"], Output>;
16
28
  }
17
29
  /** The public shape of `query.batch`, parameterised by its handler env. */
18
- interface QueryBatchFn<Env> {
30
+ export interface QueryBatchFn<Env> {
19
31
  <Input, Output>(validate: "unchecked", fn: (args: Input[]) => Effect.Effect<(arg: Input, idx: number) => Output, unknown, Env>): RemoteQueryFunction<Input, Output>;
20
32
  <Sch extends StandardSchemaV1, Output>(schema: Sch, fn: (args: StandardSchemaV1.InferOutput<Sch>[]) => Effect.Effect<(arg: StandardSchemaV1.InferOutput<Sch>, idx: number) => Output, unknown, Env>): RemoteQueryFunction<StandardSchemaV1.InferInput<Sch>, Output>;
21
33
  <S extends Schema.Top, Output>(schema: S, fn: (args: S["Type"][]) => Effect.Effect<(arg: S["Type"], idx: number) => Output, unknown, Env>): RemoteQueryFunction<S["Encoded"], Output>;
22
34
  }
23
- /** The public shape of `query.live`, parameterised by its handler env. */
24
- interface QueryLiveFn<Env> {
25
- <Input, Output>(validate: "unchecked", fn: (arg: Input) => Effect.Effect<AsyncIterable<Output>, unknown, Env>): RemoteQueryFunction<Input, Output>;
26
- <Sch extends StandardSchemaV1, Output>(schema: Sch, fn: (arg: StandardSchemaV1.InferOutput<Sch>) => Effect.Effect<AsyncIterable<Output>, unknown, Env>): RemoteQueryFunction<StandardSchemaV1.InferInput<Sch>, Output>;
27
- <S extends Schema.Top, Output>(schema: S, fn: (arg: S["Type"]) => Effect.Effect<AsyncIterable<Output>, unknown, Env>): RemoteQueryFunction<S["Encoded"], Output>;
35
+ /**
36
+ * The public shape of `query.live`, parameterised by its handler env: kit 3's
37
+ * `query.live` overloads with an Effect handler that produces the
38
+ * `AsyncIterable` of values.
39
+ */
40
+ export interface QueryLiveFn<Env> {
41
+ <Input, Output>(validate: "unchecked", fn: (arg: Input) => Effect.Effect<AsyncIterable<Output>, unknown, Env>): RemoteLiveQueryFunction<Input, Output>;
42
+ <Sch extends StandardSchemaV1, Output>(schema: Sch, fn: (arg: StandardSchemaV1.InferOutput<Sch>) => Effect.Effect<AsyncIterable<Output>, unknown, Env>): RemoteLiveQueryFunction<StandardSchemaV1.InferInput<Sch>, Output, StandardSchemaV1.InferOutput<Sch>>;
43
+ <S extends Schema.Top, Output>(schema: S, fn: (arg: S["Type"]) => Effect.Effect<AsyncIterable<Output>, unknown, Env>): RemoteLiveQueryFunction<S["Encoded"], Output, S["Type"]>;
28
44
  }
29
45
  /** The public shape of the `form` helper, parameterised by its handler env. */
30
- interface FormFn<Env> {
46
+ export interface FormFn<Env> {
31
47
  <Output>(fn: () => Effect.Effect<Output, unknown, Env>): RemoteForm<void, Output>;
32
48
  <Input, Output>(validate: "unchecked", fn: (data: Input, issue: RemoteFormInvalidField<Input & RemoteFormInput>) => Effect.Effect<Output, unknown, Env>): RemoteForm<Input & RemoteFormInput, Output>;
33
49
  <Sch extends StandardSchemaV1, Output>(validate: Sch, fn: (data: StandardSchemaV1.InferOutput<Sch>, issue: RemoteFormInvalidField<StandardSchemaV1.InferInput<Sch> & RemoteFormInput>) => Effect.Effect<Output, unknown, Env>): RemoteForm<StandardSchemaV1.InferInput<Sch> & RemoteFormInput, Output>;
34
50
  <S extends Schema.Top, Output>(validate: S, fn: (data: S["Type"], issue: RemoteFormInvalidField<S["Encoded"] & RemoteFormInput>) => Effect.Effect<Output, unknown, Env>): RemoteForm<S["Encoded"] & RemoteFormInput, Output>;
35
51
  }
36
52
  /** The public shape of the `command` helper, parameterised by its handler env. */
37
- interface CommandFn<Env> {
53
+ export interface CommandFn<Env> {
38
54
  <Output>(fn: () => Effect.Effect<Output, unknown, Env>): RemoteCommand<void, Output>;
39
55
  <Input, Output>(validate: "unchecked", fn: (arg: Input) => Effect.Effect<Output, unknown, Env>): RemoteCommand<Input, Output>;
40
56
  <Sch extends StandardSchemaV1, Output>(validate: Sch, fn: (arg: StandardSchemaV1.InferOutput<Sch>) => Effect.Effect<Output, unknown, Env>): RemoteCommand<StandardSchemaV1.InferInput<Sch>, Output>;
41
57
  <S extends Schema.Top, Output>(validate: S, fn: (arg: S["Type"]) => Effect.Effect<Output, unknown, Env>): RemoteCommand<S["Encoded"], Output>;
42
58
  }
43
59
  /** The public shape of the `prerender` helper, parameterised by its handler env. */
44
- interface PrerenderFn<Env> {
60
+ export interface PrerenderFn<Env> {
45
61
  <Output>(fn: () => Effect.Effect<Output, unknown, Env>, options?: {
46
62
  inputs?: () => Promise<void[]> | void[];
47
63
  dynamic?: boolean;
@@ -63,14 +79,14 @@ interface PrerenderFn<Env> {
63
79
  * SvelteKit's `requested` from `$app/server`, passed through. Throws when the
64
80
  * installed SvelteKit version does not provide it.
65
81
  */
66
- declare function requested<Result = unknown>(...args: unknown[]): Result;
82
+ export declare function requested<Result = unknown>(...args: unknown[]): Result;
67
83
  /** A `query` with its `batch` / `live` helpers attached. */
68
- type QueryNamespace<Env> = QueryFn<Env> & {
84
+ export type QueryNamespace<Env> = QueryFn<Env> & {
69
85
  batch: QueryBatchFn<Env>;
70
86
  live: QueryLiveFn<Env>;
71
87
  };
72
88
  /** The set of remote-function helpers bound to a particular runner. */
73
- interface RemoteFunctions<Env> {
89
+ export interface RemoteFunctions<Env> {
74
90
  readonly query: QueryNamespace<Env>;
75
91
  readonly form: FormFn<Env>;
76
92
  readonly command: CommandFn<Env>;
@@ -111,7 +127,7 @@ interface RemoteFunctions<Env> {
111
127
  * );
112
128
  * ```
113
129
  */
114
- declare function withRuntime<R>(provider: RequestRuntimeProvider<R, any>, opts?: {
130
+ export declare function withRuntime<R>(provider: RequestRuntimeProvider<R, any>, opts?: {
115
131
  translateError?: ErrorTranslator;
116
132
  formError?: FormErrorMapper;
117
133
  }): RemoteFunctions<R>;
@@ -120,7 +136,7 @@ declare function withRuntime<R>(provider: RequestRuntimeProvider<R, any>, opts?:
120
136
  * `requested`) bound to the default per-request runtime; `withRuntime` binds
121
137
  * them to your own services.
122
138
  */
123
- declare const RemoteFunction: {
139
+ export declare const RemoteFunction: {
124
140
  query: QueryNamespace<SvelteKitEffectEnv>;
125
141
  form: FormFn<SvelteKitEffectEnv>;
126
142
  command: CommandFn<SvelteKitEffectEnv>;
@@ -129,5 +145,5 @@ declare const RemoteFunction: {
129
145
  withRuntime: typeof withRuntime;
130
146
  };
131
147
  //#endregion
132
- export { CommandFn, FormFn, PrerenderFn, QueryBatchFn, QueryFn, QueryLiveFn, QueryNamespace, RemoteFunction, RemoteFunctions, requested, withRuntime };
148
+ export {};
133
149
  //# sourceMappingURL=remote-functions.d.ts.map