zustand-querystring 0.0.16 → 0.0.18

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
@@ -5,14 +5,16 @@ A Zustand middleware that syncs the store with the querystring.
5
5
  Try on [StackBlitz](https://stackblitz.com/github/nitedani/zustand-querystring/tree/main/examples/react) (You need to click "Open in New Tab")
6
6
 
7
7
  Examples:
8
+
8
9
  - [React](./examples/react/)
9
10
  - [NextJS](./examples/next/)
10
11
  - [Rakkas](./examples/rakkas/)
11
12
 
12
13
  Quickstart:
14
+
13
15
  ```ts
14
- import create from "zustand";
15
- import { querystring } from "zustand-querystring";
16
+ import create from 'zustand';
17
+ import { querystring } from 'zustand-querystring';
16
18
 
17
19
  interface Store {
18
20
  count: number;
@@ -30,7 +32,7 @@ export const useStore = create<Store>()(
30
32
  ticks: 0,
31
33
  someNestedState: {
32
34
  nestedCount: 0,
33
- hello: "Hello",
35
+ hello: 'Hello',
34
36
  },
35
37
  }),
36
38
  {
@@ -43,19 +45,20 @@ export const useStore = create<Store>()(
43
45
 
44
46
  someNestedState: {
45
47
  nestedCount: true,
46
- hello: "/about" === pathname,
48
+ hello: '/about' === pathname,
47
49
  },
48
50
 
49
51
  // OR select the whole nested state
50
52
  // someNestedState: true
51
53
  };
52
54
  },
53
- }
54
- )
55
+ },
56
+ ),
55
57
  );
56
58
  ```
57
59
 
58
60
  querystring options:
61
+
59
62
  - <b>select</b> - the select option controls what part of the state is synced with the query string
60
63
  - <b>key: string</b> - the key option controls how the state is stored in the querystring (default: $)
61
- - <b>url</b> - the url option is used to provide the request url on the server side render
64
+ - <b>url</b> - the url option is used to provide the request url on the server side render
@@ -7,7 +7,7 @@ function encodeString(str, regexp) {
7
7
  return encodeURI(str.replace(regexp, "/$1"));
8
8
  }
9
9
  function trim(res) {
10
- return typeof res === "string" ? res.replace(/;+$/g, "") : res;
10
+ return typeof res === "string" ? res.replace(/;+$/g, "").replace(/^\$/, "") : res;
11
11
  }
12
12
  function stringify(input, recursive) {
13
13
  if (!recursive) {
@@ -41,6 +41,9 @@ function stringify(input, recursive) {
41
41
  return "=" + encodeString(input.toString(), valueStringifyRegexp);
42
42
  }
43
43
  function parse(str) {
44
+ if (!str.startsWith("$")) {
45
+ str = "$" + str;
46
+ }
44
47
  let pos = 0;
45
48
  str = decodeURI(str);
46
49
  function readToken(regexp) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  parse,
3
3
  stringify
4
- } from "./chunk-QPGVZKLE.mjs";
4
+ } from "./chunk-77OZJNG4.mjs";
5
5
 
6
6
  // src/middleware.ts
7
7
  import { mergeWith, isEqual, cloneDeep } from "lodash-es";
@@ -58,11 +58,7 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
58
58
  var _a;
59
59
  const match = querystring2.match(stateMatcher);
60
60
  if (match) {
61
- let m = (_a = match[1]) != null ? _a : match[2];
62
- if (!m.startsWith("$")) {
63
- m = "$" + m;
64
- }
65
- return parse(m);
61
+ return parse((_a = match[1]) != null ? _a : match[2]);
66
62
  }
67
63
  return null;
68
64
  };
@@ -131,10 +127,10 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
131
127
  ignored += (ignored ? "&" : "?") + str;
132
128
  }
133
129
  const newCompacted = compact(newMerged, initialState);
130
+ let newQueryString = "";
134
131
  if (Object.keys(newCompacted).length) {
135
- const stringified = stringify(newCompacted).substring(1);
132
+ const stringified = stringify(newCompacted);
136
133
  const newQueryState = `${defaultedOptions.key}=${stringified};;`;
137
- let newQueryString = "";
138
134
  if (currentParsed) {
139
135
  newQueryString = currentQueryString.replace(
140
136
  splitMatcher,
@@ -145,13 +141,13 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
145
141
  } else {
146
142
  newQueryString = "?" + newQueryState;
147
143
  }
148
- history.replaceState(
149
- history.state,
150
- "",
151
- location.pathname + newQueryString
152
- );
153
144
  } else {
154
- history.replaceState(history.state, "", location.pathname + ignored);
145
+ newQueryString = ignored;
146
+ }
147
+ const currentUrl = location.pathname + location.search;
148
+ const newUrl = location.pathname + newQueryString;
149
+ if (newUrl !== currentUrl) {
150
+ history.replaceState(history.state, "", newUrl);
155
151
  }
156
152
  };
157
153
  if (!api.__ZUSTAND_QUERYSTRING_INIT__) {
@@ -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 CHANGED
@@ -1,2 +1,4 @@
1
1
  export { QueryStringOptions, querystring } from './middleware.js';
2
+ export { parse, stringify } from './parser.js';
3
+ export { createURL } from './utils.js';
2
4
  import 'zustand/vanilla';
package/dist/index.js CHANGED
@@ -19,7 +19,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  // src/index.ts
20
20
  var src_exports = {};
21
21
  __export(src_exports, {
22
- querystring: () => querystring
22
+ createURL: () => createURL,
23
+ parse: () => parse,
24
+ querystring: () => querystring,
25
+ stringify: () => stringify
23
26
  });
24
27
  module.exports = __toCommonJS(src_exports);
25
28
 
@@ -32,7 +35,7 @@ function encodeString(str, regexp) {
32
35
  return encodeURI(str.replace(regexp, "/$1"));
33
36
  }
34
37
  function trim(res) {
35
- return typeof res === "string" ? res.replace(/;+$/g, "") : res;
38
+ return typeof res === "string" ? res.replace(/;+$/g, "").replace(/^\$/, "") : res;
36
39
  }
37
40
  function stringify(input, recursive) {
38
41
  if (!recursive) {
@@ -66,6 +69,9 @@ function stringify(input, recursive) {
66
69
  return "=" + encodeString(input.toString(), valueStringifyRegexp);
67
70
  }
68
71
  function parse(str) {
72
+ if (!str.startsWith("$")) {
73
+ str = "$" + str;
74
+ }
69
75
  let pos = 0;
70
76
  str = decodeURI(str);
71
77
  function readToken(regexp) {
@@ -191,15 +197,11 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
191
197
  const escapedKey = escapeStringRegexp(defaultedOptions.key);
192
198
  const stateMatcher = new RegExp(`${escapedKey}=(.*);;|${escapedKey}=(.*)$`);
193
199
  const splitMatcher = new RegExp(`${escapedKey}=.*;;|${escapedKey}=.*$`);
194
- const parseQueryString = (querystring2) => {
200
+ const parseQueryString2 = (querystring2) => {
195
201
  var _a;
196
202
  const match = querystring2.match(stateMatcher);
197
203
  if (match) {
198
- let m = (_a = match[1]) != null ? _a : match[2];
199
- if (!m.startsWith("$")) {
200
- m = "$" + m;
201
- }
202
- return parse(m);
204
+ return parse((_a = match[1]) != null ? _a : match[2]);
203
205
  }
204
206
  return null;
205
207
  };
@@ -219,7 +221,7 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
219
221
  if (!queryString) {
220
222
  return initialState;
221
223
  }
222
- const parsed = parseQueryString(queryString);
224
+ const parsed = parseQueryString2(queryString);
223
225
  if (!parsed) {
224
226
  return initialState;
225
227
  }
@@ -248,7 +250,7 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
248
250
  const setQuery = () => {
249
251
  const selectedState = getSelectedState(get(), location.pathname);
250
252
  const currentQueryString = location.search;
251
- const currentParsed = parseQueryString(currentQueryString);
253
+ const currentParsed = parseQueryString2(currentQueryString);
252
254
  const newMerged = {
253
255
  ...currentParsed,
254
256
  ...selectedState
@@ -268,10 +270,10 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
268
270
  ignored += (ignored ? "&" : "?") + str;
269
271
  }
270
272
  const newCompacted = compact(newMerged, initialState);
273
+ let newQueryString = "";
271
274
  if (Object.keys(newCompacted).length) {
272
- const stringified = stringify(newCompacted).substring(1);
275
+ const stringified = stringify(newCompacted);
273
276
  const newQueryState = `${defaultedOptions.key}=${stringified};;`;
274
- let newQueryString = "";
275
277
  if (currentParsed) {
276
278
  newQueryString = currentQueryString.replace(
277
279
  splitMatcher,
@@ -282,13 +284,13 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
282
284
  } else {
283
285
  newQueryString = "?" + newQueryState;
284
286
  }
285
- history.replaceState(
286
- history.state,
287
- "",
288
- location.pathname + newQueryString
289
- );
290
287
  } else {
291
- history.replaceState(history.state, "", location.pathname + ignored);
288
+ newQueryString = ignored;
289
+ }
290
+ const currentUrl = location.pathname + location.search;
291
+ const newUrl = location.pathname + newQueryString;
292
+ if (newUrl !== currentUrl) {
293
+ history.replaceState(history.state, "", newUrl);
292
294
  }
293
295
  };
294
296
  if (!api.__ZUSTAND_QUERYSTRING_INIT__) {
@@ -318,7 +320,66 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
318
320
  return fn(set, get, api);
319
321
  };
320
322
  var querystring = queryStringImpl;
323
+
324
+ // src/utils.ts
325
+ var escapeStringRegexp2 = (string) => {
326
+ if (typeof string !== "string") {
327
+ throw new TypeError("Expected a string");
328
+ }
329
+ return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
330
+ };
331
+ var parseQueryString = (key, querystring2) => {
332
+ var _a;
333
+ const stateMatcher = new RegExp(`${key}=(.*);;|${key}=(.*)$`);
334
+ const match = querystring2.match(stateMatcher);
335
+ if (match) {
336
+ return parse((_a = match[1]) != null ? _a : match[2]);
337
+ }
338
+ return null;
339
+ };
340
+ var createURL = ({
341
+ baseUrl,
342
+ key,
343
+ state
344
+ }) => {
345
+ const escapedKey = escapeStringRegexp2(key);
346
+ const stringified = stringify(state);
347
+ const newQueryState = `${key}=${stringified};;`;
348
+ const match = baseUrl.indexOf("?");
349
+ const currentQueryString = match >= 0 ? baseUrl.substring(match) : "";
350
+ const currentParsed = parseQueryString(escapedKey, currentQueryString);
351
+ const splitMatcher = new RegExp(`${escapedKey}=.*;;|${escapedKey}=.*$`);
352
+ const splitIgnored = currentQueryString.split(splitMatcher);
353
+ let ignored = "";
354
+ for (let str of splitIgnored) {
355
+ if (!str || str === "?" || str === "&") {
356
+ continue;
357
+ }
358
+ if (str.startsWith("&") || str.startsWith("?")) {
359
+ str = str.substring(1);
360
+ }
361
+ if (str.endsWith("&")) {
362
+ str = str.substring(0, str.length - 1);
363
+ }
364
+ ignored += (ignored ? "&" : "?") + str;
365
+ }
366
+ let newQueryString = "";
367
+ if (currentParsed) {
368
+ newQueryString = currentQueryString.replace(splitMatcher, newQueryState);
369
+ } else if (ignored) {
370
+ newQueryString = ignored + "&" + newQueryState;
371
+ } else {
372
+ newQueryString = "?" + newQueryState;
373
+ }
374
+ if (currentQueryString) {
375
+ return baseUrl.replace(currentQueryString, newQueryString);
376
+ }
377
+ return baseUrl + newQueryString;
378
+ };
321
379
  // Annotate the CommonJS export names for ESM import in node:
322
380
  0 && (module.exports = {
323
- querystring
381
+ createURL,
382
+ parse,
383
+ querystring,
384
+ stringify
324
385
  });
package/dist/index.mjs CHANGED
@@ -1,7 +1,16 @@
1
1
  import {
2
2
  querystring
3
- } from "./chunk-QIA7KKX4.mjs";
4
- import "./chunk-QPGVZKLE.mjs";
3
+ } from "./chunk-H7YBN6IK.mjs";
4
+ import {
5
+ createURL
6
+ } from "./chunk-STY4LBQG.mjs";
7
+ import {
8
+ parse,
9
+ stringify
10
+ } from "./chunk-77OZJNG4.mjs";
5
11
  export {
6
- querystring
12
+ createURL,
13
+ parse,
14
+ querystring,
15
+ stringify
7
16
  };
@@ -32,7 +32,7 @@ function encodeString(str, regexp) {
32
32
  return encodeURI(str.replace(regexp, "/$1"));
33
33
  }
34
34
  function trim(res) {
35
- return typeof res === "string" ? res.replace(/;+$/g, "") : res;
35
+ return typeof res === "string" ? res.replace(/;+$/g, "").replace(/^\$/, "") : res;
36
36
  }
37
37
  function stringify(input, recursive) {
38
38
  if (!recursive) {
@@ -66,6 +66,9 @@ function stringify(input, recursive) {
66
66
  return "=" + encodeString(input.toString(), valueStringifyRegexp);
67
67
  }
68
68
  function parse(str) {
69
+ if (!str.startsWith("$")) {
70
+ str = "$" + str;
71
+ }
69
72
  let pos = 0;
70
73
  str = decodeURI(str);
71
74
  function readToken(regexp) {
@@ -195,11 +198,7 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
195
198
  var _a;
196
199
  const match = querystring2.match(stateMatcher);
197
200
  if (match) {
198
- let m = (_a = match[1]) != null ? _a : match[2];
199
- if (!m.startsWith("$")) {
200
- m = "$" + m;
201
- }
202
- return parse(m);
201
+ return parse((_a = match[1]) != null ? _a : match[2]);
203
202
  }
204
203
  return null;
205
204
  };
@@ -268,10 +267,10 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
268
267
  ignored += (ignored ? "&" : "?") + str;
269
268
  }
270
269
  const newCompacted = compact(newMerged, initialState);
270
+ let newQueryString = "";
271
271
  if (Object.keys(newCompacted).length) {
272
- const stringified = stringify(newCompacted).substring(1);
272
+ const stringified = stringify(newCompacted);
273
273
  const newQueryState = `${defaultedOptions.key}=${stringified};;`;
274
- let newQueryString = "";
275
274
  if (currentParsed) {
276
275
  newQueryString = currentQueryString.replace(
277
276
  splitMatcher,
@@ -282,13 +281,13 @@ var queryStringImpl = (fn, options) => (set, get, api) => {
282
281
  } else {
283
282
  newQueryString = "?" + newQueryState;
284
283
  }
285
- history.replaceState(
286
- history.state,
287
- "",
288
- location.pathname + newQueryString
289
- );
290
284
  } else {
291
- history.replaceState(history.state, "", location.pathname + ignored);
285
+ newQueryString = ignored;
286
+ }
287
+ const currentUrl = location.pathname + location.search;
288
+ const newUrl = location.pathname + newQueryString;
289
+ if (newUrl !== currentUrl) {
290
+ history.replaceState(history.state, "", newUrl);
292
291
  }
293
292
  };
294
293
  if (!api.__ZUSTAND_QUERYSTRING_INIT__) {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  querystring
3
- } from "./chunk-QIA7KKX4.mjs";
4
- import "./chunk-QPGVZKLE.mjs";
3
+ } from "./chunk-H7YBN6IK.mjs";
4
+ import "./chunk-77OZJNG4.mjs";
5
5
  export {
6
6
  querystring
7
7
  };
package/dist/parser.js CHANGED
@@ -31,7 +31,7 @@ function encodeString(str, regexp) {
31
31
  return encodeURI(str.replace(regexp, "/$1"));
32
32
  }
33
33
  function trim(res) {
34
- return typeof res === "string" ? res.replace(/;+$/g, "") : res;
34
+ return typeof res === "string" ? res.replace(/;+$/g, "").replace(/^\$/, "") : res;
35
35
  }
36
36
  function stringify(input, recursive) {
37
37
  if (!recursive) {
@@ -65,6 +65,9 @@ function stringify(input, recursive) {
65
65
  return "=" + encodeString(input.toString(), valueStringifyRegexp);
66
66
  }
67
67
  function parse(str) {
68
+ if (!str.startsWith("$")) {
69
+ str = "$" + str;
70
+ }
68
71
  let pos = 0;
69
72
  str = decodeURI(str);
70
73
  function readToken(regexp) {
package/dist/parser.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  parse,
3
3
  stringify
4
- } from "./chunk-QPGVZKLE.mjs";
4
+ } from "./chunk-77OZJNG4.mjs";
5
5
  export {
6
6
  parse,
7
7
  stringify
@@ -0,0 +1,7 @@
1
+ declare const createURL: ({ baseUrl, key, state, }: {
2
+ baseUrl: string;
3
+ key: string;
4
+ state: Object;
5
+ }) => string;
6
+
7
+ export { createURL };
package/dist/utils.js ADDED
@@ -0,0 +1,204 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/utils.ts
20
+ var utils_exports = {};
21
+ __export(utils_exports, {
22
+ createURL: () => createURL
23
+ });
24
+ module.exports = __toCommonJS(utils_exports);
25
+
26
+ // src/parser.ts
27
+ var keyStringifyRegexp = /([=:@$/])/g;
28
+ var valueStringifyRegexp = /([&;/])/g;
29
+ var keyParseRegexp = /[=:@$]/;
30
+ var valueParseRegexp = /[&;]/;
31
+ function encodeString(str, regexp) {
32
+ return encodeURI(str.replace(regexp, "/$1"));
33
+ }
34
+ function trim(res) {
35
+ return typeof res === "string" ? res.replace(/;+$/g, "").replace(/^\$/, "") : res;
36
+ }
37
+ function stringify(input, recursive) {
38
+ if (!recursive) {
39
+ return trim(stringify(input, true));
40
+ }
41
+ if (typeof input === "function") {
42
+ return;
43
+ }
44
+ if (typeof input === "number" || input === true || input === false || input === null) {
45
+ return ":" + input;
46
+ }
47
+ const res = [];
48
+ if (Array.isArray(input)) {
49
+ for (const elem of input) {
50
+ typeof elem === "undefined" ? res.push(":null") : res.push(stringify(elem, true));
51
+ }
52
+ return "@" + res.join("&") + ";";
53
+ }
54
+ if (typeof input === "object") {
55
+ for (const [key, value] of Object.entries(input)) {
56
+ const stringifiedValue = stringify(value, true);
57
+ if (stringifiedValue) {
58
+ res.push(encodeString(key, keyStringifyRegexp) + stringifiedValue);
59
+ }
60
+ }
61
+ return "$" + res.join("&") + ";";
62
+ }
63
+ if (typeof input === "undefined") {
64
+ return;
65
+ }
66
+ return "=" + encodeString(input.toString(), valueStringifyRegexp);
67
+ }
68
+ function parse(str) {
69
+ if (!str.startsWith("$")) {
70
+ str = "$" + str;
71
+ }
72
+ let pos = 0;
73
+ str = decodeURI(str);
74
+ function readToken(regexp) {
75
+ let token = "";
76
+ for (; pos !== str.length; ++pos) {
77
+ if (str.charAt(pos) === "/") {
78
+ pos += 1;
79
+ if (pos === str.length) {
80
+ token += ";";
81
+ break;
82
+ }
83
+ } else if (str.charAt(pos).match(regexp)) {
84
+ break;
85
+ }
86
+ token += str.charAt(pos);
87
+ }
88
+ return token;
89
+ }
90
+ function parseToken() {
91
+ const type = str.charAt(pos++);
92
+ if (type === "=") {
93
+ return readToken(valueParseRegexp);
94
+ }
95
+ if (type === ":") {
96
+ const value = readToken(valueParseRegexp);
97
+ if (value === "true") {
98
+ return true;
99
+ }
100
+ if (value === "false") {
101
+ return false;
102
+ }
103
+ const parsedValue = parseFloat(value);
104
+ return isNaN(parsedValue) ? null : parsedValue;
105
+ }
106
+ if (type === "@") {
107
+ const res = [];
108
+ loop: {
109
+ if (pos >= str.length || str.charAt(pos) === ";") {
110
+ break loop;
111
+ }
112
+ while (1) {
113
+ res.push(parseToken());
114
+ if (pos >= str.length || str.charAt(pos) === ";") {
115
+ break loop;
116
+ }
117
+ pos += 1;
118
+ }
119
+ }
120
+ pos += 1;
121
+ return res;
122
+ }
123
+ if (type === "$") {
124
+ const res = {};
125
+ loop: {
126
+ if (pos >= str.length || str.charAt(pos) === ";") {
127
+ break loop;
128
+ }
129
+ while (1) {
130
+ var name = readToken(keyParseRegexp);
131
+ res[name] = parseToken();
132
+ if (pos >= str.length || str.charAt(pos) === ";") {
133
+ break loop;
134
+ }
135
+ pos += 1;
136
+ }
137
+ }
138
+ pos += 1;
139
+ return res;
140
+ }
141
+ throw new Error("Unexpected char " + type);
142
+ }
143
+ return parseToken();
144
+ }
145
+
146
+ // src/utils.ts
147
+ var escapeStringRegexp = (string) => {
148
+ if (typeof string !== "string") {
149
+ throw new TypeError("Expected a string");
150
+ }
151
+ return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&");
152
+ };
153
+ var parseQueryString = (key, querystring) => {
154
+ var _a;
155
+ const stateMatcher = new RegExp(`${key}=(.*);;|${key}=(.*)$`);
156
+ const match = querystring.match(stateMatcher);
157
+ if (match) {
158
+ return parse((_a = match[1]) != null ? _a : match[2]);
159
+ }
160
+ return null;
161
+ };
162
+ var createURL = ({
163
+ baseUrl,
164
+ key,
165
+ state
166
+ }) => {
167
+ const escapedKey = escapeStringRegexp(key);
168
+ const stringified = stringify(state);
169
+ const newQueryState = `${key}=${stringified};;`;
170
+ const match = baseUrl.indexOf("?");
171
+ const currentQueryString = match >= 0 ? baseUrl.substring(match) : "";
172
+ const currentParsed = parseQueryString(escapedKey, currentQueryString);
173
+ const splitMatcher = new RegExp(`${escapedKey}=.*;;|${escapedKey}=.*$`);
174
+ const splitIgnored = currentQueryString.split(splitMatcher);
175
+ let ignored = "";
176
+ for (let str of splitIgnored) {
177
+ if (!str || str === "?" || str === "&") {
178
+ continue;
179
+ }
180
+ if (str.startsWith("&") || str.startsWith("?")) {
181
+ str = str.substring(1);
182
+ }
183
+ if (str.endsWith("&")) {
184
+ str = str.substring(0, str.length - 1);
185
+ }
186
+ ignored += (ignored ? "&" : "?") + str;
187
+ }
188
+ let newQueryString = "";
189
+ if (currentParsed) {
190
+ newQueryString = currentQueryString.replace(splitMatcher, newQueryState);
191
+ } else if (ignored) {
192
+ newQueryString = ignored + "&" + newQueryState;
193
+ } else {
194
+ newQueryString = "?" + newQueryState;
195
+ }
196
+ if (currentQueryString) {
197
+ return baseUrl.replace(currentQueryString, newQueryString);
198
+ }
199
+ return baseUrl + newQueryString;
200
+ };
201
+ // Annotate the CommonJS export names for ESM import in node:
202
+ 0 && (module.exports = {
203
+ createURL
204
+ });
package/dist/utils.mjs ADDED
@@ -0,0 +1,7 @@
1
+ import {
2
+ createURL
3
+ } from "./chunk-STY4LBQG.mjs";
4
+ import "./chunk-77OZJNG4.mjs";
5
+ export {
6
+ createURL
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zustand-querystring",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",