@sveltejs/kit 1.3.5 → 1.3.7

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.3.5",
3
+ "version": "1.3.7",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -32,6 +32,8 @@
32
32
  "@types/node": "^16.18.6",
33
33
  "@types/sade": "^1.7.4",
34
34
  "@types/set-cookie-parser": "^2.4.2",
35
+ "eslint": "^8.33.0",
36
+ "eslint-plugin-unicorn": "^45.0.2",
35
37
  "marked": "^4.2.3",
36
38
  "rollup": "^3.7.0",
37
39
  "svelte": "^3.55.1",
@@ -80,7 +82,7 @@
80
82
  "node": "^16.14 || >=18"
81
83
  },
82
84
  "scripts": {
83
- "lint": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore",
85
+ "lint": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore && eslint src/**",
84
86
  "check": "tsc",
85
87
  "check:all": "tsc && pnpm -r --filter=\"./**\" check",
86
88
  "format": "pnpm lint --write",
package/src/cli.js CHANGED
@@ -1,5 +1,5 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
  import colors from 'kleur';
4
4
  import sade from 'sade';
5
5
  import { load_config } from './core/config/index.js';
@@ -1,10 +1,10 @@
1
+ import { fork } from 'node:child_process';
1
2
  import { existsSync, statSync, createReadStream, createWriteStream } from 'node:fs';
2
3
  import { pipeline } from 'node:stream';
3
- import { promisify } from 'node:util';
4
- import { fork } from 'node:child_process';
5
4
  import { fileURLToPath } from 'node:url';
5
+ import { promisify } from 'node:util';
6
+ import zlib from 'node:zlib';
6
7
  import glob from 'tiny-glob';
7
- import zlib from 'zlib';
8
8
  import { copy, rimraf, mkdirp } from '../../utils/filesystem.js';
9
9
  import { generate_manifest } from '../generate_manifest/index.js';
10
10
  import { get_route_segments } from '../../utils/routing.js';
@@ -1,6 +1,6 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import * as url from 'url';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import * as url from 'node:url';
4
4
  import options from './options.js';
5
5
 
6
6
  /**
@@ -1,4 +1,4 @@
1
- import { join } from 'path';
1
+ import { join } from 'node:path';
2
2
 
3
3
  /** @typedef {import('./types').Validator} Validator */
4
4
 
@@ -1,5 +1,5 @@
1
- import { join } from 'path';
2
- import { pathToFileURL } from 'url';
1
+ import { join } from 'node:path';
2
+ import { pathToFileURL } from 'node:url';
3
3
  import { get_option } from '../../runtime/server/utils.js';
4
4
  import {
5
5
  validate_common_exports,
@@ -1,6 +1,6 @@
1
- import { readFileSync, writeFileSync } from 'fs';
2
- import { dirname, join } from 'path';
3
- import { pathToFileURL } from 'url';
1
+ import { readFileSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
4
  import { mkdirp } from '../../utils/filesystem.js';
5
5
  import { installPolyfills } from '../../exports/node/polyfills.js';
6
6
  import { load_config } from '../config/index.js';
@@ -361,6 +361,15 @@ async function prerender({ out, manifest_path, metadata, verbose, env }) {
361
361
  saved.set(file, dest);
362
362
  }
363
363
 
364
+ if (
365
+ config.prerender.entries.length > 1 ||
366
+ config.prerender.entries[0] !== '*' ||
367
+ prerender_map.size > 0
368
+ ) {
369
+ // Only log if we're actually going to do something to not confuse users
370
+ log.info('Prerendering');
371
+ }
372
+
364
373
  for (const entry of config.prerender.entries) {
365
374
  if (entry === '*') {
366
375
  for (const [id, prerender] of prerender_map) {
@@ -1,5 +1,5 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
  import mime from 'mime';
4
4
  import { runtime_directory } from '../../utils.js';
5
5
  import { posixify } from '../../../utils/filesystem.js';
@@ -1,4 +1,4 @@
1
- import path from 'path';
1
+ import path from 'node:path';
2
2
  import create_manifest_data from './create_manifest_data/index.js';
3
3
  import { write_client_manifest } from './write_client_manifest.js';
4
4
  import { write_root } from './write_root.js';
@@ -1,5 +1,5 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
  import { mkdirp } from '../../utils/filesystem.js';
4
4
 
5
5
  /** @type {Map<string, string>} */
@@ -1,10 +1,10 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
3
4
  import { get_env } from '../../exports/vite/utils.js';
4
5
  import { GENERATED_COMMENT } from '../../constants.js';
5
6
  import { create_dynamic_types, create_static_types } from '../env.js';
6
7
  import { write_if_changed } from './utils.js';
7
- import { fileURLToPath } from 'url';
8
8
 
9
9
  // TODO these types should be described in a neutral place, rather than
10
10
  // inside either `packages/kit` or `kit.svelte.dev`
@@ -1,5 +1,5 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
  import colors from 'kleur';
4
4
  import { posixify } from '../../utils/filesystem.js';
5
5
  import { write_if_changed } from './utils.js';
@@ -1,5 +1,5 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
  import MagicString from 'magic-string';
4
4
  import { posixify, rimraf, walk } from '../../../utils/filesystem.js';
5
5
  import { compact } from '../../../utils/array.js';
package/src/core/utils.js CHANGED
@@ -1,6 +1,6 @@
1
- import path from 'path';
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
2
3
  import colors from 'kleur';
3
- import { fileURLToPath } from 'url';
4
4
  import { posixify, to_fs } from '../utils/filesystem.js';
5
5
 
6
6
  /**
@@ -1,6 +1,6 @@
1
+ import { ReadableStream, TransformStream, WritableStream } from 'node:stream/web';
2
+ import { webcrypto as crypto } from 'node:crypto';
1
3
  import { fetch, Response, Request, Headers, FormData } from 'undici';
2
- import { ReadableStream, TransformStream, WritableStream } from 'stream/web';
3
- import { webcrypto as crypto } from 'crypto';
4
4
 
5
5
  /** @type {Record<string, any>} */
6
6
  const globals = {
@@ -1,4 +1,4 @@
1
- import fs from 'fs';
1
+ import fs from 'node:fs';
2
2
  import * as vite from 'vite';
3
3
  import { s } from '../../../utils/misc.js';
4
4
  import { get_config_aliases } from '../utils.js';
@@ -1,8 +1,8 @@
1
- import fs from 'fs';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { URL } from 'node:url';
2
4
  import colors from 'kleur';
3
- import path from 'path';
4
5
  import sirv from 'sirv';
5
- import { URL } from 'url';
6
6
  import { isCSSRequest, loadEnv } from 'vite';
7
7
  import { getRequest, setResponse } from '../../../exports/node/index.js';
8
8
  import { installPolyfills } from '../../../exports/node/polyfills.js';
@@ -1,4 +1,4 @@
1
- import path from 'path';
1
+ import path from 'node:path';
2
2
  import { posixify } from '../../../utils/filesystem.js';
3
3
 
4
4
  const ILLEGAL_IMPORTS = new Set(['\0$env/dynamic/private', '\0$env/static/private']);
@@ -139,10 +139,7 @@ export async function sveltekit() {
139
139
  return [...svelte(vite_plugin_svelte_options), ...kit({ svelte_config })];
140
140
  }
141
141
 
142
- /**
143
- * If `true`, the server build has been completed and we're creating the client build
144
- */
145
- let secondary_build = false;
142
+ let secondary_build_started = false;
146
143
 
147
144
  /**
148
145
  * Returns the SvelteKit Vite plugin. Vite executes Rollup hooks as well as some of its own.
@@ -176,8 +173,8 @@ function kit({ svelte_config }) {
176
173
  /** @type {{ public: Record<string, string>; private: Record<string, string> }} */
177
174
  let env;
178
175
 
179
- /** @type {(() => Promise<void>) | null} */
180
- let finalise = null;
176
+ /** @type {() => Promise<void>} */
177
+ let finalise;
181
178
 
182
179
  const service_worker_entry_file = resolve_entry(kit.files.serviceWorker);
183
180
 
@@ -251,7 +248,7 @@ function kit({ svelte_config }) {
251
248
 
252
249
  if (is_build) {
253
250
  if (!new_config.build) new_config.build = {};
254
- new_config.build.ssr = !secondary_build;
251
+ new_config.build.ssr = !secondary_build_started;
255
252
 
256
253
  new_config.define = {
257
254
  __SVELTEKIT_ADAPTER_NAME__: JSON.stringify(kit.adapter?.name),
@@ -363,7 +360,7 @@ function kit({ svelte_config }) {
363
360
  writeBundle: {
364
361
  sequential: true,
365
362
  async handler(_options) {
366
- if (!secondary_build) return;
363
+ if (vite_config.build.ssr) return;
367
364
 
368
365
  const guard = module_guard(this, {
369
366
  cwd: vite.normalizePath(process.cwd()),
@@ -535,10 +532,7 @@ function kit({ svelte_config }) {
535
532
  * Clears the output directories.
536
533
  */
537
534
  buildStart() {
538
- if (secondary_build) return;
539
-
540
- // reset (here, not in `config`, because `build --watch` skips `config`)
541
- finalise = null;
535
+ if (secondary_build_started) return;
542
536
 
543
537
  if (is_build) {
544
538
  if (!vite_config.build.watch) {
@@ -549,7 +543,7 @@ function kit({ svelte_config }) {
549
543
  },
550
544
 
551
545
  generateBundle() {
552
- if (!secondary_build) return;
546
+ if (vite_config.build.ssr) return;
553
547
 
554
548
  this.emitFile({
555
549
  type: 'asset',
@@ -566,8 +560,7 @@ function kit({ svelte_config }) {
566
560
  writeBundle: {
567
561
  sequential: true,
568
562
  async handler(_options) {
569
- if (secondary_build) return; // only run this once
570
- secondary_build = true;
563
+ if (secondary_build_started) return; // only run this once
571
564
 
572
565
  const verbose = vite_config.logLevel === 'info';
573
566
  const log = logger({ verbose });
@@ -596,6 +589,8 @@ function kit({ svelte_config }) {
596
589
  );
597
590
 
598
591
  // first, build server nodes without the client manifest so we can analyse it
592
+ log.info('Analysing routes');
593
+
599
594
  build_server_nodes(out, kit, manifest_data, server_manifest, null, null);
600
595
 
601
596
  const metadata = await analyse({
@@ -603,6 +598,8 @@ function kit({ svelte_config }) {
603
598
  env: { ...env.private, ...env.public }
604
599
  });
605
600
 
601
+ log.info('Building app');
602
+
606
603
  // create client build
607
604
  write_client_manifest(
608
605
  kit,
@@ -611,6 +608,8 @@ function kit({ svelte_config }) {
611
608
  metadata.nodes
612
609
  );
613
610
 
611
+ secondary_build_started = true;
612
+
614
613
  const { output } = /** @type {import('rollup').RollupOutput} */ (
615
614
  await vite.build({
616
615
  configFile: vite_config.configFile,
@@ -649,8 +648,6 @@ function kit({ svelte_config }) {
649
648
  build_server_nodes(out, kit, manifest_data, server_manifest, client_manifest, css);
650
649
 
651
650
  // ...and prerender
652
- log.info('Prerendering');
653
-
654
651
  const { prerendered, prerender_map } = await prerender({
655
652
  out,
656
653
  manifest_path,
@@ -721,7 +718,8 @@ function kit({ svelte_config }) {
721
718
  closeBundle: {
722
719
  sequential: true,
723
720
  async handler() {
724
- finalise?.();
721
+ if (!vite_config.build.ssr) return;
722
+ await finalise();
725
723
  }
726
724
  }
727
725
  };
@@ -1,7 +1,7 @@
1
- import fs from 'fs';
2
- import { join } from 'path';
1
+ import fs from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
3
4
  import sirv from 'sirv';
4
- import { pathToFileURL } from 'url';
5
5
  import { loadEnv, normalizePath } from 'vite';
6
6
  import { getRequest, setResponse } from '../../../exports/node/index.js';
7
7
  import { installPolyfills } from '../../../exports/node/polyfills.js';
@@ -1,4 +1,4 @@
1
- import path from 'path';
1
+ import path from 'node:path';
2
2
  import { loadEnv } from 'vite';
3
3
  import { posixify } from '../../utils/filesystem.js';
4
4
  import { negotiate } from '../../utils/http.js';
@@ -343,7 +343,8 @@ export function create_client({ target, base }) {
343
343
  }
344
344
 
345
345
  if (autoscroll) {
346
- const deep_linked = url.hash && document.querySelector(decodeURIComponent(url.hash));
346
+ const deep_linked =
347
+ url.hash && document.getElementById(decodeURIComponent(url.hash.slice(1)));
347
348
  if (scroll) {
348
349
  scrollTo(scroll.x, scroll.y);
349
350
  } else if (deep_linked) {
@@ -127,8 +127,19 @@ function build_selector(resource, opts) {
127
127
 
128
128
  let selector = `script[data-sveltekit-fetched][data-url=${url}]`;
129
129
 
130
- if (opts?.body && (typeof opts.body === 'string' || ArrayBuffer.isView(opts.body))) {
131
- selector += `[data-hash="${hash(opts.body)}"]`;
130
+ if (opts?.headers || opts?.body) {
131
+ /** @type {import('types').StrictBody[]} */
132
+ const values = [];
133
+
134
+ if (opts.headers) {
135
+ values.push([...new Headers(opts.headers)].join(','));
136
+ }
137
+
138
+ if (opts.body && (typeof opts.body === 'string' || ArrayBuffer.isView(opts.body))) {
139
+ values.push(opts.body);
140
+ }
141
+
142
+ selector += `[data-hash="${hash(...values)}"]`;
132
143
  }
133
144
 
134
145
  return selector;
@@ -1,19 +1,21 @@
1
1
  /**
2
2
  * Hash using djb2
3
- * @param {import('types').StrictBody} value
3
+ * @param {import('types').StrictBody[]} values
4
4
  */
5
- export function hash(value) {
5
+ export function hash(...values) {
6
6
  let hash = 5381;
7
7
 
8
- if (typeof value === 'string') {
9
- let i = value.length;
10
- while (i) hash = (hash * 33) ^ value.charCodeAt(--i);
11
- } else if (ArrayBuffer.isView(value)) {
12
- const buffer = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
13
- let i = buffer.length;
14
- while (i) hash = (hash * 33) ^ buffer[--i];
15
- } else {
16
- throw new TypeError('value must be a string or TypedArray');
8
+ for (const value of values) {
9
+ if (typeof value === 'string') {
10
+ let i = value.length;
11
+ while (i) hash = (hash * 33) ^ value.charCodeAt(--i);
12
+ } else if (ArrayBuffer.isView(value)) {
13
+ const buffer = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
14
+ let i = buffer.length;
15
+ while (i) hash = (hash * 33) ^ buffer[--i];
16
+ } else {
17
+ throw new TypeError('value must be a string or TypedArray');
18
+ }
17
19
  }
18
20
 
19
21
  return (hash >>> 0).toString(36);
@@ -194,6 +194,7 @@ export function create_universal_fetch(event, state, fetched, csr, resolve_opts)
194
194
  ? await stream_to_string(cloned_body)
195
195
  : init?.body
196
196
  ),
197
+ request_headers: init?.headers,
197
198
  response_body: body,
198
199
  response: response
199
200
  });
@@ -73,8 +73,19 @@ export function serialize_data(fetched, filter, prerendering = false) {
73
73
  `data-url=${escape_html_attr(fetched.url)}`
74
74
  ];
75
75
 
76
- if (fetched.request_body) {
77
- attrs.push(`data-hash=${escape_html_attr(hash(fetched.request_body))}`);
76
+ if (fetched.request_headers || fetched.request_body) {
77
+ /** @type {import('types').StrictBody[]} */
78
+ const values = [];
79
+
80
+ if (fetched.request_headers) {
81
+ values.push([...new Headers(fetched.request_headers)].join(','));
82
+ }
83
+
84
+ if (fetched.request_body) {
85
+ values.push(fetched.request_body);
86
+ }
87
+
88
+ attrs.push(`data-hash="${hash(...values)}"`);
78
89
  }
79
90
 
80
91
  // Compute the time the response should be cached, taking into account max-age and age.
@@ -5,6 +5,7 @@ export interface Fetched {
5
5
  url: string;
6
6
  method: string;
7
7
  request_body?: string | ArrayBufferView | null;
8
+ request_headers?: HeadersInit | undefined;
8
9
  response_body: string;
9
10
  response: Response;
10
11
  }
@@ -1,5 +1,5 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
3
 
4
4
  /** @param {string} dir */
5
5
  export function mkdirp(dir) {
@@ -126,57 +126,44 @@ export function exec(match, params, matchers) {
126
126
 
127
127
  const values = match.slice(1);
128
128
 
129
- let buffered = '';
129
+ let buffered = 0;
130
130
 
131
131
  for (let i = 0; i < params.length; i += 1) {
132
132
  const param = params[i];
133
- let value = values[i];
133
+ const value = values[i - buffered];
134
134
 
135
+ // in the `[[a=b]]/.../[...rest]` case, if one or more optional parameters
136
+ // weren't matched, roll the skipped values into the rest
135
137
  if (param.chained && param.rest && buffered) {
136
- // in the `[[lang=lang]]/[...rest]` case, if `lang` didn't
137
- // match, we roll it over into the rest value
138
- value = value ? buffered + '/' + value : buffered;
139
- }
138
+ result[param.name] = values
139
+ .slice(i - buffered, i + 1)
140
+ .filter((s) => s)
141
+ .join('/');
140
142
 
141
- buffered = '';
143
+ buffered = 0;
144
+ continue;
145
+ }
142
146
 
147
+ // if `value` is undefined, it means this is an optional or rest parameter
143
148
  if (value === undefined) {
144
- // if `value` is undefined, it means this is
145
- // an optional or rest parameter
146
149
  if (param.rest) result[param.name] = '';
147
- } else {
148
- if (param.matcher && !matchers[param.matcher](value)) {
149
- // in the `/[[a=b]]/[[c=d]]` case, if the value didn't satisfy the `b` matcher,
150
- // try again with the next segment by shifting values rightwards
151
- if (param.optional && param.chained) {
152
- // @ts-expect-error TypeScript is... wrong
153
- let j = values.indexOf(undefined, i);
154
-
155
- if (j === -1) {
156
- // we can't shift values any further, so hang on to this value
157
- // so it can be rolled into a subsequent `[...rest]` param
158
- const next = params[i + 1];
159
- if (next?.rest && next.chained) {
160
- buffered = value;
161
- } else {
162
- return;
163
- }
164
- }
165
-
166
- while (j >= i) {
167
- values[j] = values[j - 1];
168
- j -= 1;
169
- }
170
-
171
- continue;
172
- }
173
-
174
- // otherwise, if the matcher returns `false`, the route did not match
175
- return;
176
- }
150
+ continue;
151
+ }
177
152
 
153
+ if (!param.matcher || matchers[param.matcher](value)) {
178
154
  result[param.name] = value;
155
+ continue;
179
156
  }
157
+
158
+ // in the `/[[a=b]]/...` case, if the value didn't satisfy the matcher,
159
+ // keep track of the number of skipped optional parameters and continue
160
+ if (param.optional && param.chained) {
161
+ buffered++;
162
+ continue;
163
+ }
164
+
165
+ // otherwise, if the matcher returns `false`, the route did not match
166
+ return;
180
167
  }
181
168
 
182
169
  if (buffered) return;