crelte 0.3.0 → 0.3.2
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/dist/Crelte.d.ts +12 -0
- package/dist/Crelte.d.ts.map +1 -1
- package/dist/Crelte.js +12 -0
- package/dist/CrelteRequest.d.ts +0 -4
- package/dist/CrelteRequest.d.ts.map +1 -1
- package/dist/CrelteRequest.js +0 -4
- package/dist/entry/EntryRouter.d.ts +30 -0
- package/dist/entry/EntryRouter.d.ts.map +1 -0
- package/dist/entry/EntryRouter.js +45 -0
- package/dist/entry/index.d.ts +32 -0
- package/dist/entry/index.d.ts.map +1 -0
- package/dist/entry/index.js +31 -0
- package/dist/index.d.ts +2 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -6
- package/dist/init/client.d.ts +1 -1
- package/dist/init/client.d.ts.map +1 -1
- package/dist/init/client.js +4 -3
- package/dist/init/server.d.ts.map +1 -1
- package/dist/init/server.js +3 -2
- package/dist/init/shared.d.ts +3 -1
- package/dist/init/shared.d.ts.map +1 -1
- package/dist/init/shared.js +47 -26
- package/dist/routing/InnerRouter.d.ts +1 -10
- package/dist/routing/InnerRouter.d.ts.map +1 -1
- package/dist/routing/InnerRouter.js +20 -21
- package/dist/routing/Request.d.ts +2 -0
- package/dist/routing/Request.d.ts.map +1 -1
- package/dist/routing/Request.js +9 -0
- package/dist/routing/Route.d.ts +67 -1
- package/dist/routing/Route.d.ts.map +1 -1
- package/dist/routing/Route.js +98 -2
- package/dist/routing/Router.d.ts +49 -12
- package/dist/routing/Router.d.ts.map +1 -1
- package/dist/routing/Router.js +82 -28
- package/dist/routing/index.d.ts +2 -2
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +8 -0
- package/package.json +9 -4
- package/src/Crelte.ts +15 -0
- package/src/CrelteRequest.ts +0 -4
- package/src/entry/EntryRouter.ts +71 -0
- package/src/entry/index.ts +48 -0
- package/src/index.ts +2 -11
- package/src/init/client.ts +10 -3
- package/src/init/server.ts +9 -2
- package/src/init/shared.ts +78 -28
- package/src/routing/InnerRouter.ts +29 -30
- package/src/routing/Request.ts +11 -0
- package/src/routing/Route.ts +107 -2
- package/src/routing/Router.ts +110 -31
- package/src/routing/index.ts +2 -1
- package/src/utils.ts +10 -0
package/src/init/shared.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Crelte from '../Crelte.js';
|
|
2
2
|
import CrelteRequest from '../CrelteRequest.js';
|
|
3
|
+
import EntryRouter, { EntryRoutes } from '../entry/EntryRouter.js';
|
|
3
4
|
import { GraphQlQuery } from '../graphql/GraphQl.js';
|
|
4
5
|
import { LoadData, callLoadData } from '../loadData/index.js';
|
|
5
6
|
import { PluginCreator } from '../plugins/Plugins.js';
|
|
@@ -12,6 +13,8 @@ interface App<E, T> {
|
|
|
12
13
|
loadEntryData?: LoadData<any>;
|
|
13
14
|
|
|
14
15
|
templates?: Record<string, LazyTemplateModule<E, T>>;
|
|
16
|
+
|
|
17
|
+
entryRoutes?: EntryRoutes;
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
interface TemplateModule<E, T> {
|
|
@@ -58,14 +61,43 @@ export function getEntry(page: any): any {
|
|
|
58
61
|
};
|
|
59
62
|
}
|
|
60
63
|
|
|
61
|
-
|
|
64
|
+
// todo it would be nice to call this only once per server start
|
|
65
|
+
export async function prepareLoadFn<E, T>(
|
|
66
|
+
crelte: Crelte,
|
|
67
|
+
app: App<E, T>,
|
|
68
|
+
entryQuery: GraphQlQuery,
|
|
69
|
+
globalQuery?: GraphQlQuery,
|
|
70
|
+
): Promise<(cr: CrelteRequest, loadOpts?: LoadOptions) => Promise<any>> {
|
|
71
|
+
const templateModules = prepareTemplates(app.templates ?? {});
|
|
72
|
+
let entryRouter: EntryRouter | null = null;
|
|
73
|
+
if (app.entryRoutes) {
|
|
74
|
+
entryRouter = new EntryRouter(crelte);
|
|
75
|
+
await app.entryRoutes(entryRouter);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return async (cr, loadOpts) => {
|
|
79
|
+
return await loadFn(
|
|
80
|
+
cr,
|
|
81
|
+
app,
|
|
82
|
+
templateModules,
|
|
83
|
+
entryRouter,
|
|
84
|
+
entryQuery,
|
|
85
|
+
globalQuery,
|
|
86
|
+
loadOpts,
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function loadFn<E, T>(
|
|
62
92
|
cr: CrelteRequest,
|
|
63
93
|
app: App<E, T>,
|
|
94
|
+
templateModules: Map<string, LazyTemplateModule<E, T>>,
|
|
95
|
+
entryRouter: EntryRouter | null,
|
|
64
96
|
entryQuery: GraphQlQuery,
|
|
65
97
|
globalQuery?: GraphQlQuery,
|
|
66
98
|
loadOpts?: LoadOptions,
|
|
67
99
|
): Promise<any> {
|
|
68
|
-
let dataProm: Promise<
|
|
100
|
+
let dataProm: Promise<any> | null = null;
|
|
69
101
|
// @ts-ignore
|
|
70
102
|
if (app.loadData) {
|
|
71
103
|
throw new Error(
|
|
@@ -93,43 +125,29 @@ export async function loadFn<D, E, T>(
|
|
|
93
125
|
})();
|
|
94
126
|
}
|
|
95
127
|
|
|
96
|
-
|
|
97
|
-
if (cr.req.siteMatches()) {
|
|
98
|
-
let uri = decodeURI(cr.req.uri);
|
|
99
|
-
if (uri.startsWith('/')) uri = uri.substring(1);
|
|
100
|
-
if (uri === '' || uri === '/') uri = '__home__';
|
|
101
|
-
|
|
102
|
-
pageProm = cr.query(entryQuery, {
|
|
103
|
-
uri,
|
|
104
|
-
siteId: cr.site.id,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
128
|
+
const entryProm = queryEntry(cr, app, entryRouter, entryQuery);
|
|
107
129
|
|
|
108
130
|
const pluginsLoadGlobalData = cr.events.trigger('loadGlobalData', cr);
|
|
109
131
|
|
|
110
132
|
// loading progress is at 20%
|
|
111
133
|
loadOpts?.setProgress(0.2);
|
|
112
134
|
|
|
113
|
-
const [data, global,
|
|
135
|
+
const [data, global, entry] = await Promise.all([
|
|
114
136
|
dataProm,
|
|
115
137
|
globalProm,
|
|
116
|
-
|
|
138
|
+
entryProm,
|
|
117
139
|
...pluginsLoadGlobalData,
|
|
118
140
|
]);
|
|
119
141
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
// so any waiters get's triggered
|
|
125
|
-
cr.globals._setData(cr.site.id, {});
|
|
142
|
+
// global is only set if !wasLoaded but we need to store something
|
|
143
|
+
// even if no globalQuery exists
|
|
144
|
+
if (global || !cr.globals._wasLoaded(cr.site.id)) {
|
|
145
|
+
cr.globals._setData(cr.site.id, global ?? {});
|
|
126
146
|
}
|
|
127
147
|
|
|
128
|
-
const entry = getEntry(page);
|
|
129
|
-
|
|
130
148
|
let template;
|
|
131
149
|
if (app.templates) {
|
|
132
|
-
template = await loadTemplate(
|
|
150
|
+
template = await loadTemplate(templateModules, entry);
|
|
133
151
|
} else {
|
|
134
152
|
throw new Error('App must have templates or loadTemplate method');
|
|
135
153
|
}
|
|
@@ -180,12 +198,39 @@ function parseFilename(path: string): [string, string] {
|
|
|
180
198
|
return [name, ext];
|
|
181
199
|
}
|
|
182
200
|
|
|
183
|
-
async function
|
|
201
|
+
async function queryEntry<E, T>(
|
|
202
|
+
cr: CrelteRequest,
|
|
203
|
+
app: App<E, T>,
|
|
204
|
+
entryRouter: EntryRouter | null,
|
|
205
|
+
entryQuery: GraphQlQuery,
|
|
206
|
+
): Promise<any | null> {
|
|
207
|
+
// check
|
|
208
|
+
if (entryRouter) {
|
|
209
|
+
const entry = await entryRouter._handle(cr);
|
|
210
|
+
if (entry) return entry;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (cr.req.siteMatches()) {
|
|
214
|
+
let uri = decodeURI(cr.req.uri);
|
|
215
|
+
if (uri.startsWith('/')) uri = uri.substring(1);
|
|
216
|
+
if (uri === '' || uri === '/') uri = '__home__';
|
|
217
|
+
|
|
218
|
+
const page = await cr.query(entryQuery, {
|
|
219
|
+
uri,
|
|
220
|
+
siteId: cr.site.id,
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
return getEntry(page);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function prepareTemplates<E, T>(
|
|
184
230
|
rawModules: Record<string, LazyTemplateModule<E, T>>,
|
|
185
|
-
|
|
186
|
-
): Promise<TemplateModule<E, T>> {
|
|
231
|
+
): Map<string, LazyTemplateModule<E, T>> {
|
|
187
232
|
// parse modules
|
|
188
|
-
|
|
233
|
+
return new Map(
|
|
189
234
|
Object.entries(rawModules)
|
|
190
235
|
.map(([path, mod]) => {
|
|
191
236
|
const [name, _ext] = parseFilename(path);
|
|
@@ -193,7 +238,12 @@ async function loadTemplate<E, T>(
|
|
|
193
238
|
})
|
|
194
239
|
.filter(([name, _mod]) => !!name),
|
|
195
240
|
);
|
|
241
|
+
}
|
|
196
242
|
|
|
243
|
+
async function loadTemplate<E, T>(
|
|
244
|
+
modules: Map<string, LazyTemplateModule<E, T>>,
|
|
245
|
+
entry: E,
|
|
246
|
+
): Promise<TemplateModule<E, T>> {
|
|
197
247
|
const entr = entry as any;
|
|
198
248
|
const handle = `${entr.sectionHandle}-${entr.typeHandle}`;
|
|
199
249
|
|
|
@@ -68,7 +68,10 @@ export default class InnerRouter {
|
|
|
68
68
|
req.origin = 'init';
|
|
69
69
|
window.history.scrollRestoration = 'manual';
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
// we set it now instead of waiting for the onRoute call
|
|
72
|
+
// because the window.history is already set
|
|
73
|
+
this.route = req.toRoute();
|
|
74
|
+
this.onRoute(req, () => {});
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
/**
|
|
@@ -301,7 +304,10 @@ export default class InnerRouter {
|
|
|
301
304
|
req._fillFromState(e.state);
|
|
302
305
|
req.origin = 'pop';
|
|
303
306
|
|
|
304
|
-
|
|
307
|
+
// we set it now instead of waiting for the onRoute call
|
|
308
|
+
// because the window.history was already modified
|
|
309
|
+
this.route = req.toRoute();
|
|
310
|
+
this.onRoute(req, () => {});
|
|
305
311
|
});
|
|
306
312
|
}
|
|
307
313
|
|
|
@@ -350,24 +356,15 @@ export default class InnerRouter {
|
|
|
350
356
|
|
|
351
357
|
req.index = (current?.index ?? 0) + 1;
|
|
352
358
|
this.onRoute(req, () => {
|
|
353
|
-
|
|
359
|
+
const url = req.url;
|
|
360
|
+
this.history.pushState(
|
|
361
|
+
req._toState(),
|
|
362
|
+
url.pathname + url.search + url.hash,
|
|
363
|
+
);
|
|
364
|
+
this.route = req.toRoute();
|
|
354
365
|
});
|
|
355
366
|
}
|
|
356
367
|
|
|
357
|
-
/**
|
|
358
|
-
* Sets a route
|
|
359
|
-
*
|
|
360
|
-
* Will trigger an onRoute event but will not store any scroll progress
|
|
361
|
-
* or modify the history
|
|
362
|
-
*
|
|
363
|
-
* @param req
|
|
364
|
-
*/
|
|
365
|
-
setRoute(req: Request, preventOnRoute = false) {
|
|
366
|
-
this.route = req.toRoute();
|
|
367
|
-
|
|
368
|
-
if (!preventOnRoute) this.onRoute(req, () => {});
|
|
369
|
-
}
|
|
370
|
-
|
|
371
368
|
/**
|
|
372
369
|
* This pushes a new route to the history
|
|
373
370
|
*
|
|
@@ -376,7 +373,7 @@ export default class InnerRouter {
|
|
|
376
373
|
* ## Important
|
|
377
374
|
* Make sure the route has the correct origin
|
|
378
375
|
*/
|
|
379
|
-
push(req: Request
|
|
376
|
+
push(req: Request) {
|
|
380
377
|
const url = req.url;
|
|
381
378
|
// todo a push should also store the previous scrollY
|
|
382
379
|
|
|
@@ -390,12 +387,13 @@ export default class InnerRouter {
|
|
|
390
387
|
nReq.scrollY = this.history.scrollY();
|
|
391
388
|
}
|
|
392
389
|
|
|
393
|
-
this.
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
390
|
+
this.onRoute(req, () => {
|
|
391
|
+
this.history.pushState(
|
|
392
|
+
req._toState(),
|
|
393
|
+
url.pathname + url.search + url.hash,
|
|
394
|
+
);
|
|
395
|
+
this.route = req.toRoute();
|
|
396
|
+
});
|
|
399
397
|
}
|
|
400
398
|
|
|
401
399
|
/**
|
|
@@ -420,12 +418,13 @@ export default class InnerRouter {
|
|
|
420
418
|
nReq.scrollY = this.history.scrollY();
|
|
421
419
|
}
|
|
422
420
|
|
|
423
|
-
this.
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
421
|
+
this.onRoute(req, () => {
|
|
422
|
+
this.history.replaceState(
|
|
423
|
+
req._toState(),
|
|
424
|
+
url.pathname + url.search + url.hash,
|
|
425
|
+
);
|
|
426
|
+
this.route = req.toRoute();
|
|
427
|
+
});
|
|
429
428
|
}
|
|
430
429
|
|
|
431
430
|
/**
|
package/src/routing/Request.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Barrier } from 'crelte-std/sync';
|
|
2
2
|
import Route, { RouteOrigin } from './Route.js';
|
|
3
3
|
import Site from './Site.js';
|
|
4
|
+
import { objClone } from '../utils.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Options to create a Request
|
|
@@ -9,6 +10,8 @@ export type RequestOptions = {
|
|
|
9
10
|
scrollY?: number;
|
|
10
11
|
index?: number;
|
|
11
12
|
origin?: RouteOrigin;
|
|
13
|
+
state?: Record<string, any>;
|
|
14
|
+
context?: Record<string, any>;
|
|
12
15
|
disableScroll?: boolean;
|
|
13
16
|
disableLoadData?: boolean;
|
|
14
17
|
statusCode?: number;
|
|
@@ -60,6 +63,8 @@ export default class Request extends Route {
|
|
|
60
63
|
scrollY: route.scrollY ?? undefined,
|
|
61
64
|
index: route.index,
|
|
62
65
|
origin: route.origin,
|
|
66
|
+
state: route._state,
|
|
67
|
+
context: route._context,
|
|
63
68
|
...opts,
|
|
64
69
|
});
|
|
65
70
|
}
|
|
@@ -104,6 +109,8 @@ export default class Request extends Route {
|
|
|
104
109
|
scrollY: this.scrollY ?? undefined,
|
|
105
110
|
index: this.index,
|
|
106
111
|
origin: this.origin,
|
|
112
|
+
state: objClone(this._state),
|
|
113
|
+
context: this._context,
|
|
107
114
|
disableScroll: this.disableScroll,
|
|
108
115
|
statusCode: this.statusCode ?? undefined,
|
|
109
116
|
});
|
|
@@ -117,6 +124,8 @@ export default class Request extends Route {
|
|
|
117
124
|
scrollY: this.scrollY ?? undefined,
|
|
118
125
|
index: this.index,
|
|
119
126
|
origin: this.origin,
|
|
127
|
+
state: objClone(this._state),
|
|
128
|
+
context: this._context,
|
|
120
129
|
});
|
|
121
130
|
}
|
|
122
131
|
|
|
@@ -125,6 +134,8 @@ export default class Request extends Route {
|
|
|
125
134
|
this.scrollY = opts.scrollY ?? this.scrollY;
|
|
126
135
|
this.index = opts.index ?? this.index;
|
|
127
136
|
this.origin = opts.origin ?? this.origin;
|
|
137
|
+
this._state = opts.state ?? this._state;
|
|
138
|
+
this._context = opts.context ?? this._context;
|
|
128
139
|
this.disableScroll = opts.disableScroll ?? this.disableScroll;
|
|
129
140
|
this.statusCode = opts.statusCode ?? this.statusCode;
|
|
130
141
|
}
|
package/src/routing/Route.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { objClone } from '../utils.js';
|
|
1
2
|
import Site from './Site.js';
|
|
2
3
|
import { trimSlashEnd } from './utils.js';
|
|
3
4
|
|
|
@@ -5,6 +6,8 @@ export type RouteOptions = {
|
|
|
5
6
|
scrollY?: number;
|
|
6
7
|
index?: number;
|
|
7
8
|
origin?: RouteOrigin;
|
|
9
|
+
state?: Record<string, any>;
|
|
10
|
+
context?: Record<string, any>;
|
|
8
11
|
};
|
|
9
12
|
|
|
10
13
|
/**
|
|
@@ -74,6 +77,25 @@ export default class Route {
|
|
|
74
77
|
*/
|
|
75
78
|
origin: RouteOrigin;
|
|
76
79
|
|
|
80
|
+
/**
|
|
81
|
+
* @hidden
|
|
82
|
+
* State data that can be used to store additional information
|
|
83
|
+
*/
|
|
84
|
+
_state: Record<string, any>;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @hidden
|
|
88
|
+
* Any data that should be passed to onRoute and onRequest handlers
|
|
89
|
+
* or exchanged between loadData's
|
|
90
|
+
* This context is not persistant and should be considered "valid"
|
|
91
|
+
* only for the current request / route
|
|
92
|
+
*
|
|
93
|
+
* ## Note
|
|
94
|
+
* Consider using state instead. This will not be cloned in the clone
|
|
95
|
+
* call so will always be the same object
|
|
96
|
+
*/
|
|
97
|
+
_context: Record<string, any>;
|
|
98
|
+
|
|
77
99
|
/**
|
|
78
100
|
* Creates a new Route
|
|
79
101
|
*/
|
|
@@ -84,6 +106,8 @@ export default class Route {
|
|
|
84
106
|
this.scrollY = opts.scrollY ?? null;
|
|
85
107
|
this.index = opts.index ?? 0;
|
|
86
108
|
this.origin = opts.origin ?? 'manual';
|
|
109
|
+
this._state = opts.state ?? {};
|
|
110
|
+
this._context = opts.context ?? {};
|
|
87
111
|
}
|
|
88
112
|
|
|
89
113
|
/**
|
|
@@ -163,6 +187,20 @@ export default class Route {
|
|
|
163
187
|
return this.url.hash;
|
|
164
188
|
}
|
|
165
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Set the hash of the route
|
|
192
|
+
*
|
|
193
|
+
* ## Example
|
|
194
|
+
* ```
|
|
195
|
+
* const route = new Route('https://example.com/foo/bar/', null);
|
|
196
|
+
* route.hash = '#hash';
|
|
197
|
+
* console.log(route.url.href); // 'https://example.com/foo/bar/#hash'
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
set hash(hash: string) {
|
|
201
|
+
this.url.hash = hash;
|
|
202
|
+
}
|
|
203
|
+
|
|
166
204
|
/**
|
|
167
205
|
* Checks if there are previous routes which would allow it to go back
|
|
168
206
|
*/
|
|
@@ -184,7 +222,8 @@ export default class Route {
|
|
|
184
222
|
}
|
|
185
223
|
|
|
186
224
|
/**
|
|
187
|
-
* Sets the search param or removes it if the value is null or
|
|
225
|
+
* Sets the search param or removes it if the value is null, undefined or an
|
|
226
|
+
* empty string
|
|
188
227
|
*
|
|
189
228
|
* ## Example
|
|
190
229
|
* ```
|
|
@@ -197,13 +236,69 @@ export default class Route {
|
|
|
197
236
|
* ```
|
|
198
237
|
*/
|
|
199
238
|
setSearchParam(key: string, value?: string | number | null) {
|
|
200
|
-
|
|
239
|
+
const deleteValue =
|
|
240
|
+
typeof value === 'undefined' ||
|
|
241
|
+
value === null ||
|
|
242
|
+
(typeof value === 'string' && value === '');
|
|
243
|
+
|
|
244
|
+
if (!deleteValue) {
|
|
201
245
|
this.search.set(key, value as string);
|
|
202
246
|
} else {
|
|
203
247
|
this.search.delete(key);
|
|
204
248
|
}
|
|
205
249
|
}
|
|
206
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Returns a state value if it exists.
|
|
253
|
+
*/
|
|
254
|
+
getState<T = any>(key: string): T | null {
|
|
255
|
+
return this._state[key] ?? null;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Sets a state value.
|
|
260
|
+
* If the value is null or undefined, the key will be removed.
|
|
261
|
+
*
|
|
262
|
+
* ## When to use state
|
|
263
|
+
* State is used to store additional information that persists across route changes.
|
|
264
|
+
* The State is only available in the client code since it is stored using window.history.
|
|
265
|
+
*
|
|
266
|
+
* Consider using setSearchParam instead to enable server side rendering.
|
|
267
|
+
*/
|
|
268
|
+
setState<T>(key: string, value: T | null | undefined) {
|
|
269
|
+
if (typeof value === 'undefined' || value === null) {
|
|
270
|
+
delete this._state[key];
|
|
271
|
+
} else {
|
|
272
|
+
this._state[key] = value;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Returns a context value if it exists.
|
|
278
|
+
*/
|
|
279
|
+
getContext<T = any>(key: string): T | null {
|
|
280
|
+
return this._context[key] ?? null;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Sets a context value.
|
|
285
|
+
* If the value is null or undefined, the key will be removed.
|
|
286
|
+
*
|
|
287
|
+
* ## When to use context
|
|
288
|
+
* Context is used to pass data to onRoute and onRequest handlers or exchange data between loadData calls.
|
|
289
|
+
* This context is not persistent and should be considered valid only for the current request/route.
|
|
290
|
+
* The context is not cloned in the clone call and will be the same object.
|
|
291
|
+
*/
|
|
292
|
+
setContext<T>(key: string, value: T | null | undefined) {
|
|
293
|
+
if (typeof value === 'undefined' || value === null) {
|
|
294
|
+
delete this._context[key];
|
|
295
|
+
} else {
|
|
296
|
+
this._context[key] = value;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Returns true if the route is in live preview mode
|
|
301
|
+
*/
|
|
207
302
|
inLivePreview(): boolean {
|
|
208
303
|
return !!this.search.get('x-craft-live-preview');
|
|
209
304
|
}
|
|
@@ -229,6 +324,9 @@ export default class Route {
|
|
|
229
324
|
*
|
|
230
325
|
* This checks all properties of the url but search params do not have to be
|
|
231
326
|
* in the same order
|
|
327
|
+
*
|
|
328
|
+
* ## Note
|
|
329
|
+
* This does not check the state or context
|
|
232
330
|
*/
|
|
233
331
|
eq(route: Route | null) {
|
|
234
332
|
return (
|
|
@@ -288,6 +386,8 @@ export default class Route {
|
|
|
288
386
|
scrollY: this.scrollY ?? undefined,
|
|
289
387
|
index: this.index,
|
|
290
388
|
origin: this.origin,
|
|
389
|
+
state: objClone(this._state),
|
|
390
|
+
context: this._context,
|
|
291
391
|
});
|
|
292
392
|
}
|
|
293
393
|
|
|
@@ -298,6 +398,10 @@ export default class Route {
|
|
|
298
398
|
|
|
299
399
|
if (typeof state?.route?.index === 'number')
|
|
300
400
|
this.index = state.route.index;
|
|
401
|
+
|
|
402
|
+
if (typeof state?.state === 'object' && state.state !== null) {
|
|
403
|
+
this._state = state.state;
|
|
404
|
+
}
|
|
301
405
|
}
|
|
302
406
|
|
|
303
407
|
/** @hidden */
|
|
@@ -307,6 +411,7 @@ export default class Route {
|
|
|
307
411
|
scrollY: this.scrollY,
|
|
308
412
|
index: this.index,
|
|
309
413
|
},
|
|
414
|
+
state: this._state,
|
|
310
415
|
};
|
|
311
416
|
}
|
|
312
417
|
}
|