@antelopejs/dms-frontend 0.5.1 → 0.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antelopejs/dms-frontend",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Frontend-agnostic loader for AntelopeJS DMS, shipping the Vue 3 renderer (Vite, Inertia, SSR)",
5
5
  "keywords": [
6
6
  "antelope",
@@ -537,11 +537,54 @@ function parseRoute(runtime: DmsFrontendRuntime, url: string): DmsRoute {
537
537
  };
538
538
  }
539
539
 
540
+ function hasSameEntries(
541
+ left: Record<string, string>,
542
+ right: Record<string, string>,
543
+ ): boolean {
544
+ const keys = Object.keys(left);
545
+ return (
546
+ keys.length === Object.keys(right).length &&
547
+ keys.every((key) => right[key] === left[key])
548
+ );
549
+ }
550
+
551
+ // Every parse builds a new query, params and matched: assigning them as they
552
+ // come would re-run each watcher of the route on every call of useDmsRoute,
553
+ // though the URL did not change. They are only replaced when their content did.
540
554
  function updateRoute(runtime: DmsFrontendRuntime, url: string): void {
541
555
  // The meta is the page's, not the URL's: a page declares it, then reads its
542
556
  // route, and the middleware the meta selected must still find it.
543
- const { meta: _pageMeta, ...location } = parseRoute(runtime, url);
544
- Object.assign(runtime.route, location);
557
+ const {
558
+ meta: _pageMeta,
559
+ query,
560
+ params,
561
+ matched,
562
+ ...location
563
+ } = parseRoute(runtime, url);
564
+ const route = runtime.route;
565
+ if (!hasSameEntries(query, route.query)) route.query = query;
566
+ if (!hasSameEntries(params, route.params)) route.params = params;
567
+ if (matched.length !== route.matched.length) route.matched = matched;
568
+ Object.assign(route, location);
569
+ }
570
+
571
+ const URL_BASE = "http://frontend.local";
572
+
573
+ // The URL the browser shows: it may be ahead of the route, which follows
574
+ // Inertia's page, when a component wrote it in place (history.replaceState).
575
+ function currentUrl(runtime: DmsFrontendRuntime): string {
576
+ if (runtime.isServer || typeof window === "undefined")
577
+ return new URL(runtime.route.fullPath, URL_BASE).href;
578
+ return window.location.href;
579
+ }
580
+
581
+ // One spelling per URL: `a b`, `a+b` and `a%20b` are the same query, as are
582
+ // `:` and `%3A`. The origin is kept, so a URL of another site never matches
583
+ // the current one, whatever its path.
584
+ function normalizeUrl(url: string, base: string): string {
585
+ const parsed = new URL(url, base);
586
+ const search = parsed.searchParams.toString();
587
+ return `${parsed.origin}${parsed.pathname}${search ? `?${search}` : ""}${parsed.hash}`;
545
588
  }
546
589
 
547
590
  function locationToUrl(
@@ -645,10 +688,13 @@ export function useDmsRoute(pattern?: string): DmsRoute {
645
688
 
646
689
  export function useDmsRouter(): DmsRouter {
647
690
  const runtime = useDmsRuntime();
648
- const navigate = (to: RouteLocationRaw, options?: DmsNavigationOptions) =>
649
- locationToUrl(runtime, to) === runtime.route.fullPath
691
+ const navigate = (to: RouteLocationRaw, options?: DmsNavigationOptions) => {
692
+ const current = currentUrl(runtime);
693
+ return normalizeUrl(locationToUrl(runtime, to), current) ===
694
+ normalizeUrl(current, current)
650
695
  ? Promise.resolve()
651
696
  : visit(runtime, to, options);
697
+ };
652
698
  return {
653
699
  currentRoute: computed(() => runtime.route),
654
700
  push: navigate,