crelte 0.4.7 → 0.5.0-alpha.1

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 (110) hide show
  1. package/dist/Crelte.d.ts +7 -6
  2. package/dist/Crelte.d.ts.map +1 -1
  3. package/dist/Crelte.js +5 -13
  4. package/dist/CrelteRequest.d.ts +9 -0
  5. package/dist/CrelteRequest.d.ts.map +1 -1
  6. package/dist/CrelteRequest.js +16 -2
  7. package/dist/blocks/Blocks.svelte +2 -2
  8. package/dist/blocks/Blocks.svelte.d.ts +3 -19
  9. package/dist/blocks/Blocks.svelte.d.ts.map +1 -1
  10. package/dist/cookies/ClientCookies.d.ts +0 -1
  11. package/dist/cookies/ClientCookies.d.ts.map +1 -1
  12. package/dist/cookies/ClientCookies.js +0 -1
  13. package/dist/cookies/ServerCookies.d.ts +1 -2
  14. package/dist/cookies/ServerCookies.d.ts.map +1 -1
  15. package/dist/cookies/ServerCookies.js +2 -6
  16. package/dist/cookies/index.d.ts +0 -2
  17. package/dist/cookies/index.d.ts.map +1 -1
  18. package/dist/graphql/GraphQl.d.ts +2 -2
  19. package/dist/graphql/GraphQl.d.ts.map +1 -1
  20. package/dist/index.d.ts +9 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +14 -6
  23. package/dist/init/InternalApp.d.ts +30 -0
  24. package/dist/init/InternalApp.d.ts.map +1 -0
  25. package/dist/init/InternalApp.js +71 -0
  26. package/dist/init/client.d.ts +0 -5
  27. package/dist/init/client.d.ts.map +1 -1
  28. package/dist/init/client.js +88 -75
  29. package/dist/init/crelte-vite-plugin.d.ts +5 -0
  30. package/dist/init/server.d.ts +0 -5
  31. package/dist/init/server.d.ts.map +1 -1
  32. package/dist/init/server.js +50 -20
  33. package/dist/init/shared.d.ts +7 -18
  34. package/dist/init/shared.d.ts.map +1 -1
  35. package/dist/init/shared.js +97 -154
  36. package/dist/init/svelteComponents.d.ts +3 -0
  37. package/dist/init/svelteComponents.d.ts.map +1 -0
  38. package/dist/init/svelteComponents.js +7 -0
  39. package/dist/loadData/Globals.d.ts +40 -33
  40. package/dist/loadData/Globals.d.ts.map +1 -1
  41. package/dist/loadData/Globals.js +99 -88
  42. package/dist/loadData/index.d.ts +3 -2
  43. package/dist/loadData/index.d.ts.map +1 -1
  44. package/dist/loadData/index.js +2 -0
  45. package/dist/plugins/Events.d.ts +11 -13
  46. package/dist/plugins/Events.d.ts.map +1 -1
  47. package/dist/plugins/Events.js +10 -3
  48. package/dist/routing/BaseRoute.d.ts +255 -0
  49. package/dist/routing/BaseRoute.d.ts.map +1 -0
  50. package/dist/routing/BaseRoute.js +349 -0
  51. package/dist/routing/BaseRouter.d.ts +210 -0
  52. package/dist/routing/BaseRouter.d.ts.map +1 -0
  53. package/dist/routing/BaseRouter.js +444 -0
  54. package/dist/routing/ClientRouter.d.ts +32 -0
  55. package/dist/routing/ClientRouter.d.ts.map +1 -0
  56. package/dist/routing/ClientRouter.js +259 -0
  57. package/dist/routing/LoadRunner.d.ts +39 -0
  58. package/dist/routing/LoadRunner.d.ts.map +1 -0
  59. package/dist/routing/{PageLoader.js → LoadRunner.js} +32 -20
  60. package/dist/routing/Request.d.ts +35 -3
  61. package/dist/routing/Request.d.ts.map +1 -1
  62. package/dist/routing/Request.js +64 -5
  63. package/dist/routing/Route.d.ts +24 -223
  64. package/dist/routing/Route.d.ts.map +1 -1
  65. package/dist/routing/Route.js +26 -315
  66. package/dist/routing/Router.d.ts +49 -73
  67. package/dist/routing/Router.d.ts.map +1 -1
  68. package/dist/routing/Router.js +85 -251
  69. package/dist/routing/ServerRouter.d.ts +23 -0
  70. package/dist/routing/ServerRouter.d.ts.map +1 -0
  71. package/dist/routing/ServerRouter.js +57 -0
  72. package/dist/routing/utils.d.ts +5 -0
  73. package/dist/routing/utils.d.ts.map +1 -1
  74. package/dist/routing/utils.js +39 -0
  75. package/dist/utils.d.ts +1 -0
  76. package/dist/utils.d.ts.map +1 -1
  77. package/dist/utils.js +3 -0
  78. package/package.json +6 -5
  79. package/src/Crelte.ts +12 -18
  80. package/src/CrelteRequest.ts +21 -2
  81. package/src/cookies/ClientCookies.ts +0 -2
  82. package/src/cookies/ServerCookies.ts +2 -7
  83. package/src/cookies/index.ts +0 -3
  84. package/src/graphql/GraphQl.ts +2 -1
  85. package/src/index.ts +17 -9
  86. package/src/init/InternalApp.ts +134 -0
  87. package/src/init/client.ts +104 -93
  88. package/src/init/crelte-vite-plugin.d.ts +5 -0
  89. package/src/init/server.ts +70 -35
  90. package/src/init/shared.ts +107 -227
  91. package/src/init/svelteComponents.ts +12 -0
  92. package/src/loadData/Globals.ts +121 -102
  93. package/src/loadData/index.ts +3 -2
  94. package/src/plugins/Events.ts +40 -42
  95. package/src/routing/BaseRoute.ts +422 -0
  96. package/src/routing/BaseRouter.ts +528 -0
  97. package/src/routing/ClientRouter.ts +329 -0
  98. package/src/routing/{PageLoader.ts → LoadRunner.ts} +43 -30
  99. package/src/routing/Request.ts +97 -12
  100. package/src/routing/Route.ts +56 -376
  101. package/src/routing/Router.ts +100 -359
  102. package/src/routing/ServerRouter.ts +78 -0
  103. package/src/routing/utils.ts +53 -0
  104. package/src/utils.ts +4 -0
  105. package/dist/routing/InnerRouter.d.ts +0 -113
  106. package/dist/routing/InnerRouter.d.ts.map +0 -1
  107. package/dist/routing/InnerRouter.js +0 -417
  108. package/dist/routing/PageLoader.d.ts +0 -36
  109. package/dist/routing/PageLoader.d.ts.map +0 -1
  110. package/src/routing/InnerRouter.ts +0 -498
@@ -0,0 +1,259 @@
1
+ import BaseRouter from './BaseRouter.js';
2
+ export default class ClientRouter extends BaseRouter {
3
+ scrollDebounceTimeout;
4
+ preloadOnMouseOver;
5
+ onError;
6
+ constructor(sites, opts) {
7
+ super(sites, opts);
8
+ this.scrollDebounceTimeout = null;
9
+ this.preloadOnMouseOver = opts.preloadOnMouseOver;
10
+ this.onError = () => { };
11
+ }
12
+ /**
13
+ * ## Throws
14
+ */
15
+ async init() {
16
+ this.listen();
17
+ // let's first try to load from the state
18
+ const req = this.targetToRequest(window.location.href);
19
+ req._fillFromState(window.history.state);
20
+ req.origin = 'init';
21
+ window.history.scrollRestoration = 'manual';
22
+ return await this.handleRequest(req, () => { });
23
+ }
24
+ /**
25
+ * Do not call this with origin push or replace
26
+ */
27
+ async openRequest(req) {
28
+ if (['push', 'replace'].includes(req.origin)) {
29
+ throw new Error('Do not use open with push or replace');
30
+ }
31
+ const current = this.route.get();
32
+ // store scrollY
33
+ if (current) {
34
+ // if the scrollY would still be updated we clear the timeout
35
+ // since we should have the latest scrollY
36
+ if (this.scrollDebounceTimeout) {
37
+ clearTimeout(this.scrollDebounceTimeout);
38
+ this.scrollDebounceTimeout = null;
39
+ }
40
+ // store the scroll position
41
+ const scrollY = window.scrollY;
42
+ if (typeof scrollY === 'number') {
43
+ current.scrollY = scrollY;
44
+ window.history.replaceState(current._toState(), '');
45
+ }
46
+ }
47
+ // if the domain of the current site is different than the domain of the
48
+ // new site we need to do a window.location.href call
49
+ if ((current && current.url.origin !== req.url.origin) ||
50
+ // @ts-ignore
51
+ import.meta.env.SSR) {
52
+ window.location.href = req.url.href;
53
+ return;
54
+ }
55
+ req.index = (current?.index ?? 0) + 1;
56
+ return await this.handleRequestAndError(req, route => {
57
+ const url = route.url;
58
+ window.history.pushState(route._toState(), '', url.pathname + url.search + url.hash);
59
+ });
60
+ }
61
+ async pushRequest(req, _opts = {}) {
62
+ const url = req.url;
63
+ // todo a push should also store the previous scrollY
64
+ let nReq = req;
65
+ if (req.scrollY === null) {
66
+ // if there is no scrollY stored we store the current scrollY
67
+ // since a push does not cause a scroll top
68
+ // todo: probably should refactor something probably
69
+ // should not be here
70
+ nReq = req.clone();
71
+ nReq.scrollY = window.scrollY;
72
+ // todo this does not work? nReq is never used
73
+ // why not assign it without a clone?
74
+ }
75
+ return await this.handleRequest(req, route => {
76
+ window.history.pushState(route._toState(), url.pathname + url.search + url.hash);
77
+ });
78
+ }
79
+ async replaceRequest(req, _opts = {}) {
80
+ const url = req.url;
81
+ let nReq = req;
82
+ if (req.scrollY === null) {
83
+ // if there is no scrollY stored we store the current scrollY
84
+ // since a replace does not cause a scrollTo and we wan't
85
+ // history back to work as intended
86
+ // todo: probably should refactor something probably
87
+ // should not be here
88
+ nReq = req.clone();
89
+ nReq.scrollY = window.scrollY;
90
+ // todo this does not work? nReq is never used
91
+ // why not assign it without a clone?
92
+ }
93
+ try {
94
+ return await this.handleRequest(req, () => {
95
+ window.history.replaceState(req._toState(), url.pathname + url.search + url.hash);
96
+ });
97
+ }
98
+ catch (e) {
99
+ console.warn('replacing route failed', e);
100
+ throw e;
101
+ }
102
+ }
103
+ /**
104
+ * This returns a route if it was handled else if an error occured
105
+ * or the request was cancelled returns void
106
+ */
107
+ async handleRequestAndError(req, updateHistory) {
108
+ try {
109
+ return await this.handleRequest(req, updateHistory);
110
+ }
111
+ catch (e) {
112
+ console.error('request failed', e);
113
+ this.onError(e);
114
+ }
115
+ }
116
+ listen() {
117
+ window.addEventListener('click', async (e) => {
118
+ // @ts-ignore
119
+ const link = e.target.closest('a');
120
+ const openInNewTab = e.metaKey || e.ctrlKey || e.shiftKey;
121
+ const saveLink = e.altKey;
122
+ if (!link || !link.href || openInNewTab || saveLink)
123
+ return;
124
+ if (link.target.toLowerCase() === '_blank')
125
+ return;
126
+ if (!link.href.startsWith('http'))
127
+ return;
128
+ e.preventDefault();
129
+ const req = this.targetToRequest(link.href, { origin: 'click' });
130
+ const currRoute = this.route.get();
131
+ const routeEq = currRoute && currRoute.eqUrl(req) && currRoute.eqSearch(req);
132
+ // this means the route is the same maybe with a different hash
133
+ // so it is not necessary to load the data again
134
+ if (routeEq) {
135
+ req.disableLoadData = true;
136
+ }
137
+ this.openRequest(req);
138
+ });
139
+ if (this.preloadOnMouseOver) {
140
+ let currentMouseOver = null;
141
+ window.addEventListener('mouseover', e => {
142
+ // @ts-ignore
143
+ const link = e.target.closest('a');
144
+ if (currentMouseOver && link === currentMouseOver)
145
+ return;
146
+ if (link && link.target.toLowerCase() === '_blank')
147
+ return;
148
+ if (link &&
149
+ !link.hasAttribute('data-no-preload') &&
150
+ link.href) {
151
+ this.preload(link.href);
152
+ }
153
+ currentMouseOver = link;
154
+ });
155
+ }
156
+ // store the scrollY position every 200ms
157
+ // we can't do this at the time of the open call since the pop event
158
+ // has already changed to a new history state so we can't update our
159
+ // current/previous state
160
+ // eslint-disable-next-line no-constant-condition
161
+ if (true) {
162
+ window.addEventListener('scroll', () => {
163
+ const current = this.route.get();
164
+ if (!current)
165
+ return;
166
+ // store the scroll position
167
+ current.scrollY = window.scrollY;
168
+ if (this.scrollDebounceTimeout)
169
+ return;
170
+ // this might cause `Attempt to use history.replaceState() more than
171
+ // 100 times per 30 seconds` in safari
172
+ // since we wait a moment we should almost ever be fine
173
+ this.scrollDebounceTimeout = setTimeout(() => {
174
+ const routerRoute = this.route.get();
175
+ if (!routerRoute || !current.eq(routerRoute))
176
+ return;
177
+ // use the latest state
178
+ window.history.replaceState(routerRoute._toState(), '');
179
+ if (current.inLivePreview()) {
180
+ sessionStorage.setItem('live-preview-scroll',
181
+ // use the latest scrollY
182
+ routerRoute.scrollY + '');
183
+ }
184
+ this.scrollDebounceTimeout = null;
185
+ }, 280);
186
+ });
187
+ }
188
+ window.addEventListener('popstate', async (e) => {
189
+ if (!e.state?.route)
190
+ return;
191
+ const req = this.targetToRequest(window.location.href);
192
+ req._fillFromState(e.state);
193
+ req.origin = 'pop';
194
+ // todo handle errors
195
+ this.handleRequest(req, () => { });
196
+ });
197
+ }
198
+ updateScroll(cr, _route) {
199
+ const req = cr.req;
200
+ if (req.disableScroll)
201
+ return;
202
+ // scroll to target
203
+ let scrollTo = null;
204
+ // if the route is a live preview init and we have a scrollY stored
205
+ // scroll to that
206
+ if (req.inLivePreview()) {
207
+ const scrollY = sessionStorage.getItem('live-preview-scroll');
208
+ if (scrollY) {
209
+ scrollTo = {
210
+ top: parseInt(scrollY),
211
+ behavior: 'instant',
212
+ };
213
+ }
214
+ // if we have a hash and the route was not visited
215
+ }
216
+ else if (req.hash &&
217
+ ((req.origin === 'init' && typeof req.scrollY !== 'number') ||
218
+ req.origin === 'click')) {
219
+ const el = document.getElementById(req.hash.substring(1));
220
+ if (el) {
221
+ scrollTo = {
222
+ intoView: el,
223
+ behavior: 'smooth',
224
+ };
225
+ }
226
+ }
227
+ // restore scroll position
228
+ if (!scrollTo &&
229
+ req.origin !== 'click' &&
230
+ typeof req.scrollY === 'number') {
231
+ scrollTo = {
232
+ top: req.scrollY,
233
+ behavior: 'instant',
234
+ };
235
+ }
236
+ // make sure push and replace don't cause a scroll if it is not intended
237
+ if (!scrollTo && (req.origin === 'push' || req.origin === 'replace'))
238
+ return;
239
+ // scroll to the top if nothing else matches
240
+ if (!scrollTo) {
241
+ scrollTo = {
242
+ top: 0,
243
+ behavior: 'instant',
244
+ };
245
+ }
246
+ if ('top' in scrollTo) {
247
+ window.scrollTo({
248
+ top: scrollTo.top,
249
+ behavior: scrollTo.behavior,
250
+ });
251
+ }
252
+ else {
253
+ scrollTo.intoView.scrollIntoView({
254
+ behavior: scrollTo.behavior,
255
+ block: 'start',
256
+ });
257
+ }
258
+ }
259
+ }
@@ -0,0 +1,39 @@
1
+ import { type CrelteRequest } from '../index.js';
2
+ export type LoadRunnerOptions = {
3
+ debugTiming: boolean;
4
+ };
5
+ export type LoadFn = (cr: CrelteRequest, opts: LoadOptions) => Promise<void> | void;
6
+ export type LoadOptions = {
7
+ setProgress: (num: number) => void;
8
+ isCanceled: () => boolean;
9
+ };
10
+ /**
11
+ * The PageLoader which is responsible for loading page Data
12
+ */
13
+ export default class LoadRunner {
14
+ private debugTiming;
15
+ private preloadedUrls;
16
+ private loadingVersion;
17
+ onProgress: (loading: boolean, progress?: number) => void;
18
+ loadFn: LoadFn;
19
+ /**
20
+ * Creates a new PageLoader
21
+ *
22
+ * @param {Object} options `{debugTiming}`
23
+ */
24
+ constructor(options: LoadRunnerOptions);
25
+ /**
26
+ * Discard the current page load if one is happening
27
+ */
28
+ discard(): void;
29
+ /**
30
+ * @returns true if the load was completed
31
+ *
32
+ * ## Throws
33
+ * if there was an error but not if the request
34
+ * was cancelled before
35
+ */
36
+ load(req: CrelteRequest): Promise<boolean>;
37
+ preload(cr: CrelteRequest): Promise<void>;
38
+ }
39
+ //# sourceMappingURL=LoadRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadRunner.d.ts","sourceRoot":"","sources":["../../src/routing/LoadRunner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,MAAM,iBAAiB,GAAG;IAC/B,WAAW,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,CACpB,EAAE,EAAE,aAAa,EACjB,IAAI,EAAE,WAAW,KACb,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1B,MAAM,MAAM,WAAW,GAAG;IACzB,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,UAAU,EAAE,MAAM,OAAO,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,UAAU;IAC9B,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,aAAa,CAAc;IAEnC,OAAO,CAAC,cAAc,CAAS;IAE/B,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,MAAM,EAAE,MAAM,CAAC;IAEf;;;;OAIG;gBACS,OAAO,EAAE,iBAAiB;IAUtC;;OAEG;IACH,OAAO;IAKP;;;;;;OAMG;IACG,IAAI,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAuC1C,OAAO,CAAC,EAAE,EAAE,aAAa;CAiB/B"}
@@ -1,11 +1,10 @@
1
1
  /**
2
2
  * The PageLoader which is responsible for loading page Data
3
3
  */
4
- export default class PageLoader {
4
+ export default class LoadRunner {
5
5
  debugTiming;
6
6
  preloadedUrls;
7
7
  loadingVersion;
8
- onLoaded;
9
8
  onProgress;
10
9
  loadFn;
11
10
  /**
@@ -17,7 +16,6 @@ export default class PageLoader {
17
16
  this.debugTiming = options.debugTiming;
18
17
  this.preloadedUrls = new Set();
19
18
  this.loadingVersion = 0;
20
- this.onLoaded = () => null;
21
19
  this.onProgress = () => null;
22
20
  this.loadFn = () => null;
23
21
  }
@@ -28,43 +26,57 @@ export default class PageLoader {
28
26
  this.loadingVersion++;
29
27
  this.onProgress(false);
30
28
  }
31
- async load(req, more) {
29
+ /**
30
+ * @returns true if the load was completed
31
+ *
32
+ * ## Throws
33
+ * if there was an error but not if the request
34
+ * was cancelled before
35
+ */
36
+ async load(req) {
32
37
  this.onProgress(true);
33
38
  const version = ++this.loadingVersion;
34
39
  const startTime = this.debugTiming ? Date.now() : null;
40
+ const isCanceled = () => this.loadingVersion !== version;
35
41
  const setProgress = (num) => {
36
- if (this.loadingVersion !== version)
42
+ if (isCanceled())
37
43
  return;
38
44
  this.onProgress(true, num);
39
45
  };
40
- const resp = { success: false, data: null };
46
+ // a function which should return the response
47
+ let resp;
41
48
  try {
42
- resp.data = await this.loadFn(req, { setProgress });
43
- resp.success = true;
49
+ const data = await this.loadFn(req, { isCanceled, setProgress });
50
+ resp = () => data;
44
51
  }
45
52
  catch (e) {
46
- resp.success = false;
47
- resp.data = e;
53
+ resp = () => {
54
+ throw e;
55
+ };
56
+ }
57
+ if (isCanceled()) {
58
+ console.log('route changed quickly, ignoring response');
59
+ return false;
48
60
  }
61
+ this.onProgress(false);
49
62
  if (startTime)
50
63
  console.log('page load took ' + (Date.now() - startTime) + 'ms');
51
- // if were the last that called loading, trigger the loaded event
52
- if (this.loadingVersion !== version)
53
- return console.log('route changed quickly, ignoring response');
54
- this.onProgress(false);
55
- this.onLoaded(resp, req, more);
64
+ return (resp(), true);
56
65
  }
57
66
  // you don't need to wait on this call
58
- async preload(req) {
59
- const url = req.url.origin + req.url.pathname;
67
+ async preload(cr) {
68
+ const url = cr.req.url.origin + cr.req.url.pathname;
60
69
  if (this.preloadedUrls.has(url))
61
70
  return;
62
71
  this.preloadedUrls.add(url);
63
72
  try {
64
- await this.loadFn(req, { setProgress: () => null });
73
+ await this.loadFn(cr, {
74
+ isCanceled: () => false,
75
+ setProgress: () => null,
76
+ });
65
77
  }
66
- catch (_e) {
67
- console.log('preload failed');
78
+ catch (e) {
79
+ console.log('preload failed', e);
68
80
  // retry at another time
69
81
  this.preloadedUrls.delete(url);
70
82
  }
@@ -1,10 +1,15 @@
1
1
  import { Barrier } from 'crelte-std/sync';
2
- import Route, { RouteOrigin } from './Route.js';
3
2
  import Site from './Site.js';
3
+ import { Entry } from '../entry/index.js';
4
+ import BaseRoute, { RouteOrigin } from './BaseRoute.js';
5
+ import Route, { TemplateModule } from './Route.js';
4
6
  /**
5
7
  * Options to create a Request
6
8
  */
7
9
  export type RequestOptions = {
10
+ entry?: Entry;
11
+ template?: TemplateModule;
12
+ loadedData?: Record<string, any>;
8
13
  scrollY?: number;
9
14
  index?: number;
10
15
  origin?: RouteOrigin;
@@ -19,7 +24,19 @@ export type RequestOptions = {
19
24
  * you get a Request from the onRequest event or
20
25
  * in a loadGlobal function.
21
26
  */
22
- export default class Request extends Route {
27
+ export default class Request extends BaseRoute {
28
+ /**
29
+ * The entry of the request once loaded
30
+ */
31
+ entry: Entry | null;
32
+ /**
33
+ * The template module of the request once loaded
34
+ */
35
+ template: TemplateModule | null;
36
+ /**
37
+ * The loaded data of the request
38
+ */
39
+ loadedData: Record<string, any> | null;
23
40
  /**
24
41
  * Disable scrolling for this request
25
42
  * @default false
@@ -36,14 +53,19 @@ export default class Request extends Route {
36
53
  statusCode: number | null;
37
54
  /** @hidden */
38
55
  _renderBarrier: RenderBarrier;
56
+ private _cancelled;
39
57
  /**
40
58
  * Create a new Request
41
59
  */
42
60
  constructor(url: string | URL, site: Site, opts?: RequestOptions);
43
61
  /**
44
62
  * Create a Request from a Route
63
+ *
64
+ * Clears the entry, template, and loadedData
65
+ * todo should it?
45
66
  */
46
67
  static fromRoute(route: Route, opts?: RequestOptions): Request;
68
+ get cancelled(): boolean;
47
69
  /**
48
70
  * With delayRender you can make sure that the render waits
49
71
  * until you are ready. This is useful for building page transitions.
@@ -75,14 +97,24 @@ export default class Request extends Route {
75
97
  delayRender(): DelayRender;
76
98
  /**
77
99
  * Create a copy of the request
100
+ *
101
+ * without including the entry, template, loadedData or cancelled state
102
+ *
103
+ * Is this what we wan't, maybe it should copy everything
78
104
  */
79
105
  clone(): Request;
80
106
  /**
81
107
  * Create a Route from the Request
108
+ *
109
+ * ## Throws
110
+ * if the entry, template or loadedData is missing
111
+ * or the request was cancelled
82
112
  */
83
113
  toRoute(): Route;
84
114
  /** @hidden */
85
115
  _updateOpts(opts?: RequestOptions): void;
116
+ /** @hidden */
117
+ _cancel(): void;
86
118
  }
87
119
  export declare function isRequest(req: any): req is Request;
88
120
  declare class RenderBarrier {
@@ -95,7 +127,7 @@ declare class RenderBarrier {
95
127
  /** @hidden */
96
128
  cancel(): void;
97
129
  /** @hidden */
98
- ready(): Promise<boolean>;
130
+ ready(): Promise<boolean> | boolean;
99
131
  }
100
132
  /**
101
133
  * DelayRender is returned by `Request.delayRender`
@@ -1 +1 @@
1
- {"version":3,"file":"Request.d.ts","sourceRoot":"","sources":["../../src/routing/Request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,KAAK;IACzC;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,eAAe,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B,cAAc;IACd,cAAc,EAAE,aAAa,CAAC;IAE9B;;OAEG;gBACS,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAE,cAAmB;IASpE;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,GAAE,cAAmB;IAWxD;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,WAAW,IAAI,WAAW;IAI1B;;OAEG;IACH,KAAK;IAaL;;OAEG;IACH,OAAO;IAUP,cAAc;IACd,WAAW,CAAC,IAAI,GAAE,cAAmB;CAUrC;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,OAAO,CAElD;AAED,cAAM,aAAa;IAClB,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,WAAW,CAAC;;IAQlB,MAAM,IAAI,OAAO;IAIjB,GAAG,IAAI,WAAW;IAclB,cAAc;IACd,MAAM;IAQN,cAAc;IACd,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;CAGzB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACzB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9B;;OAEG;IACH,MAAM,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC"}
1
+ {"version":3,"file":"Request.d.ts","sourceRoot":"","sources":["../../src/routing/Request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,SAAS,EAAE,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,SAAS;IAC7C;;OAEG;IACH,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAEpB;;OAEG;IACH,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAC;IAEhC;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IAEvC;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAC;IAEvB;;;OAGG;IACH,eAAe,EAAE,OAAO,CAAC;IAEzB;;OAEG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B,cAAc;IACd,cAAc,EAAE,aAAa,CAAC;IAE9B,OAAO,CAAC,UAAU,CAAU;IAE5B;;OAEG;gBACS,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAE,cAAmB;IAapE;;;;;OAKG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,GAAE,cAAmB;IAWxD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,WAAW,IAAI,WAAW;IAI1B;;;;;;OAMG;IACH,KAAK;IAsBL;;;;;;OAMG;IACH,OAAO;IA8BP,cAAc;IACd,WAAW,CAAC,IAAI,GAAE,cAAmB;IAiBrC,cAAc;IACd,OAAO;CAIP;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,OAAO,CAElD;AAED,cAAM,aAAa;IAClB,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,WAAW,CAAC;;IAQlB,MAAM,IAAI,OAAO;IAIjB,GAAG,IAAI,WAAW;IAclB,cAAc;IACd,MAAM;IAWN,cAAc;IACd,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO;CAGnC;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACzB;;;;;OAKG;IACH,KAAK,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9B;;OAEG;IACH,MAAM,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC"}
@@ -1,12 +1,25 @@
1
1
  import { Barrier } from 'crelte-std/sync';
2
- import Route from './Route.js';
3
2
  import { objClone } from '../utils.js';
3
+ import BaseRoute from './BaseRoute.js';
4
+ import Route from './Route.js';
4
5
  /**
5
6
  * A Request is a Route with some extra options
6
7
  * you get a Request from the onRequest event or
7
8
  * in a loadGlobal function.
8
9
  */
9
- export default class Request extends Route {
10
+ export default class Request extends BaseRoute {
11
+ /**
12
+ * The entry of the request once loaded
13
+ */
14
+ entry;
15
+ /**
16
+ * The template module of the request once loaded
17
+ */
18
+ template;
19
+ /**
20
+ * The loaded data of the request
21
+ */
22
+ loadedData;
10
23
  /**
11
24
  * Disable scrolling for this request
12
25
  * @default false
@@ -23,18 +36,26 @@ export default class Request extends Route {
23
36
  statusCode;
24
37
  /** @hidden */
25
38
  _renderBarrier;
39
+ _cancelled;
26
40
  /**
27
41
  * Create a new Request
28
42
  */
29
43
  constructor(url, site, opts = {}) {
30
44
  super(url, site, opts);
45
+ this.entry = opts.entry ?? null;
46
+ this.template = opts.template ?? null;
47
+ this.loadedData = opts.loadedData ?? null;
31
48
  this.disableScroll = opts.disableScroll ?? false;
32
49
  this.disableLoadData = opts.disableLoadData ?? false;
33
50
  this.statusCode = opts.statusCode ?? null;
34
51
  this._renderBarrier = new RenderBarrier();
52
+ this._cancelled = false;
35
53
  }
36
54
  /**
37
55
  * Create a Request from a Route
56
+ *
57
+ * Clears the entry, template, and loadedData
58
+ * todo should it?
38
59
  */
39
60
  static fromRoute(route, opts = {}) {
40
61
  return new Request(route.url.href, route.site, {
@@ -46,6 +67,9 @@ export default class Request extends Route {
46
67
  ...opts,
47
68
  });
48
69
  }
70
+ get cancelled() {
71
+ return this._cancelled;
72
+ }
49
73
  /**
50
74
  * With delayRender you can make sure that the render waits
51
75
  * until you are ready. This is useful for building page transitions.
@@ -79,9 +103,20 @@ export default class Request extends Route {
79
103
  }
80
104
  /**
81
105
  * Create a copy of the request
106
+ *
107
+ * without including the entry, template, loadedData or cancelled state
108
+ *
109
+ * Is this what we wan't, maybe it should copy everything
82
110
  */
83
111
  clone() {
84
- return new Request(this.url.href, this.site, {
112
+ // todo should this clone the entry
113
+ // the route for example does not do it
114
+ //
115
+ // todo should this clone keep the entry?
116
+ const req = new Request(this.url.href, this.site, {
117
+ // entry: objClone(this.entry),
118
+ // template: this.template ?? undefined,
119
+ // loadedData: objClone(this.loadedData),
85
120
  scrollY: this.scrollY ?? undefined,
86
121
  index: this.index,
87
122
  origin: this.origin,
@@ -91,21 +126,37 @@ export default class Request extends Route {
91
126
  disableLoadData: this.disableLoadData,
92
127
  statusCode: this.statusCode ?? undefined,
93
128
  });
129
+ return req;
94
130
  }
95
131
  /**
96
132
  * Create a Route from the Request
133
+ *
134
+ * ## Throws
135
+ * if the entry, template or loadedData is missing
136
+ * or the request was cancelled
97
137
  */
98
138
  toRoute() {
99
- return new Route(this.url.href, this.site, {
139
+ if (this.cancelled)
140
+ throw new Error('cannot create a new route because it was cancelled');
141
+ if (!this.entry || !this.template || !this.loadedData)
142
+ throw new Error('cannot create a new route because entry, template or loadedData is missing');
143
+ const route = new Route(this.url.href, this.site, this.entry, this.template, this.loadedData, {
100
144
  scrollY: this.scrollY ?? undefined,
101
145
  index: this.index,
102
146
  origin: this.origin,
103
147
  state: objClone(this._state),
104
148
  context: this._context,
105
149
  });
150
+ route.entryChanged = !this.disableLoadData;
151
+ return route;
106
152
  }
107
153
  /** @hidden */
108
154
  _updateOpts(opts = {}) {
155
+ // todo maybe should check that if entry is updated
156
+ // template and loadedData is also updated
157
+ this.entry = opts.entry ?? this.entry;
158
+ this.template = opts.template ?? this.template;
159
+ this.loadedData = opts.loadedData ?? this.loadedData;
109
160
  this.scrollY = opts.scrollY ?? this.scrollY;
110
161
  this.index = opts.index ?? this.index;
111
162
  this.origin = opts.origin ?? this.origin;
@@ -115,6 +166,11 @@ export default class Request extends Route {
115
166
  this.disableLoadData = opts.disableLoadData ?? this.disableLoadData;
116
167
  this.statusCode = opts.statusCode ?? this.statusCode;
117
168
  }
169
+ /** @hidden */
170
+ _cancel() {
171
+ this._cancelled = true;
172
+ this._renderBarrier.cancel();
173
+ }
118
174
  }
119
175
  export function isRequest(req) {
120
176
  return typeof req === 'object' && req !== null && req instanceof Request;
@@ -147,12 +203,15 @@ class RenderBarrier {
147
203
  }
148
204
  /** @hidden */
149
205
  cancel() {
206
+ // if the barrier is already open
207
+ // we don't wan't to flag the render as cancelled
208
+ // because it already happened
150
209
  if (this.inner.isOpen())
151
210
  return;
152
211
  this.cancelled = true;
153
212
  this.root.remove();
154
213
  }
155
- // returns if the render was cancelled
214
+ // returns true if the render was cancelled
156
215
  /** @hidden */
157
216
  ready() {
158
217
  return this.root.ready();