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
@@ -1,8 +1,10 @@
1
- import { objClone } from '../utils.js';
2
1
  import Site from './Site.js';
3
- import { trimSlashEnd } from './utils.js';
2
+ import { objClone } from '../utils.js';
3
+ import { Entry, LoadData } from '../index.js';
4
+ import BaseRoute, { RouteOrigin } from './BaseRoute.js';
4
5
 
5
6
  export type RouteOptions = {
7
+ entryChanged?: boolean;
6
8
  scrollY?: number;
7
9
  index?: number;
8
10
  origin?: RouteOrigin;
@@ -10,408 +12,86 @@ export type RouteOptions = {
10
12
  context?: Record<string, any>;
11
13
  };
12
14
 
13
- /**
14
- * RouteOrigin represents the origin of a route.
15
- * This type is non-exhaustive and might expand in the future.
16
- *
17
- * - `'init'`: is set on the first page load
18
- * - `'manual'`: is set when a route is triggered manually via `Router.open`
19
- * - `'click'`: is set when a route is triggered by a click event
20
- * - `'pop'`: is set when a route is triggered by a popstate event (back/forward)
21
- * - `'replace'`: is set when a route is replaced via `Router.replaceState`
22
- * - `'push'`: is set when a route is pushed via `Router.pushState`
23
- *
24
- * ## Note
25
- * `replace` and `push` will not call loadData
26
- */
27
- export type RouteOrigin =
28
- | 'init'
29
- | 'manual'
30
- | 'click'
31
- | 'pop'
32
- | 'replace'
33
- | 'push';
15
+ export interface TemplateModule {
16
+ // svelte component
17
+ default: any;
18
+
19
+ loadData?: LoadData<Entry>;
20
+ }
34
21
 
35
22
  /**
36
- * A Route contains information about the current page for example the url and
37
- * the site
23
+ * A Route contains information about the current page for example the url,
24
+ * the site and its entry.
38
25
  */
39
- export default class Route {
26
+ export default class Route extends BaseRoute {
40
27
  /**
41
- * The url of the route
28
+ * The entry of the route
42
29
  */
43
- url: URL;
30
+ entry: Entry;
44
31
 
45
32
  /**
46
- * The site of the route
47
- *
48
- * ## Note
49
- * The site might not always match with the current route
50
- * but be the site default site or one that matches the
51
- * users language.
52
- *
53
- * If that is important call `route.siteMatches()` to verify
33
+ * The template module of the route
54
34
  */
55
- site: Site;
56
-
57
- /**
58
- * The scroll position of the current route
59
- *
60
- * ## Note
61
- * This does not have to represent the current scroll position
62
- * should more be used internally.
63
- *
64
- * It might be useful for a new request to specify the wanted
65
- * scroll position
66
- */
67
- scrollY: number | null;
68
-
69
- /**
70
- * the position in the browser history of this route
71
- * this allows to find out if we can go back
72
- */
73
- index: number;
74
-
75
- /**
76
- * The origin of this route, See [[RouteOrigin]]
77
- */
78
- origin: RouteOrigin;
79
-
80
- /**
81
- * @hidden
82
- * State data that can be used to store additional information
83
- */
84
- _state: Record<string, any>;
85
-
86
- /**
87
- * @hidden
88
- * Any data that should be passed to onRoute and onRequest handlers
89
- * or exchanged between loadData's
90
- * This context is not persistant and should be considered "valid"
91
- * only for the current request / route
92
- *
93
- * ## Note
94
- * Consider using state instead. This will not be cloned in the clone
95
- * call so will always be the same object
96
- */
97
- _context: Record<string, any>;
98
-
99
- /**
100
- * Creates a new Route
101
- */
102
- constructor(url: string | URL, site: Site, opts: RouteOptions = {}) {
103
- this.url = new URL(url);
104
-
105
- this.site = site;
106
- this.scrollY = opts.scrollY ?? null;
107
- this.index = opts.index ?? 0;
108
- this.origin = opts.origin ?? 'manual';
109
- this._state = opts.state ?? {};
110
- this._context = opts.context ?? {};
111
- }
35
+ template: TemplateModule;
112
36
 
113
37
  /**
114
- * Returns the uri of the route
115
- *
116
- * Never ends with a slash
117
- *
118
- * ## Example
119
- * ```
120
- * const site = _; // site with url https://example.com/fo
121
- * const route = new Route('https://example.com/foo/bar/', site);
122
- * console.log(route.uri); // '/bar'
123
- *
124
- * const site2 = _; // site with url https://example.com/other
125
- * const route2 = new Route('https://example.com/foo/bar/?a=1', site2);
126
- * console.log(route2.uri); // '/foo/bar'
127
- * ```
38
+ * The loaded data of the route
128
39
  */
129
- get uri(): string {
130
- if (this.siteMatches()) {
131
- return trimSlashEnd(
132
- this.url.pathname.substring(this.site.uri.length),
133
- );
134
- }
135
-
136
- return trimSlashEnd(this.url.pathname);
137
- }
40
+ loadedData: Record<string, any>;
138
41
 
139
42
  /**
140
- * Returns the base url of the route
141
- *
142
- * Never ends with a slash
143
- *
144
- * ## Example
145
- * ```
146
- * const site = _; // site with url https://example.com/foo
147
- * const route = new Route('https://example.com/foo/bar/', null);
148
- * console.log(route.baseUrl); // 'https://example.com/foo'
149
- *
150
- * const site2 = _; // site with url https://example.com/other
151
- * const route2 = new Route('https://example.com/foo/bar/', site2);
152
- * console.log(route2.baseUrl); // 'https://example.com'
153
- * ```
43
+ * Wether the entry changed since the last Route change
154
44
  */
155
- get baseUrl(): string {
156
- if (this.siteMatches()) return trimSlashEnd(this.site.url.href);
157
-
158
- return this.url.origin;
159
- }
45
+ entryChanged: boolean;
160
46
 
161
47
  /**
162
- * Returns the search params
48
+ * Create a new Route
163
49
  *
164
50
  * ## Note
165
- * You might also have a look at `getSearchParam` and `setSearchParam`
166
- *
167
- * ## Example
168
- * ```
169
- * const route = new Route('https://example.com/foo/bar/?a=1&b=2', null);
170
- * console.log(route.search.get('a')); // '1'
171
- * ```
172
- */
173
- get search(): URLSearchParams {
174
- return this.url.searchParams;
175
- }
176
-
177
- /**
178
- * Returns the hash of the route
179
- *
180
- * ## Example
181
- * ```
182
- * const route = new Route('https://example.com/foo/bar/#hash', null);
183
- * console.log(route.hash); // '#hash'
184
- * ```
185
- */
186
- get hash(): string {
187
- return this.url.hash;
188
- }
189
-
190
- /**
191
- * Set the hash of the route
192
- *
193
- * ## Example
194
- * ```
195
- * const route = new Route('https://example.com/foo/bar/', null);
196
- * route.hash = '#hash';
197
- * console.log(route.url.href); // 'https://example.com/foo/bar/#hash'
198
- * ```
199
- */
200
- set hash(hash: string) {
201
- this.url.hash = hash;
202
- }
203
-
204
- /**
205
- * Checks if there are previous routes which would allow it to go back
206
- */
207
- canGoBack(): boolean {
208
- return !!this.index;
209
- }
210
-
211
- /**
212
- * Gets the search param
213
- *
214
- * ## Example
215
- * ```
216
- * const route = new Route('https://example.com/foo/bar/?a=1&b=2', null);
217
- * console.log(route.getSearchParam('a')); // '1'
218
- * ```
219
- */
220
- getSearchParam(key: string): string | null {
221
- return this.search.get(key);
222
- }
223
-
224
- /**
225
- * Sets the search param or removes it if the value is null, undefined or an
226
- * empty string
227
- *
228
- * ## Example
229
- * ```
230
- * const route = new Route('https://example.com/foo/bar/?a=1&b=2', null);
231
- * route.setSearchParam('a', '3');
232
- * console.log(route.url.href); // 'https://example.com/foo/bar/?a=3&b=2'
233
- *
234
- * route.setSearchParam('a', null);
235
- * console.log(route.url.href); // 'https://example.com/foo/bar/?b=2'
236
- * ```
51
+ * This should only be created by crelte
237
52
  */
238
- setSearchParam(key: string, value?: string | number | null) {
239
- const deleteValue =
240
- typeof value === 'undefined' ||
241
- value === null ||
242
- (typeof value === 'string' && value === '');
53
+ constructor(
54
+ url: string | URL,
55
+ site: Site,
56
+ entry: Entry,
57
+ template: TemplateModule,
58
+ loadedData: Record<string, any>,
59
+ opts: RouteOptions = {},
60
+ ) {
61
+ super(url, site, opts);
243
62
 
244
- if (!deleteValue) {
245
- this.search.set(key, value as string);
246
- } else {
247
- this.search.delete(key);
248
- }
249
- }
250
-
251
- /**
252
- * Returns a state value if it exists.
253
- */
254
- getState<T = any>(key: string): T | null {
255
- return this._state[key] ?? null;
256
- }
257
-
258
- /**
259
- * Sets a state value.
260
- * If the value is null or undefined, the key will be removed.
261
- *
262
- * ## When to use state
263
- * State is used to store additional information that persists across route changes.
264
- * The State is only available in the client code since it is stored using window.history.
265
- *
266
- * Consider using setSearchParam instead to enable server side rendering.
267
- */
268
- setState<T>(key: string, value: T | null | undefined) {
269
- if (typeof value === 'undefined' || value === null) {
270
- delete this._state[key];
271
- } else {
272
- this._state[key] = value;
273
- }
274
- }
275
-
276
- /**
277
- * Returns a context value if it exists.
278
- */
279
- getContext<T = any>(key: string): T | null {
280
- return this._context[key] ?? null;
281
- }
282
-
283
- /**
284
- * Sets a context value.
285
- * If the value is null or undefined, the key will be removed.
286
- *
287
- * ## When to use context
288
- * Context is used to pass data to onRoute and onRequest handlers or exchange data between loadData calls.
289
- * This context is not persistent and should be considered valid only for the current request/route.
290
- * The context is not cloned in the clone call and will be the same object.
291
- */
292
- setContext<T>(key: string, value: T | null | undefined) {
293
- if (typeof value === 'undefined' || value === null) {
294
- delete this._context[key];
295
- } else {
296
- this._context[key] = value;
297
- }
298
- }
299
- /**
300
- * Returns true if the route is in live preview mode
301
- */
302
- inLivePreview(): boolean {
303
- return !!this.search.get('x-craft-live-preview');
304
- }
305
-
306
- /**
307
- * Returns if the site matches the url
308
- */
309
- siteMatches(): boolean {
310
- if (this.url.origin !== this.site.url.origin) return false;
311
-
312
- // now we need to validate the pathname we should make sure both end with a slash
313
- // todo can we do this better?
314
-
315
- // make sure that urls like pathname: /abcbc and site: /abc don't match
316
- return (this.url.pathname + '/').startsWith(
317
- // uri never returns a slash at the end
318
- this.site.uri + '/',
319
- );
63
+ this.entry = entry;
64
+ this.template = template;
65
+ this.loadedData = loadedData;
66
+ this.entryChanged = opts?.entryChanged ?? true;
320
67
  }
321
68
 
322
69
  /**
323
- * Checks if the route is equal to another route
324
- *
325
- * This checks all properties of the url but search params do not have to be
326
- * in the same order
70
+ * Create a copy of the EntryRoute
327
71
  *
328
72
  * ## Note
329
- * This does not check the state or context
330
- */
331
- eq(route: Route | null) {
332
- return (
333
- route &&
334
- this.eqUrl(route) &&
335
- this.eqSearch(route) &&
336
- this.eqHash(route)
337
- );
338
- }
339
-
340
- /**
341
- * Checks if the route is equal to another route
342
- *
343
- * This does not check the search params or hash
344
- */
345
- eqUrl(route: Route | null) {
346
- return (
347
- route &&
348
- this.url.pathname === route.url.pathname &&
349
- this.url.origin === route.url.origin
350
- );
351
- }
352
-
353
- /**
354
- * Checks if the search params are equal to another route
355
- */
356
- eqSearch(route: Route | null) {
357
- const searchEq = (a: URLSearchParams, b: URLSearchParams) => {
358
- if (a.size !== b.size) return false;
359
-
360
- a.sort();
361
- b.sort();
362
-
363
- const aEntries = Array.from(a.entries());
364
- const bEntries = Array.from(b.entries());
365
-
366
- return aEntries
367
- .map((a, i) => [a, bEntries[i]])
368
- .every(([[ak, av], [bk, bv]]) => ak === bk && av === bv);
369
- };
370
-
371
- return route && searchEq(this.search, route.search);
372
- }
373
-
374
- /**
375
- * Checks if the hash is equal to another route
376
- */
377
- eqHash(route: Route | null) {
378
- return route && this.hash === route.hash;
379
- }
380
-
381
- /**
382
- * Create a copy of the request
73
+ * This does not make a copy of the entry, template or loadedData.
383
74
  */
384
75
  clone() {
385
- return new Route(this.url.href, this.site, {
386
- scrollY: this.scrollY ?? undefined,
387
- index: this.index,
388
- origin: this.origin,
389
- state: objClone(this._state),
390
- context: this._context,
391
- });
392
- }
393
-
394
- /** @hidden */
395
- _fillFromState(state: any) {
396
- if (typeof state?.route?.scrollY === 'number')
397
- this.scrollY = state.route.scrollY;
398
-
399
- if (typeof state?.route?.index === 'number')
400
- this.index = state.route.index;
401
-
402
- if (typeof state?.state === 'object' && state.state !== null) {
403
- this._state = state.state;
404
- }
405
- }
406
-
407
- /** @hidden */
408
- _toState(): any {
409
- return {
410
- route: {
411
- scrollY: this.scrollY,
76
+ return new Route(
77
+ this.url.href,
78
+ this.site,
79
+ this.entry,
80
+ this.template,
81
+ this.loadedData,
82
+ {
83
+ scrollY: this.scrollY ?? undefined,
412
84
  index: this.index,
85
+ origin: this.origin,
86
+ state: objClone(this._state),
87
+ context: this._context,
413
88
  },
414
- state: this._state,
415
- };
89
+ );
416
90
  }
417
91
  }
92
+
93
+ export function isRoute(route: any): route is Route {
94
+ return (
95
+ typeof route === 'object' && route !== null && route instanceof Route
96
+ );
97
+ }