zustand-querystring 0.0.9 → 0.0.11
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/lib/middleware.d.ts +1 -0
- package/lib/middleware.js +62 -35
- package/package.json +2 -2
package/lib/middleware.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ type DeepSelect<T> = T extends object ? {
|
|
|
5
5
|
export interface QueryStringOptions<T> {
|
|
6
6
|
url?: string;
|
|
7
7
|
select?: (pathname: string) => DeepSelect<T>;
|
|
8
|
+
key?: string;
|
|
8
9
|
}
|
|
9
10
|
type QueryString = <T, Mps extends [StoreMutatorIdentifier, unknown][] = [], Mcs extends [StoreMutatorIdentifier, unknown][] = []>(initializer: StateCreator<T, Mps, Mcs>, options?: QueryStringOptions<T>) => StateCreator<T, Mps, Mcs>;
|
|
10
11
|
export declare const querystring: QueryString;
|
package/lib/middleware.js
CHANGED
|
@@ -36,10 +36,30 @@ const translateSelectionToState = (selection, state) => Object.keys(selection).r
|
|
|
36
36
|
}
|
|
37
37
|
return acc;
|
|
38
38
|
}, {});
|
|
39
|
+
const escapeStringRegexp = string => {
|
|
40
|
+
if (typeof string !== 'string') {
|
|
41
|
+
throw new TypeError('Expected a string');
|
|
42
|
+
}
|
|
43
|
+
return string.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
|
|
44
|
+
};
|
|
39
45
|
const queryStringImpl = (fn, options) => (set, get, api) => {
|
|
40
46
|
const defaultedOptions = {
|
|
47
|
+
key: '$',
|
|
41
48
|
...options,
|
|
42
49
|
};
|
|
50
|
+
const stateMatcher = new RegExp(`${escapeStringRegexp(defaultedOptions.key)}=(.*);;`);
|
|
51
|
+
const matcher = new RegExp(`[&\?]?${escapeStringRegexp(defaultedOptions.key)}=(.*);;&?`);
|
|
52
|
+
const parseQueryString = querystring => {
|
|
53
|
+
const match = querystring.match(stateMatcher);
|
|
54
|
+
if (match) {
|
|
55
|
+
let m = match[1];
|
|
56
|
+
if (!m.startsWith('$')) {
|
|
57
|
+
m = '$' + m;
|
|
58
|
+
}
|
|
59
|
+
return parse(m);
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
};
|
|
43
63
|
const url = defaultedOptions.url;
|
|
44
64
|
const initialState = get() ?? fn(set, get, api);
|
|
45
65
|
const getSelectedState = (state, pathname) => {
|
|
@@ -54,19 +74,15 @@ const queryStringImpl = (fn, options) => (set, get, api) => {
|
|
|
54
74
|
const initialize = (url, _set = set) => {
|
|
55
75
|
const fallback = () => fn(_set, get, api);
|
|
56
76
|
try {
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
const pathname = splitUrl[0];
|
|
77
|
+
const queryString = url.search.substring(1);
|
|
78
|
+
const pathname = url.pathname;
|
|
60
79
|
if (!queryString) {
|
|
61
80
|
return fallback();
|
|
62
81
|
}
|
|
63
|
-
|
|
82
|
+
const parsed = parseQueryString(queryString);
|
|
83
|
+
if (!parsed) {
|
|
64
84
|
return fallback();
|
|
65
85
|
}
|
|
66
|
-
if (!queryString.startsWith('$')) {
|
|
67
|
-
queryString = '$' + queryString;
|
|
68
|
-
}
|
|
69
|
-
const parsed = parse(queryString);
|
|
70
86
|
const currentValue = get() ?? fn(_set, get, api);
|
|
71
87
|
const merged = mergeWith(currentValue, getSelectedState(parsed, pathname));
|
|
72
88
|
set(merged, true);
|
|
@@ -79,49 +95,60 @@ const queryStringImpl = (fn, options) => (set, get, api) => {
|
|
|
79
95
|
};
|
|
80
96
|
if (typeof window !== 'undefined') {
|
|
81
97
|
const setQuery = () => {
|
|
82
|
-
const selectedState = getSelectedState(get(),
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const currentParsed = parse(currentQueryString);
|
|
91
|
-
const newMerged = mergeWith(currentParsed, selectedState, (objValue, srcValue) => {
|
|
92
|
-
if (Array.isArray(objValue)) {
|
|
93
|
-
return srcValue;
|
|
94
|
-
}
|
|
95
|
-
});
|
|
98
|
+
const selectedState = getSelectedState(get(), location.pathname);
|
|
99
|
+
const currentQueryString = location.search.slice(1);
|
|
100
|
+
const currentParsed = parseQueryString(currentQueryString);
|
|
101
|
+
const newMerged = {
|
|
102
|
+
...currentParsed,
|
|
103
|
+
...selectedState,
|
|
104
|
+
};
|
|
105
|
+
const ignored = currentQueryString.replace(matcher, '');
|
|
96
106
|
const newCompacted = compact(newMerged, initialState);
|
|
97
107
|
if (Object.keys(newCompacted).length) {
|
|
98
108
|
const stringified = stringify(newCompacted).substring(1);
|
|
99
|
-
|
|
109
|
+
const newQueryState = `${defaultedOptions.key}=${stringified};;`;
|
|
110
|
+
let newQueryString = '';
|
|
111
|
+
if (currentParsed) {
|
|
112
|
+
newQueryString = currentQueryString.replace(stateMatcher, newQueryState);
|
|
113
|
+
}
|
|
114
|
+
else if (ignored) {
|
|
115
|
+
newQueryString = ignored + '&' + newQueryState;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
newQueryString = newQueryState;
|
|
119
|
+
}
|
|
120
|
+
history.replaceState(history.state, '', location.pathname + (newQueryString ? '?' + newQueryString : ''));
|
|
100
121
|
}
|
|
101
122
|
else {
|
|
102
|
-
|
|
123
|
+
history.replaceState(history.state, '', location.pathname + (ignored ? '?' + ignored : ''));
|
|
103
124
|
}
|
|
104
125
|
};
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
126
|
+
// @ts-ignore
|
|
127
|
+
if (!api.__ZUSTAND_QUERYSTRING_INIT__) {
|
|
128
|
+
// @ts-ignore
|
|
129
|
+
api.__ZUSTAND_QUERYSTRING_INIT__ = true;
|
|
130
|
+
let previousPathname = '';
|
|
131
|
+
const cb = () => {
|
|
132
|
+
if (location.pathname !== previousPathname) {
|
|
133
|
+
previousPathname = location.pathname;
|
|
134
|
+
setQuery();
|
|
135
|
+
}
|
|
136
|
+
requestAnimationFrame(cb);
|
|
137
|
+
};
|
|
138
|
+
requestAnimationFrame(cb);
|
|
139
|
+
}
|
|
113
140
|
const originalSetState = api.setState;
|
|
114
141
|
api.setState = (...args) => {
|
|
115
142
|
originalSetState(...args);
|
|
116
143
|
setQuery();
|
|
117
144
|
};
|
|
118
|
-
return initialize(
|
|
145
|
+
return initialize(new URL(location.href), (...args) => {
|
|
119
146
|
set(...args);
|
|
120
147
|
setQuery();
|
|
121
148
|
});
|
|
122
149
|
}
|
|
123
|
-
if (url) {
|
|
124
|
-
return initialize(url);
|
|
150
|
+
else if (url) {
|
|
151
|
+
return initialize(new URL(decodeURIComponent(url), 'http://localhost'));
|
|
125
152
|
}
|
|
126
153
|
return fn(set, get, api);
|
|
127
154
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zustand-querystring",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@types/lodash-es": "^4.17.6",
|
|
36
36
|
"rimraf": "^3.0.2",
|
|
37
37
|
"typescript": "^4.9.3",
|
|
38
|
-
"zustand": "^4.
|
|
38
|
+
"zustand": "^4.3.2"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "rimraf lib && tsc -b"
|