crelte 0.1.3 → 0.2.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.
- package/dist/CrelteRequest.d.ts +11 -6
- package/dist/CrelteRequest.d.ts.map +1 -1
- package/dist/CrelteRequest.js +14 -14
- package/dist/graphql/GraphQl.d.ts +1 -1
- package/dist/graphql/GraphQl.d.ts.map +1 -1
- package/dist/graphql/GraphQl.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -3
- package/dist/init/client.d.ts.map +1 -1
- package/dist/init/client.js +11 -5
- package/dist/init/server.d.ts +2 -0
- package/dist/init/server.d.ts.map +1 -1
- package/dist/init/server.js +24 -10
- package/dist/init/shared.d.ts +3 -3
- package/dist/init/shared.d.ts.map +1 -1
- package/dist/init/shared.js +1 -1
- package/dist/loadData/index.d.ts +11 -5
- package/dist/loadData/index.d.ts.map +1 -1
- package/dist/loadData/index.js +15 -6
- package/dist/routing/History.d.ts +5 -3
- package/dist/routing/History.d.ts.map +1 -1
- package/dist/routing/History.js +9 -4
- package/dist/routing/InnerRouter.d.ts +31 -21
- package/dist/routing/InnerRouter.d.ts.map +1 -1
- package/dist/routing/InnerRouter.js +98 -76
- package/dist/routing/PageLoader.d.ts +4 -5
- package/dist/routing/PageLoader.d.ts.map +1 -1
- package/dist/routing/PageLoader.js +5 -5
- package/dist/routing/Request.d.ts +15 -2
- package/dist/routing/Request.d.ts.map +1 -1
- package/dist/routing/Request.js +22 -1
- package/dist/routing/Route.d.ts +61 -25
- package/dist/routing/Route.d.ts.map +1 -1
- package/dist/routing/Route.js +90 -41
- package/dist/routing/Router.d.ts +34 -13
- package/dist/routing/Router.d.ts.map +1 -1
- package/dist/routing/Router.js +102 -49
- package/package.json +3 -2
- package/src/CrelteRequest.ts +14 -19
- package/src/graphql/GraphQl.ts +5 -2
- package/src/index.ts +26 -3
- package/src/init/client.ts +14 -10
- package/src/init/server.ts +31 -11
- package/src/init/shared.ts +4 -4
- package/src/loadData/index.ts +47 -15
- package/src/routing/History.ts +12 -5
- package/src/routing/InnerRouter.ts +109 -82
- package/src/routing/PageLoader.ts +7 -17
- package/src/routing/Request.ts +28 -6
- package/src/routing/Route.ts +115 -52
- package/src/routing/Router.ts +123 -59
- package/LICENSE.md +0 -41
package/dist/routing/Router.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import Route from './Route.js';
|
|
2
1
|
import InnerRouter from './InnerRouter.js';
|
|
3
2
|
import PageLoader from './PageLoader.js';
|
|
4
3
|
import { Writable } from 'crelte-std/stores';
|
|
@@ -29,7 +28,6 @@ export default class Router {
|
|
|
29
28
|
* The loading progress, the value is between 0 and 1
|
|
30
29
|
*/
|
|
31
30
|
_loadingProgress;
|
|
32
|
-
_onRouteEv;
|
|
33
31
|
_onRequest;
|
|
34
32
|
/** @hidden */
|
|
35
33
|
_internal;
|
|
@@ -49,19 +47,19 @@ export default class Router {
|
|
|
49
47
|
this._request = null;
|
|
50
48
|
this._loading = new Writable(false);
|
|
51
49
|
this._loadingProgress = new Writable(0);
|
|
52
|
-
this._onRouteEv = new Listeners();
|
|
53
50
|
this._onRequest = new Listeners();
|
|
54
51
|
this._internal = {
|
|
55
52
|
onLoaded: () => { },
|
|
53
|
+
onNothingLoaded: () => { },
|
|
56
54
|
onLoad: () => { },
|
|
57
55
|
domReady: req => this.inner.domReady(req),
|
|
58
56
|
initClient: () => this._initClient(),
|
|
59
57
|
initServer: (url, acceptLang) => this._initServer(url, acceptLang),
|
|
60
58
|
};
|
|
61
|
-
this.inner.onRoute = (route,
|
|
62
|
-
this.inner.onPreload =
|
|
63
|
-
this.pageLoader.onLoaded = (resp, req,
|
|
64
|
-
this.pageLoader.loadFn = (req,
|
|
59
|
+
this.inner.onRoute = (route, changeHistory) => this._onRoute(route, changeHistory);
|
|
60
|
+
this.inner.onPreload = route => this._onPreload(route);
|
|
61
|
+
this.pageLoader.onLoaded = (resp, req, more) => this._onLoaded(resp, req, more);
|
|
62
|
+
this.pageLoader.loadFn = (req, opts) => this._internal.onLoad(req, opts);
|
|
65
63
|
this.pageLoader.onProgress = (loading, progress) => this._onProgress(loading, progress);
|
|
66
64
|
}
|
|
67
65
|
/**
|
|
@@ -97,10 +95,13 @@ export default class Router {
|
|
|
97
95
|
/**
|
|
98
96
|
* Open a new route
|
|
99
97
|
*
|
|
100
|
-
* @param target the target to open can be an url or a
|
|
98
|
+
* @param target the target to open can be an url, a route or a request
|
|
101
99
|
* the url needs to start with http or with a / which will be considered as
|
|
102
100
|
* the site baseUrl
|
|
103
101
|
*
|
|
102
|
+
* ## Note
|
|
103
|
+
* The origin will always be set to 'manual'
|
|
104
|
+
*
|
|
104
105
|
* ## Example
|
|
105
106
|
* ```
|
|
106
107
|
* import { getRouter } from 'crelte';
|
|
@@ -112,15 +113,24 @@ export default class Router {
|
|
|
112
113
|
* // the following page will be opened https://example.com/de/foo/bar
|
|
113
114
|
* ```
|
|
114
115
|
*/
|
|
115
|
-
open(target) {
|
|
116
|
-
this.inner.
|
|
116
|
+
open(target, opts = {}) {
|
|
117
|
+
const req = this.inner.targetToRequest(target, {
|
|
118
|
+
...opts,
|
|
119
|
+
origin: 'manual',
|
|
120
|
+
});
|
|
121
|
+
this.inner.open(req);
|
|
117
122
|
}
|
|
118
123
|
/**
|
|
119
|
-
* This pushes the
|
|
124
|
+
* This pushes the new route without triggering a new pageload
|
|
120
125
|
*
|
|
121
126
|
* You can use this when using pagination for example change the route object
|
|
122
127
|
* (search argument) and then call pushState
|
|
123
128
|
*
|
|
129
|
+
* ## Note
|
|
130
|
+
* This will always set the origin to 'push'
|
|
131
|
+
* And will clear the scrollY value if you not provide a new one via the `opts`
|
|
132
|
+
* This will disableLoadData by default if you not provide an override via the `opts`
|
|
133
|
+
*
|
|
124
134
|
* ## Example
|
|
125
135
|
* ```
|
|
126
136
|
* import { getRouter } from 'crelte';
|
|
@@ -133,16 +143,35 @@ export default class Router {
|
|
|
133
143
|
* router.pushState(route);
|
|
134
144
|
* ```
|
|
135
145
|
*/
|
|
136
|
-
|
|
146
|
+
push(route, opts = {}) {
|
|
147
|
+
// cancel previous request
|
|
137
148
|
this.pageLoader.discard();
|
|
138
|
-
this.inner.
|
|
149
|
+
const req = this.inner.targetToRequest(route, {
|
|
150
|
+
...opts,
|
|
151
|
+
origin: 'push',
|
|
152
|
+
scrollY: opts.scrollY ?? undefined,
|
|
153
|
+
disableLoadData: opts.disableLoadData ?? true,
|
|
154
|
+
});
|
|
155
|
+
this.inner.push(req);
|
|
156
|
+
this.destroyRequest();
|
|
139
157
|
this.setNewRoute(route);
|
|
140
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* @deprecated use push instead
|
|
161
|
+
*/
|
|
162
|
+
pushState(route) {
|
|
163
|
+
this.push(route);
|
|
164
|
+
}
|
|
141
165
|
/**
|
|
142
166
|
* This replaces the state of the route without triggering an event
|
|
143
167
|
*
|
|
144
168
|
* You can use this when using some filters for example a search filter
|
|
145
169
|
*
|
|
170
|
+
* ## Note
|
|
171
|
+
* This will always set the origin to 'replace'
|
|
172
|
+
* And will clear the scrollY value if you not provide a new one via the `opts`
|
|
173
|
+
* This will disableLoadData by default if you not provide an override via the `opts`
|
|
174
|
+
*
|
|
146
175
|
* ## Example
|
|
147
176
|
* ```
|
|
148
177
|
* import { getRouter } from 'crelte';
|
|
@@ -155,10 +184,23 @@ export default class Router {
|
|
|
155
184
|
* router.replaceState(route);
|
|
156
185
|
* ```
|
|
157
186
|
*/
|
|
158
|
-
|
|
187
|
+
replace(route, opts = {}) {
|
|
188
|
+
// cancel previous request
|
|
159
189
|
this.pageLoader.discard();
|
|
160
|
-
this.inner.
|
|
161
|
-
|
|
190
|
+
const req = this.inner.targetToRequest(route, {
|
|
191
|
+
origin: 'replace',
|
|
192
|
+
scrollY: opts.scrollY ?? undefined,
|
|
193
|
+
disableLoadData: opts.disableLoadData ?? true,
|
|
194
|
+
});
|
|
195
|
+
this.inner.replace(req);
|
|
196
|
+
this.destroyRequest();
|
|
197
|
+
this.setNewRoute(req);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* @deprecated use replace instead
|
|
201
|
+
*/
|
|
202
|
+
replaceState(route) {
|
|
203
|
+
this.replace(route);
|
|
162
204
|
}
|
|
163
205
|
/**
|
|
164
206
|
* Checks if there are previous routes which would allow it to go back
|
|
@@ -181,13 +223,13 @@ export default class Router {
|
|
|
181
223
|
/**
|
|
182
224
|
* Add a listener for the onRoute event
|
|
183
225
|
*
|
|
184
|
-
* This
|
|
185
|
-
*
|
|
226
|
+
* This will trigger every time a new route is set
|
|
227
|
+
* and is equivalent to router.route.subscribe(fn)
|
|
186
228
|
*
|
|
187
229
|
* @returns a function to remove the listener
|
|
188
230
|
*/
|
|
189
231
|
onRoute(fn) {
|
|
190
|
-
return this.
|
|
232
|
+
return this.route.subscribe(fn);
|
|
191
233
|
}
|
|
192
234
|
/**
|
|
193
235
|
* Add a listener for the onRequest event
|
|
@@ -200,12 +242,11 @@ export default class Router {
|
|
|
200
242
|
return this._onRequest.add(fn);
|
|
201
243
|
}
|
|
202
244
|
setNewRoute(route) {
|
|
203
|
-
this.destroyRequest();
|
|
204
245
|
this._route.setSilent(route);
|
|
205
|
-
|
|
206
|
-
|
|
246
|
+
const siteChanged = this.site.get()?.id !== route.site.id;
|
|
247
|
+
this._site.setSilent(route.site);
|
|
207
248
|
this._route.notify();
|
|
208
|
-
if (
|
|
249
|
+
if (siteChanged)
|
|
209
250
|
this._site.notify();
|
|
210
251
|
}
|
|
211
252
|
async _initClient() {
|
|
@@ -213,15 +254,17 @@ export default class Router {
|
|
|
213
254
|
}
|
|
214
255
|
async _initServer(url, acceptLang) {
|
|
215
256
|
this.inner.initServer();
|
|
257
|
+
this._internal.onNothingLoaded = (_req, ready) => {
|
|
258
|
+
ready();
|
|
259
|
+
};
|
|
216
260
|
const prom = new Promise(resolve => {
|
|
217
|
-
this._internal.onLoaded = (success, req,
|
|
261
|
+
this._internal.onLoaded = (success, req, ready) => {
|
|
218
262
|
const props = ready();
|
|
219
263
|
this._internal.onLoaded = () => { };
|
|
220
264
|
resolve({
|
|
221
265
|
success,
|
|
222
266
|
redirect: false,
|
|
223
267
|
req,
|
|
224
|
-
site,
|
|
225
268
|
props,
|
|
226
269
|
});
|
|
227
270
|
};
|
|
@@ -230,43 +273,46 @@ export default class Router {
|
|
|
230
273
|
route.origin = 'init';
|
|
231
274
|
// let's see if the url matches any route and site
|
|
232
275
|
// if not let's redirect to the site which matches the acceptLang
|
|
233
|
-
if (!route.
|
|
276
|
+
if (!route.siteMatches()) {
|
|
234
277
|
const site = this.inner.siteByAcceptLang(acceptLang);
|
|
235
278
|
return {
|
|
236
279
|
success: true,
|
|
237
280
|
redirect: true,
|
|
238
281
|
req: new Request(site.url, site),
|
|
239
|
-
site,
|
|
240
282
|
props: {},
|
|
241
283
|
};
|
|
242
284
|
}
|
|
243
285
|
this.inner.setRoute(route);
|
|
244
286
|
const resp = await prom;
|
|
245
287
|
const hist = this.inner.history;
|
|
246
|
-
if (hist.url) {
|
|
247
|
-
const
|
|
248
|
-
if (!route.eq(
|
|
288
|
+
if (hist.url || hist.req) {
|
|
289
|
+
const nReq = this.inner.targetToRequest(hist.req ?? hist.url);
|
|
290
|
+
if (!route.eq(nReq)) {
|
|
249
291
|
return {
|
|
250
292
|
success: true,
|
|
251
293
|
redirect: true,
|
|
252
|
-
req:
|
|
253
|
-
site: route.site,
|
|
294
|
+
req: nReq,
|
|
254
295
|
props: {},
|
|
255
296
|
};
|
|
256
297
|
}
|
|
257
298
|
}
|
|
258
299
|
return resp;
|
|
259
300
|
}
|
|
260
|
-
_onRoute(req,
|
|
301
|
+
_onRoute(req, changeHistory) {
|
|
261
302
|
this.destroyRequest();
|
|
262
303
|
this._request = req;
|
|
263
304
|
const barrier = req._renderBarrier;
|
|
264
305
|
if (barrier.isOpen()) {
|
|
265
306
|
throw new Error('render barrier is already open');
|
|
266
307
|
}
|
|
267
|
-
this._onRequest.trigger(req
|
|
308
|
+
this._onRequest.trigger(req);
|
|
268
309
|
// route prepared
|
|
269
|
-
|
|
310
|
+
if (!req.disableLoadData) {
|
|
311
|
+
this.pageLoader.load(req, { changeHistory });
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
this._onNothingLoaded(req, { changeHistory });
|
|
315
|
+
}
|
|
270
316
|
}
|
|
271
317
|
destroyRequest() {
|
|
272
318
|
if (!this._request)
|
|
@@ -274,10 +320,10 @@ export default class Router {
|
|
|
274
320
|
this._request._renderBarrier.cancel();
|
|
275
321
|
this._request = null;
|
|
276
322
|
}
|
|
277
|
-
_onPreload(req
|
|
278
|
-
this.pageLoader.preload(req
|
|
323
|
+
_onPreload(req) {
|
|
324
|
+
this.pageLoader.preload(req);
|
|
279
325
|
}
|
|
280
|
-
async _onLoaded(resp, req,
|
|
326
|
+
async _onLoaded(resp, req, more) {
|
|
281
327
|
// check if the render was cancelled
|
|
282
328
|
if (await req._renderBarrier.ready())
|
|
283
329
|
return;
|
|
@@ -286,20 +332,27 @@ export default class Router {
|
|
|
286
332
|
// in the meantime
|
|
287
333
|
more.changeHistory();
|
|
288
334
|
const route = req.toRoute();
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
this._site.setSilent(site);
|
|
293
|
-
this._route.notify();
|
|
294
|
-
if (siteChanged)
|
|
295
|
-
this._site.notify();
|
|
296
|
-
this._onRouteEv.trigger(route.clone(), site);
|
|
297
|
-
};
|
|
298
|
-
this._internal.onLoaded(resp.success, req, site, () => {
|
|
299
|
-
updateRoute();
|
|
335
|
+
// call the client or server saying we are ready for a new render
|
|
336
|
+
this._internal.onLoaded(resp.success, req, () => {
|
|
337
|
+
this.setNewRoute(route);
|
|
300
338
|
return resp.data;
|
|
301
339
|
});
|
|
302
340
|
}
|
|
341
|
+
async _onNothingLoaded(req, more) {
|
|
342
|
+
// check if the render was cancelled
|
|
343
|
+
if (await req._renderBarrier.ready())
|
|
344
|
+
return;
|
|
345
|
+
// when the data is loaded let's update the route of the inner
|
|
346
|
+
// this is will only happen if no other route has been requested
|
|
347
|
+
// in the meantime
|
|
348
|
+
more.changeHistory();
|
|
349
|
+
const route = req.toRoute();
|
|
350
|
+
// call the client or server saying there was an update in the route
|
|
351
|
+
// but no new data was loaded so no render should happen
|
|
352
|
+
this._internal.onNothingLoaded(req, () => {
|
|
353
|
+
this.setNewRoute(route);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
303
356
|
_onProgress(loading, progress) {
|
|
304
357
|
if (this._loading.get() !== loading)
|
|
305
358
|
this._loading.set(loading);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crelte",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"author": "Crelte <support@crelte.com>",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -74,6 +74,7 @@
|
|
|
74
74
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
|
75
75
|
"svelte-check": "^4.1.4",
|
|
76
76
|
"typescript-svelte-plugin": "^0.3.45",
|
|
77
|
-
"vitest": "^2.0.0"
|
|
77
|
+
"vitest": "^2.0.0",
|
|
78
|
+
"vite": "^5.0"
|
|
78
79
|
}
|
|
79
80
|
}
|
package/src/CrelteRequest.ts
CHANGED
|
@@ -11,19 +11,12 @@ export default class CrelteRequest extends Crelte {
|
|
|
11
11
|
*/
|
|
12
12
|
req: Request;
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
* The current site
|
|
16
|
-
*/
|
|
17
|
-
site: Site;
|
|
18
|
-
|
|
19
14
|
private innerGlobals: Map<string, any>;
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
constructor(inner: Crelte, req: Request, site: Site) {
|
|
16
|
+
constructor(inner: Crelte, req: Request) {
|
|
23
17
|
super(inner);
|
|
24
18
|
|
|
25
19
|
this.req = req;
|
|
26
|
-
this.site = site;
|
|
27
20
|
this.innerGlobals = new Map();
|
|
28
21
|
}
|
|
29
22
|
|
|
@@ -37,24 +30,14 @@ export default class CrelteRequest extends Crelte {
|
|
|
37
30
|
* If you provide a route it must contain a site or you must
|
|
38
31
|
* provide one,
|
|
39
32
|
*/
|
|
40
|
-
static fromCrelte(
|
|
41
|
-
inner: Crelte,
|
|
42
|
-
req?: Route | Request,
|
|
43
|
-
site?: Site,
|
|
44
|
-
): CrelteRequest {
|
|
33
|
+
static fromCrelte(inner: Crelte, req?: Route | Request): CrelteRequest {
|
|
45
34
|
if (!req) {
|
|
46
35
|
req = inner.router.route.get();
|
|
47
36
|
}
|
|
48
37
|
|
|
49
|
-
if (!site) {
|
|
50
|
-
if (!req.site) throw new Error('site is required');
|
|
51
|
-
site = req.site;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
38
|
return new CrelteRequest(
|
|
55
39
|
inner,
|
|
56
40
|
req instanceof Request ? req : Request.fromRoute(req),
|
|
57
|
-
site,
|
|
58
41
|
);
|
|
59
42
|
}
|
|
60
43
|
|
|
@@ -66,6 +49,18 @@ export default class CrelteRequest extends Crelte {
|
|
|
66
49
|
return this.req;
|
|
67
50
|
}
|
|
68
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Easy access to this.req.site
|
|
54
|
+
*
|
|
55
|
+
* ## Note
|
|
56
|
+
* The site might not always match with the current route
|
|
57
|
+
* but be the site default site or one that matches the
|
|
58
|
+
* users language.
|
|
59
|
+
*/
|
|
60
|
+
get site(): Site {
|
|
61
|
+
return this.req.site;
|
|
62
|
+
}
|
|
63
|
+
|
|
69
64
|
/**
|
|
70
65
|
* returns a globalSet
|
|
71
66
|
*
|
package/src/graphql/GraphQl.ts
CHANGED
|
@@ -70,7 +70,9 @@ export type GraphQlOptions = {
|
|
|
70
70
|
*/
|
|
71
71
|
export type GraphQlRequestOptions = {
|
|
72
72
|
path?: string;
|
|
73
|
-
route
|
|
73
|
+
// !! the route here might not contain a site even if the types
|
|
74
|
+
// says it does. CrelteServer does not know about site
|
|
75
|
+
route?: Route | URL;
|
|
74
76
|
ignoreStatusCode?: boolean;
|
|
75
77
|
previewToken?: string;
|
|
76
78
|
siteToken?: string;
|
|
@@ -124,7 +126,8 @@ export default class GraphQl {
|
|
|
124
126
|
opts: GraphQlRequestOptions = {},
|
|
125
127
|
): Promise<unknown> {
|
|
126
128
|
if (opts.route) {
|
|
127
|
-
const search =
|
|
129
|
+
const search =
|
|
130
|
+
(opts.route as URL).searchParams ?? opts.route.search;
|
|
128
131
|
|
|
129
132
|
// todo should variables contain siteId
|
|
130
133
|
// or maybe gql should detect loadData and add it there
|
package/src/index.ts
CHANGED
|
@@ -9,8 +9,22 @@ import CrelteRequest from './CrelteRequest.js';
|
|
|
9
9
|
import type { Global, GlobalData } from './loadData/Globals.js';
|
|
10
10
|
import type { Cookies } from './cookies/index.js';
|
|
11
11
|
import type { Readable } from 'crelte-std/stores';
|
|
12
|
+
import {
|
|
13
|
+
LoadData,
|
|
14
|
+
LoadDataArray,
|
|
15
|
+
LoadDataFn,
|
|
16
|
+
LoadDataObj,
|
|
17
|
+
} from './loadData/index.js';
|
|
12
18
|
|
|
13
|
-
export {
|
|
19
|
+
export {
|
|
20
|
+
Crelte,
|
|
21
|
+
CrelteRequest,
|
|
22
|
+
type QueryOptions,
|
|
23
|
+
type LoadData,
|
|
24
|
+
type LoadDataFn,
|
|
25
|
+
type LoadDataObj,
|
|
26
|
+
type LoadDataArray,
|
|
27
|
+
};
|
|
14
28
|
|
|
15
29
|
/**
|
|
16
30
|
* Get Crelte from the current context
|
|
@@ -129,6 +143,15 @@ export function getCookies(): Cookies {
|
|
|
129
143
|
return getCrelte().cookies;
|
|
130
144
|
}
|
|
131
145
|
|
|
146
|
+
export function onRoute(fn: (route: Route, crelte: Crelte) => void) {
|
|
147
|
+
const crelte = getCrelte();
|
|
148
|
+
const rmListener = crelte.router.onRoute(route => {
|
|
149
|
+
fn(route, crelte);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
onDestroy(rmListener);
|
|
153
|
+
}
|
|
154
|
+
|
|
132
155
|
/**
|
|
133
156
|
* Listen for requests
|
|
134
157
|
*
|
|
@@ -137,8 +160,8 @@ export function getCookies(): Cookies {
|
|
|
137
160
|
*/
|
|
138
161
|
export function onRequest(fn: (cr: CrelteRequest) => void) {
|
|
139
162
|
const crelte = getCrelte();
|
|
140
|
-
const rmListener = crelte.router.onRequest(
|
|
141
|
-
fn(new CrelteRequest(crelte, req
|
|
163
|
+
const rmListener = crelte.router.onRequest(req => {
|
|
164
|
+
fn(new CrelteRequest(crelte, req));
|
|
142
165
|
});
|
|
143
166
|
|
|
144
167
|
onDestroy(rmListener);
|
package/src/init/client.ts
CHANGED
|
@@ -131,8 +131,8 @@ export function main(data: MainData) {
|
|
|
131
131
|
|
|
132
132
|
// setup load Data
|
|
133
133
|
|
|
134
|
-
crelte.router._internal.onLoad = (req,
|
|
135
|
-
const cr = new CrelteRequest(crelte, req
|
|
134
|
+
crelte.router._internal.onLoad = (req, opts) => {
|
|
135
|
+
const cr = new CrelteRequest(crelte, req);
|
|
136
136
|
return loadFn(cr, data.app, data.entryQuery, data.globalQuery, opts);
|
|
137
137
|
};
|
|
138
138
|
|
|
@@ -154,12 +154,7 @@ export function main(data: MainData) {
|
|
|
154
154
|
};
|
|
155
155
|
|
|
156
156
|
let firstLoad = true;
|
|
157
|
-
crelte.router._internal.onLoaded = async (
|
|
158
|
-
success,
|
|
159
|
-
req,
|
|
160
|
-
site,
|
|
161
|
-
readyForProps,
|
|
162
|
-
) => {
|
|
157
|
+
crelte.router._internal.onLoaded = async (success, req, readyForProps) => {
|
|
163
158
|
const isFirstLoad = firstLoad;
|
|
164
159
|
firstLoad = false;
|
|
165
160
|
|
|
@@ -177,13 +172,13 @@ export function main(data: MainData) {
|
|
|
177
172
|
return handleLoadError(readyForProps());
|
|
178
173
|
}
|
|
179
174
|
|
|
180
|
-
const cr = new CrelteRequest(crelte, req
|
|
175
|
+
const cr = new CrelteRequest(crelte, req);
|
|
181
176
|
|
|
182
177
|
const startTime = data.debugTiming ? Date.now() : null;
|
|
183
178
|
let render = async () => {
|
|
184
179
|
// we should trigger the route update here
|
|
185
180
|
pluginsBeforeRender(cr);
|
|
186
|
-
crelte.globals._updateSiteId(site.id);
|
|
181
|
+
crelte.globals._updateSiteId(cr.site.id);
|
|
187
182
|
updateAppProps(readyForProps());
|
|
188
183
|
|
|
189
184
|
await tick();
|
|
@@ -209,6 +204,15 @@ export function main(data: MainData) {
|
|
|
209
204
|
await render();
|
|
210
205
|
};
|
|
211
206
|
|
|
207
|
+
crelte.router._internal.onNothingLoaded = async (req, ready) => {
|
|
208
|
+
crelte.globals._updateSiteId(req.site.id);
|
|
209
|
+
ready();
|
|
210
|
+
|
|
211
|
+
await tick();
|
|
212
|
+
|
|
213
|
+
crelte.router._internal.domReady(req);
|
|
214
|
+
};
|
|
215
|
+
|
|
212
216
|
crelte.router._internal.initClient();
|
|
213
217
|
}
|
|
214
218
|
|
package/src/init/server.ts
CHANGED
|
@@ -16,6 +16,8 @@ export type ServerData = {
|
|
|
16
16
|
craftWeb: string;
|
|
17
17
|
viteEnv: Map<string, string>;
|
|
18
18
|
cookies?: string;
|
|
19
|
+
readSitesCache?: () => Promise<any>;
|
|
20
|
+
writeSitesCache?: (data: any) => Promise<void>;
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
/**
|
|
@@ -85,7 +87,7 @@ export async function main(data: MainData): Promise<{
|
|
|
85
87
|
const cookies = data.serverData.cookies ?? '';
|
|
86
88
|
builder.setupCookies(cookies);
|
|
87
89
|
|
|
88
|
-
const csites = await loadSites(builder);
|
|
90
|
+
const csites = await loadSites(builder, data.serverData);
|
|
89
91
|
builder.ssrCache.set('crelteSites', csites);
|
|
90
92
|
builder.setupRouter(csites);
|
|
91
93
|
|
|
@@ -96,12 +98,12 @@ export async function main(data: MainData): Promise<{
|
|
|
96
98
|
|
|
97
99
|
// setup load Data
|
|
98
100
|
|
|
99
|
-
crelte.router._internal.onLoad =
|
|
100
|
-
const cr = new CrelteRequest(crelte, req
|
|
101
|
+
crelte.router._internal.onLoad = req => {
|
|
102
|
+
const cr = new CrelteRequest(crelte, req);
|
|
101
103
|
return loadFn(cr, data.app, data.entryQuery, data.globalQuery);
|
|
102
104
|
};
|
|
103
105
|
|
|
104
|
-
const { success, redirect, req,
|
|
106
|
+
const { success, redirect, req, props } =
|
|
105
107
|
await crelte.router._internal.initServer(
|
|
106
108
|
data.serverData.url,
|
|
107
109
|
data.serverData.acceptLang,
|
|
@@ -110,7 +112,7 @@ export async function main(data: MainData): Promise<{
|
|
|
110
112
|
|
|
111
113
|
if (redirect) {
|
|
112
114
|
return {
|
|
113
|
-
status: 302,
|
|
115
|
+
status: req.statusCode ?? 302,
|
|
114
116
|
location: req.url.toString(),
|
|
115
117
|
};
|
|
116
118
|
}
|
|
@@ -119,8 +121,9 @@ export async function main(data: MainData): Promise<{
|
|
|
119
121
|
const ssrComponents = new SsrComponents();
|
|
120
122
|
ssrComponents.addToContext(context);
|
|
121
123
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
const cr = new CrelteRequest(crelte, req);
|
|
125
|
+
pluginsBeforeRender(cr);
|
|
126
|
+
crelte.globals._updateSiteId(cr.site.id);
|
|
124
127
|
// eslint-disable-next-line prefer-const
|
|
125
128
|
let { html, head } = data.app.default.render(props, { context });
|
|
126
129
|
|
|
@@ -128,7 +131,7 @@ export async function main(data: MainData): Promise<{
|
|
|
128
131
|
head += crelte.ssrCache._exportToHead();
|
|
129
132
|
|
|
130
133
|
let htmlTemplate = data.serverData.htmlTemplate;
|
|
131
|
-
htmlTemplate = htmlTemplate.replace('<!--page-lang-->', site.language);
|
|
134
|
+
htmlTemplate = htmlTemplate.replace('<!--page-lang-->', cr.site.language);
|
|
132
135
|
|
|
133
136
|
const finalHtml = htmlTemplate
|
|
134
137
|
.replace('</head>', head + '\n\t</head>')
|
|
@@ -205,12 +208,26 @@ export async function mainError(
|
|
|
205
208
|
}
|
|
206
209
|
|
|
207
210
|
// requires, GraphQl, SsrCache
|
|
208
|
-
async function loadSites(
|
|
211
|
+
async function loadSites(
|
|
212
|
+
builder: CrelteBuilder,
|
|
213
|
+
serverData: ServerData,
|
|
214
|
+
): Promise<SiteFromGraphQl[]> {
|
|
209
215
|
if (!builder.graphQl) throw new Error();
|
|
210
216
|
|
|
211
217
|
if ('CRAFT_SITES_CACHED' in globalThis) {
|
|
212
|
-
|
|
213
|
-
|
|
218
|
+
return (globalThis as any)['CRAFT_SITES_CACHED'];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (import.meta.env.PROD && serverData.readSitesCache) {
|
|
222
|
+
try {
|
|
223
|
+
const sites =
|
|
224
|
+
(await serverData.readSitesCache()) as SiteFromGraphQl[];
|
|
225
|
+
// @ts-ignore
|
|
226
|
+
globalThis['CRAFT_SITES_CACHED'] = sites;
|
|
227
|
+
return sites;
|
|
228
|
+
} catch (_e: any) {
|
|
229
|
+
// ignore
|
|
230
|
+
}
|
|
214
231
|
}
|
|
215
232
|
|
|
216
233
|
const resp = (await builder.graphQl.query(
|
|
@@ -233,5 +250,8 @@ async function loadSites(builder: CrelteBuilder): Promise<SiteFromGraphQl[]> {
|
|
|
233
250
|
|
|
234
251
|
// @ts-ignore
|
|
235
252
|
globalThis['CRAFT_SITES_CACHED'] = resp.crelteSites;
|
|
253
|
+
if (import.meta.env.PROD && serverData.writeSitesCache) {
|
|
254
|
+
await serverData.writeSitesCache(resp.crelteSites);
|
|
255
|
+
}
|
|
236
256
|
return resp.crelteSites;
|
|
237
257
|
}
|
package/src/init/shared.ts
CHANGED
|
@@ -5,8 +5,8 @@ import { LoadData, callLoadData } from '../loadData/index.js';
|
|
|
5
5
|
import { PluginCreator } from '../plugins/Plugins.js';
|
|
6
6
|
import { LoadOptions } from '../routing/PageLoader.js';
|
|
7
7
|
|
|
8
|
-
interface App<
|
|
9
|
-
loadGlobalData?: LoadData<
|
|
8
|
+
interface App<E, T> {
|
|
9
|
+
loadGlobalData?: LoadData<null>;
|
|
10
10
|
|
|
11
11
|
// todo: add a generic
|
|
12
12
|
loadEntryData?: LoadData<any>;
|
|
@@ -60,7 +60,7 @@ export function getEntry(page: any): any {
|
|
|
60
60
|
|
|
61
61
|
export async function loadFn<D, E, T>(
|
|
62
62
|
cr: CrelteRequest,
|
|
63
|
-
app: App<
|
|
63
|
+
app: App<E, T>,
|
|
64
64
|
entryQuery: GraphQlQuery,
|
|
65
65
|
globalQuery?: GraphQlQuery,
|
|
66
66
|
loadOpts?: LoadOptions,
|
|
@@ -75,7 +75,7 @@ export async function loadFn<D, E, T>(
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
if (app.loadGlobalData) {
|
|
78
|
-
dataProm = callLoadData(app.loadGlobalData, cr) as any;
|
|
78
|
+
dataProm = callLoadData(app.loadGlobalData, cr, null) as any;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
let globalProm: Promise<any> | null = null;
|