@mauroandre/velojs 0.0.43 → 0.0.44

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.
@@ -127,8 +127,10 @@ Understanding the data flow helps you debug issues:
127
127
 
128
128
  **Client-side navigation (SPA):**
129
129
  1. User clicks a link
130
- 2. VeloJS compares each module's route pattern against the new URL and marks stale the ones whose **declared params** changed
130
+ 2. VeloJS marks stale the modules whose **declared params** changed — or that **were not part of the previous location** (they unmounted and are remounting now)
131
131
  3. One `?_data=1` request serves all of them
132
132
  4. Only the stale modules are written — a module the client owns locally (a filtered list, an optimistic edit) is left alone
133
133
 
134
- That last point is why a layout at `/admin/empresas` keeps a filtered list while you navigate among its children: its route declares no param, so nothing invalidates it.
134
+ The second rule is why returning to a page always shows fresh data: leaving `/` for `/leads` unmounts the Dashboard, so navigating back re-runs its loader. The first rule is why `/leads/1` → `/leads/2` refetches.
135
+
136
+ That last point is why a layout at `/admin/empresas` keeps a filtered list while you navigate among its children: it stays matched the whole time — no param changed and it never unmounted, so nothing invalidates it. (Leaving the subtree entirely and coming back *does* revalidate it — the layout remounted.)
@@ -7,9 +7,12 @@
7
7
  * no module-scope mirror to keep in sync.
8
8
  *
9
9
  * Invalidation follows the route tree: an entry is stale when the params its own
10
- * route declares have changed. That is what the server already does — a loader
11
- * re-runs when a request arrives with different params — so the client stops
12
- * making the author restate it in `useLoader([params.id])`.
10
+ * route declares have changed — or when the module was not part of the previous
11
+ * location's matched chain (it unmounted and is now remounting). The first rule
12
+ * mirrors the server (a loader re-runs when a request arrives with different
13
+ * params); the second mirrors user expectation (returning to a page shows fresh
14
+ * data). A layout keeps its data while navigating among its children because it
15
+ * stays matched the whole time — its client-owned state survives.
13
16
  *
14
17
  * Deliberately NOT invalidated by:
15
18
  * - a query-string change: `routes.tsx` declares path params, never `?x=`, so
@@ -32,14 +35,16 @@ export declare function registerRoutePatterns(routes: AppRoutes): void;
32
35
  /**
33
36
  * Extract the params a pattern declares from a pathname. Layout patterns are
34
37
  * prefixes of the URL (`/x/:id` covers `/x/1/tab`), mirroring how the client
35
- * router matches them, so the match is prefix-tolerant.
38
+ * router matches them, so the match is prefix-tolerant. Leaf patterns (routes
39
+ * without children) match exactly, mirroring wouter's exact `<Route>` for them.
36
40
  *
37
41
  * Returns null when the pattern does not cover the pathname at all.
38
42
  */
39
- export declare function extractParams(pattern: string, pathname: string): Record<string, string> | null;
43
+ export declare function extractParams(pattern: string, pathname: string, exact?: boolean): Record<string, string> | null;
40
44
  /**
41
45
  * Called on every client navigation. Refetches exactly the entries whose
42
- * declared params changed, in one coalesced request.
46
+ * declared params changed OR that were not matched at the previous location
47
+ * (they unmounted and are remounting now), in one coalesced request.
43
48
  */
44
49
  export declare function syncLocation(pathname: string): void;
45
50
  /** Explicit refresh. Never coalesced: a caller asking after a mutation must not
@@ -1,103 +1,119 @@
1
- import { signal as f } from "@preact/signals";
2
- const p = f(!1), c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), _ = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new WeakSet();
3
- let u = !1;
4
- function S(t) {
5
- y();
1
+ import { signal as d } from "@preact/signals";
2
+ const S = d(!1), c = /* @__PURE__ */ new Map(), _ = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Set(), p = /* @__PURE__ */ new Map();
3
+ let u = /* @__PURE__ */ new Set();
4
+ const l = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new WeakSet();
5
+ let w = !1;
6
+ function E(t) {
7
+ v();
6
8
  let e = c.get(t);
7
- return e || (e = f(null), c.set(t, e)), e;
9
+ return e || (e = d(null), c.set(t, e)), e;
8
10
  }
9
- function w(t) {
10
- let e = l.get(t);
11
- return e || (e = f(!1), l.set(t, e)), e;
11
+ function g(t) {
12
+ let e = _.get(t);
13
+ return e || (e = d(!1), _.set(t, e)), e;
12
14
  }
13
- function y() {
14
- if (u || typeof window > "u") return;
15
- u = !0;
15
+ function v() {
16
+ if (w || typeof window > "u") return;
17
+ w = !0;
16
18
  const t = window.__PAGE_DATA__;
17
19
  if (t)
18
20
  for (const e of Object.keys(t)) {
19
21
  if (e.startsWith("__")) continue;
20
22
  let n = c.get(e);
21
- n || (n = f(null), c.set(e, n)), n.value = t[e];
23
+ n || (n = d(null), c.set(e, n)), n.value = t[e];
22
24
  }
23
25
  }
24
- function O(t) {
25
- if (h.has(t)) return;
26
- h.add(t);
26
+ function x(t) {
27
+ if (y.has(t)) return;
28
+ y.add(t);
27
29
  const e = (n) => {
28
30
  for (const o of n) {
29
31
  const i = o.module?.metadata;
30
- i?.moduleId && i.fullPath !== void 0 && d.set(i.moduleId, i.fullPath), o.children && e(o.children);
32
+ i?.moduleId && i.fullPath !== void 0 && (f.set(i.moduleId, i.fullPath), (!o.children || o.children.length === 0) && h.add(i.moduleId)), o.children && e(o.children);
31
33
  }
32
34
  };
33
35
  if (e(t), typeof window < "u") {
34
- y();
35
- for (const n of c.keys()) v(n, window.location.pathname);
36
+ v();
37
+ for (const n of c.keys()) M(n, window.location.pathname);
38
+ u = L(window.location.pathname);
36
39
  }
37
40
  }
38
- const k = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
39
- function E(t, e) {
40
- const n = [], o = t.split("/").map((r) => r.startsWith(":") ? (n.push(r.slice(1)), "([^/]+)") : k(r)).join("/"), i = e.match(new RegExp(`^${o}(?:/.*)?$`));
41
- if (!i) return null;
42
- const a = {};
43
- return n.forEach((r, L) => {
44
- a[r] = i[L + 1];
45
- }), a;
41
+ const P = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
42
+ function m(t, e, n = !1) {
43
+ const o = [], i = t.split("/").map((s) => s.startsWith(":") ? (o.push(s.slice(1)), "([^/]+)") : P(s)).join("/"), a = e.match(
44
+ new RegExp(n ? `^${i}/?$` : `^${i}(?:/.*)?$`)
45
+ );
46
+ if (!a) return null;
47
+ const r = {};
48
+ return o.forEach((s, A) => {
49
+ r[s] = a[A + 1];
50
+ }), r;
46
51
  }
47
- function g(t, e) {
48
- const n = d.get(t);
52
+ function O(t, e) {
53
+ const n = f.get(t);
54
+ return n === void 0 ? !1 : m(n, e, h.has(t)) !== null;
55
+ }
56
+ function L(t) {
57
+ const e = /* @__PURE__ */ new Set();
58
+ for (const n of f.keys())
59
+ O(n, t) && e.add(n);
60
+ return e;
61
+ }
62
+ function k(t, e) {
63
+ const n = f.get(t);
49
64
  if (n === void 0) return null;
50
- const o = E(n, e);
65
+ const o = m(n, e, h.has(t));
51
66
  return o === null ? null : JSON.stringify(o);
52
67
  }
53
- function v(t, e) {
54
- const n = g(t, e);
55
- n !== null && _.set(t, n);
68
+ function M(t, e) {
69
+ const n = k(t, e);
70
+ n !== null && p.set(t, n);
56
71
  }
57
- function P(t) {
72
+ function H(t) {
58
73
  if (typeof __VELO_STATIC__ < "u" && __VELO_STATIC__) return `${t === "/" ? "" : t}/index.json`;
59
74
  const n = new URLSearchParams(window.location.search);
60
75
  return n.set("_data", "1"), `${t}?${n.toString()}`;
61
76
  }
62
- async function m(t, e, n) {
77
+ async function $(t, e, n) {
63
78
  if (typeof window > "u" || t.length === 0) return;
64
- const o = P(e);
65
- for (const a of t) w(a).value = !0;
66
- let i = n ? s.get(o) : void 0;
67
- i || (i = fetch(o, { cache: "no-cache" }).then((a) => a.json()), n && (s.set(o, i), i.catch(() => {
68
- }).then(() => s.delete(o))));
79
+ const o = H(e);
80
+ for (const a of t) g(a).value = !0;
81
+ let i = n ? l.get(o) : void 0;
82
+ i || (i = fetch(o, { cache: "no-cache" }).then((a) => a.json()), n && (l.set(o, i), i.catch(() => {
83
+ }).then(() => l.delete(o))));
69
84
  try {
70
85
  const a = await i;
71
- typeof __VELO_BUILD_HASH__ < "u" && a.__buildHash && a.__buildHash !== __VELO_BUILD_HASH__ && (p.value = !0);
86
+ typeof __VELO_BUILD_HASH__ < "u" && a.__buildHash && a.__buildHash !== __VELO_BUILD_HASH__ && (S.value = !0);
72
87
  for (const r of t)
73
- r in a && (S(r).value = a[r], v(r, e));
88
+ r in a && (E(r).value = a[r], M(r, e));
74
89
  } catch {
75
90
  } finally {
76
- for (const a of t) w(a).value = !1;
91
+ for (const a of t) g(a).value = !1;
77
92
  }
78
93
  }
79
- function $(t) {
94
+ function T(t) {
80
95
  if (typeof window > "u") return;
81
- const e = [];
82
- for (const n of c.keys()) {
83
- const o = g(n, t);
84
- o !== null && _.get(n) !== o && e.push(n);
96
+ const e = [], n = L(t);
97
+ for (const o of c.keys()) {
98
+ if (!n.has(o)) continue;
99
+ const i = k(o, t);
100
+ p.get(o) === i && u.has(o) || e.push(o);
85
101
  }
86
- m(e, t, !0);
102
+ u = n, $(e, t, !0);
87
103
  }
88
- function H(t) {
89
- typeof window > "u" || m([t], window.location.pathname, !1);
104
+ function U(t) {
105
+ typeof window > "u" || $([t], window.location.pathname, !1);
90
106
  }
91
- function M() {
92
- c.clear(), l.clear(), d.clear(), _.clear(), s.clear(), u = !1, p.value = !1;
107
+ function D() {
108
+ c.clear(), _.clear(), f.clear(), h.clear(), p.clear(), u = /* @__PURE__ */ new Set(), l.clear(), w = !1, S.value = !1;
93
109
  }
94
110
  export {
95
- M as __resetLoaderStore,
96
- p as __veloUpdatePending,
97
- E as extractParams,
98
- S as loaderEntry,
99
- w as loaderLoading,
100
- H as refetchModule,
101
- O as registerRoutePatterns,
102
- $ as syncLocation
111
+ D as __resetLoaderStore,
112
+ S as __veloUpdatePending,
113
+ m as extractParams,
114
+ E as loaderEntry,
115
+ g as loaderLoading,
116
+ U as refetchModule,
117
+ x as registerRoutePatterns,
118
+ T as syncLocation
103
119
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mauroandre/velojs",
3
- "version": "0.0.43",
3
+ "version": "0.0.44",
4
4
  "type": "module",
5
5
  "description": "Fullstack web framework built on Hono + Preact with Vite-powered AST transforms",
6
6
  "keywords": [