crelte 0.4.8 → 0.5.0-alpha.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 +7 -6
- package/dist/Crelte.d.ts.map +1 -1
- package/dist/Crelte.js +5 -13
- package/dist/CrelteRequest.d.ts +9 -0
- package/dist/CrelteRequest.d.ts.map +1 -1
- package/dist/CrelteRequest.js +16 -2
- package/dist/blocks/Blocks.svelte +2 -2
- package/dist/blocks/Blocks.svelte.d.ts +3 -19
- package/dist/blocks/Blocks.svelte.d.ts.map +1 -1
- package/dist/cookies/ClientCookies.d.ts +0 -1
- package/dist/cookies/ClientCookies.d.ts.map +1 -1
- package/dist/cookies/ClientCookies.js +0 -1
- package/dist/cookies/ServerCookies.d.ts +1 -2
- package/dist/cookies/ServerCookies.d.ts.map +1 -1
- package/dist/cookies/ServerCookies.js +2 -6
- package/dist/cookies/index.d.ts +0 -2
- package/dist/cookies/index.d.ts.map +1 -1
- package/dist/graphql/GraphQl.d.ts +2 -2
- package/dist/graphql/GraphQl.d.ts.map +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -6
- package/dist/init/InternalApp.d.ts +30 -0
- package/dist/init/InternalApp.d.ts.map +1 -0
- package/dist/init/InternalApp.js +71 -0
- package/dist/init/client.d.ts +0 -5
- package/dist/init/client.d.ts.map +1 -1
- package/dist/init/client.js +88 -75
- package/dist/init/crelte-vite-plugin.d.ts +5 -0
- package/dist/init/server.d.ts +0 -5
- package/dist/init/server.d.ts.map +1 -1
- package/dist/init/server.js +49 -20
- package/dist/init/shared.d.ts +7 -18
- package/dist/init/shared.d.ts.map +1 -1
- package/dist/init/shared.js +97 -154
- package/dist/init/svelteComponents.d.ts +3 -0
- package/dist/init/svelteComponents.d.ts.map +1 -0
- package/dist/init/svelteComponents.js +7 -0
- package/dist/loadData/Globals.d.ts +40 -33
- package/dist/loadData/Globals.d.ts.map +1 -1
- package/dist/loadData/Globals.js +99 -88
- package/dist/loadData/index.d.ts +3 -2
- package/dist/loadData/index.d.ts.map +1 -1
- package/dist/loadData/index.js +2 -0
- package/dist/plugins/Events.d.ts +11 -13
- package/dist/plugins/Events.d.ts.map +1 -1
- package/dist/plugins/Events.js +10 -3
- package/dist/routing/BaseRoute.d.ts +255 -0
- package/dist/routing/BaseRoute.d.ts.map +1 -0
- package/dist/routing/BaseRoute.js +349 -0
- package/dist/routing/BaseRouter.d.ts +210 -0
- package/dist/routing/BaseRouter.d.ts.map +1 -0
- package/dist/routing/BaseRouter.js +444 -0
- package/dist/routing/ClientRouter.d.ts +32 -0
- package/dist/routing/ClientRouter.d.ts.map +1 -0
- package/dist/routing/ClientRouter.js +259 -0
- package/dist/routing/LoadRunner.d.ts +39 -0
- package/dist/routing/LoadRunner.d.ts.map +1 -0
- package/dist/routing/{PageLoader.js → LoadRunner.js} +32 -20
- package/dist/routing/Request.d.ts +35 -3
- package/dist/routing/Request.d.ts.map +1 -1
- package/dist/routing/Request.js +64 -5
- package/dist/routing/Route.d.ts +24 -223
- package/dist/routing/Route.d.ts.map +1 -1
- package/dist/routing/Route.js +26 -315
- package/dist/routing/Router.d.ts +49 -73
- package/dist/routing/Router.d.ts.map +1 -1
- package/dist/routing/Router.js +85 -251
- package/dist/routing/ServerRouter.d.ts +23 -0
- package/dist/routing/ServerRouter.d.ts.map +1 -0
- package/dist/routing/ServerRouter.js +57 -0
- package/dist/routing/utils.d.ts +5 -0
- package/dist/routing/utils.d.ts.map +1 -1
- package/dist/routing/utils.js +39 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +3 -0
- package/package.json +7 -6
- package/src/Crelte.ts +12 -18
- package/src/CrelteRequest.ts +21 -2
- package/src/cookies/ClientCookies.ts +0 -2
- package/src/cookies/ServerCookies.ts +2 -7
- package/src/cookies/index.ts +0 -3
- package/src/graphql/GraphQl.ts +2 -1
- package/src/index.ts +17 -9
- package/src/init/InternalApp.ts +134 -0
- package/src/init/client.ts +104 -93
- package/src/init/crelte-vite-plugin.d.ts +5 -0
- package/src/init/server.ts +67 -35
- package/src/init/shared.ts +107 -227
- package/src/init/svelteComponents.ts +12 -0
- package/src/loadData/Globals.ts +121 -102
- package/src/loadData/index.ts +3 -2
- package/src/plugins/Events.ts +40 -42
- package/src/routing/BaseRoute.ts +422 -0
- package/src/routing/BaseRouter.ts +528 -0
- package/src/routing/ClientRouter.ts +329 -0
- package/src/routing/{PageLoader.ts → LoadRunner.ts} +43 -30
- package/src/routing/Request.ts +97 -12
- package/src/routing/Route.ts +56 -376
- package/src/routing/Router.ts +100 -359
- package/src/routing/ServerRouter.ts +78 -0
- package/src/routing/utils.ts +53 -0
- package/src/utils.ts +4 -0
- package/dist/routing/InnerRouter.d.ts +0 -113
- package/dist/routing/InnerRouter.d.ts.map +0 -1
- package/dist/routing/InnerRouter.js +0 -417
- package/dist/routing/PageLoader.d.ts +0 -36
- package/dist/routing/PageLoader.d.ts.map +0 -1
- package/src/routing/InnerRouter.ts +0 -498
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import BaseRouter, { BaseRouterOptions } from './BaseRouter.js';
|
|
2
|
+
import { Request, RequestOptions } from './index.js';
|
|
3
|
+
import Route from './Route.js';
|
|
4
|
+
import Site, { SiteFromGraphQl } from './Site.js';
|
|
5
|
+
export default class ServerRouter extends BaseRouter {
|
|
6
|
+
acceptLang: string | null;
|
|
7
|
+
redirect: Request | null;
|
|
8
|
+
constructor(sites: SiteFromGraphQl[], opts: BaseRouterOptions);
|
|
9
|
+
defaultSite(): Site;
|
|
10
|
+
openRequest(req: Request): Promise<void>;
|
|
11
|
+
pushRequest(req: Request, _opts?: RequestOptions): Promise<void>;
|
|
12
|
+
replaceRequest(req: Request, _opts?: RequestOptions): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* This function always returns the request or a redirect one
|
|
15
|
+
*
|
|
16
|
+
* And then if no redirect happen the final route
|
|
17
|
+
*
|
|
18
|
+
* ## Throws
|
|
19
|
+
* If the request fails
|
|
20
|
+
*/
|
|
21
|
+
init(url: string, acceptLang?: string): Promise<[Request, Route | null]>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=ServerRouter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServerRouter.d.ts","sourceRoot":"","sources":["../../src/routing/ServerRouter.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,EAAE,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,IAAI,EAAE,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAElD,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,UAAU;IACnD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;gBAEb,KAAK,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,iBAAiB;IAO7D,WAAW,IAAI,IAAI;IAIb,WAAW,CAAC,GAAG,EAAE,OAAO;IAiBxB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,cAAmB;IAKpD,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,GAAE,cAAmB;IAK7D;;;;;;;OAOG;IACG,IAAI,CACT,GAAG,EAAE,MAAM,EACX,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC;CAmBnC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import BaseRouter from './BaseRouter.js';
|
|
2
|
+
export default class ServerRouter extends BaseRouter {
|
|
3
|
+
acceptLang;
|
|
4
|
+
redirect;
|
|
5
|
+
constructor(sites, opts) {
|
|
6
|
+
super(sites, opts);
|
|
7
|
+
this.acceptLang = null;
|
|
8
|
+
this.redirect = null;
|
|
9
|
+
}
|
|
10
|
+
defaultSite() {
|
|
11
|
+
return this.siteByAcceptLang(this.acceptLang);
|
|
12
|
+
}
|
|
13
|
+
async openRequest(req) {
|
|
14
|
+
// only handle the first redirect
|
|
15
|
+
// this makes the behaviour the same as client router
|
|
16
|
+
// not true
|
|
17
|
+
// todo: the client only instatly redirects if it belongs to another
|
|
18
|
+
// site (aka needs to use window.location.href)
|
|
19
|
+
if (this.redirect)
|
|
20
|
+
return;
|
|
21
|
+
this.redirect = req;
|
|
22
|
+
this.cancelRequest();
|
|
23
|
+
// request was handled with a redirect so we don't have an entry
|
|
24
|
+
// templateData or anything else
|
|
25
|
+
// todo is that what we wan't to return. Because void would tell
|
|
26
|
+
// the user the request was cancelled
|
|
27
|
+
}
|
|
28
|
+
async pushRequest(req, _opts = {}) {
|
|
29
|
+
// todo not sure if that is what we want?
|
|
30
|
+
return await this.openRequest(req);
|
|
31
|
+
}
|
|
32
|
+
async replaceRequest(req, _opts = {}) {
|
|
33
|
+
// todo not sure if that is what we want?
|
|
34
|
+
return await this.openRequest(req);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* This function always returns the request or a redirect one
|
|
38
|
+
*
|
|
39
|
+
* And then if no redirect happen the final route
|
|
40
|
+
*
|
|
41
|
+
* ## Throws
|
|
42
|
+
* If the request fails
|
|
43
|
+
*/
|
|
44
|
+
async init(url, acceptLang) {
|
|
45
|
+
this.acceptLang = acceptLang ?? null;
|
|
46
|
+
const req = this.targetToRequest(url);
|
|
47
|
+
req.origin = 'init';
|
|
48
|
+
// throws if something goes wrong
|
|
49
|
+
const route = await this.handleRequest(req, () => { });
|
|
50
|
+
if (!route) {
|
|
51
|
+
if (!this.redirect)
|
|
52
|
+
throw new Error('if the request gets cancelled on the server there should be a redirect');
|
|
53
|
+
return [this.redirect, null];
|
|
54
|
+
}
|
|
55
|
+
return [req, route];
|
|
56
|
+
}
|
|
57
|
+
}
|
package/dist/routing/utils.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
1
|
export declare function trimSlashEnd(str: string): string;
|
|
2
|
+
/**
|
|
3
|
+
* if no match was found null is returned
|
|
4
|
+
* `matchAcceptLang('fr-CH, en;q=0.7, fr;q=0.8', ['en-GB'])` will return `en-GB`
|
|
5
|
+
*/
|
|
6
|
+
export declare function matchAcceptLang(acceptLang: string, langs: string[]): string | null;
|
|
2
7
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/routing/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,UAEvC"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/routing/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,UAEvC;AA0BD;;;GAGG;AACH,wBAAgB,eAAe,CAC9B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EAAE,GACb,MAAM,GAAG,IAAI,CAoBf"}
|
package/dist/routing/utils.js
CHANGED
|
@@ -1,3 +1,42 @@
|
|
|
1
1
|
export function trimSlashEnd(str) {
|
|
2
2
|
return str.endsWith('/') ? str.substring(0, str.length - 1) : str;
|
|
3
3
|
}
|
|
4
|
+
/**
|
|
5
|
+
* `parseAcceptLang('fr-CH, en;q=0.7, fr;q=0.8')` will return `[['fr-CH', 1], ['fr', 0.8], ['en', 0.7]]`
|
|
6
|
+
*/
|
|
7
|
+
function parseAcceptLang(acceptLang) {
|
|
8
|
+
return acceptLang
|
|
9
|
+
.split(',')
|
|
10
|
+
.map(d => {
|
|
11
|
+
// eslint-disable-next-line prefer-const
|
|
12
|
+
let [lang, pq] = d.split(';');
|
|
13
|
+
lang = lang.trim();
|
|
14
|
+
if (!lang)
|
|
15
|
+
return null;
|
|
16
|
+
let quality = 1;
|
|
17
|
+
if (pq?.startsWith('q=')) {
|
|
18
|
+
const q = parseFloat(pq.substring(2));
|
|
19
|
+
if (!isNaN(q))
|
|
20
|
+
quality = q;
|
|
21
|
+
}
|
|
22
|
+
return [lang, quality];
|
|
23
|
+
})
|
|
24
|
+
.filter(d => !!d)
|
|
25
|
+
.sort((a, b) => b[1] - a[1]);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* if no match was found null is returned
|
|
29
|
+
* `matchAcceptLang('fr-CH, en;q=0.7, fr;q=0.8', ['en-GB'])` will return `en-GB`
|
|
30
|
+
*/
|
|
31
|
+
export function matchAcceptLang(acceptLang, langs) {
|
|
32
|
+
const qualities = new Map(parseAcceptLang(acceptLang).map(([l, q]) => [l.toLowerCase(), q]));
|
|
33
|
+
return langs.reduce((best, lang) => {
|
|
34
|
+
const lowerLang = lang.toLowerCase();
|
|
35
|
+
// this might splitting to much
|
|
36
|
+
const [p1, p2] = lowerLang.split('-');
|
|
37
|
+
const q1 = qualities.get(lowerLang) ?? 0;
|
|
38
|
+
const q2 = p2 ? (qualities.get(p1) ?? 0) : 0;
|
|
39
|
+
const q = Math.max(q1, q2);
|
|
40
|
+
return best.q < q ? { lang, q } : best;
|
|
41
|
+
}, { lang: null, q: 0 }).lang;
|
|
42
|
+
}
|
package/dist/utils.d.ts
CHANGED
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAMtC;AAGD,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,CAAC"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAMtC;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAE/D;AAGD,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,CAAC"}
|
package/dist/utils.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-alpha.2",
|
|
4
4
|
"author": "Crelte <support@crelte.com>",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -78,16 +78,17 @@
|
|
|
78
78
|
}
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
|
-
"crelte-std": "^0.1.
|
|
82
|
-
"svelte": "^4.2.12",
|
|
81
|
+
"crelte-std": "^0.1.2",
|
|
83
82
|
"trouter": "^4.0.0"
|
|
84
83
|
},
|
|
84
|
+
"peerDependencies": {
|
|
85
|
+
"svelte": "^4.0.0 || ^5.0.0"
|
|
86
|
+
},
|
|
85
87
|
"devDependencies": {
|
|
86
88
|
"@sveltejs/package": "^2.3.1",
|
|
87
|
-
"@sveltejs/vite-plugin-svelte": "^
|
|
89
|
+
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
|
88
90
|
"svelte-check": "^4.1.4",
|
|
89
91
|
"typescript-svelte-plugin": "^0.3.45",
|
|
90
|
-
"
|
|
91
|
-
"vitest": "^2.0.0"
|
|
92
|
+
"vitest": "^3.0.0"
|
|
92
93
|
}
|
|
93
94
|
}
|
package/src/Crelte.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import ClientCookies from './cookies/ClientCookies.js';
|
|
2
1
|
import { Cookies } from './cookies/index.js';
|
|
3
|
-
import ServerCookies from './cookies/ServerCookies.js';
|
|
4
2
|
import GraphQl, { GraphQlQuery } from './graphql/GraphQl.js';
|
|
5
|
-
import Globals
|
|
3
|
+
import Globals from './loadData/Globals.js';
|
|
6
4
|
import Events from './plugins/Events.js';
|
|
7
5
|
import Plugins, { Plugin } from './plugins/Plugins.js';
|
|
8
6
|
import type Route from './routing/Route.js';
|
|
9
7
|
import type Request from './routing/Request.js';
|
|
10
8
|
import Router from './routing/Router.js';
|
|
11
|
-
import { SiteFromGraphQl } from './routing/Site.js';
|
|
12
9
|
import SsrCache from './ssr/SsrCache.js';
|
|
13
10
|
import { type CrelteRequest } from './index.js';
|
|
14
11
|
import { circles } from './utils.js';
|
|
12
|
+
import BaseRouter from './routing/BaseRouter.js';
|
|
13
|
+
import { Readable } from 'crelte-std/stores';
|
|
15
14
|
|
|
16
15
|
export type Config = {
|
|
17
16
|
/**
|
|
@@ -70,7 +69,7 @@ export class CrelteBuilder {
|
|
|
70
69
|
graphQl?: GraphQl;
|
|
71
70
|
router?: Router;
|
|
72
71
|
globals: Globals;
|
|
73
|
-
cookies
|
|
72
|
+
cookies?: Cookies;
|
|
74
73
|
|
|
75
74
|
constructor(config: Config) {
|
|
76
75
|
this.config = { ...defaultConfig, ...config };
|
|
@@ -79,10 +78,6 @@ export class CrelteBuilder {
|
|
|
79
78
|
this.plugins = new Plugins();
|
|
80
79
|
this.events = new Events();
|
|
81
80
|
this.globals = new Globals();
|
|
82
|
-
// @ts-ignore
|
|
83
|
-
this.cookies = import.meta.env.SSR
|
|
84
|
-
? new ServerCookies()
|
|
85
|
-
: new ClientCookies();
|
|
86
81
|
}
|
|
87
82
|
|
|
88
83
|
setupGraphQl(endpoint: string) {
|
|
@@ -93,15 +88,12 @@ export class CrelteBuilder {
|
|
|
93
88
|
});
|
|
94
89
|
}
|
|
95
90
|
|
|
96
|
-
setupRouter(
|
|
97
|
-
this.router = new Router(
|
|
98
|
-
preloadOnMouseOver: this.config.preloadOnMouseOver,
|
|
99
|
-
debugTiming: this.config.debugTiming,
|
|
100
|
-
});
|
|
91
|
+
setupRouter(router: BaseRouter) {
|
|
92
|
+
this.router = new Router(router);
|
|
101
93
|
}
|
|
102
94
|
|
|
103
|
-
setupCookies(cookies:
|
|
104
|
-
this.cookies
|
|
95
|
+
setupCookies(cookies: Cookies) {
|
|
96
|
+
this.cookies = cookies;
|
|
105
97
|
}
|
|
106
98
|
|
|
107
99
|
build(): Crelte {
|
|
@@ -155,7 +147,7 @@ export default class Crelte {
|
|
|
155
147
|
protected _cookies: Cookies;
|
|
156
148
|
|
|
157
149
|
constructor(builder: CrelteBuilder | Crelte) {
|
|
158
|
-
if (!builder.graphQl || !builder.router)
|
|
150
|
+
if (!builder.graphQl || !builder.router || !builder.cookies)
|
|
159
151
|
throw new Error('builder not ready');
|
|
160
152
|
|
|
161
153
|
this._ssrCache = builder.ssrCache;
|
|
@@ -243,7 +235,7 @@ export default class Crelte {
|
|
|
243
235
|
* always return null. In that context you should use
|
|
244
236
|
* `CrelteRequest.getGlobalAsync`
|
|
245
237
|
*/
|
|
246
|
-
getGlobalStore<T = any>(name: string):
|
|
238
|
+
getGlobalStore<T = any>(name: string): Readable<T> | null {
|
|
247
239
|
return this.globals.getStore(name) ?? null;
|
|
248
240
|
}
|
|
249
241
|
|
|
@@ -256,6 +248,8 @@ export default class Crelte {
|
|
|
256
248
|
* to use in loadData context
|
|
257
249
|
*/
|
|
258
250
|
toRequest(req?: Route | Request): CrelteRequest {
|
|
251
|
+
// todo can we remove this function or is it still relevant?
|
|
252
|
+
|
|
259
253
|
// we do this to avoid cyclic dependencies
|
|
260
254
|
return circles.requestFromCrelte(this, req);
|
|
261
255
|
}
|
package/src/CrelteRequest.ts
CHANGED
|
@@ -4,10 +4,15 @@ import Site from './routing/Site.js';
|
|
|
4
4
|
import Request from './routing/Request.js';
|
|
5
5
|
import Route from './routing/Route.js';
|
|
6
6
|
import { circles } from './utils.js';
|
|
7
|
+
import Globals from './loadData/Globals.js';
|
|
8
|
+
import { Router } from './routing/index.js';
|
|
7
9
|
|
|
8
10
|
export default class CrelteRequest extends Crelte {
|
|
9
11
|
/**
|
|
10
12
|
* The current request
|
|
13
|
+
*
|
|
14
|
+
* ## Warning
|
|
15
|
+
* Do not override this
|
|
11
16
|
*/
|
|
12
17
|
req: Request;
|
|
13
18
|
|
|
@@ -71,7 +76,7 @@ export default class CrelteRequest extends Crelte {
|
|
|
71
76
|
* `.getGlobalAsync`
|
|
72
77
|
*/
|
|
73
78
|
getGlobal<T = any>(name: string): T | null {
|
|
74
|
-
return this.globals.get(name
|
|
79
|
+
return this.globals.get(name);
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
/**
|
|
@@ -82,9 +87,13 @@ export default class CrelteRequest extends Crelte {
|
|
|
82
87
|
* you can use `.getGlobal` which does return a Promise
|
|
83
88
|
*/
|
|
84
89
|
async getGlobalAsync<T = any>(name: string): Promise<T | null> {
|
|
85
|
-
return this.globals.getAsync(name
|
|
90
|
+
return this.globals.getAsync(name);
|
|
86
91
|
}
|
|
87
92
|
|
|
93
|
+
// todo we should override getPlugin making it possible for the plugin
|
|
94
|
+
// to attach a CrelteRequest to itself
|
|
95
|
+
// for that we should call cloneWithRequest(cr: CrelteRequest)
|
|
96
|
+
|
|
88
97
|
/**
|
|
89
98
|
* Run a GraphQl Query
|
|
90
99
|
*
|
|
@@ -104,6 +113,16 @@ export default class CrelteRequest extends Crelte {
|
|
|
104
113
|
...opts,
|
|
105
114
|
});
|
|
106
115
|
}
|
|
116
|
+
|
|
117
|
+
/** @hidden */
|
|
118
|
+
_setRouter(router: Router) {
|
|
119
|
+
this._router = router;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** @hidden */
|
|
123
|
+
_setGlobals(globals: Globals) {
|
|
124
|
+
this._globals = globals;
|
|
125
|
+
}
|
|
107
126
|
}
|
|
108
127
|
|
|
109
128
|
export function requestFromCrelte(
|
|
@@ -7,8 +7,6 @@ import { parseCookies, setCookieToString } from './utils.js';
|
|
|
7
7
|
export default class ClientCookies implements Cookies {
|
|
8
8
|
constructor() {}
|
|
9
9
|
|
|
10
|
-
_init(_cookies: string): void {}
|
|
11
|
-
|
|
12
10
|
get(name: string): string | null {
|
|
13
11
|
const cookies = getCookies();
|
|
14
12
|
return cookies.get(name) ?? null;
|
|
@@ -9,14 +9,9 @@ export default class ServerCookies implements Cookies {
|
|
|
9
9
|
requestCookies: Map<string, string>;
|
|
10
10
|
setCookies: Map<string, SetCookie>;
|
|
11
11
|
|
|
12
|
-
constructor() {
|
|
13
|
-
this.requestCookies = new Map();
|
|
14
|
-
this.setCookies = new Map();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
_init(cookies: string): void {
|
|
18
|
-
// parse the cookies
|
|
12
|
+
constructor(cookies: string) {
|
|
19
13
|
this.requestCookies = parseCookies(cookies);
|
|
14
|
+
this.setCookies = new Map();
|
|
20
15
|
}
|
|
21
16
|
|
|
22
17
|
/// Rethrns the value of the cookie with the given name, or null if it doesn't exist.
|
package/src/cookies/index.ts
CHANGED
package/src/graphql/GraphQl.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import BaseRoute from '../routing/BaseRoute.js';
|
|
1
2
|
import Route from '../routing/Route.js';
|
|
2
3
|
import SsrCache, { calcKey as ssrCacheCalcKey } from '../ssr/SsrCache.js';
|
|
3
4
|
|
|
@@ -75,7 +76,7 @@ export type GraphQlRequestOptions = {
|
|
|
75
76
|
* !! the route here might not contain a site even if the types
|
|
76
77
|
* says it does. CrelteServer does not know about site
|
|
77
78
|
*/
|
|
78
|
-
route?:
|
|
79
|
+
route?: BaseRoute | URL;
|
|
79
80
|
ignoreStatusCode?: boolean;
|
|
80
81
|
previewToken?: string;
|
|
81
82
|
siteToken?: string;
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,6 @@ import type Site from './routing/Site.js';
|
|
|
6
6
|
import type GraphQl from './graphql/GraphQl.js';
|
|
7
7
|
import Crelte, { type QueryOptions, type Config } from './Crelte.js';
|
|
8
8
|
import CrelteRequest from './CrelteRequest.js';
|
|
9
|
-
import type { Global } from './loadData/Globals.js';
|
|
10
9
|
import type { Cookies } from './cookies/index.js';
|
|
11
10
|
import type { Readable } from 'crelte-std/stores';
|
|
12
11
|
import {
|
|
@@ -97,6 +96,19 @@ export function getSite(): Readable<Site> {
|
|
|
97
96
|
return getRouter().site as Readable<Site>;
|
|
98
97
|
}
|
|
99
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Get a store with the current entry
|
|
101
|
+
*
|
|
102
|
+
* ## Note
|
|
103
|
+
* This only works during component initialisation.
|
|
104
|
+
*/
|
|
105
|
+
export function getEntry(): Readable<Entry> {
|
|
106
|
+
/// the entry will never be null because it is only null in the
|
|
107
|
+
// first loadData call and that happens before any component
|
|
108
|
+
// initialisation
|
|
109
|
+
return getRouter().entry as Readable<Entry>;
|
|
110
|
+
}
|
|
111
|
+
|
|
100
112
|
/**
|
|
101
113
|
* returns an env variable from the craft/.env file.
|
|
102
114
|
* All env variables need to start with VITE_
|
|
@@ -138,7 +150,7 @@ export function getLoadingProgress(): Readable<number> {
|
|
|
138
150
|
* ## Note
|
|
139
151
|
* This only works during component initialisation.
|
|
140
152
|
*/
|
|
141
|
-
export function getGlobal<T = any>(name: string):
|
|
153
|
+
export function getGlobal<T = any>(name: string): Readable<T> | null {
|
|
142
154
|
return getCrelte().globals.getStore(name);
|
|
143
155
|
}
|
|
144
156
|
|
|
@@ -158,11 +170,9 @@ export function getCookies(): Cookies {
|
|
|
158
170
|
* ## Note
|
|
159
171
|
* This only works during component initialisation.
|
|
160
172
|
*/
|
|
161
|
-
export function onRoute(fn: (route: Route
|
|
173
|
+
export function onRoute(fn: (route: Route) => void) {
|
|
162
174
|
const crelte = getCrelte();
|
|
163
|
-
const rmListener = crelte.router.onRoute(route =>
|
|
164
|
-
fn(route, crelte);
|
|
165
|
-
});
|
|
175
|
+
const rmListener = crelte.router.onRoute(route => fn(route));
|
|
166
176
|
|
|
167
177
|
onDestroy(rmListener);
|
|
168
178
|
}
|
|
@@ -175,9 +185,7 @@ export function onRoute(fn: (route: Route, crelte: Crelte) => void) {
|
|
|
175
185
|
*/
|
|
176
186
|
export function onRequest(fn: (cr: CrelteRequest) => void) {
|
|
177
187
|
const crelte = getCrelte();
|
|
178
|
-
const rmListener = crelte.router.onRequest(
|
|
179
|
-
fn(new CrelteRequest(crelte, req));
|
|
180
|
-
});
|
|
188
|
+
const rmListener = crelte.router.onRequest(cr => fn(cr));
|
|
181
189
|
|
|
182
190
|
onDestroy(rmListener);
|
|
183
191
|
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Entry } from '../entry/index.js';
|
|
2
|
+
import { Crelte } from '../index.js';
|
|
3
|
+
import { LoadData } from '../loadData/index.js';
|
|
4
|
+
import { PluginCreator } from '../plugins/index.js';
|
|
5
|
+
|
|
6
|
+
export interface App {
|
|
7
|
+
plugins?: PluginCreator[];
|
|
8
|
+
|
|
9
|
+
templates?: Record<string, LazyTemplateModule>;
|
|
10
|
+
|
|
11
|
+
loadGlobalData?: LoadData<null>;
|
|
12
|
+
|
|
13
|
+
loadEntry: LoadData<null>;
|
|
14
|
+
|
|
15
|
+
// todo: add a generic
|
|
16
|
+
loadEntryData?: LoadData<Entry>;
|
|
17
|
+
|
|
18
|
+
// entryRoutes?: EntryRoutes;
|
|
19
|
+
|
|
20
|
+
init?: (crelte: Crelte) => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface TemplateModule {
|
|
24
|
+
// svelte component
|
|
25
|
+
default: any;
|
|
26
|
+
|
|
27
|
+
loadData?: LoadData<Entry>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type LazyTemplateModule =
|
|
31
|
+
| (() => Promise<TemplateModule>)
|
|
32
|
+
| TemplateModule;
|
|
33
|
+
|
|
34
|
+
export type TemplateModules = Map<string, LazyTemplateModule>;
|
|
35
|
+
|
|
36
|
+
export default class InternalApp {
|
|
37
|
+
inner: App;
|
|
38
|
+
templateModules: TemplateModules;
|
|
39
|
+
|
|
40
|
+
constructor(inner: App) {
|
|
41
|
+
this.inner = inner;
|
|
42
|
+
this.templateModules = prepareTemplates(inner.templates ?? {});
|
|
43
|
+
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
if (inner.loadData) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
'loadData is ambigous, choose loadGlobalData or ' +
|
|
48
|
+
'loadEntryData depending on if you need access to the entry or not?',
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!inner.loadEntry) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
'loadEntry is required in the app. `export const loadEntry ' +
|
|
55
|
+
'= entryQuery;`',
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
get plugins(): PluginCreator[] {
|
|
61
|
+
return this.inner.plugins ?? [];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
get loadGlobalData(): LoadData<null> | undefined {
|
|
65
|
+
return this.inner.loadGlobalData;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
init(crelte: Crelte): void {
|
|
69
|
+
this.inner.init?.(crelte);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get loadEntry(): LoadData<null> {
|
|
73
|
+
return this.inner.loadEntry;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async loadTemplate(entry: Entry): Promise<TemplateModule> {
|
|
77
|
+
const modules = this.templateModules;
|
|
78
|
+
const entr = entry as any;
|
|
79
|
+
const handle = `${entr.sectionHandle}-${entr.typeHandle}`;
|
|
80
|
+
|
|
81
|
+
if (
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
import.meta.env.DEV &&
|
|
84
|
+
!modules.has(handle) &&
|
|
85
|
+
!modules.has(entr.sectionHandle)
|
|
86
|
+
) {
|
|
87
|
+
console.error(
|
|
88
|
+
`Template not found: <${handle}>, expecting file: ${handle}.svelte or ${entr.sectionHandle}.svelte`,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const loadMod =
|
|
93
|
+
modules.get(handle) ??
|
|
94
|
+
modules.get(entr.sectionHandle) ??
|
|
95
|
+
modules.get('error-404');
|
|
96
|
+
if (!loadMod) throw new Error('could not find error-404 template');
|
|
97
|
+
|
|
98
|
+
if (typeof loadMod === 'function') {
|
|
99
|
+
return await loadMod();
|
|
100
|
+
}
|
|
101
|
+
return loadMod;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get loadEntryData(): LoadData<Entry> | null {
|
|
105
|
+
return this.inner.loadEntryData;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function prepareTemplates(
|
|
110
|
+
rawModules: Record<string, LazyTemplateModule>,
|
|
111
|
+
): Map<string, LazyTemplateModule> {
|
|
112
|
+
// parse modules
|
|
113
|
+
return new Map(
|
|
114
|
+
Object.entries(rawModules)
|
|
115
|
+
.map(([path, mod]) => {
|
|
116
|
+
const [name, _ext] = parseFilename(path);
|
|
117
|
+
return [name, mod] as [string, LazyTemplateModule];
|
|
118
|
+
})
|
|
119
|
+
.filter(([name, _mod]) => !!name),
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function parseFilename(path: string): [string, string] {
|
|
124
|
+
// get filename with extension
|
|
125
|
+
const slash = path.lastIndexOf('/');
|
|
126
|
+
const filename = path.substring(slash + 1);
|
|
127
|
+
|
|
128
|
+
const extPos = filename.lastIndexOf('.');
|
|
129
|
+
|
|
130
|
+
const name = filename.substring(0, extPos);
|
|
131
|
+
const ext = filename.substring(extPos + 1);
|
|
132
|
+
|
|
133
|
+
return [name, ext];
|
|
134
|
+
}
|