@sveltejs/kit 1.0.0-next.465 → 1.0.0-next.468

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.465",
3
+ "version": "1.0.0-next.468",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -145,7 +145,8 @@ export function create_client({ target, base, trailing_slash }) {
145
145
  const url = new URL(location.href);
146
146
 
147
147
  invalidating = Promise.resolve().then(async () => {
148
- await update(url, []);
148
+ const intent = get_navigation_intent(url);
149
+ await update(intent, url, []);
149
150
 
150
151
  invalidating = null;
151
152
  force_invalidation = false;
@@ -200,14 +201,13 @@ export function create_client({ target, base, trailing_slash }) {
200
201
 
201
202
  /**
202
203
  * Returns `true` if update completes, `false` if it is aborted
204
+ * @param {import('./types').NavigationIntent | undefined} intent
203
205
  * @param {URL} url
204
206
  * @param {string[]} redirect_chain
205
207
  * @param {{hash?: string, scroll: { x: number, y: number } | null, keepfocus: boolean, details: { replaceState: boolean, state: any } | null}} [opts]
206
208
  * @param {() => void} [callback]
207
209
  */
208
- async function update(url, redirect_chain, opts, callback) {
209
- const intent = get_navigation_intent(url);
210
-
210
+ async function update(intent, url, redirect_chain, opts, callback) {
211
211
  const current_token = (token = {});
212
212
  let navigation_result = intent && (await load_route(intent));
213
213
 
@@ -399,7 +399,15 @@ export function create_client({ target, base, trailing_slash }) {
399
399
  }
400
400
 
401
401
  /** @type {import('types').Navigation} */
402
- const navigation = { from: null, to: new URL(location.href), type: 'load' };
402
+ const navigation = {
403
+ from: null,
404
+ to: add_url_properties('to', {
405
+ params: current.params,
406
+ routeId: current.route?.id ?? null,
407
+ url: new URL(location.href)
408
+ }),
409
+ type: 'load'
410
+ };
403
411
  callbacks.after_navigate.forEach((fn) => fn(navigation));
404
412
 
405
413
  started = true;
@@ -413,7 +421,7 @@ export function create_client({ target, base, trailing_slash }) {
413
421
  * branch: Array<import('./types').BranchNode | undefined>;
414
422
  * status: number;
415
423
  * error: HttpError | Error | null;
416
- * routeId: string | null;
424
+ * route: import('types').CSRRoute | null;
417
425
  * validation_errors?: Record<string, any> | null;
418
426
  * }} opts
419
427
  */
@@ -423,7 +431,7 @@ export function create_client({ target, base, trailing_slash }) {
423
431
  branch,
424
432
  status,
425
433
  error,
426
- routeId,
434
+ route,
427
435
  validation_errors
428
436
  }) {
429
437
  const filtered = /** @type {import('./types').BranchNode[] } */ (branch.filter(Boolean));
@@ -436,6 +444,7 @@ export function create_client({ target, base, trailing_slash }) {
436
444
  params,
437
445
  branch,
438
446
  error,
447
+ route,
439
448
  session_id
440
449
  },
441
450
  props: {
@@ -470,7 +479,7 @@ export function create_client({ target, base, trailing_slash }) {
470
479
  result.props.page = {
471
480
  error,
472
481
  params,
473
- routeId,
482
+ routeId: route && route.id,
474
483
  status,
475
484
  url,
476
485
  // The whole page store is updated, but this way the object reference stays the same
@@ -846,7 +855,7 @@ export function create_client({ target, base, trailing_slash }) {
846
855
  branch: branch.slice(0, j + 1).concat(error_loaded),
847
856
  status,
848
857
  error,
849
- routeId: route.id
858
+ route
850
859
  });
851
860
  } catch (e) {
852
861
  continue;
@@ -872,7 +881,7 @@ export function create_client({ target, base, trailing_slash }) {
872
881
  branch,
873
882
  status: 200,
874
883
  error: null,
875
- routeId: route.id
884
+ route
876
885
  });
877
886
  }
878
887
 
@@ -941,7 +950,7 @@ export function create_client({ target, base, trailing_slash }) {
941
950
  branch: [root_layout, root_error],
942
951
  status,
943
952
  error,
944
- routeId
953
+ route: null
945
954
  });
946
955
  }
947
956
 
@@ -1000,10 +1009,20 @@ export function create_client({ target, base, trailing_slash }) {
1000
1009
  }) {
1001
1010
  let should_block = false;
1002
1011
 
1012
+ const intent = get_navigation_intent(url);
1013
+
1003
1014
  /** @type {import('types').Navigation} */
1004
1015
  const navigation = {
1005
- from: current.url,
1006
- to: url,
1016
+ from: add_url_properties('from', {
1017
+ params: current.params,
1018
+ routeId: current.route?.id ?? null,
1019
+ url: current.url
1020
+ }),
1021
+ to: add_url_properties('to', {
1022
+ params: intent?.params ?? null,
1023
+ routeId: intent?.route.id ?? null,
1024
+ url
1025
+ }),
1007
1026
  type
1008
1027
  };
1009
1028
 
@@ -1034,6 +1053,7 @@ export function create_client({ target, base, trailing_slash }) {
1034
1053
  }
1035
1054
 
1036
1055
  await update(
1056
+ intent,
1037
1057
  url,
1038
1058
  redirect_chain,
1039
1059
  {
@@ -1153,7 +1173,11 @@ export function create_client({ target, base, trailing_slash }) {
1153
1173
 
1154
1174
  /** @type {import('types').Navigation & { cancel: () => void }} */
1155
1175
  const navigation = {
1156
- from: current.url,
1176
+ from: add_url_properties('from', {
1177
+ params: current.params,
1178
+ routeId: current.route?.id ?? null,
1179
+ url: current.url
1180
+ }),
1157
1181
  to: null,
1158
1182
  type: 'unload',
1159
1183
  cancel: () => (should_block = true)
@@ -1184,7 +1208,7 @@ export function create_client({ target, base, trailing_slash }) {
1184
1208
  /** @param {Event} event */
1185
1209
  const trigger_prefetch = (event) => {
1186
1210
  const { url, options } = find_anchor(event);
1187
- if (url && options.prefetch === '') {
1211
+ if (url && options.prefetch) {
1188
1212
  if (is_external_url(url)) return;
1189
1213
  prefetch(url);
1190
1214
  }
@@ -1234,7 +1258,7 @@ export function create_client({ target, base, trailing_slash }) {
1234
1258
  // 2. 'rel' attribute includes external
1235
1259
  const rel = (a.getAttribute('rel') || '').split(/\s+/);
1236
1260
 
1237
- if (a.hasAttribute('download') || rel.includes('external') || options.reload === '') {
1261
+ if (a.hasAttribute('download') || rel.includes('external') || options.reload) {
1238
1262
  return;
1239
1263
  }
1240
1264
 
@@ -1260,7 +1284,7 @@ export function create_client({ target, base, trailing_slash }) {
1260
1284
 
1261
1285
  navigate({
1262
1286
  url,
1263
- scroll: options.noscroll === '' ? scroll_state() : null,
1287
+ scroll: options.noscroll ? scroll_state() : null,
1264
1288
  keepfocus: false,
1265
1289
  redirect_chain: [],
1266
1290
  details: {
@@ -1379,7 +1403,7 @@ export function create_client({ target, base, trailing_slash }) {
1379
1403
  )
1380
1404
  : original_error,
1381
1405
  validation_errors,
1382
- routeId
1406
+ route: routes.find((route) => route.id === routeId) ?? null
1383
1407
  });
1384
1408
  } catch (e) {
1385
1409
  const error = normalize_error(e);
@@ -1434,3 +1458,37 @@ async function load_data(url, invalid) {
1434
1458
 
1435
1459
  return server_data;
1436
1460
  }
1461
+
1462
+ // TODO remove for 1.0
1463
+ const properties = [
1464
+ 'hash',
1465
+ 'href',
1466
+ 'host',
1467
+ 'hostname',
1468
+ 'origin',
1469
+ 'pathname',
1470
+ 'port',
1471
+ 'protocol',
1472
+ 'search',
1473
+ 'searchParams',
1474
+ 'toString',
1475
+ 'toJSON'
1476
+ ];
1477
+
1478
+ /**
1479
+ * @param {'from' | 'to'} type
1480
+ * @param {import('types').NavigationTarget} target
1481
+ */
1482
+ function add_url_properties(type, target) {
1483
+ for (const prop of properties) {
1484
+ Object.defineProperty(target, prop, {
1485
+ get() {
1486
+ throw new Error(
1487
+ `The navigation shape changed - ${type}.${prop} should now be ${type}.url.${prop}`
1488
+ );
1489
+ }
1490
+ });
1491
+ }
1492
+
1493
+ return target;
1494
+ }
@@ -81,10 +81,11 @@ export interface DataNode {
81
81
  uses: Uses;
82
82
  }
83
83
 
84
- export type NavigationState = {
84
+ export interface NavigationState {
85
85
  branch: Array<BranchNode | undefined>;
86
86
  error: HttpError | Error | null;
87
87
  params: Record<string, string>;
88
+ route: CSRRoute | null;
88
89
  session_id: number;
89
90
  url: URL;
90
- };
91
+ }
@@ -27,16 +27,14 @@ export function find_anchor(event) {
27
27
  /** @type {HTMLAnchorElement | SVGAElement | undefined} */
28
28
  let a;
29
29
 
30
- const options = {
31
- /** @type {string | null} */
32
- noscroll: null,
30
+ /** @type {boolean | null} */
31
+ let noscroll = null;
33
32
 
34
- /** @type {string | null} */
35
- prefetch: null,
33
+ /** @type {boolean | null} */
34
+ let prefetch = null;
36
35
 
37
- /** @type {string | null} */
38
- reload: null
39
- };
36
+ /** @type {boolean | null} */
37
+ let reload = null;
40
38
 
41
39
  for (const element of event.composedPath()) {
42
40
  if (!(element instanceof Element)) continue;
@@ -46,22 +44,43 @@ export function find_anchor(event) {
46
44
  a = /** @type {HTMLAnchorElement | SVGAElement} */ (element);
47
45
  }
48
46
 
49
- if (options.noscroll === null) {
50
- options.noscroll = element.getAttribute('data-sveltekit-noscroll');
51
- }
47
+ if (noscroll === null) noscroll = get_link_option(element, 'data-sveltekit-noscroll');
48
+ if (prefetch === null) prefetch = get_link_option(element, 'data-sveltekit-prefetch');
49
+ if (reload === null) reload = get_link_option(element, 'data-sveltekit-reload');
50
+ }
52
51
 
53
- if (options.prefetch === null) {
54
- options.prefetch = element.getAttribute('data-sveltekit-prefetch');
55
- }
52
+ const url = a && new URL(a instanceof SVGAElement ? a.href.baseVal : a.href, document.baseURI);
56
53
 
57
- if (options.reload === null) {
58
- options.reload = element.getAttribute('data-sveltekit-reload');
54
+ return {
55
+ a,
56
+ url,
57
+ options: {
58
+ noscroll,
59
+ prefetch,
60
+ reload
59
61
  }
60
- }
62
+ };
63
+ }
61
64
 
62
- const url = a && new URL(a instanceof SVGAElement ? a.href.baseVal : a.href, document.baseURI);
65
+ const warned = new WeakSet();
66
+
67
+ /**
68
+ * @param {Element} element
69
+ * @param {string} attribute
70
+ */
71
+ function get_link_option(element, attribute) {
72
+ const value = element.getAttribute(attribute);
73
+ if (value === null) return value;
74
+
75
+ if (value === '') return true;
76
+ if (value === 'off') return false;
77
+
78
+ if (__SVELTEKIT_DEV__ && !warned.has(element)) {
79
+ console.error(`Unexpected value for ${attribute} — should be "" or "off"`, element);
80
+ warned.add(element);
81
+ }
63
82
 
64
- return { a, url, options };
83
+ return false;
65
84
  }
66
85
 
67
86
  /** @param {any} value */
@@ -63,7 +63,7 @@ export function create_fetch({ event, options, state, route, prerender_default }
63
63
  }
64
64
  }
65
65
 
66
- const resolved = resolve(event.url.pathname, requested.split('?')[0]);
66
+ const resolved = resolve(event.url.pathname, requested.split('?')[0]).replace(/#.+$/, '');
67
67
 
68
68
  /** @type {Response} */
69
69
  let response;
@@ -152,6 +152,8 @@ export function create_fetch({ event, options, state, route, prerender_default }
152
152
  requested = event.url.protocol + requested;
153
153
  }
154
154
 
155
+ const url = new URL(requested);
156
+
155
157
  // external fetch
156
158
  // allow cookie passthrough for "same-origin"
157
159
  // if SvelteKit is serving my.domain.com:
@@ -161,10 +163,7 @@ export function create_fetch({ event, options, state, route, prerender_default }
161
163
  // - sub.my.domain.com WILL receive cookies
162
164
  // ports do not affect the resolution
163
165
  // leading dot prevents mydomain.com matching domain.com
164
- if (
165
- `.${new URL(requested).hostname}`.endsWith(`.${event.url.hostname}`) &&
166
- opts.credentials !== 'omit'
167
- ) {
166
+ if (`.${url.hostname}`.endsWith(`.${event.url.hostname}`) && opts.credentials !== 'omit') {
168
167
  const cookie = event.request.headers.get('cookie');
169
168
  if (cookie) opts.headers.set('cookie', cookie);
170
169
  }
@@ -176,6 +175,25 @@ export function create_fetch({ event, options, state, route, prerender_default }
176
175
 
177
176
  const external_request = new Request(requested, /** @type {RequestInit} */ (opts));
178
177
  response = await options.hooks.externalFetch.call(null, external_request);
178
+
179
+ if (opts.mode === 'no-cors') {
180
+ response = new Response('', {
181
+ status: response.status,
182
+ statusText: response.statusText,
183
+ headers: response.headers
184
+ });
185
+ } else {
186
+ if (url.origin !== event.url.origin) {
187
+ const acao = response.headers.get('access-control-allow-origin');
188
+ if (!acao || (acao !== event.url.origin && acao !== '*')) {
189
+ throw new Error(
190
+ `CORS error: ${
191
+ acao ? 'Incorrect' : 'No'
192
+ } 'Access-Control-Allow-Origin' header is present on the requested resource`
193
+ );
194
+ }
195
+ }
196
+ }
179
197
  }
180
198
 
181
199
  const set_cookie = response.headers.get('set-cookie');
package/types/index.d.ts CHANGED
@@ -219,11 +219,17 @@ export interface LoadEvent<
219
219
  depends: (...deps: string[]) => void;
220
220
  }
221
221
 
222
+ export interface NavigationTarget {
223
+ params: Record<string, string> | null;
224
+ routeId: string | null;
225
+ url: URL;
226
+ }
227
+
222
228
  export type NavigationType = 'load' | 'unload' | 'link' | 'goto' | 'popstate';
223
229
 
224
230
  export interface Navigation {
225
- from: URL | null;
226
- to: URL | null;
231
+ from: NavigationTarget | null;
232
+ to: NavigationTarget | null;
227
233
  type: NavigationType;
228
234
  delta?: number;
229
235
  }