zustand-querystring 0.4.1 → 0.6.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 +280 -60
- package/dist/chunk-TQQUWVLF.mjs +367 -0
- package/dist/format/json.d.mts +6 -0
- package/dist/format/json.d.ts +6 -0
- package/dist/format/json.js +59 -0
- package/dist/format/json.mjs +35 -0
- package/dist/format/marked.d.mts +67 -0
- package/dist/format/marked.d.ts +67 -0
- package/dist/format/marked.js +393 -0
- package/dist/format/marked.mjs +14 -0
- package/dist/format/plain.d.mts +55 -0
- package/dist/format/plain.d.ts +55 -0
- package/dist/format/plain.js +459 -0
- package/dist/format/plain.mjs +434 -0
- package/dist/index.d.mts +33 -16
- package/dist/index.d.ts +33 -16
- package/dist/index.js +450 -105
- package/dist/index.mjs +97 -106
- package/package.json +34 -8
- package/dist/format/readable.d.mts +0 -14
- package/dist/format/readable.d.ts +0 -14
- package/dist/format/readable.js +0 -238
- package/dist/format/readable.mjs +0 -212
package/dist/index.js
CHANGED
|
@@ -19,23 +19,368 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
// src/index.ts
|
|
20
20
|
var src_exports = {};
|
|
21
21
|
__export(src_exports, {
|
|
22
|
-
|
|
23
|
-
parse: () => parse,
|
|
24
|
-
querystring: () => querystring,
|
|
25
|
-
stringify: () => stringify
|
|
22
|
+
querystring: () => querystring
|
|
26
23
|
});
|
|
27
24
|
module.exports = __toCommonJS(src_exports);
|
|
28
25
|
|
|
29
26
|
// src/middleware.ts
|
|
30
27
|
var import_lodash_es = require("lodash-es");
|
|
31
28
|
|
|
32
|
-
// src/
|
|
33
|
-
function
|
|
34
|
-
|
|
29
|
+
// src/format/marked.ts
|
|
30
|
+
function resolveOptions(opts = {}) {
|
|
31
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
32
|
+
return {
|
|
33
|
+
typeObject: (_a = opts.typeObject) != null ? _a : ".",
|
|
34
|
+
typeArray: (_b = opts.typeArray) != null ? _b : "@",
|
|
35
|
+
typeString: (_c = opts.typeString) != null ? _c : "=",
|
|
36
|
+
typePrimitive: (_d = opts.typePrimitive) != null ? _d : ":",
|
|
37
|
+
separator: (_e = opts.separator) != null ? _e : ",",
|
|
38
|
+
terminator: (_f = opts.terminator) != null ? _f : "~",
|
|
39
|
+
escape: (_g = opts.escapeChar) != null ? _g : "_",
|
|
40
|
+
datePrefix: (_h = opts.datePrefix) != null ? _h : "D"
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function validateOptions(opts) {
|
|
44
|
+
const tokens = [
|
|
45
|
+
opts.typeObject,
|
|
46
|
+
opts.typeArray,
|
|
47
|
+
opts.typeString,
|
|
48
|
+
opts.typePrimitive,
|
|
49
|
+
opts.separator,
|
|
50
|
+
opts.terminator,
|
|
51
|
+
opts.escape
|
|
52
|
+
];
|
|
53
|
+
for (const token of tokens) {
|
|
54
|
+
if (token.length === 0) {
|
|
55
|
+
throw new Error("All tokens must be non-empty strings");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (opts.datePrefix.length === 0) {
|
|
59
|
+
throw new Error("datePrefix must be non-empty");
|
|
60
|
+
}
|
|
61
|
+
const seen = /* @__PURE__ */ new Set();
|
|
62
|
+
for (const token of tokens) {
|
|
63
|
+
if (seen.has(token)) {
|
|
64
|
+
throw new Error(`Duplicate token detected: '${token}'`);
|
|
65
|
+
}
|
|
66
|
+
seen.add(token);
|
|
67
|
+
}
|
|
68
|
+
if (seen.has(opts.datePrefix)) {
|
|
69
|
+
throw new Error(`datePrefix '${opts.datePrefix}' conflicts with another token`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function escapeRegex(str) {
|
|
73
|
+
return str.replace(/[.$^*+?()[\]{}|\\-]/g, "\\$&");
|
|
74
|
+
}
|
|
75
|
+
function buildKeyStopPattern(opts) {
|
|
76
|
+
return new RegExp(
|
|
77
|
+
`[${escapeRegex(opts.typeString)}${escapeRegex(opts.typePrimitive)}${escapeRegex(opts.typeArray)}${escapeRegex(opts.typeObject)}${escapeRegex(opts.separator)}]`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
function buildValueStopPattern(opts) {
|
|
81
|
+
return new RegExp(`[${escapeRegex(opts.separator)}${escapeRegex(opts.terminator)}]`);
|
|
82
|
+
}
|
|
83
|
+
function buildKeyEscapePattern(opts) {
|
|
84
|
+
return new RegExp(
|
|
85
|
+
`([${escapeRegex(opts.typeString)}${escapeRegex(opts.typePrimitive)}${escapeRegex(opts.typeArray)}${escapeRegex(opts.typeObject)}${escapeRegex(opts.separator)}])`,
|
|
86
|
+
"g"
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
function buildValueEscapePattern(opts) {
|
|
90
|
+
return new RegExp(`([${escapeRegex(opts.separator)}${escapeRegex(opts.terminator)}])`, "g");
|
|
91
|
+
}
|
|
92
|
+
function buildDatePattern(opts) {
|
|
93
|
+
return new RegExp(`^${escapeRegex(opts.datePrefix)}-?\\d+$`);
|
|
94
|
+
}
|
|
95
|
+
function buildDateStartPattern(opts) {
|
|
96
|
+
return new RegExp(`^${escapeRegex(opts.datePrefix)}-?\\d`);
|
|
35
97
|
}
|
|
36
|
-
function
|
|
37
|
-
|
|
98
|
+
function encodePreservingMarkers(str, opts) {
|
|
99
|
+
const markers = /* @__PURE__ */ new Set([
|
|
100
|
+
opts.typeObject,
|
|
101
|
+
opts.typeArray,
|
|
102
|
+
opts.typeString,
|
|
103
|
+
opts.typePrimitive,
|
|
104
|
+
opts.separator,
|
|
105
|
+
opts.terminator,
|
|
106
|
+
opts.escape
|
|
107
|
+
]);
|
|
108
|
+
let result = "";
|
|
109
|
+
for (const char of str) {
|
|
110
|
+
if (markers.has(char)) {
|
|
111
|
+
result += char;
|
|
112
|
+
} else {
|
|
113
|
+
result += encodeURIComponent(char);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
function escapeStr(str, pattern, escape, opts) {
|
|
119
|
+
return encodePreservingMarkers(str.replace(pattern, `${escape}$1`), opts);
|
|
120
|
+
}
|
|
121
|
+
function cleanResult(str, standalone, opts) {
|
|
122
|
+
while (str.endsWith(opts.terminator)) {
|
|
123
|
+
str = str.slice(0, -opts.terminator.length);
|
|
124
|
+
}
|
|
125
|
+
const datePattern = new RegExp(`^${escapeRegex(opts.typeString)}${escapeRegex(opts.datePrefix)}-?\\d+$`);
|
|
126
|
+
if (standalone && datePattern.test(str)) {
|
|
127
|
+
return str.slice(opts.typeString.length);
|
|
128
|
+
}
|
|
129
|
+
if (!standalone && str.startsWith(opts.typeObject)) {
|
|
130
|
+
return str.slice(opts.typeObject.length);
|
|
131
|
+
}
|
|
132
|
+
return str;
|
|
133
|
+
}
|
|
134
|
+
function createSerializer(opts) {
|
|
135
|
+
const keyEscape = buildKeyEscapePattern(opts);
|
|
136
|
+
const valueEscape = buildValueEscapePattern(opts);
|
|
137
|
+
const dateStartPattern = buildDateStartPattern(opts);
|
|
138
|
+
function serialize(value, standalone, inArray = false) {
|
|
139
|
+
if (value === null) return `${opts.typePrimitive}null`;
|
|
140
|
+
if (value === void 0) return `${opts.typePrimitive}undefined`;
|
|
141
|
+
if (typeof value === "function") return "";
|
|
142
|
+
if (typeof value === "number") {
|
|
143
|
+
return `${opts.typePrimitive}${value}`;
|
|
144
|
+
}
|
|
145
|
+
if (typeof value === "boolean") {
|
|
146
|
+
return `${opts.typePrimitive}${value}`;
|
|
147
|
+
}
|
|
148
|
+
if (value instanceof Date) {
|
|
149
|
+
return `${opts.typeString}${opts.datePrefix}${value.getTime()}`;
|
|
150
|
+
}
|
|
151
|
+
if (Array.isArray(value)) {
|
|
152
|
+
const items = value.map((v) => serialize(v, standalone, true));
|
|
153
|
+
return `${opts.typeArray}${items.join(opts.separator)}${opts.terminator}`;
|
|
154
|
+
}
|
|
155
|
+
if (typeof value === "object") {
|
|
156
|
+
const entries = [];
|
|
157
|
+
for (const [k, v] of Object.entries(value)) {
|
|
158
|
+
const val = serialize(v, false, false);
|
|
159
|
+
if (val || v === void 0) {
|
|
160
|
+
entries.push(`${escapeStr(k, keyEscape, opts.escape, opts)}${val}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return `${opts.typeObject}${entries.join(opts.separator)}${opts.terminator}`;
|
|
164
|
+
}
|
|
165
|
+
const strVal = String(value);
|
|
166
|
+
let escaped = escapeStr(strVal, valueEscape, opts.escape, opts);
|
|
167
|
+
if (dateStartPattern.test(strVal)) {
|
|
168
|
+
escaped = opts.escape + escaped;
|
|
169
|
+
} else if ((standalone || inArray) && (strVal.startsWith(opts.typeObject) || strVal.startsWith(opts.typeArray) || strVal.startsWith(opts.typePrimitive) || strVal.startsWith(opts.typeString))) {
|
|
170
|
+
escaped = opts.escape + escaped;
|
|
171
|
+
}
|
|
172
|
+
return standalone || inArray ? escaped : `${opts.typeString}${escaped}`;
|
|
173
|
+
}
|
|
174
|
+
return serialize;
|
|
38
175
|
}
|
|
176
|
+
function createParser(opts) {
|
|
177
|
+
const keyStop = buildKeyStopPattern(opts);
|
|
178
|
+
const valueStop = buildValueStopPattern(opts);
|
|
179
|
+
const datePattern = buildDatePattern(opts);
|
|
180
|
+
const tokens = {
|
|
181
|
+
typePrimitive: opts.typePrimitive,
|
|
182
|
+
typeArray: opts.typeArray,
|
|
183
|
+
typeObject: opts.typeObject,
|
|
184
|
+
typeString: opts.typeString,
|
|
185
|
+
separator: opts.separator,
|
|
186
|
+
terminator: opts.terminator,
|
|
187
|
+
escape: opts.escape,
|
|
188
|
+
datePrefix: opts.datePrefix
|
|
189
|
+
};
|
|
190
|
+
return function parseSource(source) {
|
|
191
|
+
let pos = 0;
|
|
192
|
+
function peek(len = 1) {
|
|
193
|
+
return source.slice(pos, pos + len);
|
|
194
|
+
}
|
|
195
|
+
function startsWith(token) {
|
|
196
|
+
return source.slice(pos, pos + token.length) === token;
|
|
197
|
+
}
|
|
198
|
+
function advance(len = 1) {
|
|
199
|
+
pos += len;
|
|
200
|
+
}
|
|
201
|
+
function readUntil(stopPattern, checkEscape = false) {
|
|
202
|
+
let result = "";
|
|
203
|
+
let wasEscaped = false;
|
|
204
|
+
while (pos < source.length) {
|
|
205
|
+
if (startsWith(tokens.escape)) {
|
|
206
|
+
const nextPos = pos + tokens.escape.length;
|
|
207
|
+
const nextChar = source.slice(nextPos, nextPos + 1);
|
|
208
|
+
const isEscapeSequence = stopPattern.test(nextChar);
|
|
209
|
+
const isDateEscape = checkEscape && source.slice(nextPos, nextPos + tokens.datePrefix.length) === tokens.datePrefix;
|
|
210
|
+
if (isEscapeSequence || isDateEscape) {
|
|
211
|
+
if (isDateEscape) {
|
|
212
|
+
wasEscaped = true;
|
|
213
|
+
}
|
|
214
|
+
advance(tokens.escape.length);
|
|
215
|
+
if (pos < source.length) {
|
|
216
|
+
result += peek();
|
|
217
|
+
advance();
|
|
218
|
+
}
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const ch = peek();
|
|
223
|
+
if (stopPattern.test(ch)) break;
|
|
224
|
+
result += ch;
|
|
225
|
+
advance();
|
|
226
|
+
}
|
|
227
|
+
return { value: result, wasEscaped };
|
|
228
|
+
}
|
|
229
|
+
function parseString() {
|
|
230
|
+
const { value, wasEscaped } = readUntil(valueStop, true);
|
|
231
|
+
if (!wasEscaped && datePattern.test(value)) {
|
|
232
|
+
const timestamp = parseInt(value.slice(tokens.datePrefix.length), 10);
|
|
233
|
+
if (!isNaN(timestamp)) {
|
|
234
|
+
return new Date(timestamp);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return value;
|
|
238
|
+
}
|
|
239
|
+
function parsePrimitive() {
|
|
240
|
+
const { value } = readUntil(valueStop, false);
|
|
241
|
+
if (value === "null") return null;
|
|
242
|
+
if (value === "undefined") return void 0;
|
|
243
|
+
if (value === "true") return true;
|
|
244
|
+
if (value === "false") return false;
|
|
245
|
+
return parseFloat(value);
|
|
246
|
+
}
|
|
247
|
+
function parseArray() {
|
|
248
|
+
const result = [];
|
|
249
|
+
let lastWasSeparator = false;
|
|
250
|
+
while (pos < source.length && !startsWith(tokens.terminator)) {
|
|
251
|
+
if (startsWith(tokens.separator)) {
|
|
252
|
+
result.push("");
|
|
253
|
+
advance(tokens.separator.length);
|
|
254
|
+
lastWasSeparator = true;
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
lastWasSeparator = false;
|
|
258
|
+
if (startsWith(tokens.typePrimitive) || startsWith(tokens.typeArray) || startsWith(tokens.typeObject) || startsWith(tokens.typeString)) {
|
|
259
|
+
result.push(parseValue());
|
|
260
|
+
} else {
|
|
261
|
+
result.push(parseString());
|
|
262
|
+
}
|
|
263
|
+
if (pos < source.length && startsWith(tokens.separator)) {
|
|
264
|
+
advance(tokens.separator.length);
|
|
265
|
+
lastWasSeparator = true;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (lastWasSeparator && (startsWith(tokens.terminator) || pos >= source.length)) {
|
|
269
|
+
result.push("");
|
|
270
|
+
}
|
|
271
|
+
if (startsWith(tokens.terminator)) advance(tokens.terminator.length);
|
|
272
|
+
return result;
|
|
273
|
+
}
|
|
274
|
+
function parseObject() {
|
|
275
|
+
const result = {};
|
|
276
|
+
while (pos < source.length && !startsWith(tokens.terminator)) {
|
|
277
|
+
const { value: key } = readUntil(keyStop, false);
|
|
278
|
+
result[key] = parseValue();
|
|
279
|
+
if (pos < source.length && !startsWith(tokens.terminator) && startsWith(tokens.separator)) {
|
|
280
|
+
advance(tokens.separator.length);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (startsWith(tokens.terminator)) advance(tokens.terminator.length);
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
286
|
+
function parseValue() {
|
|
287
|
+
if (startsWith(tokens.typePrimitive)) {
|
|
288
|
+
advance(tokens.typePrimitive.length);
|
|
289
|
+
return parsePrimitive();
|
|
290
|
+
}
|
|
291
|
+
if (startsWith(tokens.typeArray)) {
|
|
292
|
+
advance(tokens.typeArray.length);
|
|
293
|
+
return parseArray();
|
|
294
|
+
}
|
|
295
|
+
if (startsWith(tokens.typeObject)) {
|
|
296
|
+
advance(tokens.typeObject.length);
|
|
297
|
+
return parseObject();
|
|
298
|
+
}
|
|
299
|
+
if (startsWith(tokens.typeString)) {
|
|
300
|
+
advance(tokens.typeString.length);
|
|
301
|
+
return parseString();
|
|
302
|
+
}
|
|
303
|
+
throw new Error(`Unexpected type "${peek()}" at position ${pos}`);
|
|
304
|
+
}
|
|
305
|
+
return parseValue();
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function stringify(value, standalone = false, options = {}) {
|
|
309
|
+
const opts = resolveOptions(options);
|
|
310
|
+
const serialize = createSerializer(opts);
|
|
311
|
+
return cleanResult(serialize(value, standalone), standalone, opts);
|
|
312
|
+
}
|
|
313
|
+
function parse(input, standalone = false, options = {}) {
|
|
314
|
+
const opts = resolveOptions(options);
|
|
315
|
+
const datePattern = buildDatePattern(opts);
|
|
316
|
+
const str = decodeURIComponent(input);
|
|
317
|
+
if (str.length === 0) {
|
|
318
|
+
return standalone ? "" : {};
|
|
319
|
+
}
|
|
320
|
+
const hasMarker = str.startsWith(opts.typeString) || str.startsWith(opts.typePrimitive) || str.startsWith(opts.typeArray) || str.startsWith(opts.typeObject);
|
|
321
|
+
let source;
|
|
322
|
+
if (hasMarker) {
|
|
323
|
+
source = str;
|
|
324
|
+
} else if (standalone) {
|
|
325
|
+
if (datePattern.test(str)) {
|
|
326
|
+
const timestamp = parseInt(str.slice(opts.datePrefix.length), 10);
|
|
327
|
+
if (!isNaN(timestamp)) {
|
|
328
|
+
return new Date(timestamp);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
let result = "";
|
|
332
|
+
for (let i = 0; i < str.length; i++) {
|
|
333
|
+
if (str.slice(i, i + opts.escape.length) === opts.escape && i + opts.escape.length < str.length) {
|
|
334
|
+
i += opts.escape.length - 1;
|
|
335
|
+
result += str[i + 1];
|
|
336
|
+
i++;
|
|
337
|
+
} else {
|
|
338
|
+
result += str[i];
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return result;
|
|
342
|
+
} else {
|
|
343
|
+
const escapedMarkers = [opts.typeString, opts.typePrimitive, opts.typeArray, opts.typeObject].map(escapeRegex).join("");
|
|
344
|
+
const escapedEscape = escapeRegex(opts.escape);
|
|
345
|
+
const escapedSeparator = escapeRegex(opts.separator);
|
|
346
|
+
const escapedTerminator = escapeRegex(opts.terminator);
|
|
347
|
+
const objectPattern = new RegExp(
|
|
348
|
+
`[^${escapedEscape}${escapedMarkers}${escapedSeparator}${escapedTerminator}][${escapedMarkers}]`
|
|
349
|
+
);
|
|
350
|
+
source = objectPattern.test(str) ? `${opts.typeObject}${str}` : `${opts.typeString}${str}`;
|
|
351
|
+
}
|
|
352
|
+
const parseSource = createParser(opts);
|
|
353
|
+
return parseSource(source);
|
|
354
|
+
}
|
|
355
|
+
function createFormat(options = {}) {
|
|
356
|
+
const opts = resolveOptions(options);
|
|
357
|
+
validateOptions(opts);
|
|
358
|
+
return {
|
|
359
|
+
stringify(state) {
|
|
360
|
+
return stringify(state, false, options);
|
|
361
|
+
},
|
|
362
|
+
parse(value, _ctx) {
|
|
363
|
+
return parse(value, false, options);
|
|
364
|
+
},
|
|
365
|
+
stringifyStandalone(state) {
|
|
366
|
+
const result = {};
|
|
367
|
+
for (const [key, value] of Object.entries(state)) {
|
|
368
|
+
result[encodeURIComponent(key)] = [stringify(value, true, options)];
|
|
369
|
+
}
|
|
370
|
+
return result;
|
|
371
|
+
},
|
|
372
|
+
parseStandalone(params, _ctx) {
|
|
373
|
+
const result = {};
|
|
374
|
+
for (const [key, values] of Object.entries(params)) {
|
|
375
|
+
if (values.length > 0) {
|
|
376
|
+
result[decodeURIComponent(key)] = parse(values[0], true, options);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return result;
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
var marked = createFormat();
|
|
39
384
|
|
|
40
385
|
// src/middleware.ts
|
|
41
386
|
var compact = (newState, initialState, syncNull = false, syncUndefined = false) => {
|
|
@@ -79,55 +424,60 @@ var translateSelectionToState = (selection, state) => {
|
|
|
79
424
|
return acc;
|
|
80
425
|
}, {});
|
|
81
426
|
};
|
|
427
|
+
var parseSearchString = (search) => {
|
|
428
|
+
const result = {};
|
|
429
|
+
search.slice(search.startsWith("?") ? 1 : 0).split("&").filter(Boolean).forEach((param) => {
|
|
430
|
+
const eqIndex = param.indexOf("=");
|
|
431
|
+
if (eqIndex === -1) return;
|
|
432
|
+
const key = param.slice(0, eqIndex);
|
|
433
|
+
const value = param.slice(eqIndex + 1);
|
|
434
|
+
if (!result[key]) {
|
|
435
|
+
result[key] = [];
|
|
436
|
+
}
|
|
437
|
+
result[key].push(value);
|
|
438
|
+
});
|
|
439
|
+
return result;
|
|
440
|
+
};
|
|
82
441
|
var queryStringImpl = (fn, options) => (set, get, api) => {
|
|
83
442
|
const defaultedOptions = {
|
|
84
|
-
key:
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
parse
|
|
88
|
-
},
|
|
443
|
+
key: false,
|
|
444
|
+
prefix: "",
|
|
445
|
+
format: marked,
|
|
89
446
|
syncNull: false,
|
|
90
447
|
syncUndefined: false,
|
|
91
448
|
...options
|
|
92
449
|
};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (!window.__ZUSTAND_QUERYSTRING_KEYS__) {
|
|
96
|
-
window.__ZUSTAND_QUERYSTRING_KEYS__ = /* @__PURE__ */ new Map();
|
|
97
|
-
}
|
|
450
|
+
if (defaultedOptions.prefix === void 0) {
|
|
451
|
+
defaultedOptions.prefix = "";
|
|
98
452
|
}
|
|
453
|
+
const format = defaultedOptions.format;
|
|
454
|
+
const standalone = defaultedOptions.key === false;
|
|
99
455
|
const getStateFromUrl = (url, initialState) => {
|
|
456
|
+
const params = parseSearchString(url.search);
|
|
100
457
|
if (standalone) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
458
|
+
let filteredParams = params;
|
|
459
|
+
if (defaultedOptions.prefix) {
|
|
460
|
+
filteredParams = {};
|
|
461
|
+
for (const [key, values] of Object.entries(params)) {
|
|
462
|
+
if (key.startsWith(defaultedOptions.prefix)) {
|
|
463
|
+
filteredParams[key.slice(defaultedOptions.prefix.length)] = values;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
const result = format.parseStandalone(filteredParams, { initialState });
|
|
468
|
+
return Object.keys(result).length > 0 ? result : null;
|
|
469
|
+
} else {
|
|
470
|
+
const fullKey = defaultedOptions.prefix + defaultedOptions.key;
|
|
471
|
+
const values = params[fullKey];
|
|
472
|
+
if (values && values.length > 0) {
|
|
110
473
|
try {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
console.error("[getStateFromUrl] error parsing key:", key, error);
|
|
474
|
+
return format.parse(values[0], { initialState });
|
|
475
|
+
} catch {
|
|
476
|
+
return null;
|
|
115
477
|
}
|
|
116
|
-
});
|
|
117
|
-
return Object.keys(state).length > 0 ? state : null;
|
|
118
|
-
}
|
|
119
|
-
const params = url.search.slice(1).split("&");
|
|
120
|
-
for (const param of params) {
|
|
121
|
-
const eqIndex = param.indexOf("=");
|
|
122
|
-
if (eqIndex === -1) continue;
|
|
123
|
-
const key = param.slice(0, eqIndex);
|
|
124
|
-
if (key === defaultedOptions.key) {
|
|
125
|
-
const value = param.slice(eqIndex + 1);
|
|
126
|
-
const parsed = value ? defaultedOptions.format.parse(value, false) : null;
|
|
127
|
-
return parsed;
|
|
128
478
|
}
|
|
479
|
+
return null;
|
|
129
480
|
}
|
|
130
|
-
return null;
|
|
131
481
|
};
|
|
132
482
|
const getSelectedState = (state, pathname) => {
|
|
133
483
|
if (defaultedOptions.select) {
|
|
@@ -139,11 +489,11 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
|
|
|
139
489
|
};
|
|
140
490
|
const initialize = (url, initialState) => {
|
|
141
491
|
try {
|
|
142
|
-
const
|
|
143
|
-
if (!
|
|
492
|
+
const stateFromUrl = getStateFromUrl(url, initialState);
|
|
493
|
+
if (!stateFromUrl) {
|
|
144
494
|
return initialState;
|
|
145
495
|
}
|
|
146
|
-
const selected = getSelectedState(
|
|
496
|
+
const selected = getSelectedState(stateFromUrl, url.pathname);
|
|
147
497
|
const merged = (0, import_lodash_es.mergeWith)(
|
|
148
498
|
{},
|
|
149
499
|
initialState,
|
|
@@ -170,29 +520,7 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
|
|
|
170
520
|
get,
|
|
171
521
|
api
|
|
172
522
|
);
|
|
173
|
-
|
|
174
|
-
const registry = window.__ZUSTAND_QUERYSTRING_KEYS__;
|
|
175
|
-
const stateKeys = Object.keys(initialState).filter(
|
|
176
|
-
(k) => typeof initialState[k] !== "function"
|
|
177
|
-
);
|
|
178
|
-
const conflicts = [];
|
|
179
|
-
for (const key of stateKeys) {
|
|
180
|
-
if (registry.has(key)) {
|
|
181
|
-
const existing = registry.get(key);
|
|
182
|
-
const current = defaultedOptions.format;
|
|
183
|
-
if (existing !== current) {
|
|
184
|
-
conflicts.push(key);
|
|
185
|
-
}
|
|
186
|
-
} else {
|
|
187
|
-
registry.set(key, defaultedOptions.format);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
if (conflicts.length > 0) {
|
|
191
|
-
throw new Error(
|
|
192
|
-
`[zustand-querystring] Standalone mode conflict: Multiple stores are using the following keys with different formats: ${conflicts.map((k) => `"${k}"`).join(", ")}. This will cause parsing errors. Please use unique state keys or the same format for all stores sharing keys.`
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
523
|
+
let previouslyManagedKeys = /* @__PURE__ */ new Set();
|
|
196
524
|
const setQuery = () => {
|
|
197
525
|
const url = new URL(window.location.href);
|
|
198
526
|
const selectedState = getSelectedState(get(), url.pathname);
|
|
@@ -203,31 +531,55 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
|
|
|
203
531
|
defaultedOptions.syncUndefined
|
|
204
532
|
);
|
|
205
533
|
const previous = url.search;
|
|
534
|
+
let stateParams;
|
|
535
|
+
let managedKeys;
|
|
536
|
+
if (standalone) {
|
|
537
|
+
const allParams = format.stringifyStandalone(selectedState);
|
|
538
|
+
const currentKeys = new Set(Object.keys(allParams).map((k) => defaultedOptions.prefix + k));
|
|
539
|
+
managedKeys = /* @__PURE__ */ new Set([...Array.from(currentKeys), ...Array.from(previouslyManagedKeys)]);
|
|
540
|
+
previouslyManagedKeys = currentKeys;
|
|
541
|
+
const compactedParams = format.stringifyStandalone(newCompacted);
|
|
542
|
+
stateParams = {};
|
|
543
|
+
for (const [key, values] of Object.entries(compactedParams)) {
|
|
544
|
+
stateParams[defaultedOptions.prefix + key] = values;
|
|
545
|
+
}
|
|
546
|
+
} else {
|
|
547
|
+
const fullKey = defaultedOptions.prefix + defaultedOptions.key;
|
|
548
|
+
if (Object.keys(newCompacted).length > 0) {
|
|
549
|
+
stateParams = { [fullKey]: [format.stringify(newCompacted)] };
|
|
550
|
+
} else {
|
|
551
|
+
stateParams = {};
|
|
552
|
+
}
|
|
553
|
+
managedKeys = /* @__PURE__ */ new Set([fullKey]);
|
|
554
|
+
}
|
|
555
|
+
const valuesToWrite = /* @__PURE__ */ new Map();
|
|
556
|
+
const keyOrder = [];
|
|
557
|
+
for (const [key, values] of Object.entries(stateParams)) {
|
|
558
|
+
valuesToWrite.set(key, [...values]);
|
|
559
|
+
keyOrder.push(key);
|
|
560
|
+
}
|
|
206
561
|
const params = url.search.slice(1).split("&").filter(Boolean);
|
|
207
|
-
const managedKeys = standalone ? new Set(Object.keys(selectedState).map(encodeURI)) : /* @__PURE__ */ new Set([defaultedOptions.key]);
|
|
208
|
-
const valuesToWrite = standalone ? new Map(
|
|
209
|
-
Object.entries(newCompacted).map(([k, v]) => [encodeURI(k), v])
|
|
210
|
-
) : Object.keys(newCompacted).length ? /* @__PURE__ */ new Map([[defaultedOptions.key, newCompacted]]) : /* @__PURE__ */ new Map();
|
|
211
562
|
const result = [];
|
|
212
|
-
params.forEach((
|
|
213
|
-
const
|
|
563
|
+
params.forEach((param) => {
|
|
564
|
+
const eqIndex = param.indexOf("=");
|
|
565
|
+
if (eqIndex === -1) return;
|
|
566
|
+
const key = param.slice(0, eqIndex);
|
|
214
567
|
if (!managedKeys.has(key)) {
|
|
215
|
-
result.push(
|
|
568
|
+
result.push(param);
|
|
216
569
|
return;
|
|
217
570
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
);
|
|
223
|
-
result.push(`${key}=${encoded}`);
|
|
224
|
-
valuesToWrite.delete(key);
|
|
571
|
+
const values = valuesToWrite.get(key);
|
|
572
|
+
if (values && values.length > 0) {
|
|
573
|
+
const value = values.shift();
|
|
574
|
+
result.push(`${key}=${value}`);
|
|
225
575
|
}
|
|
226
576
|
});
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
577
|
+
for (const key of keyOrder) {
|
|
578
|
+
const values = valuesToWrite.get(key);
|
|
579
|
+
if (values) {
|
|
580
|
+
values.forEach((v) => result.push(`${key}=${v}`));
|
|
581
|
+
}
|
|
582
|
+
}
|
|
231
583
|
url.search = result.length ? "?" + result.join("&") : "";
|
|
232
584
|
if (url.search !== previous) {
|
|
233
585
|
history.replaceState(history.state, "", url);
|
|
@@ -251,6 +603,11 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
|
|
|
251
603
|
setQuery();
|
|
252
604
|
};
|
|
253
605
|
const initialized = initialize(new URL(window.location.href), initialState);
|
|
606
|
+
if (standalone) {
|
|
607
|
+
const initSelected = getSelectedState(initialized, new URL(window.location.href).pathname);
|
|
608
|
+
const initParams = format.stringifyStandalone(initSelected);
|
|
609
|
+
previouslyManagedKeys = new Set(Object.keys(initParams).map((k) => defaultedOptions.prefix + k));
|
|
610
|
+
}
|
|
254
611
|
api.getInitialState = () => initialized;
|
|
255
612
|
return initialized;
|
|
256
613
|
} else if (defaultedOptions.url) {
|
|
@@ -264,22 +621,10 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
|
|
|
264
621
|
return fn(set, get, api);
|
|
265
622
|
};
|
|
266
623
|
var querystring = queryStringImpl;
|
|
267
|
-
|
|
268
|
-
// src/utils.ts
|
|
269
|
-
var createURL = ({
|
|
270
|
-
baseUrl,
|
|
271
|
-
key,
|
|
272
|
-
state
|
|
273
|
-
}) => {
|
|
274
|
-
const url = new URL(baseUrl);
|
|
275
|
-
const stringified = stringify(state);
|
|
276
|
-
url.searchParams.set(key, stringified);
|
|
277
|
-
return url.href;
|
|
278
|
-
};
|
|
279
624
|
// Annotate the CommonJS export names for ESM import in node:
|
|
280
625
|
0 && (module.exports = {
|
|
281
|
-
|
|
282
|
-
parse,
|
|
283
|
-
querystring,
|
|
284
|
-
stringify
|
|
626
|
+
querystring
|
|
285
627
|
});
|
|
628
|
+
/* v8 ignore next 4 -- @preserve: defensive - handles escape char at very end of source */
|
|
629
|
+
/* v8 ignore next 3 -- @preserve: defensive - parseInt on digit string won't produce NaN */
|
|
630
|
+
/* v8 ignore next 2 -- @preserve: defensive code - all valid types are handled above */
|