@sveltejs/kit 3.0.0-next.22 → 3.0.0-next.24

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 (106) hide show
  1. package/package.json +40 -9
  2. package/src/cli.js +3 -3
  3. package/src/constants.js +13 -1
  4. package/src/core/adapt/builder.js +2 -3
  5. package/src/core/env.js +139 -181
  6. package/src/core/postbuild/analyse.js +9 -4
  7. package/src/core/postbuild/prerender.js +22 -23
  8. package/src/core/sync/create_manifest_data/index.js +29 -33
  9. package/src/core/sync/sync.js +23 -40
  10. package/src/core/sync/write_app_manifest.js +83 -0
  11. package/src/core/sync/write_client_manifest.js +6 -4
  12. package/src/core/sync/write_server.js +10 -6
  13. package/src/core/sync/write_types/index.js +2 -2
  14. package/src/core/utils.js +0 -28
  15. package/src/exports/hooks/public.d.ts +9 -1
  16. package/src/exports/index.js +10 -0
  17. package/src/exports/node/index.js +77 -5
  18. package/src/exports/public.d.ts +9 -0
  19. package/src/exports/vite/build/build_server.js +3 -3
  20. package/src/exports/vite/build/utils.js +48 -4
  21. package/src/exports/vite/dev/index.js +11 -22
  22. package/src/exports/vite/index.js +62 -345
  23. package/src/exports/vite/module_ids.js +1 -11
  24. package/src/exports/vite/plugins/env-vars.js +117 -0
  25. package/src/exports/vite/preview/index.js +6 -4
  26. package/src/exports/vite/utils.js +2 -4
  27. package/src/runtime/app/env/{types.d.ts → client.js} +9 -4
  28. package/src/runtime/app/env/index.js +1 -2
  29. package/src/runtime/app/env/private/index.js +1 -0
  30. package/src/runtime/app/env/public/client.js +1 -1
  31. package/src/runtime/app/env/public/server.js +1 -1
  32. package/src/runtime/app/env/{internal.js → server.js} +4 -4
  33. package/src/runtime/app/forms/client.js +263 -0
  34. package/src/runtime/app/forms/index.js +1 -263
  35. package/src/runtime/app/forms/public.d.ts +1 -1
  36. package/src/runtime/app/forms/server.js +6 -0
  37. package/src/runtime/app/forms/shared.js +34 -0
  38. package/src/runtime/app/manifest/index.js +1 -1
  39. package/src/runtime/app/navigation/client.js +15 -0
  40. package/src/runtime/app/navigation/index.js +1 -15
  41. package/src/runtime/app/navigation/public.d.ts +1 -1
  42. package/src/runtime/app/navigation/server.js +15 -0
  43. package/src/runtime/app/paths/server.js +1 -1
  44. package/src/runtime/app/server/public.d.ts +512 -0
  45. package/src/runtime/app/server/remote/command.js +1 -1
  46. package/src/runtime/app/server/remote/form.js +16 -6
  47. package/src/runtime/app/server/remote/prerender.js +2 -3
  48. package/src/runtime/app/server/remote/query.js +2 -2
  49. package/src/runtime/app/server/remote/requested.js +3 -3
  50. package/src/runtime/app/state/client.svelte.js +207 -0
  51. package/src/runtime/app/state/index.js +1 -66
  52. package/src/runtime/app/state/public.d.ts +1 -1
  53. package/src/runtime/client/bundle.js +1 -1
  54. package/src/runtime/client/client.js +206 -274
  55. package/src/runtime/client/fetcher.js +18 -8
  56. package/src/runtime/client/remote-functions/command.svelte.js +1 -1
  57. package/src/runtime/client/remote-functions/form.svelte.js +10 -7
  58. package/src/runtime/client/remote-functions/prerender.svelte.js +2 -2
  59. package/src/runtime/client/remote-functions/query/index.js +1 -1
  60. package/src/runtime/client/remote-functions/query/instance.svelte.js +2 -1
  61. package/src/runtime/client/remote-functions/query-batch.svelte.js +1 -1
  62. package/src/runtime/client/remote-functions/query-live/index.js +1 -1
  63. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +4 -3
  64. package/src/runtime/client/remote-functions/query-live/iterator.js +1 -1
  65. package/src/runtime/client/remote-functions/shared.svelte.js +3 -3
  66. package/src/runtime/client/snapshots.js +1 -3
  67. package/src/runtime/client/stream.js +27 -20
  68. package/src/runtime/client/utils.js +7 -3
  69. package/src/runtime/components/root.svelte +5 -5
  70. package/src/runtime/env/dynamic/private.js +1 -1
  71. package/src/runtime/env/static/private.js +1 -1
  72. package/src/runtime/error-chain.js +54 -0
  73. package/src/runtime/form-utils.js +53 -77
  74. package/src/runtime/invalid-import.js +1 -0
  75. package/src/runtime/props.svelte.js +1 -1
  76. package/src/runtime/server/data/index.js +1 -1
  77. package/src/runtime/server/endpoint.js +8 -3
  78. package/src/runtime/server/env_module.js +1 -1
  79. package/src/runtime/server/errors.js +2 -2
  80. package/src/runtime/server/index.js +2 -2
  81. package/src/runtime/server/page/actions.js +77 -122
  82. package/src/runtime/server/page/index.js +37 -69
  83. package/src/runtime/server/page/render.js +18 -23
  84. package/src/runtime/server/remote-functions.js +15 -43
  85. package/src/runtime/server/respond.js +23 -3
  86. package/src/telemetry.js +1 -33
  87. package/src/types/ambient-private.d.ts +9 -17
  88. package/src/types/internal.d.ts +21 -5
  89. package/src/types/private.d.ts +1 -1
  90. package/src/utils/exports.js +1 -0
  91. package/src/utils/filesystem.js +9 -21
  92. package/src/utils/functions.js +10 -0
  93. package/src/utils/promise.js +25 -0
  94. package/src/utils/routing.js +0 -11
  95. package/src/utils/url.js +0 -11
  96. package/src/version.js +1 -1
  97. package/types/index.d.ts +1134 -1136
  98. package/types/index.d.ts.map +50 -50
  99. package/src/exports/remote/index.js +0 -11
  100. package/src/exports/remote/public.d.ts +0 -519
  101. package/src/runtime/app/env/private.js +0 -1
  102. package/src/runtime/app/env/standard-schema.d.ts +0 -0
  103. package/src/runtime/app/state/client.js +0 -63
  104. package/src/runtime/client/state.svelte.js +0 -98
  105. package/src/runtime/server/ambient.d.ts +0 -4
  106. package/src/utils/path.js +0 -23
@@ -0,0 +1,117 @@
1
+ /** @import { Plugin, ResolvedConfig } from 'vite' */
2
+ /** @import { EnvVarConfig } from '@sveltejs/kit/env' */
3
+ /** @import { ValidatedConfig } from 'types' */
4
+ import path from 'node:path';
5
+ import * as sync from '../../../core/sync/sync.js';
6
+ import { create_env_modules, resolve_env_entry } from '../../../core/env.js';
7
+ import { import_peer } from '../../../utils/import.js';
8
+ import { write_if_changed } from '../../../core/sync/utils.js';
9
+ import { posixify } from '../../../utils/os.js';
10
+
11
+ /**
12
+ * Generate (and, in dev, maintain) the `${outDir}/generated/{build,dev}/env` modules
13
+ * derived from `src/env.ts`
14
+ *
15
+ * @param {ValidatedConfig} config
16
+ * @param {(variables: Record<string, EnvVarConfig<any>> | null) => void} callback
17
+ * @returns {Plugin}
18
+ */
19
+ export function plugin_env_vars(config, callback) {
20
+ /** @type {string} */
21
+ let dir;
22
+
23
+ /** @type {Record<string, any>} */
24
+ let env;
25
+
26
+ /** @type {ResolvedConfig} */
27
+ let resolved_config;
28
+
29
+ /** @type {string | null} */
30
+ let resolved_entry = null;
31
+
32
+ /** @type {Set<string>} */
33
+ let deps = new Set();
34
+
35
+ let is_build = false;
36
+
37
+ /** @type {Promise<void> | undefined} */
38
+ let generated;
39
+
40
+ async function generate() {
41
+ const synced = await sync.env(
42
+ config,
43
+ resolved_entry,
44
+ resolved_config.root,
45
+ resolved_config.mode
46
+ );
47
+
48
+ deps = synced.deps;
49
+
50
+ const vars = synced.variables;
51
+ callback(vars);
52
+
53
+ const modules = create_env_modules(
54
+ config,
55
+ vars,
56
+ env,
57
+ dir,
58
+ resolved_entry && posixify(path.relative(dir, resolved_entry)),
59
+ !is_build
60
+ );
61
+
62
+ for (const [file, code] of Object.entries(modules)) {
63
+ write_if_changed(`${dir}/${file}`, code);
64
+ }
65
+ }
66
+
67
+ return {
68
+ name: 'vite-plugin-sveltekit-env-vars',
69
+
70
+ async configResolved(c) {
71
+ resolved_config = c;
72
+
73
+ const vite = await import_peer('vite', c.root);
74
+ env = vite.loadEnv(c.mode, path.resolve(c.root, config.env.dir), '');
75
+
76
+ is_build = c.command === 'build';
77
+
78
+ dir = posixify(
79
+ path.resolve(c.root, config.outDir, `generated/${is_build ? 'build' : 'dev'}/env`)
80
+ );
81
+ },
82
+
83
+ async buildStart() {
84
+ // runs once via the memo — per-process, whichever environment starts first
85
+ // (environment names vary by adapter), and never in the postbuild forks,
86
+ // which resolve the config without building
87
+ await (generated ??= (async () => {
88
+ resolved_entry = resolve_env_entry(config, resolved_config.root);
89
+ await generate();
90
+ })());
91
+ },
92
+
93
+ configureServer(server) {
94
+ // `handleHotUpdate` only fires for `change` events on files Vite already knows about,
95
+ // so it doesn't cover the env entry being created or deleted while the dev server is
96
+ // running. Watch for those events explicitly, re-resolve the entry, regenerate the
97
+ // modules and trigger a full reload (mirroring the previous behaviour).
98
+ const on_entry_add_unlink = async (/** @type {string} */ file) => {
99
+ const resolved = resolve_env_entry(config, resolved_config.root);
100
+
101
+ if (file === resolved_entry || file === resolved) {
102
+ resolved_entry = resolved;
103
+ await generate();
104
+ server.hot.send({ type: 'full-reload' });
105
+ }
106
+ };
107
+
108
+ server.watcher.on('add', on_entry_add_unlink);
109
+ server.watcher.on('unlink', on_entry_add_unlink);
110
+ },
111
+
112
+ async handleHotUpdate(update) {
113
+ if (!deps.has(update.file)) return;
114
+ await generate();
115
+ }
116
+ };
117
+ }
@@ -9,6 +9,7 @@ import sirv from 'sirv';
9
9
  import { loadEnv, normalizePath } from 'vite';
10
10
  import { createReadableStream, getRequest, setResponse } from '../../../exports/node/index.js';
11
11
  import { SVELTE_KIT_ASSETS } from '../../../constants.js';
12
+ import { relative_pathname } from '../../../utils/url.js';
12
13
  import { is_chrome_devtools_request, not_found } from '../utils.js';
13
14
  import { stackless } from '../../../utils/error.js';
14
15
 
@@ -176,9 +177,9 @@ export async function preview(vite, vite_config, svelte_config) {
176
177
  }
177
178
 
178
179
  if (redirect) {
179
- if (search) redirect += search;
180
- res.writeHead(307, {
181
- location: redirect
180
+ res.writeHead(308, {
181
+ // relative so (possibly invisible) path prefixes are preserved
182
+ location: relative_pathname(pathname, redirect) + search
182
183
  });
183
184
 
184
185
  res.end();
@@ -206,7 +207,8 @@ export async function preview(vite, vite_config, svelte_config) {
206
207
 
207
208
  const request = getRequest({
208
209
  base: `${protocol}://${host}`,
209
- request: req
210
+ request: req,
211
+ response: res
210
212
  });
211
213
 
212
214
  setResponse(
@@ -6,7 +6,7 @@ import { escape_html } from '../../utils/escape.js';
6
6
  import { escape_for_regexp } from '../../utils/regex.js';
7
7
  import { stackless } from '../../utils/error.js';
8
8
  import { dedent } from '../../core/sync/utils.js';
9
- import { app_server, app_env_private, sveltekit_env_private } from './module_ids.js';
9
+ import { app_server, app_env_private } from './module_ids.js';
10
10
 
11
11
  /**
12
12
  * Transforms alias to a valid vite.resolve.alias array.
@@ -119,7 +119,7 @@ export function normalize_id(id, aliases, cwd) {
119
119
  return '$app/server';
120
120
  }
121
121
 
122
- if (id === app_env_private || id === sveltekit_env_private) {
122
+ if (id === app_env_private) {
123
123
  return '$app/env/private';
124
124
  }
125
125
 
@@ -191,8 +191,6 @@ function can_export_remote_module(directory) {
191
191
  export const server_only_module_pattern = /[/.]server\.[^/]+$/;
192
192
  export const server_only_directory_pattern = /\/server\//;
193
193
 
194
- export const strip_virtual_prefix = /** @param {string} id */ (id) => id.replace('\0virtual:', '');
195
-
196
194
  /**
197
195
  * For `error_for_missing_config('remote functions', 'experimental.remoteFunctions', 'true')`,
198
196
  * returns:
@@ -1,19 +1,24 @@
1
+ import { payload } from '../../client/payload.js';
2
+
1
3
  /**
2
4
  * `true` if the app is running in the browser.
5
+ * @type {boolean}
3
6
  */
4
- export const browser: boolean;
7
+ export const browser = true;
5
8
 
6
9
  /**
7
10
  * Whether the dev server is running. This is not guaranteed to correspond to `NODE_ENV` or `MODE`.
11
+ * @type {boolean}
8
12
  */
9
- export const dev: boolean;
13
+ export const dev = __SVELTEKIT_DEV__;
10
14
 
11
15
  /**
12
16
  * SvelteKit analyses your app during the `build` step by running it. During this process, `building` is `true`. This also applies during prerendering.
17
+ * @type {boolean}
13
18
  */
14
- export const building: boolean;
19
+ export const building = false;
15
20
 
16
21
  /**
17
22
  * The value of `config.version.name`.
18
23
  */
19
- export const version: string;
24
+ export const version = payload.version;
@@ -1,2 +1 @@
1
- export { BROWSER as browser, DEV as dev } from 'esm-env';
2
- export { building, version } from './internal.js';
1
+ export { browser, dev, building, version } from '#app/env';
@@ -0,0 +1 @@
1
+ export * from '<sveltekit:generated>/env/private/server.js';
@@ -1 +1 @@
1
- export * from '__sveltekit/env/public/client';
1
+ export * from '<sveltekit:generated>/env/public/client.js';
@@ -1 +1 @@
1
- export * from '__sveltekit/env/public/server';
1
+ export * from '<sveltekit:generated>/env/public/server.js';
@@ -1,8 +1,8 @@
1
- import { BROWSER } from 'esm-env';
2
- import { payload } from '../../client/payload.js';
3
-
4
- export const version = BROWSER ? payload.version : __SVELTEKIT_APP_VERSION__;
1
+ export const browser = false;
2
+ export const dev = __SVELTEKIT_DEV__;
3
+ export const version = __SVELTEKIT_APP_VERSION__;
5
4
  export let building = false;
5
+
6
6
  export let prerendering = false;
7
7
 
8
8
  export function set_building() {
@@ -0,0 +1,263 @@
1
+ /** @import { ActionResult, SubmitFunction } from './types.js' */
2
+ import { HttpError, SvelteKitError } from '@sveltejs/kit/internal';
3
+ import { DEV } from 'esm-env';
4
+ import { noop } from '../../../utils/functions.js';
5
+ import { refreshAll } from '../navigation/index.js';
6
+ import {
7
+ applyAction,
8
+ apply_action_navigation,
9
+ handle_error,
10
+ is_current_location
11
+ } from '../../client/client.js';
12
+ import { notify_version } from '#app/state/client';
13
+ import { deserialize } from './shared.js';
14
+
15
+ export { applyAction, deserialize };
16
+
17
+ /**
18
+ * Shallow clone an element, so that we can access e.g. `form.action` without worrying
19
+ * that someone has added an `<input name="action">` (https://github.com/sveltejs/kit/issues/7593)
20
+ * @template {HTMLElement} T
21
+ * @param {T} element
22
+ * @returns {T}
23
+ */
24
+ function clone(element) {
25
+ return /** @type {T} */ (HTMLElement.prototype.cloneNode.call(element));
26
+ }
27
+
28
+ /**
29
+ * This action enhances a `<form>` element that otherwise would work without JavaScript.
30
+ *
31
+ * The `submit` function is called upon submission with the given FormData and the `action` that should be triggered.
32
+ * If `cancel` is called, the form will not be submitted.
33
+ * You can use the abort `controller` to cancel the submission in case another one starts.
34
+ * If a function is returned, that function is called with the response from the server.
35
+ * If nothing is returned, the fallback will be used.
36
+ *
37
+ * If this function or its return value isn't set, it emulates the browser-native behaviour, just without the full-page reload. It
38
+ * - resets the `<form>` element and refreshes all data in case of a successful submission with no redirect response
39
+ * - updates the `form` prop, `page.form` and `page.status` if the action is on the same page as the form
40
+ * - navigates to the page the submission lands on — populating that page's `form` prop and `page.status` — on success and failure if that isn't the current page, just as a native form submission would, but with the `?/actionName` param stripped from the destination URL
41
+ * - redirects in case of a redirect response
42
+ * - renders the nearest error page in case of an unexpected error — the one nearest the action's route, if the action is on a different page
43
+ *
44
+ * If you provide a custom function with a callback and want to use the default behavior, invoke `update` in your callback.
45
+ * It accepts an options object
46
+ * - `reset: false` if you don't want the `<form>` values to be reset after a successful submission
47
+ * - `refreshAll` to control whether all data is refreshed after submission; it defaults to `true` for successes and `false` for failures
48
+ * - `navigate: false` to apply non-redirect results to the current page rather than navigating to `result.location`; redirects are always followed
49
+ * @template {Record<string, unknown> | undefined} Success
50
+ * @template {Record<string, unknown> | undefined} Failure
51
+ * @param {HTMLFormElement} form_element The form element
52
+ * @param {SubmitFunction<Success, Failure>} submit Submit callback
53
+ */
54
+ export function enhance(form_element, submit = noop) {
55
+ if (DEV && clone(form_element).method !== 'post') {
56
+ throw new Error('use:enhance can only be used on <form> fields with method="POST"');
57
+ }
58
+
59
+ /**
60
+ * @param {{
61
+ * result: ActionResult;
62
+ * reset?: boolean;
63
+ * refreshAll?: boolean;
64
+ * invalidateAll?: boolean;
65
+ * navigate?: boolean;
66
+ * }} opts
67
+ */
68
+ const fallback_callback = async ({
69
+ result,
70
+ reset = true,
71
+ refreshAll: should_refresh_all,
72
+ invalidateAll: deprecated_invalidate_all,
73
+ navigate = true
74
+ }) => {
75
+ if (DEV && deprecated_invalidate_all !== undefined) {
76
+ console.warn(
77
+ 'The `update({ invalidateAll })` option has been deprecated in favour of `update({ refreshAll })`'
78
+ );
79
+ }
80
+
81
+ should_refresh_all ??= deprecated_invalidate_all ?? result.type === 'success';
82
+
83
+ if (result.type === 'success' && reset) {
84
+ // We call reset from the prototype to avoid DOM clobbering
85
+ HTMLFormElement.prototype.reset.call(form_element);
86
+ }
87
+
88
+ const destination =
89
+ navigate && result.type !== 'redirect' && !is_current_location(result.location)
90
+ ? result.location
91
+ : undefined;
92
+
93
+ if (destination === undefined) {
94
+ if (should_refresh_all && result.type !== 'redirect') {
95
+ await refreshAll();
96
+ }
97
+
98
+ await applyAction(result);
99
+ return;
100
+ }
101
+
102
+ // emulate the browser: navigate to where the submission lands, rendering that
103
+ // page with this result
104
+ await apply_action_navigation(destination, result, should_refresh_all);
105
+ };
106
+
107
+ /** @param {SubmitEvent} event */
108
+ async function handle_submit(event) {
109
+ const method = event.submitter?.hasAttribute('formmethod')
110
+ ? /** @type {HTMLButtonElement | HTMLInputElement} */ (event.submitter).formMethod
111
+ : clone(form_element).method;
112
+ if (method !== 'post') return;
113
+
114
+ event.preventDefault();
115
+
116
+ const action = new URL(
117
+ // We can't do submitter.formAction directly because that property is always set
118
+ event.submitter?.hasAttribute('formaction')
119
+ ? /** @type {HTMLButtonElement | HTMLInputElement} */ (event.submitter).formAction
120
+ : clone(form_element).action
121
+ );
122
+
123
+ const enctype = event.submitter?.hasAttribute('formenctype')
124
+ ? /** @type {HTMLButtonElement | HTMLInputElement} */ (event.submitter).formEnctype
125
+ : clone(form_element).enctype;
126
+
127
+ const form_data = new FormData(form_element, event.submitter);
128
+
129
+ if (DEV && enctype !== 'multipart/form-data') {
130
+ for (const value of form_data.values()) {
131
+ if (value instanceof File) {
132
+ throw new Error(
133
+ 'Your form contains <input type="file"> fields, but is missing the necessary `enctype="multipart/form-data"` attribute. This will lead to inconsistent behavior between enhanced and native forms. For more details, see https://github.com/sveltejs/kit/issues/9819.'
134
+ );
135
+ }
136
+ }
137
+ }
138
+
139
+ const controller = new AbortController();
140
+
141
+ let cancelled = false;
142
+ const cancel = () => (cancelled = true);
143
+
144
+ const callback =
145
+ (await submit({
146
+ action,
147
+ cancel,
148
+ controller,
149
+ formData: form_data,
150
+ formElement: form_element,
151
+ submitter: event.submitter
152
+ })) ?? fallback_callback;
153
+ if (cancelled) return;
154
+
155
+ /** @type {ActionResult} */
156
+ let result;
157
+
158
+ try {
159
+ const headers = new Headers({
160
+ accept: 'application/json',
161
+ 'x-sveltekit-action': 'true'
162
+ });
163
+
164
+ // do not explicitly set the `Content-Type` header when sending `FormData`
165
+ // or else it will interfere with the browser's header setting
166
+ // see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects#sect4
167
+ if (enctype !== 'multipart/form-data') {
168
+ headers.set(
169
+ 'Content-Type',
170
+ /^(:?application\/x-www-form-urlencoded|text\/plain)$/.test(enctype)
171
+ ? enctype
172
+ : 'application/x-www-form-urlencoded'
173
+ );
174
+ }
175
+
176
+ // @ts-expect-error `URLSearchParams(form_data)` is kosher, but typescript doesn't know that
177
+ const body = enctype === 'multipart/form-data' ? form_data : new URLSearchParams(form_data);
178
+
179
+ const response = await fetch(action, {
180
+ method: 'POST',
181
+ headers,
182
+ cache: 'no-store',
183
+ body,
184
+ signal: controller.signal
185
+ });
186
+
187
+ // detect new deployments from the response header
188
+ notify_version(response.headers.get('x-sveltekit-version'));
189
+
190
+ const text = await response.text();
191
+
192
+ /** @type {any} */
193
+ let parsed;
194
+ try {
195
+ // an empty body carries no result for an error response
196
+ parsed = text === '' && !response.ok ? undefined : deserialize(text);
197
+ } catch (error) {
198
+ // only an error response may have a non-ActionResult body, e.g. an HTML error page
199
+ if (response.ok) throw error;
200
+ }
201
+
202
+ if (
203
+ parsed?.type === 'success' ||
204
+ parsed?.type === 'failure' ||
205
+ parsed?.type === 'redirect' ||
206
+ parsed?.type === 'error'
207
+ ) {
208
+ result = parsed;
209
+ if (result.type === 'error' || result.type === 'failure') {
210
+ result.status = response.status;
211
+ }
212
+ } else if (!response.ok) {
213
+ // the action never ran, e.g. the CSRF check or a proxy rejected the request.
214
+ // an `App.Error`-shaped body is an expected error, anything else goes through `handleError`
215
+ throw parsed && typeof parsed === 'object' && typeof parsed.message === 'string'
216
+ ? new HttpError({ ...parsed, status: response.status })
217
+ : new SvelteKitError(
218
+ response.status,
219
+ response.statusText,
220
+ typeof parsed === 'string' ? parsed : response.statusText
221
+ );
222
+ } else {
223
+ result = parsed;
224
+ }
225
+ } catch (error) {
226
+ if (/** @type {any} */ (error)?.name === 'AbortError') return;
227
+ result = {
228
+ type: 'error',
229
+ error: await handle_error(error, {
230
+ params: {},
231
+ route: { id: null },
232
+ url: new URL(location.href)
233
+ })
234
+ };
235
+ }
236
+
237
+ await callback({
238
+ action,
239
+ formData: form_data,
240
+ formElement: form_element,
241
+ update: (opts) =>
242
+ fallback_callback({
243
+ result,
244
+ reset: opts?.reset,
245
+ refreshAll: opts?.refreshAll,
246
+ invalidateAll: opts?.invalidateAll,
247
+ navigate: opts?.navigate
248
+ }),
249
+ // @ts-expect-error generic constraints stuff we don't care about
250
+ result
251
+ });
252
+ }
253
+
254
+ // @ts-expect-error
255
+ HTMLFormElement.prototype.addEventListener.call(form_element, 'submit', handle_submit);
256
+
257
+ return {
258
+ destroy() {
259
+ // @ts-expect-error
260
+ HTMLFormElement.prototype.removeEventListener.call(form_element, 'submit', handle_submit);
261
+ }
262
+ };
263
+ }