@sveltejs/kit 1.0.0-next.215 → 1.0.0-next.219

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/assets/kit.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @param {Record<string, string | string[]>} headers
2
+ * @param {Record<string, string | string[] | undefined>} headers
3
3
  * @param {string} key
4
4
  * @returns {string | undefined}
5
5
  * @throws {Error}
@@ -68,21 +68,24 @@ function is_string(s) {
68
68
  return typeof s === 'string' || s instanceof String;
69
69
  }
70
70
 
71
+ const text_types = new Set([
72
+ 'application/xml',
73
+ 'application/json',
74
+ 'application/x-www-form-urlencoded',
75
+ 'multipart/form-data'
76
+ ]);
77
+
71
78
  /**
72
79
  * Decides how the body should be parsed based on its mime type. Should match what's in parse_body
73
80
  *
74
81
  * @param {string | undefined | null} content_type The `content-type` header of a request/response.
75
82
  * @returns {boolean}
76
83
  */
77
- function is_content_type_textual(content_type) {
84
+ function is_text(content_type) {
78
85
  if (!content_type) return true; // defaults to json
79
- const [type] = content_type.split(';'); // get the mime type
80
- return (
81
- type === 'text/plain' ||
82
- type === 'application/json' ||
83
- type === 'application/x-www-form-urlencoded' ||
84
- type === 'multipart/form-data'
85
- );
86
+ const type = content_type.split(';')[0].toLowerCase(); // get the mime type
87
+
88
+ return type.startsWith('text/') || type.endsWith('+xml') || text_types.has(type);
86
89
  }
87
90
 
88
91
  /**
@@ -121,9 +124,7 @@ async function render_endpoint(request, route, match) {
121
124
  headers = lowercase_keys(headers);
122
125
  const type = get_single_valued_header(headers, 'content-type');
123
126
 
124
- const is_type_textual = is_content_type_textual(type);
125
-
126
- if (!is_type_textual && !(body instanceof Uint8Array || is_string(body))) {
127
+ if (!is_text(type) && !(body instanceof Uint8Array || is_string(body))) {
127
128
  return error(
128
129
  `${preface}: body must be an instance of string or Uint8Array if content-type is not a supported textual content-type`
129
130
  );
@@ -743,10 +744,18 @@ async function render_response({
743
744
  headers['permissions-policy'] = 'interest-cohort=()';
744
745
  }
745
746
 
747
+ const segments = url.pathname.slice(options.paths.base.length).split('/').slice(2);
748
+ const assets =
749
+ options.paths.assets || (segments.length > 0 ? segments.map(() => '..').join('/') : '.');
750
+
746
751
  return {
747
752
  status,
748
753
  headers,
749
- body: options.template({ head, body })
754
+ body: options.template({
755
+ head,
756
+ body,
757
+ assets
758
+ })
750
759
  };
751
760
  }
752
761
 
@@ -1213,53 +1222,53 @@ async function load_node({
1213
1222
  * }} opts
1214
1223
  */
1215
1224
  async function respond_with_error({ request, options, state, $session, status, error }) {
1216
- const default_layout = await options.manifest._.nodes[0](); // 0 is always the root layout
1217
- const default_error = await options.manifest._.nodes[1](); // 1 is always the root error
1218
-
1219
- /** @type {Record<string, string>} */
1220
- const params = {}; // error page has no params
1225
+ try {
1226
+ const default_layout = await options.manifest._.nodes[0](); // 0 is always the root layout
1227
+ const default_error = await options.manifest._.nodes[1](); // 1 is always the root error
1221
1228
 
1222
- // error pages don't fall through, so we know it's not undefined
1223
- const loaded = /** @type {Loaded} */ (
1224
- await load_node({
1225
- request,
1226
- options,
1227
- state,
1228
- route: null,
1229
- url: request.url, // TODO this is redundant, no?
1230
- params,
1231
- node: default_layout,
1232
- $session,
1233
- stuff: {},
1234
- prerender_enabled: is_prerender_enabled(options, default_error, state),
1235
- is_leaf: false,
1236
- is_error: false
1237
- })
1238
- );
1229
+ /** @type {Record<string, string>} */
1230
+ const params = {}; // error page has no params
1239
1231
 
1240
- const branch = [
1241
- loaded,
1242
- /** @type {Loaded} */ (
1232
+ // error pages don't fall through, so we know it's not undefined
1233
+ const loaded = /** @type {Loaded} */ (
1243
1234
  await load_node({
1244
1235
  request,
1245
1236
  options,
1246
1237
  state,
1247
1238
  route: null,
1248
- url: request.url,
1239
+ url: request.url, // TODO this is redundant, no?
1249
1240
  params,
1250
- node: default_error,
1241
+ node: default_layout,
1251
1242
  $session,
1252
- stuff: loaded ? loaded.stuff : {},
1243
+ stuff: {},
1253
1244
  prerender_enabled: is_prerender_enabled(options, default_error, state),
1254
1245
  is_leaf: false,
1255
- is_error: true,
1256
- status,
1257
- error
1246
+ is_error: false
1258
1247
  })
1259
- )
1260
- ];
1248
+ );
1249
+
1250
+ const branch = [
1251
+ loaded,
1252
+ /** @type {Loaded} */ (
1253
+ await load_node({
1254
+ request,
1255
+ options,
1256
+ state,
1257
+ route: null,
1258
+ url: request.url,
1259
+ params,
1260
+ node: default_error,
1261
+ $session,
1262
+ stuff: loaded ? loaded.stuff : {},
1263
+ prerender_enabled: is_prerender_enabled(options, default_error, state),
1264
+ is_leaf: false,
1265
+ is_error: true,
1266
+ status,
1267
+ error
1268
+ })
1269
+ )
1270
+ ];
1261
1271
 
1262
- try {
1263
1272
  return await render_response({
1264
1273
  options,
1265
1274
  $session,
@@ -1896,16 +1905,30 @@ async function respond(incoming, options, state = {}) {
1896
1905
  }
1897
1906
  }
1898
1907
  });
1899
- } catch (/** @type {unknown} */ err) {
1900
- const e = coalesce_to_error(err);
1908
+ } catch (/** @type {unknown} */ e) {
1909
+ const error = coalesce_to_error(e);
1901
1910
 
1902
- options.handle_error(e, request);
1911
+ options.handle_error(error, request);
1903
1912
 
1904
- return {
1905
- status: 500,
1906
- headers: {},
1907
- body: options.dev ? e.stack : e.message
1908
- };
1913
+ try {
1914
+ const $session = await options.hooks.getSession(request);
1915
+ return await respond_with_error({
1916
+ request,
1917
+ options,
1918
+ state,
1919
+ $session,
1920
+ status: 500,
1921
+ error
1922
+ });
1923
+ } catch (/** @type {unknown} */ e) {
1924
+ const error = coalesce_to_error(e);
1925
+
1926
+ return {
1927
+ status: 500,
1928
+ headers: {},
1929
+ body: options.dev ? error.stack : error.message
1930
+ };
1931
+ }
1909
1932
  }
1910
1933
  }
1911
1934
 
@@ -1,6 +1,7 @@
1
1
  import Root from '../../generated/root.svelte';
2
2
  import { fallback, routes } from '../../generated/manifest.js';
3
3
  import { g as get_base_uri } from '../chunks/utils.js';
4
+ import { tick } from 'svelte';
4
5
  import { writable } from 'svelte/store';
5
6
  import { init } from './singletons.js';
6
7
  import { set_paths } from '../paths.js';
@@ -661,7 +662,7 @@ class Renderer {
661
662
  this._init(navigation_result);
662
663
  }
663
664
 
664
- // opts must be passed if we're navigating...
665
+ // opts must be passed if we're navigating
665
666
  if (opts) {
666
667
  const { hash, scroll, keepfocus } = opts;
667
668
 
@@ -670,7 +671,8 @@ class Renderer {
670
671
  document.body.focus();
671
672
  }
672
673
 
673
- await 0;
674
+ // need to render the DOM before we can scroll to the rendered elements
675
+ await tick();
674
676
 
675
677
  if (this.autoscroll) {
676
678
  const deep_linked = hash && document.getElementById(hash.slice(1));
@@ -686,8 +688,8 @@ class Renderer {
686
688
  }
687
689
  }
688
690
  } else {
689
- // ...they will not be supplied if we're simply invalidating
690
- await 0;
691
+ // in this case we're simply invalidating
692
+ await tick();
691
693
  }
692
694
 
693
695
  this.loading.promise = null;
@@ -9,13 +9,4 @@ function coalesce_to_error(err) {
9
9
  : new Error(JSON.stringify(err));
10
10
  }
11
11
 
12
- /**
13
- * @param {Error} err
14
- * @param {any} errorCode
15
- * @return {err is Error & {code: any}}
16
- */
17
- function has_error_code(err, errorCode = undefined) {
18
- return 'code' in err && (errorCode === undefined || /** @type {any} */ (err).code === errorCode);
19
- }
20
-
21
- export { coalesce_to_error as c, has_error_code as h };
12
+ export { coalesce_to_error as c };
@@ -12,7 +12,7 @@ import 'querystring';
12
12
  import { URL } from 'url';
13
13
  import require$$10 from 'vm';
14
14
  import vite from 'vite';
15
- import { r as resolve_entry, $, g as get_mime_lookup, a as rimraf, c as copy_assets, p as print_config_conflicts } from '../cli.js';
15
+ import { r as resolve_entry, $, l as load_template, g as get_mime_lookup, a as rimraf, c as copy_assets, p as print_config_conflicts } from '../cli.js';
16
16
  import { c as create_manifest_data, a as create_app, d as deep_merge } from './index2.js';
17
17
  import { S as SVELTE_KIT, a as SVELTE_KIT_ASSETS } from './constants.js';
18
18
  import { respond } from '../ssr.js';
@@ -4406,11 +4406,11 @@ function create_plugin(config, output, cwd, amp) {
4406
4406
  router: config.kit.router,
4407
4407
  ssr: config.kit.ssr,
4408
4408
  target: config.kit.target,
4409
- template: ({ head, body }) => {
4410
- let rendered = fs__default
4411
- .readFileSync(config.kit.files.template, 'utf8')
4409
+ template: ({ head, body, assets }) => {
4410
+ let rendered = load_template(cwd, config)
4412
4411
  .replace('%svelte.head%', () => head)
4413
- .replace('%svelte.body%', () => body);
4412
+ .replace('%svelte.body%', () => body)
4413
+ .replace(/%svelte\.assets%/g, assets);
4414
4414
 
4415
4415
  if (amp) {
4416
4416
  const result = amp.validateString(rendered);
@@ -1,6 +1,6 @@
1
1
  import fs__default from 'fs';
2
2
  import path__default from 'path';
3
- import { p as print_config_conflicts, c as copy_assets, b as posixify, r as resolve_entry, m as mkdirp, a as rimraf } from '../cli.js';
3
+ import { p as print_config_conflicts, c as copy_assets, b as posixify, r as resolve_entry, l as load_template, m as mkdirp, a as rimraf } from '../cli.js';
4
4
  import { d as deep_merge, a as create_app, c as create_manifest_data } from './index2.js';
5
5
  import { S as SVELTE_KIT } from './constants.js';
6
6
  import { g as generate_manifest } from './index4.js';
@@ -247,23 +247,25 @@ async function build_client({
247
247
 
248
248
  /**
249
249
  * @param {{
250
- * runtime: string,
251
- * hooks: string,
252
- * config: import('types/config').ValidatedConfig,
253
- * has_service_worker: boolean
250
+ * cwd: string;
251
+ * runtime: string;
252
+ * hooks: string;
253
+ * config: import('types/config').ValidatedConfig;
254
+ * has_service_worker: boolean;
254
255
  * }} opts
255
256
  * @returns
256
257
  */
257
- const template = ({ config, hooks, runtime, has_service_worker }) => `
258
+ const template = ({ cwd, config, hooks, runtime, has_service_worker }) => `
258
259
  import { respond } from '${runtime}';
259
260
  import root from './generated/root.svelte';
260
261
  import { set_paths, assets, base } from './runtime/paths.js';
261
262
  import { set_prerendering } from './runtime/env.js';
262
263
  import * as user_hooks from ${s(hooks)};
263
264
 
264
- const template = ({ head, body }) => ${s(fs__default.readFileSync(config.kit.files.template, 'utf-8'))
265
+ const template = ({ head, body, assets }) => ${s(load_template(cwd, config))
265
266
  .replace('%svelte.head%', '" + head + "')
266
- .replace('%svelte.body%', '" + body + "')};
267
+ .replace('%svelte.body%', '" + body + "')
268
+ .replace(/%svelte\.assets%/g, '" + assets + "')};
267
269
 
268
270
  let read = null;
269
271
 
@@ -415,6 +417,7 @@ async function build_server(
415
417
  fs__default.writeFileSync(
416
418
  input.app,
417
419
  template({
420
+ cwd,
418
421
  config,
419
422
  hooks: app_relative(hooks_file),
420
423
  runtime,
@@ -1,4 +1,4 @@
1
- import { m as mkdirp, a as rimraf, d as copy, $, l as logger } from '../cli.js';
1
+ import { m as mkdirp, a as rimraf, d as copy, $, e as logger } from '../cli.js';
2
2
  import { S as SVELTE_KIT } from './constants.js';
3
3
  import { readFileSync, writeFileSync } from 'fs';
4
4
  import { resolve, join, dirname } from 'path';
@@ -470,6 +470,8 @@ function create_builder({ cwd, config, build_data, log }) {
470
470
  mkdirp,
471
471
  copy,
472
472
 
473
+ appDir: config.kit.appDir,
474
+
473
475
  createEntries(fn) {
474
476
  generated_manifest = true;
475
477
 
@@ -16,6 +16,19 @@ import 'node:util';
16
16
  import 'node:url';
17
17
  import 'net';
18
18
 
19
+ function totalist(dir, callback, pre='') {
20
+ dir = resolve('.', dir);
21
+ let arr = readdirSync(dir);
22
+ let i=0, abs, stats;
23
+ for (; i < arr.length; i++) {
24
+ abs = join(dir, arr[i]);
25
+ stats = statSync(abs);
26
+ stats.isDirectory()
27
+ ? totalist(abs, callback, join(pre, arr[i]))
28
+ : callback(join(pre, arr[i]), abs, stats);
29
+ }
30
+ }
31
+
19
32
  /**
20
33
  * @typedef ParsedURL
21
34
  * @type {import('.').ParsedURL}
@@ -55,19 +68,6 @@ function parse(req) {
55
68
  return req._parsedUrl = { pathname, search, query, raw };
56
69
  }
57
70
 
58
- function list(dir, callback, pre='') {
59
- dir = resolve('.', dir);
60
- let arr = readdirSync(dir);
61
- let i=0, abs, stats;
62
- for (; i < arr.length; i++) {
63
- abs = join(dir, arr[i]);
64
- stats = statSync(abs);
65
- stats.isDirectory()
66
- ? list(abs, callback, join(pre, arr[i]))
67
- : callback(join(pre, arr[i]), abs, stats);
68
- }
69
- }
70
-
71
71
  const mimes = {
72
72
  "ez": "application/andrew-inset",
73
73
  "aw": "application/applixware",
@@ -625,7 +625,7 @@ function sirv (dir, opts={}) {
625
625
  else if (cc && opts.maxAge === 0) cc += ',must-revalidate';
626
626
 
627
627
  if (!opts.dev) {
628
- list(dir, (name, abs, stats) => {
628
+ totalist(dir, (name, abs, stats) => {
629
629
  if (/\.well-known[\\+\/]/.test(name)) ; // keep
630
630
  else if (!opts.dotfiles && /(^\.|[\\+|\/+]\.)/.test(name)) return;
631
631
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @param {Record<string, string | string[]>} headers
2
+ * @param {Record<string, string | string[] | undefined>} headers
3
3
  * @param {string} key
4
4
  * @returns {string | undefined}
5
5
  * @throws {Error}
package/dist/cli.js CHANGED
@@ -1,12 +1,12 @@
1
- import fs__default, { existsSync } from 'fs';
2
1
  import sade from 'sade';
3
2
  import path__default, { relative } from 'path';
4
3
  import { exec as exec$1 } from 'child_process';
5
4
  import { createConnection, createServer } from 'net';
5
+ import fs__default from 'fs';
6
6
  import * as url from 'url';
7
7
  import { fileURLToPath } from 'url';
8
8
  import { networkInterfaces, release } from 'os';
9
- import { c as coalesce_to_error, h as has_error_code } from './chunks/error.js';
9
+ import { c as coalesce_to_error } from './chunks/error.js';
10
10
 
11
11
  let FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, isTTY=true;
12
12
  if (typeof process !== 'undefined') {
@@ -740,10 +740,10 @@ function assert_string(input, keypath) {
740
740
 
741
741
  /**
742
742
  * @param {string} cwd
743
- * @param {import('types/config').ValidatedConfig} validated
743
+ * @param {import('types/config').ValidatedConfig} config
744
744
  */
745
- function validate_template(cwd, validated) {
746
- const { template } = validated.kit.files;
745
+ function load_template(cwd, config) {
746
+ const { template } = config.kit.files;
747
747
  const relative = path__default.relative(cwd, template);
748
748
 
749
749
  if (fs__default.existsSync(template)) {
@@ -757,13 +757,19 @@ function validate_template(cwd, validated) {
757
757
  } else {
758
758
  throw new Error(`${relative} does not exist`);
759
759
  }
760
+
761
+ return fs__default.readFileSync(template, 'utf-8');
760
762
  }
761
763
 
762
764
  async function load_config({ cwd = process.cwd() } = {}) {
763
- const config_file_esm = path__default.join(cwd, 'svelte.config.js');
764
- const config_file = fs__default.existsSync(config_file_esm)
765
- ? config_file_esm
766
- : path__default.join(cwd, 'svelte.config.cjs');
765
+ const config_file = path__default.join(cwd, 'svelte.config.js');
766
+
767
+ if (!fs__default.existsSync(config_file)) {
768
+ throw new Error(
769
+ 'You need to create a svelte.config.js file. See https://kit.svelte.dev/docs#configuration'
770
+ );
771
+ }
772
+
767
773
  const config = await import(url.pathToFileURL(config_file).href);
768
774
 
769
775
  const validated = validate_config(config.default);
@@ -775,10 +781,6 @@ async function load_config({ cwd = process.cwd() } = {}) {
775
781
  validated.kit.files.serviceWorker = path__default.resolve(cwd, validated.kit.files.serviceWorker);
776
782
  validated.kit.files.template = path__default.resolve(cwd, validated.kit.files.template);
777
783
 
778
- validate_template(cwd, validated);
779
-
780
- // TODO check all the `files` exist when the config is loaded?
781
-
782
784
  return validated;
783
785
  }
784
786
 
@@ -787,17 +789,9 @@ async function load_config({ cwd = process.cwd() } = {}) {
787
789
  * @returns {import('types/config').ValidatedConfig}
788
790
  */
789
791
  function validate_config(config) {
790
- const type = typeof config;
791
-
792
- if (type === 'undefined') {
793
- throw new Error(
794
- 'Your config is missing default exports. Make sure to include "export default config;"'
795
- );
796
- }
797
-
798
- if (type !== 'object') {
792
+ if (typeof config !== 'object') {
799
793
  throw new Error(
800
- `Unexpected config type "${type}", make sure your default export is an object.`
794
+ 'svelte.config.js must have a configuration object as its default export. See https://kit.svelte.dev/docs#configuration'
801
795
  );
802
796
  }
803
797
 
@@ -819,52 +813,17 @@ function print_config_conflicts(conflicts, pathPrefix = '', scope) {
819
813
  });
820
814
  }
821
815
 
822
- async function get_config() {
823
- // TODO this is temporary, for the benefit of early adopters
824
- if (existsSync('svelte.config.cjs')) {
825
- // prettier-ignore
826
- console.error($.bold().red(
827
- 'svelte.config.cjs should be renamed to svelte.config.js and converted to an ES module. See https://kit.svelte.dev/docs#configuration for an example'
828
- ));
829
- }
816
+ /** @param {unknown} e */
817
+ function handle_error(e) {
818
+ const error = coalesce_to_error(e);
830
819
 
831
- if (existsSync('vite.config.js')) {
832
- // prettier-ignore
833
- console.error($.bold().red(
834
- 'Please remove vite.config.js and put Vite config in svelte.config.js: https://kit.svelte.dev/docs#configuration-vite'
835
- ));
836
- }
837
-
838
- try {
839
- return await load_config();
840
- } catch (err) {
841
- const error = coalesce_to_error(err);
842
- let message = error.message;
843
-
844
- if (
845
- has_error_code(error, 'MODULE_NOT_FOUND') &&
846
- /Cannot find module svelte\.config\./.test(error.message)
847
- ) {
848
- message = 'Missing svelte.config.js';
849
- } else if (error.name === 'SyntaxError') {
850
- message = 'Malformed svelte.config.js';
851
- }
820
+ if (error.name === 'SyntaxError') throw error;
852
821
 
853
- console.error($.bold().red(message));
854
- if (error.stack) {
855
- console.error($.grey(error.stack));
856
- }
857
- process.exit(1);
822
+ console.log($.bold().red(`> ${error.message}`));
823
+ if (error.stack) {
824
+ console.log($.gray(error.stack.split('\n').slice(1).join('\n')));
858
825
  }
859
- }
860
826
 
861
- /** @param {unknown} error */
862
- function handle_error(error) {
863
- const err = coalesce_to_error(error);
864
- console.log($.bold().red(`> ${err.message}`));
865
- if (err.stack) {
866
- console.log($.gray(err.stack));
867
- }
868
827
  process.exit(1);
869
828
  }
870
829
 
@@ -887,7 +846,7 @@ async function launch(port, https) {
887
846
  exec(`${cmd} ${https ? 'https' : 'http'}://localhost:${port}`);
888
847
  }
889
848
 
890
- const prog = sade('svelte-kit').version('1.0.0-next.215');
849
+ const prog = sade('svelte-kit').version('1.0.0-next.219');
891
850
 
892
851
  prog
893
852
  .command('dev')
@@ -897,12 +856,12 @@ prog
897
856
  .option('-H, --https', 'Use self-signed HTTPS certificate')
898
857
  .option('-o, --open', 'Open a browser tab')
899
858
  .action(async ({ port, host, https, open }) => {
900
- process.env.NODE_ENV = process.env.NODE_ENV || 'development';
901
- const config = await get_config();
859
+ try {
860
+ process.env.NODE_ENV = process.env.NODE_ENV || 'development';
861
+ const config = await load_config();
902
862
 
903
- const { dev } = await import('./chunks/index.js');
863
+ const { dev } = await import('./chunks/index.js');
904
864
 
905
- try {
906
865
  const cwd = process.cwd();
907
866
 
908
867
  const { address_info, server_config } = await dev({
@@ -932,10 +891,10 @@ prog
932
891
  .describe('Create a production build of your app')
933
892
  .option('--verbose', 'Log more stuff', false)
934
893
  .action(async ({ verbose }) => {
935
- process.env.NODE_ENV = process.env.NODE_ENV || 'production';
936
- const config = await get_config();
937
-
938
894
  try {
895
+ process.env.NODE_ENV = process.env.NODE_ENV || 'production';
896
+ const config = await load_config();
897
+
939
898
  const { build } = await import('./chunks/index3.js');
940
899
  const build_data = await build(config);
941
900
 
@@ -970,14 +929,14 @@ prog
970
929
  .option('-H, --https', 'Use self-signed HTTPS certificate', false)
971
930
  .option('-o, --open', 'Open a browser tab', false)
972
931
  .action(async ({ port, host, https, open }) => {
973
- await check_port(port);
932
+ try {
933
+ await check_port(port);
974
934
 
975
- process.env.NODE_ENV = process.env.NODE_ENV || 'production';
976
- const config = await get_config();
935
+ process.env.NODE_ENV = process.env.NODE_ENV || 'production';
936
+ const config = await load_config();
977
937
 
978
- const { preview } = await import('./chunks/index6.js');
938
+ const { preview } = await import('./chunks/index6.js');
979
939
 
980
- try {
981
940
  await preview({ port, host, config, https });
982
941
 
983
942
  welcome({ port, host, https, open });
@@ -991,11 +950,11 @@ prog
991
950
  .describe('Create a package')
992
951
  .option('-d, --dir', 'Destination directory', 'package')
993
952
  .action(async () => {
994
- const config = await get_config();
953
+ try {
954
+ const config = await load_config();
995
955
 
996
- const { make_package } = await import('./chunks/index7.js');
956
+ const { make_package } = await import('./chunks/index7.js');
997
957
 
998
- try {
999
958
  await make_package(config);
1000
959
  } catch (error) {
1001
960
  handle_error(error);
@@ -1039,7 +998,7 @@ async function check_port(port) {
1039
998
  function welcome({ port, host, https, open, loose, allow, cwd }) {
1040
999
  if (open) launch(port, https);
1041
1000
 
1042
- console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.215'}\n`));
1001
+ console.log($.bold().cyan(`\n SvelteKit v${'1.0.0-next.219'}\n`));
1043
1002
 
1044
1003
  const protocol = https ? 'https:' : 'http:';
1045
1004
  const exposed = typeof host !== 'undefined' && host !== 'localhost' && host !== '127.0.0.1';
@@ -1076,4 +1035,4 @@ function welcome({ port, host, https, open, loose, allow, cwd }) {
1076
1035
  console.log('\n');
1077
1036
  }
1078
1037
 
1079
- export { $, rimraf as a, posixify as b, copy_assets as c, copy as d, get_mime_lookup as g, logger as l, mkdirp as m, print_config_conflicts as p, resolve_entry as r, walk as w };
1038
+ export { $, rimraf as a, posixify as b, copy_assets as c, copy as d, logger as e, get_mime_lookup as g, load_template as l, mkdirp as m, print_config_conflicts as p, resolve_entry as r, walk as w };
package/dist/ssr.js CHANGED
@@ -50,21 +50,24 @@ function is_string(s) {
50
50
  return typeof s === 'string' || s instanceof String;
51
51
  }
52
52
 
53
+ const text_types = new Set([
54
+ 'application/xml',
55
+ 'application/json',
56
+ 'application/x-www-form-urlencoded',
57
+ 'multipart/form-data'
58
+ ]);
59
+
53
60
  /**
54
61
  * Decides how the body should be parsed based on its mime type. Should match what's in parse_body
55
62
  *
56
63
  * @param {string | undefined | null} content_type The `content-type` header of a request/response.
57
64
  * @returns {boolean}
58
65
  */
59
- function is_content_type_textual(content_type) {
66
+ function is_text(content_type) {
60
67
  if (!content_type) return true; // defaults to json
61
- const [type] = content_type.split(';'); // get the mime type
62
- return (
63
- type === 'text/plain' ||
64
- type === 'application/json' ||
65
- type === 'application/x-www-form-urlencoded' ||
66
- type === 'multipart/form-data'
67
- );
68
+ const type = content_type.split(';')[0].toLowerCase(); // get the mime type
69
+
70
+ return type.startsWith('text/') || type.endsWith('+xml') || text_types.has(type);
68
71
  }
69
72
 
70
73
  /**
@@ -103,9 +106,7 @@ async function render_endpoint(request, route, match) {
103
106
  headers = lowercase_keys(headers);
104
107
  const type = get_single_valued_header(headers, 'content-type');
105
108
 
106
- const is_type_textual = is_content_type_textual(type);
107
-
108
- if (!is_type_textual && !(body instanceof Uint8Array || is_string(body))) {
109
+ if (!is_text(type) && !(body instanceof Uint8Array || is_string(body))) {
109
110
  return error(
110
111
  `${preface}: body must be an instance of string or Uint8Array if content-type is not a supported textual content-type`
111
112
  );
@@ -712,10 +713,18 @@ async function render_response({
712
713
  headers['permissions-policy'] = 'interest-cohort=()';
713
714
  }
714
715
 
716
+ const segments = url.pathname.slice(options.paths.base.length).split('/').slice(2);
717
+ const assets =
718
+ options.paths.assets || (segments.length > 0 ? segments.map(() => '..').join('/') : '.');
719
+
715
720
  return {
716
721
  status,
717
722
  headers,
718
- body: options.template({ head, body })
723
+ body: options.template({
724
+ head,
725
+ body,
726
+ assets
727
+ })
719
728
  };
720
729
  }
721
730
 
@@ -1143,53 +1152,53 @@ async function load_node({
1143
1152
  * }} opts
1144
1153
  */
1145
1154
  async function respond_with_error({ request, options, state, $session, status, error }) {
1146
- const default_layout = await options.manifest._.nodes[0](); // 0 is always the root layout
1147
- const default_error = await options.manifest._.nodes[1](); // 1 is always the root error
1148
-
1149
- /** @type {Record<string, string>} */
1150
- const params = {}; // error page has no params
1155
+ try {
1156
+ const default_layout = await options.manifest._.nodes[0](); // 0 is always the root layout
1157
+ const default_error = await options.manifest._.nodes[1](); // 1 is always the root error
1151
1158
 
1152
- // error pages don't fall through, so we know it's not undefined
1153
- const loaded = /** @type {Loaded} */ (
1154
- await load_node({
1155
- request,
1156
- options,
1157
- state,
1158
- route: null,
1159
- url: request.url, // TODO this is redundant, no?
1160
- params,
1161
- node: default_layout,
1162
- $session,
1163
- stuff: {},
1164
- prerender_enabled: is_prerender_enabled(options, default_error, state),
1165
- is_leaf: false,
1166
- is_error: false
1167
- })
1168
- );
1159
+ /** @type {Record<string, string>} */
1160
+ const params = {}; // error page has no params
1169
1161
 
1170
- const branch = [
1171
- loaded,
1172
- /** @type {Loaded} */ (
1162
+ // error pages don't fall through, so we know it's not undefined
1163
+ const loaded = /** @type {Loaded} */ (
1173
1164
  await load_node({
1174
1165
  request,
1175
1166
  options,
1176
1167
  state,
1177
1168
  route: null,
1178
- url: request.url,
1169
+ url: request.url, // TODO this is redundant, no?
1179
1170
  params,
1180
- node: default_error,
1171
+ node: default_layout,
1181
1172
  $session,
1182
- stuff: loaded ? loaded.stuff : {},
1173
+ stuff: {},
1183
1174
  prerender_enabled: is_prerender_enabled(options, default_error, state),
1184
1175
  is_leaf: false,
1185
- is_error: true,
1186
- status,
1187
- error
1176
+ is_error: false
1188
1177
  })
1189
- )
1190
- ];
1178
+ );
1179
+
1180
+ const branch = [
1181
+ loaded,
1182
+ /** @type {Loaded} */ (
1183
+ await load_node({
1184
+ request,
1185
+ options,
1186
+ state,
1187
+ route: null,
1188
+ url: request.url,
1189
+ params,
1190
+ node: default_error,
1191
+ $session,
1192
+ stuff: loaded ? loaded.stuff : {},
1193
+ prerender_enabled: is_prerender_enabled(options, default_error, state),
1194
+ is_leaf: false,
1195
+ is_error: true,
1196
+ status,
1197
+ error
1198
+ })
1199
+ )
1200
+ ];
1191
1201
 
1192
- try {
1193
1202
  return await render_response({
1194
1203
  options,
1195
1204
  $session,
@@ -1826,16 +1835,30 @@ async function respond(incoming, options, state = {}) {
1826
1835
  }
1827
1836
  }
1828
1837
  });
1829
- } catch (/** @type {unknown} */ err) {
1830
- const e = coalesce_to_error(err);
1838
+ } catch (/** @type {unknown} */ e) {
1839
+ const error = coalesce_to_error(e);
1831
1840
 
1832
- options.handle_error(e, request);
1841
+ options.handle_error(error, request);
1833
1842
 
1834
- return {
1835
- status: 500,
1836
- headers: {},
1837
- body: options.dev ? e.stack : e.message
1838
- };
1843
+ try {
1844
+ const $session = await options.hooks.getSession(request);
1845
+ return await respond_with_error({
1846
+ request,
1847
+ options,
1848
+ state,
1849
+ $session,
1850
+ status: 500,
1851
+ error
1852
+ });
1853
+ } catch (/** @type {unknown} */ e) {
1854
+ const error = coalesce_to_error(e);
1855
+
1856
+ return {
1857
+ status: 500,
1858
+ headers: {},
1859
+ body: options.dev ? error.stack : error.message
1860
+ };
1861
+ }
1839
1862
  }
1840
1863
  }
1841
1864
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "1.0.0-next.215",
3
+ "version": "1.0.0-next.219",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -36,9 +36,10 @@
36
36
  "port-authority": "^1.1.2",
37
37
  "rollup": "^2.60.2",
38
38
  "selfsigned": "^1.10.11",
39
- "sirv": "^1.0.19",
39
+ "sirv": "^2.0.0",
40
40
  "svelte": "^3.44.2",
41
41
  "svelte-check": "^2.2.10",
42
+ "svelte-preprocess": "^4.9.8",
42
43
  "svelte2tsx": "~0.4.10",
43
44
  "tiny-glob": "^0.2.9",
44
45
  "uvu": "^0.5.2"
package/types/config.d.ts CHANGED
@@ -38,6 +38,8 @@ export interface Builder {
38
38
  rimraf(dir: string): void;
39
39
  mkdirp(dir: string): void;
40
40
 
41
+ appDir: string;
42
+
41
43
  /**
42
44
  * Create entry points that map to individual functions
43
45
  * @param fn A function that groups a set of routes into an entry point
@@ -5,7 +5,7 @@ type DefaultBody = JSONString | Uint8Array;
5
5
 
6
6
  export interface EndpointOutput<Body extends DefaultBody = DefaultBody> {
7
7
  status?: number;
8
- headers?: ResponseHeaders;
8
+ headers?: Partial<ResponseHeaders>;
9
9
  body?: Body;
10
10
  }
11
11
 
package/types/hooks.d.ts CHANGED
@@ -15,7 +15,7 @@ export interface ServerRequest<Locals = Record<string, any>, Body = unknown> {
15
15
 
16
16
  export interface ServerResponse {
17
17
  status: number;
18
- headers: ResponseHeaders;
18
+ headers: Partial<ResponseHeaders>;
19
19
  body?: StrictBody;
20
20
  }
21
21
 
@@ -144,7 +144,7 @@ export interface SSRRenderOptions {
144
144
  service_worker?: string;
145
145
  ssr: boolean;
146
146
  target: string;
147
- template({ head, body }: { head: string; body: string }): string;
147
+ template({ head, body, assets }: { head: string; body: string; assets: string }): string;
148
148
  trailing_slash: TrailingSlash;
149
149
  }
150
150