@sveltejs/kit 1.1.3 → 1.2.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.1.3",
3
+ "version": "1.2.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -22,7 +22,7 @@
22
22
  "set-cookie-parser": "^2.5.1",
23
23
  "sirv": "^2.0.2",
24
24
  "tiny-glob": "^0.2.9",
25
- "undici": "5.15.0"
25
+ "undici": "5.15.1"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@playwright/test": "^1.29.2",
@@ -86,6 +86,7 @@
86
86
  "format": "pnpm lint --write",
87
87
  "test": "pnpm test:unit && pnpm test:integration",
88
88
  "test:integration": "pnpm -r --workspace-concurrency 1 --filter=\"./test/**\" test",
89
+ "test:cross-browser": "pnpm -r --workspace-concurrency 1 --filter=\"./test/**\" test:cross-browser",
89
90
  "test:unit": "uvu src \"(spec\\.js|test[\\\\/]index\\.js)\"",
90
91
  "postinstall": "node postinstall.js"
91
92
  }
@@ -9,24 +9,33 @@ import options from './options.js';
9
9
  * @param {string} cwd
10
10
  * @param {import('types').ValidatedConfig} config
11
11
  */
12
- export function load_template(cwd, config) {
13
- const { appTemplate } = config.kit.files;
14
- const relative = path.relative(cwd, appTemplate);
15
-
16
- if (fs.existsSync(appTemplate)) {
17
- const contents = fs.readFileSync(appTemplate, 'utf8');
18
-
19
- const expected_tags = ['%sveltekit.head%', '%sveltekit.body%'];
20
- expected_tags.forEach((tag) => {
21
- if (contents.indexOf(tag) === -1) {
22
- throw new Error(`${relative} is missing ${tag}`);
23
- }
24
- });
25
- } else {
12
+ export function load_template(cwd, { kit }) {
13
+ const { env, files } = kit;
14
+
15
+ const relative = path.relative(cwd, files.appTemplate);
16
+
17
+ if (!fs.existsSync(files.appTemplate)) {
26
18
  throw new Error(`${relative} does not exist`);
27
19
  }
28
20
 
29
- return fs.readFileSync(appTemplate, 'utf-8');
21
+ const contents = fs.readFileSync(files.appTemplate, 'utf8');
22
+
23
+ const expected_tags = ['%sveltekit.head%', '%sveltekit.body%'];
24
+ expected_tags.forEach((tag) => {
25
+ if (contents.indexOf(tag) === -1) {
26
+ throw new Error(`${relative} is missing ${tag}`);
27
+ }
28
+ });
29
+
30
+ for (const match of contents.matchAll(/%sveltekit\.env\.([^%]+)%/g)) {
31
+ if (!match[1].startsWith(env.publicPrefix)) {
32
+ throw new Error(
33
+ `Environment variables in ${relative} must start with ${env.publicPrefix} (saw %sveltekit.env.${match[1]}%)`
34
+ );
35
+ }
36
+ }
37
+
38
+ return contents;
30
39
  }
31
40
 
32
41
  /**
@@ -38,11 +38,15 @@ export const options = {
38
38
  root,
39
39
  service_worker: ${has_service_worker},
40
40
  templates: {
41
- app: ({ head, body, assets, nonce }) => ${s(template)
41
+ app: ({ head, body, assets, nonce, env }) => ${s(template)
42
42
  .replace('%sveltekit.head%', '" + head + "')
43
43
  .replace('%sveltekit.body%', '" + body + "')
44
44
  .replace(/%sveltekit\.assets%/g, '" + assets + "')
45
- .replace(/%sveltekit\.nonce%/g, '" + nonce + "')},
45
+ .replace(/%sveltekit\.nonce%/g, '" + nonce + "')
46
+ .replace(
47
+ /%sveltekit\.env\.([^%]+)%/g,
48
+ (_match, capture) => `" + (env[${s(capture)}] ?? "") + "`
49
+ )},
46
50
  error: ({ status, message }) => ${s(error_page)
47
51
  .replace(/%sveltekit\.status%/g, '" + status + "')
48
52
  .replace(/%sveltekit\.error\.message%/g, '" + message + "')}
@@ -29,12 +29,36 @@ export function redirect(status, location) {
29
29
  export function json(data, init) {
30
30
  // TODO deprecate this in favour of `Response.json` when it's
31
31
  // more widely supported
32
+ const body = JSON.stringify(data);
33
+
34
+ // we can't just do `text(JSON.stringify(data), init)` because
35
+ // it will set a default `content-type` header. duplicated code
36
+ // means less duplicated work
32
37
  const headers = new Headers(init?.headers);
38
+ if (!headers.has('content-length')) {
39
+ headers.set('content-length', encoder.encode(body).byteLength.toString());
40
+ }
41
+
33
42
  if (!headers.has('content-type')) {
34
43
  headers.set('content-type', 'application/json');
35
44
  }
36
45
 
37
- return new Response(JSON.stringify(data), {
46
+ return new Response(body, {
47
+ ...init,
48
+ headers
49
+ });
50
+ }
51
+
52
+ const encoder = new TextEncoder();
53
+
54
+ /** @type {import('@sveltejs/kit').text} */
55
+ export function text(body, init) {
56
+ const headers = new Headers(init?.headers);
57
+ if (!headers.has('content-length')) {
58
+ headers.set('content-length', encoder.encode(body).byteLength.toString());
59
+ }
60
+
61
+ return new Response(body, {
38
62
  ...init,
39
63
  headers
40
64
  });
@@ -1,17 +1,9 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { mergeConfig } from 'vite';
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import * as vite from 'vite';
4
4
  import { mkdirp, posixify } from '../../../utils/filesystem.js';
5
- import { get_vite_config } from '../utils.js';
6
- import {
7
- create_build,
8
- find_deps,
9
- get_default_build_config,
10
- is_http_method,
11
- resolve_symlinks
12
- } from './utils.js';
5
+ import { find_deps, is_http_method, resolve_symlinks } from './utils.js';
13
6
  import { s } from '../../../utils/misc.js';
14
- import { runtime_directory } from '../../../core/utils.js';
15
7
 
16
8
  /**
17
9
  * @param {{
@@ -26,49 +18,22 @@ import { runtime_directory } from '../../../core/utils.js';
26
18
  export async function build_server(options, client) {
27
19
  const { config, vite_config, vite_config_env, manifest_data, output_dir } = options;
28
20
 
29
- /** @type {Record<string, string>} */
30
- const input = {
31
- index: `${runtime_directory}/server/index.js`,
32
- internal: `${config.kit.outDir}/generated/server-internal.js`
33
- };
34
-
35
- // add entry points for every endpoint...
36
- manifest_data.routes.forEach((route) => {
37
- if (route.endpoint) {
38
- const resolved = path.resolve(route.endpoint.file);
39
- const relative = decodeURIComponent(path.relative(config.kit.files.routes, resolved));
40
- const name = posixify(path.join('entries/endpoints', relative.replace(/\.js$/, '')));
41
- input[name] = resolved;
42
- }
43
- });
44
-
45
- // ...and every component used by pages...
46
- manifest_data.nodes.forEach((node) => {
47
- for (const file of [node.component, node.universal, node.server]) {
48
- if (file) {
49
- const resolved = path.resolve(file);
50
- const relative = decodeURIComponent(path.relative(config.kit.files.routes, resolved));
51
-
52
- const name = relative.startsWith('..')
53
- ? posixify(path.join('entries/fallbacks', path.basename(file)))
54
- : posixify(path.join('entries/pages', relative.replace(/\.js$/, '')));
55
- input[name] = resolved;
21
+ const { output } = /** @type {import('rollup').RollupOutput} */ (
22
+ await vite.build({
23
+ // CLI args
24
+ configFile: vite_config.configFile,
25
+ mode: vite_config_env.mode,
26
+ logLevel: config.logLevel,
27
+ clearScreen: config.clearScreen,
28
+ build: {
29
+ ssr: true
56
30
  }
57
- }
58
- });
59
-
60
- // ...and every matcher
61
- Object.entries(manifest_data.matchers).forEach(([key, file]) => {
62
- const name = posixify(path.join('entries/matchers', key));
63
- input[name] = path.resolve(file);
64
- });
65
-
66
- const merged_config = mergeConfig(
67
- get_default_build_config({ config, input, ssr: true, outDir: `${output_dir}/server` }),
68
- await get_vite_config(vite_config, vite_config_env)
31
+ })
69
32
  );
70
33
 
71
- const { chunks } = await create_build(merged_config);
34
+ const chunks = /** @type {import('rollup').OutputChunk[]} */ (
35
+ output.filter((chunk) => chunk.type === 'chunk')
36
+ );
72
37
 
73
38
  /** @type {import('vite').Manifest} */
74
39
  const vite_manifest = JSON.parse(
@@ -1,33 +1,5 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import * as vite from 'vite';
4
- import { get_config_aliases, get_app_aliases } from '../utils.js';
5
-
6
- /**
7
- * @typedef {import('rollup').RollupOutput} RollupOutput
8
- * @typedef {import('rollup').OutputChunk} OutputChunk
9
- * @typedef {import('rollup').OutputAsset} OutputAsset
10
- */
11
-
12
- /**
13
- * Invokes Vite.
14
- * @param {import('vite').UserConfig} config
15
- */
16
- export async function create_build(config) {
17
- const { output } = /** @type {RollupOutput} */ (
18
- await vite.build({ ...config, configFile: false })
19
- );
20
-
21
- const chunks = output.filter(
22
- /** @returns {output is OutputChunk} */ (output) => output.type === 'chunk'
23
- );
24
-
25
- const assets = output.filter(
26
- /** @returns {output is OutputAsset} */ (output) => output.type === 'asset'
27
- );
28
-
29
- return { chunks, assets };
30
- }
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
31
3
 
32
4
  /**
33
5
  * Adds transitive JS and CSS dependencies to the js and css inputs.
@@ -107,111 +79,6 @@ export function resolve_symlinks(manifest, file) {
107
79
  return { chunk, file };
108
80
  }
109
81
 
110
- /**
111
- * Partial Vite configuration that we use by default for setting up the build.
112
- * Can be used in a non-SvelteKit Vite server and build process such as Storybook.
113
- * @param {{
114
- * config: import('types').ValidatedConfig;
115
- * ssr: boolean;
116
- * }} options
117
- * @return {import('vite').UserConfig}
118
- */
119
- export function get_build_setup_config({ config, ssr }) {
120
- return {
121
- build: {
122
- // don't use the default name to avoid collisions with 'static/manifest.json'
123
- manifest: 'vite-manifest.json',
124
- ssr
125
- },
126
- define: {
127
- __SVELTEKIT_ADAPTER_NAME__: JSON.stringify(config.kit.adapter?.name),
128
- __SVELTEKIT_APP_VERSION_FILE__: JSON.stringify(`${config.kit.appDir}/version.json`),
129
- __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: JSON.stringify(config.kit.version.pollInterval),
130
- __SVELTEKIT_DEV__: 'false',
131
- __SVELTEKIT_EMBEDDED__: config.kit.embedded ? 'true' : 'false'
132
- },
133
- resolve: {
134
- alias: [...get_app_aliases(config.kit), ...get_config_aliases(config.kit)]
135
- },
136
- optimizeDeps: {
137
- exclude: ['@sveltejs/kit']
138
- },
139
- ssr: {
140
- noExternal: [
141
- // TODO document why this is necessary
142
- '@sveltejs/kit',
143
- // This ensures that esm-env is inlined into the server output with the
144
- // export conditions resolved correctly through Vite. This prevents adapters
145
- // that bundle later on to resolve the export conditions incorrectly
146
- // and for example include browser-only code in the server output
147
- // because they for example use esbuild.build with `platform: 'browser'`
148
- 'esm-env'
149
- ]
150
- }
151
- };
152
- }
153
-
154
- /**
155
- * Partial Vite configuration that we use by default for setting up the build.
156
- * Cannot be used in a non-SvelteKit Vite server and build process such as Storybook.
157
- * @param {{
158
- * config: import('types').ValidatedConfig;
159
- * input: Record<string, string>;
160
- * ssr: boolean;
161
- * outDir: string;
162
- * }} options
163
- * @return {import('vite').UserConfig}
164
- */
165
- export function get_build_compile_config({ config, input, ssr, outDir }) {
166
- const prefix = `${config.kit.appDir}/immutable`;
167
-
168
- return {
169
- appType: 'custom',
170
- base: ssr ? assets_base(config.kit) : './',
171
- build: {
172
- cssCodeSplit: true,
173
- outDir,
174
- rollupOptions: {
175
- input,
176
- output: {
177
- format: 'esm',
178
- entryFileNames: ssr ? '[name].js' : `${prefix}/[name]-[hash].js`,
179
- chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/chunks/[name]-[hash].js`,
180
- assetFileNames: `${prefix}/assets/[name]-[hash][extname]`,
181
- hoistTransitiveImports: false
182
- },
183
- preserveEntrySignatures: 'strict'
184
- },
185
- target: ssr ? 'node16.14' : undefined
186
- },
187
- publicDir: ssr ? false : config.kit.files.assets,
188
- worker: {
189
- rollupOptions: {
190
- output: {
191
- entryFileNames: `${prefix}/workers/[name]-[hash].js`,
192
- chunkFileNames: `${prefix}/workers/chunks/[name]-[hash].js`,
193
- assetFileNames: `${prefix}/workers/assets/[name]-[hash][extname]`,
194
- hoistTransitiveImports: false
195
- }
196
- }
197
- }
198
- };
199
- }
200
-
201
- /**
202
- * The Vite configuration that we use by default for building.
203
- * @param {{
204
- * config: import('types').ValidatedConfig;
205
- * input: Record<string, string>;
206
- * ssr: boolean;
207
- * outDir: string;
208
- * }} options
209
- * @return {import('vite').UserConfig}
210
- */
211
- export function get_default_build_config(options) {
212
- return vite.mergeConfig(get_build_setup_config(options), get_build_compile_config(options));
213
- }
214
-
215
82
  /**
216
83
  * @param {import('types').ValidatedKitConfig} config
217
84
  * @returns {string}
@@ -73,8 +73,7 @@ export async function dev(vite, vite_config, svelte_config) {
73
73
  } catch (error) {
74
74
  manifest_error = /** @type {Error} */ (error);
75
75
 
76
- console.error(colors.bold().red('Invalid routes'));
77
- console.error(error);
76
+ console.error(colors.bold().red(manifest_error.message));
78
77
  vite.ws.send({
79
78
  type: 'error',
80
79
  err: {
@@ -408,15 +407,16 @@ export async function dev(vite, vite_config, svelte_config) {
408
407
  return;
409
408
  }
410
409
 
410
+ // we have to import `Server` before calling `set_paths`
411
+ const { Server } = /** @type {import('types').ServerModule} */ (
412
+ await vite.ssrLoadModule(`${runtime_base}/server/index.js`)
413
+ );
414
+
411
415
  const { set_paths, set_version, set_fix_stack_trace } =
412
416
  /** @type {import('types').ServerInternalModule} */ (
413
417
  await vite.ssrLoadModule(`${runtime_base}/shared.js`)
414
418
  );
415
419
 
416
- const { Server } = /** @type {import('types').ServerModule} */ (
417
- await vite.ssrLoadModule(`${runtime_base}/server/index.js`)
418
- );
419
-
420
420
  set_paths({
421
421
  base: svelte_config.kit.paths.base,
422
422
  assets
@@ -443,8 +443,7 @@ export async function dev(vite, vite_config, svelte_config) {
443
443
  }
444
444
 
445
445
  if (manifest_error) {
446
- console.error(colors.bold().red('Invalid routes'));
447
- console.error(manifest_error);
446
+ console.error(colors.bold().red(manifest_error.message));
448
447
 
449
448
  const error_page = load_error_page(svelte_config);
450
449