vue-router-query-sync 1.0.1 → 2.0.0-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 +73 -170
- package/dist/defineCodec.d.ts +3 -0
- package/dist/defineCodec.d.ts.map +1 -0
- package/dist/index.d.ts +5 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +164 -68
- package/dist/internal/equal.d.ts +2 -0
- package/dist/internal/equal.d.ts.map +1 -0
- package/dist/internal/field.d.ts +5 -0
- package/dist/internal/field.d.ts.map +1 -0
- package/dist/internal/normalize.d.ts +3 -0
- package/dist/internal/normalize.d.ts.map +1 -0
- package/dist/internal/queryQueue.d.ts +3 -0
- package/dist/internal/queryQueue.d.ts.map +1 -0
- package/dist/param.d.ts +39 -0
- package/dist/param.d.ts.map +1 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/useQueryFilters.d.ts +3 -0
- package/dist/useQueryFilters.d.ts.map +1 -0
- package/dist/useQueryParam.d.ts +4 -0
- package/dist/useQueryParam.d.ts.map +1 -0
- package/package.json +17 -13
- package/dist/composables/useQuerySync.d.ts +0 -17
- package/dist/composables/useQuerySync.d.ts.map +0 -1
- package/dist/index.js +0 -1
- package/dist/router.d.ts +0 -4
- package/dist/router.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -6
- package/dist/types/index.d.ts.map +0 -1
- package/dist/utils/replaceRouterQueue.d.ts +0 -2
- package/dist/utils/replaceRouterQueue.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,213 +1,116 @@
|
|
|
1
1
|
# vue-router-query-sync
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Draft docs for `2.0.0-alpha.0`. API only — no tests, migration guide or final docs yet.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
A reactive, typed view of the Vue Router query string. The URL (`route.query`) is the
|
|
6
|
+
single source of truth: reads parse `route.query`, writes navigate the router. The library
|
|
7
|
+
holds no state of its own and never throws because of URL contents.
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
- Vue 3 + Vue Router 4 (peer dependencies).
|
|
10
|
+
- Codecs + defaults per param; defaults never appear in the URL.
|
|
11
|
+
- Arrays use native repeated keys (`?a=1&a=2`).
|
|
12
|
+
- Batched navigation: several writes in one tick collapse into one `push`/`replace`.
|
|
13
|
+
- SSR-safe: router is read via `useRouter()`/`useRoute()`, no global/module state.
|
|
9
14
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## ✨ What is this?
|
|
13
|
-
|
|
14
|
-
`vue-router-query-sync` is a tiny, fully-typed Vue 3 utility that keeps your reactive state
|
|
15
|
-
(Pinia store fields or local refs) in sync with the current URL query string — both ways.
|
|
16
|
-
|
|
17
|
-
- Changes in your store update the URL query.
|
|
18
|
-
- Changes in the URL query update your store.
|
|
19
|
-
- Batched updates prevent excessive `router.replace` calls.
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## 💡 Why use this plugin?
|
|
24
|
-
|
|
25
|
-
- 🔄 Keeps your app state and URL perfectly in sync — no more manual watchers or `router.replace` logic.
|
|
26
|
-
- 🧠 Works with **Pinia**, **local refs**, or any reactive source.
|
|
27
|
-
- 🧩 Handles multiple query keys and isolated contexts safely.
|
|
28
|
-
- ⚙️ Fully typed with TypeScript and designed for Vue 3’s Composition API.
|
|
29
|
-
- 🚀 Tiny footprint — optimized for production.
|
|
30
|
-
|
|
31
|
-
## ✅ Requirements
|
|
32
|
-
|
|
33
|
-
- Vue 3
|
|
34
|
-
- Vue Router 4
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## 🚀 Installation
|
|
15
|
+
## Install
|
|
39
16
|
|
|
40
17
|
```bash
|
|
41
18
|
npm install vue-router-query-sync
|
|
42
|
-
# or
|
|
43
|
-
yarn add vue-router-query-sync
|
|
44
|
-
# or
|
|
45
|
-
pnpm add vue-router-query-sync
|
|
46
19
|
```
|
|
47
20
|
|
|
48
|
-
|
|
21
|
+
## `useQueryFilters(schema)`
|
|
49
22
|
|
|
50
|
-
|
|
23
|
+
Returns a reactive object; access fields without `.value`. The type is inferred from the schema.
|
|
51
24
|
|
|
52
25
|
```ts
|
|
53
|
-
|
|
54
|
-
import { createApp } from 'vue'
|
|
55
|
-
import { createRouter, createWebHistory } from 'vue-router'
|
|
56
|
-
import routerQuerySync from 'vue-router-query-sync'
|
|
57
|
-
import App from './App.vue'
|
|
58
|
-
|
|
59
|
-
const router = createRouter({
|
|
60
|
-
history: createWebHistory(),
|
|
61
|
-
routes: []
|
|
62
|
-
})
|
|
26
|
+
import { useQueryFilters, param } from 'vue-router-query-sync'
|
|
63
27
|
|
|
64
|
-
|
|
65
|
-
.use(router)
|
|
66
|
-
.use(routerQuerySync, { router })
|
|
67
|
-
.mount('#app')
|
|
68
|
-
```
|
|
28
|
+
enum SortType { Popular = 'popular', New = 'new' }
|
|
69
29
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
#### Sync a value with a query param named `tab`:
|
|
77
|
-
|
|
78
|
-
- Visiting `?tab=favorite` sets `tab.value = 'favorite'`.
|
|
79
|
-
- Changing `tab.value = 'all'` updates the URL to `?tab=all`.
|
|
80
|
-
|
|
81
|
-
```ts
|
|
82
|
-
import { useQuerySync } from 'vue-router-query-sync'
|
|
83
|
-
|
|
84
|
-
const tab = ref<'favorite' | 'all'>('all')
|
|
30
|
+
const filters = useQueryFilters({
|
|
31
|
+
sort: param.enum(SortType, { default: SortType.Popular, history: 'push' }),
|
|
32
|
+
brands: param.stringArray(), // default: []
|
|
33
|
+
page: param.number({ default: 1 }),
|
|
34
|
+
from: param.custom(dateCodec), // default: null
|
|
35
|
+
})
|
|
85
36
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
)
|
|
37
|
+
filters.sort = SortType.New // write -> router navigation
|
|
38
|
+
filters.brands // read -> parses route.query
|
|
39
|
+
filters.patch({ brands: ['lg'], page: 1 }) // several fields, ONE navigation
|
|
40
|
+
filters.reset() // all fields back to defaults (keys removed)
|
|
91
41
|
```
|
|
92
42
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
43
|
+
- **Read**: `route.query[key]` → `deserialize` → on `undefined`/throw → `default`.
|
|
44
|
+
- **Write**: `serialize` → if `null` or equal to `serialize(default)` → the key is removed.
|
|
45
|
+
- Query keys not described in the schema are left untouched.
|
|
46
|
+
- `patch` / `reset` are reserved names; using them as param keys throws at creation.
|
|
47
|
+
- Destructuring loses reactivity — use Vue's `toRefs(filters)`.
|
|
98
48
|
|
|
99
|
-
|
|
100
|
-
import { useQuerySync } from 'vue-router-query-sync'
|
|
101
|
-
|
|
102
|
-
const brands = [
|
|
103
|
-
{ value: 'lg', label: 'LG' },
|
|
104
|
-
{ value: 'samsung', label: 'Samsung' }
|
|
105
|
-
]
|
|
106
|
-
|
|
107
|
-
const selectedBrands = ref<string[]>([])
|
|
108
|
-
|
|
109
|
-
useQuerySync(
|
|
110
|
-
'brands',
|
|
111
|
-
() => {
|
|
112
|
-
return selectedBrands.value.length > 0 ? selectedBrands.value.join('%') : null
|
|
113
|
-
},
|
|
114
|
-
(val) => {
|
|
115
|
-
if (typeof val === 'string' && val) {
|
|
116
|
-
selectedBrands.value = val.includes('%') ? val.split('%') : [val]
|
|
117
|
-
} else {
|
|
118
|
-
selectedBrands.value = []
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
)
|
|
122
|
-
```
|
|
123
|
-
---
|
|
49
|
+
## `useQueryParam(key, param)`
|
|
124
50
|
|
|
125
|
-
|
|
51
|
+
Single-parameter wrapper over the same logic. Returns a `WritableComputedRef`.
|
|
126
52
|
|
|
127
53
|
```ts
|
|
128
|
-
|
|
129
|
-
key: string,
|
|
130
|
-
get: () => T | null,
|
|
131
|
-
set: (val: T) => void,
|
|
132
|
-
options?: QuerySyncOptions
|
|
133
|
-
): void
|
|
134
|
-
|
|
135
|
-
type QuerySyncOptions = {
|
|
136
|
-
deps?: Ref<unknown>[]
|
|
137
|
-
context?: string
|
|
138
|
-
}
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
- **key**: Query parameter name, e.g., `'tab'`.
|
|
142
|
-
- **get**: Function returning the current value from your store/ref. Return `null` to indicate “no value”.
|
|
143
|
-
- **set**: Function that writes the value to your store/ref.
|
|
144
|
-
- **options.deps**: Array of refs. If provided, the initial sync runs after any of these deps change (useful when state is populated asynchronously).
|
|
145
|
-
- **options.context**: If the same query key may be used multiple times on the same page, provide a unique context to avoid collisions. The actual query key becomes `${context}_${key}`.
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
## ❗ Important
|
|
150
|
-
|
|
151
|
-
If a page can have multiple components with the same query key, pass a unique `context` to avoid conflicts.
|
|
152
|
-
The real key used in the URL will be `${context}_${key}`. Otherwise, use unique keys per component.
|
|
54
|
+
import { useQueryParam, param } from 'vue-router-query-sync'
|
|
153
55
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
## 🏷️ Context Example
|
|
157
|
-
|
|
158
|
-
If two widgets on the same page need a `tab` param, use unique contexts:
|
|
159
|
-
|
|
160
|
-
```ts
|
|
161
|
-
useQuerySync('tab', () => usersStore.tab, (v) => (usersStore.tab = v), { context: 'users' })
|
|
162
|
-
useQuerySync('tab', () => ordersStore.tab, (v) => (ordersStore.tab = v), { context: 'orders' })
|
|
163
|
-
// URL keys will be: users_tab and orders_tab
|
|
56
|
+
const tab = useQueryParam('tab', param.enum(['all', 'favorite'] as const))
|
|
57
|
+
tab.value = 'favorite'
|
|
164
58
|
```
|
|
165
59
|
|
|
166
|
-
|
|
60
|
+
## `param`
|
|
167
61
|
|
|
168
|
-
|
|
62
|
+
All options are shared: `{ default?: T; history?: 'push' | 'replace' }` (`history` defaults to
|
|
63
|
+
`'replace'`). Passing `default` narrows the field type from `T | null` to `T`.
|
|
169
64
|
|
|
170
|
-
|
|
65
|
+
| Factory | Field type | Notes |
|
|
66
|
+
| --- | --- | --- |
|
|
67
|
+
| `param.string(options?)` | `string \| null` | |
|
|
68
|
+
| `param.number(options?)` | `number \| null` | |
|
|
69
|
+
| `param.boolean(options?)` | `boolean \| null` | URL is `'true'` / `'false'` |
|
|
70
|
+
| `param.stringArray(options?)` | `string[]` | repeated keys; default always `[]` |
|
|
71
|
+
| `param.enum(input, options?)` | member of `input` | see below |
|
|
72
|
+
| `param.custom(codec, options?)` | `T` from codec | default `null` if unset |
|
|
171
73
|
|
|
172
|
-
|
|
173
|
-
|
|
74
|
+
`param.enum` accepts either a readonly string array or a TS enum object (string or numeric).
|
|
75
|
+
Numeric enums have their reverse mapping filtered out and URL strings are coerced to numbers.
|
|
76
|
+
A value outside the set becomes `undefined` → `default` (behaviour mirrors `z.enum`).
|
|
174
77
|
|
|
175
|
-
|
|
78
|
+
## Codecs
|
|
176
79
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
---
|
|
80
|
+
```ts
|
|
81
|
+
import { defineCodec, type QueryCodec } from 'vue-router-query-sync'
|
|
182
82
|
|
|
183
|
-
|
|
83
|
+
interface QueryCodec<T> {
|
|
84
|
+
serialize(value: T): string | string[] | null // null = remove key
|
|
85
|
+
deserialize(raw: string | string[]): T | undefined // undefined = use default
|
|
86
|
+
}
|
|
184
87
|
|
|
185
|
-
|
|
186
|
-
|
|
88
|
+
const dateCodec = defineCodec<Date | null>({
|
|
89
|
+
serialize: (d) => (d ? d.toISOString().slice(0, 10) : null),
|
|
90
|
+
deserialize: (raw) => {
|
|
91
|
+
const t = Date.parse(Array.isArray(raw) ? raw[0] : raw)
|
|
92
|
+
return Number.isNaN(t) ? undefined : new Date(t)
|
|
93
|
+
},
|
|
94
|
+
})
|
|
187
95
|
```
|
|
188
96
|
|
|
189
|
-
|
|
190
|
-
- **useQuerySync**: The composable described above.
|
|
191
|
-
- **replaceRouterQueue**: Internal helper that batches query updates (exported in case you need manual batching).
|
|
192
|
-
|
|
193
|
-
Note: `setRouter/getRouter` are internal; prefer using the plugin install.
|
|
97
|
+
`defineCodec` is an identity helper for type inference. All built-in `param.*` types are codecs.
|
|
194
98
|
|
|
195
|
-
|
|
99
|
+
## Batching & history
|
|
196
100
|
|
|
197
|
-
|
|
101
|
+
Writes made in the same tick are merged into a single navigation via `queueMicrotask`.
|
|
102
|
+
If any changed param in the batch has `history: 'push'`, `router.push` is used; otherwise
|
|
103
|
+
`router.replace`. Query keys are sorted for a deterministic URL.
|
|
198
104
|
|
|
199
|
-
|
|
105
|
+
## Playground
|
|
200
106
|
|
|
201
|
-
```
|
|
202
|
-
|
|
107
|
+
```bash
|
|
108
|
+
npm run dev
|
|
203
109
|
```
|
|
204
110
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
---
|
|
111
|
+
A catalog page exercises every param type plus `reset`/`patch`, and a second route uses
|
|
112
|
+
`useQueryParam`. The current `route.query` is rendered on screen.
|
|
208
113
|
|
|
209
|
-
##
|
|
114
|
+
## License
|
|
210
115
|
|
|
211
116
|
MIT © Ivan Chikachev
|
|
212
|
-
|
|
213
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defineCodec.d.ts","sourceRoot":"","sources":["../src/defineCodec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAGzC,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAElE"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export * from './types/index';
|
|
7
|
-
declare const _default: {
|
|
8
|
-
install(app: App, options: {
|
|
9
|
-
router: Router;
|
|
10
|
-
}): void;
|
|
11
|
-
};
|
|
12
|
-
export default _default;
|
|
1
|
+
export { useQueryFilters } from './useQueryFilters';
|
|
2
|
+
export { useQueryParam } from './useQueryParam';
|
|
3
|
+
export { param } from './param';
|
|
4
|
+
export { defineCodec } from './defineCodec';
|
|
5
|
+
export type { QueryCodec, ParamOptions, Param, FilterSchema, InferFilters, QueryFilters } from './types';
|
|
13
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
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,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,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,YAAY,EACb,MAAM,SAAS,CAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,77 +1,173 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
function x(e) {
|
|
4
|
-
v = e;
|
|
5
|
-
}
|
|
6
|
-
function S() {
|
|
7
|
-
if (!v)
|
|
8
|
-
throw new Error(
|
|
9
|
-
"[vue-router-query-sync] Router instance not set. Call setRouter(router) before using composables."
|
|
10
|
-
);
|
|
11
|
-
return v;
|
|
12
|
-
}
|
|
13
|
-
let f = {};
|
|
14
|
-
const a = /* @__PURE__ */ new Set();
|
|
15
|
-
let Q = !1;
|
|
16
|
-
function l(e, t) {
|
|
17
|
-
const s = S();
|
|
18
|
-
t === null ? e in f || a.add(e) : (f[e] = t, a.delete(e)), Q || (Q = !0, queueMicrotask(() => {
|
|
19
|
-
const c = { ...s.currentRoute.value.query };
|
|
20
|
-
a.forEach((o) => {
|
|
21
|
-
delete c[o];
|
|
22
|
-
});
|
|
23
|
-
const R = {
|
|
24
|
-
...c,
|
|
25
|
-
...f
|
|
26
|
-
};
|
|
27
|
-
s.replace({ query: R }), f = {}, a.clear(), Q = !1;
|
|
28
|
-
}));
|
|
29
|
-
}
|
|
1
|
+
import { computed as h, reactive as b } from "vue";
|
|
2
|
+
import { useRoute as o, useRouter as A } from "vue-router";
|
|
30
3
|
function N(e) {
|
|
31
|
-
if (e
|
|
32
|
-
return e;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const n = String(u);
|
|
55
|
-
i !== n && l(r, u);
|
|
4
|
+
if (e != null)
|
|
5
|
+
return Array.isArray(e) ? e.filter((r) => r !== null) : e;
|
|
6
|
+
}
|
|
7
|
+
function S(e, r) {
|
|
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
|
+
}
|
|
10
|
+
const f = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
function q(e) {
|
|
12
|
+
let r = f.get(e);
|
|
13
|
+
return r || (r = { sets: /* @__PURE__ */ new Map(), deletes: /* @__PURE__ */ new Set(), usePush: !1, scheduled: !1 }, f.set(e, r)), r;
|
|
14
|
+
}
|
|
15
|
+
function y(e, r, t, u) {
|
|
16
|
+
const n = q(e);
|
|
17
|
+
t === null ? (n.sets.delete(r), n.deletes.add(r)) : (n.deletes.delete(r), n.sets.set(r, t)), u === "push" && (n.usePush = !0), n.scheduled || (n.scheduled = !0, queueMicrotask(() => j(e)));
|
|
18
|
+
}
|
|
19
|
+
function v(e, r) {
|
|
20
|
+
const t = Object.keys(e), u = Object.keys(r);
|
|
21
|
+
if (t.length !== u.length)
|
|
22
|
+
return !1;
|
|
23
|
+
const n = (s, c) => {
|
|
24
|
+
if (Array.isArray(s) || Array.isArray(c)) {
|
|
25
|
+
const l = Array.isArray(s) ? s : [s], a = Array.isArray(c) ? c : [c];
|
|
26
|
+
return l.length === a.length && l.every((z, m) => String(z) === String(a[m]));
|
|
56
27
|
}
|
|
28
|
+
return String(s) === String(c);
|
|
57
29
|
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
30
|
+
return t.every((s) => s in r && n(e[s], r[s]));
|
|
31
|
+
}
|
|
32
|
+
function j(e) {
|
|
33
|
+
const r = f.get(e);
|
|
34
|
+
if (!r)
|
|
35
|
+
return;
|
|
36
|
+
f.delete(e);
|
|
37
|
+
const t = e.currentRoute.value.query, u = {};
|
|
38
|
+
for (const [c, l] of Object.entries(t))
|
|
39
|
+
l !== null && (u[c] = Array.isArray(l) ? l.filter((a) => a !== null) : l);
|
|
40
|
+
r.deletes.forEach((c) => delete u[c]), r.sets.forEach((c, l) => {
|
|
41
|
+
u[l] = c;
|
|
42
|
+
});
|
|
43
|
+
const n = {};
|
|
44
|
+
for (const c of Object.keys(u).sort())
|
|
45
|
+
n[c] = u[c];
|
|
46
|
+
if (v(t, n))
|
|
47
|
+
return;
|
|
48
|
+
(r.usePush ? e.push({ query: n }) : e.replace({ query: n })).catch(() => {
|
|
65
49
|
});
|
|
66
50
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
51
|
+
function g(e, r, t) {
|
|
52
|
+
const u = N(e[r]);
|
|
53
|
+
if (u === void 0)
|
|
54
|
+
return t.default;
|
|
55
|
+
try {
|
|
56
|
+
const n = t.codec.deserialize(u);
|
|
57
|
+
return n === void 0 ? t.default : n;
|
|
58
|
+
} catch {
|
|
59
|
+
return t.default;
|
|
70
60
|
}
|
|
61
|
+
}
|
|
62
|
+
function i(e, r, t, u) {
|
|
63
|
+
const n = t.codec.serialize(u), s = t.codec.serialize(t.default);
|
|
64
|
+
n === null || S(n, s) ? y(e, r, null, t.history) : y(e, r, n, t.history);
|
|
65
|
+
}
|
|
66
|
+
const k = ["patch", "reset"];
|
|
67
|
+
function V(e) {
|
|
68
|
+
for (const l of k)
|
|
69
|
+
if (l in e)
|
|
70
|
+
throw new Error(
|
|
71
|
+
`[vue-router-query-sync] "${l}" is a reserved method name and cannot be used as a param key.`
|
|
72
|
+
);
|
|
73
|
+
const r = o(), t = A(), u = Object.keys(e), n = {};
|
|
74
|
+
for (const l of u)
|
|
75
|
+
n[l] = h({
|
|
76
|
+
get: () => g(r.query, l, e[l]),
|
|
77
|
+
set: (a) => i(t, l, e[l], a)
|
|
78
|
+
});
|
|
79
|
+
return b({ ...n, patch: (l) => {
|
|
80
|
+
for (const a of Object.keys(l))
|
|
81
|
+
a in e && i(t, a, e[a], l[a]);
|
|
82
|
+
}, reset: () => {
|
|
83
|
+
for (const l of u)
|
|
84
|
+
i(t, l, e[l], e[l].default);
|
|
85
|
+
} });
|
|
86
|
+
}
|
|
87
|
+
function C(e, r) {
|
|
88
|
+
const t = o(), u = A();
|
|
89
|
+
return h({
|
|
90
|
+
get: () => g(t.query, e, r),
|
|
91
|
+
set: (n) => i(u, e, r, n)
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function d(e) {
|
|
95
|
+
return Array.isArray(e) ? e[0] ?? "" : e;
|
|
96
|
+
}
|
|
97
|
+
function w(e) {
|
|
98
|
+
return { codec: {
|
|
99
|
+
serialize: (t) => t === null || t === "" ? null : t,
|
|
100
|
+
deserialize: (t) => d(t)
|
|
101
|
+
}, default: (e == null ? void 0 : e.default) ?? null, history: (e == null ? void 0 : e.history) ?? "replace" };
|
|
102
|
+
}
|
|
103
|
+
function E(e) {
|
|
104
|
+
return { codec: {
|
|
105
|
+
serialize: (t) => t === null ? null : String(t),
|
|
106
|
+
deserialize: (t) => {
|
|
107
|
+
const u = d(t), n = Number(u);
|
|
108
|
+
return u === "" || Number.isNaN(n) ? void 0 : n;
|
|
109
|
+
}
|
|
110
|
+
}, default: (e == null ? void 0 : e.default) ?? null, history: (e == null ? void 0 : e.history) ?? "replace" };
|
|
111
|
+
}
|
|
112
|
+
function O(e) {
|
|
113
|
+
return { codec: {
|
|
114
|
+
serialize: (t) => t === null ? null : t ? "true" : "false",
|
|
115
|
+
deserialize: (t) => {
|
|
116
|
+
const u = d(t);
|
|
117
|
+
if (u === "true")
|
|
118
|
+
return !0;
|
|
119
|
+
if (u === "false")
|
|
120
|
+
return !1;
|
|
121
|
+
}
|
|
122
|
+
}, default: (e == null ? void 0 : e.default) ?? null, history: (e == null ? void 0 : e.history) ?? "replace" };
|
|
123
|
+
}
|
|
124
|
+
function R(e) {
|
|
125
|
+
return { codec: {
|
|
126
|
+
serialize: (t) => t.length === 0 ? null : [...t],
|
|
127
|
+
deserialize: (t) => Array.isArray(t) ? [...t] : [t]
|
|
128
|
+
}, default: (e == null ? void 0 : e.default) ?? [], history: (e == null ? void 0 : e.history) ?? "replace" };
|
|
129
|
+
}
|
|
130
|
+
function P(e) {
|
|
131
|
+
return Object.entries(e).filter(([r]) => Number.isNaN(Number(r))).map(([, r]) => r);
|
|
132
|
+
}
|
|
133
|
+
function Q(e, r) {
|
|
134
|
+
const t = Array.isArray(e) ? [...e] : P(e), u = new Set(t);
|
|
135
|
+
return { codec: {
|
|
136
|
+
serialize: (s) => s === null ? null : String(s),
|
|
137
|
+
deserialize: (s) => {
|
|
138
|
+
const c = d(s);
|
|
139
|
+
if (u.has(c))
|
|
140
|
+
return c;
|
|
141
|
+
const l = Number(c);
|
|
142
|
+
if (c !== "" && !Number.isNaN(l) && u.has(l))
|
|
143
|
+
return l;
|
|
144
|
+
}
|
|
145
|
+
}, default: (r == null ? void 0 : r.default) ?? null, history: (r == null ? void 0 : r.history) ?? "replace" };
|
|
146
|
+
}
|
|
147
|
+
function F(e, r) {
|
|
148
|
+
return {
|
|
149
|
+
codec: {
|
|
150
|
+
serialize: (u) => u === null ? null : e.serialize(u),
|
|
151
|
+
deserialize: (u) => e.deserialize(u)
|
|
152
|
+
},
|
|
153
|
+
default: (r == null ? void 0 : r.default) ?? null,
|
|
154
|
+
history: (r == null ? void 0 : r.history) ?? "replace"
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const D = {
|
|
158
|
+
string: w,
|
|
159
|
+
number: E,
|
|
160
|
+
boolean: O,
|
|
161
|
+
stringArray: R,
|
|
162
|
+
enum: Q,
|
|
163
|
+
custom: F
|
|
71
164
|
};
|
|
165
|
+
function W(e) {
|
|
166
|
+
return e;
|
|
167
|
+
}
|
|
72
168
|
export {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
169
|
+
W as defineCodec,
|
|
170
|
+
D as param,
|
|
171
|
+
V as useQueryFilters,
|
|
172
|
+
C as useQueryParam
|
|
77
173
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"equal.d.ts","sourceRoot":"","sources":["../../src/internal/equal.ts"],"names":[],"mappings":"AACA,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,GAAG,OAAO,CAWjG"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { LocationQuery, Router } from 'vue-router';
|
|
2
|
+
import { Param } from '../types';
|
|
3
|
+
export declare function readField<Out>(query: LocationQuery, key: string, p: Param<Out>): Out;
|
|
4
|
+
export declare function writeField<Out>(router: Router, key: string, p: Param<Out>, value: Out): void;
|
|
5
|
+
//# sourceMappingURL=field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field.d.ts","sourceRoot":"","sources":["../../src/internal/field.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAMrC,wBAAgB,SAAS,CAAC,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,CAWpF;AAGD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI,CAQ5F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/internal/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAG/C,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAQxF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queryQueue.d.ts","sourceRoot":"","sources":["../../src/internal/queryQueue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmC,MAAM,EAAE,MAAM,YAAY,CAAA;AAsBzE,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EAC/B,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,IAAI,CAiBN"}
|
package/dist/param.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Param, ParamOptions, QueryCodec } from './types';
|
|
2
|
+
declare function string(): Param<string | null>;
|
|
3
|
+
declare function string(options: ParamOptions<string> & {
|
|
4
|
+
default: string;
|
|
5
|
+
}): Param<string>;
|
|
6
|
+
declare function string(options?: ParamOptions<string>): Param<string | null>;
|
|
7
|
+
declare function number(): Param<number | null>;
|
|
8
|
+
declare function number(options: ParamOptions<number> & {
|
|
9
|
+
default: number;
|
|
10
|
+
}): Param<number>;
|
|
11
|
+
declare function number(options?: ParamOptions<number>): Param<number | null>;
|
|
12
|
+
declare function boolean(): Param<boolean | null>;
|
|
13
|
+
declare function boolean(options: ParamOptions<boolean> & {
|
|
14
|
+
default: boolean;
|
|
15
|
+
}): Param<boolean>;
|
|
16
|
+
declare function boolean(options?: ParamOptions<boolean>): Param<boolean | null>;
|
|
17
|
+
declare function stringArray(options?: ParamOptions<string[]>): Param<string[]>;
|
|
18
|
+
declare function enumParam<const T extends readonly string[]>(values: T, options: ParamOptions<T[number]> & {
|
|
19
|
+
default: T[number];
|
|
20
|
+
}): Param<T[number]>;
|
|
21
|
+
declare function enumParam<const T extends readonly string[]>(values: T, options?: ParamOptions<T[number]>): Param<T[number] | null>;
|
|
22
|
+
declare function enumParam<T extends Record<string, string | number>>(enumObj: T, options: ParamOptions<T[keyof T]> & {
|
|
23
|
+
default: T[keyof T];
|
|
24
|
+
}): Param<T[keyof T]>;
|
|
25
|
+
declare function enumParam<T extends Record<string, string | number>>(enumObj: T, options?: ParamOptions<T[keyof T]>): Param<T[keyof T] | null>;
|
|
26
|
+
declare function custom<T>(codec: QueryCodec<T>, options: ParamOptions<T> & {
|
|
27
|
+
default: T;
|
|
28
|
+
}): Param<T>;
|
|
29
|
+
declare function custom<T>(codec: QueryCodec<T>, options?: ParamOptions<T>): Param<T | null>;
|
|
30
|
+
export declare const param: {
|
|
31
|
+
string: typeof string;
|
|
32
|
+
number: typeof number;
|
|
33
|
+
boolean: typeof boolean;
|
|
34
|
+
stringArray: typeof stringArray;
|
|
35
|
+
enum: typeof enumParam;
|
|
36
|
+
custom: typeof custom;
|
|
37
|
+
};
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=param.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"param.d.ts","sourceRoot":"","sources":["../src/param.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface QueryCodec<T> {
|
|
2
|
+
serialize(value: T): string | string[] | null;
|
|
3
|
+
deserialize(raw: string | string[]): T | undefined;
|
|
4
|
+
}
|
|
5
|
+
export type ParamOptions<T> = {
|
|
6
|
+
default?: T;
|
|
7
|
+
history?: 'push' | 'replace';
|
|
8
|
+
};
|
|
9
|
+
export interface Param<Out> {
|
|
10
|
+
codec: QueryCodec<Out>;
|
|
11
|
+
default: Out;
|
|
12
|
+
history: 'push' | 'replace';
|
|
13
|
+
}
|
|
14
|
+
export type FilterSchema = Record<string, Param<unknown>>;
|
|
15
|
+
export type InferFilters<S extends FilterSchema> = {
|
|
16
|
+
[K in keyof S]: S[K] extends Param<infer O> ? O : never;
|
|
17
|
+
};
|
|
18
|
+
export type QueryFilters<S extends FilterSchema> = InferFilters<S> & {
|
|
19
|
+
patch(partial: Partial<InferFilters<S>>): void;
|
|
20
|
+
reset(): void;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +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,MAAM,YAAY,CAAC,CAAC,SAAS,YAAY,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG;IACnE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IAC9C,KAAK,IAAI,IAAI,CAAA;CACd,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useQueryFilters.d.ts","sourceRoot":"","sources":["../src/useQueryFilters.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAMzD,wBAAgB,eAAe,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAoClF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useQueryParam.d.ts","sourceRoot":"","sources":["../src/useQueryParam.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,KAAK,CAAA;AAE9C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAIpC,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAOvF"}
|
package/package.json
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vue-router-query-sync",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
"module": "dist/index.mjs",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
3
|
+
"version": "2.0.0-alpha.0",
|
|
4
|
+
"description": "Reactive, typed view of Vue Router query params with codecs and defaults",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"
|
|
9
|
+
"dev": "vite --config vite.dev.config.ts",
|
|
10
|
+
"build": "vite build",
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"lint": "eslint ."
|
|
10
13
|
},
|
|
11
14
|
"exports": {
|
|
12
15
|
".": {
|
|
13
16
|
"types": "./dist/index.d.ts",
|
|
14
|
-
"import": "./dist/index.mjs"
|
|
15
|
-
"require": "./dist/index.js"
|
|
17
|
+
"import": "./dist/index.mjs"
|
|
16
18
|
}
|
|
17
19
|
},
|
|
18
20
|
"files": [
|
|
@@ -35,7 +37,7 @@
|
|
|
35
37
|
"license": "MIT",
|
|
36
38
|
"repository": {
|
|
37
39
|
"type": "git",
|
|
38
|
-
"url": "https://github.com/Ivan-Chikachev/vue-router-query-sync"
|
|
40
|
+
"url": "git+https://github.com/Ivan-Chikachev/vue-router-query-sync.git"
|
|
39
41
|
},
|
|
40
42
|
"peerDependencies": {
|
|
41
43
|
"vue": "^3.3.13",
|
|
@@ -43,16 +45,18 @@
|
|
|
43
45
|
},
|
|
44
46
|
"devDependencies": {
|
|
45
47
|
"vite-plugin-dts": "^4.5.4",
|
|
48
|
+
"@eslint/js": "^9.36.0",
|
|
46
49
|
"@types/node": "^20.1.0",
|
|
47
|
-
"@typescript-eslint/eslint-plugin": "^8.4.0",
|
|
48
50
|
"@vitejs/plugin-vue": "^5.2.3",
|
|
49
|
-
"
|
|
50
|
-
"eslint": "^8.57.0",
|
|
51
|
+
"eslint": "^9.36.0",
|
|
51
52
|
"eslint-config-prettier": "^9.1.0",
|
|
52
53
|
"eslint-plugin-import": "^2.30.0",
|
|
53
54
|
"eslint-plugin-prettier": "^5.2.1",
|
|
54
|
-
"eslint-plugin-vue": "^9.
|
|
55
|
+
"eslint-plugin-vue": "^9.33.0",
|
|
56
|
+
"globals": "^15.15.0",
|
|
57
|
+
"prettier": "^3.6.2",
|
|
55
58
|
"typescript": "^5.2.0",
|
|
59
|
+
"typescript-eslint": "^8.45.0",
|
|
56
60
|
"vite": "^6.3.6"
|
|
57
61
|
}
|
|
58
62
|
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { QuerySyncOptions } from '../types';
|
|
2
|
-
/**
|
|
3
|
-
* Synchronizes a store value with a query parameter in the URL.
|
|
4
|
-
*
|
|
5
|
-
* @param key - The name of the query parameter, e.g. "tab".
|
|
6
|
-
* @param get - A function that returns the current value from the store.
|
|
7
|
-
* @param set - A function that updates the value in the store.
|
|
8
|
-
* @param options.deps - A list of reactive dependencies that must change before synchronization occurs.
|
|
9
|
-
* @param options.context - A unique context identifier, required when multiple instances use the same query key on the same page.
|
|
10
|
-
*
|
|
11
|
-
* ⚠️ Important:
|
|
12
|
-
* If multiple components on the same page use the same query key,
|
|
13
|
-
* you must provide a unique `context` to prevent conflicts.
|
|
14
|
-
* Alternatively, always use unique query keys (for example, instead of "page", use "usersPage").
|
|
15
|
-
*/
|
|
16
|
-
export declare function useQuerySync<T extends string | number>(key: string, get: () => T | null, set: (val: T) => void, options?: QuerySyncOptions): void;
|
|
17
|
-
//# sourceMappingURL=useQuerySync.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useQuerySync.d.ts","sourceRoot":"","sources":["../../src/composables/useQuerySync.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAgB1C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EACpD,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,EACnB,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EACrB,OAAO,GAAE,gBAAqB,QAiE/B"}
|
package/dist/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(u,n){typeof exports=="object"&&typeof module<"u"?n(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],n):(u=typeof globalThis<"u"?globalThis:u||self,n(u.VueRouterQuerySync={},u.Vue))})(this,(function(u,n){"use strict";let p=null;function m(e){p=e}function Q(){if(!p)throw new Error("[vue-router-query-sync] Router instance not set. Call setRouter(router) before using composables.");return p}let c={};const f=new Set;let R=!1;function l(e,t){const a=Q();t===null?e in c||f.add(e):(c[e]=t,f.delete(e)),R||(R=!0,queueMicrotask(()=>{const d={...a.currentRoute.value.query};f.forEach(i=>{delete d[i]});const q={...d,...c};a.replace({query:q}),c={},f.clear(),R=!1}))}function g(e){if(e==="")return e;const t=Number(e);return isNaN(t)?e:t}function T(e,t,a,d={}){const i=Q().currentRoute,{deps:v=[],context:b}=d,r=b?`${b}_${e}`:e,S=(o,y=!1)=>{if(typeof o=="string"){const s=g(o);if(y||s!==t()){a(s);const h=t();h!==s&&h!==null&&l(r,h)}}else if(o===void 0){const s=t();s!==null&&l(r,s)}},M=o=>{const y=i.value.query[r];if(o===null)y!==void 0&&l(r,null);else{const s=String(o);y!==s&&l(r,o)}};n.onBeforeMount(()=>{v.length>0?n.watch(v,()=>S(i.value.query[r])):S(i.value.query[r])}),n.watch(t,M),n.watch(()=>i.value.query[r],o=>S(o)),n.onBeforeUnmount(()=>{l(r,null)})}const w={install(e,t){m(t.router)}};u.default=w,u.getRouter=Q,u.setRouter=m,u.useQuerySync=T,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|
package/dist/router.d.ts
DELETED
package/dist/router.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAIxC,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,QAEvC;AAED,wBAAgB,SAAS,IAAI,MAAM,CAOlC"}
|
package/dist/types/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replaceRouterQueue.d.ts","sourceRoot":"","sources":["../../src/utils/replaceRouterQueue.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,QAiCpF"}
|