crelte 0.3.0 → 0.3.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 +12 -0
- package/dist/Crelte.d.ts.map +1 -1
- package/dist/Crelte.js +12 -0
- package/dist/CrelteRequest.d.ts +0 -4
- package/dist/CrelteRequest.d.ts.map +1 -1
- package/dist/CrelteRequest.js +0 -4
- package/dist/entry/EntryRouter.d.ts +30 -0
- package/dist/entry/EntryRouter.d.ts.map +1 -0
- package/dist/entry/EntryRouter.js +45 -0
- package/dist/entry/index.d.ts +32 -0
- package/dist/entry/index.d.ts.map +1 -0
- package/dist/entry/index.js +31 -0
- package/dist/index.d.ts +2 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -6
- package/dist/init/client.d.ts +1 -1
- package/dist/init/client.d.ts.map +1 -1
- package/dist/init/client.js +4 -3
- package/dist/init/server.d.ts.map +1 -1
- package/dist/init/server.js +3 -2
- package/dist/init/shared.d.ts +3 -1
- package/dist/init/shared.d.ts.map +1 -1
- package/dist/init/shared.js +47 -26
- package/dist/routing/InnerRouter.d.ts +1 -10
- package/dist/routing/InnerRouter.d.ts.map +1 -1
- package/dist/routing/InnerRouter.js +20 -21
- package/dist/routing/Request.d.ts +2 -0
- package/dist/routing/Request.d.ts.map +1 -1
- package/dist/routing/Request.js +9 -0
- package/dist/routing/Route.d.ts +67 -1
- package/dist/routing/Route.d.ts.map +1 -1
- package/dist/routing/Route.js +98 -2
- package/dist/routing/Router.d.ts +49 -12
- package/dist/routing/Router.d.ts.map +1 -1
- package/dist/routing/Router.js +82 -28
- package/dist/routing/index.d.ts +2 -2
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/utils.d.ts +2 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +8 -0
- package/package.json +9 -4
- package/src/Crelte.ts +15 -0
- package/src/CrelteRequest.ts +0 -4
- package/src/entry/EntryRouter.ts +71 -0
- package/src/entry/index.ts +48 -0
- package/src/index.ts +2 -11
- package/src/init/client.ts +10 -3
- package/src/init/server.ts +9 -2
- package/src/init/shared.ts +78 -28
- package/src/routing/InnerRouter.ts +29 -30
- package/src/routing/Request.ts +11 -0
- package/src/routing/Route.ts +107 -2
- package/src/routing/Router.ts +110 -31
- package/src/routing/index.ts +2 -1
- package/src/utils.ts +10 -0
package/src/routing/Router.ts
CHANGED
|
@@ -17,6 +17,18 @@ const defaultRouterOpts = {
|
|
|
17
17
|
debugTiming: false,
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Allows to easely modify a Request
|
|
22
|
+
*
|
|
23
|
+
* If you return `false` the request will be aborted
|
|
24
|
+
*
|
|
25
|
+
* ## Example
|
|
26
|
+
* ```
|
|
27
|
+
* router.replace(req => (req.hash = ''));
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export type UpdateRequest = (req: Request) => boolean | null | undefined | void;
|
|
31
|
+
|
|
20
32
|
type LoadedMore = {
|
|
21
33
|
changeHistory: () => void;
|
|
22
34
|
};
|
|
@@ -122,6 +134,8 @@ export default class Router {
|
|
|
122
134
|
|
|
123
135
|
this._onRequest = new Listeners();
|
|
124
136
|
|
|
137
|
+
// these functions are exposed to the init "module"
|
|
138
|
+
// but should not be used by anybody else
|
|
125
139
|
this._internal = {
|
|
126
140
|
onLoaded: () => {},
|
|
127
141
|
onNothingLoaded: () => {},
|
|
@@ -209,11 +223,15 @@ export default class Router {
|
|
|
209
223
|
* // the following page will be opened https://example.com/de/foo/bar
|
|
210
224
|
* ```
|
|
211
225
|
*/
|
|
212
|
-
open(
|
|
213
|
-
|
|
214
|
-
|
|
226
|
+
open(
|
|
227
|
+
target: string | URL | Route | Request | UpdateRequest,
|
|
228
|
+
opts: RequestOptions = {},
|
|
229
|
+
) {
|
|
230
|
+
const req = this.targetOrUpdateToRequest(target, opts, {
|
|
215
231
|
origin: 'manual',
|
|
216
232
|
});
|
|
233
|
+
if (!req) return;
|
|
234
|
+
|
|
217
235
|
this.inner.open(req);
|
|
218
236
|
}
|
|
219
237
|
|
|
@@ -221,14 +239,24 @@ export default class Router {
|
|
|
221
239
|
* This pushes the new route without triggering a new pageload
|
|
222
240
|
*
|
|
223
241
|
* You can use this when using pagination for example change the route object
|
|
224
|
-
* (search argument) and then call
|
|
242
|
+
* (search argument) and then call push
|
|
225
243
|
*
|
|
226
244
|
* ## Note
|
|
227
245
|
* This will always set the origin to 'push'
|
|
228
246
|
* And will clear the scrollY value if you not provide a new one via the `opts`
|
|
229
247
|
* This will disableLoadData by default if you not provide an override via the `opts`
|
|
230
248
|
*
|
|
231
|
-
* ## Example
|
|
249
|
+
* ## Example using the update function
|
|
250
|
+
* ```
|
|
251
|
+
* import { getRouter } from 'crelte';
|
|
252
|
+
*
|
|
253
|
+
* const router = getRouter();
|
|
254
|
+
*
|
|
255
|
+
* const page = 1;
|
|
256
|
+
* router.push(req => req.setSearchParam('page', page || null));
|
|
257
|
+
* ```
|
|
258
|
+
*
|
|
259
|
+
* ## Example using the route object
|
|
232
260
|
* ```
|
|
233
261
|
* import { getRouter } from 'crelte';
|
|
234
262
|
*
|
|
@@ -237,21 +265,20 @@ export default class Router {
|
|
|
237
265
|
* const page = 1;
|
|
238
266
|
* const route = router.route.get();
|
|
239
267
|
* route.setSearchParam('page', page > 0 ? page : null);
|
|
240
|
-
* router.
|
|
268
|
+
* router.push(route);
|
|
241
269
|
* ```
|
|
242
270
|
*/
|
|
243
|
-
push(route: Route | Request, opts: RequestOptions = {}) {
|
|
244
|
-
//
|
|
245
|
-
|
|
246
|
-
const req = this.
|
|
247
|
-
...opts,
|
|
271
|
+
push(route: Route | Request | UpdateRequest, opts: RequestOptions = {}) {
|
|
272
|
+
// theoretically string and URL also work but we might
|
|
273
|
+
// change that in the future
|
|
274
|
+
const req = this.targetOrUpdateToRequest(route, opts, {
|
|
248
275
|
origin: 'push',
|
|
249
276
|
scrollY: opts.scrollY ?? undefined,
|
|
250
277
|
disableLoadData: opts.disableLoadData ?? true,
|
|
251
278
|
});
|
|
279
|
+
if (!req) return;
|
|
280
|
+
|
|
252
281
|
this.inner.push(req);
|
|
253
|
-
this.destroyRequest();
|
|
254
|
-
this.setNewRoute(route);
|
|
255
282
|
}
|
|
256
283
|
|
|
257
284
|
/**
|
|
@@ -263,16 +290,26 @@ export default class Router {
|
|
|
263
290
|
}
|
|
264
291
|
|
|
265
292
|
/**
|
|
266
|
-
* This replaces the state of the route without triggering
|
|
293
|
+
* This replaces the state of the route without triggering a new pageload
|
|
267
294
|
*
|
|
268
295
|
* You can use this when using some filters for example a search filter
|
|
269
296
|
*
|
|
270
297
|
* ## Note
|
|
271
298
|
* This will always set the origin to 'replace'
|
|
272
|
-
* And will clear the scrollY value if you
|
|
273
|
-
* This will disableLoadData by default if you
|
|
299
|
+
* And will clear the scrollY value if you don't provide a new one via the `opts`
|
|
300
|
+
* This will disableLoadData by default if you don't provide an override via the `opts`
|
|
274
301
|
*
|
|
275
|
-
* ## Example
|
|
302
|
+
* ## Example using the update function
|
|
303
|
+
* ```
|
|
304
|
+
* import { getRouter } from 'crelte';
|
|
305
|
+
*
|
|
306
|
+
* const router = getRouter();
|
|
307
|
+
*
|
|
308
|
+
* const search = 'foo';
|
|
309
|
+
* router.replace(req => req.setSearchParam('search', search));
|
|
310
|
+
* ```
|
|
311
|
+
*
|
|
312
|
+
* ## Example using the route object
|
|
276
313
|
* ```
|
|
277
314
|
* import { getRouter } from 'crelte';
|
|
278
315
|
*
|
|
@@ -280,21 +317,21 @@ export default class Router {
|
|
|
280
317
|
*
|
|
281
318
|
* const search = 'foo';
|
|
282
319
|
* const route = router.route.get();
|
|
283
|
-
* route.setSearchParam('search', search
|
|
284
|
-
* router.
|
|
320
|
+
* route.setSearchParam('search', search);
|
|
321
|
+
* router.replace(route);
|
|
285
322
|
* ```
|
|
286
323
|
*/
|
|
287
|
-
replace(route: Route | Request, opts: RequestOptions = {}) {
|
|
288
|
-
//
|
|
289
|
-
|
|
290
|
-
const req = this.
|
|
324
|
+
replace(route: Route | Request | UpdateRequest, opts: RequestOptions = {}) {
|
|
325
|
+
// theoretically string and URL also work but we might
|
|
326
|
+
// change that in the future
|
|
327
|
+
const req = this.targetOrUpdateToRequest(route, opts, {
|
|
291
328
|
origin: 'replace',
|
|
292
329
|
scrollY: opts.scrollY ?? undefined,
|
|
293
330
|
disableLoadData: opts.disableLoadData ?? true,
|
|
294
331
|
});
|
|
332
|
+
if (!req) return;
|
|
333
|
+
|
|
295
334
|
this.inner.replace(req);
|
|
296
|
-
this.destroyRequest();
|
|
297
|
-
this.setNewRoute(req);
|
|
298
335
|
}
|
|
299
336
|
|
|
300
337
|
/**
|
|
@@ -401,12 +438,12 @@ export default class Router {
|
|
|
401
438
|
};
|
|
402
439
|
});
|
|
403
440
|
|
|
404
|
-
const
|
|
405
|
-
|
|
441
|
+
const req = this.inner.targetToRequest(url);
|
|
442
|
+
req.origin = 'init';
|
|
406
443
|
|
|
407
444
|
// let's see if the url matches any route and site
|
|
408
445
|
// if not let's redirect to the site which matches the acceptLang
|
|
409
|
-
if (!
|
|
446
|
+
if (!req.siteMatches()) {
|
|
410
447
|
const site = this.inner.siteByAcceptLang(acceptLang);
|
|
411
448
|
|
|
412
449
|
return {
|
|
@@ -417,14 +454,15 @@ export default class Router {
|
|
|
417
454
|
};
|
|
418
455
|
}
|
|
419
456
|
|
|
420
|
-
this.inner.
|
|
457
|
+
this.inner.route = req.toRoute();
|
|
458
|
+
this.inner.onRoute(req, () => {});
|
|
421
459
|
|
|
422
460
|
const resp = await prom;
|
|
423
461
|
|
|
424
462
|
const hist = this.inner.history as ServerHistory;
|
|
425
463
|
if (hist.url || hist.req) {
|
|
426
464
|
const nReq = this.inner.targetToRequest(hist.req ?? hist.url!);
|
|
427
|
-
if (!
|
|
465
|
+
if (!req.eq(nReq)) {
|
|
428
466
|
return {
|
|
429
467
|
success: true,
|
|
430
468
|
redirect: true,
|
|
@@ -437,6 +475,7 @@ export default class Router {
|
|
|
437
475
|
return resp;
|
|
438
476
|
}
|
|
439
477
|
|
|
478
|
+
// gets called by the InnerRouter when a new route is requested
|
|
440
479
|
private _onRoute(req: Request, changeHistory: () => void) {
|
|
441
480
|
this.destroyRequest();
|
|
442
481
|
|
|
@@ -453,6 +492,7 @@ export default class Router {
|
|
|
453
492
|
if (!req.disableLoadData) {
|
|
454
493
|
this.pageLoader.load(req, { changeHistory });
|
|
455
494
|
} else {
|
|
495
|
+
this.pageLoader.discard();
|
|
456
496
|
this._onNothingLoaded(req, { changeHistory });
|
|
457
497
|
}
|
|
458
498
|
}
|
|
@@ -468,6 +508,7 @@ export default class Router {
|
|
|
468
508
|
this.pageLoader.preload(req);
|
|
469
509
|
}
|
|
470
510
|
|
|
511
|
+
// gets called by the pageLoader when teh loadData completes
|
|
471
512
|
private async _onLoaded(
|
|
472
513
|
resp: LoadResponse,
|
|
473
514
|
req: Request,
|
|
@@ -477,7 +518,7 @@ export default class Router {
|
|
|
477
518
|
if (await req._renderBarrier.ready()) return;
|
|
478
519
|
|
|
479
520
|
// when the data is loaded let's update the route of the inner
|
|
480
|
-
// this
|
|
521
|
+
// this will only happen if no other route has been requested
|
|
481
522
|
// in the meantime
|
|
482
523
|
more.changeHistory();
|
|
483
524
|
|
|
@@ -490,6 +531,7 @@ export default class Router {
|
|
|
490
531
|
});
|
|
491
532
|
}
|
|
492
533
|
|
|
534
|
+
// this gets called if loadData is not called
|
|
493
535
|
private async _onNothingLoaded(req: Request, more: LoadedMore) {
|
|
494
536
|
// check if the render was cancelled
|
|
495
537
|
if (await req._renderBarrier.ready()) return;
|
|
@@ -508,9 +550,46 @@ export default class Router {
|
|
|
508
550
|
});
|
|
509
551
|
}
|
|
510
552
|
|
|
553
|
+
// this is called by the pageLoader if we get a progress update
|
|
511
554
|
private _onProgress(loading: boolean, progress?: number): void {
|
|
512
555
|
if (this._loading.get() !== loading) this._loading.set(loading);
|
|
513
556
|
|
|
514
557
|
if (typeof progress === 'number') this._loadingProgress.set(progress);
|
|
515
558
|
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Transforms a target to a request
|
|
562
|
+
*
|
|
563
|
+
* returns null if the request was canceled by the update request
|
|
564
|
+
*/
|
|
565
|
+
private targetOrUpdateToRequest(
|
|
566
|
+
target: string | URL | Route | Request | UpdateRequest,
|
|
567
|
+
opts: RequestOptions = {},
|
|
568
|
+
forcedOpts: RequestOptions = {},
|
|
569
|
+
): Request | null {
|
|
570
|
+
// we have an update request
|
|
571
|
+
if (typeof target === 'function') {
|
|
572
|
+
const route = this.route.get();
|
|
573
|
+
if (!route) {
|
|
574
|
+
throw new Error(
|
|
575
|
+
'route to update missing in first loadData call',
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// first get a req
|
|
580
|
+
const req = this.inner.targetToRequest(route, opts);
|
|
581
|
+
// check if the request was canceled by the update request
|
|
582
|
+
if (target(req) === false) return null;
|
|
583
|
+
|
|
584
|
+
// now we add the forcedOpts
|
|
585
|
+
req._updateOpts(forcedOpts);
|
|
586
|
+
|
|
587
|
+
return req;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
return this.inner.targetToRequest(target, {
|
|
591
|
+
...opts,
|
|
592
|
+
...forcedOpts,
|
|
593
|
+
});
|
|
594
|
+
}
|
|
516
595
|
}
|
package/src/routing/index.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import Router from './Router.js';
|
|
1
|
+
import Router, { type UpdateRequest } from './Router.js';
|
|
2
2
|
import Route, { type RouteOptions } from './Route.js';
|
|
3
3
|
import Request, { type RequestOptions, type DelayRender } from './Request.js';
|
|
4
4
|
import Site from './Site.js';
|
|
5
5
|
|
|
6
6
|
export {
|
|
7
7
|
Router,
|
|
8
|
+
UpdateRequest,
|
|
8
9
|
Route,
|
|
9
10
|
RouteOptions,
|
|
10
11
|
Site,
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// This are internal utils. Consider adding them to crelte-std instead
|
|
2
|
+
|
|
3
|
+
// this tries to do a structuredClone and else just uses JSON
|
|
4
|
+
export function objClone(obj: any): any {
|
|
5
|
+
if (typeof structuredClone === 'function') {
|
|
6
|
+
return structuredClone(obj);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return JSON.parse(JSON.stringify(obj));
|
|
10
|
+
}
|