@thomasfosterau/effect-sveltekit 0.6.0 → 0.7.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.
- package/README.md +16 -13
- package/dist/Hooks.d.ts +3 -3
- package/dist/Hooks.js +1 -1
- package/dist/Hooks.js.map +1 -1
- package/dist/Navigation.d.ts +11 -11
- package/dist/Navigation.js +15 -2
- package/dist/Navigation.js.map +1 -1
- package/dist/Remote.d.ts +18 -17
- package/dist/Remote.js +2 -4
- package/dist/Remote.js.map +1 -1
- package/dist/State.d.ts +10 -6
- package/dist/State.js +2 -1
- package/dist/State.js.map +1 -1
- package/dist/adapter/assets.d.ts +24 -7
- package/dist/adapter/assets.js +58 -37
- package/dist/adapter/assets.js.map +1 -1
- package/dist/adapter/handler.d.ts +27 -12
- package/dist/adapter/handler.js +53 -26
- package/dist/adapter/handler.js.map +1 -1
- package/dist/adapter/index.d.ts +3 -3
- package/dist/adapter/index.js +1 -1
- package/dist/adapter/index.js.map +1 -1
- package/dist/adapter/serve.d.ts +6 -5
- package/dist/adapter/serve.js +3 -1
- package/dist/adapter/serve.js.map +1 -1
- package/dist/api-client.d.ts +3 -4
- package/dist/api-client.js +2 -1
- package/dist/api-client.js.map +1 -1
- package/dist/app-runtime.d.ts +12 -9
- package/dist/app-runtime.js +23 -14
- package/dist/app-runtime.js.map +1 -1
- package/dist/client/Hooks.d.ts +4 -4
- package/dist/client/Hooks.js +2 -1
- package/dist/client/Hooks.js.map +1 -1
- package/dist/client.d.ts +2 -2
- package/dist/config.d.ts +7 -5
- package/dist/config.js +5 -34
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +14 -16
- package/dist/errors.js +20 -12
- package/dist/errors.js.map +1 -1
- package/dist/forms.d.ts +9 -10
- package/dist/forms.js +5 -2
- package/dist/forms.js.map +1 -1
- package/dist/internal/app-state.d.ts +16 -14
- package/dist/internal/app-state.js +9 -3
- package/dist/internal/app-state.js.map +1 -1
- package/dist/internal/auto.d.ts +23 -14
- package/dist/internal/auto.js +50 -40
- package/dist/internal/auto.js.map +1 -1
- package/dist/internal/enhance.d.ts +20 -18
- package/dist/internal/enhance.js +3 -1
- package/dist/internal/enhance.js.map +1 -1
- package/dist/internal/error.d.ts +13 -0
- package/dist/internal/error.js +4 -3
- package/dist/internal/error.js.map +1 -1
- package/dist/internal/navigation-events.js +3 -1
- package/dist/internal/navigation-events.js.map +1 -1
- package/dist/internal/remote-run.d.ts +6 -6
- package/dist/internal/remote-run.js +13 -16
- package/dist/internal/remote-run.js.map +1 -1
- package/dist/internal/remote-validators.js +4 -3
- package/dist/internal/remote-validators.js.map +1 -1
- package/dist/internal/route-params.d.ts +1 -2
- package/dist/internal/sse.js +2 -1
- package/dist/internal/sse.js.map +1 -1
- package/dist/kit.d.ts +12 -11
- package/dist/kit.js +6 -2
- package/dist/kit.js.map +1 -1
- package/dist/realtime.d.ts +29 -31
- package/dist/realtime.js +23 -4
- package/dist/realtime.js.map +1 -1
- package/dist/remote-functions.d.ts +34 -18
- package/dist/remote-functions.js +78 -46
- package/dist/remote-functions.js.map +1 -1
- package/dist/remote-reactive.d.ts +8 -4
- package/dist/remote-reactive.js.map +1 -1
- package/dist/request-parse.d.ts +13 -13
- package/dist/request-parse.js +29 -15
- package/dist/request-parse.js.map +1 -1
- package/dist/request-runtime.d.ts +16 -11
- package/dist/request-runtime.js +28 -29
- package/dist/request-runtime.js.map +1 -1
- package/dist/request-services.d.ts +10 -8
- package/dist/request-services.js +3 -1
- package/dist/request-services.js.map +1 -1
- package/dist/response-headers.d.ts +2 -3
- package/dist/response-headers.js +2 -1
- package/dist/response-headers.js.map +1 -1
- package/dist/runtime.d.ts +8 -5
- package/dist/runtime.js +4 -1
- package/dist/runtime.js.map +1 -1
- package/dist/server/Endpoint.d.ts +17 -11
- package/dist/server/Endpoint.js +18 -4
- package/dist/server/Endpoint.js.map +1 -1
- package/dist/server/Hooks.d.ts +6 -6
- package/dist/server/Hooks.js +1 -1
- package/dist/server/Hooks.js.map +1 -1
- package/dist/server.d.ts +8 -7
- package/dist/server.js +8 -8
- package/dist/server.js.map +1 -1
- package/dist/streamed-load.d.ts +2 -3
- package/dist/streamed-load.js +1 -1
- package/dist/streamed-load.js.map +1 -1
- package/dist/testing.d.ts +15 -14
- package/dist/testing.js +27 -7
- package/dist/testing.js.map +1 -1
- package/dist/transport.d.ts +6 -7
- package/dist/transport.js +3 -6
- package/dist/transport.js.map +1 -1
- package/dist/universal.d.ts +3 -3
- package/dist/universal.js +1 -1
- package/dist/universal.js.map +1 -1
- package/dist/vite.d.ts +4 -4
- package/dist/vite.js +102 -103
- package/dist/vite.js.map +1 -1
- package/package.json +12 -9
package/dist/errors.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { throwKitError } from "./internal/error.js";
|
|
3
3
|
import { SvelteKit } from "./kit.js";
|
|
4
|
-
import
|
|
4
|
+
import * as Predicate from "effect/Predicate";
|
|
5
5
|
import { redirect } from "@sveltejs/kit";
|
|
6
|
+
import * as Cause from "effect/Cause";
|
|
6
7
|
//#region src/errors.ts
|
|
7
8
|
/**
|
|
8
9
|
* A `translateError` built from a **tagged-error catalogue** instead of a
|
|
@@ -65,19 +66,24 @@ const rethrowSquashed = (cause) => {
|
|
|
65
66
|
throw Cause.squash(cause);
|
|
66
67
|
};
|
|
67
68
|
const isTagged = (value) => Predicate.hasProperty(value, "_tag") && Predicate.isString(value._tag);
|
|
68
|
-
const isErrorStatus = (status) =>
|
|
69
|
-
const isRedirectStatus = (status) =>
|
|
69
|
+
const isErrorStatus = (status) => status !== void 0 && Number.isInteger(status) && status >= 400 && status <= 599;
|
|
70
|
+
const isRedirectStatus = (status) => status !== void 0 && Number.isInteger(status) && status >= 300 && status <= 308;
|
|
70
71
|
/** The error's own non-empty `message` field, else its `_tag`. */
|
|
71
|
-
const defaultBody = (error) => Object.hasOwn(error, "message") && Predicate.isString(error.message) && error.message !== "" ? error.message : error._tag;
|
|
72
|
+
const defaultBody = (error) => Object.hasOwn(error, "message") && Predicate.hasProperty(error, "message") && Predicate.isString(error.message) && error.message !== "" ? error.message : error._tag;
|
|
72
73
|
const throwError = (status, body) => throwKitError(status, body);
|
|
74
|
+
/** The error's numeric `status` field, if it has one. */
|
|
75
|
+
const statusField = (error) => Predicate.hasProperty(error, "status") && Predicate.isNumber(error.status) ? error.status : void 0;
|
|
76
|
+
/** The error's redirect target: its `to` field, else its `location`, if a string or `URL`. */
|
|
77
|
+
const locationField = (error) => {
|
|
78
|
+
const location = (Predicate.hasProperty(error, "to") ? error.to : void 0) ?? (Predicate.hasProperty(error, "location") ? error.location : void 0);
|
|
79
|
+
return Predicate.isString(location) || location instanceof URL ? location : void 0;
|
|
80
|
+
};
|
|
73
81
|
const apply = (entry, error) => {
|
|
74
82
|
if (Predicate.isNumber(entry)) return throwError(entry, defaultBody(error));
|
|
75
83
|
if (Predicate.isFunction(entry)) return entry(error);
|
|
76
|
-
|
|
77
|
-
if (entry === "
|
|
78
|
-
|
|
79
|
-
return redirect(isRedirectStatus(error.status) ? error.status : 303, Predicate.isString(location) || location instanceof URL ? location : "/");
|
|
80
|
-
}
|
|
84
|
+
const status = statusField(error);
|
|
85
|
+
if (entry === "status") return throwError(isErrorStatus(status) ? status : 500, defaultBody(error));
|
|
86
|
+
if (entry === "redirect") return redirect(isRedirectStatus(status) ? status : 303, locationField(error) ?? "/");
|
|
81
87
|
return throwError(entry.status, entry.message === void 0 ? defaultBody(error) : entry.message(error));
|
|
82
88
|
};
|
|
83
89
|
/**
|
|
@@ -90,15 +96,17 @@ const apply = (entry, error) => {
|
|
|
90
96
|
* {@link SvelteKit.translate}).
|
|
91
97
|
*
|
|
92
98
|
* Pass the application's error union as the type argument to have the keys and
|
|
93
|
-
* each entry's callbacks checked against it
|
|
94
|
-
*
|
|
99
|
+
* each entry's callbacks checked against it (a callback reads the matching
|
|
100
|
+
* member's fields); without it any tag is a key, and a callback receives only
|
|
101
|
+
* a {@link Tagged}.
|
|
95
102
|
*
|
|
96
103
|
* @example
|
|
97
104
|
* ```ts
|
|
98
105
|
* import { Errors } from "@thomasfosterau/effect-sveltekit/server";
|
|
99
106
|
* import { error } from "@sveltejs/kit";
|
|
107
|
+
* import type { AppError } from "$lib/errors"; // your tagged-error union
|
|
100
108
|
*
|
|
101
|
-
* const translateError = Errors.toSvelteKit({
|
|
109
|
+
* const translateError = Errors.toSvelteKit<AppError>({
|
|
102
110
|
* NotFound: 404,
|
|
103
111
|
* Unauthorized: 401,
|
|
104
112
|
* Forbidden: 403,
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","names":["kitRedirect"],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * A `translateError` built from a **tagged-error catalogue** instead of a\n * hand-written switch.\n *\n * Every application maps the same handful of domain errors to SvelteKit control\n * flow at the request boundary — `NotFound → error(404)`, `Forbidden → 403`,\n * `Unauthorized → 401`, `Redirect → redirect()`, the catch-all HTTP error →\n * `error(status)` — and re-throws everything else so `handleError` sees the\n * defect. {@link toSvelteKit} takes that mapping as data, keyed by `_tag`, and\n * returns the {@link KitErrorTranslator} that `makeRuntimeAdapter` /\n * `RemoteFunction.withRuntime` accept.\n *\n * @example\n * ```ts\n * // src/lib/server/effect/kit.ts\n * import { Errors, makeRuntimeAdapter, RequestRuntime } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Layer, Schema } from \"effect\";\n *\n * // The application's tagged-error catalogue (usually imported from a shared models package).\n * class NotFound extends Schema.TaggedError<NotFound>()(\"NotFound\", {\n * resource: Schema.String,\n * id: Schema.String,\n * }) {}\n * class Forbidden extends Schema.TaggedError<Forbidden>()(\"Forbidden\", {\n * message: Schema.optional(Schema.String),\n * }) {}\n * class Redirect extends Schema.TaggedError<Redirect>()(\"Redirect\", {\n * to: Schema.String,\n * status: Schema.Number,\n * }) {}\n * class HttpError extends Schema.TaggedError<HttpError>()(\"HttpError\", {\n * status: Schema.Number,\n * message: Schema.String,\n * }) {}\n *\n * type AppError = NotFound | Forbidden | Redirect | HttpError;\n *\n * // Apps typically use `RequestRuntime.fromLocals((event) => event.locals.runtime)`.\n * const AppLayer = Layer.empty;\n *\n * export const { serverLoad, endpoint } = makeRuntimeAdapter(RequestRuntime.fromLayer(AppLayer), {\n * translateError: Errors.toSvelteKit<AppError>({\n * NotFound: { status: 404, message: (e) => `${e.resource} ${e.id} not found` },\n * Forbidden: 403, // body: the error's own `message`, else \"Forbidden\"\n * Redirect: \"redirect\", // redirect(e.status, e.to)\n * HttpError: \"status\", // error(e.status, e.message)\n * }),\n * });\n * ```\n *\n * @module\n */\n\nimport { redirect as kitRedirect } from \"@sveltejs/kit\";\nimport { Cause, Predicate } from \"effect\";\nimport { throwKitError } from \"./internal/error.js\";\nimport { SvelteKit, type KitErrorTranslator } from \"./kit.js\";\n\n/** Any value carrying a string `_tag` — `Schema.TaggedError`, `Data.TaggedError`, … */\nexport interface Tagged {\n readonly _tag: string;\n}\n\n/** An error `_tag` with arbitrary fields: the element type of an untyped catalogue. */\nexport type AnyTagged = Tagged & { readonly [field: string]: any };\n\n/** A 4xx / 5xx status for SvelteKit's `error()`. */\nexport type ErrorStatus = number;\n\n/**\n * How one tag is translated.\n *\n * - `404` (a status) — `error(status, body)`. The body is the error's own\n * non-empty `message` field, else its `_tag`.\n * - `{ status, message }` — `error(status, message(e))`; `message` may return a\n * string or an `App.Error` object.\n * - `\"status\"` — `error(e.status, body)`, for a catch-all error that carries its\n * own status (a non-4xx/5xx status becomes `500`).\n * - `\"redirect\"` — `redirect(e.status, e.to ?? e.location)`; a missing or\n * non-3xx status becomes `303`.\n * - a function — full control: throw any SvelteKit primitive (`error`,\n * `redirect`, `invalid`, …) or anything else.\n */\nexport type CatalogueEntry<E> =\n | ErrorStatus\n | {\n readonly status: ErrorStatus;\n readonly message?: ((error: E) => string | App.Error) | undefined;\n }\n | \"status\"\n | \"redirect\"\n | ((error: E) => never);\n\n/**\n * A tag-keyed catalogue. With an explicit error union `E`, keys are limited to\n * `E`'s tags and each entry's functions receive the matching member.\n */\nexport type Catalogue<E extends Tagged> = {\n readonly [K in E[\"_tag\"]]?: CatalogueEntry<Extract<E, { readonly _tag: K }>>;\n};\n\n/** Options for {@link toSvelteKit}. */\nexport interface ToSvelteKitOptions {\n /**\n * What to do with a cause whose error is not in the catalogue. Defaults to\n * {@link SvelteKit.translate}: the Kit control-flow errors\n * (`SvelteKit.redirect` / `.error` / `.fail`) and SvelteKit's own thrown\n * `redirect()` / `error()` pass through, anything else becomes an\n * `EffectCauseError` (a 500 whose `cause` is the full Effect `Cause`).\n *\n * Pass {@link rethrowSquashed} to rethrow the squashed error unchanged\n * instead, so `handleError` sees the original value.\n */\n readonly fallback?: KitErrorTranslator | undefined;\n}\n\n/** A {@link ToSvelteKitOptions.fallback} that rethrows `Cause.squash(cause)` unchanged. */\nexport const rethrowSquashed: KitErrorTranslator = (cause) => {\n throw Cause.squash(cause);\n};\n\nconst isTagged = (value: unknown): value is AnyTagged =>\n Predicate.hasProperty(value, \"_tag\") && Predicate.isString(value._tag);\n\nconst isErrorStatus = (status: unknown): status is number =>\n Predicate.isNumber(status) && Number.isInteger(status) && status >= 400 && status <= 599;\n\nconst isRedirectStatus = (\n status: unknown,\n): status is 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 =>\n Predicate.isNumber(status) && Number.isInteger(status) && status >= 300 && status <= 308;\n\n/** The error's own non-empty `message` field, else its `_tag`. */\nconst defaultBody = (error: AnyTagged): string =>\n Object.hasOwn(error, \"message\") && Predicate.isString(error.message) && error.message !== \"\"\n ? error.message\n : error._tag;\n\nconst throwError = (status: number, body: string | App.Error): never =>\n throwKitError(status, body as string | Readonly<Record<string, unknown>>);\n\nconst apply = (entry: CatalogueEntry<AnyTagged>, error: AnyTagged): never => {\n if (Predicate.isNumber(entry)) return throwError(entry, defaultBody(error));\n if (Predicate.isFunction(entry)) return entry(error);\n if (entry === \"status\") {\n return throwError(isErrorStatus(error.status) ? error.status : 500, defaultBody(error));\n }\n if (entry === \"redirect\") {\n const location: unknown = error.to ?? error.location;\n return kitRedirect(\n isRedirectStatus(error.status) ? error.status : 303,\n Predicate.isString(location) || location instanceof URL ? location : \"/\",\n );\n }\n return throwError(\n entry.status,\n entry.message === undefined ? defaultBody(error) : entry.message(error),\n );\n};\n\n/**\n * Build a `translateError` from a tag-keyed catalogue.\n *\n * The translator squashes the failed `Cause` (the first typed failure, else the\n * first defect — so a tagged error that was thrown also matches), looks its\n * `_tag` up in `catalogue`, and throws the matching SvelteKit primitive. Errors\n * outside the catalogue go to `options.fallback` (by default\n * {@link SvelteKit.translate}).\n *\n * Pass the application's error union as the type argument to have the keys and\n * each entry's callbacks checked against it; without it the catalogue is\n * untyped (`Record<string, CatalogueEntry<AnyTagged>>`).\n *\n * @example\n * ```ts\n * import { Errors } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { error } from \"@sveltejs/kit\";\n *\n * const translateError = Errors.toSvelteKit({\n * NotFound: 404,\n * Unauthorized: 401,\n * Forbidden: 403,\n * Redirect: \"redirect\",\n * HttpError: \"status\",\n * // Full control for anything bespoke, e.g. a JSON:API error document:\n * JsonapiError: (e) => error(e.status, JSON.stringify(e.toDocument())),\n * });\n * ```\n */\nexport const toSvelteKit = <E extends Tagged = AnyTagged>(\n catalogue: Catalogue<E>,\n options: ToSvelteKitOptions = {},\n): KitErrorTranslator => {\n const entries = catalogue as Readonly<Record<string, CatalogueEntry<AnyTagged> | undefined>>;\n const fallback = options.fallback ?? SvelteKit.translate;\n return (cause) => {\n const squashed = Cause.squash(cause);\n if (isTagged(squashed) && Object.hasOwn(entries, squashed._tag)) {\n const entry = entries[squashed._tag];\n if (entry !== undefined) return apply(entry, squashed);\n }\n return fallback(cause);\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqHA,MAAa,mBAAuC,UAAU;CAC5D,MAAM,MAAM,OAAO,KAAK;AAC1B;AAEA,MAAM,YAAY,UAChB,UAAU,YAAY,OAAO,MAAM,KAAK,UAAU,SAAS,MAAM,IAAI;AAEvE,MAAM,iBAAiB,WACrB,UAAU,SAAS,MAAM,KAAK,OAAO,UAAU,MAAM,KAAK,UAAU,OAAO,UAAU;AAEvF,MAAM,oBACJ,WAEA,UAAU,SAAS,MAAM,KAAK,OAAO,UAAU,MAAM,KAAK,UAAU,OAAO,UAAU;;AAGvF,MAAM,eAAe,UACnB,OAAO,OAAO,OAAO,SAAS,KAAK,UAAU,SAAS,MAAM,OAAO,KAAK,MAAM,YAAY,KACtF,MAAM,UACN,MAAM;AAEZ,MAAM,cAAc,QAAgB,SAClC,cAAc,QAAQ,IAAkD;AAE1E,MAAM,SAAS,OAAkC,UAA4B;CAC3E,IAAI,UAAU,SAAS,KAAK,GAAG,OAAO,WAAW,OAAO,YAAY,KAAK,CAAC;CAC1E,IAAI,UAAU,WAAW,KAAK,GAAG,OAAO,MAAM,KAAK;CACnD,IAAI,UAAU,UACZ,OAAO,WAAW,cAAc,MAAM,MAAM,IAAI,MAAM,SAAS,KAAK,YAAY,KAAK,CAAC;CAExF,IAAI,UAAU,YAAY;EACxB,MAAM,WAAoB,MAAM,MAAM,MAAM;EAC5C,OAAOA,SACL,iBAAiB,MAAM,MAAM,IAAI,MAAM,SAAS,KAChD,UAAU,SAAS,QAAQ,KAAK,oBAAoB,MAAM,WAAW,GACvE;CACF;CACA,OAAO,WACL,MAAM,QACN,MAAM,YAAY,KAAA,IAAY,YAAY,KAAK,IAAI,MAAM,QAAQ,KAAK,CACxE;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,eACX,WACA,UAA8B,CAAC,MACR;CACvB,MAAM,UAAU;CAChB,MAAM,WAAW,QAAQ,YAAY,UAAU;CAC/C,QAAQ,UAAU;EAChB,MAAM,WAAW,MAAM,OAAO,KAAK;EACnC,IAAI,SAAS,QAAQ,KAAK,OAAO,OAAO,SAAS,SAAS,IAAI,GAAG;GAC/D,MAAM,QAAQ,QAAQ,SAAS;GAC/B,IAAI,UAAU,KAAA,GAAW,OAAO,MAAM,OAAO,QAAQ;EACvD;EACA,OAAO,SAAS,KAAK;CACvB;AACF"}
|
|
1
|
+
{"version":3,"file":"errors.js","names":["kitRedirect"],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * A `translateError` built from a **tagged-error catalogue** instead of a\n * hand-written switch.\n *\n * Every application maps the same handful of domain errors to SvelteKit control\n * flow at the request boundary — `NotFound → error(404)`, `Forbidden → 403`,\n * `Unauthorized → 401`, `Redirect → redirect()`, the catch-all HTTP error →\n * `error(status)` — and re-throws everything else so `handleError` sees the\n * defect. {@link toSvelteKit} takes that mapping as data, keyed by `_tag`, and\n * returns the {@link KitErrorTranslator} that `makeRuntimeAdapter` /\n * `RemoteFunction.withRuntime` accept.\n *\n * @example\n * ```ts\n * // src/lib/server/effect/kit.ts\n * import { Errors, makeRuntimeAdapter, RequestRuntime } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { Layer, Schema } from \"effect\";\n *\n * // The application's tagged-error catalogue (usually imported from a shared models package).\n * class NotFound extends Schema.TaggedError<NotFound>()(\"NotFound\", {\n * resource: Schema.String,\n * id: Schema.String,\n * }) {}\n * class Forbidden extends Schema.TaggedError<Forbidden>()(\"Forbidden\", {\n * message: Schema.optional(Schema.String),\n * }) {}\n * class Redirect extends Schema.TaggedError<Redirect>()(\"Redirect\", {\n * to: Schema.String,\n * status: Schema.Number,\n * }) {}\n * class HttpError extends Schema.TaggedError<HttpError>()(\"HttpError\", {\n * status: Schema.Number,\n * message: Schema.String,\n * }) {}\n *\n * type AppError = NotFound | Forbidden | Redirect | HttpError;\n *\n * // Apps typically use `RequestRuntime.fromLocals((event) => event.locals.runtime)`.\n * const AppLayer = Layer.empty;\n *\n * export const { serverLoad, endpoint } = makeRuntimeAdapter(RequestRuntime.fromLayer(AppLayer), {\n * translateError: Errors.toSvelteKit<AppError>({\n * NotFound: { status: 404, message: (e) => `${e.resource} ${e.id} not found` },\n * Forbidden: 403, // body: the error's own `message`, else \"Forbidden\"\n * Redirect: \"redirect\", // redirect(e.status, e.to)\n * HttpError: \"status\", // error(e.status, e.message)\n * }),\n * });\n * ```\n *\n * @module\n */\n\nimport { redirect as kitRedirect } from \"@sveltejs/kit\";\nimport * as Cause from \"effect/Cause\";\nimport * as Predicate from \"effect/Predicate\";\nimport { throwKitError } from \"./internal/error.js\";\nimport { SvelteKit, type KitErrorTranslator } from \"./kit.js\";\n\n/** Any value carrying a string `_tag` — `Schema.TaggedError`, `Data.TaggedError`, … */\nexport interface Tagged {\n readonly _tag: string;\n}\n\n/** A 4xx / 5xx status for SvelteKit's `error()`. */\nexport type ErrorStatus = number;\n\n/**\n * How one tag is translated.\n *\n * - `404` (a status) — `error(status, body)`. The body is the error's own\n * non-empty `message` field, else its `_tag`.\n * - `{ status, message }` — `error(status, message(e))`; `message` may return a\n * string or an `App.Error` object.\n * - `\"status\"` — `error(e.status, body)`, for a catch-all error that carries its\n * own status (a non-4xx/5xx status becomes `500`).\n * - `\"redirect\"` — `redirect(e.status, e.to ?? e.location)`; a missing or\n * non-3xx status becomes `303`.\n * - a function — full control: throw any SvelteKit primitive (`error`,\n * `redirect`, `invalid`, …) or anything else.\n */\nexport type CatalogueEntry<E> =\n | ErrorStatus\n | {\n readonly status: ErrorStatus;\n readonly message?: ((error: E) => string | App.Error) | undefined;\n }\n | \"status\"\n | \"redirect\"\n | ((error: E) => never);\n\n/**\n * A tag-keyed catalogue. With an explicit error union `E`, keys are limited to\n * `E`'s tags and each entry's functions receive the matching member.\n */\nexport type Catalogue<E extends Tagged> = {\n readonly [K in E[\"_tag\"]]?: CatalogueEntry<Extract<E, { readonly _tag: K }>>;\n};\n\n/** Options for {@link toSvelteKit}. */\nexport interface ToSvelteKitOptions {\n /**\n * What to do with a cause whose error is not in the catalogue. Defaults to\n * {@link SvelteKit.translate}: the Kit control-flow errors\n * (`SvelteKit.redirect` / `.error` / `.fail`) and SvelteKit's own thrown\n * `redirect()` / `error()` pass through, anything else becomes an\n * `EffectCauseError` (a 500 whose `cause` is the full Effect `Cause`).\n *\n * Pass {@link rethrowSquashed} to rethrow the squashed error unchanged\n * instead, so `handleError` sees the original value.\n */\n readonly fallback?: KitErrorTranslator | undefined;\n}\n\n/** A {@link ToSvelteKitOptions.fallback} that rethrows `Cause.squash(cause)` unchanged. */\nexport const rethrowSquashed: KitErrorTranslator = (cause) => {\n throw Cause.squash(cause);\n};\n\nconst isTagged = (value: unknown): value is Tagged =>\n Predicate.hasProperty(value, \"_tag\") && Predicate.isString(value._tag);\n\nconst isErrorStatus = (status: number | undefined): status is number =>\n status !== undefined && Number.isInteger(status) && status >= 400 && status <= 599;\n\nconst isRedirectStatus = (\n status: number | undefined,\n): status is 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 =>\n status !== undefined && Number.isInteger(status) && status >= 300 && status <= 308;\n\n/** The error's own non-empty `message` field, else its `_tag`. */\nconst defaultBody = (error: Tagged): string =>\n Object.hasOwn(error, \"message\") &&\n Predicate.hasProperty(error, \"message\") &&\n Predicate.isString(error.message) &&\n error.message !== \"\"\n ? error.message\n : error._tag;\n\nconst throwError = (status: number, body: string | App.Error): never => throwKitError(status, body);\n\n/** The error's numeric `status` field, if it has one. */\nconst statusField = (error: Tagged): number | undefined =>\n Predicate.hasProperty(error, \"status\") && Predicate.isNumber(error.status)\n ? error.status\n : undefined;\n\n/** The error's redirect target: its `to` field, else its `location`, if a string or `URL`. */\nconst locationField = (error: Tagged): string | URL | undefined => {\n const to = Predicate.hasProperty(error, \"to\") ? error.to : undefined;\n const location = to ?? (Predicate.hasProperty(error, \"location\") ? error.location : undefined);\n return Predicate.isString(location) || location instanceof URL ? location : undefined;\n};\n\nconst apply = (entry: CatalogueEntry<Tagged>, error: Tagged): never => {\n if (Predicate.isNumber(entry)) return throwError(entry, defaultBody(error));\n if (Predicate.isFunction(entry)) return entry(error);\n const status = statusField(error);\n if (entry === \"status\") {\n return throwError(isErrorStatus(status) ? status : 500, defaultBody(error));\n }\n if (entry === \"redirect\") {\n return kitRedirect(isRedirectStatus(status) ? status : 303, locationField(error) ?? \"/\");\n }\n return throwError(\n entry.status,\n entry.message === undefined ? defaultBody(error) : entry.message(error),\n );\n};\n\n/**\n * Build a `translateError` from a tag-keyed catalogue.\n *\n * The translator squashes the failed `Cause` (the first typed failure, else the\n * first defect — so a tagged error that was thrown also matches), looks its\n * `_tag` up in `catalogue`, and throws the matching SvelteKit primitive. Errors\n * outside the catalogue go to `options.fallback` (by default\n * {@link SvelteKit.translate}).\n *\n * Pass the application's error union as the type argument to have the keys and\n * each entry's callbacks checked against it (a callback reads the matching\n * member's fields); without it any tag is a key, and a callback receives only\n * a {@link Tagged}.\n *\n * @example\n * ```ts\n * import { Errors } from \"@thomasfosterau/effect-sveltekit/server\";\n * import { error } from \"@sveltejs/kit\";\n * import type { AppError } from \"$lib/errors\"; // your tagged-error union\n *\n * const translateError = Errors.toSvelteKit<AppError>({\n * NotFound: 404,\n * Unauthorized: 401,\n * Forbidden: 403,\n * Redirect: \"redirect\",\n * HttpError: \"status\",\n * // Full control for anything bespoke, e.g. a JSON:API error document:\n * JsonapiError: (e) => error(e.status, JSON.stringify(e.toDocument())),\n * });\n * ```\n */\nexport const toSvelteKit = <E extends Tagged = Tagged>(\n catalogue: Catalogue<E>,\n options: ToSvelteKitOptions = {},\n): KitErrorTranslator => {\n // SAFETY: every key of a `Catalogue<E>` is one of `E`'s tags and its entry is\n // a `CatalogueEntry` of the matching member, which `apply` only ever calls\n // with an error of that tag; the lookup below is guarded by `Object.hasOwn`,\n // so absent keys read `undefined`.\n const entries = catalogue as Readonly<Record<string, CatalogueEntry<Tagged> | undefined>>;\n const fallback = options.fallback ?? SvelteKit.translate;\n return (cause) => {\n const squashed = Cause.squash(cause);\n if (isTagged(squashed) && Object.hasOwn(entries, squashed._tag)) {\n const entry = entries[squashed._tag];\n if (entry !== undefined) return apply(entry, squashed);\n }\n return fallback(cause);\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmHA,MAAa,mBAAuC,UAAU;CAC5D,MAAM,MAAM,OAAO,KAAK;AAC1B;AAEA,MAAM,YAAY,UAChB,UAAU,YAAY,OAAO,MAAM,KAAK,UAAU,SAAS,MAAM,IAAI;AAEvE,MAAM,iBAAiB,WACrB,WAAW,KAAA,KAAa,OAAO,UAAU,MAAM,KAAK,UAAU,OAAO,UAAU;AAEjF,MAAM,oBACJ,WAEA,WAAW,KAAA,KAAa,OAAO,UAAU,MAAM,KAAK,UAAU,OAAO,UAAU;;AAGjF,MAAM,eAAe,UACnB,OAAO,OAAO,OAAO,SAAS,KAC9B,UAAU,YAAY,OAAO,SAAS,KACtC,UAAU,SAAS,MAAM,OAAO,KAChC,MAAM,YAAY,KACd,MAAM,UACN,MAAM;AAEZ,MAAM,cAAc,QAAgB,SAAoC,cAAc,QAAQ,IAAI;;AAGlG,MAAM,eAAe,UACnB,UAAU,YAAY,OAAO,QAAQ,KAAK,UAAU,SAAS,MAAM,MAAM,IACrE,MAAM,SACN,KAAA;;AAGN,MAAM,iBAAiB,UAA4C;CAEjE,MAAM,YADK,UAAU,YAAY,OAAO,IAAI,IAAI,MAAM,KAAK,KAAA,OACnC,UAAU,YAAY,OAAO,UAAU,IAAI,MAAM,WAAW,KAAA;CACpF,OAAO,UAAU,SAAS,QAAQ,KAAK,oBAAoB,MAAM,WAAW,KAAA;AAC9E;AAEA,MAAM,SAAS,OAA+B,UAAyB;CACrE,IAAI,UAAU,SAAS,KAAK,GAAG,OAAO,WAAW,OAAO,YAAY,KAAK,CAAC;CAC1E,IAAI,UAAU,WAAW,KAAK,GAAG,OAAO,MAAM,KAAK;CACnD,MAAM,SAAS,YAAY,KAAK;CAChC,IAAI,UAAU,UACZ,OAAO,WAAW,cAAc,MAAM,IAAI,SAAS,KAAK,YAAY,KAAK,CAAC;CAE5E,IAAI,UAAU,YACZ,OAAOA,SAAY,iBAAiB,MAAM,IAAI,SAAS,KAAK,cAAc,KAAK,KAAK,GAAG;CAEzF,OAAO,WACL,MAAM,QACN,MAAM,YAAY,KAAA,IAAY,YAAY,KAAK,IAAI,MAAM,QAAQ,KAAK,CACxE;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAa,eACX,WACA,UAA8B,CAAC,MACR;CAKvB,MAAM,UAAU;CAChB,MAAM,WAAW,QAAQ,YAAY,UAAU;CAC/C,QAAQ,UAAU;EAChB,MAAM,WAAW,MAAM,OAAO,KAAK;EACnC,IAAI,SAAS,QAAQ,KAAK,OAAO,OAAO,SAAS,SAAS,IAAI,GAAG;GAC/D,MAAM,QAAQ,QAAQ,SAAS;GAC/B,IAAI,UAAU,KAAA,GAAW,OAAO,MAAM,OAAO,QAAQ;EACvD;EACA,OAAO,SAAS,KAAK;CACvB;AACF"}
|
package/dist/forms.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EnhanceHandlerKey, EnhanceHandlers, EnhanceHandlersBy, EnhanceOptions, EnhanceOptionsArgs, EnhanceRuntime, HandlerErrors, HandlerKeys, OnErrorAccepts, OnErrorInput, RequiredServices, ResultOptions, SubmitInput } from "./internal/enhance.js";
|
|
2
2
|
import "./forms.js";
|
|
3
|
-
import
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Schema from "effect/Schema";
|
|
4
5
|
import { ActionResult } from "$app/forms";
|
|
5
6
|
declare namespace forms_d_exports {
|
|
6
7
|
export { ApplyActionError, EnhanceHandlers, EnhanceOptions, EnhanceOptionsArgs, EnhanceRuntime, ResultOptions, SubmitInput, applyAction$1 as applyAction, deserialize$1 as deserialize, enhance };
|
|
@@ -43,10 +44,11 @@ declare namespace forms_d_exports {
|
|
|
43
44
|
* });
|
|
44
45
|
* ```
|
|
45
46
|
*/
|
|
46
|
-
declare const enhance: <RSubmit = unknown, RResult = unknown, RError = unknown, ESubmit = any, EResult = any, Keys extends EnhanceHandlerKey = never, E = OnErrorInput<HandlerErrors<Keys, ESubmit, EResult>>>(handlers: EnhanceHandlersBy<RSubmit, RResult, RError, ESubmit, EResult, E> & HandlerKeys<Keys> & NoInfer<OnErrorAccepts<RError, HandlerErrors<Keys, ESubmit, EResult>, E>>, ...rest: NoInfer<EnhanceOptionsArgs<RequiredServices<RSubmit> | RequiredServices<RResult> | RequiredServices<RError>>>) => import("$app/forms").SubmitFunction;
|
|
47
|
-
declare const ApplyActionError_base:
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
export declare const enhance: <RSubmit = unknown, RResult = unknown, RError = unknown, ESubmit = any, EResult = any, Keys extends EnhanceHandlerKey = never, E = OnErrorInput<HandlerErrors<Keys, ESubmit, EResult>>>(handlers: EnhanceHandlersBy<RSubmit, RResult, RError, ESubmit, EResult, E> & HandlerKeys<Keys> & NoInfer<OnErrorAccepts<RError, HandlerErrors<Keys, ESubmit, EResult>, E>>, ...rest: NoInfer<EnhanceOptionsArgs<RequiredServices<RSubmit> | RequiredServices<RResult> | RequiredServices<RError>>>) => import("$app/forms").SubmitFunction;
|
|
48
|
+
declare const ApplyActionError_base: Schema.Class<ApplyActionError, Schema.TaggedStruct<"ApplyActionError", {
|
|
49
|
+
/** The rejection reason, or the value thrown, as SvelteKit produced it. */
|
|
50
|
+
readonly cause: Schema.Defect;
|
|
51
|
+
}>, import("effect/Cause").YieldableError>;
|
|
50
52
|
/**
|
|
51
53
|
* {@link applyAction} rejected or threw. `cause` is SvelteKit's original
|
|
52
54
|
* reason, unchanged.
|
|
@@ -57,10 +59,7 @@ declare const ApplyActionError_base: new <A extends Record<string, any> = {}>(ar
|
|
|
57
59
|
* page's base URL, or a `beforeNavigate` / `onNavigate` callback that throws. Recover with
|
|
58
60
|
* `Effect.catchTag("ApplyActionError", ...)`.
|
|
59
61
|
*/
|
|
60
|
-
declare class ApplyActionError extends ApplyActionError_base
|
|
61
|
-
/** The rejection reason, or the value thrown, as SvelteKit produced it. */
|
|
62
|
-
readonly cause: unknown;
|
|
63
|
-
}> {}
|
|
62
|
+
export declare class ApplyActionError extends ApplyActionError_base {}
|
|
64
63
|
/**
|
|
65
64
|
* Apply an `ActionResult` to the page (updating `page.form` / `page.status`,
|
|
66
65
|
* resetting the form, etc.) as an Effect. Wraps `$app/forms`' `applyAction`.
|
|
@@ -88,5 +87,5 @@ declare const applyAction$1: <Success extends Record<string, unknown> | undefine
|
|
|
88
87
|
*/
|
|
89
88
|
declare const deserialize$1: <Success extends Record<string, unknown> | undefined = Record<string, unknown>, Failure extends Record<string, unknown> | undefined = Record<string, unknown>>(result: string) => Effect.Effect<ActionResult<Success, Failure>, unknown>;
|
|
90
89
|
//#endregion
|
|
91
|
-
export {
|
|
90
|
+
export { type EnhanceHandlers, type EnhanceOptions, type EnhanceOptionsArgs, type EnhanceRuntime, type ResultOptions, type SubmitInput, applyAction$1 as applyAction, deserialize$1 as deserialize, forms_d_exports };
|
|
92
91
|
//# sourceMappingURL=forms.d.ts.map
|
package/dist/forms.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { makeSubmitFunction } from "./internal/enhance.js";
|
|
3
|
-
import
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Schema from "effect/Schema";
|
|
4
5
|
import { applyAction, deserialize } from "$app/forms";
|
|
5
6
|
//#region src/forms.ts
|
|
6
7
|
/**
|
|
@@ -88,7 +89,9 @@ const enhance = makeSubmitFunction;
|
|
|
88
89
|
* page's base URL, or a `beforeNavigate` / `onNavigate` callback that throws. Recover with
|
|
89
90
|
* `Effect.catchTag("ApplyActionError", ...)`.
|
|
90
91
|
*/
|
|
91
|
-
var ApplyActionError = class extends
|
|
92
|
+
var ApplyActionError = class extends Schema.TaggedError()("ApplyActionError", {
|
|
93
|
+
/** The rejection reason, or the value thrown, as SvelteKit produced it. */
|
|
94
|
+
cause: Schema.Defect() }) {};
|
|
92
95
|
/**
|
|
93
96
|
* Apply an `ActionResult` to the page (updating `page.form` / `page.status`,
|
|
94
97
|
* resetting the form, etc.) as an Effect. Wraps `$app/forms`' `applyAction`.
|
package/dist/forms.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forms.js","names":["applyAction","kitApplyAction","deserialize","kitDeserialize"],"sources":["../src/forms.ts"],"sourcesContent":["/**\n * Effect bridge for SvelteKit's native form actions\n * ([`$app/forms`](https://svelte.dev/docs/kit/$app-forms)) — the `Forms`\n * namespace of `@thomasfosterau/effect-sveltekit/client`.\n *\n * This complements `Remote.submitForm` (which covers *remote* forms): here the\n * progressive-enhancement `use:enhance` flow for page `actions` is expressed\n * with Effects, and `applyAction` / `deserialize` are wrapped so a hand-rolled\n * `fetch` submission can be finished off inside an Effect pipeline.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { enhance } from '$app/forms';\n * import { Forms } from '@thomasfosterau/effect-sveltekit/client';\n * import { Effect } from 'effect';\n *\n * const submit = Forms.enhance({\n * onSubmit: () => Effect.sync(() => { saving = true; }),\n * onResult: ({ result, update }) =>\n * Effect.gen(function* () {\n * yield* Effect.promise(() => update());\n * saving = false;\n * }),\n * });\n * </script>\n *\n * <form method=\"POST\" use:enhance={submit}>...</form>\n * ```\n */\n\nimport { applyAction as kitApplyAction, deserialize as kitDeserialize } from \"$app/forms\";\nimport type { ActionResult } from \"$app/forms\";\nimport
|
|
1
|
+
{"version":3,"file":"forms.js","names":["applyAction","kitApplyAction","deserialize","kitDeserialize"],"sources":["../src/forms.ts"],"sourcesContent":["/**\n * Effect bridge for SvelteKit's native form actions\n * ([`$app/forms`](https://svelte.dev/docs/kit/$app-forms)) — the `Forms`\n * namespace of `@thomasfosterau/effect-sveltekit/client`.\n *\n * This complements `Remote.submitForm` (which covers *remote* forms): here the\n * progressive-enhancement `use:enhance` flow for page `actions` is expressed\n * with Effects, and `applyAction` / `deserialize` are wrapped so a hand-rolled\n * `fetch` submission can be finished off inside an Effect pipeline.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { enhance } from '$app/forms';\n * import { Forms } from '@thomasfosterau/effect-sveltekit/client';\n * import { Effect } from 'effect';\n *\n * const submit = Forms.enhance({\n * onSubmit: () => Effect.sync(() => { saving = true; }),\n * onResult: ({ result, update }) =>\n * Effect.gen(function* () {\n * yield* Effect.promise(() => update());\n * saving = false;\n * }),\n * });\n * </script>\n *\n * <form method=\"POST\" use:enhance={submit}>...</form>\n * ```\n */\n\nimport { applyAction as kitApplyAction, deserialize as kitDeserialize } from \"$app/forms\";\nimport type { ActionResult } from \"$app/forms\";\nimport * as Schema from \"effect/Schema\";\nimport * as Effect from \"effect/Effect\";\nimport { makeSubmitFunction } from \"./internal/enhance.js\";\n\nexport type {\n EnhanceHandlers,\n EnhanceOptions,\n EnhanceOptionsArgs,\n EnhanceRuntime,\n SubmitInput,\n ResultOptions,\n} from \"./internal/enhance.js\";\n\n/**\n * Build a `SubmitFunction` for `use:enhance` from Effect-based handlers.\n *\n * `onSubmit` runs before the request (call `input.cancel()` to abort);\n * `onResult` runs on the response with SvelteKit's `update()`. Omit `onResult`\n * to keep SvelteKit's default behaviour. When the handlers (or `onError`)\n * require application services, pass `{ runtime }` (a `Context` or\n * `ManagedRuntime` providing them): it is then required, and a call without it\n * does not type-check. Each handler may require different services; the runtime\n * must provide all of them. A missing runtime is reported on the call, and one\n * that lacks a service on the runtime, never on a handler; the message may at\n * first name only the services of the handlers TypeScript types first (such as\n * an `onError` passed by name), and the rest once the runtime provides those.\n * Handlers that require no services run on the default runtime, and the options\n * may be omitted; an effect typed as requiring `any` or `unknown` is treated as\n * requiring no services, so no runtime is demanded. A function that wraps\n * `enhance` for handlers requiring any `R` forwards its options as\n * `...options: EnhanceOptionsArgs<R>` (or takes a required\n * `{ runtime: EnhanceRuntime<R> }`): an `EnhanceOptions<R>`, whose runtime is\n * optional, does not type-check there.\n *\n * Either handler may fail. Add an `onError` handler to handle the error\n * (typed as the union of the handlers' error types when written after them;\n * `unknown` when written before a handler with unannotated parameters): a\n * failed `onSubmit` also cancels the submission, and a failed `onResult` does\n * not fall back to SvelteKit's default behaviour. Without `onError`, or for a\n * defect or interruption, the promise SvelteKit awaits rejects (with the error\n * itself for a failure), which SvelteKit leaves unhandled.\n *\n * @example\n * ```ts\n * const submit = Forms.enhance({\n * onResult: ({ result }) => Forms.applyAction(result),\n * // error: ApplyActionError\n * onError: (error) => Effect.logWarning(\"applyAction failed\", error.cause),\n * });\n * ```\n */\nexport const enhance = makeSubmitFunction;\n\n/**\n * {@link applyAction} rejected or threw. `cause` is SvelteKit's original\n * reason, unchanged.\n *\n * SvelteKit 3 throws when `applyAction` is called during server rendering, and\n * follows a `redirect` result with a client-side navigation that rejects if it\n * fails: for example, a `location` that cannot be parsed even relative to the\n * page's base URL, or a `beforeNavigate` / `onNavigate` callback that throws. Recover with\n * `Effect.catchTag(\"ApplyActionError\", ...)`.\n */\nexport class ApplyActionError extends Schema.TaggedError<ApplyActionError>()(\"ApplyActionError\", {\n /** The rejection reason, or the value thrown, as SvelteKit produced it. */\n cause: Schema.Defect(),\n}) {}\n\n/**\n * Apply an `ActionResult` to the page (updating `page.form` / `page.status`,\n * resetting the form, etc.) as an Effect. Wraps `$app/forms`' `applyAction`.\n *\n * Fails with an {@link ApplyActionError} if SvelteKit rejects or throws: for\n * example, when the navigation that follows a `redirect` result fails, or when\n * called during server rendering.\n *\n * {@link enhance}'s `onResult` can return it directly; its `onError` handler\n * then receives the `ApplyActionError`. Without `onError`, the error rejects\n * the promise SvelteKit awaits.\n *\n * @example\n * ```ts\n * const submit = Forms.enhance({\n * onResult: ({ result }) => Forms.applyAction(result),\n * onError: (error) => Effect.logWarning(\"applyAction failed\", error.cause),\n * });\n * ```\n */\nexport const applyAction = <\n Success extends Record<string, unknown> | undefined = Record<string, unknown>,\n Failure extends Record<string, unknown> | undefined = Record<string, unknown>,\n>(\n result: ActionResult<Success, Failure>,\n): Effect.Effect<void, ApplyActionError> =>\n Effect.tryPromise({\n try: () => kitApplyAction(result),\n catch: (cause) => new ApplyActionError({ cause }),\n });\n\n/**\n * Deserialize a raw form-action response body into an `ActionResult`, as an\n * Effect. Wraps `$app/forms`' `deserialize`; a malformed body fails the effect.\n */\nexport const deserialize = <\n Success extends Record<string, unknown> | undefined = Record<string, unknown>,\n Failure extends Record<string, unknown> | undefined = Record<string, unknown>,\n>(\n result: string,\n): Effect.Effect<ActionResult<Success, Failure>, unknown> =>\n Effect.try({\n try: () => kitDeserialize<Success, Failure>(result),\n catch: (error) => error,\n });\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFA,MAAa,UAAU;;;;;;;;;;;AAYvB,IAAa,mBAAb,cAAsC,OAAO,YAA8B,CAAC,CAAC,oBAAoB;;AAE/F,OAAO,OAAO,OAAO,EACvB,CAAC,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;AAsBJ,MAAaA,iBAIX,WAEA,OAAO,WAAW;CAChB,WAAWC,YAAe,MAAM;CAChC,QAAQ,UAAU,IAAI,iBAAiB,EAAE,MAAM,CAAC;AAClD,CAAC;;;;;AAMH,MAAaC,iBAIX,WAEA,OAAO,IAAI;CACT,WAAWC,YAAiC,MAAM;CAClD,QAAQ,UAAU;AACpB,CAAC"}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Stream from "effect/Stream";
|
|
3
|
+
import * as Schema from "effect/Schema";
|
|
2
4
|
import { NavigationTarget, NavigationType } from "$app/navigation";
|
|
5
|
+
import "effect/Option";
|
|
3
6
|
//#region src/internal/app-state.d.ts
|
|
4
7
|
/**
|
|
5
8
|
* The fields of SvelteKit's `page` we snapshot. Mirrors the shape of
|
|
6
9
|
* `@sveltejs/kit`'s `Page`, but as a plain readonly record rather than the live
|
|
7
10
|
* mutating proxy.
|
|
8
11
|
*/
|
|
9
|
-
interface PageSnapshot<P extends ReadonlyPage = ReadonlyPage> {
|
|
12
|
+
export interface PageSnapshot<P extends ReadonlyPage = ReadonlyPage> {
|
|
10
13
|
readonly url: P["url"];
|
|
11
14
|
readonly params: P["params"];
|
|
12
15
|
readonly route: P["route"];
|
|
@@ -23,7 +26,7 @@ interface PageSnapshot<P extends ReadonlyPage = ReadonlyPage> {
|
|
|
23
26
|
* / `error` / `state` are app-specific — satisfies the constraint, while
|
|
24
27
|
* `PageSnapshot<P>` recovers the precise field types from `P`.
|
|
25
28
|
*/
|
|
26
|
-
interface ReadonlyPage {
|
|
29
|
+
export interface ReadonlyPage {
|
|
27
30
|
readonly url: Readonly<Omit<URL, "searchParams">>;
|
|
28
31
|
readonly params: Record<string, string | undefined>;
|
|
29
32
|
readonly route: {
|
|
@@ -31,7 +34,7 @@ interface ReadonlyPage {
|
|
|
31
34
|
};
|
|
32
35
|
readonly status: number;
|
|
33
36
|
readonly error: unknown;
|
|
34
|
-
readonly data:
|
|
37
|
+
readonly data: App.PageData;
|
|
35
38
|
readonly state: unknown;
|
|
36
39
|
readonly form: unknown;
|
|
37
40
|
readonly shallow: unknown;
|
|
@@ -42,7 +45,7 @@ interface ReadonlyPage {
|
|
|
42
45
|
* navigation and `null` otherwise; `complete` resolves when the navigation
|
|
43
46
|
* finishes and rejects if it fails or is aborted.
|
|
44
47
|
*/
|
|
45
|
-
interface NavigatingSnapshot {
|
|
48
|
+
export interface NavigatingSnapshot {
|
|
46
49
|
readonly type: Exclude<NavigationType, "enter">;
|
|
47
50
|
readonly from: NavigationTarget | null;
|
|
48
51
|
readonly to: NavigationTarget | null;
|
|
@@ -50,24 +53,23 @@ interface NavigatingSnapshot {
|
|
|
50
53
|
readonly delta: number | null;
|
|
51
54
|
readonly complete: Promise<void>;
|
|
52
55
|
}
|
|
53
|
-
declare const UpdateCheckError_base:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
declare const UpdateCheckError_base: Schema.Class<UpdateCheckError, Schema.TaggedStruct<"UpdateCheckError", {
|
|
57
|
+
/** What `updated.check()` rejected with, or threw. */
|
|
58
|
+
readonly cause: Schema.Defect;
|
|
59
|
+
}>, import("effect/Cause").YieldableError>;
|
|
56
60
|
/**
|
|
57
61
|
* `updated.check()` rejected. SvelteKit resolves `false` when the version
|
|
58
62
|
* request fails, so this signals misuse (e.g. calling it during server
|
|
59
63
|
* rendering, where there is no `window`) rather than a network error.
|
|
60
64
|
*/
|
|
61
|
-
declare class UpdateCheckError extends UpdateCheckError_base
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
/** The service shape behind `State.CurrentPage`. */
|
|
65
|
-
interface CurrentPageShape<P extends ReadonlyPage = ReadonlyPage> {
|
|
65
|
+
export declare class UpdateCheckError extends UpdateCheckError_base {}
|
|
66
|
+
/** The service behind `State.CurrentPage`: a snapshot and a stream of page changes. */
|
|
67
|
+
export interface CurrentPageService<P extends ReadonlyPage = ReadonlyPage> {
|
|
66
68
|
/** Snapshots the current page when run. */
|
|
67
69
|
readonly get: Effect.Effect<PageSnapshot<P>>;
|
|
68
70
|
/** The current page, then a fresh snapshot whenever any of its fields changes. */
|
|
69
71
|
readonly changes: Stream.Stream<PageSnapshot<P>>;
|
|
70
72
|
}
|
|
71
73
|
//#endregion
|
|
72
|
-
export {
|
|
74
|
+
export {};
|
|
73
75
|
//# sourceMappingURL=app-state.d.ts.map
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Stream from "effect/Stream";
|
|
3
|
+
import * as Schema from "effect/Schema";
|
|
4
|
+
import * as Queue from "effect/Queue";
|
|
5
|
+
import * as Option from "effect/Option";
|
|
2
6
|
//#region src/internal/app-state.ts
|
|
3
7
|
/**
|
|
4
8
|
* Builds a shallow snapshot of the `page` fields that matter. We copy the
|
|
@@ -69,7 +73,9 @@ function snapshotNavigating(navigating) {
|
|
|
69
73
|
* request fails, so this signals misuse (e.g. calling it during server
|
|
70
74
|
* rendering, where there is no `window`) rather than a network error.
|
|
71
75
|
*/
|
|
72
|
-
var UpdateCheckError = class extends
|
|
76
|
+
var UpdateCheckError = class extends Schema.TaggedError()("UpdateCheckError", {
|
|
77
|
+
/** What `updated.check()` rejected with, or threw. */
|
|
78
|
+
cause: Schema.Defect() }) {};
|
|
73
79
|
/**
|
|
74
80
|
* Runs `check` (SvelteKit's `updated.check`) as an Effect that succeeds with
|
|
75
81
|
* whether a new version is available and fails with {@link UpdateCheckError}
|
|
@@ -81,7 +87,7 @@ function checkForUpdateWith(check) {
|
|
|
81
87
|
catch: (cause) => new UpdateCheckError({ cause })
|
|
82
88
|
});
|
|
83
89
|
}
|
|
84
|
-
/** Builds a {@link
|
|
90
|
+
/** Builds a {@link CurrentPageService} reading `readPage()` and watching it with `watch`. */
|
|
85
91
|
function makeCurrentPage(readPage, watch) {
|
|
86
92
|
const read = () => snapshotPage(readPage());
|
|
87
93
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-state.js","names":[],"sources":["../../src/internal/app-state.ts"],"sourcesContent":["/**\n * Pure, `$app/*`-free core for the `$app/state` bridge in `../State.ts`.\n *\n * The public helpers can't be unit-tested in plain Node because importing them\n * pulls in `$app/navigation` and `$app/state` (SvelteKit virtual modules that\n * only exist inside a build). The snapshotting, the \"emit now, then after each\n * navigation\" plumbing and the watch-to-`Stream` bridge live here instead,\n * parameterised over the navigation registrar, a {@link Watch} function and\n * read thunks, so they can be driven with stand-ins in tests while the public\n * wrappers stay thin pass-throughs. The only runes code is `watch.svelte.ts`.\n *\n * @internal\n */\n\nimport type { NavigationTarget, NavigationType } from \"$app/navigation\";\nimport { Data, Effect, Option, Queue, Stream } from \"effect\";\n\n/**\n * The fields of SvelteKit's `page` we snapshot. Mirrors the shape of\n * `@sveltejs/kit`'s `Page`, but as a plain readonly record rather than the live\n * mutating proxy.\n */\nexport interface PageSnapshot<P extends ReadonlyPage = ReadonlyPage> {\n readonly url: P[\"url\"];\n readonly params: P[\"params\"];\n readonly route: P[\"route\"];\n readonly status: P[\"status\"];\n readonly error: P[\"error\"];\n readonly data: P[\"data\"];\n readonly state: P[\"state\"];\n readonly form: P[\"form\"];\n readonly shallow: P[\"shallow\"];\n}\n\n/**\n * The subset of `Page` fields the snapshot reads. Deliberately loose (the value\n * types are `unknown` / broad) so SvelteKit's `Page` — whose `params` / `data`\n * / `error` / `state` are app-specific — satisfies the constraint, while\n * `PageSnapshot<P>` recovers the precise field types from `P`.\n */\nexport interface ReadonlyPage {\n // SvelteKit 3 types `page.url` as an immutable `ReadonlyURL` (from\n // `$app/state`); everything but `searchParams` is enough here.\n readonly url: Readonly<Omit<URL, \"searchParams\">>;\n readonly params: Record<string, string | undefined>;\n readonly route: { readonly id: string | null };\n readonly status: number;\n readonly error: unknown;\n readonly data: Record<string, unknown>;\n readonly state: unknown;\n readonly form: unknown;\n // SvelteKit 3: the target of the current shallow navigation, or `null`.\n readonly shallow: unknown;\n}\n\n/**\n * Builds a shallow snapshot of the `page` fields that matter. We copy the\n * fields rather than forwarding the live `$app/state` proxy so downstream Effect\n * consumers see a stable value (the proxy mutates in place on every\n * navigation, which would make a captured reference unreliable). Nested values\n * (`url`, `data`, ...) are *not* deep-cloned: they're replaced wholesale on each\n * navigation, so a shallow copy is enough to distinguish snapshots.\n */\nexport function snapshotPage<P extends ReadonlyPage>(page: P): PageSnapshot<P> {\n return {\n url: page.url,\n params: page.params,\n route: page.route,\n status: page.status,\n error: page.error,\n data: page.data,\n state: page.state,\n form: page.form,\n shallow: page.shallow,\n };\n}\n\n/**\n * Emits a snapshot of `readPage()` immediately, then again every time\n * `registerAfterNavigate`'s callback fires (i.e. after each navigation). Backed\n * by an unbounded queue, exposed as a `Stream` — the same push bridge as the\n * navigation-event helpers.\n */\nexport function pageSnapshotStream<P extends ReadonlyPage>(\n registerAfterNavigate: (callback: () => void) => void,\n readPage: () => P,\n): Stream.Stream<PageSnapshot<P>> {\n const queue = Effect.runSync(Queue.unbounded<PageSnapshot<P>>());\n // Initial value: the current page, so consumers start from a known state.\n Queue.offerUnsafe(queue, snapshotPage(readPage()));\n // afterNavigate fires once on mount too, but emitting up front means a\n // late-subscribing consumer still sees the current page without waiting for a\n // navigation.\n registerAfterNavigate(() => {\n Queue.offerUnsafe(queue, snapshotPage(readPage()));\n });\n return Stream.fromQueue(queue);\n}\n\n// ─── Watching rune state ─────────────────────────────────────────────────────\n\n/**\n * Observes a reactive read: calls `onValue` with `read()` once, then again\n * whenever something `read` touched changes, until the returned disposer runs.\n * The real implementation is `watch` in `./watch.svelte.ts`.\n */\nexport type Watch = <A>(read: () => A, onValue: (value: A) => void) => () => void;\n\n/**\n * A `Stream` of `read()`: the current value, then a new one each time `watch`\n * reports a change. Cold and lazy — each run opens its own watcher and disposes\n * it when the stream ends or is interrupted. Never fails; a throwing `watch`\n * surfaces as a defect (the stream dies with what it threw, with no watcher\n * left to dispose).\n */\nexport function watchedStream<A>(watch: Watch, read: () => A): Stream.Stream<A> {\n return Stream.callback<A>((queue) =>\n Effect.acquireRelease(\n Effect.sync(() =>\n watch(read, (value) => {\n Queue.offerUnsafe(queue, value);\n }),\n ),\n (dispose) => Effect.sync(dispose),\n ),\n );\n}\n\n// ─── navigating ──────────────────────────────────────────────────────────────\n\n/**\n * A snapshot of an in-flight SvelteKit navigation, as `$app/state`'s\n * `navigating` exposes it. `delta` is the history step count for a `popstate`\n * navigation and `null` otherwise; `complete` resolves when the navigation\n * finishes and rejects if it fails or is aborted.\n */\nexport interface NavigatingSnapshot {\n readonly type: Exclude<NavigationType, \"enter\">;\n readonly from: NavigationTarget | null;\n readonly to: NavigationTarget | null;\n readonly willUnload: boolean;\n readonly delta: number | null;\n readonly complete: Promise<void>;\n}\n\n/**\n * The shape of `$app/state`'s `navigating`: every field is `null` while no\n * navigation is in flight.\n */\nexport interface ReadonlyNavigating {\n readonly type: NavigatingSnapshot[\"type\"] | null;\n readonly from: NavigationTarget | null;\n readonly to: NavigationTarget | null;\n readonly willUnload: boolean | null;\n readonly delta?: number | null | undefined;\n readonly complete: Promise<void> | null;\n}\n\n/**\n * Copies `navigating` into a plain {@link NavigatingSnapshot}, or `None` when\n * no navigation is in flight (`type` is `null`). Reads every field, so a\n * watcher tracks the whole object.\n */\nexport function snapshotNavigating(\n navigating: ReadonlyNavigating,\n): Option.Option<NavigatingSnapshot> {\n const { type, from, to, willUnload, delta, complete } = navigating;\n if (type === null || willUnload === null || complete === null) return Option.none();\n return Option.some({ type, from, to, willUnload, delta: delta ?? null, complete });\n}\n\n// ─── updated ─────────────────────────────────────────────────────────────────\n\n/**\n * `updated.check()` rejected. SvelteKit resolves `false` when the version\n * request fails, so this signals misuse (e.g. calling it during server\n * rendering, where there is no `window`) rather than a network error.\n */\nexport class UpdateCheckError extends Data.TaggedError(\"UpdateCheckError\")<{\n readonly cause: unknown;\n}> {}\n\n/**\n * Runs `check` (SvelteKit's `updated.check`) as an Effect that succeeds with\n * whether a new version is available and fails with {@link UpdateCheckError}\n * if the promise rejects (or `check` throws).\n */\nexport function checkForUpdateWith(\n check: () => Promise<boolean>,\n): Effect.Effect<boolean, UpdateCheckError> {\n return Effect.tryPromise({\n try: () => check(),\n catch: (cause) => new UpdateCheckError({ cause }),\n });\n}\n\n// ─── CurrentPage ─────────────────────────────────────────────────────────────\n\n/** The service shape behind `State.CurrentPage`. */\nexport interface CurrentPageShape<P extends ReadonlyPage = ReadonlyPage> {\n /** Snapshots the current page when run. */\n readonly get: Effect.Effect<PageSnapshot<P>>;\n /** The current page, then a fresh snapshot whenever any of its fields changes. */\n readonly changes: Stream.Stream<PageSnapshot<P>>;\n}\n\n/** Builds a {@link CurrentPageShape} reading `readPage()` and watching it with `watch`. */\nexport function makeCurrentPage<P extends ReadonlyPage>(\n readPage: () => P,\n watch: Watch,\n): CurrentPageShape<P> {\n const read = (): PageSnapshot<P> => snapshotPage(readPage());\n return { get: Effect.sync(read), changes: watchedStream(watch, read) };\n}\n"],"mappings":";;;;;;;;;;AA+DA,SAAgB,aAAqC,MAA0B;CAC7E,OAAO;EACL,KAAK,KAAK;EACV,QAAQ,KAAK;EACb,OAAO,KAAK;EACZ,QAAQ,KAAK;EACb,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,SAAS,KAAK;CAChB;AACF;;;;;;;AAQA,SAAgB,mBACd,uBACA,UACgC;CAChC,MAAM,QAAQ,OAAO,QAAQ,MAAM,UAA2B,CAAC;CAE/D,MAAM,YAAY,OAAO,aAAa,SAAS,CAAC,CAAC;CAIjD,4BAA4B;EAC1B,MAAM,YAAY,OAAO,aAAa,SAAS,CAAC,CAAC;CACnD,CAAC;CACD,OAAO,OAAO,UAAU,KAAK;AAC/B;;;;;;;;AAkBA,SAAgB,cAAiB,OAAc,MAAiC;CAC9E,OAAO,OAAO,UAAa,UACzB,OAAO,eACL,OAAO,WACL,MAAM,OAAO,UAAU;EACrB,MAAM,YAAY,OAAO,KAAK;CAChC,CAAC,CACH,IACC,YAAY,OAAO,KAAK,OAAO,CAClC,CACF;AACF;;;;;;AAqCA,SAAgB,mBACd,YACmC;CACnC,MAAM,EAAE,MAAM,MAAM,IAAI,YAAY,OAAO,aAAa;CACxD,IAAI,SAAS,QAAQ,eAAe,QAAQ,aAAa,MAAM,OAAO,OAAO,KAAK;CAClF,OAAO,OAAO,KAAK;EAAE;EAAM;EAAM;EAAI;EAAY,OAAO,SAAS;EAAM;CAAS,CAAC;AACnF;;;;;;AASA,IAAa,mBAAb,cAAsC,KAAK,YAAY,kBAAkB,CAAC,CAEvE,CAAC;;;;;;AAOJ,SAAgB,mBACd,OAC0C;CAC1C,OAAO,OAAO,WAAW;EACvB,WAAW,MAAM;EACjB,QAAQ,UAAU,IAAI,iBAAiB,EAAE,MAAM,CAAC;CAClD,CAAC;AACH;;AAaA,SAAgB,gBACd,UACA,OACqB;CACrB,MAAM,aAA8B,aAAa,SAAS,CAAC;CAC3D,OAAO;EAAE,KAAK,OAAO,KAAK,IAAI;EAAG,SAAS,cAAc,OAAO,IAAI;CAAE;AACvE"}
|
|
1
|
+
{"version":3,"file":"app-state.js","names":[],"sources":["../../src/internal/app-state.ts"],"sourcesContent":["/**\n * Pure, `$app/*`-free core for the `$app/state` bridge in `../State.ts`.\n *\n * The public helpers can't be unit-tested in plain Node because importing them\n * pulls in `$app/navigation` and `$app/state` (SvelteKit virtual modules that\n * only exist inside a build). The snapshotting, the \"emit now, then after each\n * navigation\" plumbing and the watch-to-`Stream` bridge live here instead,\n * parameterised over the navigation registrar, a {@link Watch} function and\n * read thunks, so they can be driven with stand-ins in tests while the public\n * wrappers stay thin pass-throughs. The only runes code is `watch.svelte.ts`.\n *\n * @internal\n */\n\nimport type { NavigationTarget, NavigationType } from \"$app/navigation\";\nimport * as Schema from \"effect/Schema\";\nimport * as Effect from \"effect/Effect\";\nimport * as Option from \"effect/Option\";\nimport * as Queue from \"effect/Queue\";\nimport * as Stream from \"effect/Stream\";\n\n/**\n * The fields of SvelteKit's `page` we snapshot. Mirrors the shape of\n * `@sveltejs/kit`'s `Page`, but as a plain readonly record rather than the live\n * mutating proxy.\n */\nexport interface PageSnapshot<P extends ReadonlyPage = ReadonlyPage> {\n readonly url: P[\"url\"];\n readonly params: P[\"params\"];\n readonly route: P[\"route\"];\n readonly status: P[\"status\"];\n readonly error: P[\"error\"];\n readonly data: P[\"data\"];\n readonly state: P[\"state\"];\n readonly form: P[\"form\"];\n readonly shallow: P[\"shallow\"];\n}\n\n/**\n * The subset of `Page` fields the snapshot reads. Deliberately loose (the value\n * types are `unknown` / broad) so SvelteKit's `Page` — whose `params` / `data`\n * / `error` / `state` are app-specific — satisfies the constraint, while\n * `PageSnapshot<P>` recovers the precise field types from `P`.\n */\nexport interface ReadonlyPage {\n // SvelteKit 3 types `page.url` as an immutable `ReadonlyURL` (from\n // `$app/state`); everything but `searchParams` is enough here.\n readonly url: Readonly<Omit<URL, \"searchParams\">>;\n readonly params: Record<string, string | undefined>;\n readonly route: { readonly id: string | null };\n readonly status: number;\n readonly error: unknown;\n readonly data: App.PageData;\n readonly state: unknown;\n readonly form: unknown;\n // SvelteKit 3: the target of the current shallow navigation, or `null`.\n readonly shallow: unknown;\n}\n\n/**\n * Builds a shallow snapshot of the `page` fields that matter. We copy the\n * fields rather than forwarding the live `$app/state` proxy so downstream Effect\n * consumers see a stable value (the proxy mutates in place on every\n * navigation, which would make a captured reference unreliable). Nested values\n * (`url`, `data`, ...) are *not* deep-cloned: they're replaced wholesale on each\n * navigation, so a shallow copy is enough to distinguish snapshots.\n */\nexport function snapshotPage<P extends ReadonlyPage>(page: P): PageSnapshot<P> {\n return {\n url: page.url,\n params: page.params,\n route: page.route,\n status: page.status,\n error: page.error,\n data: page.data,\n state: page.state,\n form: page.form,\n shallow: page.shallow,\n };\n}\n\n/**\n * Emits a snapshot of `readPage()` immediately, then again every time\n * `registerAfterNavigate`'s callback fires (i.e. after each navigation). Backed\n * by an unbounded queue, exposed as a `Stream` — the same push bridge as the\n * navigation-event helpers.\n */\nexport function pageSnapshotStream<P extends ReadonlyPage>(\n registerAfterNavigate: (callback: () => void) => void,\n readPage: () => P,\n): Stream.Stream<PageSnapshot<P>> {\n const queue = Effect.runSync(Queue.unbounded<PageSnapshot<P>>());\n // Initial value: the current page, so consumers start from a known state.\n Queue.offerUnsafe(queue, snapshotPage(readPage()));\n // afterNavigate fires once on mount too, but emitting up front means a\n // late-subscribing consumer still sees the current page without waiting for a\n // navigation.\n registerAfterNavigate(() => {\n Queue.offerUnsafe(queue, snapshotPage(readPage()));\n });\n return Stream.fromQueue(queue);\n}\n\n// ─── Watching rune state ─────────────────────────────────────────────────────\n\n/**\n * Observes a reactive read: calls `onValue` with `read()` once, then again\n * whenever something `read` touched changes, until the returned disposer runs.\n * The real implementation is `watch` in `./watch.svelte.ts`.\n */\nexport type Watch = <A>(read: () => A, onValue: (value: A) => void) => () => void;\n\n/**\n * A `Stream` of `read()`: the current value, then a new one each time `watch`\n * reports a change. Cold and lazy — each run opens its own watcher and disposes\n * it when the stream ends or is interrupted. Never fails; a throwing `watch`\n * surfaces as a defect (the stream dies with what it threw, with no watcher\n * left to dispose).\n */\nexport function watchedStream<A>(watch: Watch, read: () => A): Stream.Stream<A> {\n return Stream.callback<A>((queue) =>\n Effect.acquireRelease(\n Effect.sync(() =>\n watch(read, (value) => {\n Queue.offerUnsafe(queue, value);\n }),\n ),\n (dispose) => Effect.sync(dispose),\n ),\n );\n}\n\n// ─── navigating ──────────────────────────────────────────────────────────────\n\n/**\n * A snapshot of an in-flight SvelteKit navigation, as `$app/state`'s\n * `navigating` exposes it. `delta` is the history step count for a `popstate`\n * navigation and `null` otherwise; `complete` resolves when the navigation\n * finishes and rejects if it fails or is aborted.\n */\nexport interface NavigatingSnapshot {\n readonly type: Exclude<NavigationType, \"enter\">;\n readonly from: NavigationTarget | null;\n readonly to: NavigationTarget | null;\n readonly willUnload: boolean;\n readonly delta: number | null;\n readonly complete: Promise<void>;\n}\n\n/**\n * The shape of `$app/state`'s `navigating`: every field is `null` while no\n * navigation is in flight.\n */\nexport interface ReadonlyNavigating {\n readonly type: NavigatingSnapshot[\"type\"] | null;\n readonly from: NavigationTarget | null;\n readonly to: NavigationTarget | null;\n readonly willUnload: boolean | null;\n readonly delta?: number | null | undefined;\n readonly complete: Promise<void> | null;\n}\n\n/**\n * Copies `navigating` into a plain {@link NavigatingSnapshot}, or `None` when\n * no navigation is in flight (`type` is `null`). Reads every field, so a\n * watcher tracks the whole object.\n */\nexport function snapshotNavigating(\n navigating: ReadonlyNavigating,\n): Option.Option<NavigatingSnapshot> {\n const { type, from, to, willUnload, delta, complete } = navigating;\n if (type === null || willUnload === null || complete === null) return Option.none();\n return Option.some({ type, from, to, willUnload, delta: delta ?? null, complete });\n}\n\n// ─── updated ─────────────────────────────────────────────────────────────────\n\n/**\n * `updated.check()` rejected. SvelteKit resolves `false` when the version\n * request fails, so this signals misuse (e.g. calling it during server\n * rendering, where there is no `window`) rather than a network error.\n */\nexport class UpdateCheckError extends Schema.TaggedError<UpdateCheckError>()(\"UpdateCheckError\", {\n /** What `updated.check()` rejected with, or threw. */\n cause: Schema.Defect(),\n}) {}\n\n/**\n * Runs `check` (SvelteKit's `updated.check`) as an Effect that succeeds with\n * whether a new version is available and fails with {@link UpdateCheckError}\n * if the promise rejects (or `check` throws).\n */\nexport function checkForUpdateWith(\n check: () => Promise<boolean>,\n): Effect.Effect<boolean, UpdateCheckError> {\n return Effect.tryPromise({\n try: () => check(),\n catch: (cause) => new UpdateCheckError({ cause }),\n });\n}\n\n// ─── CurrentPage ─────────────────────────────────────────────────────────────\n\n/** The service behind `State.CurrentPage`: a snapshot and a stream of page changes. */\nexport interface CurrentPageService<P extends ReadonlyPage = ReadonlyPage> {\n /** Snapshots the current page when run. */\n readonly get: Effect.Effect<PageSnapshot<P>>;\n /** The current page, then a fresh snapshot whenever any of its fields changes. */\n readonly changes: Stream.Stream<PageSnapshot<P>>;\n}\n\n/** Builds a {@link CurrentPageService} reading `readPage()` and watching it with `watch`. */\nexport function makeCurrentPage<P extends ReadonlyPage>(\n readPage: () => P,\n watch: Watch,\n): CurrentPageService<P> {\n const read = (): PageSnapshot<P> => snapshotPage(readPage());\n return { get: Effect.sync(read), changes: watchedStream(watch, read) };\n}\n"],"mappings":";;;;;;;;;;;;;;AAmEA,SAAgB,aAAqC,MAA0B;CAC7E,OAAO;EACL,KAAK,KAAK;EACV,QAAQ,KAAK;EACb,OAAO,KAAK;EACZ,QAAQ,KAAK;EACb,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,OAAO,KAAK;EACZ,MAAM,KAAK;EACX,SAAS,KAAK;CAChB;AACF;;;;;;;AAQA,SAAgB,mBACd,uBACA,UACgC;CAChC,MAAM,QAAQ,OAAO,QAAQ,MAAM,UAA2B,CAAC;CAE/D,MAAM,YAAY,OAAO,aAAa,SAAS,CAAC,CAAC;CAIjD,4BAA4B;EAC1B,MAAM,YAAY,OAAO,aAAa,SAAS,CAAC,CAAC;CACnD,CAAC;CACD,OAAO,OAAO,UAAU,KAAK;AAC/B;;;;;;;;AAkBA,SAAgB,cAAiB,OAAc,MAAiC;CAC9E,OAAO,OAAO,UAAa,UACzB,OAAO,eACL,OAAO,WACL,MAAM,OAAO,UAAU;EACrB,MAAM,YAAY,OAAO,KAAK;CAChC,CAAC,CACH,IACC,YAAY,OAAO,KAAK,OAAO,CAClC,CACF;AACF;;;;;;AAqCA,SAAgB,mBACd,YACmC;CACnC,MAAM,EAAE,MAAM,MAAM,IAAI,YAAY,OAAO,aAAa;CACxD,IAAI,SAAS,QAAQ,eAAe,QAAQ,aAAa,MAAM,OAAO,OAAO,KAAK;CAClF,OAAO,OAAO,KAAK;EAAE;EAAM;EAAM;EAAI;EAAY,OAAO,SAAS;EAAM;CAAS,CAAC;AACnF;;;;;;AASA,IAAa,mBAAb,cAAsC,OAAO,YAA8B,CAAC,CAAC,oBAAoB;;AAE/F,OAAO,OAAO,OAAO,EACvB,CAAC,CAAC,CAAC,CAAC;;;;;;AAOJ,SAAgB,mBACd,OAC0C;CAC1C,OAAO,OAAO,WAAW;EACvB,WAAW,MAAM;EACjB,QAAQ,UAAU,IAAI,iBAAiB,EAAE,MAAM,CAAC;CAClD,CAAC;AACH;;AAaA,SAAgB,gBACd,UACA,OACuB;CACvB,MAAM,aAA8B,aAAa,SAAS,CAAC;CAC3D,OAAO;EAAE,KAAK,OAAO,KAAK,IAAI;EAAG,SAAS,cAAc,OAAO,IAAI;CAAE;AACvE"}
|
package/dist/internal/auto.d.ts
CHANGED
|
@@ -1,70 +1,79 @@
|
|
|
1
1
|
import { ServerRuntime, UniversalRuntime } from "../app-runtime.js";
|
|
2
|
-
import
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
3
|
import { Action, Actions, Load, RequestEvent, ServerLoad } from "@sveltejs/kit";
|
|
4
4
|
import { Handle, HandleClientError, HandleFetch, HandleServerError, Reroute } from "@sveltejs/kit/hooks";
|
|
5
5
|
//#region src/internal/auto.d.ts
|
|
6
6
|
type AnyEffect = Effect.Effect<unknown, unknown, never>;
|
|
7
|
+
/**
|
|
8
|
+
* The function form of a user export: called with the hook / load argument, it
|
|
9
|
+
* returns an Effect to run or a plain SvelteKit value to pass through. Its
|
|
10
|
+
* result is only known at runtime (`Effect.isEffect` tells the two apart).
|
|
11
|
+
*/
|
|
12
|
+
type UserFn<Arg> = (arg: Arg) => unknown;
|
|
13
|
+
/** The argument-less function form of a user `init` export (see {@link UserFn}). */
|
|
14
|
+
type UserThunk = () => unknown;
|
|
7
15
|
type AnyRuntime = ServerRuntime<any, any> | UniversalRuntime<any, any>;
|
|
8
16
|
/**
|
|
9
17
|
* Module shape accepted for the plugin's `serverRuntime` / `clientRuntime`
|
|
10
18
|
* options: the runtime can be the default export or a named `runtime` export.
|
|
11
19
|
*/
|
|
12
|
-
interface RuntimeModule {
|
|
20
|
+
export interface RuntimeModule {
|
|
13
21
|
readonly runtime?: AnyRuntime;
|
|
14
22
|
readonly default?: AnyRuntime;
|
|
15
23
|
}
|
|
16
|
-
type LoadLikeInput = undefined | AnyEffect |
|
|
24
|
+
type LoadLikeInput = undefined | AnyEffect | UserFn<any>;
|
|
17
25
|
/**
|
|
18
26
|
* Wraps a value intended to be a SvelteKit universal `load` export.
|
|
19
27
|
* Used by the Vite plugin for `+page.ts` / `+layout.ts`.
|
|
20
28
|
*/
|
|
21
|
-
declare function wrapLoad<T extends LoadLikeInput>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : Load;
|
|
29
|
+
export declare function wrapLoad<T extends LoadLikeInput>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : Load;
|
|
22
30
|
/**
|
|
23
31
|
* Wraps a value intended to be a SvelteKit server `load` export.
|
|
24
32
|
* Used by the Vite plugin for `+page.server.ts` / `+layout.server.ts`.
|
|
25
33
|
*/
|
|
26
|
-
declare function wrapServerLoad<T extends LoadLikeInput>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : ServerLoad;
|
|
34
|
+
export declare function wrapServerLoad<T extends LoadLikeInput>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : ServerLoad;
|
|
27
35
|
/**
|
|
28
36
|
* Wraps a single SvelteKit action handler.
|
|
29
37
|
*/
|
|
30
|
-
declare function wrapAction<T extends LoadLikeInput>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : Action;
|
|
38
|
+
export declare function wrapAction<T extends LoadLikeInput>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : Action;
|
|
31
39
|
/**
|
|
32
40
|
* Wraps a SvelteKit `actions` object, individually wrapping each entry.
|
|
33
41
|
*/
|
|
34
|
-
declare function wrapActions<T extends Record<string, LoadLikeInput> | undefined>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : Actions;
|
|
42
|
+
export declare function wrapActions<T extends Record<string, LoadLikeInput> | undefined>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : Actions;
|
|
35
43
|
/**
|
|
36
44
|
* Wraps a SvelteKit `handle` hook export.
|
|
37
45
|
*/
|
|
38
|
-
declare function wrapHandle<T extends undefined | AnyEffect |
|
|
46
|
+
export declare function wrapHandle<T extends undefined | AnyEffect | UserFn<Parameters<Handle>[0]>>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : Handle;
|
|
39
47
|
/**
|
|
40
48
|
* Wraps a SvelteKit `handleFetch` hook export.
|
|
41
49
|
*/
|
|
42
|
-
declare function wrapHandleFetch<T extends undefined | AnyEffect |
|
|
50
|
+
export declare function wrapHandleFetch<T extends undefined | AnyEffect | UserFn<Parameters<HandleFetch>[0]>>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : HandleFetch;
|
|
43
51
|
type AnyHandleError = HandleServerError | HandleClientError;
|
|
52
|
+
type HandleErrorInput = Parameters<AnyHandleError>[0];
|
|
44
53
|
/**
|
|
45
54
|
* Wraps a SvelteKit `handleError` hook export.
|
|
46
55
|
*/
|
|
47
|
-
declare function wrapHandleError<T extends undefined | AnyEffect |
|
|
56
|
+
export declare function wrapHandleError<T extends undefined | AnyEffect | UserFn<HandleErrorInput>>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : AnyHandleError;
|
|
48
57
|
/**
|
|
49
58
|
* Wraps a SvelteKit HTTP endpoint export (`GET`, `POST`, etc.).
|
|
50
59
|
* Errors thrown by the underlying Effect propagate to SvelteKit's normal
|
|
51
60
|
* error-handling pipeline (i.e. they are not silently swallowed). Use the
|
|
52
61
|
* explicit `endpoint()` helper if you need the `exposeErrors` toggle.
|
|
53
62
|
*/
|
|
54
|
-
declare function wrapEndpoint<T extends undefined | AnyEffect |
|
|
63
|
+
export declare function wrapEndpoint<T extends undefined | AnyEffect | UserFn<RequestEvent>>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : (event: RequestEvent) => Response | Promise<Response>;
|
|
55
64
|
type RerouteEvent = Parameters<Reroute>[0];
|
|
56
65
|
/**
|
|
57
66
|
* Wraps a SvelteKit universal `reroute` hook export. The effect runs on the
|
|
58
67
|
* universal runtime with an `HttpClient` backed by the event's `fetch`, on both
|
|
59
68
|
* the server and the client.
|
|
60
69
|
*/
|
|
61
|
-
declare function wrapReroute<T extends undefined | AnyEffect |
|
|
70
|
+
export declare function wrapReroute<T extends undefined | AnyEffect | UserFn<RerouteEvent>>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : Reroute;
|
|
62
71
|
/**
|
|
63
72
|
* Wraps a SvelteKit `init` hook export (server or client).
|
|
64
73
|
* `init` runs once at startup; there is no request event available, but the
|
|
65
74
|
* application runtime's services (if configured) are.
|
|
66
75
|
*/
|
|
67
|
-
declare function wrapInit<T extends undefined | AnyEffect |
|
|
76
|
+
export declare function wrapInit<T extends undefined | AnyEffect | UserThunk>(value: T, runtimeMod?: RuntimeModule): T extends undefined ? undefined : () => Promise<void>;
|
|
68
77
|
//#endregion
|
|
69
|
-
export {
|
|
78
|
+
export {};
|
|
70
79
|
//# sourceMappingURL=auto.d.ts.map
|