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.
Files changed (110) hide show
  1. package/dist/Crelte.d.ts +7 -6
  2. package/dist/Crelte.d.ts.map +1 -1
  3. package/dist/Crelte.js +5 -13
  4. package/dist/CrelteRequest.d.ts +9 -0
  5. package/dist/CrelteRequest.d.ts.map +1 -1
  6. package/dist/CrelteRequest.js +16 -2
  7. package/dist/blocks/Blocks.svelte +2 -2
  8. package/dist/blocks/Blocks.svelte.d.ts +3 -19
  9. package/dist/blocks/Blocks.svelte.d.ts.map +1 -1
  10. package/dist/cookies/ClientCookies.d.ts +0 -1
  11. package/dist/cookies/ClientCookies.d.ts.map +1 -1
  12. package/dist/cookies/ClientCookies.js +0 -1
  13. package/dist/cookies/ServerCookies.d.ts +1 -2
  14. package/dist/cookies/ServerCookies.d.ts.map +1 -1
  15. package/dist/cookies/ServerCookies.js +2 -6
  16. package/dist/cookies/index.d.ts +0 -2
  17. package/dist/cookies/index.d.ts.map +1 -1
  18. package/dist/graphql/GraphQl.d.ts +2 -2
  19. package/dist/graphql/GraphQl.d.ts.map +1 -1
  20. package/dist/index.d.ts +9 -3
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +14 -6
  23. package/dist/init/InternalApp.d.ts +30 -0
  24. package/dist/init/InternalApp.d.ts.map +1 -0
  25. package/dist/init/InternalApp.js +71 -0
  26. package/dist/init/client.d.ts +0 -5
  27. package/dist/init/client.d.ts.map +1 -1
  28. package/dist/init/client.js +88 -75
  29. package/dist/init/crelte-vite-plugin.d.ts +5 -0
  30. package/dist/init/server.d.ts +0 -5
  31. package/dist/init/server.d.ts.map +1 -1
  32. package/dist/init/server.js +49 -20
  33. package/dist/init/shared.d.ts +7 -18
  34. package/dist/init/shared.d.ts.map +1 -1
  35. package/dist/init/shared.js +97 -154
  36. package/dist/init/svelteComponents.d.ts +3 -0
  37. package/dist/init/svelteComponents.d.ts.map +1 -0
  38. package/dist/init/svelteComponents.js +7 -0
  39. package/dist/loadData/Globals.d.ts +40 -33
  40. package/dist/loadData/Globals.d.ts.map +1 -1
  41. package/dist/loadData/Globals.js +99 -88
  42. package/dist/loadData/index.d.ts +3 -2
  43. package/dist/loadData/index.d.ts.map +1 -1
  44. package/dist/loadData/index.js +2 -0
  45. package/dist/plugins/Events.d.ts +11 -13
  46. package/dist/plugins/Events.d.ts.map +1 -1
  47. package/dist/plugins/Events.js +10 -3
  48. package/dist/routing/BaseRoute.d.ts +255 -0
  49. package/dist/routing/BaseRoute.d.ts.map +1 -0
  50. package/dist/routing/BaseRoute.js +349 -0
  51. package/dist/routing/BaseRouter.d.ts +210 -0
  52. package/dist/routing/BaseRouter.d.ts.map +1 -0
  53. package/dist/routing/BaseRouter.js +444 -0
  54. package/dist/routing/ClientRouter.d.ts +32 -0
  55. package/dist/routing/ClientRouter.d.ts.map +1 -0
  56. package/dist/routing/ClientRouter.js +259 -0
  57. package/dist/routing/LoadRunner.d.ts +39 -0
  58. package/dist/routing/LoadRunner.d.ts.map +1 -0
  59. package/dist/routing/{PageLoader.js → LoadRunner.js} +32 -20
  60. package/dist/routing/Request.d.ts +35 -3
  61. package/dist/routing/Request.d.ts.map +1 -1
  62. package/dist/routing/Request.js +64 -5
  63. package/dist/routing/Route.d.ts +24 -223
  64. package/dist/routing/Route.d.ts.map +1 -1
  65. package/dist/routing/Route.js +26 -315
  66. package/dist/routing/Router.d.ts +49 -73
  67. package/dist/routing/Router.d.ts.map +1 -1
  68. package/dist/routing/Router.js +85 -251
  69. package/dist/routing/ServerRouter.d.ts +23 -0
  70. package/dist/routing/ServerRouter.d.ts.map +1 -0
  71. package/dist/routing/ServerRouter.js +57 -0
  72. package/dist/routing/utils.d.ts +5 -0
  73. package/dist/routing/utils.d.ts.map +1 -1
  74. package/dist/routing/utils.js +39 -0
  75. package/dist/utils.d.ts +1 -0
  76. package/dist/utils.d.ts.map +1 -1
  77. package/dist/utils.js +3 -0
  78. package/package.json +7 -6
  79. package/src/Crelte.ts +12 -18
  80. package/src/CrelteRequest.ts +21 -2
  81. package/src/cookies/ClientCookies.ts +0 -2
  82. package/src/cookies/ServerCookies.ts +2 -7
  83. package/src/cookies/index.ts +0 -3
  84. package/src/graphql/GraphQl.ts +2 -1
  85. package/src/index.ts +17 -9
  86. package/src/init/InternalApp.ts +134 -0
  87. package/src/init/client.ts +104 -93
  88. package/src/init/crelte-vite-plugin.d.ts +5 -0
  89. package/src/init/server.ts +67 -35
  90. package/src/init/shared.ts +107 -227
  91. package/src/init/svelteComponents.ts +12 -0
  92. package/src/loadData/Globals.ts +121 -102
  93. package/src/loadData/index.ts +3 -2
  94. package/src/plugins/Events.ts +40 -42
  95. package/src/routing/BaseRoute.ts +422 -0
  96. package/src/routing/BaseRouter.ts +528 -0
  97. package/src/routing/ClientRouter.ts +329 -0
  98. package/src/routing/{PageLoader.ts → LoadRunner.ts} +43 -30
  99. package/src/routing/Request.ts +97 -12
  100. package/src/routing/Route.ts +56 -376
  101. package/src/routing/Router.ts +100 -359
  102. package/src/routing/ServerRouter.ts +78 -0
  103. package/src/routing/utils.ts +53 -0
  104. package/src/utils.ts +4 -0
  105. package/dist/routing/InnerRouter.d.ts +0 -113
  106. package/dist/routing/InnerRouter.d.ts.map +0 -1
  107. package/dist/routing/InnerRouter.js +0 -417
  108. package/dist/routing/PageLoader.d.ts +0 -36
  109. package/dist/routing/PageLoader.d.ts.map +0 -1
  110. 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
+ }
@@ -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"}
@@ -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
@@ -1,3 +1,4 @@
1
1
  export declare function objClone(obj: any): any;
2
+ export declare function isPromise<T>(p: Promise<T> | T): p is Promise<T>;
2
3
  export declare const circles: Record<string, any>;
3
4
  //# sourceMappingURL=utils.d.ts.map
@@ -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
@@ -6,5 +6,8 @@ export function objClone(obj) {
6
6
  }
7
7
  return JSON.parse(JSON.stringify(obj));
8
8
  }
9
+ export function isPromise(p) {
10
+ return typeof p?.then === 'function';
11
+ }
9
12
  // this allows us to fix cyclic dependencies
10
13
  export const circles = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crelte",
3
- "version": "0.4.8",
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.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": "^3.0.0",
89
+ "@sveltejs/vite-plugin-svelte": "^4.0.0",
88
90
  "svelte-check": "^4.1.4",
89
91
  "typescript-svelte-plugin": "^0.3.45",
90
- "vite": "^5.0",
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, { Global } from './loadData/Globals.js';
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: 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(sites: SiteFromGraphQl[]) {
97
- this.router = new Router(sites, {
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: string) {
104
- this.cookies._init(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): Global<T> | null {
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
  }
@@ -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, this.site.id);
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, this.site.id);
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.
@@ -24,7 +24,4 @@ export interface Cookies {
24
24
  * removes the cookie
25
25
  */
26
26
  remove(name: string): void;
27
-
28
- /** @hidden */
29
- _init(cookies: string): void;
30
27
  }
@@ -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?: Route | URL;
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): Global<T> | null {
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, crelte: Crelte) => void) {
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(req => {
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
+ }