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

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 (195) hide show
  1. package/package.json +62 -36
  2. package/src/cli.js +15 -12
  3. package/src/constants.js +6 -1
  4. package/src/core/adapt/builder.js +66 -72
  5. package/src/core/adapt/index.js +17 -6
  6. package/src/core/config/index.js +134 -80
  7. package/src/core/config/options.js +295 -273
  8. package/src/core/config/types.d.ts +1 -1
  9. package/src/core/env.js +146 -16
  10. package/src/core/generate_manifest/index.js +18 -15
  11. package/src/core/postbuild/analyse.js +8 -20
  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 +222 -70
  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 +82 -62
  19. package/src/core/sync/sync.js +40 -31
  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} +107 -58
  23. package/src/core/sync/write_client_manifest.js +14 -29
  24. package/src/core/sync/write_env.js +7 -5
  25. package/src/core/sync/write_server.js +37 -45
  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 +127 -123
  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 +195 -0
  36. package/src/exports/hooks/sequence.js +9 -6
  37. package/src/exports/index.js +52 -29
  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} +2 -3
  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 +50 -1733
  49. package/src/exports/remote/index.js +11 -0
  50. package/src/exports/remote/public.d.ts +519 -0
  51. package/src/exports/url.js +86 -0
  52. package/src/exports/vite/build/build_server.js +54 -65
  53. package/src/exports/vite/build/remote.js +24 -19
  54. package/src/exports/vite/build/utils.js +0 -8
  55. package/src/exports/vite/dev/index.js +218 -146
  56. package/src/exports/vite/index.js +1590 -858
  57. package/src/exports/vite/module_ids.js +2 -2
  58. package/src/exports/vite/preview/index.js +40 -32
  59. package/src/exports/vite/public.d.ts +588 -0
  60. package/src/exports/vite/utils.js +84 -46
  61. package/src/pathname.js +55 -0
  62. package/src/runner.js +15 -0
  63. package/src/runtime/app/env/internal.js +4 -4
  64. package/src/runtime/app/env/types.d.ts +1 -1
  65. package/src/runtime/app/environment/index.js +3 -3
  66. package/src/runtime/app/{forms.js → forms/index.js} +73 -42
  67. package/src/runtime/app/forms/public.d.ts +2 -0
  68. package/src/runtime/app/forms/types.d.ts +56 -0
  69. package/src/runtime/app/internal/transport.js +53 -0
  70. package/src/runtime/app/manifest/index.js +1 -0
  71. package/src/runtime/app/{navigation.js → navigation/index.js} +2 -1
  72. package/src/runtime/app/navigation/public.d.ts +237 -0
  73. package/src/runtime/app/paths/client.js +37 -37
  74. package/src/runtime/app/paths/index.js +1 -1
  75. package/src/runtime/app/paths/internal/client.js +34 -2
  76. package/src/runtime/app/paths/internal/server.js +6 -23
  77. package/src/runtime/app/paths/internal.d.ts +3 -0
  78. package/src/runtime/app/paths/public.d.ts +1 -29
  79. package/src/runtime/app/paths/server.js +36 -17
  80. package/src/runtime/app/paths/types.d.ts +11 -19
  81. package/src/runtime/app/server/index.js +2 -2
  82. package/src/runtime/app/server/public.d.ts +201 -0
  83. package/src/runtime/app/server/remote/command.js +13 -11
  84. package/src/runtime/app/server/remote/form.js +61 -39
  85. package/src/runtime/app/server/remote/prerender.js +45 -45
  86. package/src/runtime/app/server/remote/query.js +106 -108
  87. package/src/runtime/app/server/remote/requested.js +27 -19
  88. package/src/runtime/app/server/remote/shared.js +76 -76
  89. package/src/runtime/app/service-worker/index.js +24 -0
  90. package/src/runtime/app/state/client.js +4 -2
  91. package/src/runtime/app/state/index.js +7 -5
  92. package/src/runtime/app/state/public.d.ts +72 -0
  93. package/src/runtime/app/state/server.js +3 -0
  94. package/src/runtime/app/stores.js +15 -78
  95. package/src/runtime/client/bundle.js +1 -1
  96. package/src/runtime/client/client-entry.js +3 -0
  97. package/src/runtime/client/client.js +1336 -648
  98. package/src/runtime/client/constants.js +3 -6
  99. package/src/runtime/client/entry.js +24 -3
  100. package/src/runtime/client/fetcher.js +25 -25
  101. package/src/runtime/client/ndjson.js +1 -1
  102. package/src/runtime/client/parse.js +1 -1
  103. package/src/runtime/client/payload.js +17 -0
  104. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  105. package/src/runtime/client/remote-functions/command.svelte.js +37 -61
  106. package/src/runtime/client/remote-functions/form.svelte.js +267 -178
  107. package/src/runtime/client/remote-functions/prerender.svelte.js +32 -11
  108. package/src/runtime/client/remote-functions/query/index.js +10 -17
  109. package/src/runtime/client/remote-functions/query/instance.svelte.js +64 -18
  110. package/src/runtime/client/remote-functions/query/proxy.js +5 -5
  111. package/src/runtime/client/remote-functions/query-batch.svelte.js +61 -70
  112. package/src/runtime/client/remote-functions/query-live/index.js +1 -1
  113. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +63 -21
  114. package/src/runtime/client/remote-functions/query-live/iterator.js +15 -12
  115. package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
  116. package/src/runtime/client/remote-functions/shared.svelte.js +90 -65
  117. package/src/runtime/client/snapshots.js +147 -0
  118. package/src/runtime/client/state.svelte.js +94 -55
  119. package/src/runtime/client/stream.js +3 -2
  120. package/src/runtime/client/types.d.ts +13 -9
  121. package/src/runtime/client/utils.js +22 -110
  122. package/src/runtime/components/root.svelte +56 -0
  123. package/src/runtime/env/dynamic/private.js +7 -0
  124. package/src/runtime/env/dynamic/public.js +7 -0
  125. package/src/runtime/env/static/private.js +6 -0
  126. package/src/runtime/env/static/public.js +6 -0
  127. package/src/runtime/form-utils.js +172 -61
  128. package/src/runtime/pathname.js +20 -32
  129. package/src/runtime/props.svelte.js +72 -0
  130. package/src/runtime/server/constants.js +0 -3
  131. package/src/runtime/server/cookie.js +72 -55
  132. package/src/runtime/server/csrf.js +65 -0
  133. package/src/runtime/server/data/index.js +49 -53
  134. package/src/runtime/server/dev.js +22 -0
  135. package/src/runtime/server/endpoint.js +6 -7
  136. package/src/runtime/server/env_module.js +0 -5
  137. package/src/runtime/server/errors.js +160 -0
  138. package/src/runtime/server/fetch.js +32 -39
  139. package/src/runtime/server/index.js +90 -64
  140. package/src/runtime/server/internal.js +71 -0
  141. package/src/runtime/server/page/actions.js +85 -64
  142. package/src/runtime/server/page/crypto.js +2 -2
  143. package/src/runtime/server/page/csp.js +88 -104
  144. package/src/runtime/server/page/data_serializer.js +24 -25
  145. package/src/runtime/server/page/index.js +36 -53
  146. package/src/runtime/server/page/load_data.js +50 -57
  147. package/src/runtime/server/page/render.js +173 -239
  148. package/src/runtime/server/page/respond_with_error.js +17 -31
  149. package/src/runtime/server/page/serialize_data.js +2 -13
  150. package/src/runtime/server/page/server_routing.js +85 -26
  151. package/src/runtime/server/remote-functions.js +640 -0
  152. package/src/runtime/server/respond.js +190 -131
  153. package/src/runtime/server/sourcemaps.js +183 -0
  154. package/src/runtime/server/state.js +53 -0
  155. package/src/runtime/server/utils.js +13 -155
  156. package/src/runtime/shared.js +20 -40
  157. package/src/runtime/utils.js +3 -0
  158. package/src/types/ambient-private.d.ts +11 -1
  159. package/src/types/ambient.d.ts +87 -36
  160. package/src/types/global-private.d.ts +25 -25
  161. package/src/types/internal.d.ts +163 -157
  162. package/src/types/private.d.ts +41 -1
  163. package/src/utils/error.js +28 -4
  164. package/src/utils/escape.js +9 -25
  165. package/src/utils/features.js +1 -1
  166. package/src/utils/filesystem.js +1 -23
  167. package/src/utils/fork.js +7 -2
  168. package/src/utils/hash.js +21 -0
  169. package/src/utils/http.js +8 -7
  170. package/src/utils/import.js +9 -2
  171. package/src/utils/imports.js +83 -0
  172. package/src/utils/mime.js +9 -0
  173. package/src/utils/page_nodes.js +6 -7
  174. package/src/utils/params.js +67 -0
  175. package/src/utils/regex.js +9 -0
  176. package/src/utils/routing.js +145 -73
  177. package/src/utils/shared-iterator.js +5 -0
  178. package/src/utils/streaming.js +14 -4
  179. package/src/utils/url.js +33 -2
  180. package/src/version.js +1 -1
  181. package/types/index.d.ts +2616 -2433
  182. package/types/index.d.ts.map +120 -106
  183. package/src/core/sync/write_ambient.js +0 -18
  184. package/src/core/sync/write_root.js +0 -148
  185. package/src/core/sync/write_tsconfig.js +0 -250
  186. package/src/exports/internal/server.js +0 -22
  187. package/src/exports/node/polyfills.js +0 -30
  188. package/src/runtime/server/app.js +0 -9
  189. package/src/runtime/server/remote.js +0 -457
  190. package/src/runtime/shared-server.js +0 -7
  191. package/src/runtime/telemetry/otel.js +0 -21
  192. package/src/runtime/telemetry/record_span.js +0 -65
  193. package/src/types/synthetic/$lib.md +0 -5
  194. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
  195. /package/src/{runtime/telemetry/noop.js → telemetry.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { parse, serialize } from 'cookie';
1
+ import { parseCookie, parseSetCookie, stringifySetCookie } from 'cookie';
2
2
  import { DEV } from 'esm-env';
3
3
  import { normalize_path, resolve } from '../../utils/url.js';
4
4
  import { add_data_suffix } from '../pathname.js';
@@ -12,10 +12,11 @@ import { text_encoder } from '../utils.js';
12
12
  const cookie_paths = {};
13
13
 
14
14
  /**
15
- * Cookies that are larger than this size (including the name and other
16
- * attributes) are discarded by browsers
15
+ * Cookies whose name and value combined are larger than this size are
16
+ * discarded by browsers. This is the limit codified for the name/value pair
17
+ * in RFC 6265bis: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-20#section-5.6-7.5.1
17
18
  */
18
- const MAX_COOKIE_SIZE = 4129;
19
+ const MAX_COOKIE_SIZE = 4096;
19
20
 
20
21
  /**
21
22
  * Generates a unique key for a cookie based on its domain, path, and name in
@@ -39,52 +40,68 @@ function generate_cookie_key(domain, path, name) {
39
40
  export function get_cookies(request, url) {
40
41
  const header = request.headers.get('cookie') ?? '';
41
42
  const initial_cookies = /** @type {Record<string, string>} */ (
42
- parse(header, { decode: (value) => value })
43
+ parseCookie(header, { decode: (value) => value })
43
44
  );
44
45
 
46
+ /** @type {ReturnType<typeof parseCookie> | undefined} */
47
+ let default_cookies;
48
+
49
+ /**
50
+ * The header never changes during the request, so the default-decode parse is cached
51
+ * @param {import('cookie').ParseOptions} [opts]
52
+ */
53
+ function parse_header(opts) {
54
+ return opts?.decode ? parseCookie(header, opts) : (default_cookies ??= parseCookie(header));
55
+ }
56
+
57
+ /** @param {import('./page/types.js').Cookie} cookie */
58
+ function matches_url(cookie) {
59
+ return (
60
+ domain_matches(url.hostname, cookie.options.domain) &&
61
+ path_matches(url.pathname, cookie.options.path)
62
+ );
63
+ }
64
+
45
65
  /** @type {string | undefined} */
46
66
  let normalized_url;
47
67
 
48
68
  /** @type {Map<string, import('./page/types.js').Cookie>} */
49
69
  const new_cookies = new Map();
50
70
 
51
- /** @type {import('cookie').SerializeOptions} */
71
+ /** @type {Omit<import('cookie').SetCookie, 'name' | 'value'>} */
52
72
  const defaults = {
53
73
  httpOnly: true,
54
74
  path: '/',
55
75
  sameSite: 'lax',
56
- secure: url.hostname === 'localhost' && url.protocol === 'http:' ? false : true
76
+ secure: !__SVELTEKIT_DEV__ && !(url.hostname === 'localhost' && url.protocol === 'http:')
57
77
  };
58
78
 
59
- /** @type {import('@sveltejs/kit').Cookies} */
79
+ /** @type {import('$app/server').Cookies} */
60
80
  const cookies = {
61
81
  // The JSDoc param annotations appearing below for get, set and delete
62
82
  // are necessary to expose the `cookie` library types to
63
- // typescript users. `@type {import('@sveltejs/kit').Cookies}` above is not
83
+ // typescript users. `@type {import('$app/server').Cookies}` above is not
64
84
  // sufficient to do so.
65
85
 
66
- /**
67
- * @param {string} name
68
- * @param {import('cookie').ParseOptions} [opts]
69
- */
70
86
  get(name, opts) {
71
87
  // Look for the most specific matching cookie from new_cookies
72
- const best_match = Array.from(new_cookies.values())
73
- .filter((c) => {
74
- return (
75
- c.name === name &&
76
- domain_matches(url.hostname, c.options.domain) &&
77
- path_matches(url.pathname, c.options.path)
78
- );
79
- })
80
- .sort((a, b) => b.options.path.length - a.options.path.length)[0];
88
+ /** @type {import('./page/types.js').Cookie | undefined} */
89
+ let best_match;
90
+ for (const c of new_cookies.values()) {
91
+ if (
92
+ c.name === name &&
93
+ matches_url(c) &&
94
+ (!best_match || c.options.path.length > best_match.options.path.length)
95
+ ) {
96
+ best_match = c;
97
+ }
98
+ }
81
99
 
82
100
  if (best_match) {
83
101
  return best_match.options.maxAge === 0 ? undefined : best_match.value;
84
102
  }
85
103
 
86
- const req_cookies = parse(header, { decode: opts?.decode });
87
- const cookie = req_cookies[name]; // the decoded string or undefined
104
+ const cookie = parse_header(opts)[name]; // the decoded string or undefined
88
105
 
89
106
  // in development, if the cookie was set during this session with `cookies.set`,
90
107
  // but at a different path, warn the user. (ignore cookies from request headers,
@@ -106,20 +123,15 @@ export function get_cookies(request, url) {
106
123
  return cookie;
107
124
  },
108
125
 
109
- /**
110
- * @param {import('cookie').ParseOptions} [opts]
111
- */
112
126
  getAll(opts) {
113
- const cookies = parse(header, { decode: opts?.decode });
127
+ // copy, so the cached parse isn't mutated below
128
+ const cookies = { ...parse_header(opts) };
114
129
 
115
130
  // Group cookies by name and find the most specific one for each name
116
131
  const lookup = new Map();
117
132
 
118
133
  for (const c of new_cookies.values()) {
119
- if (
120
- domain_matches(url.hostname, c.options.domain) &&
121
- path_matches(url.pathname, c.options.path)
122
- ) {
134
+ if (matches_url(c)) {
123
135
  const existing = lookup.get(c.name);
124
136
 
125
137
  // If no existing cookie or this one has a more specific (longer) path, use this one
@@ -131,7 +143,13 @@ export function get_cookies(request, url) {
131
143
 
132
144
  // Add the most specific cookies to the result
133
145
  for (const c of lookup.values()) {
134
- cookies[c.name] = c.value;
146
+ // tombstones (deleted cookies) shadow request-header cookies,
147
+ // mirroring the behavior of `get()`
148
+ if (c.options.maxAge === 0) {
149
+ delete cookies[c.name];
150
+ } else {
151
+ cookies[c.name] = c.value;
152
+ }
135
153
  }
136
154
 
137
155
  return /** @type {Array<{ name: string; value: string }>} */ (
@@ -141,29 +159,17 @@ export function get_cookies(request, url) {
141
159
  );
142
160
  },
143
161
 
144
- /**
145
- * @param {string} name
146
- * @param {string} value
147
- * @param {import('cookie').SerializeOptions} options
148
- */
149
162
  set(name, value, options) {
150
163
  set_internal(name, value, { ...defaults, ...options });
151
164
  },
152
165
 
153
- /**
154
- * @param {string} name
155
- * @param {import('cookie').SerializeOptions} options
156
- */
157
166
  delete(name, options) {
158
167
  cookies.set(name, '', { ...options, maxAge: 0 });
159
168
  },
160
169
 
161
- /**
162
- * @param {string} name
163
- * @param {string} value
164
- * @param {import('cookie').SerializeOptions} options
165
- */
166
- serialize(name, value, options) {
170
+ parse: parseSetCookie,
171
+
172
+ serialize(name, value, { encode, ...options }) {
167
173
  let path = options.path ?? '/';
168
174
 
169
175
  if (!options.domain || options.domain === url.hostname) {
@@ -173,7 +179,7 @@ export function get_cookies(request, url) {
173
179
  path = resolve(normalized_url, path);
174
180
  }
175
181
 
176
- return serialize(name, value, { ...defaults, ...options, path });
182
+ return stringifySetCookie({ name, value, ...defaults, ...options, path }, { encode });
177
183
  }
178
184
  };
179
185
 
@@ -200,7 +206,7 @@ export function get_cookies(request, url) {
200
206
  // explicit header has highest precedence
201
207
  if (header) {
202
208
  const parsed = /** @type {Record<string, string>} */ (
203
- parse(header, { decode: (value) => value })
209
+ parseCookie(header, { decode: (value) => value })
204
210
  );
205
211
  for (const name in parsed) {
206
212
  combined_cookies[name] = parsed[name];
@@ -238,8 +244,12 @@ export function get_cookies(request, url) {
238
244
  new_cookies.set(cookie_key, cookie);
239
245
 
240
246
  if (DEV) {
241
- const serialized = serialize(name, value, cookie.options);
242
- if (text_encoder.encode(serialized).byteLength > MAX_COOKIE_SIZE) {
247
+ const size =
248
+ // only the name/value pair counts towards MAX_COOKIE_SIZE, not the other attributes
249
+ text_encoder.encode(name).byteLength +
250
+ text_encoder.encode((options.encode ?? encodeURIComponent)(value)).byteLength;
251
+
252
+ if (size > MAX_COOKIE_SIZE) {
243
253
  throw new Error(`Cookie "${name}" is too large, and will be discarded by the browser`);
244
254
  }
245
255
 
@@ -296,15 +306,22 @@ export function path_matches(path, constraint) {
296
306
  */
297
307
  export function add_cookies_to_headers(headers, cookies) {
298
308
  for (const new_cookie of cookies) {
299
- const { name, value, options } = new_cookie;
300
- headers.append('set-cookie', serialize(name, value, options));
309
+ const {
310
+ name,
311
+ value,
312
+ options: { encode, ...options }
313
+ } = new_cookie;
314
+ headers.append('set-cookie', stringifySetCookie({ name, value, ...options }, { encode }));
301
315
 
302
316
  // special case — for routes ending with .html, the route data lives in a sibling
303
317
  // `.html__data.json` file rather than a child `/__data.json` file, which means
304
318
  // we need to duplicate the cookie
305
319
  if (options.path.endsWith('.html')) {
306
320
  const path = add_data_suffix(options.path);
307
- headers.append('set-cookie', serialize(name, value, { ...options, path }));
321
+ headers.append(
322
+ 'set-cookie',
323
+ stringifySetCookie({ name, value, ...options, path }, { encode })
324
+ );
308
325
  }
309
326
  }
310
327
  }
@@ -0,0 +1,65 @@
1
+ import { is_form_content_type } from '../../utils/http.js';
2
+
3
+ const mutating_form_methods = new Set(['POST', 'PUT', 'PATCH', 'DELETE']);
4
+
5
+ /**
6
+ * The origin SvelteKit treats as "self" when validating the `Origin` header on
7
+ * cross-site requests.
8
+ *
9
+ * By default (`paths.origin` is `undefined`), SvelteKit derives the origin
10
+ * from `request.url` (which is set by the adapter, and ultimately by the
11
+ * platform). When `paths.origin` is configured — for example so that a preview
12
+ * deployment whose URL isn't known at build time, or an app behind a reverse
13
+ * proxy, can declare a canonical origin — that value takes precedence.
14
+ *
15
+ * @param {string | undefined} paths_origin the configured `kit.paths.origin`
16
+ * @param {string} url_origin the origin derived from `request.url`
17
+ * @returns {string}
18
+ */
19
+ export function get_self_origin(paths_origin, url_origin) {
20
+ return paths_origin || url_origin;
21
+ }
22
+
23
+ /**
24
+ * Determines whether a non-remote request should be rejected as a cross-site
25
+ * request forgery (CSRF). Used by `respond.js` to gate form `POST`/`PUT`/
26
+ * `PATCH`/`DELETE` requests whose `Origin` header doesn't match the app's
27
+ * self-origin (and isn't in `trusted_origins`).
28
+ *
29
+ * @param {{
30
+ * request: Request;
31
+ * request_origin: string | null;
32
+ * self_origin: string;
33
+ * trusted_origins: string[];
34
+ * }} input
35
+ * @returns {boolean}
36
+ */
37
+ export function is_csrf_forbidden({ request, request_origin, self_origin, trusted_origins }) {
38
+ return (
39
+ (!request.headers.get('content-type') || is_form_content_type(request)) &&
40
+ mutating_form_methods.has(request.method) &&
41
+ request_origin !== self_origin &&
42
+ (!request_origin || !trusted_origins.includes(request_origin))
43
+ );
44
+ }
45
+
46
+ /**
47
+ * Determines whether a remote-function request should be rejected as cross-site.
48
+ *
49
+ * Unlike form submissions, remote functions accept any content type (e.g.
50
+ * `application/json`), so the check is solely on the request method and origin:
51
+ * a non-`GET` request is forbidden when its `Origin` header doesn't match the
52
+ * app's self-origin. Unlike `is_csrf_forbidden`, entries in `trusted_origins`
53
+ * are *not* honoured — remote function endpoints are an implementation detail,
54
+ * not a public API, so cross-origin calls are forbidden regardless.
55
+ *
56
+ * @param {{
57
+ * request: Request;
58
+ * request_origin: string | null;
59
+ * self_origin: string;
60
+ * }} input
61
+ * @returns {boolean}
62
+ */
63
+ export function is_remote_forbidden({ request, request_origin, self_origin }) {
64
+ return request.method !== 'GET' && request_origin !== self_origin;
65
+ }
@@ -1,39 +1,36 @@
1
1
  import { text } from '@sveltejs/kit';
2
- import { HttpError, SvelteKitError, Redirect } from '@sveltejs/kit/internal';
2
+ import { Redirect } from '@sveltejs/kit/internal';
3
3
  import { normalize_error } from '../../../utils/error.js';
4
4
  import { once } from '../../../utils/functions.js';
5
5
  import { server_data_serializer_json } from '../page/data_serializer.js';
6
6
  import { load_server_data } from '../page/load_data.js';
7
- import { handle_error_and_jsonify } from '../utils.js';
7
+ import { handle_error_and_jsonify } from '../errors.js';
8
8
  import { normalize_path } from '../../../utils/url.js';
9
9
  import { text_encoder } from '../../utils.js';
10
+ import { with_version_header } from '../utils.js';
10
11
 
11
12
  /**
12
- * @param {import('@sveltejs/kit').RequestEvent} event
13
- * @param {import('types').RequestState} event_state
13
+ * @param {import('$app/server').RequestEvent} event
14
+ * @param {import('types').RequestState} state
14
15
  * @param {import('types').SSRRoute} route
15
16
  * @param {import('types').SSROptions} options
16
17
  * @param {import('@sveltejs/kit').SSRManifest} manifest
17
- * @param {import('types').SSRState} state
18
18
  * @param {boolean[] | undefined} invalidated_data_nodes
19
19
  * @param {import('types').TrailingSlash} trailing_slash
20
20
  * @returns {Promise<Response>}
21
21
  */
22
22
  export async function render_data(
23
23
  event,
24
- event_state,
24
+ state,
25
25
  route,
26
26
  options,
27
27
  manifest,
28
- state,
29
28
  invalidated_data_nodes,
30
29
  trailing_slash
31
30
  ) {
32
31
  if (!route.page) {
33
32
  // requesting /__data.json should fail for a +server.js
34
- return new Response(undefined, {
35
- status: 404
36
- });
33
+ return with_version_header(new Response(undefined, { status: 404 }));
37
34
  }
38
35
 
39
36
  try {
@@ -61,7 +58,6 @@ export async function render_data(
61
58
  // load this. for the child, return as is. for the final result, stream things
62
59
  return load_server_data({
63
60
  event: new_event,
64
- event_state,
65
61
  state,
66
62
  node,
67
63
  parent: async () => {
@@ -96,31 +92,25 @@ export async function render_data(
96
92
  return fn();
97
93
  });
98
94
 
99
- let length = promises.length;
100
- const nodes = await Promise.all(
101
- promises.map((p, i) =>
102
- p.catch(async (error) => {
95
+ const data_serializer = server_data_serializer_json(event, state, options);
96
+ await Promise.all(
97
+ promises.map(async (p, i) => {
98
+ const node = await p.catch(async (error) => {
103
99
  if (error instanceof Redirect) {
104
100
  throw error;
105
101
  }
106
102
 
107
- // Math.min because array isn't guaranteed to resolve in order
108
- length = Math.min(length, i + 1);
103
+ const transformed = await handle_error_and_jsonify(event, state, options, error);
109
104
 
110
105
  return /** @type {import('types').ServerErrorNode} */ ({
111
106
  type: 'error',
112
- error: await handle_error_and_jsonify(event, event_state, options, error),
113
- status:
114
- error instanceof HttpError || error instanceof SvelteKitError
115
- ? error.status
116
- : undefined
107
+ error: transformed
117
108
  });
118
- })
119
- )
120
- );
109
+ });
121
110
 
122
- const data_serializer = server_data_serializer_json(event, event_state, options);
123
- for (let i = 0; i < nodes.length; i++) data_serializer.add_node(i, nodes[i]);
111
+ data_serializer.add_node(i, node);
112
+ })
113
+ );
124
114
  const { data, chunks } = data_serializer.get_data();
125
115
 
126
116
  if (!chunks) {
@@ -129,26 +119,28 @@ export async function render_data(
129
119
  return json_response(data);
130
120
  }
131
121
 
132
- return new Response(
133
- new ReadableStream({
134
- async start(controller) {
135
- controller.enqueue(text_encoder.encode(data));
136
- for await (const chunk of chunks) {
137
- controller.enqueue(text_encoder.encode(chunk));
122
+ return with_version_header(
123
+ new Response(
124
+ new ReadableStream({
125
+ async start(controller) {
126
+ controller.enqueue(text_encoder.encode(data));
127
+ for await (const chunk of chunks) {
128
+ controller.enqueue(text_encoder.encode(chunk));
129
+ }
130
+ controller.close();
131
+ },
132
+
133
+ type: 'bytes'
134
+ }),
135
+ {
136
+ headers: {
137
+ // we use a proprietary content type to prevent buffering.
138
+ // the `text` prefix makes it inspectable
139
+ 'content-type': 'text/sveltekit-data',
140
+ 'cache-control': 'private, no-store'
138
141
  }
139
- controller.close();
140
- },
141
-
142
- type: 'bytes'
143
- }),
144
- {
145
- headers: {
146
- // we use a proprietary content type to prevent buffering.
147
- // the `text` prefix makes it inspectable
148
- 'content-type': 'text/sveltekit-data',
149
- 'cache-control': 'private, no-store'
150
142
  }
151
- }
143
+ )
152
144
  );
153
145
  } catch (e) {
154
146
  const error = normalize_error(e);
@@ -156,7 +148,8 @@ export async function render_data(
156
148
  if (error instanceof Redirect) {
157
149
  return redirect_json_response(error);
158
150
  } else {
159
- return json_response(await handle_error_and_jsonify(event, event_state, options, error), 500);
151
+ const transformed = await handle_error_and_jsonify(event, state, options, error);
152
+ return json_response(transformed, transformed.status);
160
153
  }
161
154
  }
162
155
  }
@@ -166,13 +159,15 @@ export async function render_data(
166
159
  * @param {number} [status]
167
160
  */
168
161
  function json_response(json, status = 200) {
169
- return text(typeof json === 'string' ? json : JSON.stringify(json), {
170
- status,
171
- headers: {
172
- 'content-type': 'application/json',
173
- 'cache-control': 'private, no-store'
174
- }
175
- });
162
+ return with_version_header(
163
+ text(typeof json === 'string' ? json : JSON.stringify(json), {
164
+ status,
165
+ headers: {
166
+ 'content-type': 'application/json',
167
+ 'cache-control': 'private, no-store'
168
+ }
169
+ })
170
+ );
176
171
  }
177
172
 
178
173
  /**
@@ -182,6 +177,7 @@ export function redirect_json_response(redirect) {
182
177
  return json_response(
183
178
  /** @type {import('types').ServerRedirectNode} */ ({
184
179
  type: 'redirect',
180
+ status: redirect.status,
185
181
  location: redirect.location
186
182
  })
187
183
  );
@@ -0,0 +1,22 @@
1
+ const symbol = Symbol.for('sveltekit.global_state');
2
+ const state = /** @type {Record<symbol, any>} */ (
3
+ /** @type {Record<symbol, unknown>} */ (/** @type {unknown} */ (globalThis))[symbol] ??= {}
4
+ );
5
+
6
+ /**
7
+ * Persist a value across dev server reloads, in case a freshly-invalidated module
8
+ * reads global state that is not set until a request is handled
9
+ * @param {symbol} key
10
+ * @param {any} value
11
+ */
12
+ export function save(key, value) {
13
+ state[key] = value;
14
+ }
15
+
16
+ /**
17
+ * Restore a value after a dev server reload
18
+ * @param {symbol} key
19
+ */
20
+ export function restore(key) {
21
+ return state[key];
22
+ }
@@ -5,13 +5,12 @@ import { negotiate } from '../../utils/http.js';
5
5
  import { method_not_allowed } from './utils.js';
6
6
 
7
7
  /**
8
- * @param {import('@sveltejs/kit').RequestEvent} event
9
- * @param {import('types').RequestState} event_state
8
+ * @param {import('$app/server').RequestEvent} event
9
+ * @param {import('types').RequestState} state
10
10
  * @param {import('types').SSREndpoint} mod
11
- * @param {import('types').SSRState} state
12
11
  * @returns {Promise<Response>}
13
12
  */
14
- export async function render_endpoint(event, event_state, mod, state) {
13
+ export async function render_endpoint(event, state, mod) {
15
14
  const method = /** @type {import('types').HttpMethod} */ (event.request.method);
16
15
 
17
16
  let handler = mod[method] || mod.fallback;
@@ -42,8 +41,8 @@ export async function render_endpoint(event, event_state, mod, state) {
42
41
  }
43
42
 
44
43
  try {
45
- const response = await with_request_store({ event, state: event_state }, () =>
46
- handler(/** @type {import('@sveltejs/kit').RequestEvent<Record<string, any>>} */ (event))
44
+ const response = await with_request_store({ event, state }, () =>
45
+ handler(/** @type {import('$app/server').RequestEvent<Record<string, any>>} */ (event))
47
46
  );
48
47
 
49
48
  if (!(response instanceof Response)) {
@@ -90,7 +89,7 @@ export async function render_endpoint(event, event_state, mod, state) {
90
89
  }
91
90
 
92
91
  /**
93
- * @param {import('@sveltejs/kit').RequestEvent} event
92
+ * @param {import('$app/server').RequestEvent} event
94
93
  */
95
94
  export function is_endpoint_request(event) {
96
95
  const { method, headers } = event.request;
@@ -16,7 +16,6 @@ let headers;
16
16
  */
17
17
  export function get_public_env(request) {
18
18
  const env = rendered_env;
19
- const script = request.url.endsWith('.script.js');
20
19
 
21
20
  payload ??= devalue.uneval(env);
22
21
  etag ??= `W/${Date.now()}`;
@@ -29,9 +28,5 @@ export function get_public_env(request) {
29
28
  return new Response(undefined, { status: 304, headers });
30
29
  }
31
30
 
32
- if (script) {
33
- return new Response(`globalThis.__sveltekit_sw={env:${payload}}`, { headers });
34
- }
35
-
36
31
  return new Response(`export const env=${payload}`, { headers });
37
32
  }