@sveltejs/kit 1.0.0-next.237 → 1.0.0-next.240

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.
@@ -686,6 +686,12 @@ async function render_response({
686
686
 
687
687
  const inlined_style = Array.from(styles.values()).join('\n');
688
688
 
689
+ if (state.prerender) {
690
+ if (maxage) {
691
+ head += `<meta http-equiv="cache-control" content="max-age=${maxage}">`;
692
+ }
693
+ }
694
+
689
695
  if (options.amp) {
690
696
  head += `
691
697
  <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style>
@@ -1704,7 +1710,7 @@ async function respond(request, options, state = {}) {
1704
1710
  let ssr = true;
1705
1711
 
1706
1712
  try {
1707
- return await options.hooks.handle({
1713
+ const response = await options.hooks.handle({
1708
1714
  event,
1709
1715
  resolve: async (event, opts) => {
1710
1716
  if (opts && 'ssr' in opts) ssr = /** @type {boolean} */ (opts.ssr);
@@ -1800,6 +1806,13 @@ async function respond(request, options, state = {}) {
1800
1806
  throw new Error('request in handle has been replaced with event' + details);
1801
1807
  }
1802
1808
  });
1809
+
1810
+ // TODO for 1.0, change the error message to point to docs rather than PR
1811
+ if (response && !(response instanceof Response)) {
1812
+ throw new Error('handle must return a Response object' + details);
1813
+ }
1814
+
1815
+ return response;
1803
1816
  } catch (/** @type {unknown} */ e) {
1804
1817
  const error = coalesce_to_error(e);
1805
1818
 
@@ -655,26 +655,4 @@ function sirv (dir, opts={}) {
655
655
  };
656
656
  }
657
657
 
658
- /** @param {Partial<import('types/helper').ResponseHeaders> | undefined} object */
659
- function to_headers(object) {
660
- const headers = new Headers();
661
-
662
- if (object) {
663
- for (const key in object) {
664
- const value = object[key];
665
- if (!value) continue;
666
-
667
- if (typeof value === 'string') {
668
- headers.set(key, value);
669
- } else {
670
- value.forEach((value) => {
671
- headers.append(key, value);
672
- });
673
- }
674
- }
675
- }
676
-
677
- return headers;
678
- }
679
-
680
- export { sirv as s, to_headers as t };
658
+ export { sirv as s };
@@ -5,11 +5,11 @@ import { c as create_manifest_data, a as create_app, d as deep_merge } from './i
5
5
  import { c as coalesce_to_error, S as SVELTE_KIT_ASSETS, r as resolve_entry, $, a as SVELTE_KIT, b as runtime, l as load_template, g as get_mime_lookup, d as copy_assets, e as get_aliases, p as print_config_conflicts } from '../cli.js';
6
6
  import fs__default from 'fs';
7
7
  import { URL as URL$1 } from 'url';
8
- import { t as to_headers, s as sirv } from './http.js';
8
+ import { s as sirv } from './build.js';
9
+ import { e as escape_html_attr, r as resolve, i as is_root_relative, a as escape_json_string_in_html } from './url.js';
9
10
  import { s } from './misc.js';
10
- import { r as resolve, i as is_root_relative } from './url.js';
11
11
  import { __fetch_polyfill } from '../install-fetch.js';
12
- import { getRawBody, setResponse } from '../node.js';
12
+ import { getRequest, setResponse } from '../node.js';
13
13
  import 'sade';
14
14
  import 'child_process';
15
15
  import 'net';
@@ -23,6 +23,28 @@ import 'node:util';
23
23
  import 'node:url';
24
24
  import 'stream';
25
25
 
26
+ /** @param {Partial<import('types/helper').ResponseHeaders> | undefined} object */
27
+ function to_headers(object) {
28
+ const headers = new Headers();
29
+
30
+ if (object) {
31
+ for (const key in object) {
32
+ const value = object[key];
33
+ if (!value) continue;
34
+
35
+ if (typeof value === 'string') {
36
+ headers.set(key, value);
37
+ } else {
38
+ value.forEach((value) => {
39
+ headers.append(key, value);
40
+ });
41
+ }
42
+ }
43
+ }
44
+
45
+ return headers;
46
+ }
47
+
26
48
  /**
27
49
  * Hash using djb2
28
50
  * @param {import('types/hooks').StrictBody} value
@@ -463,85 +485,6 @@ function writable(value, start = noop) {
463
485
  return { set, update, subscribe };
464
486
  }
465
487
 
466
- /** @type {Record<string, string>} */
467
- const escape_json_string_in_html_dict = {
468
- '"': '\\"',
469
- '<': '\\u003C',
470
- '>': '\\u003E',
471
- '/': '\\u002F',
472
- '\\': '\\\\',
473
- '\b': '\\b',
474
- '\f': '\\f',
475
- '\n': '\\n',
476
- '\r': '\\r',
477
- '\t': '\\t',
478
- '\0': '\\0',
479
- '\u2028': '\\u2028',
480
- '\u2029': '\\u2029'
481
- };
482
-
483
- /** @param {string} str */
484
- function escape_json_string_in_html(str) {
485
- return escape(
486
- str,
487
- escape_json_string_in_html_dict,
488
- (code) => `\\u${code.toString(16).toUpperCase()}`
489
- );
490
- }
491
-
492
- /** @type {Record<string, string>} */
493
- const escape_html_attr_dict = {
494
- '<': '&lt;',
495
- '>': '&gt;',
496
- '"': '&quot;'
497
- };
498
-
499
- /**
500
- * use for escaping string values to be used html attributes on the page
501
- * e.g.
502
- * <script data-url="here">
503
- *
504
- * @param {string} str
505
- * @returns string escaped string
506
- */
507
- function escape_html_attr(str) {
508
- return '"' + escape(str, escape_html_attr_dict, (code) => `&#${code};`) + '"';
509
- }
510
-
511
- /**
512
- *
513
- * @param str {string} string to escape
514
- * @param dict {Record<string, string>} dictionary of character replacements
515
- * @param unicode_encoder {function(number): string} encoder to use for high unicode characters
516
- * @returns {string}
517
- */
518
- function escape(str, dict, unicode_encoder) {
519
- let result = '';
520
-
521
- for (let i = 0; i < str.length; i += 1) {
522
- const char = str.charAt(i);
523
- const code = char.charCodeAt(0);
524
-
525
- if (char in dict) {
526
- result += dict[char];
527
- } else if (code >= 0xd800 && code <= 0xdfff) {
528
- const next = str.charCodeAt(i + 1);
529
-
530
- // If this is the beginning of a [high, low] surrogate pair,
531
- // add the next two characters, otherwise escape
532
- if (code <= 0xdbff && next >= 0xdc00 && next <= 0xdfff) {
533
- result += char + str[++i];
534
- } else {
535
- result += unicode_encoder(code);
536
- }
537
- } else {
538
- result += char;
539
- }
540
- }
541
-
542
- return result;
543
- }
544
-
545
488
  /** @param {URL} url */
546
489
  function create_prerendering_url_proxy(url) {
547
490
  return new Proxy(url, {
@@ -676,6 +619,12 @@ async function render_response({
676
619
 
677
620
  const inlined_style = Array.from(styles.values()).join('\n');
678
621
 
622
+ if (state.prerender) {
623
+ if (maxage) {
624
+ head += `<meta http-equiv="cache-control" content="max-age=${maxage}">`;
625
+ }
626
+ }
627
+
679
628
  if (options.amp) {
680
629
  head += `
681
630
  <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style>
@@ -1655,7 +1604,7 @@ async function respond(request, options, state = {}) {
1655
1604
  let ssr = true;
1656
1605
 
1657
1606
  try {
1658
- return await options.hooks.handle({
1607
+ const response = await options.hooks.handle({
1659
1608
  event,
1660
1609
  resolve: async (event, opts) => {
1661
1610
  if (opts && 'ssr' in opts) ssr = /** @type {boolean} */ (opts.ssr);
@@ -1751,6 +1700,13 @@ async function respond(request, options, state = {}) {
1751
1700
  throw new Error('request in handle has been replaced with event' + details);
1752
1701
  }
1753
1702
  });
1703
+
1704
+ // TODO for 1.0, change the error message to point to docs rather than PR
1705
+ if (response && !(response instanceof Response)) {
1706
+ throw new Error('handle must return a Response object' + details);
1707
+ }
1708
+
1709
+ return response;
1754
1710
  } catch (/** @type {unknown} */ e) {
1755
1711
  const error = coalesce_to_error(e);
1756
1712
 
@@ -1907,11 +1863,9 @@ async function create_plugin(config, cwd) {
1907
1863
  if (!req.url || !req.method) throw new Error('Incomplete request');
1908
1864
  if (req.url === '/favicon.ico') return not_found(res);
1909
1865
 
1910
- const url = new URL$1(
1911
- `${vite.config.server.https ? 'https' : 'http'}://${req.headers.host}${req.url}`
1912
- );
1866
+ const base = `${vite.config.server.https ? 'https' : 'http'}://${req.headers.host}`;
1913
1867
 
1914
- const decoded = decodeURI(url.pathname);
1868
+ const decoded = decodeURI(new URL$1(base + req.url).pathname);
1915
1869
 
1916
1870
  if (decoded.startsWith(assets)) {
1917
1871
  const pathname = decoded.slice(assets.length);
@@ -1971,75 +1925,70 @@ async function create_plugin(config, cwd) {
1971
1925
  assets
1972
1926
  });
1973
1927
 
1974
- let body;
1928
+ let request;
1975
1929
 
1976
1930
  try {
1977
- body = await getRawBody(req);
1931
+ request = await getRequest(base, req);
1978
1932
  } catch (/** @type {any} */ err) {
1979
1933
  res.statusCode = err.status || 400;
1980
1934
  return res.end(err.reason || 'Invalid request body');
1981
1935
  }
1982
1936
 
1983
- const rendered = await respond(
1984
- new Request(url.href, {
1985
- headers: /** @type {Record<string, string>} */ (req.headers),
1986
- method: req.method,
1987
- body
1988
- }),
1989
- {
1990
- amp: config.kit.amp,
1991
- dev: true,
1992
- floc: config.kit.floc,
1993
- get_stack: (error) => {
1994
- vite.ssrFixStacktrace(error);
1995
- return error.stack;
1996
- },
1997
- handle_error: (error, event) => {
1998
- vite.ssrFixStacktrace(error);
1999
- hooks.handleError({
2000
- error,
2001
- event,
2002
-
2003
- // TODO remove for 1.0
2004
- // @ts-expect-error
2005
- get request() {
2006
- throw new Error(
2007
- 'request in handleError has been replaced with event. See https://github.com/sveltejs/kit/pull/3384 for details'
2008
- );
2009
- }
2010
- });
2011
- },
2012
- hooks,
2013
- hydrate: config.kit.hydrate,
2014
- manifest,
2015
- method_override: config.kit.methodOverride,
2016
- paths: {
2017
- base: config.kit.paths.base,
2018
- assets
2019
- },
2020
- prefix: '',
2021
- prerender: config.kit.prerender.enabled,
2022
- read: (file) => fs__default.readFileSync(path__default.join(config.kit.files.assets, file)),
2023
- root,
2024
- router: config.kit.router,
2025
- target: config.kit.target,
2026
- template: ({ head, body, assets }) => {
2027
- let rendered = load_template(cwd, config)
2028
- .replace('%svelte.head%', () => head)
2029
- .replace('%svelte.body%', () => body)
2030
- .replace(/%svelte\.assets%/g, assets);
2031
-
2032
- if (amp) {
2033
- const result = amp.validateString(rendered);
2034
-
2035
- if (result.status !== 'PASS') {
2036
- const lines = rendered.split('\n');
2037
-
2038
- /** @param {string} str */
2039
- const escape = (str) =>
2040
- str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
2041
-
2042
- rendered = `<!doctype html>
1937
+ const rendered = await respond(request, {
1938
+ amp: config.kit.amp,
1939
+ dev: true,
1940
+ floc: config.kit.floc,
1941
+ get_stack: (error) => {
1942
+ vite.ssrFixStacktrace(error);
1943
+ return error.stack;
1944
+ },
1945
+ handle_error: (error, event) => {
1946
+ vite.ssrFixStacktrace(error);
1947
+ hooks.handleError({
1948
+ error,
1949
+ event,
1950
+
1951
+ // TODO remove for 1.0
1952
+ // @ts-expect-error
1953
+ get request() {
1954
+ throw new Error(
1955
+ 'request in handleError has been replaced with event. See https://github.com/sveltejs/kit/pull/3384 for details'
1956
+ );
1957
+ }
1958
+ });
1959
+ },
1960
+ hooks,
1961
+ hydrate: config.kit.hydrate,
1962
+ manifest,
1963
+ method_override: config.kit.methodOverride,
1964
+ paths: {
1965
+ base: config.kit.paths.base,
1966
+ assets
1967
+ },
1968
+ prefix: '',
1969
+ prerender: config.kit.prerender.enabled,
1970
+ read: (file) => fs__default.readFileSync(path__default.join(config.kit.files.assets, file)),
1971
+ root,
1972
+ router: config.kit.router,
1973
+ target: config.kit.target,
1974
+ template: ({ head, body, assets }) => {
1975
+ let rendered = load_template(cwd, config)
1976
+ .replace(/%svelte\.assets%/g, assets)
1977
+ // head and body must be replaced last, in case someone tries to sneak in %svelte.assets% etc
1978
+ .replace('%svelte.head%', () => head)
1979
+ .replace('%svelte.body%', () => body);
1980
+
1981
+ if (amp) {
1982
+ const result = amp.validateString(rendered);
1983
+
1984
+ if (result.status !== 'PASS') {
1985
+ const lines = rendered.split('\n');
1986
+
1987
+ /** @param {string} str */
1988
+ const escape = (str) =>
1989
+ str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
1990
+
1991
+ rendered = `<!doctype html>
2043
1992
  <head>
2044
1993
  <meta charset="utf-8" />
2045
1994
  <meta name="viewport" content="width=device-width, initial-scale=1" />
@@ -2070,14 +2019,13 @@ async function create_plugin(config, cwd) {
2070
2019
  )
2071
2020
  .join('\n\n')}
2072
2021
  `;
2073
- }
2074
2022
  }
2023
+ }
2075
2024
 
2076
- return rendered;
2077
- },
2078
- trailing_slash: config.kit.trailingSlash
2079
- }
2080
- );
2025
+ return rendered;
2026
+ },
2027
+ trailing_slash: config.kit.trailingSlash
2028
+ });
2081
2029
 
2082
2030
  if (rendered) {
2083
2031
  setResponse(res, rendered);
@@ -3,7 +3,7 @@ import { readFileSync, writeFileSync } from 'fs';
3
3
  import { resolve, join, dirname } from 'path';
4
4
  import { pathToFileURL, URL } from 'url';
5
5
  import { __fetch_polyfill } from '../install-fetch.js';
6
- import { r as resolve$1, i as is_root_relative } from './url.js';
6
+ import { e as escape_html_attr, r as resolve$1, i as is_root_relative } from './url.js';
7
7
  import { g as generate_manifest } from './index4.js';
8
8
  import 'sade';
9
9
  import 'child_process';
@@ -414,8 +414,11 @@ async function prerender({ cwd, out, log, config, build_data, fallback, all }) {
414
414
  async function visit(path, decoded_path, referrer) {
415
415
  /** @type {Map<string, Response>} */
416
416
  const dependencies = new Map();
417
+ const render_path = config.kit.paths?.base
418
+ ? `http://sveltekit-prerender${config.kit.paths.base}${path === '/' ? '' : path}`
419
+ : `http://sveltekit-prerender${path}`;
417
420
 
418
- const rendered = await app.render(new Request(`http://sveltekit-prerender${path}`), {
421
+ const rendered = await app.render(new Request(render_path), {
419
422
  prerender: {
420
423
  all,
421
424
  dependencies
@@ -441,7 +444,11 @@ async function prerender({ cwd, out, log, config, build_data, fallback, all }) {
441
444
  mkdirp(dirname(file));
442
445
 
443
446
  log.warn(`${rendered.status} ${decoded_path} -> ${location}`);
444
- writeFileSync(file, `<meta http-equiv="refresh" content="0;url=${encodeURI(location)}">`);
447
+
448
+ writeFileSync(
449
+ file,
450
+ `<meta http-equiv="refresh" content=${escape_html_attr(`0;url=${location}`)}>`
451
+ );
445
452
 
446
453
  const resolved = resolve$1(path, location);
447
454
  if (is_root_relative(resolved)) {
@@ -2,9 +2,9 @@ import fs__default from 'fs';
2
2
  import http from 'http';
3
3
  import https from 'https';
4
4
  import { resolve, join } from 'path';
5
- import { s as sirv, t as to_headers } from './http.js';
5
+ import { s as sirv } from './build.js';
6
6
  import { pathToFileURL } from 'url';
7
- import { getRawBody } from '../node.js';
7
+ import { getRequest, setResponse } from '../node.js';
8
8
  import { __fetch_polyfill } from '../install-fetch.js';
9
9
  import { a as SVELTE_KIT, S as SVELTE_KIT_ASSETS } from '../cli.js';
10
10
  import 'querystring';
@@ -91,32 +91,21 @@ async function preview({
91
91
  const initial_url = req.url;
92
92
 
93
93
  const render_handler = async () => {
94
- if (!req.method) throw new Error('Incomplete request');
95
-
96
- let body;
97
-
98
- try {
99
- body = await getRawBody(req);
100
- } catch (/** @type {any} */ err) {
101
- res.statusCode = err.status || 400;
102
- return res.end(err.reason || 'Invalid request body');
103
- }
104
-
105
94
  if (initial_url.startsWith(config.kit.paths.base)) {
106
95
  const protocol = use_https ? 'https' : 'http';
107
96
  const host = req.headers['host'];
108
97
 
109
- const rendered = await app.render(
110
- new Request(`${protocol}://${host}${initial_url}`, {
111
- method: req.method,
112
- headers: to_headers(req.headers),
113
- body
114
- })
115
- );
116
-
117
- res.writeHead(rendered.status, Object.fromEntries(rendered.headers));
118
- if (rendered.body) res.write(new Uint8Array(await rendered.arrayBuffer()));
119
- res.end();
98
+ let request;
99
+
100
+ try {
101
+ req.url = initial_url;
102
+ request = await getRequest(`${protocol}://${host}`, req);
103
+ } catch (/** @type {any} */ err) {
104
+ res.statusCode = err.status || 400;
105
+ return res.end(err.reason || 'Invalid request body');
106
+ }
107
+
108
+ setResponse(res, await app.render(request));
120
109
  } else {
121
110
  res.statusCode = 404;
122
111
  res.end('Not found');
@@ -1,3 +1,82 @@
1
+ /** @type {Record<string, string>} */
2
+ const escape_json_string_in_html_dict = {
3
+ '"': '\\"',
4
+ '<': '\\u003C',
5
+ '>': '\\u003E',
6
+ '/': '\\u002F',
7
+ '\\': '\\\\',
8
+ '\b': '\\b',
9
+ '\f': '\\f',
10
+ '\n': '\\n',
11
+ '\r': '\\r',
12
+ '\t': '\\t',
13
+ '\0': '\\0',
14
+ '\u2028': '\\u2028',
15
+ '\u2029': '\\u2029'
16
+ };
17
+
18
+ /** @param {string} str */
19
+ function escape_json_string_in_html(str) {
20
+ return escape(
21
+ str,
22
+ escape_json_string_in_html_dict,
23
+ (code) => `\\u${code.toString(16).toUpperCase()}`
24
+ );
25
+ }
26
+
27
+ /** @type {Record<string, string>} */
28
+ const escape_html_attr_dict = {
29
+ '<': '&lt;',
30
+ '>': '&gt;',
31
+ '"': '&quot;'
32
+ };
33
+
34
+ /**
35
+ * use for escaping string values to be used html attributes on the page
36
+ * e.g.
37
+ * <script data-url="here">
38
+ *
39
+ * @param {string} str
40
+ * @returns string escaped string
41
+ */
42
+ function escape_html_attr(str) {
43
+ return '"' + escape(str, escape_html_attr_dict, (code) => `&#${code};`) + '"';
44
+ }
45
+
46
+ /**
47
+ *
48
+ * @param str {string} string to escape
49
+ * @param dict {Record<string, string>} dictionary of character replacements
50
+ * @param unicode_encoder {function(number): string} encoder to use for high unicode characters
51
+ * @returns {string}
52
+ */
53
+ function escape(str, dict, unicode_encoder) {
54
+ let result = '';
55
+
56
+ for (let i = 0; i < str.length; i += 1) {
57
+ const char = str.charAt(i);
58
+ const code = char.charCodeAt(0);
59
+
60
+ if (char in dict) {
61
+ result += dict[char];
62
+ } else if (code >= 0xd800 && code <= 0xdfff) {
63
+ const next = str.charCodeAt(i + 1);
64
+
65
+ // If this is the beginning of a [high, low] surrogate pair,
66
+ // add the next two characters, otherwise escape
67
+ if (code <= 0xdbff && next >= 0xdc00 && next <= 0xdfff) {
68
+ result += char + str[++i];
69
+ } else {
70
+ result += unicode_encoder(code);
71
+ }
72
+ } else {
73
+ result += char;
74
+ }
75
+ }
76
+
77
+ return result;
78
+ }
79
+
1
80
  const absolute = /^([a-z]+:)?\/?\//;
2
81
  const scheme = /^[a-z]+:/;
3
82
 
@@ -37,4 +116,4 @@ function is_root_relative(path) {
37
116
  return path[0] === '/' && path[1] !== '/';
38
117
  }
39
118
 
40
- export { is_root_relative as i, resolve as r };
119
+ export { escape_json_string_in_html as a, escape_html_attr as e, is_root_relative as i, resolve as r };
package/dist/cli.js CHANGED
@@ -933,7 +933,7 @@ async function launch(port, https) {
933
933
  exec(`${cmd} ${https ? 'https' : 'http'}://localhost:${port}`);
934
934
  }
935
935
 
936
- const prog = sade('svelte-kit').version('1.0.0-next.237');
936
+ const prog = sade('svelte-kit').version('1.0.0-next.240');
937
937
 
938
938
  prog
939
939
  .command('dev')
@@ -1085,7 +1085,7 @@ async function check_port(port) {
1085
1085
  function welcome({ port, host, https, open, loose, allow, cwd }) {
1086
1086
  if (open) launch(port, https);
1087
1087
 
1088
- console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.237'}\n`));
1088
+ console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.240'}\n`));
1089
1089
 
1090
1090
  const protocol = https ? 'https:' : 'http:';
1091
1091
  const exposed = typeof host !== 'undefined' && host !== 'localhost' && host !== '127.0.0.1';
package/dist/node.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Readable } from 'stream';
2
2
 
3
3
  /** @type {import('@sveltejs/kit/node').GetRawBody} */
4
- function getRawBody(req) {
4
+ function get_raw_body(req) {
5
5
  return new Promise((fulfil, reject) => {
6
6
  const h = req.headers;
7
7
 
@@ -55,13 +55,21 @@ async function getRequest(base, req) {
55
55
  return new Request(base + req.url, {
56
56
  method: req.method,
57
57
  headers: /** @type {Record<string, string>} */ (req.headers),
58
- body: await getRawBody(req)
58
+ body: await get_raw_body(req) // TODO stream rather than buffer
59
59
  });
60
60
  }
61
61
 
62
62
  /** @type {import('@sveltejs/kit/node').SetResponse} */
63
63
  async function setResponse(res, response) {
64
- res.writeHead(response.status, Object.fromEntries(response.headers));
64
+ /** @type {import('../types/helper').ResponseHeaders} */
65
+ const headers = Object.fromEntries(response.headers);
66
+
67
+ if (response.headers.has('set-cookie')) {
68
+ // @ts-expect-error (headers.raw() is non-standard)
69
+ headers['set-cookie'] = response.headers.raw()['set-cookie'];
70
+ }
71
+
72
+ res.writeHead(response.status, headers);
65
73
 
66
74
  if (response.body instanceof Readable) {
67
75
  response.body.pipe(res);
@@ -74,4 +82,4 @@ async function setResponse(res, response) {
74
82
  }
75
83
  }
76
84
 
77
- export { getRawBody, getRequest, setResponse };
85
+ export { getRequest, setResponse };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "1.0.0-next.237",
3
+ "version": "1.0.0-next.240",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -79,11 +79,13 @@
79
79
  "build": "rollup -c && node scripts/cp.js src/runtime/components assets/components",
80
80
  "dev": "rollup -cw",
81
81
  "lint": "eslint --ignore-path .gitignore --ignore-pattern \"src/packaging/test/**\" \"{src,test}/**/*.{ts,mjs,js,svelte}\" && npm run check-format",
82
- "check": "tsc && svelte-check --ignore \"src/packaging/test\"",
82
+ "check": "tsc && svelte-check --ignore test/prerendering,src/packaging/test",
83
83
  "format": "npm run check-format -- --write",
84
84
  "check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore",
85
- "test": "npm run test:unit && npm run test:packaging && npm run test:integration",
85
+ "test": "npm run test:unit && npm run test:packaging && npm run test:prerendering && npm run test:integration",
86
86
  "test:unit": "uvu src \"(spec\\.js|test[\\\\/]index\\.js)\" -i packaging",
87
+ "test:prerendering": "pnpm test:prerendering:basics",
88
+ "test:prerendering:basics": "cd test/prerendering/basics && pnpm test",
87
89
  "test:packaging": "uvu src/packaging \"(spec\\.js|test[\\\\/]index\\.js)\"",
88
90
  "test:integration": "pnpm test:integration:amp && pnpm test:integration:basics && pnpm test:integration:options && pnpm test:integration:options-2",
89
91
  "test:integration:amp": "cd test/apps/amp && pnpm test",