@sveltejs/kit 1.0.0-next.476 → 1.0.0-next.477

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.0.0-next.476",
3
+ "version": "1.0.0-next.477",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -2,7 +2,7 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
- <title>%sveltekit.message%</title>
5
+ <title>%sveltekit.error.message%</title>
6
6
 
7
7
  <style>
8
8
  body {
@@ -49,7 +49,7 @@
49
49
  <div class="error">
50
50
  <span class="status">%sveltekit.status%</span>
51
51
  <div class="message">
52
- <h1>%sveltekit.message%</h1>
52
+ <h1>%sveltekit.error.message%</h1>
53
53
  </div>
54
54
  </div>
55
55
  </body>
@@ -77,8 +77,13 @@ function process_config(config, { cwd = process.cwd() } = {}) {
77
77
  // TODO remove for 1.0
78
78
  if (key === 'template') continue;
79
79
 
80
- // @ts-expect-error this is typescript at its stupidest
81
- validated.kit.files[key] = path.resolve(cwd, validated.kit.files[key]);
80
+ if (key === 'hooks') {
81
+ validated.kit.files.hooks.client = path.resolve(cwd, validated.kit.files.hooks.client);
82
+ validated.kit.files.hooks.server = path.resolve(cwd, validated.kit.files.hooks.server);
83
+ } else {
84
+ // @ts-expect-error
85
+ validated.kit.files[key] = path.resolve(cwd, validated.kit.files[key]);
86
+ }
82
87
  }
83
88
 
84
89
  if (!fs.existsSync(validated.kit.files.errorTemplate)) {
@@ -141,7 +141,19 @@ const options = object(
141
141
 
142
142
  files: object({
143
143
  assets: string('static'),
144
- hooks: string(join('src', 'hooks')),
144
+ hooks: (input, keypath) => {
145
+ // TODO remove this for the 1.0 release
146
+ if (typeof input === 'string') {
147
+ throw new Error(
148
+ `${keypath} is an object with { server: string, client: string } now. See the PR for more information: https://github.com/sveltejs/kit/pull/6586`
149
+ );
150
+ }
151
+
152
+ return object({
153
+ client: string(join('src', 'hooks.client')),
154
+ server: string(join('src', 'hooks.server'))
155
+ })(input, keypath);
156
+ },
145
157
  lib: string(join('src', 'lib')),
146
158
  params: string(join('src', 'params')),
147
159
  routes: string(join('src', 'routes')),
@@ -26,7 +26,7 @@ export async function create(config) {
26
26
 
27
27
  const output = path.join(config.kit.outDir, 'generated');
28
28
 
29
- write_client_manifest(manifest_data, output);
29
+ write_client_manifest(config, manifest_data, output);
30
30
  write_root(manifest_data, output);
31
31
  write_matchers(manifest_data, output);
32
32
  await write_all_types(config, manifest_data);
@@ -1,14 +1,16 @@
1
1
  import { relative } from 'path';
2
+ import { posixify, resolve_entry } from '../../utils/filesystem.js';
2
3
  import { s } from '../../utils/misc.js';
3
4
  import { trim, write_if_changed } from './utils.js';
4
5
 
5
6
  /**
6
7
  * Writes the client manifest to disk. The manifest is used to power the router. It contains the
7
8
  * list of routes and corresponding Svelte components (i.e. pages and layouts).
9
+ * @param {import('types').ValidatedConfig} config
8
10
  * @param {import('types').ManifestData} manifest_data
9
11
  * @param {string} output
10
12
  */
11
- export function write_client_manifest(manifest_data, output) {
13
+ export function write_client_manifest(config, manifest_data, output) {
12
14
  /**
13
15
  * Creates a module that exports a `CSRPageNode`
14
16
  * @param {import('types').PageNode} node
@@ -78,10 +80,14 @@ export function write_client_manifest(manifest_data, output) {
78
80
  .join(',\n\t\t')}
79
81
  }`.replace(/^\t/gm, '');
80
82
 
83
+ const hooks_file = resolve_entry(config.kit.files.hooks.client);
84
+
81
85
  // String representation of __GENERATED__/client-manifest.js
82
86
  write_if_changed(
83
87
  `${output}/client-manifest.js`,
84
88
  trim(`
89
+ ${hooks_file ? `import * as client_hooks from '${posixify(relative(output, hooks_file))}';` : ''}
90
+
85
91
  export { matchers } from './client-matchers.js';
86
92
 
87
93
  export const nodes = [${nodes}];
@@ -89,6 +95,12 @@ export function write_client_manifest(manifest_data, output) {
89
95
  export const server_loads = [${[...layouts_with_server_load].join(',')}];
90
96
 
91
97
  export const dictionary = ${dictionary};
98
+
99
+ export const hooks = {
100
+ handleError: ${
101
+ hooks_file ? 'client_hooks.handleError || ' : ''
102
+ }(({ error }) => { console.error(error); return { message: 'Internal Error' }; }),
103
+ };
92
104
  `)
93
105
  );
94
106
  }
@@ -1,22 +1,17 @@
1
1
  import { HttpError, Redirect, ValidationError } from '../runtime/control.js';
2
2
 
3
+ // For some reason we need to type the params as well here,
4
+ // JSdoc doesn't seem to like @type with function overloads
3
5
  /**
4
- * Creates an `HttpError` object with an HTTP status code and an optional message.
5
- * This object, if thrown during request handling, will cause SvelteKit to
6
- * return an error response without invoking `handleError`
6
+ * @type {import('@sveltejs/kit').error}
7
7
  * @param {number} status
8
- * @param {string | undefined} [message]
8
+ * @param {any} message
9
9
  */
10
10
  export function error(status, message) {
11
11
  return new HttpError(status, message);
12
12
  }
13
13
 
14
- /**
15
- * Creates a `Redirect` object. If thrown during request handling, SvelteKit will
16
- * return a redirect response.
17
- * @param {number} status
18
- * @param {string} location
19
- */
14
+ /** @type {import('@sveltejs/kit').redirect} */
20
15
  export function redirect(status, location) {
21
16
  if (isNaN(status) || status < 300 || status > 399) {
22
17
  throw new Error('Invalid status code');
@@ -25,11 +20,7 @@ export function redirect(status, location) {
25
20
  return new Redirect(status, location);
26
21
  }
27
22
 
28
- /**
29
- * Generates a JSON `Response` object from the supplied data.
30
- * @param {any} data
31
- * @param {ResponseInit} [init]
32
- */
23
+ /** @type {import('@sveltejs/kit').json} */
33
24
  export function json(data, init) {
34
25
  // TODO deprecate this in favour of `Response.json` when it's
35
26
  // more widely supported
@@ -1,7 +1,7 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { mkdirp, posixify } from '../../../utils/filesystem.js';
4
- import { get_vite_config, merge_vite_configs, resolve_entry } from '../utils.js';
3
+ import { mkdirp, posixify, resolve_entry } from '../../../utils/filesystem.js';
4
+ import { get_vite_config, merge_vite_configs } from '../utils.js';
5
5
  import { load_error_page, load_template } from '../../../core/config/index.js';
6
6
  import { runtime_directory } from '../../../core/utils.js';
7
7
  import { create_build, find_deps, get_default_build_config, is_http_method } from './utils.js';
@@ -33,7 +33,7 @@ const app_template = ({ head, body, assets, nonce }) => ${s(template)
33
33
 
34
34
  const error_template = ({ status, message }) => ${s(error_page)
35
35
  .replace(/%sveltekit\.status%/g, '" + status + "')
36
- .replace(/%sveltekit\.message%/g, '" + message + "')};
36
+ .replace(/%sveltekit\.error\.message%/g, '" + message + "')};
37
37
 
38
38
  let read = null;
39
39
 
@@ -58,9 +58,8 @@ export class Server {
58
58
  check_origin: ${s(config.kit.csrf.checkOrigin)},
59
59
  },
60
60
  dev: false,
61
- get_stack: error => String(error), // for security
62
61
  handle_error: (error, event) => {
63
- this.options.hooks.handleError({
62
+ return this.options.hooks.handleError({
64
63
  error,
65
64
  event,
66
65
 
@@ -69,8 +68,7 @@ export class Server {
69
68
  get request() {
70
69
  throw new Error('request in handleError has been replaced with event. See https://github.com/sveltejs/kit/pull/3384 for details');
71
70
  }
72
- });
73
- error.stack = this.options.get_stack(error);
71
+ }) ?? { message: 'Internal Error' };
74
72
  },
75
73
  hooks: null,
76
74
  manifest,
@@ -158,7 +156,24 @@ export async function build_server(options, client) {
158
156
  service_worker_entry_file
159
157
  } = options;
160
158
 
161
- let hooks_file = resolve_entry(config.kit.files.hooks);
159
+ let hooks_file = resolve_entry(config.kit.files.hooks.server);
160
+
161
+ // TODO remove for 1.0
162
+ if (!hooks_file) {
163
+ const old_file = resolve_entry(path.join(process.cwd(), 'src', 'hooks'));
164
+ if (old_file && fs.existsSync(old_file)) {
165
+ throw new Error(
166
+ `Rename your server hook file from ${posixify(
167
+ path.relative(process.cwd(), old_file)
168
+ )} to ${posixify(
169
+ path.relative(process.cwd(), config.kit.files.hooks.server)
170
+ )}${path.extname(
171
+ old_file
172
+ )} (because there's also client hooks now). See the PR for more information: https://github.com/sveltejs/kit/pull/6586`
173
+ );
174
+ }
175
+ }
176
+
162
177
  if (!hooks_file || !fs.existsSync(hooks_file)) {
163
178
  hooks_file = path.join(config.kit.outDir, 'build/hooks.js');
164
179
  fs.writeFileSync(hooks_file, '');
@@ -6,12 +6,12 @@ import { URL } from 'url';
6
6
  import { getRequest, setResponse } from '../../../exports/node/index.js';
7
7
  import { installPolyfills } from '../../../exports/node/polyfills.js';
8
8
  import { coalesce_to_error } from '../../../utils/error.js';
9
- import { posixify } from '../../../utils/filesystem.js';
9
+ import { posixify, resolve_entry } from '../../../utils/filesystem.js';
10
10
  import { load_error_page, load_template } from '../../../core/config/index.js';
11
11
  import { SVELTE_KIT_ASSETS } from '../../../constants.js';
12
12
  import * as sync from '../../../core/sync/sync.js';
13
13
  import { get_mime_lookup, runtime_base, runtime_prefix } from '../../../core/utils.js';
14
- import { prevent_illegal_vite_imports, resolve_entry } from '../utils.js';
14
+ import { prevent_illegal_vite_imports } from '../utils.js';
15
15
  import { compact } from '../../../utils/array.js';
16
16
  import { normalizePath } from 'vite';
17
17
 
@@ -311,11 +311,28 @@ export async function dev(vite, vite_config, svelte_config) {
311
311
  );
312
312
  }
313
313
 
314
- /** @type {Partial<import('types').Hooks>} */
315
- const user_hooks = resolve_entry(svelte_config.kit.files.hooks)
316
- ? await vite.ssrLoadModule(`/${svelte_config.kit.files.hooks}`)
314
+ const hooks_file = svelte_config.kit.files.hooks.server;
315
+ /** @type {Partial<import('types').ServerHooks>} */
316
+ const user_hooks = resolve_entry(hooks_file)
317
+ ? await vite.ssrLoadModule(`/${hooks_file}`)
317
318
  : {};
318
319
 
320
+ // TODO remove for 1.0
321
+ if (!resolve_entry(hooks_file)) {
322
+ const old_file = resolve_entry(path.join(process.cwd(), 'src', 'hooks'));
323
+ if (old_file && fs.existsSync(old_file)) {
324
+ throw new Error(
325
+ `Rename your server hook file from ${posixify(
326
+ path.relative(process.cwd(), old_file)
327
+ )} to ${posixify(
328
+ path.relative(process.cwd(), svelte_config.kit.files.hooks.server)
329
+ )}${path.extname(
330
+ old_file
331
+ )} (because there's also client hooks now). See the PR for more information: https://github.com/sveltejs/kit/pull/6586`
332
+ );
333
+ }
334
+ }
335
+
319
336
  const handle = user_hooks.handle || (({ event, resolve }) => resolve(event));
320
337
 
321
338
  // TODO remove for 1.0
@@ -326,12 +343,13 @@ export async function dev(vite, vite_config, svelte_config) {
326
343
  );
327
344
  }
328
345
 
329
- /** @type {import('types').Hooks} */
346
+ /** @type {import('types').ServerHooks} */
330
347
  const hooks = {
331
348
  handle,
332
349
  handleError:
333
350
  user_hooks.handleError ||
334
- (({ /** @type {Error & { frame?: string }} */ error }) => {
351
+ (({ error: e }) => {
352
+ const error = /** @type {Error & { frame?: string }} */ (e);
335
353
  console.error(colors.bold().red(error.message));
336
354
  if (error.frame) {
337
355
  console.error(colors.gray(error.frame));
@@ -390,28 +408,29 @@ export async function dev(vite, vite_config, svelte_config) {
390
408
  check_origin: svelte_config.kit.csrf.checkOrigin
391
409
  },
392
410
  dev: true,
393
- get_stack: (error) => fix_stack_trace(error),
394
411
  handle_error: (error, event) => {
395
- hooks.handleError({
396
- error: new Proxy(error, {
397
- get: (target, property) => {
398
- if (property === 'stack') {
399
- return fix_stack_trace(error);
412
+ return (
413
+ hooks.handleError({
414
+ error: new Proxy(error, {
415
+ get: (target, property) => {
416
+ if (property === 'stack') {
417
+ return fix_stack_trace(error);
418
+ }
419
+
420
+ return Reflect.get(target, property, target);
400
421
  }
401
-
402
- return Reflect.get(target, property, target);
422
+ }),
423
+ event,
424
+
425
+ // TODO remove for 1.0
426
+ // @ts-expect-error
427
+ get request() {
428
+ throw new Error(
429
+ 'request in handleError has been replaced with event. See https://github.com/sveltejs/kit/pull/3384 for details'
430
+ );
403
431
  }
404
- }),
405
- event,
406
-
407
- // TODO remove for 1.0
408
- // @ts-expect-error
409
- get request() {
410
- throw new Error(
411
- 'request in handleError has been replaced with event. See https://github.com/sveltejs/kit/pull/3384 for details'
412
- );
413
- }
414
- });
432
+ }) ?? { message: 'Internal Error' }
433
+ );
415
434
  },
416
435
  hooks,
417
436
  manifest,
@@ -436,7 +455,7 @@ export async function dev(vite, vite_config, svelte_config) {
436
455
  error_template: ({ status, message }) => {
437
456
  return error_page
438
457
  .replace(/%sveltekit\.status%/g, String(status))
439
- .replace(/%sveltekit\.message%/g, message);
458
+ .replace(/%sveltekit\.error\.message%/g, message);
440
459
  },
441
460
  trailing_slash: svelte_config.kit.trailingSlash
442
461
  },
@@ -4,7 +4,7 @@ import path from 'node:path';
4
4
  import colors from 'kleur';
5
5
  import { svelte } from '@sveltejs/vite-plugin-svelte';
6
6
  import * as vite from 'vite';
7
- import { mkdirp, posixify, rimraf } from '../../utils/filesystem.js';
7
+ import { mkdirp, posixify, resolve_entry, rimraf } from '../../utils/filesystem.js';
8
8
  import * as sync from '../../core/sync/sync.js';
9
9
  import { build_server } from './build/build_server.js';
10
10
  import { build_service_worker } from './build/build_service_worker.js';
@@ -14,7 +14,7 @@ import { generate_manifest } from '../../core/generate_manifest/index.js';
14
14
  import { runtime_directory, logger } from '../../core/utils.js';
15
15
  import { find_deps, get_default_build_config } from './build/utils.js';
16
16
  import { preview } from './preview/index.js';
17
- import { get_aliases, resolve_entry, prevent_illegal_rollup_imports, get_env } from './utils.js';
17
+ import { get_aliases, prevent_illegal_rollup_imports, get_env } from './utils.js';
18
18
  import { fileURLToPath } from 'node:url';
19
19
  import { create_static_module, create_dynamic_module } from '../../core/env.js';
20
20
 
@@ -220,6 +220,21 @@ function kit() {
220
220
  return new_config;
221
221
  }
222
222
 
223
+ const allow = new Set([
224
+ svelte_config.kit.files.lib,
225
+ svelte_config.kit.files.routes,
226
+ svelte_config.kit.outDir,
227
+ path.resolve(cwd, 'src'), // TODO this isn't correct if user changed all his files to sth else than src (like in test/options)
228
+ path.resolve(cwd, 'node_modules'),
229
+ path.resolve(vite.searchForWorkspaceRoot(cwd), 'node_modules')
230
+ ]);
231
+ // We can only add directories to the allow list, so we find out
232
+ // if there's a client hooks file and pass its directory
233
+ const client_hooks = resolve_entry(svelte_config.kit.files.hooks.client);
234
+ if (client_hooks) {
235
+ allow.add(path.dirname(client_hooks));
236
+ }
237
+
223
238
  // dev and preview config can be shared
224
239
  /** @type {import('vite').UserConfig} */
225
240
  const result = {
@@ -243,16 +258,7 @@ function kit() {
243
258
  root: cwd,
244
259
  server: {
245
260
  fs: {
246
- allow: [
247
- ...new Set([
248
- svelte_config.kit.files.lib,
249
- svelte_config.kit.files.routes,
250
- svelte_config.kit.outDir,
251
- path.resolve(cwd, 'src'),
252
- path.resolve(cwd, 'node_modules'),
253
- path.resolve(vite.searchForWorkspaceRoot(cwd), 'node_modules')
254
- ])
255
- ]
261
+ allow: [...allow]
256
262
  },
257
263
  watch: {
258
264
  ignored: [