crelte 0.1.3 → 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 +34 -13
- package/dist/routing/Router.d.ts +5 -6
- package/dist/routing/Router.d.ts.map +1 -1
- package/dist/routing/Router.js +26 -34
- 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 +39 -15
- package/src/routing/Router.ts +33 -42
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';
|
|
@@ -58,10 +57,10 @@ export default class Router {
|
|
|
58
57
|
initClient: () => this._initClient(),
|
|
59
58
|
initServer: (url, acceptLang) => this._initServer(url, acceptLang),
|
|
60
59
|
};
|
|
61
|
-
this.inner.onRoute = (route,
|
|
62
|
-
this.inner.onPreload =
|
|
63
|
-
this.pageLoader.onLoaded = (resp, req,
|
|
64
|
-
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);
|
|
65
64
|
this.pageLoader.onProgress = (loading, progress) => this._onProgress(loading, progress);
|
|
66
65
|
}
|
|
67
66
|
/**
|
|
@@ -112,8 +111,8 @@ export default class Router {
|
|
|
112
111
|
* // the following page will be opened https://example.com/de/foo/bar
|
|
113
112
|
* ```
|
|
114
113
|
*/
|
|
115
|
-
open(target) {
|
|
116
|
-
this.inner.open(target);
|
|
114
|
+
open(target, opts = {}) {
|
|
115
|
+
this.inner.open(target, opts);
|
|
117
116
|
}
|
|
118
117
|
/**
|
|
119
118
|
* This pushes the state of the route without triggering an event
|
|
@@ -136,6 +135,7 @@ export default class Router {
|
|
|
136
135
|
pushState(route) {
|
|
137
136
|
this.pageLoader.discard();
|
|
138
137
|
this.inner.pushState(route);
|
|
138
|
+
this.destroyRequest();
|
|
139
139
|
this.setNewRoute(route);
|
|
140
140
|
}
|
|
141
141
|
/**
|
|
@@ -158,6 +158,7 @@ export default class Router {
|
|
|
158
158
|
replaceState(route) {
|
|
159
159
|
this.pageLoader.discard();
|
|
160
160
|
this.inner.replaceState(route);
|
|
161
|
+
this.destroyRequest();
|
|
161
162
|
this.setNewRoute(route);
|
|
162
163
|
}
|
|
163
164
|
/**
|
|
@@ -200,12 +201,11 @@ export default class Router {
|
|
|
200
201
|
return this._onRequest.add(fn);
|
|
201
202
|
}
|
|
202
203
|
setNewRoute(route) {
|
|
203
|
-
this.destroyRequest();
|
|
204
204
|
this._route.setSilent(route);
|
|
205
|
-
|
|
206
|
-
|
|
205
|
+
const siteChanged = this.site.get()?.id !== route.site.id;
|
|
206
|
+
this._site.setSilent(route.site);
|
|
207
207
|
this._route.notify();
|
|
208
|
-
if (
|
|
208
|
+
if (siteChanged)
|
|
209
209
|
this._site.notify();
|
|
210
210
|
}
|
|
211
211
|
async _initClient() {
|
|
@@ -214,14 +214,13 @@ export default class Router {
|
|
|
214
214
|
async _initServer(url, acceptLang) {
|
|
215
215
|
this.inner.initServer();
|
|
216
216
|
const prom = new Promise(resolve => {
|
|
217
|
-
this._internal.onLoaded = (success, req,
|
|
217
|
+
this._internal.onLoaded = (success, req, ready) => {
|
|
218
218
|
const props = ready();
|
|
219
219
|
this._internal.onLoaded = () => { };
|
|
220
220
|
resolve({
|
|
221
221
|
success,
|
|
222
222
|
redirect: false,
|
|
223
223
|
req,
|
|
224
|
-
site,
|
|
225
224
|
props,
|
|
226
225
|
});
|
|
227
226
|
};
|
|
@@ -230,43 +229,41 @@ export default class Router {
|
|
|
230
229
|
route.origin = 'init';
|
|
231
230
|
// let's see if the url matches any route and site
|
|
232
231
|
// if not let's redirect to the site which matches the acceptLang
|
|
233
|
-
if (!route.
|
|
232
|
+
if (!route.siteMatches()) {
|
|
234
233
|
const site = this.inner.siteByAcceptLang(acceptLang);
|
|
235
234
|
return {
|
|
236
235
|
success: true,
|
|
237
236
|
redirect: true,
|
|
238
237
|
req: new Request(site.url, site),
|
|
239
|
-
site,
|
|
240
238
|
props: {},
|
|
241
239
|
};
|
|
242
240
|
}
|
|
243
241
|
this.inner.setRoute(route);
|
|
244
242
|
const resp = await prom;
|
|
245
243
|
const hist = this.inner.history;
|
|
246
|
-
if (hist.url) {
|
|
247
|
-
const
|
|
248
|
-
if (!route.eq(
|
|
244
|
+
if (hist.url || hist.req) {
|
|
245
|
+
const nReq = this.inner.targetToRequest(hist.req ?? hist.url);
|
|
246
|
+
if (!route.eq(nReq)) {
|
|
249
247
|
return {
|
|
250
248
|
success: true,
|
|
251
249
|
redirect: true,
|
|
252
|
-
req:
|
|
253
|
-
site: route.site,
|
|
250
|
+
req: nReq,
|
|
254
251
|
props: {},
|
|
255
252
|
};
|
|
256
253
|
}
|
|
257
254
|
}
|
|
258
255
|
return resp;
|
|
259
256
|
}
|
|
260
|
-
_onRoute(req,
|
|
257
|
+
_onRoute(req, changeHistory) {
|
|
261
258
|
this.destroyRequest();
|
|
262
259
|
this._request = req;
|
|
263
260
|
const barrier = req._renderBarrier;
|
|
264
261
|
if (barrier.isOpen()) {
|
|
265
262
|
throw new Error('render barrier is already open');
|
|
266
263
|
}
|
|
267
|
-
this._onRequest.trigger(req
|
|
264
|
+
this._onRequest.trigger(req);
|
|
268
265
|
// route prepared
|
|
269
|
-
this.pageLoader.load(req,
|
|
266
|
+
this.pageLoader.load(req, { changeHistory });
|
|
270
267
|
}
|
|
271
268
|
destroyRequest() {
|
|
272
269
|
if (!this._request)
|
|
@@ -274,10 +271,10 @@ export default class Router {
|
|
|
274
271
|
this._request._renderBarrier.cancel();
|
|
275
272
|
this._request = null;
|
|
276
273
|
}
|
|
277
|
-
_onPreload(req
|
|
278
|
-
this.pageLoader.preload(req
|
|
274
|
+
_onPreload(req) {
|
|
275
|
+
this.pageLoader.preload(req);
|
|
279
276
|
}
|
|
280
|
-
async _onLoaded(resp, req,
|
|
277
|
+
async _onLoaded(resp, req, more) {
|
|
281
278
|
// check if the render was cancelled
|
|
282
279
|
if (await req._renderBarrier.ready())
|
|
283
280
|
return;
|
|
@@ -287,15 +284,10 @@ export default class Router {
|
|
|
287
284
|
more.changeHistory();
|
|
288
285
|
const route = req.toRoute();
|
|
289
286
|
const updateRoute = () => {
|
|
290
|
-
this.
|
|
291
|
-
|
|
292
|
-
this._site.setSilent(site);
|
|
293
|
-
this._route.notify();
|
|
294
|
-
if (siteChanged)
|
|
295
|
-
this._site.notify();
|
|
296
|
-
this._onRouteEv.trigger(route.clone(), site);
|
|
287
|
+
this.setNewRoute(route);
|
|
288
|
+
this._onRouteEv.trigger(route.clone());
|
|
297
289
|
};
|
|
298
|
-
this._internal.onLoaded(resp.success, req,
|
|
290
|
+
this._internal.onLoaded(resp.success, req, () => {
|
|
299
291
|
updateRoute();
|
|
300
292
|
return resp.data;
|
|
301
293
|
});
|
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 {
|