@sveltejs/kit 1.6.0 → 1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -106,8 +106,8 @@ async function analyse({ manifest_path, env }) {
106
106
 
107
107
  for (const layout of layouts) {
108
108
  if (layout) {
109
- validate_common_exports(layout.server, route.id);
110
- validate_common_exports(layout.universal, route.id);
109
+ validate_common_exports(layout.server, layout.server_id);
110
+ validate_common_exports(layout.universal, layout.universal_id);
111
111
  }
112
112
  }
113
113
 
@@ -115,8 +115,8 @@ async function analyse({ manifest_path, env }) {
115
115
  methods.add('GET');
116
116
  if (page.server?.actions) methods.add('POST');
117
117
 
118
- validate_page_server_exports(page.server, route.id);
119
- validate_common_exports(page.universal, route.id);
118
+ validate_page_server_exports(page.server, page.server_id);
119
+ validate_common_exports(page.universal, page.universal_id);
120
120
  }
121
121
 
122
122
  const should_prerender = get_option(nodes, 'prerender');
@@ -4,7 +4,7 @@ import { pathToFileURL } from 'node:url';
4
4
  import { installPolyfills } from '../../exports/node/polyfills.js';
5
5
  import { mkdirp, posixify, walk } from '../../utils/filesystem.js';
6
6
  import { should_polyfill } from '../../utils/platform.js';
7
- import { is_root_relative, resolve } from '../../utils/url.js';
7
+ import { decode_uri, is_root_relative, resolve } from '../../utils/url.js';
8
8
  import { escape_html_attr } from '../../utils/escape.js';
9
9
  import { logger } from '../utils.js';
10
10
  import { load_config } from '../config/index.js';
@@ -207,7 +207,7 @@ async function prerender({ out, manifest_path, metadata, verbose, env }) {
207
207
  // this seems circuitous, but using new URL allows us to not care
208
208
  // whether dependency_path is encoded or not
209
209
  const encoded_dependency_path = new URL(dependency_path, 'http://localhost').pathname;
210
- const decoded_dependency_path = decodeURI(encoded_dependency_path);
210
+ const decoded_dependency_path = decode_uri(encoded_dependency_path);
211
211
 
212
212
  const headers = Object.fromEntries(result.response.headers);
213
213
 
@@ -215,7 +215,7 @@ async function prerender({ out, manifest_path, metadata, verbose, env }) {
215
215
  if (prerender) {
216
216
  const encoded_route_id = headers['x-sveltekit-routeid'];
217
217
  if (encoded_route_id != null) {
218
- const route_id = decodeURI(encoded_route_id);
218
+ const route_id = decode_uri(encoded_route_id);
219
219
  const existing_value = prerender_map.get(route_id);
220
220
  if (existing_value !== 'auto') {
221
221
  prerender_map.set(route_id, prerender === 'true' ? true : 'auto');
@@ -257,7 +257,7 @@ async function prerender({ out, manifest_path, metadata, verbose, env }) {
257
257
  }
258
258
 
259
259
  if (hash) {
260
- const key = decodeURI(pathname + hash);
260
+ const key = decode_uri(pathname + hash);
261
261
 
262
262
  if (!expected_hashlinks.has(key)) {
263
263
  expected_hashlinks.set(key, new Set());
@@ -266,7 +266,7 @@ async function prerender({ out, manifest_path, metadata, verbose, env }) {
266
266
  /** @type {Set<string>} */ (expected_hashlinks.get(key)).add(decoded);
267
267
  }
268
268
 
269
- enqueue(decoded, decodeURI(pathname), pathname);
269
+ enqueue(decoded, decode_uri(pathname), pathname);
270
270
  }
271
271
  }
272
272
  }
@@ -293,7 +293,7 @@ async function prerender({ out, manifest_path, metadata, verbose, env }) {
293
293
  if (written.has(file)) return;
294
294
 
295
295
  const encoded_route_id = response.headers.get('x-sveltekit-routeid');
296
- const route_id = encoded_route_id != null ? decodeURI(encoded_route_id) : null;
296
+ const route_id = encoded_route_id != null ? decode_uri(encoded_route_id) : null;
297
297
  if (route_id !== null) prerendered_routes.add(route_id);
298
298
 
299
299
  if (response_type === REDIRECT) {
@@ -302,7 +302,7 @@ async function prerender({ out, manifest_path, metadata, verbose, env }) {
302
302
  if (location) {
303
303
  const resolved = resolve(encoded, location);
304
304
  if (is_root_relative(resolved)) {
305
- enqueue(decoded, decodeURI(resolved), resolved);
305
+ enqueue(decoded, decode_uri(resolved), resolved);
306
306
  }
307
307
 
308
308
  if (!headers['x-sveltekit-normalize']) {
@@ -73,11 +73,13 @@ export function build_server_nodes(out, kit, manifest_data, server_manifest, cli
73
73
 
74
74
  imports.push(`import * as universal from '../${server_manifest[node.universal].file}';`);
75
75
  exports.push(`export { universal };`);
76
+ exports.push(`export const universal_id = ${s(node.universal)};`);
76
77
  }
77
78
 
78
79
  if (node.server) {
79
80
  imports.push(`import * as server from '../${server_manifest[node.server].file}';`);
80
81
  exports.push(`export { server };`);
82
+ exports.push(`export const server_id = ${s(node.server)};`);
81
83
  }
82
84
 
83
85
  exports.push(
@@ -6,36 +6,52 @@ function validator(expected) {
6
6
 
7
7
  /**
8
8
  * @param {any} module
9
- * @param {string} [route_id]
9
+ * @param {string} [file]
10
10
  */
11
- function validate(module, route_id) {
11
+ function validate(module, file) {
12
12
  if (!module) return;
13
13
 
14
14
  for (const key in module) {
15
- if (key[0] !== '_' && !set.has(key)) {
16
- const valid = expected.join(', ');
17
- throw new Error(
18
- `Invalid export '${key}'${
19
- route_id ? ` in ${route_id}` : ''
20
- } (valid exports are ${valid}, or anything with a '_' prefix)`
21
- );
22
- }
15
+ if (key[0] === '_' || set.has(key)) continue; // key is valid in this module
16
+
17
+ const hint =
18
+ hint_for_supported_files(key, file?.slice(file.lastIndexOf('.'))) ??
19
+ `valid exports are ${expected.join(', ')}, or anything with a '_' prefix`;
20
+
21
+ throw new Error(`Invalid export '${key}'${file ? ` in ${file}` : ''} (${hint})`);
23
22
  }
24
23
  }
25
24
 
26
25
  return validate;
27
26
  }
28
27
 
29
- export const validate_common_exports = validator([
30
- 'load',
31
- 'prerender',
32
- 'csr',
33
- 'ssr',
34
- 'trailingSlash',
35
- 'config'
36
- ]);
28
+ /**
29
+ * @param {string} key
30
+ * @param {string} ext
31
+ * @returns {string | void}
32
+ */
33
+ function hint_for_supported_files(key, ext = '.js') {
34
+ let supported_files = [];
37
35
 
38
- export const validate_page_server_exports = validator([
36
+ if (valid_common_exports.includes(key)) {
37
+ supported_files.push(`+page${ext}`);
38
+ }
39
+
40
+ if (valid_page_server_exports.includes(key)) {
41
+ supported_files.push(`+page.server${ext}`);
42
+ }
43
+
44
+ if (valid_server_exports.includes(key)) {
45
+ supported_files.push(`+server${ext}`);
46
+ }
47
+
48
+ if (supported_files.length > 0) {
49
+ return `'${key}' is a valid export in ${supported_files.join(` or `)}`;
50
+ }
51
+ }
52
+
53
+ const valid_common_exports = ['load', 'prerender', 'csr', 'ssr', 'trailingSlash', 'config'];
54
+ const valid_page_server_exports = [
39
55
  'load',
40
56
  'prerender',
41
57
  'csr',
@@ -43,9 +59,8 @@ export const validate_page_server_exports = validator([
43
59
  'actions',
44
60
  'trailingSlash',
45
61
  'config'
46
- ]);
47
-
48
- export const validate_server_exports = validator([
62
+ ];
63
+ const valid_server_exports = [
49
64
  'GET',
50
65
  'POST',
51
66
  'PATCH',
@@ -55,4 +70,8 @@ export const validate_server_exports = validator([
55
70
  'prerender',
56
71
  'trailingSlash',
57
72
  'config'
58
- ]);
73
+ ];
74
+
75
+ export const validate_common_exports = validator(valid_common_exports);
76
+ export const validate_page_server_exports = validator(valid_page_server_exports);
77
+ export const validate_server_exports = validator(valid_server_exports);
package/src/utils/url.js CHANGED
@@ -75,6 +75,21 @@ export function decode_params(params) {
75
75
  return params;
76
76
  }
77
77
 
78
+ /**
79
+ * The error when a URL is malformed is not very helpful, so we augment it with the URI
80
+ * @param {string} uri
81
+ */
82
+ export function decode_uri(uri) {
83
+ try {
84
+ return decodeURI(uri);
85
+ } catch (e) {
86
+ if (e instanceof Error) {
87
+ e.message = `Failed to decode URI: ${uri}\n` + e.message;
88
+ }
89
+ throw e;
90
+ }
91
+ }
92
+
78
93
  /**
79
94
  * URL properties that could change during the lifetime of the page,
80
95
  * which excludes things like `origin`
@@ -293,9 +293,8 @@ export interface SSRNode {
293
293
  config?: any;
294
294
  };
295
295
 
296
- // store this in dev so we can print serialization errors
297
- universal_id?: string;
298
- server_id?: string;
296
+ universal_id: string;
297
+ server_id: string;
299
298
  }
300
299
 
301
300
  export type SSRNodeLoader = () => Promise<SSRNode>;