zustand-querystring 0.0.15 → 0.0.17
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/dist/chunk-4CDMBGCR.mjs +183 -0
- package/dist/chunk-77OZJNG4.mjs +124 -0
- package/dist/chunk-STY4LBQG.mjs +64 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +385 -0
- package/dist/index.mjs +16 -0
- package/{lib → dist}/middleware.d.ts +6 -4
- package/dist/middleware.js +323 -0
- package/dist/middleware.mjs +7 -0
- package/dist/parser.d.ts +4 -0
- package/dist/parser.js +148 -0
- package/dist/parser.mjs +8 -0
- package/dist/utils.d.ts +7 -0
- package/dist/utils.js +204 -0
- package/dist/utils.mjs +7 -0
- package/package.json +22 -13
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/lib/middleware.js +0 -171
- package/lib/parser.d.ts +0 -2
- package/lib/parser.js +0 -134
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parse,
|
|
3
|
+
stringify
|
|
4
|
+
} from "./chunk-77OZJNG4.mjs";
|
|
5
|
+
|
|
6
|
+
// src/middleware.ts
|
|
7
|
+
import { mergeWith, isEqual, cloneDeep } from "lodash-es";
|
|
8
|
+
var compact = (newState, initialState) => {
|
|
9
|
+
const output = {};
|
|
10
|
+
Object.keys(newState).forEach((key) => {
|
|
11
|
+
if (newState[key] !== null && newState[key] !== void 0 && typeof newState[key] !== "function" && !isEqual(newState[key], initialState[key])) {
|
|
12
|
+
if (typeof newState[key] === "object" && !Array.isArray(newState[key])) {
|
|
13
|
+
const value = compact(newState[key], initialState[key]);
|
|
14
|
+
if (value && Object.keys(value).length > 0) {
|
|
15
|
+
output[key] = value;
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
output[key] = newState[key];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return output;
|
|
23
|
+
};
|
|
24
|
+
var translateSelectionToState = (selection, state) => {
|
|
25
|
+
if (typeof state !== "object" || !state) {
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
return Object.keys(selection).reduce((acc, key) => {
|
|
29
|
+
if (!(key in state)) {
|
|
30
|
+
return acc;
|
|
31
|
+
}
|
|
32
|
+
const value = selection[key];
|
|
33
|
+
if (typeof value === "boolean") {
|
|
34
|
+
if (value) {
|
|
35
|
+
acc[key] = state[key];
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
acc[key] = translateSelectionToState(value, state[key]);
|
|
39
|
+
}
|
|
40
|
+
return acc;
|
|
41
|
+
}, {});
|
|
42
|
+
};
|
|
43
|
+
var escapeStringRegexp = (string) => {
|
|
44
|
+
if (typeof string !== "string") {
|
|
45
|
+
throw new TypeError("Expected a string");
|
|
46
|
+
}
|
|
47
|
+
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
|
|
48
|
+
};
|
|
49
|
+
var queryStringImpl = (fn, options) => (set, get, api) => {
|
|
50
|
+
const defaultedOptions = {
|
|
51
|
+
key: "$",
|
|
52
|
+
...options
|
|
53
|
+
};
|
|
54
|
+
const escapedKey = escapeStringRegexp(defaultedOptions.key);
|
|
55
|
+
const stateMatcher = new RegExp(`${escapedKey}=(.*);;|${escapedKey}=(.*)$`);
|
|
56
|
+
const splitMatcher = new RegExp(`${escapedKey}=.*;;|${escapedKey}=.*$`);
|
|
57
|
+
const parseQueryString = (querystring2) => {
|
|
58
|
+
var _a;
|
|
59
|
+
const match = querystring2.match(stateMatcher);
|
|
60
|
+
if (match) {
|
|
61
|
+
return parse((_a = match[1]) != null ? _a : match[2]);
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
};
|
|
65
|
+
const url = defaultedOptions.url;
|
|
66
|
+
const getSelectedState = (state, pathname) => {
|
|
67
|
+
if (defaultedOptions.select) {
|
|
68
|
+
const selection = defaultedOptions.select(pathname);
|
|
69
|
+
const selectedState = translateSelectionToState(selection, state);
|
|
70
|
+
return selectedState;
|
|
71
|
+
}
|
|
72
|
+
return state != null ? state : {};
|
|
73
|
+
};
|
|
74
|
+
const initialize = (url2, initialState) => {
|
|
75
|
+
try {
|
|
76
|
+
const queryString = url2.search.substring(1);
|
|
77
|
+
const pathname = url2.pathname;
|
|
78
|
+
if (!queryString) {
|
|
79
|
+
return initialState;
|
|
80
|
+
}
|
|
81
|
+
const parsed = parseQueryString(queryString);
|
|
82
|
+
if (!parsed) {
|
|
83
|
+
return initialState;
|
|
84
|
+
}
|
|
85
|
+
const merged = mergeWith(
|
|
86
|
+
cloneDeep(initialState),
|
|
87
|
+
getSelectedState(parsed, pathname)
|
|
88
|
+
);
|
|
89
|
+
set(merged, true);
|
|
90
|
+
return merged;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error(error);
|
|
93
|
+
return initialState;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
if (typeof window !== "undefined") {
|
|
97
|
+
const initialState = cloneDeep(
|
|
98
|
+
fn(
|
|
99
|
+
(...args) => {
|
|
100
|
+
set(...args);
|
|
101
|
+
setQuery();
|
|
102
|
+
},
|
|
103
|
+
get,
|
|
104
|
+
api
|
|
105
|
+
)
|
|
106
|
+
);
|
|
107
|
+
const setQuery = () => {
|
|
108
|
+
const selectedState = getSelectedState(get(), location.pathname);
|
|
109
|
+
const currentQueryString = location.search;
|
|
110
|
+
const currentParsed = parseQueryString(currentQueryString);
|
|
111
|
+
const newMerged = {
|
|
112
|
+
...currentParsed,
|
|
113
|
+
...selectedState
|
|
114
|
+
};
|
|
115
|
+
const splitIgnored = currentQueryString.split(splitMatcher);
|
|
116
|
+
let ignored = "";
|
|
117
|
+
for (let str of splitIgnored) {
|
|
118
|
+
if (!str || str === "?" || str === "&") {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (str.startsWith("&") || str.startsWith("?")) {
|
|
122
|
+
str = str.substring(1);
|
|
123
|
+
}
|
|
124
|
+
if (str.endsWith("&")) {
|
|
125
|
+
str = str.substring(0, str.length - 1);
|
|
126
|
+
}
|
|
127
|
+
ignored += (ignored ? "&" : "?") + str;
|
|
128
|
+
}
|
|
129
|
+
const newCompacted = compact(newMerged, initialState);
|
|
130
|
+
if (Object.keys(newCompacted).length) {
|
|
131
|
+
const stringified = stringify(newCompacted);
|
|
132
|
+
const newQueryState = `${defaultedOptions.key}=${stringified};;`;
|
|
133
|
+
let newQueryString = "";
|
|
134
|
+
if (currentParsed) {
|
|
135
|
+
newQueryString = currentQueryString.replace(
|
|
136
|
+
splitMatcher,
|
|
137
|
+
newQueryState
|
|
138
|
+
);
|
|
139
|
+
} else if (ignored) {
|
|
140
|
+
newQueryString = ignored + "&" + newQueryState;
|
|
141
|
+
} else {
|
|
142
|
+
newQueryString = "?" + newQueryState;
|
|
143
|
+
}
|
|
144
|
+
history.replaceState(
|
|
145
|
+
history.state,
|
|
146
|
+
"",
|
|
147
|
+
location.pathname + newQueryString
|
|
148
|
+
);
|
|
149
|
+
} else {
|
|
150
|
+
history.replaceState(history.state, "", location.pathname + ignored);
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
if (!api.__ZUSTAND_QUERYSTRING_INIT__) {
|
|
154
|
+
api.__ZUSTAND_QUERYSTRING_INIT__ = true;
|
|
155
|
+
let previousPathname = "";
|
|
156
|
+
const cb = () => {
|
|
157
|
+
if (location.pathname !== previousPathname) {
|
|
158
|
+
previousPathname = location.pathname;
|
|
159
|
+
setQuery();
|
|
160
|
+
}
|
|
161
|
+
requestAnimationFrame(cb);
|
|
162
|
+
};
|
|
163
|
+
requestAnimationFrame(cb);
|
|
164
|
+
}
|
|
165
|
+
const originalSetState = api.setState;
|
|
166
|
+
api.setState = (...args) => {
|
|
167
|
+
originalSetState(...args);
|
|
168
|
+
setQuery();
|
|
169
|
+
};
|
|
170
|
+
return initialize(new URL(location.href), initialState);
|
|
171
|
+
} else if (url) {
|
|
172
|
+
return initialize(
|
|
173
|
+
new URL(decodeURIComponent(url), "http://localhost"),
|
|
174
|
+
fn(set, get, api)
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
return fn(set, get, api);
|
|
178
|
+
};
|
|
179
|
+
var querystring = queryStringImpl;
|
|
180
|
+
|
|
181
|
+
export {
|
|
182
|
+
querystring
|
|
183
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// src/parser.ts
|
|
2
|
+
var keyStringifyRegexp = /([=:@$/])/g;
|
|
3
|
+
var valueStringifyRegexp = /([&;/])/g;
|
|
4
|
+
var keyParseRegexp = /[=:@$]/;
|
|
5
|
+
var valueParseRegexp = /[&;]/;
|
|
6
|
+
function encodeString(str, regexp) {
|
|
7
|
+
return encodeURI(str.replace(regexp, "/$1"));
|
|
8
|
+
}
|
|
9
|
+
function trim(res) {
|
|
10
|
+
return typeof res === "string" ? res.replace(/;+$/g, "").replace(/^\$/, "") : res;
|
|
11
|
+
}
|
|
12
|
+
function stringify(input, recursive) {
|
|
13
|
+
if (!recursive) {
|
|
14
|
+
return trim(stringify(input, true));
|
|
15
|
+
}
|
|
16
|
+
if (typeof input === "function") {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (typeof input === "number" || input === true || input === false || input === null) {
|
|
20
|
+
return ":" + input;
|
|
21
|
+
}
|
|
22
|
+
const res = [];
|
|
23
|
+
if (Array.isArray(input)) {
|
|
24
|
+
for (const elem of input) {
|
|
25
|
+
typeof elem === "undefined" ? res.push(":null") : res.push(stringify(elem, true));
|
|
26
|
+
}
|
|
27
|
+
return "@" + res.join("&") + ";";
|
|
28
|
+
}
|
|
29
|
+
if (typeof input === "object") {
|
|
30
|
+
for (const [key, value] of Object.entries(input)) {
|
|
31
|
+
const stringifiedValue = stringify(value, true);
|
|
32
|
+
if (stringifiedValue) {
|
|
33
|
+
res.push(encodeString(key, keyStringifyRegexp) + stringifiedValue);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return "$" + res.join("&") + ";";
|
|
37
|
+
}
|
|
38
|
+
if (typeof input === "undefined") {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
return "=" + encodeString(input.toString(), valueStringifyRegexp);
|
|
42
|
+
}
|
|
43
|
+
function parse(str) {
|
|
44
|
+
if (!str.startsWith("$")) {
|
|
45
|
+
str = "$" + str;
|
|
46
|
+
}
|
|
47
|
+
let pos = 0;
|
|
48
|
+
str = decodeURI(str);
|
|
49
|
+
function readToken(regexp) {
|
|
50
|
+
let token = "";
|
|
51
|
+
for (; pos !== str.length; ++pos) {
|
|
52
|
+
if (str.charAt(pos) === "/") {
|
|
53
|
+
pos += 1;
|
|
54
|
+
if (pos === str.length) {
|
|
55
|
+
token += ";";
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
} else if (str.charAt(pos).match(regexp)) {
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
token += str.charAt(pos);
|
|
62
|
+
}
|
|
63
|
+
return token;
|
|
64
|
+
}
|
|
65
|
+
function parseToken() {
|
|
66
|
+
const type = str.charAt(pos++);
|
|
67
|
+
if (type === "=") {
|
|
68
|
+
return readToken(valueParseRegexp);
|
|
69
|
+
}
|
|
70
|
+
if (type === ":") {
|
|
71
|
+
const value = readToken(valueParseRegexp);
|
|
72
|
+
if (value === "true") {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
if (value === "false") {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const parsedValue = parseFloat(value);
|
|
79
|
+
return isNaN(parsedValue) ? null : parsedValue;
|
|
80
|
+
}
|
|
81
|
+
if (type === "@") {
|
|
82
|
+
const res = [];
|
|
83
|
+
loop: {
|
|
84
|
+
if (pos >= str.length || str.charAt(pos) === ";") {
|
|
85
|
+
break loop;
|
|
86
|
+
}
|
|
87
|
+
while (1) {
|
|
88
|
+
res.push(parseToken());
|
|
89
|
+
if (pos >= str.length || str.charAt(pos) === ";") {
|
|
90
|
+
break loop;
|
|
91
|
+
}
|
|
92
|
+
pos += 1;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
pos += 1;
|
|
96
|
+
return res;
|
|
97
|
+
}
|
|
98
|
+
if (type === "$") {
|
|
99
|
+
const res = {};
|
|
100
|
+
loop: {
|
|
101
|
+
if (pos >= str.length || str.charAt(pos) === ";") {
|
|
102
|
+
break loop;
|
|
103
|
+
}
|
|
104
|
+
while (1) {
|
|
105
|
+
var name = readToken(keyParseRegexp);
|
|
106
|
+
res[name] = parseToken();
|
|
107
|
+
if (pos >= str.length || str.charAt(pos) === ";") {
|
|
108
|
+
break loop;
|
|
109
|
+
}
|
|
110
|
+
pos += 1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
pos += 1;
|
|
114
|
+
return res;
|
|
115
|
+
}
|
|
116
|
+
throw new Error("Unexpected char " + type);
|
|
117
|
+
}
|
|
118
|
+
return parseToken();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export {
|
|
122
|
+
stringify,
|
|
123
|
+
parse
|
|
124
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parse,
|
|
3
|
+
stringify
|
|
4
|
+
} from "./chunk-77OZJNG4.mjs";
|
|
5
|
+
|
|
6
|
+
// src/utils.ts
|
|
7
|
+
var escapeStringRegexp = (string) => {
|
|
8
|
+
if (typeof string !== "string") {
|
|
9
|
+
throw new TypeError("Expected a string");
|
|
10
|
+
}
|
|
11
|
+
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
|
|
12
|
+
};
|
|
13
|
+
var parseQueryString = (key, querystring) => {
|
|
14
|
+
var _a;
|
|
15
|
+
const stateMatcher = new RegExp(`${key}=(.*);;|${key}=(.*)$`);
|
|
16
|
+
const match = querystring.match(stateMatcher);
|
|
17
|
+
if (match) {
|
|
18
|
+
return parse((_a = match[1]) != null ? _a : match[2]);
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
};
|
|
22
|
+
var createURL = ({
|
|
23
|
+
baseUrl,
|
|
24
|
+
key,
|
|
25
|
+
state
|
|
26
|
+
}) => {
|
|
27
|
+
const escapedKey = escapeStringRegexp(key);
|
|
28
|
+
const stringified = stringify(state);
|
|
29
|
+
const newQueryState = `${key}=${stringified};;`;
|
|
30
|
+
const match = baseUrl.indexOf("?");
|
|
31
|
+
const currentQueryString = match >= 0 ? baseUrl.substring(match) : "";
|
|
32
|
+
const currentParsed = parseQueryString(escapedKey, currentQueryString);
|
|
33
|
+
const splitMatcher = new RegExp(`${escapedKey}=.*;;|${escapedKey}=.*$`);
|
|
34
|
+
const splitIgnored = currentQueryString.split(splitMatcher);
|
|
35
|
+
let ignored = "";
|
|
36
|
+
for (let str of splitIgnored) {
|
|
37
|
+
if (!str || str === "?" || str === "&") {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (str.startsWith("&") || str.startsWith("?")) {
|
|
41
|
+
str = str.substring(1);
|
|
42
|
+
}
|
|
43
|
+
if (str.endsWith("&")) {
|
|
44
|
+
str = str.substring(0, str.length - 1);
|
|
45
|
+
}
|
|
46
|
+
ignored += (ignored ? "&" : "?") + str;
|
|
47
|
+
}
|
|
48
|
+
let newQueryString = "";
|
|
49
|
+
if (currentParsed) {
|
|
50
|
+
newQueryString = currentQueryString.replace(splitMatcher, newQueryState);
|
|
51
|
+
} else if (ignored) {
|
|
52
|
+
newQueryString = ignored + "&" + newQueryState;
|
|
53
|
+
} else {
|
|
54
|
+
newQueryString = "?" + newQueryState;
|
|
55
|
+
}
|
|
56
|
+
if (currentQueryString) {
|
|
57
|
+
return baseUrl.replace(currentQueryString, newQueryString);
|
|
58
|
+
}
|
|
59
|
+
return baseUrl + newQueryString;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export {
|
|
63
|
+
createURL
|
|
64
|
+
};
|
package/dist/index.d.ts
ADDED