@sveltejs/kit 3.0.0-next.2 → 3.0.0-next.20

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 (192) hide show
  1. package/package.json +58 -36
  2. package/src/cli.js +14 -11
  3. package/src/constants.js +6 -1
  4. package/src/core/adapt/builder.js +54 -60
  5. package/src/core/adapt/index.js +2 -5
  6. package/src/core/config/index.js +141 -76
  7. package/src/core/config/options.js +260 -260
  8. package/src/core/config/types.d.ts +1 -1
  9. package/src/core/env.js +143 -13
  10. package/src/core/generate_manifest/index.js +18 -15
  11. package/src/core/postbuild/analyse.js +7 -19
  12. package/src/core/postbuild/crawl.js +22 -6
  13. package/src/core/postbuild/entities.js +8 -2
  14. package/src/core/postbuild/fallback.js +4 -2
  15. package/src/core/postbuild/prerender.js +193 -69
  16. package/src/core/postbuild/queue.js +2 -1
  17. package/src/core/sync/create_manifest_data/conflict.js +1 -1
  18. package/src/core/sync/create_manifest_data/index.js +72 -52
  19. package/src/core/sync/sync.js +35 -26
  20. package/src/core/sync/ts.js +1 -1
  21. package/src/core/sync/utils.js +22 -2
  22. package/src/core/sync/{write_non_ambient.js → write_app_types.js} +105 -56
  23. package/src/core/sync/write_client_manifest.js +13 -28
  24. package/src/core/sync/write_env.js +7 -5
  25. package/src/core/sync/write_server.js +25 -33
  26. package/src/core/sync/write_tsconfig/index.js +274 -0
  27. package/src/core/sync/write_tsconfig/test-app/package.json +7 -0
  28. package/src/core/sync/write_tsconfig/utils.js +77 -0
  29. package/src/core/sync/write_tsconfig/validate.js +128 -0
  30. package/src/core/sync/write_types/index.js +119 -116
  31. package/src/core/utils.js +30 -5
  32. package/src/exports/env/index.js +77 -0
  33. package/src/exports/env/public.d.ts +55 -0
  34. package/src/exports/hooks/index.js +3 -9
  35. package/src/exports/hooks/public.d.ts +194 -0
  36. package/src/exports/hooks/sequence.js +9 -6
  37. package/src/exports/index.js +53 -20
  38. package/src/exports/internal/client.js +5 -0
  39. package/src/exports/internal/env.js +8 -5
  40. package/src/exports/internal/index.js +1 -90
  41. package/src/exports/internal/{event.js → server/event.js} +1 -2
  42. package/src/exports/internal/server/index.js +37 -0
  43. package/src/exports/internal/server/telemetry.js +95 -0
  44. package/src/exports/internal/shared.js +90 -0
  45. package/src/exports/node/index.js +64 -22
  46. package/src/exports/params/index.js +70 -0
  47. package/src/exports/params/public.d.ts +63 -0
  48. package/src/exports/public.d.ts +219 -1118
  49. package/src/exports/url.js +86 -0
  50. package/src/exports/vite/build/build_server.js +53 -64
  51. package/src/exports/vite/build/remote.js +24 -19
  52. package/src/exports/vite/build/utils.js +0 -8
  53. package/src/exports/vite/dev/index.js +199 -125
  54. package/src/exports/vite/index.js +1514 -833
  55. package/src/exports/vite/module_ids.js +2 -2
  56. package/src/exports/vite/preview/index.js +32 -24
  57. package/src/exports/vite/utils.js +83 -45
  58. package/src/pathname.js +55 -0
  59. package/src/runner.js +15 -0
  60. package/src/runtime/app/env/internal.js +4 -4
  61. package/src/runtime/app/env/types.d.ts +1 -1
  62. package/src/runtime/app/environment/index.js +3 -3
  63. package/src/runtime/app/{forms.js → forms/index.js} +73 -42
  64. package/src/runtime/app/forms/public.d.ts +2 -0
  65. package/src/runtime/app/forms/types.d.ts +56 -0
  66. package/src/runtime/app/internal/transport.js +53 -0
  67. package/src/runtime/app/manifest/index.js +1 -0
  68. package/src/runtime/app/{navigation.js → navigation/index.js} +2 -1
  69. package/src/runtime/app/navigation/public.d.ts +237 -0
  70. package/src/runtime/app/paths/client.js +37 -37
  71. package/src/runtime/app/paths/index.js +1 -1
  72. package/src/runtime/app/paths/internal/client.js +34 -2
  73. package/src/runtime/app/paths/internal/server.js +6 -23
  74. package/src/runtime/app/paths/internal.d.ts +3 -0
  75. package/src/runtime/app/paths/public.d.ts +1 -29
  76. package/src/runtime/app/paths/server.js +36 -17
  77. package/src/runtime/app/paths/types.d.ts +11 -19
  78. package/src/runtime/app/server/index.js +2 -2
  79. package/src/runtime/app/server/public.d.ts +519 -0
  80. package/src/runtime/app/server/remote/command.js +13 -11
  81. package/src/runtime/app/server/remote/form.js +61 -39
  82. package/src/runtime/app/server/remote/prerender.js +45 -45
  83. package/src/runtime/app/server/remote/query.js +106 -108
  84. package/src/runtime/app/server/remote/requested.js +27 -19
  85. package/src/runtime/app/server/remote/shared.js +75 -75
  86. package/src/runtime/app/service-worker/index.js +24 -0
  87. package/src/runtime/app/state/client.js +4 -2
  88. package/src/runtime/app/state/index.js +7 -5
  89. package/src/runtime/app/state/public.d.ts +72 -0
  90. package/src/runtime/app/state/server.js +3 -0
  91. package/src/runtime/app/stores.js +15 -78
  92. package/src/runtime/client/bundle.js +1 -1
  93. package/src/runtime/client/client-entry.js +3 -0
  94. package/src/runtime/client/client.js +1336 -648
  95. package/src/runtime/client/constants.js +3 -6
  96. package/src/runtime/client/entry.js +24 -3
  97. package/src/runtime/client/fetcher.js +25 -25
  98. package/src/runtime/client/ndjson.js +1 -1
  99. package/src/runtime/client/parse.js +1 -1
  100. package/src/runtime/client/payload.js +17 -0
  101. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  102. package/src/runtime/client/remote-functions/command.svelte.js +37 -61
  103. package/src/runtime/client/remote-functions/form.svelte.js +267 -178
  104. package/src/runtime/client/remote-functions/prerender.svelte.js +32 -11
  105. package/src/runtime/client/remote-functions/query/index.js +10 -17
  106. package/src/runtime/client/remote-functions/query/instance.svelte.js +64 -18
  107. package/src/runtime/client/remote-functions/query/proxy.js +5 -5
  108. package/src/runtime/client/remote-functions/query-batch.svelte.js +61 -70
  109. package/src/runtime/client/remote-functions/query-live/index.js +1 -1
  110. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +63 -21
  111. package/src/runtime/client/remote-functions/query-live/iterator.js +15 -12
  112. package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
  113. package/src/runtime/client/remote-functions/shared.svelte.js +90 -65
  114. package/src/runtime/client/snapshots.js +147 -0
  115. package/src/runtime/client/state.svelte.js +94 -55
  116. package/src/runtime/client/stream.js +3 -2
  117. package/src/runtime/client/types.d.ts +13 -9
  118. package/src/runtime/client/utils.js +22 -110
  119. package/src/runtime/components/root.svelte +56 -0
  120. package/src/runtime/env/dynamic/private.js +7 -0
  121. package/src/runtime/env/dynamic/public.js +7 -0
  122. package/src/runtime/env/static/private.js +6 -0
  123. package/src/runtime/env/static/public.js +6 -0
  124. package/src/runtime/form-utils.js +172 -61
  125. package/src/runtime/pathname.js +20 -32
  126. package/src/runtime/props.svelte.js +72 -0
  127. package/src/runtime/server/constants.js +0 -3
  128. package/src/runtime/server/cookie.js +70 -53
  129. package/src/runtime/server/csrf.js +65 -0
  130. package/src/runtime/server/data/index.js +48 -52
  131. package/src/runtime/server/dev.js +22 -0
  132. package/src/runtime/server/endpoint.js +3 -4
  133. package/src/runtime/server/env_module.js +0 -5
  134. package/src/runtime/server/errors.js +160 -0
  135. package/src/runtime/server/fetch.js +31 -38
  136. package/src/runtime/server/index.js +90 -64
  137. package/src/runtime/server/internal.js +71 -0
  138. package/src/runtime/server/page/actions.js +84 -64
  139. package/src/runtime/server/page/crypto.js +2 -2
  140. package/src/runtime/server/page/csp.js +88 -104
  141. package/src/runtime/server/page/data_serializer.js +22 -23
  142. package/src/runtime/server/page/index.js +35 -53
  143. package/src/runtime/server/page/load_data.js +47 -54
  144. package/src/runtime/server/page/render.js +172 -238
  145. package/src/runtime/server/page/respond_with_error.js +16 -30
  146. package/src/runtime/server/page/serialize_data.js +2 -13
  147. package/src/runtime/server/page/server_routing.js +85 -26
  148. package/src/runtime/server/remote-functions.js +639 -0
  149. package/src/runtime/server/respond.js +188 -129
  150. package/src/runtime/server/sourcemaps.js +183 -0
  151. package/src/runtime/server/state.js +53 -0
  152. package/src/runtime/server/utils.js +12 -154
  153. package/src/runtime/shared.js +20 -40
  154. package/src/runtime/utils.js +3 -0
  155. package/src/types/ambient-private.d.ts +11 -1
  156. package/src/types/ambient.d.ts +87 -36
  157. package/src/types/global-private.d.ts +25 -25
  158. package/src/types/internal.d.ts +160 -150
  159. package/src/types/private.d.ts +41 -1
  160. package/src/utils/error.js +28 -4
  161. package/src/utils/escape.js +9 -25
  162. package/src/utils/features.js +1 -1
  163. package/src/utils/filesystem.js +1 -23
  164. package/src/utils/fork.js +7 -2
  165. package/src/utils/hash.js +21 -0
  166. package/src/utils/http.js +8 -7
  167. package/src/utils/import.js +9 -2
  168. package/src/utils/imports.js +83 -0
  169. package/src/utils/mime.js +9 -0
  170. package/src/utils/page_nodes.js +6 -7
  171. package/src/utils/params.js +67 -0
  172. package/src/utils/regex.js +9 -0
  173. package/src/utils/routing.js +145 -73
  174. package/src/utils/shared-iterator.js +5 -0
  175. package/src/utils/streaming.js +14 -4
  176. package/src/utils/url.js +33 -2
  177. package/src/version.js +1 -1
  178. package/types/index.d.ts +2291 -2135
  179. package/types/index.d.ts.map +116 -108
  180. package/src/core/sync/write_ambient.js +0 -18
  181. package/src/core/sync/write_root.js +0 -148
  182. package/src/core/sync/write_tsconfig.js +0 -250
  183. package/src/exports/internal/server.js +0 -22
  184. package/src/exports/node/polyfills.js +0 -30
  185. package/src/runtime/server/app.js +0 -9
  186. package/src/runtime/server/remote.js +0 -457
  187. package/src/runtime/shared-server.js +0 -7
  188. package/src/runtime/telemetry/otel.js +0 -21
  189. package/src/runtime/telemetry/record_span.js +0 -65
  190. package/src/types/synthetic/$lib.md +0 -5
  191. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
  192. /package/src/{runtime/telemetry/noop.js → telemetry.js} +0 -0
@@ -1,5 +1,5 @@
1
- /** @import { RemoteFormInput, RemoteForm, InvalidField } from '@sveltejs/kit' */
2
- /** @import { InternalRemoteFormIssue, MaybePromise, RemoteFormInternals } from 'types' */
1
+ /** @import { RemoteFormInput, RemoteForm, InvalidField } from '$app/server' */
2
+ /** @import { InternalRemoteFormIssue, MaybePromise, HasNonOptionalBoolean, RemoteFormInternals } from 'types' */
3
3
  /** @import { StandardSchemaV1 } from '@standard-schema/spec' */
4
4
  import { get_request_store } from '@sveltejs/kit/internal/server';
5
5
  import {
@@ -7,9 +7,10 @@ import {
7
7
  set_nested_value,
8
8
  deep_set,
9
9
  normalize_issue,
10
- flatten_issues
10
+ flatten_issues,
11
+ parse_form_key
11
12
  } from '../../../form-utils.js';
12
- import { get_cache, run_remote_function } from './shared.js';
13
+ import { get_cache, get_implicit_lookup, run_remote_function } from './shared.js';
13
14
  import { ValidationError } from '@sveltejs/kit/internal';
14
15
 
15
16
  /**
@@ -44,7 +45,7 @@ import { ValidationError } from '@sveltejs/kit/internal';
44
45
  * @template {StandardSchemaV1<RemoteFormInput, Record<string, any>>} Schema
45
46
  * @template Output
46
47
  * @overload
47
- * @param {Schema} validate
48
+ * @param {true extends HasNonOptionalBoolean<StandardSchemaV1.InferInput<Schema>> ? 'Error: All booleans in form schemas must be optional (e.g. `v.optional(v.boolean(), false)`) because checkbox inputs do not send a false value when unchecked.' : Schema} validate
48
49
  * @param {(data: StandardSchemaV1.InferOutput<Schema>, issue: InvalidField<StandardSchemaV1.InferInput<Schema>>) => MaybePromise<Output>} fn
49
50
  * @returns {RemoteForm<StandardSchemaV1.InferInput<Schema>, Output>}
50
51
  * @since 2.27
@@ -71,8 +72,7 @@ export function form(validate_or_fn, maybe_fn) {
71
72
  * @param {string | number | boolean} [key]
72
73
  */
73
74
  function create_instance(key) {
74
- /** @type {RemoteForm<Input, Output>} */
75
- const instance = {};
75
+ const instance = /** @type {RemoteForm<Input, Output>} */ ({});
76
76
 
77
77
  instance.method = 'POST';
78
78
 
@@ -88,8 +88,8 @@ export function form(validate_or_fn, maybe_fn) {
88
88
  name: '',
89
89
  id: '',
90
90
  fn: async (data, meta, form_data) => {
91
- /** @type {{ submission: true, input?: Record<string, any>, issues?: InternalRemoteFormIssue[], result: Output }} */
92
- const output = {};
91
+ const output =
92
+ /** @type {{ submission: true, input?: Record<string, any>, issues?: InternalRemoteFormIssue[], result: Output }} */ ({});
93
93
 
94
94
  // make it possible to differentiate between user submission and programmatic `field.set(...)` updates
95
95
  output.submission = true;
@@ -102,15 +102,12 @@ export function form(validate_or_fn, maybe_fn) {
102
102
  }
103
103
 
104
104
  if (validated?.issues !== undefined) {
105
- handle_issues(output, validated.issues, form_data);
105
+ handle_issues(output, validated.issues, form_data, __.id);
106
106
  } else {
107
107
  if (validated !== undefined) {
108
108
  data = validated.value;
109
109
  }
110
110
 
111
- state.remote.refreshes ??= new Map();
112
- state.remote.reconnects ??= new Map();
113
-
114
111
  const issue = create_issues();
115
112
 
116
113
  try {
@@ -123,7 +120,7 @@ export function form(validate_or_fn, maybe_fn) {
123
120
  );
124
121
  } catch (e) {
125
122
  if (e instanceof ValidationError) {
126
- handle_issues(output, e.issues, form_data);
123
+ handle_issues(output, e.issues, form_data, __.id);
127
124
  } else {
128
125
  throw e;
129
126
  }
@@ -133,7 +130,12 @@ export function form(validate_or_fn, maybe_fn) {
133
130
  // We don't need to care about args or deduplicating calls, because uneval results are only relevant in full page reloads
134
131
  // where only one form submission is active at the same time
135
132
  if (!event.isRemoteRequest) {
136
- get_cache(__, state)[''] ??= { serialize: true, data: output };
133
+ const cache = get_cache(__, state);
134
+ cache[''] ??= output;
135
+
136
+ // register under the client-side action id so the output is serialized
137
+ // into the page, allowing the hydrated client to restore `result`/`issues`/`input`
138
+ get_implicit_lookup(__, state)[__.key ? `${__.id}/${__.key}` : __.id] = () => cache[''];
137
139
  }
138
140
 
139
141
  return output;
@@ -143,42 +145,55 @@ export function form(validate_or_fn, maybe_fn) {
143
145
  Object.defineProperty(instance, '__', { value: __ });
144
146
 
145
147
  Object.defineProperty(instance, 'action', {
146
- get: () => `?/remote=${__.id}`,
148
+ get: () => {
149
+ const search = new URLSearchParams(get_request_store().event.url.search);
150
+ search.delete('/remote');
151
+
152
+ const query = search.toString();
153
+ const action_id = __.key ? `${__.id}/${encodeURIComponent(__.key)}` : __.id;
154
+
155
+ return `?${query ? `${query}&` : ''}/remote=${action_id}`;
156
+ },
147
157
  enumerable: true
148
158
  });
149
159
 
150
160
  Object.defineProperty(instance, 'fields', {
151
161
  get() {
152
- return create_field_proxy(
153
- {},
154
- () => get_cache(__)?.['']?.data?.input ?? {},
155
- (path, value) => {
156
- const cache = get_cache(__);
162
+ // the form instance is created once per module and shared across requests,
163
+ // so the current request's state has to be resolved at access time
164
+ return create_field_proxy({
165
+ form_id: __.id,
166
+ get: () => get_cache(__, get_request_store().state)?.['']?.input ?? {},
167
+ set: (path, value) => {
168
+ const cache = get_cache(__, get_request_store().state);
157
169
  const entry = cache[''];
158
170
 
159
- if (entry?.data?.submission) {
171
+ if (entry?.submission) {
160
172
  // don't override a submission
161
173
  return;
162
174
  }
163
175
 
164
176
  if (path.length === 0) {
165
- (cache[''] ??= { serialize: true, data: {} }).data.input = value;
177
+ (cache[''] ??= {}).input = value;
166
178
  return;
167
179
  }
168
180
 
169
- const input = entry?.data?.input ?? {};
181
+ const input = entry?.input ?? {};
170
182
  deep_set(input, path.map(String), value);
171
- (cache[''] ??= { serialize: true, data: {} }).data.input = input;
183
+ (cache[''] ??= {}).input = input;
172
184
  },
173
- () => flatten_issues(get_cache(__)?.['']?.data?.issues ?? [])
174
- );
185
+ get_issues: () =>
186
+ flatten_issues(get_cache(__, get_request_store().state)?.['']?.issues ?? []),
187
+ get_touched: () => ({}),
188
+ get_dirty: () => ({})
189
+ });
175
190
  }
176
191
  });
177
192
 
178
193
  Object.defineProperty(instance, 'result', {
179
194
  get() {
180
195
  try {
181
- return get_cache(__)?.['']?.data?.result;
196
+ return get_cache(__, get_request_store().state)?.['']?.result;
182
197
  } catch {
183
198
  return undefined;
184
199
  }
@@ -190,6 +205,10 @@ export function form(validate_or_fn, maybe_fn) {
190
205
  get: () => 0
191
206
  });
192
207
 
208
+ Object.defineProperty(instance, 'submitted', {
209
+ get: () => false
210
+ });
211
+
193
212
  Object.defineProperty(instance, 'preflight', {
194
213
  // preflight is a noop on the server
195
214
  value: () => instance
@@ -217,11 +236,15 @@ export function form(validate_or_fn, maybe_fn) {
217
236
  value: (key) => {
218
237
  const { state } = get_request_store();
219
238
  const cache_key = __.id + '|' + JSON.stringify(key);
239
+ /** @type {RemoteForm<Input, Output> & { __: RemoteFormInternals }} */
220
240
  let instance = (state.remote.forms ??= new Map()).get(cache_key);
221
241
 
222
242
  if (!instance) {
223
- instance = create_instance(key);
224
- instance.__.id = `${__.id}/${encodeURIComponent(JSON.stringify(key))}`;
243
+ instance = /** @type {RemoteForm<Input, Output> & { __: RemoteFormInternals }} */ (
244
+ create_instance(key)
245
+ );
246
+ instance.__.id = __.id;
247
+ instance.__.key = JSON.stringify(key);
225
248
  instance.__.name = __.name;
226
249
 
227
250
  state.remote.forms.set(cache_key, instance);
@@ -242,8 +265,9 @@ export function form(validate_or_fn, maybe_fn) {
242
265
  * @param {{ issues?: InternalRemoteFormIssue[], input?: Record<string, any>, result: any }} output
243
266
  * @param {readonly StandardSchemaV1.Issue[]} issues
244
267
  * @param {FormData | null} form_data - null if the form is progressively enhanced
268
+ * @param {string} form_id - hash/name of the form
245
269
  */
246
- function handle_issues(output, issues, form_data) {
270
+ function handle_issues(output, issues, form_data, form_id) {
247
271
  output.issues = issues.map((issue) => normalize_issue(issue, true));
248
272
 
249
273
  // if it was a progressively-enhanced submission, we don't need
@@ -251,19 +275,17 @@ function handle_issues(output, issues, form_data) {
251
275
  if (form_data) {
252
276
  output.input = {};
253
277
 
254
- for (let key of form_data.keys()) {
278
+ for (const field_name of form_data.keys()) {
255
279
  // redact sensitive fields
256
- if (/^[.\]]?_/.test(key)) continue;
257
-
258
- const is_array = key.endsWith('[]');
259
- const values = form_data.getAll(key).filter((value) => typeof value === 'string');
280
+ if (/^[.\]]?_/.test(field_name)) continue;
260
281
 
261
- if (is_array) key = key.slice(0, -2);
282
+ const values = form_data.getAll(field_name).filter((value) => typeof value === 'string');
283
+ const field = parse_form_key(form_id, field_name);
262
284
 
263
285
  set_nested_value(
264
286
  /** @type {Record<string, any>} */ (output.input),
265
- key,
266
- is_array ? values : values[0]
287
+ field,
288
+ field.is_array ? values : values[0]
267
289
  );
268
290
  }
269
291
  }
@@ -1,19 +1,14 @@
1
- /** @import { RemoteResource, RemotePrerenderFunction } from '@sveltejs/kit' */
2
- /** @import { RemotePrerenderInputsGenerator, RemotePrerenderInternals, MaybePromise } from 'types' */
1
+ /** @import { RemoteResource, RemotePrerenderFunction } from '$app/server' */
2
+ /** @import { RemoteFunctionResponse, RemotePrerenderInputsGenerator, RemotePrerenderInternals, MaybePromise } from 'types' */
3
3
  /** @import { StandardSchemaV1 } from '@standard-schema/spec' */
4
- import { error, json } from '@sveltejs/kit';
5
- import { DEV } from 'esm-env';
4
+ import { json } from '@sveltejs/kit';
5
+ import { HandledHttpError } from '@sveltejs/kit/internal';
6
6
  import { get_request_store } from '@sveltejs/kit/internal/server';
7
- import { stringify, stringify_remote_arg } from '../../../shared.js';
7
+ import { stringify_remote_arg } from '../../../shared.js';
8
+ import { parse, stringify } from '#app/internal/transport';
8
9
  import { noop } from '../../../../utils/functions.js';
9
- import { app_dir, base } from '$app/paths/internal/server';
10
- import {
11
- create_validator,
12
- get_cache,
13
- get_response,
14
- parse_remote_response,
15
- run_remote_function
16
- } from './shared.js';
10
+ import { app_dir, base } from '#app/paths';
11
+ import { create_validator, get_response, run_remote_function } from './shared.js';
17
12
 
18
13
  /**
19
14
  * Creates a remote prerender function. When called from the browser, the function will be invoked on the server via a `fetch` call.
@@ -89,50 +84,55 @@ export function prerender(validate_or_fn, fn_or_options, maybe_options) {
89
84
 
90
85
  /** @type {RemotePrerenderFunction<Input, Output> & { __: RemotePrerenderInternals }} */
91
86
  const wrapper = (arg) => {
87
+ const { event, state } = get_request_store();
88
+ const payload = stringify_remote_arg(arg);
89
+
90
+ // `get_response` (as opposed to bare `get_cache`) also registers the call in the
91
+ // implicit lookup, so that the result is inlined into the page payload (`data.p`)
92
+ // and the client doesn't need to fetch it again upon hydration
92
93
  /** @type {Promise<Output> & Partial<RemoteResource<Output>>} */
93
- const promise = (async () => {
94
- const { event, state } = get_request_store();
95
- const payload = stringify_remote_arg(arg, state.transport);
94
+ const promise = get_response(__, payload, state, async () => {
96
95
  const id = __.id;
97
96
  const url = `${base}/${app_dir}/remote/${id}${payload ? `/${payload}` : ''}`;
98
97
 
99
- if (!state.prerendering && !DEV && !event.isRemoteRequest) {
98
+ if (!state.prerendering && !__SVELTEKIT_DEV__ && !event.isRemoteRequest) {
99
+ /** @type {RemoteFunctionResponse | undefined} */
100
+ let prerendered;
101
+
100
102
  try {
101
- return await get_response(__, payload, state, async () => {
102
- const cache = get_cache(__, state);
103
-
104
- // TODO adapters can provide prerendered data more efficiently than
105
- // fetching from the public internet
106
- const promise = (cache[payload] ??= {
107
- serialize: true,
108
- data: fetch(new URL(url, event.url.origin).href).then(async (response) => {
109
- if (!response.ok) {
110
- throw new Error('Prerendered response not found');
111
- }
112
-
113
- const prerendered = await response.json();
114
-
115
- if (prerendered.type === 'error') {
116
- error(prerendered.status, prerendered.error);
117
- }
118
-
119
- return prerendered.result;
120
- })
121
- }).data;
122
-
123
- return parse_remote_response(await promise, state.transport);
124
- });
103
+ // TODO adapters can provide prerendered data more efficiently than
104
+ // fetching from the public internet
105
+ // `request.url` rather than `event.url`, which throws inside queries
106
+ const response = await fetch(new URL(url, event.request.url).href);
107
+
108
+ if (response.ok) {
109
+ prerendered = /** @type {RemoteFunctionResponse} */ (await response.json());
110
+ }
125
111
  } catch {
126
112
  // not available prerendered, fallback to normal function
127
113
  }
114
+
115
+ if (prerendered) {
116
+ if (prerendered.type === 'error') {
117
+ throw new HandledHttpError(prerendered.error);
118
+ }
119
+
120
+ return parse(prerendered.data)._;
121
+ }
128
122
  }
129
123
 
124
+ // during a prerender run, the same function might be invoked while rendering
125
+ // multiple pages — share the result across the entire run
130
126
  if (state.prerendering?.remote_responses.has(url)) {
131
127
  return /** @type {Promise<any>} */ (state.prerendering.remote_responses.get(url));
132
128
  }
133
129
 
134
- const promise = get_response(__, payload, state, () =>
135
- run_remote_function(event, state, false, () => validate(arg), fn)
130
+ const promise = run_remote_function(
131
+ event,
132
+ { ...state, is_in_remote_prerender: true },
133
+ false,
134
+ () => validate(arg),
135
+ fn
136
136
  );
137
137
 
138
138
  if (state.prerendering) {
@@ -142,7 +142,7 @@ export function prerender(validate_or_fn, fn_or_options, maybe_options) {
142
142
  const result = await promise;
143
143
 
144
144
  if (state.prerendering) {
145
- const body = { type: 'result', result: stringify(result, state.transport) };
145
+ const body = { type: 'result', data: stringify({ _: result }) };
146
146
  state.prerendering.dependencies.set(url, {
147
147
  body: JSON.stringify(body),
148
148
  response: json(body)
@@ -151,7 +151,7 @@ export function prerender(validate_or_fn, fn_or_options, maybe_options) {
151
151
 
152
152
  // TODO this is missing error/loading/current/status
153
153
  return result;
154
- })();
154
+ });
155
155
 
156
156
  promise.catch(noop);
157
157