vue-router-query-sync 2.0.0-alpha.5 → 2.0.1-alpha.0

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/README.md CHANGED
@@ -60,38 +60,6 @@ const tab = toRef(filters, 'tab') // WritableComputedRef<'all' | 'favorite' | nu
60
60
  tab.value = 'favorite'
61
61
  ```
62
62
 
63
- ### `prefix` — namespacing keys
64
-
65
- When the same schema is used more than once on a page (e.g. one paginated component per
66
- tab), pass a `prefix` so each instance owns its own URL keys and they don't collide. Field
67
- names in `filters` stay unprefixed; only the URL key becomes `${prefix}-${key}`.
68
-
69
- ```ts
70
- const users = useQueryFilters({ page: param.number({ default: 1 }) }, { prefix: 'users' })
71
- const orders = useQueryFilters({ page: param.number({ default: 1 }) }, { prefix: 'orders' })
72
-
73
- users.filters.page = 3 // URL: ?users-page=3
74
- orders.filters.page = 5 // URL: ?users-page=3&orders-page=5
75
-
76
- users.filters.page // reads users-page only — independent from orders
77
- ```
78
-
79
- With a unique prefix per instance, keys never collide. Each instance keeps its own state in
80
- the URL, so switching between tabs and back restores their pagination; a direct link
81
- reproduces everything.
82
-
83
- The prefix applies to the whole schema. To namespace only some keys, split by scope: keep
84
- shared keys in a plain (unprefixed) call and private keys in a prefixed one.
85
-
86
- ```ts
87
- const { filters: shared } = useQueryFilters({ sort: param.enum(SortType) }) // ?sort=…
88
- const { filters } = useQueryFilters({ page: param.number({ default: 1 }) },
89
- { prefix: 'users' }) // ?users-page=…
90
- ```
91
-
92
- If you'd rather keep the URL minimal, render inactive tabs with `v-if` and call `reset()` in
93
- `onUnmounted` to drop the leaving tab's keys.
94
-
95
63
  ## `param`
96
64
 
97
65
  All options are shared: `{ default?: T; history?: 'push' | 'replace' }` (`history` defaults to
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { useQueryFilters } from './useQueryFilters';
2
2
  export { param } from './param';
3
3
  export { defineCodec } from './defineCodec';
4
- export type { QueryCodec, ParamOptions, Param, FilterSchema, InferFilters, UseQueryFiltersOptions, UseQueryFiltersReturn } from './types';
4
+ export type { QueryCodec, ParamOptions, Param, FilterSchema, InferFilters, UseQueryFiltersReturn } from './types';
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,YAAY,EACV,UAAU,EACV,YAAY,EACZ,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,YAAY,EACV,UAAU,EACV,YAAY,EACZ,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,qBAAqB,EACtB,MAAM,SAAS,CAAA"}
package/dist/index.mjs CHANGED
@@ -1,140 +1,120 @@
1
- import { reactive as m, computed as v } from "vue";
2
- import { useRoute as S, useRouter as P } from "vue-router";
3
- function A(e) {
1
+ import { reactive as A, computed as m } from "vue";
2
+ import { useRoute as o, useRouter as N } from "vue-router";
3
+ function h(e) {
4
4
  if (e != null)
5
5
  return Array.isArray(e) ? e.filter((r) => r !== null) : e;
6
6
  }
7
- function b(e, r) {
7
+ function v(e, r) {
8
8
  return e === r ? !0 : Array.isArray(e) && Array.isArray(r) ? e.length !== r.length ? !1 : e.every((t, u) => t === r[u]) : !1;
9
9
  }
10
- const g = /* @__PURE__ */ new WeakMap();
11
- function N(e) {
12
- let r = g.get(e);
10
+ const y = /* @__PURE__ */ new WeakMap();
11
+ function z(e) {
12
+ let r = y.get(e);
13
13
  return r || (r = {
14
- patch: m(/* @__PURE__ */ new Map()),
14
+ patch: A(/* @__PURE__ */ new Map()),
15
15
  usePush: !1,
16
16
  scheduled: !1
17
- }, g.set(e, r)), r;
17
+ }, y.set(e, r)), r;
18
18
  }
19
- function j(e, r) {
20
- const t = N(e);
19
+ function S(e, r) {
20
+ const t = z(e);
21
21
  return t.patch.has(r) ? { pending: !0, value: t.patch.get(r) ?? null } : { pending: !1, value: null };
22
22
  }
23
- function o(e, r, t, u) {
24
- const l = N(e);
25
- l.patch.set(r, t), u === "push" && (l.usePush = !0), l.scheduled || (l.scheduled = !0, queueMicrotask(() => O(e)));
23
+ function g(e, r, t, u) {
24
+ const l = z(e);
25
+ l.patch.set(r, t), u === "push" && (l.usePush = !0), l.scheduled || (l.scheduled = !0, queueMicrotask(() => k(e)));
26
26
  }
27
- function q(e, r) {
27
+ function j(e, r) {
28
28
  const t = Object.keys(e), u = Object.keys(r);
29
29
  if (t.length !== u.length)
30
30
  return !1;
31
- const l = (n, c) => {
32
- if (Array.isArray(n) || Array.isArray(c)) {
33
- const a = Array.isArray(n) ? n : [n], d = Array.isArray(c) ? c : [c];
34
- return a.length === d.length && a.every((f, i) => String(f) === String(d[i]));
31
+ const l = (n, a) => {
32
+ if (Array.isArray(n) || Array.isArray(a)) {
33
+ const s = Array.isArray(n) ? n : [n], c = Array.isArray(a) ? a : [a];
34
+ return s.length === c.length && s.every((i, b) => String(i) === String(c[b]));
35
35
  }
36
- return String(n) === String(c);
36
+ return String(n) === String(a);
37
37
  };
38
38
  return t.every((n) => n in r && l(e[n], r[n]));
39
39
  }
40
- function O(e) {
41
- const r = g.get(e);
40
+ function k(e) {
41
+ const r = y.get(e);
42
42
  if (!r)
43
43
  return;
44
- if (r.scheduled = !1, r.patch.size === 0) {
45
- r.usePush = !1;
44
+ const t = r.usePush, u = e.currentRoute.value.query, l = {};
45
+ for (const [s, c] of Object.entries(u))
46
+ c !== null && (l[s] = Array.isArray(c) ? c.filter((i) => i !== null) : c);
47
+ r.patch.forEach((s, c) => {
48
+ s === null ? delete l[c] : l[c] = s;
49
+ }), r.patch.clear(), r.usePush = !1, r.scheduled = !1;
50
+ const n = {};
51
+ for (const s of Object.keys(l).sort())
52
+ n[s] = l[s];
53
+ if (j(u, n))
46
54
  return;
47
- }
48
- const t = r.usePush;
49
- r.usePush = !1;
50
- const u = e.currentRoute.value.query, l = {};
51
- for (const [f, i] of Object.entries(u))
52
- i !== null && (l[f] = Array.isArray(i) ? i.filter((s) => s !== null) : i);
53
- const n = new Map(r.patch);
54
- n.forEach((f, i) => {
55
- f === null ? delete l[i] : l[i] = f;
55
+ (t ? e.push({ query: n }) : e.replace({ query: n })).catch(() => {
56
56
  });
57
- const c = {};
58
- for (const f of Object.keys(l).sort())
59
- c[f] = l[f];
60
- const a = () => {
61
- n.forEach((f, i) => {
62
- r.patch.get(i) === f && r.patch.delete(i);
63
- });
64
- };
65
- if (q(u, c)) {
66
- a();
67
- return;
68
- }
69
- (t ? e.push({ query: c }) : e.replace({ query: c })).then(a, a);
70
57
  }
71
- function w(e, r, t, u) {
72
- const l = j(r, t);
58
+ function q(e, r, t, u) {
59
+ const l = S(r, t);
73
60
  let n;
74
61
  if (l.pending) {
75
62
  if (l.value === null)
76
63
  return u.default;
77
- n = A(l.value);
64
+ n = h(l.value);
78
65
  } else
79
- n = A(e.query[t]);
66
+ n = h(e.query[t]);
80
67
  if (n === void 0)
81
68
  return u.default;
82
69
  try {
83
- const c = u.codec.deserialize(n);
84
- return c === void 0 ? u.default : c;
70
+ const a = u.codec.deserialize(n);
71
+ return a === void 0 ? u.default : a;
85
72
  } catch {
86
73
  return u.default;
87
74
  }
88
75
  }
89
- function z(e, r, t, u) {
76
+ function d(e, r, t, u) {
90
77
  const l = t.codec.serialize(u), n = t.codec.serialize(t.default);
91
- l === null || b(l, n) ? o(e, r, null, t.history) : o(e, r, l, t.history);
92
- }
93
- function k(e, r, t, u) {
94
- let l = !1, n, c;
95
- return v({
96
- get: () => {
97
- const a = w(e, r, t, u), d = u.codec.serialize(a);
98
- return l && b(d, c) ? n : (l = !0, n = a, c = d, a);
99
- },
100
- set: (a) => z(r, t, u, a)
101
- });
102
- }
103
- function $(e, r = {}) {
104
- const t = S(), u = P(), l = Object.keys(e), { prefix: n } = r, c = (s) => n ? `${n}-${s}` : s, a = {};
105
- for (const s of l)
106
- a[s] = k(t, u, c(s), e[s]);
107
- return { filters: m(a), patch: (s) => {
108
- for (const h of Object.keys(s))
109
- h in e && z(u, c(h), e[h], s[h]);
78
+ l === null || v(l, n) ? g(e, r, null, t.history) : g(e, r, l, t.history);
79
+ }
80
+ function W(e) {
81
+ const r = o(), t = N(), u = Object.keys(e), l = {};
82
+ for (const c of u)
83
+ l[c] = m({
84
+ get: () => q(r, t, c, e[c]),
85
+ set: (i) => d(t, c, e[c], i)
86
+ });
87
+ return { filters: A(l), patch: (c) => {
88
+ for (const i of Object.keys(c))
89
+ i in e && d(t, i, e[i], c[i]);
110
90
  }, reset: () => {
111
- for (const s of l)
112
- z(u, c(s), e[s], e[s].default);
91
+ for (const c of u)
92
+ d(t, c, e[c], e[c].default);
113
93
  } };
114
94
  }
115
- function y(e) {
95
+ function f(e) {
116
96
  return Array.isArray(e) ? e[0] ?? "" : e;
117
97
  }
118
- function F(e) {
98
+ function O(e) {
119
99
  return { codec: {
120
100
  serialize: (t) => t === null || t === "" ? null : t,
121
- deserialize: (t) => y(t)
101
+ deserialize: (t) => f(t)
122
102
  }, default: (e == null ? void 0 : e.default) ?? null, history: (e == null ? void 0 : e.history) ?? "replace" };
123
103
  }
124
- function M(e) {
104
+ function P(e) {
125
105
  return { codec: {
126
106
  serialize: (t) => t === null ? null : String(t),
127
107
  deserialize: (t) => {
128
- const u = y(t), l = Number(u);
108
+ const u = f(t), l = Number(u);
129
109
  return u === "" || Number.isNaN(l) ? void 0 : l;
130
110
  }
131
111
  }, default: (e == null ? void 0 : e.default) ?? null, history: (e == null ? void 0 : e.history) ?? "replace" };
132
112
  }
133
- function R(e) {
113
+ function w(e) {
134
114
  return { codec: {
135
115
  serialize: (t) => t === null ? null : t ? "true" : "false",
136
116
  deserialize: (t) => {
137
- const u = y(t);
117
+ const u = f(t);
138
118
  if (u === "true")
139
119
  return !0;
140
120
  if (u === "false")
@@ -142,30 +122,30 @@ function R(e) {
142
122
  }
143
123
  }, default: (e == null ? void 0 : e.default) ?? null, history: (e == null ? void 0 : e.history) ?? "replace" };
144
124
  }
145
- function E(e) {
125
+ function R(e) {
146
126
  return { codec: {
147
127
  serialize: (t) => t.length === 0 ? null : [...t],
148
128
  deserialize: (t) => Array.isArray(t) ? [...t] : [t]
149
129
  }, default: (e == null ? void 0 : e.default) ?? [], history: (e == null ? void 0 : e.history) ?? "replace" };
150
130
  }
151
- function K(e) {
131
+ function F(e) {
152
132
  return Object.entries(e).filter(([r]) => Number.isNaN(Number(r))).map(([, r]) => r);
153
133
  }
154
- function C(e, r) {
155
- const t = Array.isArray(e) ? [...e] : K(e), u = new Set(t);
134
+ function M(e, r) {
135
+ const t = Array.isArray(e) ? [...e] : F(e), u = new Set(t);
156
136
  return { codec: {
157
137
  serialize: (n) => n === null ? null : String(n),
158
138
  deserialize: (n) => {
159
- const c = y(n);
160
- if (u.has(c))
161
- return c;
162
- const a = Number(c);
163
- if (c !== "" && !Number.isNaN(a) && u.has(a))
139
+ const a = f(n);
140
+ if (u.has(a))
164
141
  return a;
142
+ const s = Number(a);
143
+ if (a !== "" && !Number.isNaN(s) && u.has(s))
144
+ return s;
165
145
  }
166
146
  }, default: (r == null ? void 0 : r.default) ?? null, history: (r == null ? void 0 : r.history) ?? "replace" };
167
147
  }
168
- function Q(e, r) {
148
+ function E(e, r) {
169
149
  return {
170
150
  codec: {
171
151
  serialize: (u) => u === null ? null : e.serialize(u),
@@ -176,18 +156,18 @@ function Q(e, r) {
176
156
  };
177
157
  }
178
158
  const B = {
179
- string: F,
180
- number: M,
181
- boolean: R,
182
- stringArray: E,
183
- enum: C,
184
- custom: Q
159
+ string: O,
160
+ number: P,
161
+ boolean: w,
162
+ stringArray: R,
163
+ enum: M,
164
+ custom: E
185
165
  };
186
- function D(e) {
166
+ function C(e) {
187
167
  return e;
188
168
  }
189
169
  export {
190
- D as defineCodec,
170
+ C as defineCodec,
191
171
  B as param,
192
- $ as useQueryFilters
172
+ W as useQueryFilters
193
173
  };
package/dist/types.d.ts CHANGED
@@ -15,9 +15,6 @@ export type FilterSchema = Record<string, Param<unknown>>;
15
15
  export type InferFilters<S extends FilterSchema> = {
16
16
  [K in keyof S]: S[K] extends Param<infer O> ? O : never;
17
17
  };
18
- export interface UseQueryFiltersOptions {
19
- prefix?: string;
20
- }
21
18
  export interface UseQueryFiltersReturn<S extends FilterSchema> {
22
19
  filters: InferFilters<S>;
23
20
  patch(partial: Partial<InferFilters<S>>): void;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,UAAU,CAAC,CAAC;IAE3B,SAAS,CAAC,KAAK,EAAE,CAAC,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAA;IAE7C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAA;CACnD;AAGD,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAC5B,OAAO,CAAC,EAAE,CAAC,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC7B,CAAA;AAGD,MAAM,WAAW,KAAK,CAAC,GAAG;IACxB,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAA;IACtB,OAAO,EAAE,GAAG,CAAA;IACZ,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAC5B;AAGD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;AAGzD,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,YAAY,IAAI;KAChD,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK;CACxD,CAAA;AAGD,MAAM,WAAW,sBAAsB;IAGrC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAGD,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,YAAY;IAC3D,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;IACxB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IAC9C,KAAK,IAAI,IAAI,CAAA;CACd"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,UAAU,CAAC,CAAC;IAE3B,SAAS,CAAC,KAAK,EAAE,CAAC,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAA;IAE7C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAA;CACnD;AAGD,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAC5B,OAAO,CAAC,EAAE,CAAC,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC7B,CAAA;AAGD,MAAM,WAAW,KAAK,CAAC,GAAG;IACxB,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAA;IACtB,OAAO,EAAE,GAAG,CAAA;IACZ,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;CAC5B;AAGD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;AAGzD,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,YAAY,IAAI;KAChD,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK;CACxD,CAAA;AAGD,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,YAAY;IAC3D,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAA;IACxB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IAC9C,KAAK,IAAI,IAAI,CAAA;CACd"}
@@ -1,3 +1,3 @@
1
- import { FilterSchema, UseQueryFiltersOptions, UseQueryFiltersReturn } from './types';
2
- export declare function useQueryFilters<S extends FilterSchema>(schema: S, options?: UseQueryFiltersOptions): UseQueryFiltersReturn<S>;
1
+ import { FilterSchema, UseQueryFiltersReturn } from './types';
2
+ export declare function useQueryFilters<S extends FilterSchema>(schema: S): UseQueryFiltersReturn<S>;
3
3
  //# sourceMappingURL=useQueryFilters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useQueryFilters.d.ts","sourceRoot":"","sources":["../src/useQueryFilters.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EAGZ,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,SAAS,CAAA;AAiChB,wBAAgB,eAAe,CAAC,CAAC,SAAS,YAAY,EACpD,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CAAC,CAAC,CAAC,CA6B1B"}
1
+ {"version":3,"file":"useQueryFilters.d.ts","sourceRoot":"","sources":["../src/useQueryFilters.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAgB,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAIhF,wBAAgB,eAAe,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,EAAE,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CA6B3F"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue-router-query-sync",
3
- "version": "2.0.0-alpha.5",
3
+ "version": "2.0.1-alpha.0",
4
4
  "description": "Reactive, typed view of Vue Router query params with codecs and defaults",
5
5
  "type": "module",
6
6
  "module": "./dist/index.mjs",