crelte 0.1.2 → 0.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.
Files changed (58) hide show
  1. package/dist/CrelteRequest.d.ts +11 -6
  2. package/dist/CrelteRequest.d.ts.map +1 -1
  3. package/dist/CrelteRequest.js +14 -14
  4. package/dist/graphql/GraphQl.d.ts +1 -1
  5. package/dist/graphql/GraphQl.d.ts.map +1 -1
  6. package/dist/graphql/GraphQl.js +1 -1
  7. package/dist/index.d.ts +2 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +3 -3
  10. package/dist/init/client.d.ts.map +1 -1
  11. package/dist/init/client.js +5 -5
  12. package/dist/init/server.d.ts +2 -0
  13. package/dist/init/server.d.ts.map +1 -1
  14. package/dist/init/server.js +24 -10
  15. package/dist/init/shared.d.ts +3 -3
  16. package/dist/init/shared.d.ts.map +1 -1
  17. package/dist/init/shared.js +1 -1
  18. package/dist/loadData/index.d.ts +11 -5
  19. package/dist/loadData/index.d.ts.map +1 -1
  20. package/dist/loadData/index.js +15 -6
  21. package/dist/routing/History.d.ts +5 -3
  22. package/dist/routing/History.d.ts.map +1 -1
  23. package/dist/routing/History.js +9 -4
  24. package/dist/routing/InnerRouter.d.ts +13 -9
  25. package/dist/routing/InnerRouter.d.ts.map +1 -1
  26. package/dist/routing/InnerRouter.js +30 -35
  27. package/dist/routing/PageLoader.d.ts +4 -5
  28. package/dist/routing/PageLoader.d.ts.map +1 -1
  29. package/dist/routing/PageLoader.js +5 -5
  30. package/dist/routing/Request.d.ts +9 -2
  31. package/dist/routing/Request.d.ts.map +1 -1
  32. package/dist/routing/Request.js +16 -1
  33. package/dist/routing/Route.d.ts +25 -12
  34. package/dist/routing/Route.d.ts.map +1 -1
  35. package/dist/routing/Route.js +35 -14
  36. package/dist/routing/Router.d.ts +5 -7
  37. package/dist/routing/Router.d.ts.map +1 -1
  38. package/dist/routing/Router.js +26 -37
  39. package/dist/routing/Site.js +1 -1
  40. package/dist/routing/utils.d.ts +2 -0
  41. package/dist/routing/utils.d.ts.map +1 -0
  42. package/dist/routing/utils.js +3 -0
  43. package/package.json +3 -2
  44. package/src/CrelteRequest.ts +14 -19
  45. package/src/graphql/GraphQl.ts +5 -2
  46. package/src/index.ts +17 -3
  47. package/src/init/client.ts +5 -10
  48. package/src/init/server.ts +31 -11
  49. package/src/init/shared.ts +4 -4
  50. package/src/loadData/index.ts +47 -15
  51. package/src/routing/History.ts +12 -5
  52. package/src/routing/InnerRouter.ts +42 -39
  53. package/src/routing/PageLoader.ts +7 -17
  54. package/src/routing/Request.ts +20 -6
  55. package/src/routing/Route.ts +40 -16
  56. package/src/routing/Router.ts +33 -46
  57. package/src/routing/Site.ts +1 -1
  58. package/src/routing/utils.ts +3 -0
@@ -1,8 +1,8 @@
1
1
  import Site, { SiteFromGraphQl } from './Site.js';
2
2
  import History from './History.js';
3
3
  import { ClientHistory, ServerHistory } from './History.js';
4
- import Request, { isRequest } from './Request.js';
5
- import Route from './Route.js';
4
+ import Request, { isRequest, RequestOptions } from './Request.js';
5
+ import Route, { RouteOptions } from './Route.js';
6
6
 
7
7
  export type InnerRouterOpts = {
8
8
  preloadOnMouseOver: boolean;
@@ -13,16 +13,21 @@ export type InnerRouterOpts = {
13
13
  */
14
14
  export default class InnerRouter {
15
15
  sites: Site[];
16
+ /**
17
+ * The current route
18
+ *
19
+ * ## Null
20
+ * It might be null on the first targetToRequest, open, and routeFromUrl call
21
+ */
16
22
  route: Route | null;
17
- site: Site;
18
23
  history: History;
19
24
  preloadOnMouseOver: boolean;
20
25
  /**
21
26
  * @param changeHistory returns a function you need to call when you are ready to
22
27
  update the window history (note do not call this after another onRoute call was made)
23
28
  */
24
- onRoute: (route: Request, site: Site, changeHistory: () => void) => void;
25
- onPreload: (route: Request, site: Site) => void;
29
+ onRoute: (route: Request, changeHistory: () => void) => void;
30
+ onPreload: (route: Request) => void;
26
31
 
27
32
  private scrollDebounceTimeout: any | null;
28
33
 
@@ -36,7 +41,6 @@ export default class InnerRouter {
36
41
  this.sites = sites.map(s => new Site(s));
37
42
 
38
43
  this.route = null;
39
- this.site = this.defaultSite();
40
44
  // @ts-ignore
41
45
  this.history = import.meta.env.SSR
42
46
  ? new ServerHistory()
@@ -58,18 +62,18 @@ export default class InnerRouter {
58
62
  this.listen();
59
63
 
60
64
  // let's first try to load from the state
61
- const route = this.targetToRequest(window.location.href);
62
- route._fillFromState(window.history.state);
65
+ const req = this.targetToRequest(window.location.href);
66
+ req._fillFromState(window.history.state);
63
67
 
64
- route.origin = 'init';
68
+ req.origin = 'init';
65
69
 
66
- if (route.search.get('x-craft-live-preview')) {
67
- route.origin = 'live-preview-init';
70
+ if (req.search.get('x-craft-live-preview')) {
71
+ req.origin = 'live-preview-init';
68
72
  }
69
73
 
70
74
  window.history.scrollRestoration = 'manual';
71
75
 
72
- this.open(route, false);
76
+ this.open(req, {}, false);
73
77
  }
74
78
 
75
79
  /**
@@ -80,8 +84,7 @@ export default class InnerRouter {
80
84
  /**
81
85
  * Get a site and if possible use the accept lang header.
82
86
  *
83
- * @param {(string|null)} [acceptLang=null] Accept Language header.
84
- * @return {Site}
87
+ * @param acceptLang Accept Language header.
85
88
  */
86
89
  siteByAcceptLang(acceptLang: string | null = null): Site {
87
90
  if (!acceptLang) return this.defaultSite();
@@ -125,7 +128,7 @@ export default class InnerRouter {
125
128
  * Get the default site
126
129
  */
127
130
  defaultSite(): Site {
128
- return this.sites[0];
131
+ return this.sites.find(s => s.primary) ?? this.sites[0];
129
132
  }
130
133
 
131
134
  /**
@@ -141,10 +144,15 @@ export default class InnerRouter {
141
144
  * @param target
142
145
  * @return Returns null if the url does not match our host (the protocol get's ignored)
143
146
  */
144
- targetToRequest(target: string | URL | Route | Request): Request {
147
+ targetToRequest(
148
+ target: string | URL | Route | Request,
149
+ opts: RequestOptions = {},
150
+ ): Request {
145
151
  if (typeof target === 'string') {
146
152
  if (target.startsWith('/')) {
147
- const site = this.site;
153
+ // todo should we use the language matching or throw if the route does not
154
+ // exists
155
+ const site = this.route?.site ?? this.defaultSite();
148
156
  target = new URL(site.uri + target, site.url);
149
157
  } else {
150
158
  target = new URL(target);
@@ -156,9 +164,10 @@ export default class InnerRouter {
156
164
  }
157
165
 
158
166
  if (!isRequest(target)) {
159
- return Request.fromRoute(target);
167
+ return Request.fromRoute(target, opts);
160
168
  }
161
169
 
170
+ target._updateOpts(opts);
162
171
  return target;
163
172
  }
164
173
 
@@ -170,7 +179,7 @@ export default class InnerRouter {
170
179
  */
171
180
  routeFromUrl(fullUrl: URL): Route {
172
181
  // strip stuff we dont need from url
173
- const route = new Route(fullUrl, null);
182
+ const route = new Route(fullUrl, null!);
174
183
  const url = route.url;
175
184
 
176
185
  let site: Site | null = null;
@@ -193,7 +202,9 @@ export default class InnerRouter {
193
202
  site = s;
194
203
  }
195
204
 
196
- route.site = site;
205
+ // todo should we throw if we can't find a site
206
+ // or use the site which matches the language
207
+ route.site = site ?? this.defaultSite();
197
208
 
198
209
  return route;
199
210
  }
@@ -284,7 +295,7 @@ export default class InnerRouter {
284
295
  // route since it is now already the new route
285
296
  this.route = null;
286
297
 
287
- this.open(route, false);
298
+ this.open(route, {}, false);
288
299
  });
289
300
  }
290
301
 
@@ -294,8 +305,12 @@ export default class InnerRouter {
294
305
  * @param route a route object or an url or uri, never input the same route object again
295
306
  * @param pushState if true pushed the state to the window.history
296
307
  */
297
- open(target: string | URL | Route | Request, pushState: boolean = true) {
298
- const req = this.targetToRequest(target);
308
+ open(
309
+ target: string | URL | Route | Request,
310
+ opts: RouteOptions = {},
311
+ pushState: boolean = true,
312
+ ) {
313
+ const req = this.targetToRequest(target, opts);
299
314
 
300
315
  const current = this.route;
301
316
  if (current) {
@@ -321,13 +336,13 @@ export default class InnerRouter {
321
336
  // @ts-ignore
322
337
  import.meta.env.SSR
323
338
  ) {
324
- this.history.open(req.url.href);
339
+ this.history.open(req);
325
340
  return;
326
341
  }
327
342
 
328
343
  if (pushState) {
329
344
  req.index = (current?.index ?? 0) + 1;
330
- this.onRoute(req, req.site ?? this.site, () => {
345
+ this.onRoute(req, () => {
331
346
  this.pushState(req.toRoute());
332
347
  });
333
348
  } else {
@@ -345,9 +360,8 @@ export default class InnerRouter {
345
360
  */
346
361
  setRoute(req: Request) {
347
362
  this.route = req.toRoute();
348
- if (req.site) this.site = req.site;
349
363
 
350
- this.onRoute(req, this.site, () => {});
364
+ this.onRoute(req, () => {});
351
365
  }
352
366
 
353
367
  /**
@@ -368,7 +382,6 @@ export default class InnerRouter {
368
382
  );
369
383
 
370
384
  this.route = route;
371
- if (route.site) this.site = route.site;
372
385
  }
373
386
 
374
387
  /**
@@ -386,7 +399,6 @@ export default class InnerRouter {
386
399
  );
387
400
 
388
401
  this.route = route;
389
- if (route.site) this.site = route.site;
390
402
  }
391
403
 
392
404
  /**
@@ -398,21 +410,12 @@ export default class InnerRouter {
398
410
  */
399
411
  preload(target: string | URL | Route | Request) {
400
412
  const req = this.targetToRequest(target);
401
-
402
- // todo, don't think this makes any sense
403
- // if the domain of the current site is different than the domain of the
404
- // new site id does not make sense to preload
405
- if (this.site.url.origin !== req.url.origin) {
406
- return;
407
- }
408
-
409
413
  const current = this.route;
410
- const site = req.site ?? this.site;
411
414
 
412
415
  // if the origin matches, the route will be able to be load
413
416
  // so let's preload it
414
417
  if (current && current.url.origin === req.url.origin) {
415
- this.onPreload(req, site);
418
+ this.onPreload(req);
416
419
  }
417
420
  }
418
421
 
@@ -1,5 +1,4 @@
1
1
  import Request from './Request.js';
2
- import Site from './Site.js';
3
2
 
4
3
  export type PageLoaderOptions = {
5
4
  debugTiming: boolean;
@@ -10,11 +9,7 @@ export type LoadResponse = {
10
9
  data: any;
11
10
  };
12
11
 
13
- export type LoadFn = (
14
- req: Request,
15
- site: Site,
16
- opts: LoadOptions,
17
- ) => Promise<any> | any;
12
+ export type LoadFn = (req: Request, opts: LoadOptions) => Promise<any> | any;
18
13
 
19
14
  export type LoadOptions = {
20
15
  setProgress: (num: number) => void;
@@ -29,12 +24,7 @@ export default class PageLoader<More> {
29
24
 
30
25
  private loadingVersion: number;
31
26
 
32
- onLoaded: (
33
- resp: LoadResponse,
34
- req: Request,
35
- site: Site,
36
- more: More,
37
- ) => void;
27
+ onLoaded: (resp: LoadResponse, req: Request, more: More) => void;
38
28
  onProgress: (loading: boolean, progress?: number) => void;
39
29
  loadFn: LoadFn;
40
30
 
@@ -62,7 +52,7 @@ export default class PageLoader<More> {
62
52
  this.onProgress(false);
63
53
  }
64
54
 
65
- async load(req: Request, site: Site, more: More) {
55
+ async load(req: Request, more: More) {
66
56
  this.onProgress(true);
67
57
 
68
58
  const version = ++this.loadingVersion;
@@ -76,7 +66,7 @@ export default class PageLoader<More> {
76
66
 
77
67
  const resp: LoadResponse = { success: false, data: null };
78
68
  try {
79
- resp.data = await this.loadFn(req, site, { setProgress });
69
+ resp.data = await this.loadFn(req, { setProgress });
80
70
  resp.success = true;
81
71
  } catch (e) {
82
72
  resp.success = false;
@@ -91,18 +81,18 @@ export default class PageLoader<More> {
91
81
  return console.log('route changed quickly, ignoring response');
92
82
 
93
83
  this.onProgress(false);
94
- this.onLoaded(resp, req, site, more);
84
+ this.onLoaded(resp, req, more);
95
85
  }
96
86
 
97
87
  // you don't need to wait on this call
98
- async preload(req: Request, site: Site) {
88
+ async preload(req: Request) {
99
89
  const url = req.url.origin + req.url.pathname;
100
90
  if (this.preloadedUrls.has(url)) return;
101
91
 
102
92
  this.preloadedUrls.add(url);
103
93
 
104
94
  try {
105
- await this.loadFn(req, site, { setProgress: () => null });
95
+ await this.loadFn(req, { setProgress: () => null });
106
96
  } catch (_e) {
107
97
  console.log('preload failed');
108
98
  // retry at another time
@@ -10,6 +10,7 @@ export type RequestOptions = {
10
10
  index?: number;
11
11
  origin?: RouteOrigin;
12
12
  disableScroll?: boolean;
13
+ statusCode?: number;
13
14
  };
14
15
 
15
16
  /**
@@ -24,31 +25,34 @@ export default class Request extends Route {
24
25
  */
25
26
  disableScroll: boolean;
26
27
 
28
+ /**
29
+ * The Status code that should be returned for a redirect
30
+ */
31
+ statusCode: number | null;
32
+
27
33
  /** @hidden */
28
34
  _renderBarrier: RenderBarrier;
29
35
 
30
36
  /**
31
37
  * Create a new Request
32
38
  */
33
- constructor(
34
- url: string | URL,
35
- site: Site | null,
36
- opts: RequestOptions = {},
37
- ) {
39
+ constructor(url: string | URL, site: Site, opts: RequestOptions = {}) {
38
40
  super(url, site, opts);
39
41
 
40
42
  this.disableScroll = opts.disableScroll ?? false;
43
+ this.statusCode = opts.statusCode ?? null;
41
44
  this._renderBarrier = new RenderBarrier();
42
45
  }
43
46
 
44
47
  /**
45
48
  * Create a Request from a Route
46
49
  */
47
- static fromRoute(route: Route) {
50
+ static fromRoute(route: Route, opts: RequestOptions = {}) {
48
51
  return new Request(route.url.href, route.site, {
49
52
  scrollY: route.scrollY ?? undefined,
50
53
  index: route.index,
51
54
  origin: route.origin,
55
+ ...opts,
52
56
  });
53
57
  }
54
58
 
@@ -93,6 +97,7 @@ export default class Request extends Route {
93
97
  index: this.index,
94
98
  origin: this.origin,
95
99
  disableScroll: this.disableScroll,
100
+ statusCode: this.statusCode ?? undefined,
96
101
  });
97
102
  }
98
103
 
@@ -106,6 +111,15 @@ export default class Request extends Route {
106
111
  origin: this.origin,
107
112
  });
108
113
  }
114
+
115
+ /** @hidden */
116
+ _updateOpts(opts: RequestOptions = {}) {
117
+ this.scrollY = opts.scrollY ?? this.scrollY;
118
+ this.index = opts.index ?? this.index;
119
+ this.origin = opts.origin ?? this.origin;
120
+ this.disableScroll = opts.disableScroll ?? this.disableScroll;
121
+ this.statusCode = opts.statusCode ?? this.statusCode;
122
+ }
109
123
  }
110
124
 
111
125
  export function isRequest(req: any): req is Request {
@@ -1,5 +1,5 @@
1
- import { trimSlashEnd } from './Router.js';
2
1
  import Site from './Site.js';
2
+ import { trimSlashEnd } from './utils.js';
3
3
 
4
4
  export type RouteOptions = {
5
5
  scrollY?: number;
@@ -38,9 +38,16 @@ export default class Route {
38
38
  url: URL;
39
39
 
40
40
  /**
41
- * The site of the route if it could be defined
41
+ * The site of the route
42
+ *
43
+ * ## Note
44
+ * The site might not always match with the current route
45
+ * but be the site default site or one that matches the
46
+ * users language.
47
+ *
48
+ * If that is important call `route.siteMatches()` to verify
42
49
  */
43
- site: Site | null;
50
+ site: Site;
44
51
 
45
52
  /**
46
53
  * The scroll position of the current route
@@ -61,7 +68,7 @@ export default class Route {
61
68
  /**
62
69
  * Creates a new Route
63
70
  */
64
- constructor(url: string | URL, site: Site | null, opts: RouteOptions = {}) {
71
+ constructor(url: string | URL, site: Site, opts: RouteOptions = {}) {
65
72
  this.url = new URL(url);
66
73
 
67
74
  this.site = site;
@@ -77,17 +84,17 @@ export default class Route {
77
84
  *
78
85
  * ## Example
79
86
  * ```
80
- * const route = new Route('https://example.com/foo/bar/', null);
81
- * console.log(route.uri); // '/foo/bar'
87
+ * const site = _; // site with url https://example.com/fo
88
+ * const route = new Route('https://example.com/foo/bar/', site);
89
+ * console.log(route.uri); // '/bar'
82
90
  *
83
- * const site = _; // site with url https://example.com/foo
84
- * const route2 = new Route('https://example.com/foo/bar/?a=1', site);
85
- * console.log(route2.uri); // '/bar'
91
+ * const site2 = _; // site with url https://example.com/other
92
+ * const route2 = new Route('https://example.com/foo/bar/?a=1', site2);
93
+ * console.log(route2.uri); // '/foo/bar'
86
94
  * ```
87
95
  */
88
96
  get uri(): string {
89
- // todo check if this is correct
90
- if (this.site) {
97
+ if (this.siteMatches()) {
91
98
  return trimSlashEnd(
92
99
  this.url.pathname.substring(this.site.uri.length),
93
100
  );
@@ -103,16 +110,17 @@ export default class Route {
103
110
  *
104
111
  * ## Example
105
112
  * ```
113
+ * const site = _; // site with url https://example.com/foo
106
114
  * const route = new Route('https://example.com/foo/bar/', null);
107
- * console.log(route.baseUrl); // 'https://example.com'
115
+ * console.log(route.baseUrl); // 'https://example.com/foo'
108
116
  *
109
- * const site = _; // site with url https://example.com/foo
110
- * const route2 = new Route('https://example.com/foo/bar/', site);
111
- * console.log(route2.baseUrl); // 'https://example.com/foo'
117
+ * const site2 = _; // site with url https://example.com/other
118
+ * const route2 = new Route('https://example.com/foo/bar/', site2);
119
+ * console.log(route2.baseUrl); // 'https://example.com'
112
120
  * ```
113
121
  */
114
122
  get baseUrl(): string {
115
- if (this.site) return trimSlashEnd(this.site.url.href);
123
+ if (this.siteMatches()) return trimSlashEnd(this.site.url.href);
116
124
 
117
125
  return this.url.origin;
118
126
  }
@@ -146,6 +154,22 @@ export default class Route {
146
154
  return this.url.hash;
147
155
  }
148
156
 
157
+ /**
158
+ * Returns if the site matches the url
159
+ */
160
+ siteMatches(): boolean {
161
+ if (this.url.origin !== this.site.url.origin) return false;
162
+
163
+ // now we need to validate the pathname we should make sure both end with a slash
164
+ // todo can we do this better?
165
+
166
+ // make sure that urls like pathname: /abcbc and site: /abc don't match
167
+ return (this.url.pathname + '/').startsWith(
168
+ // uri never returns a slash at the end
169
+ this.site.uri + '/',
170
+ );
171
+ }
172
+
149
173
  /**
150
174
  * Checks if the route is equal to another route
151
175
  *
@@ -5,7 +5,7 @@ import PageLoader, { LoadFn, LoadResponse } from './PageLoader.js';
5
5
  import { ServerHistory } from './History.js';
6
6
  import { Readable, Writable } from 'crelte-std/stores';
7
7
  import { Listeners } from 'crelte-std/sync';
8
- import Request from './Request.js';
8
+ import Request, { RequestOptions } from './Request.js';
9
9
 
10
10
  export type RouterOptions = {
11
11
  preloadOnMouseOver?: boolean;
@@ -28,7 +28,6 @@ type Internal = {
28
28
  onLoaded: (
29
29
  success: boolean,
30
30
  req: Request,
31
- site: Site,
32
31
  // call ready once your ready to update the dom
33
32
  // this makes sure we trigger a route and site update
34
33
  // almost at the same moment and probably the same tick
@@ -50,14 +49,9 @@ type ServerInited = {
50
49
  // redirect to the route url
51
50
  redirect: boolean;
52
51
  req: Request;
53
- site: Site;
54
52
  props: any;
55
53
  };
56
54
 
57
- export function trimSlashEnd(str: string) {
58
- return str.endsWith('/') ? str.substring(0, str.length - 1) : str;
59
- }
60
-
61
55
  // Make sure route and nextRoute are not the same object as _inner.route
62
56
  export default class Router {
63
57
  /**
@@ -84,9 +78,9 @@ export default class Router {
84
78
  */
85
79
  private _loadingProgress: Writable<number>;
86
80
 
87
- private _onRouteEv: Listeners<[Route, Site]>;
81
+ private _onRouteEv: Listeners<[Route]>;
88
82
 
89
- private _onRequest: Listeners<[Request, Site]>;
83
+ private _onRequest: Listeners<[Request]>;
90
84
 
91
85
  /** @hidden */
92
86
  _internal: Internal;
@@ -123,14 +117,14 @@ export default class Router {
123
117
  initServer: (url, acceptLang) => this._initServer(url, acceptLang),
124
118
  };
125
119
 
126
- this.inner.onRoute = (route, site, changeHistory) =>
127
- this._onRoute(route, site, changeHistory);
128
- this.inner.onPreload = (route, site) => this._onPreload(route, site);
120
+ this.inner.onRoute = (route, changeHistory) =>
121
+ this._onRoute(route, changeHistory);
122
+ this.inner.onPreload = route => this._onPreload(route);
129
123
 
130
- this.pageLoader.onLoaded = (resp, req, site, more) =>
131
- this._onLoaded(resp, req, site, more);
132
- this.pageLoader.loadFn = (req, site, opts) =>
133
- this._internal.onLoad(req, site, opts);
124
+ this.pageLoader.onLoaded = (resp, req, more) =>
125
+ this._onLoaded(resp, req, more);
126
+ this.pageLoader.loadFn = (req, opts) =>
127
+ this._internal.onLoad(req, opts);
134
128
  this.pageLoader.onProgress = (loading, progress) =>
135
129
  this._onProgress(loading, progress);
136
130
  }
@@ -188,8 +182,8 @@ export default class Router {
188
182
  * // the following page will be opened https://example.com/de/foo/bar
189
183
  * ```
190
184
  */
191
- open(target: string | URL | Route) {
192
- this.inner.open(target);
185
+ open(target: string | URL | Route, opts: RequestOptions = {}) {
186
+ this.inner.open(target, opts);
193
187
  }
194
188
 
195
189
  /**
@@ -213,6 +207,7 @@ export default class Router {
213
207
  pushState(route: Route) {
214
208
  this.pageLoader.discard();
215
209
  this.inner.pushState(route);
210
+ this.destroyRequest();
216
211
  this.setNewRoute(route);
217
212
  }
218
213
 
@@ -236,6 +231,7 @@ export default class Router {
236
231
  replaceState(route: Route) {
237
232
  this.pageLoader.discard();
238
233
  this.inner.replaceState(route);
234
+ this.destroyRequest();
239
235
  this.setNewRoute(route);
240
236
  }
241
237
 
@@ -268,7 +264,7 @@ export default class Router {
268
264
  *
269
265
  * @returns a function to remove the listener
270
266
  */
271
- onRoute(fn: (route: Route, site: Site) => void): () => void {
267
+ onRoute(fn: (route: Route) => void): () => void {
272
268
  return this._onRouteEv.add(fn);
273
269
  }
274
270
 
@@ -279,17 +275,16 @@ export default class Router {
279
275
  *
280
276
  * @returns a function to remove the listener
281
277
  */
282
- onRequest(fn: (req: Request, site: Site) => void): () => void {
278
+ onRequest(fn: (req: Request) => void): () => void {
283
279
  return this._onRequest.add(fn);
284
280
  }
285
281
 
286
282
  private setNewRoute(route: Route) {
287
- this.destroyRequest();
288
-
289
283
  this._route.setSilent(route);
290
- if (route.site) this._site.setSilent(route.site);
284
+ const siteChanged = this.site.get()?.id !== route.site.id;
285
+ this._site.setSilent(route.site);
291
286
  this._route.notify();
292
- if (route.site) this._site.notify();
287
+ if (siteChanged) this._site.notify();
293
288
  }
294
289
 
295
290
  private async _initClient() {
@@ -303,7 +298,7 @@ export default class Router {
303
298
  this.inner.initServer();
304
299
 
305
300
  const prom: Promise<ServerInited> = new Promise(resolve => {
306
- this._internal.onLoaded = (success, req, site, ready) => {
301
+ this._internal.onLoaded = (success, req, ready) => {
307
302
  const props = ready();
308
303
  this._internal.onLoaded = () => {};
309
304
 
@@ -311,7 +306,6 @@ export default class Router {
311
306
  success,
312
307
  redirect: false,
313
308
  req,
314
- site,
315
309
  props,
316
310
  });
317
311
  };
@@ -322,14 +316,13 @@ export default class Router {
322
316
 
323
317
  // let's see if the url matches any route and site
324
318
  // if not let's redirect to the site which matches the acceptLang
325
- if (!route.site) {
319
+ if (!route.siteMatches()) {
326
320
  const site = this.inner.siteByAcceptLang(acceptLang);
327
321
 
328
322
  return {
329
323
  success: true,
330
324
  redirect: true,
331
325
  req: new Request(site.url, site),
332
- site,
333
326
  props: {},
334
327
  };
335
328
  }
@@ -339,14 +332,13 @@ export default class Router {
339
332
  const resp = await prom;
340
333
 
341
334
  const hist = this.inner.history as ServerHistory;
342
- if (hist.url) {
343
- const nRoute = new Route(hist.url, null);
344
- if (!route.eq(nRoute)) {
335
+ if (hist.url || hist.req) {
336
+ const nReq = this.inner.targetToRequest(hist.req ?? hist.url!);
337
+ if (!route.eq(nReq)) {
345
338
  return {
346
339
  success: true,
347
340
  redirect: true,
348
- req: Request.fromRoute(nRoute),
349
- site: route.site!,
341
+ req: nReq,
350
342
  props: {},
351
343
  };
352
344
  }
@@ -355,7 +347,7 @@ export default class Router {
355
347
  return resp;
356
348
  }
357
349
 
358
- private _onRoute(req: Request, site: Site, changeHistory: () => void) {
350
+ private _onRoute(req: Request, changeHistory: () => void) {
359
351
  this.destroyRequest();
360
352
 
361
353
  this._request = req;
@@ -365,10 +357,10 @@ export default class Router {
365
357
  throw new Error('render barrier is already open');
366
358
  }
367
359
 
368
- this._onRequest.trigger(req, site);
360
+ this._onRequest.trigger(req);
369
361
 
370
362
  // route prepared
371
- this.pageLoader.load(req, site, { changeHistory });
363
+ this.pageLoader.load(req, { changeHistory });
372
364
  }
373
365
 
374
366
  private destroyRequest() {
@@ -378,14 +370,13 @@ export default class Router {
378
370
  this._request = null;
379
371
  }
380
372
 
381
- private _onPreload(req: Request, site: Site) {
382
- this.pageLoader.preload(req, site);
373
+ private _onPreload(req: Request) {
374
+ this.pageLoader.preload(req);
383
375
  }
384
376
 
385
377
  private async _onLoaded(
386
378
  resp: LoadResponse,
387
379
  req: Request,
388
- site: Site,
389
380
  more: LoadedMore,
390
381
  ) {
391
382
  // check if the render was cancelled
@@ -399,16 +390,12 @@ export default class Router {
399
390
  const route = req.toRoute();
400
391
 
401
392
  const updateRoute = () => {
402
- this._route.setSilent(route);
403
- const siteChanged = this.site.get()?.id !== site.id;
404
- this._site.setSilent(site);
405
- this._route.notify();
406
- if (siteChanged) this._site.notify();
393
+ this.setNewRoute(route);
407
394
 
408
- this._onRouteEv.trigger(route.clone(), site);
395
+ this._onRouteEv.trigger(route.clone());
409
396
  };
410
397
 
411
- this._internal.onLoaded(resp.success, req, site, () => {
398
+ this._internal.onLoaded(resp.success, req, () => {
412
399
  updateRoute();
413
400
  return resp.data;
414
401
  });