state-in-url 4.0.3 → 4.0.5
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 +13 -11
- package/dist/next/useUrlState/useUrlState.d.ts +10 -7
- package/dist/next/useUrlState/useUrlState.mjs +1 -1
- package/dist/react-router/useUrlState/useUrlState.d.ts +10 -7
- package/dist/react-router/useUrlState/useUrlState.mjs +1 -1
- package/dist/useSharedState/useSharedState.d.ts +2 -2
- package/dist/useSharedState/useSharedState.mjs +1 -1
- package/dist/useUrlEncode/useUrlEncode.mjs +1 -1
- package/dist/useUrlStateBase/useUrlStateBase.d.ts +4 -4
- package/dist/utils.d.ts +0 -3
- package/package.json +29 -25
package/README.md
CHANGED
|
@@ -23,6 +23,10 @@ English | [한국어](./README.KO.md) | [简体中文](./README.CN.md)
|
|
|
23
23
|
[](https://github.com/asmyshlyaev177/state-in-url/)
|
|
24
24
|
[]([https://github.com/semantic-release/semantic-release](https://github.com/asmyshlyaev177/state-in-url))
|
|
25
25
|

|
|
26
|
+
[](https://scorecard.dev/viewer/?uri=github.com/asmyshlyaev177/state-in-url)
|
|
27
|
+
[](https://www.bestpractices.dev/projects/9679)
|
|
28
|
+
<!-- or by embedding this in your HTML:
|
|
29
|
+
<a href="https://www.bestpractices.dev/projects/9679"><img src="https://www.bestpractices.dev/projects/9679/badge"></a> -->
|
|
26
30
|
|
|
27
31
|
</div>
|
|
28
32
|
|
|
@@ -53,7 +57,7 @@ Share if it useful for you.
|
|
|
53
57
|
|
|
54
58
|
# Why use `state-in-url`?
|
|
55
59
|
|
|
56
|
-
Store any user state in query parameters; imagine JSON in a browser URL, while keeping types and structure of data.
|
|
60
|
+
Store any user state in query parameters; imagine JSON in a browser URL, while keeping types and structure of data, e.g. numbers will be decoded as numbers not strings, Date stay a date, objects and arrays supported.
|
|
57
61
|
Dead simple, fast, and with static Typescript validation. Deep links, aka URL synchronization, made easy.
|
|
58
62
|
|
|
59
63
|
Contains `useUrlState` hook for Next.js and react-router, and helpers for anything else on JS.
|
|
@@ -131,7 +135,7 @@ All components that use the same `state` object are automatically synchronized.
|
|
|
131
135
|
|
|
132
136
|
## useUrlState hook for Next.js
|
|
133
137
|
|
|
134
|
-
[Docs](packages/urlstate/next/useUrlState#api)
|
|
138
|
+
[Full API Docs](packages/urlstate/next/useUrlState#api)
|
|
135
139
|
|
|
136
140
|
[React-Router example](#useurlstate-hook-for-react-router)
|
|
137
141
|
|
|
@@ -146,6 +150,7 @@ All components that use the same `state` object are automatically synchronized.
|
|
|
146
150
|
// Only parameters with value different from default will go to the url.
|
|
147
151
|
export const userState: UserState = { name: '', age: 0 }
|
|
148
152
|
|
|
153
|
+
// use `Type` not `Interface`!
|
|
149
154
|
type UserState = { name: string, age: number }
|
|
150
155
|
```
|
|
151
156
|
|
|
@@ -162,9 +167,6 @@ function MyComponent() {
|
|
|
162
167
|
// can pass `searchParams` from server components
|
|
163
168
|
const { urlState, setUrl, setState } = useUrlState({ defaultState: userState });
|
|
164
169
|
|
|
165
|
-
// won't let you to accidently mutate state directly, requires TS
|
|
166
|
-
// urlState.name = 'John' // <- error
|
|
167
|
-
|
|
168
170
|
return (
|
|
169
171
|
<div>
|
|
170
172
|
<input value={urlState.name}
|
|
@@ -397,7 +399,7 @@ function SettingsComponent() {
|
|
|
397
399
|
|
|
398
400
|
API is same as for Next.js version, except can pass options from [NavigateOptions](https://github.com/remix-run/react-router/blob/bc693ed9f39170bda13b9e1b282fb8e9d5925f66/packages/react-router/lib/context.ts#L99) type.
|
|
399
401
|
|
|
400
|
-
[Docs](packages/urlstate/react-router/useUrlState#api)
|
|
402
|
+
[API Docs](packages/urlstate/react-router/useUrlState#api)
|
|
401
403
|
|
|
402
404
|
### Example
|
|
403
405
|
|
|
@@ -486,7 +488,7 @@ const tags = [
|
|
|
486
488
|
|
|
487
489
|
Hooks to create your own `useUrlState` hooks with other routers, e.g. react-router or tanstack router.
|
|
488
490
|
|
|
489
|
-
[Docs](packages/urlstate/useUrlStateBase)
|
|
491
|
+
[API Docs](packages/urlstate/useUrlStateBase)
|
|
490
492
|
|
|
491
493
|
## `useSharedState` hook for React.js
|
|
492
494
|
|
|
@@ -503,19 +505,19 @@ function SettingsComponent() {
|
|
|
503
505
|
}
|
|
504
506
|
```
|
|
505
507
|
|
|
506
|
-
[Docs](packages/urlstate/useSharedState/README.md)
|
|
508
|
+
[API Docs](packages/urlstate/useSharedState/README.md)
|
|
507
509
|
|
|
508
510
|
## `useUrlEncode` hook for React.js
|
|
509
511
|
|
|
510
|
-
[Docs](packages/urlstate/useUrlEncode/README.md)
|
|
512
|
+
[API Docs](packages/urlstate/useUrlEncode/README.md)
|
|
511
513
|
|
|
512
514
|
## `encodeState` and `decodeState` helpers
|
|
513
515
|
|
|
514
|
-
[Docs](packages/urlstate/encodeState/README.md)
|
|
516
|
+
[API Docs](packages/urlstate/encodeState/README.md)
|
|
515
517
|
|
|
516
518
|
## `encode` and `decode` helpers
|
|
517
519
|
|
|
518
|
-
[Docs](packages/urlstate/encoder/README.md)
|
|
520
|
+
[API Docs](packages/urlstate/encoder/README.md)
|
|
519
521
|
|
|
520
522
|
# Best Practices
|
|
521
523
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useRouter } from "next/navigation";
|
|
2
|
-
import { type
|
|
2
|
+
import { type JSONCompatible } from "../../utils";
|
|
3
3
|
/**
|
|
4
4
|
* NextJS hook. Returns `urlState`, `setState`, and `setUrl` functions
|
|
5
5
|
*
|
|
@@ -40,11 +40,11 @@ export declare function useUrlState<T extends JSONCompatible>({ defaultState, se
|
|
|
40
40
|
*
|
|
41
41
|
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/next/useUrlState#updatestate}
|
|
42
42
|
*/
|
|
43
|
-
setState: (value: Partial<T> |
|
|
43
|
+
setState: (value: Partial<T> | ((currState: T) => T)) => void;
|
|
44
44
|
/**
|
|
45
45
|
* @deprecated use `setState`
|
|
46
46
|
*/
|
|
47
|
-
updateState: (value: Partial<T> |
|
|
47
|
+
updateState: (value: Partial<T> | ((currState: T) => T)) => void;
|
|
48
48
|
/**
|
|
49
49
|
* * Example:
|
|
50
50
|
* ```ts
|
|
@@ -55,16 +55,19 @@ export declare function useUrlState<T extends JSONCompatible>({ defaultState, se
|
|
|
55
55
|
*
|
|
56
56
|
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/next/useUrlState#updateurl}
|
|
57
57
|
*/
|
|
58
|
-
setUrl: (value?: Parameters<(value?: Partial<T> |
|
|
58
|
+
setUrl: (value?: Parameters<(value?: Partial<T> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: Options) => void;
|
|
59
59
|
/**
|
|
60
60
|
* @deprecated use `setUrl`
|
|
61
61
|
*/
|
|
62
|
-
updateUrl: (value?: Parameters<(value?: Partial<T> |
|
|
63
|
-
|
|
62
|
+
updateUrl: (value?: Parameters<(value?: Partial<T> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: Options) => void;
|
|
63
|
+
/**
|
|
64
|
+
* State object. Don't mutate directly, use `setState` or `setUrl`
|
|
65
|
+
*/
|
|
66
|
+
urlState: T;
|
|
64
67
|
/**
|
|
65
68
|
* @deprecated use `urlState`
|
|
66
69
|
*/
|
|
67
|
-
state:
|
|
70
|
+
state: T;
|
|
68
71
|
getState: () => T;
|
|
69
72
|
};
|
|
70
73
|
type Router = ReturnType<typeof useRouter>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useRouter as t,useSearchParams as e}from"next/navigation";import r from"react";import{parseSPObj as a}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{routerHistory as o,isSSR as m,filterUnknownParams as u,filterUnknownParamsClient as i}from"../../utils.mjs";function l({defaultState:l,searchParams:c,useHistory:n
|
|
1
|
+
import{useRouter as t,useSearchParams as e}from"next/navigation";import r from"react";import{parseSPObj as a}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{routerHistory as o,isSSR as m,filterUnknownParams as u,filterUnknownParamsClient as i}from"../../utils.mjs";function l({defaultState:l,searchParams:c,useHistory:f,...n}){const S=void 0===f||f?o:t(),{state:d,updateState:j,updateUrl:U,getState:b}=s(l,S,(({parse:t})=>m()?a(u(l,c),l):t(i(l)))),g=r.useCallback(((t,e)=>U(t,{...p,...n,...e})),[U,n]),v=e();return r.useEffect((()=>{j(u(l,a(Object.fromEntries([...v.entries()]),l)))}),[v]),{setState:j,updateState:j,setUrl:g,updateUrl:g,urlState:d,state:d,getState:b}}const p={replace:!0,scroll:!1};export{l as useUrlState};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type NavigateOptions } from "react-router-dom";
|
|
2
|
-
import { type
|
|
2
|
+
import { type JSONCompatible } from "../../utils";
|
|
3
3
|
/**
|
|
4
4
|
* React-router hook. Returns `urlState`, `setState`, and `setUrl` functions
|
|
5
5
|
*
|
|
@@ -35,11 +35,11 @@ export declare function useUrlState<T extends JSONCompatible>({ defaultState, us
|
|
|
35
35
|
*
|
|
36
36
|
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/react-router/useUrlState#updatestate}
|
|
37
37
|
*/
|
|
38
|
-
setState: (value: Partial<T> |
|
|
38
|
+
setState: (value: Partial<T> | ((currState: T) => T)) => void;
|
|
39
39
|
/**
|
|
40
40
|
* @deprecated use `setState`
|
|
41
41
|
*/
|
|
42
|
-
updateState: (value: Partial<T> |
|
|
42
|
+
updateState: (value: Partial<T> | ((currState: T) => T)) => void;
|
|
43
43
|
/**
|
|
44
44
|
* * Example:
|
|
45
45
|
* ```ts
|
|
@@ -52,15 +52,18 @@ export declare function useUrlState<T extends JSONCompatible>({ defaultState, us
|
|
|
52
52
|
*
|
|
53
53
|
* * Docs {@link https://github.com/asmyshlyaev177/state-in-url/tree/master/packages/urlstate/react-router/useUrlState#updateurl}
|
|
54
54
|
*/
|
|
55
|
-
setUrl: (value?: Parameters<(value?: Partial<T> |
|
|
55
|
+
setUrl: (value?: Parameters<(value?: Partial<T> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: NavigateOptions) => void;
|
|
56
56
|
/**
|
|
57
57
|
* @deprecated use `setUrl`
|
|
58
58
|
*/
|
|
59
|
-
updateUrl: (value?: Parameters<(value?: Partial<T> |
|
|
60
|
-
|
|
59
|
+
updateUrl: (value?: Parameters<(value?: Partial<T> | ((currState: T) => T) | undefined, options?: import("../../useUrlStateBase/useUrlStateBase").Options) => void>[0], options?: NavigateOptions) => void;
|
|
60
|
+
/**
|
|
61
|
+
* State object. Don't mutate directly, use `setState` or `setUrl`
|
|
62
|
+
*/
|
|
63
|
+
urlState: T;
|
|
61
64
|
/**
|
|
62
65
|
* @deprecated use `urlState`
|
|
63
66
|
*/
|
|
64
|
-
state:
|
|
67
|
+
state: T;
|
|
65
68
|
getState: () => T;
|
|
66
69
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"react";import{useNavigate as e,useSearchParams as r}from"react-router-dom";import{parseSPObj as a}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{routerHistory as o,filterUnknownParamsClient as u,assignValue as m,filterUnknownParams as p}from"../../utils.mjs";function l({defaultState:l,useHistory:S,...f}){const i=e(),n=t.useMemo((()=>S?o:{replace:(t,e)=>i(t,{...c,...f,...e}),push:(t,e)=>i(t,{...c,...f,...e})}),[i,f]),{state:d,updateState:j,updateUrl:U,getState:b}=s(l,n,(({parse:t})=>t(u(l)))),g=t.useCallback(((t,e)=>{
|
|
1
|
+
import t from"react";import{useNavigate as e,useSearchParams as r}from"react-router-dom";import{parseSPObj as a}from"../../parseSPObj.mjs";import{useUrlStateBase as s}from"../../useUrlStateBase/useUrlStateBase.mjs";import{routerHistory as o,filterUnknownParamsClient as u,assignValue as m,filterUnknownParams as p}from"../../utils.mjs";function l({defaultState:l,useHistory:S,...f}){const i=e(),n=t.useMemo((()=>S?o:{replace:(t,e)=>i(t,{...c,...f,...e}),push:(t,e)=>i(t,{...c,...f,...e})}),[i,f]),{state:d,updateState:j,updateUrl:U,getState:b}=s(l,n,(({parse:t})=>t(u(l)))),g=t.useCallback(((t,e)=>U(t,{...c,...f,...e})),[f]),[B]=r();return t.useEffect((()=>{j(m(l,d,p(l,a(Object.fromEntries([...B.entries()]),l))))}),[B]),{setState:j,updateState:j,setUrl:g,updateUrl:g,urlState:d,state:d,getState:b}}const c={replace:!0,preventScrollReset:!0};export{l as useUrlState};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type JSONCompatible } from "../utils";
|
|
2
2
|
/**
|
|
3
3
|
* Custom React hook for sharing state between unrelated components.
|
|
4
4
|
*
|
|
@@ -20,5 +20,5 @@ import { type DeepReadonly, type JSONCompatible } from "../utils";
|
|
|
20
20
|
export declare function useSharedState<T extends JSONCompatible>(defaultState: T, _getInitial?: () => T): {
|
|
21
21
|
state: T;
|
|
22
22
|
getState: () => T;
|
|
23
|
-
setState: (value:
|
|
23
|
+
setState: (value: Partial<T> | ((currState: T) => T)) => void;
|
|
24
24
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"react";import{stateMap as r,subscribers as e}from"../subscribers.mjs";import{useInsertionEffect as n}from"../useInsertionEffect.mjs";import{isSSR as u,isEqual as c}from"../utils.mjs";function s(s,o){const f=t.useRef(s),[a,i]=t.useState((()=>{if(u())return o?o?.():f.current;const t=r.get(f.current);if(t)return t;{const t=o?.()||f.current;return r.set(f.current,t),t}})),m=t.useCallback((t=>{const n=r.get(f.current),u="function"==typeof t?t(n):{...n,...t};c(n,u)||(r.set(f.current,u),e.get(f.current).forEach((t=>
|
|
1
|
+
import t from"react";import{stateMap as r,subscribers as e}from"../subscribers.mjs";import{useInsertionEffect as n}from"../useInsertionEffect.mjs";import{isSSR as u,isEqual as c}from"../utils.mjs";function s(s,o){const f=t.useRef(s),[a,i]=t.useState((()=>{if(u())return o?o?.():f.current;const t=r.get(f.current);if(t)return t;{const t=o?.()||f.current;return r.set(f.current,t),t}})),m=t.useCallback((t=>{const n=r.get(f.current),u="function"==typeof t?t(n):{...n,...t};c(n,u)||(r.set(f.current,u),e.get(f.current).forEach((t=>t())))}),[]);n((()=>{const t=e.add(f.current,(()=>{i(r.get(f.current)||f.current)}));return()=>{t()}}),[]);return{state:a,getState:t.useCallback((()=>r.get(f.current)||f.current),[]),setState:m}}export{s as useSharedState};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"react";import{encodeState as
|
|
1
|
+
import t from"react";import{encodeState as e,decodeState as o}from"../encodeState/encodeState.mjs";import{typeOf as r}from"../utils.mjs";function a(a){const c=t.useCallback(((t,o)=>"object"===r(t)?e(t,a,o):""),[a]);return{parse:t.useCallback((t=>o(t,a)),[a]),stringify:c}}export{a as useUrlEncode};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useUrlEncode } from "../useUrlEncode";
|
|
2
|
-
import { type
|
|
2
|
+
import { type JSONCompatible, type Router } from "../utils";
|
|
3
3
|
/**
|
|
4
4
|
* A custom React hook to create custom hooks.
|
|
5
5
|
*
|
|
@@ -24,9 +24,9 @@ import { type DeepReadonly, type JSONCompatible, type Router } from "../utils";
|
|
|
24
24
|
export declare function useUrlStateBase<T extends JSONCompatible>(defaultState: T, router: Router, getInitialState?: ({ parse, }: {
|
|
25
25
|
parse: ReturnType<typeof useUrlEncode<T>>["parse"];
|
|
26
26
|
}) => T): {
|
|
27
|
-
updateState: (value: Partial<T> |
|
|
28
|
-
updateUrl: (value?: Parameters<(value: Partial<T> |
|
|
29
|
-
state:
|
|
27
|
+
updateState: (value: Partial<T> | ((currState: T) => T)) => void;
|
|
28
|
+
updateUrl: (value?: Parameters<(value: Partial<T> | ((currState: T) => T)) => void>[0], options?: Options) => void;
|
|
29
|
+
state: T;
|
|
30
30
|
getState: () => T;
|
|
31
31
|
};
|
|
32
32
|
interface OptionsObject {
|
package/dist/utils.d.ts
CHANGED
|
@@ -15,9 +15,6 @@ export type JSON = null | boolean | Date | number | string | {
|
|
|
15
15
|
export type JSONCompatible = {
|
|
16
16
|
[prop: string]: JSON | JSON[];
|
|
17
17
|
};
|
|
18
|
-
export type DeepReadonly<T> = T extends Map<infer K, infer V> ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>> : T extends Set<infer S> ? ReadonlySet<DeepReadonly<S>> : T extends object ? {
|
|
19
|
-
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
20
|
-
} : T;
|
|
21
18
|
export declare const getParams: (strOrSearchParams?: string | URLSearchParams) => URLSearchParams;
|
|
22
19
|
export type UnknownObj = object | {
|
|
23
20
|
[key: string]: unknown;
|
package/package.json
CHANGED
|
@@ -1,32 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "state-in-url",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.5",
|
|
4
4
|
"description": "Easily share complex state objects between unrelated React components, preserve types and structure, with TS validation. Deep links and url state synchronization wthout any hasssle or boilerplate.",
|
|
5
5
|
"homepage": "https://state-in-url.dev",
|
|
6
|
-
"keywords": [
|
|
7
|
-
"front-end",
|
|
8
|
-
"state-management",
|
|
9
|
-
"state management",
|
|
10
|
-
"deep links",
|
|
11
|
-
"deep linking",
|
|
12
|
-
"url synchronization",
|
|
13
|
-
"useUrlState",
|
|
14
|
-
"state in url",
|
|
15
|
-
"client components communication",
|
|
16
|
-
"query string",
|
|
17
|
-
"search params",
|
|
18
|
-
"query params",
|
|
19
|
-
"typescript",
|
|
20
|
-
"workflow",
|
|
21
|
-
"javascript",
|
|
22
|
-
"hooks",
|
|
23
|
-
"react.js",
|
|
24
|
-
"reactjs",
|
|
25
|
-
"react",
|
|
26
|
-
"NextJS",
|
|
27
|
-
"Next.js",
|
|
28
|
-
"nuqs alternative"
|
|
29
|
-
],
|
|
30
6
|
"repository": {
|
|
31
7
|
"type": "git",
|
|
32
8
|
"url": "git+https://github.com/asmyshlyaev177/state-in-url.git"
|
|
@@ -127,6 +103,7 @@
|
|
|
127
103
|
"reinstall": "npm run cleanup && npm install",
|
|
128
104
|
"setup": "playwright install --with-deps",
|
|
129
105
|
"prepack": "npm run build && cp package.json dist/package.json && npm run build:demo",
|
|
106
|
+
"pin-gh-deps": "pin-github-action .github/workflows/tests.yml",
|
|
130
107
|
"prepare": "npx husky"
|
|
131
108
|
},
|
|
132
109
|
"wireit": {
|
|
@@ -387,6 +364,7 @@
|
|
|
387
364
|
"jest-environment-jsdom": "^29.7.0",
|
|
388
365
|
"lint-staged": "^15.2.9",
|
|
389
366
|
"only-allow": "^1.2.1",
|
|
367
|
+
"pin-github-action": "^1.9.1",
|
|
390
368
|
"playwright": "^1.48.2",
|
|
391
369
|
"prettier": "^3.2.5",
|
|
392
370
|
"prettier-plugin-tailwindcss": "^0.6.8",
|
|
@@ -402,5 +380,31 @@
|
|
|
402
380
|
"wait-on": "^8.0.1",
|
|
403
381
|
"wireit": "^0.14.9"
|
|
404
382
|
},
|
|
383
|
+
"keywords": [
|
|
384
|
+
"front-end",
|
|
385
|
+
"state-management",
|
|
386
|
+
"state management",
|
|
387
|
+
"deep links",
|
|
388
|
+
"deep linking",
|
|
389
|
+
"url synchronization",
|
|
390
|
+
"useUrlState",
|
|
391
|
+
"state in url",
|
|
392
|
+
"client components communication",
|
|
393
|
+
"query string",
|
|
394
|
+
"search params",
|
|
395
|
+
"query params",
|
|
396
|
+
"typescript",
|
|
397
|
+
"workflow",
|
|
398
|
+
"javascript",
|
|
399
|
+
"hooks",
|
|
400
|
+
"react.js",
|
|
401
|
+
"reactjs",
|
|
402
|
+
"react",
|
|
403
|
+
"NextJS",
|
|
404
|
+
"Next.js",
|
|
405
|
+
"nuqs alternative",
|
|
406
|
+
"query params parser",
|
|
407
|
+
"query params parsing"
|
|
408
|
+
],
|
|
405
409
|
"packageManager": "npm@10.8.2"
|
|
406
410
|
}
|