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.
- 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 +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/init/client.d.ts.map +1 -1
- package/dist/init/client.js +5 -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 +13 -9
- package/dist/routing/InnerRouter.d.ts.map +1 -1
- package/dist/routing/InnerRouter.js +30 -35
- 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 +9 -2
- package/dist/routing/Request.d.ts.map +1 -1
- package/dist/routing/Request.js +16 -1
- package/dist/routing/Route.d.ts +25 -12
- package/dist/routing/Route.d.ts.map +1 -1
- package/dist/routing/Route.js +35 -14
- package/dist/routing/Router.d.ts +5 -7
- package/dist/routing/Router.d.ts.map +1 -1
- package/dist/routing/Router.js +26 -37
- package/dist/routing/Site.js +1 -1
- package/dist/routing/utils.d.ts +2 -0
- package/dist/routing/utils.d.ts.map +1 -0
- package/dist/routing/utils.js +3 -0
- package/package.json +3 -2
- package/src/CrelteRequest.ts +14 -19
- package/src/graphql/GraphQl.ts +5 -2
- package/src/index.ts +17 -3
- package/src/init/client.ts +5 -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 +42 -39
- package/src/routing/PageLoader.ts +7 -17
- package/src/routing/Request.ts +20 -6
- package/src/routing/Route.ts +40 -16
- package/src/routing/Router.ts +33 -46
- package/src/routing/Site.ts +1 -1
- package/src/routing/utils.ts +3 -0
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';
|
|
@@ -8,9 +7,6 @@ const defaultRouterOpts = {
|
|
|
8
7
|
preloadOnMouseOver: false,
|
|
9
8
|
deubgTiming: false,
|
|
10
9
|
};
|
|
11
|
-
export function trimSlashEnd(str) {
|
|
12
|
-
return str.endsWith('/') ? str.substring(0, str.length - 1) : str;
|
|
13
|
-
}
|
|
14
10
|
// Make sure route and nextRoute are not the same object as _inner.route
|
|
15
11
|
export default class Router {
|
|
16
12
|
/**
|
|
@@ -61,10 +57,10 @@ export default class Router {
|
|
|
61
57
|
initClient: () => this._initClient(),
|
|
62
58
|
initServer: (url, acceptLang) => this._initServer(url, acceptLang),
|
|
63
59
|
};
|
|
64
|
-
this.inner.onRoute = (route,
|
|
65
|
-
this.inner.onPreload =
|
|
66
|
-
this.pageLoader.onLoaded = (resp, req,
|
|
67
|
-
this.pageLoader.loadFn = (req,
|
|
60
|
+
this.inner.onRoute = (route, changeHistory) => this._onRoute(route, changeHistory);
|
|
61
|
+
this.inner.onPreload = route => this._onPreload(route);
|
|
62
|
+
this.pageLoader.onLoaded = (resp, req, more) => this._onLoaded(resp, req, more);
|
|
63
|
+
this.pageLoader.loadFn = (req, opts) => this._internal.onLoad(req, opts);
|
|
68
64
|
this.pageLoader.onProgress = (loading, progress) => this._onProgress(loading, progress);
|
|
69
65
|
}
|
|
70
66
|
/**
|
|
@@ -115,8 +111,8 @@ export default class Router {
|
|
|
115
111
|
* // the following page will be opened https://example.com/de/foo/bar
|
|
116
112
|
* ```
|
|
117
113
|
*/
|
|
118
|
-
open(target) {
|
|
119
|
-
this.inner.open(target);
|
|
114
|
+
open(target, opts = {}) {
|
|
115
|
+
this.inner.open(target, opts);
|
|
120
116
|
}
|
|
121
117
|
/**
|
|
122
118
|
* This pushes the state of the route without triggering an event
|
|
@@ -139,6 +135,7 @@ export default class Router {
|
|
|
139
135
|
pushState(route) {
|
|
140
136
|
this.pageLoader.discard();
|
|
141
137
|
this.inner.pushState(route);
|
|
138
|
+
this.destroyRequest();
|
|
142
139
|
this.setNewRoute(route);
|
|
143
140
|
}
|
|
144
141
|
/**
|
|
@@ -161,6 +158,7 @@ export default class Router {
|
|
|
161
158
|
replaceState(route) {
|
|
162
159
|
this.pageLoader.discard();
|
|
163
160
|
this.inner.replaceState(route);
|
|
161
|
+
this.destroyRequest();
|
|
164
162
|
this.setNewRoute(route);
|
|
165
163
|
}
|
|
166
164
|
/**
|
|
@@ -203,12 +201,11 @@ export default class Router {
|
|
|
203
201
|
return this._onRequest.add(fn);
|
|
204
202
|
}
|
|
205
203
|
setNewRoute(route) {
|
|
206
|
-
this.destroyRequest();
|
|
207
204
|
this._route.setSilent(route);
|
|
208
|
-
|
|
209
|
-
|
|
205
|
+
const siteChanged = this.site.get()?.id !== route.site.id;
|
|
206
|
+
this._site.setSilent(route.site);
|
|
210
207
|
this._route.notify();
|
|
211
|
-
if (
|
|
208
|
+
if (siteChanged)
|
|
212
209
|
this._site.notify();
|
|
213
210
|
}
|
|
214
211
|
async _initClient() {
|
|
@@ -217,14 +214,13 @@ export default class Router {
|
|
|
217
214
|
async _initServer(url, acceptLang) {
|
|
218
215
|
this.inner.initServer();
|
|
219
216
|
const prom = new Promise(resolve => {
|
|
220
|
-
this._internal.onLoaded = (success, req,
|
|
217
|
+
this._internal.onLoaded = (success, req, ready) => {
|
|
221
218
|
const props = ready();
|
|
222
219
|
this._internal.onLoaded = () => { };
|
|
223
220
|
resolve({
|
|
224
221
|
success,
|
|
225
222
|
redirect: false,
|
|
226
223
|
req,
|
|
227
|
-
site,
|
|
228
224
|
props,
|
|
229
225
|
});
|
|
230
226
|
};
|
|
@@ -233,43 +229,41 @@ export default class Router {
|
|
|
233
229
|
route.origin = 'init';
|
|
234
230
|
// let's see if the url matches any route and site
|
|
235
231
|
// if not let's redirect to the site which matches the acceptLang
|
|
236
|
-
if (!route.
|
|
232
|
+
if (!route.siteMatches()) {
|
|
237
233
|
const site = this.inner.siteByAcceptLang(acceptLang);
|
|
238
234
|
return {
|
|
239
235
|
success: true,
|
|
240
236
|
redirect: true,
|
|
241
237
|
req: new Request(site.url, site),
|
|
242
|
-
site,
|
|
243
238
|
props: {},
|
|
244
239
|
};
|
|
245
240
|
}
|
|
246
241
|
this.inner.setRoute(route);
|
|
247
242
|
const resp = await prom;
|
|
248
243
|
const hist = this.inner.history;
|
|
249
|
-
if (hist.url) {
|
|
250
|
-
const
|
|
251
|
-
if (!route.eq(
|
|
244
|
+
if (hist.url || hist.req) {
|
|
245
|
+
const nReq = this.inner.targetToRequest(hist.req ?? hist.url);
|
|
246
|
+
if (!route.eq(nReq)) {
|
|
252
247
|
return {
|
|
253
248
|
success: true,
|
|
254
249
|
redirect: true,
|
|
255
|
-
req:
|
|
256
|
-
site: route.site,
|
|
250
|
+
req: nReq,
|
|
257
251
|
props: {},
|
|
258
252
|
};
|
|
259
253
|
}
|
|
260
254
|
}
|
|
261
255
|
return resp;
|
|
262
256
|
}
|
|
263
|
-
_onRoute(req,
|
|
257
|
+
_onRoute(req, changeHistory) {
|
|
264
258
|
this.destroyRequest();
|
|
265
259
|
this._request = req;
|
|
266
260
|
const barrier = req._renderBarrier;
|
|
267
261
|
if (barrier.isOpen()) {
|
|
268
262
|
throw new Error('render barrier is already open');
|
|
269
263
|
}
|
|
270
|
-
this._onRequest.trigger(req
|
|
264
|
+
this._onRequest.trigger(req);
|
|
271
265
|
// route prepared
|
|
272
|
-
this.pageLoader.load(req,
|
|
266
|
+
this.pageLoader.load(req, { changeHistory });
|
|
273
267
|
}
|
|
274
268
|
destroyRequest() {
|
|
275
269
|
if (!this._request)
|
|
@@ -277,10 +271,10 @@ export default class Router {
|
|
|
277
271
|
this._request._renderBarrier.cancel();
|
|
278
272
|
this._request = null;
|
|
279
273
|
}
|
|
280
|
-
_onPreload(req
|
|
281
|
-
this.pageLoader.preload(req
|
|
274
|
+
_onPreload(req) {
|
|
275
|
+
this.pageLoader.preload(req);
|
|
282
276
|
}
|
|
283
|
-
async _onLoaded(resp, req,
|
|
277
|
+
async _onLoaded(resp, req, more) {
|
|
284
278
|
// check if the render was cancelled
|
|
285
279
|
if (await req._renderBarrier.ready())
|
|
286
280
|
return;
|
|
@@ -290,15 +284,10 @@ export default class Router {
|
|
|
290
284
|
more.changeHistory();
|
|
291
285
|
const route = req.toRoute();
|
|
292
286
|
const updateRoute = () => {
|
|
293
|
-
this.
|
|
294
|
-
|
|
295
|
-
this._site.setSilent(site);
|
|
296
|
-
this._route.notify();
|
|
297
|
-
if (siteChanged)
|
|
298
|
-
this._site.notify();
|
|
299
|
-
this._onRouteEv.trigger(route.clone(), site);
|
|
287
|
+
this.setNewRoute(route);
|
|
288
|
+
this._onRouteEv.trigger(route.clone());
|
|
300
289
|
};
|
|
301
|
-
this._internal.onLoaded(resp.success, req,
|
|
290
|
+
this._internal.onLoaded(resp.success, req, () => {
|
|
302
291
|
updateRoute();
|
|
303
292
|
return resp.data;
|
|
304
293
|
});
|
package/dist/routing/Site.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/routing/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,UAEvC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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
|
|
@@ -137,8 +151,8 @@ export function getCookies(): Cookies {
|
|
|
137
151
|
*/
|
|
138
152
|
export function onRequest(fn: (cr: CrelteRequest) => void) {
|
|
139
153
|
const crelte = getCrelte();
|
|
140
|
-
const rmListener = crelte.router.onRequest(
|
|
141
|
-
fn(new CrelteRequest(crelte, req
|
|
154
|
+
const rmListener = crelte.router.onRequest(req => {
|
|
155
|
+
fn(new CrelteRequest(crelte, req));
|
|
142
156
|
});
|
|
143
157
|
|
|
144
158
|
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();
|
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;
|
package/src/loadData/index.ts
CHANGED
|
@@ -5,6 +5,20 @@ import type { Global } from './Globals.js';
|
|
|
5
5
|
|
|
6
6
|
export type { Globals, Global };
|
|
7
7
|
|
|
8
|
+
export interface LoadDataFn<A1 = any> {
|
|
9
|
+
(cr: CrelteRequest, entryOrBlock: A1, ...args: any[]): Promise<any> | any;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface LoadDataObj<A1 = any> {
|
|
13
|
+
[key: string]: LoadData<A1>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
17
|
+
export interface LoadDataArray<A1 = any> extends Array<LoadData<A1>> {}
|
|
18
|
+
|
|
19
|
+
// todo link to the real docs maybe instead of showing an example
|
|
20
|
+
// so we can add @type {import('crelte').LoadData}
|
|
21
|
+
// maybe enabling markdown might be enough: https://jsdoc.app/plugins-markdown
|
|
8
22
|
/**
|
|
9
23
|
* Load data function
|
|
10
24
|
*
|
|
@@ -15,8 +29,6 @@ export type { Globals, Global };
|
|
|
15
29
|
* Each property should be a loadData type, each one is called in parallel.
|
|
16
30
|
* And will be available to your component with the same name.
|
|
17
31
|
* ```
|
|
18
|
-
* export const loadData = {
|
|
19
|
-
*
|
|
20
32
|
* import entriesQuery from '@/queries/entries.graphql';
|
|
21
33
|
* import { loadData as headerLoadData } from '@/layout/header.svelte';
|
|
22
34
|
*
|
|
@@ -71,20 +83,30 @@ export type { Globals, Global };
|
|
|
71
83
|
* }
|
|
72
84
|
* ```
|
|
73
85
|
*/
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
| ((cr: CrelteRequest, ...args: any[]) => Promise<T>)
|
|
86
|
+
export type LoadData<A1 = any> =
|
|
87
|
+
| LoadDataFn<A1>
|
|
77
88
|
| GraphQlQuery
|
|
78
|
-
|
|
|
89
|
+
| LoadDataObj<A1>
|
|
90
|
+
| LoadDataArray<A1>
|
|
91
|
+
| string
|
|
92
|
+
| number
|
|
93
|
+
| null
|
|
94
|
+
| undefined;
|
|
95
|
+
|
|
96
|
+
// export type LoadData<A1 = any, R = any> =
|
|
97
|
+
// | ((cr: CrelteRequest, entryOrBlock: A1, ...args: any[]) => Promise<R>)
|
|
98
|
+
// | GraphQlQuery
|
|
99
|
+
// | Record<string, LoadData<A1, R>>;
|
|
79
100
|
|
|
80
|
-
export async function callLoadData(
|
|
81
|
-
ld: LoadData<
|
|
101
|
+
export async function callLoadData<A1 = any>(
|
|
102
|
+
ld: LoadData<A1>,
|
|
82
103
|
cr: CrelteRequest,
|
|
104
|
+
arg1: A1,
|
|
83
105
|
...args: any[]
|
|
84
|
-
): Promise<
|
|
106
|
+
): Promise<any> {
|
|
85
107
|
// either we have a function
|
|
86
108
|
if (typeof ld === 'function') {
|
|
87
|
-
return await ld(cr, ...args);
|
|
109
|
+
return await ld(cr, arg1, ...args);
|
|
88
110
|
}
|
|
89
111
|
|
|
90
112
|
// or a graphql query
|
|
@@ -92,10 +114,16 @@ export async function callLoadData(
|
|
|
92
114
|
return await cr.query(ld);
|
|
93
115
|
}
|
|
94
116
|
|
|
117
|
+
if (ld === null || typeof ld === 'undefined') return null;
|
|
118
|
+
|
|
119
|
+
if (Array.isArray(ld)) {
|
|
120
|
+
return await mergeLoadData(...ld)(cr, arg1, ...args);
|
|
121
|
+
}
|
|
122
|
+
|
|
95
123
|
// or an object
|
|
96
|
-
if (typeof ld === 'object'
|
|
124
|
+
if (typeof ld === 'object') {
|
|
97
125
|
const data = await Promise.all(
|
|
98
|
-
Object.values(ld).map(nld => callLoadData(nld, cr, ...args)),
|
|
126
|
+
Object.values(ld).map(nld => callLoadData(nld, cr, arg1, ...args)),
|
|
99
127
|
);
|
|
100
128
|
|
|
101
129
|
return Object.fromEntries(
|
|
@@ -119,10 +147,14 @@ export async function callLoadData(
|
|
|
119
147
|
* );
|
|
120
148
|
* ```
|
|
121
149
|
*/
|
|
122
|
-
export function mergeLoadData
|
|
123
|
-
|
|
150
|
+
export function mergeLoadData<A1 = any>(
|
|
151
|
+
...lds: LoadData<A1>[]
|
|
152
|
+
): LoadDataFn<A1> {
|
|
153
|
+
return async (cr: CrelteRequest, arg1, ...args: any[]) => {
|
|
124
154
|
const datas = await Promise.all(
|
|
125
|
-
lds.map(
|
|
155
|
+
lds.map(
|
|
156
|
+
ld => callLoadData(ld, cr, arg1, ...args) as Promise<object>,
|
|
157
|
+
),
|
|
126
158
|
);
|
|
127
159
|
|
|
128
160
|
return datas.reduce((acc, data) => ({ ...acc, ...data }), {});
|
package/src/routing/History.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import Request from './Request.js';
|
|
2
|
+
|
|
1
3
|
export default interface History {
|
|
2
4
|
scrollY(): number | null;
|
|
3
5
|
replaceState(data: any, url?: string): void;
|
|
4
6
|
pushState(data: any, url: string): void;
|
|
5
|
-
open(
|
|
7
|
+
open(req: Request): void;
|
|
6
8
|
back(): void;
|
|
7
9
|
}
|
|
8
10
|
|
|
@@ -19,8 +21,8 @@ export class ClientHistory implements History {
|
|
|
19
21
|
history.pushState(data, '', url);
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
open(
|
|
23
|
-
window.location.href = url;
|
|
24
|
+
open(req: Request): void {
|
|
25
|
+
window.location.href = req.url.href;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
back(): void {
|
|
@@ -31,10 +33,12 @@ export class ClientHistory implements History {
|
|
|
31
33
|
export class ServerHistory implements History {
|
|
32
34
|
state: any | null;
|
|
33
35
|
url: string | null;
|
|
36
|
+
req: Request | null;
|
|
34
37
|
|
|
35
38
|
constructor() {
|
|
36
39
|
this.state = null;
|
|
37
40
|
this.url = null;
|
|
41
|
+
this.req = null;
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
scrollY(): number | null {
|
|
@@ -44,15 +48,18 @@ export class ServerHistory implements History {
|
|
|
44
48
|
replaceState(data: any, url?: string): void {
|
|
45
49
|
this.state = data;
|
|
46
50
|
this.url = url ?? null;
|
|
51
|
+
this.req = null;
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
pushState(data: any, url: string): void {
|
|
50
55
|
this.state = data;
|
|
51
56
|
this.url = url;
|
|
57
|
+
this.req = null;
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
open(
|
|
55
|
-
this.
|
|
60
|
+
open(req: Request): void {
|
|
61
|
+
this.req = req;
|
|
62
|
+
this.url = null;
|
|
56
63
|
}
|
|
57
64
|
|
|
58
65
|
back(): void {
|