diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e8738a3434..ee522ce49c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -91,7 +91,7 @@ jobs: - name: Install build artifact run: yarn workspace @reduxjs/toolkit add $(pwd)/package.tgz - - run: sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json ./vitest.config.ts ./src/tests/*.* ./src/query/tests/*.* + - run: sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json ./vitest.config.mts ./src/tests/*.* ./src/query/tests/*.* - name: Run tests, against dist run: yarn test @@ -133,7 +133,7 @@ jobs: - name: Show installed RTK versions run: yarn info @reduxjs/toolkit - - run: sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json ./vitest.config.ts ./src/tests/*.* ./src/query/tests/*.* + - run: sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json ./vitest.config.mts ./src/tests/*.* ./src/query/tests/*.* - name: Test types run: | @@ -149,7 +149,17 @@ jobs: fail-fast: false matrix: node: ['18.x'] - example: ['cra4', 'cra5', 'next', 'vite', 'node-standard', 'node-esm', 'expo'] + example: + [ + 'cra4', + 'cra5', + 'next', + 'vite', + 'node-standard', + 'node-esm', + 'react-native', + 'expo', + ] defaults: run: working-directory: ./examples/publish-ci/${{ matrix.example }} diff --git a/.gitignore b/.gitignore index e8e2cc51d3..a8309316f0 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ typesversions !.yarn/versions .pnp.* *.tgz + +tsconfig.vitest-temp.json \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json index 61ca55dbb6..6ef9e41d05 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -3,4 +3,3 @@ "singleQuote": true, "endOfLine": "auto" } - \ No newline at end of file diff --git a/.yarn/patches/msw-npm-0.40.2-2107d48752 b/.yarn/patches/msw-npm-0.40.2-2107d48752 deleted file mode 100644 index d25dca19e4..0000000000 --- a/.yarn/patches/msw-npm-0.40.2-2107d48752 +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/lib/types/context/set.d.ts b/lib/types/context/set.d.ts -index 266229bad706ec49392b8b87e18560c1566b490d..4fad485f8ffec2db92e808a05ccd9274414a9bd9 100644 ---- a/lib/types/context/set.d.ts -+++ b/lib/types/context/set.d.ts -@@ -15,4 +15,5 @@ export declare type ForbiddenHeaderError = `SafeRespo - * }) - * @see {@link https://mswjs.io/docs/api/context/set `ctx.set()`} - */ -+// @ts-ignore - export declare function set(...args: N extends string ? Lowercase extends ForbiddenHeaderNames ? ForbiddenHeaderError : [N, string] : N extends HeadersObject ? Lowercase extends ForbiddenHeaderNames ? ForbiddenHeaderError : [N] : [N]): ResponseTransformer; -diff --git a/lib/types/sharedOptions.d.ts b/lib/types/sharedOptions.d.ts -index d1d6e05df2dc2c29f06d8d0b91c500a10e651a29..3d8c29fd2089b2abf21d78cd277aac9271e781c2 100644 ---- a/lib/types/sharedOptions.d.ts -+++ b/lib/types/sharedOptions.d.ts -@@ -21,4 +21,5 @@ export interface LifeCycleEventsMap { - 'response:bypass': (response: ResponseType, requestId: string) => void; - unhandledException: (error: Error, request: MockedRequest) => void; - } -+// @ts-ignore - export declare type LifeCycleEventEmitter = Pick, 'on' | 'removeListener' | 'removeAllListeners'>; diff --git a/.yarn/releases/yarn-3.2.4.cjs b/.yarn/releases/yarn-3.2.4.cjs index 38f17fd49e..f607954682 100644 --- a/.yarn/releases/yarn-3.2.4.cjs +++ b/.yarn/releases/yarn-3.2.4.cjs @@ -1,7 +1,7 @@ #!/usr/bin/env node /* eslint-disable */ //prettier-ignore -(()=>{var nfe=Object.create;var HS=Object.defineProperty;var sfe=Object.getOwnPropertyDescriptor;var ofe=Object.getOwnPropertyNames;var afe=Object.getPrototypeOf,Afe=Object.prototype.hasOwnProperty;var J=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+r+'" is not supported')});var y=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),ht=(r,e)=>{for(var t in e)HS(r,t,{get:e[t],enumerable:!0})},lfe=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ofe(e))!Afe.call(r,n)&&n!==t&&HS(r,n,{get:()=>e[n],enumerable:!(i=sfe(e,n))||i.enumerable});return r};var ne=(r,e,t)=>(t=r!=null?nfe(afe(r)):{},lfe(e||!r||!r.__esModule?HS(t,"default",{value:r,enumerable:!0}):t,r));var ZU=y(($_e,_U)=>{_U.exports=XU;XU.sync=Dfe;var zU=J("fs");function Pfe(r,e){var t=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT;if(!t||(t=t.split(";"),t.indexOf("")!==-1))return!0;for(var i=0;i{r1.exports=e1;e1.sync=kfe;var $U=J("fs");function e1(r,e,t){$U.stat(r,function(i,n){t(i,i?!1:t1(n,e))})}function kfe(r,e){return t1($U.statSync(r),e)}function t1(r,e){return r.isFile()&&Rfe(r,e)}function Rfe(r,e){var t=r.mode,i=r.uid,n=r.gid,s=e.uid!==void 0?e.uid:process.getuid&&process.getuid(),o=e.gid!==void 0?e.gid:process.getgid&&process.getgid(),a=parseInt("100",8),l=parseInt("010",8),c=parseInt("001",8),u=a|l,g=t&c||t&l&&n===o||t&a&&i===s||t&u&&s===0;return g}});var s1=y((rZe,n1)=>{var tZe=J("fs"),RI;process.platform==="win32"||global.TESTING_WINDOWS?RI=ZU():RI=i1();n1.exports=nv;nv.sync=Ffe;function nv(r,e,t){if(typeof e=="function"&&(t=e,e={}),!t){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(i,n){nv(r,e||{},function(s,o){s?n(s):i(o)})})}RI(r,e||{},function(i,n){i&&(i.code==="EACCES"||e&&e.ignoreErrors)&&(i=null,n=!1),t(i,n)})}function Ffe(r,e){try{return RI.sync(r,e||{})}catch(t){if(e&&e.ignoreErrors||t.code==="EACCES")return!1;throw t}}});var g1=y((iZe,u1)=>{var Xg=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",o1=J("path"),Nfe=Xg?";":":",a1=s1(),A1=r=>Object.assign(new Error(`not found: ${r}`),{code:"ENOENT"}),l1=(r,e)=>{let t=e.colon||Nfe,i=r.match(/\//)||Xg&&r.match(/\\/)?[""]:[...Xg?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(t)],n=Xg?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",s=Xg?n.split(t):[""];return Xg&&r.indexOf(".")!==-1&&s[0]!==""&&s.unshift(""),{pathEnv:i,pathExt:s,pathExtExe:n}},c1=(r,e,t)=>{typeof e=="function"&&(t=e,e={}),e||(e={});let{pathEnv:i,pathExt:n,pathExtExe:s}=l1(r,e),o=[],a=c=>new Promise((u,g)=>{if(c===i.length)return e.all&&o.length?u(o):g(A1(r));let f=i[c],h=/^".*"$/.test(f)?f.slice(1,-1):f,p=o1.join(h,r),m=!h&&/^\.[\\\/]/.test(r)?r.slice(0,2)+p:p;u(l(m,c,0))}),l=(c,u,g)=>new Promise((f,h)=>{if(g===n.length)return f(a(u+1));let p=n[g];a1(c+p,{pathExt:s},(m,w)=>{if(!m&&w)if(e.all)o.push(c+p);else return f(c+p);return f(l(c,u,g+1))})});return t?a(0).then(c=>t(null,c),t):a(0)},Lfe=(r,e)=>{e=e||{};let{pathEnv:t,pathExt:i,pathExtExe:n}=l1(r,e),s=[];for(let o=0;o{"use strict";var f1=(r={})=>{let e=r.env||process.env;return(r.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(i=>i.toUpperCase()==="PATH")||"Path"};sv.exports=f1;sv.exports.default=f1});var m1=y((sZe,C1)=>{"use strict";var p1=J("path"),Tfe=g1(),Ofe=h1();function d1(r,e){let t=r.options.env||process.env,i=process.cwd(),n=r.options.cwd!=null,s=n&&process.chdir!==void 0&&!process.chdir.disabled;if(s)try{process.chdir(r.options.cwd)}catch{}let o;try{o=Tfe.sync(r.command,{path:t[Ofe({env:t})],pathExt:e?p1.delimiter:void 0})}catch{}finally{s&&process.chdir(i)}return o&&(o=p1.resolve(n?r.options.cwd:"",o)),o}function Mfe(r){return d1(r)||d1(r,!0)}C1.exports=Mfe});var E1=y((oZe,av)=>{"use strict";var ov=/([()\][%!^"`<>&|;, *?])/g;function Kfe(r){return r=r.replace(ov,"^$1"),r}function Ufe(r,e){return r=`${r}`,r=r.replace(/(\\*)"/g,'$1$1\\"'),r=r.replace(/(\\*)$/,"$1$1"),r=`"${r}"`,r=r.replace(ov,"^$1"),e&&(r=r.replace(ov,"^$1")),r}av.exports.command=Kfe;av.exports.argument=Ufe});var y1=y((aZe,I1)=>{"use strict";I1.exports=/^#!(.*)/});var B1=y((AZe,w1)=>{"use strict";var Hfe=y1();w1.exports=(r="")=>{let e=r.match(Hfe);if(!e)return null;let[t,i]=e[0].replace(/#! ?/,"").split(" "),n=t.split("/").pop();return n==="env"?i:i?`${n} ${i}`:n}});var b1=y((lZe,Q1)=>{"use strict";var Av=J("fs"),Gfe=B1();function Yfe(r){let t=Buffer.alloc(150),i;try{i=Av.openSync(r,"r"),Av.readSync(i,t,0,150,0),Av.closeSync(i)}catch{}return Gfe(t.toString())}Q1.exports=Yfe});var P1=y((cZe,x1)=>{"use strict";var jfe=J("path"),S1=m1(),v1=E1(),qfe=b1(),Jfe=process.platform==="win32",Wfe=/\.(?:com|exe)$/i,zfe=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function Vfe(r){r.file=S1(r);let e=r.file&&qfe(r.file);return e?(r.args.unshift(r.file),r.command=e,S1(r)):r.file}function Xfe(r){if(!Jfe)return r;let e=Vfe(r),t=!Wfe.test(e);if(r.options.forceShell||t){let i=zfe.test(e);r.command=jfe.normalize(r.command),r.command=v1.command(r.command),r.args=r.args.map(s=>v1.argument(s,i));let n=[r.command].concat(r.args).join(" ");r.args=["/d","/s","/c",`"${n}"`],r.command=process.env.comspec||"cmd.exe",r.options.windowsVerbatimArguments=!0}return r}function _fe(r,e,t){e&&!Array.isArray(e)&&(t=e,e=null),e=e?e.slice(0):[],t=Object.assign({},t);let i={command:r,args:e,options:t,file:void 0,original:{command:r,args:e}};return t.shell?i:Xfe(i)}x1.exports=_fe});var R1=y((uZe,k1)=>{"use strict";var lv=process.platform==="win32";function cv(r,e){return Object.assign(new Error(`${e} ${r.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${e} ${r.command}`,path:r.command,spawnargs:r.args})}function Zfe(r,e){if(!lv)return;let t=r.emit;r.emit=function(i,n){if(i==="exit"){let s=D1(n,e,"spawn");if(s)return t.call(r,"error",s)}return t.apply(r,arguments)}}function D1(r,e){return lv&&r===1&&!e.file?cv(e.original,"spawn"):null}function $fe(r,e){return lv&&r===1&&!e.file?cv(e.original,"spawnSync"):null}k1.exports={hookChildProcess:Zfe,verifyENOENT:D1,verifyENOENTSync:$fe,notFoundError:cv}});var fv=y((gZe,_g)=>{"use strict";var F1=J("child_process"),uv=P1(),gv=R1();function N1(r,e,t){let i=uv(r,e,t),n=F1.spawn(i.command,i.args,i.options);return gv.hookChildProcess(n,i),n}function ehe(r,e,t){let i=uv(r,e,t),n=F1.spawnSync(i.command,i.args,i.options);return n.error=n.error||gv.verifyENOENTSync(n.status,i),n}_g.exports=N1;_g.exports.spawn=N1;_g.exports.sync=ehe;_g.exports._parse=uv;_g.exports._enoent=gv});var T1=y((fZe,L1)=>{"use strict";function the(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function cc(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,cc)}the(cc,Error);cc.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,f=1;g>",te=de(">>",!1),me=">&",tt=de(">&",!1),Rt=">",It=de(">",!1),Kr="<<<",oi=de("<<<",!1),pi="<&",pr=de("<&",!1),di="<",ai=de("<",!1),Os=function(C){return{type:"argument",segments:[].concat(...C)}},dr=function(C){return C},Bi="$'",_n=de("$'",!1),ga="'",CA=de("'",!1),Dg=function(C){return[{type:"text",text:C}]},Zn='""',mA=de('""',!1),fa=function(){return{type:"text",text:""}},jp='"',EA=de('"',!1),IA=function(C){return C},wr=function(C){return{type:"arithmetic",arithmetic:C,quoted:!0}},zl=function(C){return{type:"shell",shell:C,quoted:!0}},kg=function(C){return{type:"variable",...C,quoted:!0}},mo=function(C){return{type:"text",text:C}},Rg=function(C){return{type:"arithmetic",arithmetic:C,quoted:!1}},qp=function(C){return{type:"shell",shell:C,quoted:!1}},Jp=function(C){return{type:"variable",...C,quoted:!1}},xr=function(C){return{type:"glob",pattern:C}},oe=/^[^']/,Eo=Ye(["'"],!0,!1),Dn=function(C){return C.join("")},Fg=/^[^$"]/,Qt=Ye(["$",'"'],!0,!1),Vl=`\\ +;(()=>{var nfe=Object.create;var HS=Object.defineProperty;var sfe=Object.getOwnPropertyDescriptor;var ofe=Object.getOwnPropertyNames;var afe=Object.getPrototypeOf,Afe=Object.prototype.hasOwnProperty;var J=(r=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(r,{get:(e,t)=>(typeof require<"u"?require:e)[t]}):r)(function(r){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+r+'" is not supported')});var y=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),ht=(r,e)=>{for(var t in e)HS(r,t,{get:e[t],enumerable:!0})},lfe=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ofe(e))!Afe.call(r,n)&&n!==t&&HS(r,n,{get:()=>e[n],enumerable:!(i=sfe(e,n))||i.enumerable});return r};var ne=(r,e,t)=>(t=r!=null?nfe(afe(r)):{},lfe(e||!r||!r.__esModule?HS(t,"default",{value:r,enumerable:!0}):t,r));var ZU=y(($_e,_U)=>{_U.exports=XU;XU.sync=Dfe;var zU=J("fs");function Pfe(r,e){var t=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT;if(!t||(t=t.split(";"),t.indexOf("")!==-1))return!0;for(var i=0;i{r1.exports=e1;e1.sync=kfe;var $U=J("fs");function e1(r,e,t){$U.stat(r,function(i,n){t(i,i?!1:t1(n,e))})}function kfe(r,e){return t1($U.statSync(r),e)}function t1(r,e){return r.isFile()&&Rfe(r,e)}function Rfe(r,e){var t=r.mode,i=r.uid,n=r.gid,s=e.uid!==void 0?e.uid:process.getuid&&process.getuid(),o=e.gid!==void 0?e.gid:process.getgid&&process.getgid(),a=parseInt("100",8),l=parseInt("010",8),c=parseInt("001",8),u=a|l,g=t&c||t&l&&n===o||t&a&&i===s||t&u&&s===0;return g}});var s1=y((rZe,n1)=>{var tZe=J("fs"),RI;process.platform==="win32"||global.TESTING_WINDOWS?RI=ZU():RI=i1();n1.exports=nv;nv.sync=Ffe;function nv(r,e,t){if(typeof e=="function"&&(t=e,e={}),!t){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(i,n){nv(r,e||{},function(s,o){s?n(s):i(o)})})}RI(r,e||{},function(i,n){i&&(i.code==="EACCES"||e&&e.ignoreErrors)&&(i=null,n=!1),t(i,n)})}function Ffe(r,e){try{return RI.sync(r,e||{})}catch(t){if(e&&e.ignoreErrors||t.code==="EACCES")return!1;throw t}}});var g1=y((iZe,u1)=>{var Xg=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",o1=J("path"),Nfe=Xg?";":":",a1=s1(),A1=r=>Object.assign(new Error(`not found: ${r}`),{code:"ENOENT"}),l1=(r,e)=>{let t=e.colon||Nfe,i=r.match(/\//)||Xg&&r.match(/\\/)?[""]:[...Xg?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(t)],n=Xg?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",s=Xg?n.split(t):[""];return Xg&&r.indexOf(".")!==-1&&s[0]!==""&&s.unshift(""),{pathEnv:i,pathExt:s,pathExtExe:n}},c1=(r,e,t)=>{typeof e=="function"&&(t=e,e={}),e||(e={});let{pathEnv:i,pathExt:n,pathExtExe:s}=l1(r,e),o=[],a=c=>new Promise((u,g)=>{if(c===i.length)return e.all&&o.length?u(o):g(A1(r));let f=i[c],h=/^".*"$/.test(f)?f.slice(1,-1):f,p=o1.join(h,r),m=!h&&/^\.[\\\/]/.test(r)?r.slice(0,2)+p:p;u(l(m,c,0))}),l=(c,u,g)=>new Promise((f,h)=>{if(g===n.length)return f(a(u+1));let p=n[g];a1(c+p,{pathExt:s},(m,w)=>{if(!m&&w)if(e.all)o.push(c+p);else return f(c+p);return f(l(c,u,g+1))})});return t?a(0).then(c=>t(null,c),t):a(0)},Lfe=(r,e)=>{e=e||{};let{pathEnv:t,pathExt:i,pathExtExe:n}=l1(r,e),s=[];for(let o=0;o{"use strict";var f1=(r={})=>{let e=r.env||process.env;return(r.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(i=>i.toUpperCase()==="PATH")||"Path"};sv.exports=f1;sv.exports.default=f1});var m1=y((sZe,C1)=>{"use strict";var p1=J("path"),Tfe=g1(),Ofe=h1();function d1(r,e){let t=r.options.env||process.env,i=process.cwd(),n=r.options.cwd!=null,s=n&&process.chdir!==void 0&&!process.chdir.disabled;if(s)try{process.chdir(r.options.cwd)}catch{}let o;try{o=Tfe.sync(r.command,{path:t[Ofe({env:t})],pathExt:e?p1.delimiter:void 0})}catch{}finally{s&&process.chdir(i)}return o&&(o=p1.resolve(n?r.options.cwd:"",o)),o}function Mfe(r){return d1(r)||d1(r,!0)}C1.exports=Mfe});var E1=y((oZe,av)=>{"use strict";var ov=/([()\][%!^"`<>&|;, *?])/g;function Kfe(r){return r=r.replace(ov,"^$1"),r}function Ufe(r,e){return r=`${r}`,r=r.replace(/(\\*)"/g,'$1$1\\"'),r=r.replace(/(\\*)$/,"$1$1"),r=`"${r}"`,r=r.replace(ov,"^$1"),e&&(r=r.replace(ov,"^$1")),r}av.exports.command=Kfe;av.exports.argument=Ufe});var y1=y((aZe,I1)=>{"use strict";I1.exports=/^#!(.*)/});var B1=y((AZe,w1)=>{"use strict";var Hfe=y1();w1.exports=(r="")=>{let e=r.match(Hfe);if(!e)return null;let[t,i]=e[0].replace(/#! ?/,"").split(" "),n=t.split("/").pop();return n==="env"?i:i?`${n} ${i}`:n}});var b1=y((lZe,Q1)=>{"use strict";var Av=J("fs"),Gfe=B1();function Yfe(r){let t=Buffer.alloc(150),i;try{i=Av.openSync(r,"r"),Av.readSync(i,t,0,150,0),Av.closeSync(i)}catch{}return Gfe(t.toString())}Q1.exports=Yfe});var P1=y((cZe,x1)=>{"use strict";var jfe=J("path"),S1=m1(),v1=E1(),qfe=b1(),Jfe=process.platform==="win32",Wfe=/\.(?:com|exe)$/i,zfe=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function Vfe(r){r.file=S1(r);let e=r.file&&qfe(r.file);return e?(r.args.unshift(r.file),r.command=e,S1(r)):r.file}function Xfe(r){if(!Jfe)return r;let e=Vfe(r),t=!Wfe.test(e);if(r.options.forceShell||t){let i=zfe.test(e);r.command=jfe.normalize(r.command),r.command=v1.command(r.command),r.args=r.args.map(s=>v1.argument(s,i));let n=[r.command].concat(r.args).join(" ");r.args=["/d","/s","/c",`"${n}"`],r.command=process.env.comspec||"cmd.exe",r.options.windowsVerbatimArguments=!0}return r}function _fe(r,e,t){e&&!Array.isArray(e)&&(t=e,e=null),e=e?e.slice(0):[],t=Object.assign({},t);let i={command:r,args:e,options:t,file:void 0,original:{command:r,args:e}};return t.shell?i:Xfe(i)}x1.exports=_fe});var R1=y((uZe,k1)=>{"use strict";var lv=process.platform==="win32";function cv(r,e){return Object.assign(new Error(`${e} ${r.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${e} ${r.command}`,path:r.command,spawnargs:r.args})}function Zfe(r,e){if(!lv)return;let t=r.emit;r.emit=function(i,n){if(i==="exit"){let s=D1(n,e,"spawn");if(s)return t.call(r,"error",s)}return t.apply(r,arguments)}}function D1(r,e){return lv&&r===1&&!e.file?cv(e.original,"spawn"):null}function $fe(r,e){return lv&&r===1&&!e.file?cv(e.original,"spawnSync"):null}k1.exports={hookChildProcess:Zfe,verifyENOENT:D1,verifyENOENTSync:$fe,notFoundError:cv}});var fv=y((gZe,_g)=>{"use strict";var F1=J("child_process"),uv=P1(),gv=R1();function N1(r,e,t){let i=uv(r,e,t),n=F1.spawn(i.command,i.args,i.options);return gv.hookChildProcess(n,i),n}function ehe(r,e,t){let i=uv(r,e,t),n=F1.spawnSync(i.command,i.args,i.options);return n.error=n.error||gv.verifyENOENTSync(n.status,i),n}_g.exports=N1;_g.exports.spawn=N1;_g.exports.sync=ehe;_g.exports._parse=uv;_g.exports._enoent=gv});var T1=y((fZe,L1)=>{"use strict";function the(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function cc(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,cc)}the(cc,Error);cc.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,f=1;g>",te=de(">>",!1),me=">&",tt=de(">&",!1),Rt=">",It=de(">",!1),Kr="<<<",oi=de("<<<",!1),pi="<&",pr=de("<&",!1),di="<",ai=de("<",!1),Os=function(C){return{type:"argument",segments:[].concat(...C)}},dr=function(C){return C},Bi="$'",_n=de("$'",!1),ga="'",CA=de("'",!1),Dg=function(C){return[{type:"text",text:C}]},Zn='""',mA=de('""',!1),fa=function(){return{type:"text",text:""}},jp='"',EA=de('"',!1),IA=function(C){return C},wr=function(C){return{type:"arithmetic",arithmetic:C,quoted:!0}},zl=function(C){return{type:"shell",shell:C,quoted:!0}},kg=function(C){return{type:"variable",...C,quoted:!0}},mo=function(C){return{type:"text",text:C}},Rg=function(C){return{type:"arithmetic",arithmetic:C,quoted:!1}},qp=function(C){return{type:"shell",shell:C,quoted:!1}},Jp=function(C){return{type:"variable",...C,quoted:!1}},xr=function(C){return{type:"glob",pattern:C}},oe=/^[^']/,Eo=Ye(["'"],!0,!1),Dn=function(C){return C.join("")},Fg=/^[^$"]/,Qt=Ye(["$",'"'],!0,!1),Vl=`\\ `,kn=de(`\\ `,!1),$n=function(){return""},es="\\",ut=de("\\",!1),Io=/^[\\$"`]/,at=Ye(["\\","$",'"',"`"],!1,!1),ln=function(C){return C},S="\\a",Tt=de("\\a",!1),Ng=function(){return"a"},Xl="\\b",Wp=de("\\b",!1),zp=function(){return"\b"},Vp=/^[Ee]/,Xp=Ye(["E","e"],!1,!1),_p=function(){return"\x1B"},G="\\f",yt=de("\\f",!1),yA=function(){return"\f"},Wi="\\n",_l=de("\\n",!1),We=function(){return` `},ha="\\r",Lg=de("\\r",!1),oI=function(){return"\r"},Zp="\\t",aI=de("\\t",!1),ar=function(){return" "},Rn="\\v",Zl=de("\\v",!1),$p=function(){return"\v"},Ms=/^[\\'"?]/,pa=Ye(["\\","'",'"',"?"],!1,!1),cn=function(C){return String.fromCharCode(parseInt(C,16))},De="\\x",Tg=de("\\x",!1),$l="\\u",Ks=de("\\u",!1),ec="\\U",wA=de("\\U",!1),Og=function(C){return String.fromCodePoint(parseInt(C,16))},Mg=/^[0-7]/,da=Ye([["0","7"]],!1,!1),Ca=/^[0-9a-fA-f]/,$e=Ye([["0","9"],["a","f"],["A","f"]],!1,!1),yo=rt(),BA="-",tc=de("-",!1),Us="+",rc=de("+",!1),AI=".",ed=de(".",!1),Kg=function(C,b,N){return{type:"number",value:(C==="-"?-1:1)*parseFloat(b.join("")+"."+N.join(""))}},td=function(C,b){return{type:"number",value:(C==="-"?-1:1)*parseInt(b.join(""))}},lI=function(C){return{type:"variable",...C}},ic=function(C){return{type:"variable",name:C}},cI=function(C){return C},Ug="*",QA=de("*",!1),Rr="/",uI=de("/",!1),Hs=function(C,b,N){return{type:b==="*"?"multiplication":"division",right:N}},Gs=function(C,b){return b.reduce((N,U)=>({left:N,...U}),C)},Hg=function(C,b,N){return{type:b==="+"?"addition":"subtraction",right:N}},bA="$((",R=de("$((",!1),q="))",pe=de("))",!1),Ne=function(C){return C},xe="$(",qe=de("$(",!1),dt=function(C){return C},Ft="${",Fn=de("${",!1),QS=":-",tU=de(":-",!1),rU=function(C,b){return{name:C,defaultValue:b}},bS=":-}",iU=de(":-}",!1),nU=function(C){return{name:C,defaultValue:[]}},SS=":+",sU=de(":+",!1),oU=function(C,b){return{name:C,alternativeValue:b}},vS=":+}",aU=de(":+}",!1),AU=function(C){return{name:C,alternativeValue:[]}},xS=function(C){return{name:C}},lU="$",cU=de("$",!1),uU=function(C){return e.isGlobPattern(C)},gU=function(C){return C},PS=/^[a-zA-Z0-9_]/,DS=Ye([["a","z"],["A","Z"],["0","9"],"_"],!1,!1),kS=function(){return O()},RS=/^[$@*?#a-zA-Z0-9_\-]/,FS=Ye(["$","@","*","?","#",["a","z"],["A","Z"],["0","9"],"_","-"],!1,!1),fU=/^[(){}<>$|&; \t"']/,Gg=Ye(["(",")","{","}","<",">","$","|","&",";"," "," ",'"',"'"],!1,!1),NS=/^[<>&; \t"']/,LS=Ye(["<",">","&",";"," "," ",'"',"'"],!1,!1),gI=/^[ \t]/,fI=Ye([" "," "],!1,!1),Q=0,Re=0,SA=[{line:1,column:1}],d=0,E=[],I=0,k;if("startRule"in e){if(!(e.startRule in i))throw new Error(`Can't start parsing from rule "`+e.startRule+'".');n=i[e.startRule]}function O(){return r.substring(Re,Q)}function X(){return Et(Re,Q)}function ee(C,b){throw b=b!==void 0?b:Et(Re,Q),Fi([At(C)],r.substring(Re,Q),b)}function ye(C,b){throw b=b!==void 0?b:Et(Re,Q),Nn(C,b)}function de(C,b){return{type:"literal",text:C,ignoreCase:b}}function Ye(C,b,N){return{type:"class",parts:C,inverted:b,ignoreCase:N}}function rt(){return{type:"any"}}function wt(){return{type:"end"}}function At(C){return{type:"other",description:C}}function et(C){var b=SA[C],N;if(b)return b;for(N=C-1;!SA[N];)N--;for(b=SA[N],b={line:b.line,column:b.column};Nd&&(d=Q,E=[]),E.push(C))}function Nn(C,b){return new cc(C,null,null,b)}function Fi(C,b,N){return new cc(cc.buildMessage(C,b),C,b,N)}function vA(){var C,b;return C=Q,b=Ur(),b===t&&(b=null),b!==t&&(Re=C,b=s(b)),C=b,C}function Ur(){var C,b,N,U,ce;if(C=Q,b=Hr(),b!==t){for(N=[],U=Me();U!==t;)N.push(U),U=Me();N!==t?(U=ma(),U!==t?(ce=ts(),ce===t&&(ce=null),ce!==t?(Re=C,b=o(b,U,ce),C=b):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t)}else Q=C,C=t;if(C===t)if(C=Q,b=Hr(),b!==t){for(N=[],U=Me();U!==t;)N.push(U),U=Me();N!==t?(U=ma(),U===t&&(U=null),U!==t?(Re=C,b=a(b,U),C=b):(Q=C,C=t)):(Q=C,C=t)}else Q=C,C=t;return C}function ts(){var C,b,N,U,ce;for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();if(b!==t)if(N=Ur(),N!==t){for(U=[],ce=Me();ce!==t;)U.push(ce),ce=Me();U!==t?(Re=C,b=l(N),C=b):(Q=C,C=t)}else Q=C,C=t;else Q=C,C=t;return C}function ma(){var C;return r.charCodeAt(Q)===59?(C=c,Q++):(C=t,I===0&&Be(u)),C===t&&(r.charCodeAt(Q)===38?(C=g,Q++):(C=t,I===0&&Be(f))),C}function Hr(){var C,b,N;return C=Q,b=hU(),b!==t?(N=Hge(),N===t&&(N=null),N!==t?(Re=C,b=h(b,N),C=b):(Q=C,C=t)):(Q=C,C=t),C}function Hge(){var C,b,N,U,ce,be,ft;for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();if(b!==t)if(N=Gge(),N!==t){for(U=[],ce=Me();ce!==t;)U.push(ce),ce=Me();if(U!==t)if(ce=Hr(),ce!==t){for(be=[],ft=Me();ft!==t;)be.push(ft),ft=Me();be!==t?(Re=C,b=p(N,ce),C=b):(Q=C,C=t)}else Q=C,C=t;else Q=C,C=t}else Q=C,C=t;else Q=C,C=t;return C}function Gge(){var C;return r.substr(Q,2)===m?(C=m,Q+=2):(C=t,I===0&&Be(w)),C===t&&(r.substr(Q,2)===B?(C=B,Q+=2):(C=t,I===0&&Be(v))),C}function hU(){var C,b,N;return C=Q,b=qge(),b!==t?(N=Yge(),N===t&&(N=null),N!==t?(Re=C,b=D(b,N),C=b):(Q=C,C=t)):(Q=C,C=t),C}function Yge(){var C,b,N,U,ce,be,ft;for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();if(b!==t)if(N=jge(),N!==t){for(U=[],ce=Me();ce!==t;)U.push(ce),ce=Me();if(U!==t)if(ce=hU(),ce!==t){for(be=[],ft=Me();ft!==t;)be.push(ft),ft=Me();be!==t?(Re=C,b=F(N,ce),C=b):(Q=C,C=t)}else Q=C,C=t;else Q=C,C=t}else Q=C,C=t;else Q=C,C=t;return C}function jge(){var C;return r.substr(Q,2)===H?(C=H,Q+=2):(C=t,I===0&&Be(j)),C===t&&(r.charCodeAt(Q)===124?(C=$,Q++):(C=t,I===0&&Be(z))),C}function hI(){var C,b,N,U,ce,be;if(C=Q,b=SU(),b!==t)if(r.charCodeAt(Q)===61?(N=W,Q++):(N=t,I===0&&Be(Z)),N!==t)if(U=CU(),U!==t){for(ce=[],be=Me();be!==t;)ce.push(be),be=Me();ce!==t?(Re=C,b=A(b,U),C=b):(Q=C,C=t)}else Q=C,C=t;else Q=C,C=t;else Q=C,C=t;if(C===t)if(C=Q,b=SU(),b!==t)if(r.charCodeAt(Q)===61?(N=W,Q++):(N=t,I===0&&Be(Z)),N!==t){for(U=[],ce=Me();ce!==t;)U.push(ce),ce=Me();U!==t?(Re=C,b=ae(b),C=b):(Q=C,C=t)}else Q=C,C=t;else Q=C,C=t;return C}function qge(){var C,b,N,U,ce,be,ft,Bt,Vr,Ci,rs;for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();if(b!==t)if(r.charCodeAt(Q)===40?(N=ue,Q++):(N=t,I===0&&Be(_)),N!==t){for(U=[],ce=Me();ce!==t;)U.push(ce),ce=Me();if(U!==t)if(ce=Ur(),ce!==t){for(be=[],ft=Me();ft!==t;)be.push(ft),ft=Me();if(be!==t)if(r.charCodeAt(Q)===41?(ft=T,Q++):(ft=t,I===0&&Be(L)),ft!==t){for(Bt=[],Vr=Me();Vr!==t;)Bt.push(Vr),Vr=Me();if(Bt!==t){for(Vr=[],Ci=rd();Ci!==t;)Vr.push(Ci),Ci=rd();if(Vr!==t){for(Ci=[],rs=Me();rs!==t;)Ci.push(rs),rs=Me();Ci!==t?(Re=C,b=ge(ce,Vr),C=b):(Q=C,C=t)}else Q=C,C=t}else Q=C,C=t}else Q=C,C=t;else Q=C,C=t}else Q=C,C=t;else Q=C,C=t}else Q=C,C=t;else Q=C,C=t;if(C===t){for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();if(b!==t)if(r.charCodeAt(Q)===123?(N=we,Q++):(N=t,I===0&&Be(Le)),N!==t){for(U=[],ce=Me();ce!==t;)U.push(ce),ce=Me();if(U!==t)if(ce=Ur(),ce!==t){for(be=[],ft=Me();ft!==t;)be.push(ft),ft=Me();if(be!==t)if(r.charCodeAt(Q)===125?(ft=Pe,Q++):(ft=t,I===0&&Be(Te)),ft!==t){for(Bt=[],Vr=Me();Vr!==t;)Bt.push(Vr),Vr=Me();if(Bt!==t){for(Vr=[],Ci=rd();Ci!==t;)Vr.push(Ci),Ci=rd();if(Vr!==t){for(Ci=[],rs=Me();rs!==t;)Ci.push(rs),rs=Me();Ci!==t?(Re=C,b=se(ce,Vr),C=b):(Q=C,C=t)}else Q=C,C=t}else Q=C,C=t}else Q=C,C=t;else Q=C,C=t}else Q=C,C=t;else Q=C,C=t}else Q=C,C=t;else Q=C,C=t;if(C===t){for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();if(b!==t){for(N=[],U=hI();U!==t;)N.push(U),U=hI();if(N!==t){for(U=[],ce=Me();ce!==t;)U.push(ce),ce=Me();if(U!==t){if(ce=[],be=dU(),be!==t)for(;be!==t;)ce.push(be),be=dU();else ce=t;if(ce!==t){for(be=[],ft=Me();ft!==t;)be.push(ft),ft=Me();be!==t?(Re=C,b=Ae(N,ce),C=b):(Q=C,C=t)}else Q=C,C=t}else Q=C,C=t}else Q=C,C=t}else Q=C,C=t;if(C===t){for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();if(b!==t){if(N=[],U=hI(),U!==t)for(;U!==t;)N.push(U),U=hI();else N=t;if(N!==t){for(U=[],ce=Me();ce!==t;)U.push(ce),ce=Me();U!==t?(Re=C,b=Qe(N),C=b):(Q=C,C=t)}else Q=C,C=t}else Q=C,C=t}}}return C}function pU(){var C,b,N,U,ce;for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();if(b!==t){if(N=[],U=pI(),U!==t)for(;U!==t;)N.push(U),U=pI();else N=t;if(N!==t){for(U=[],ce=Me();ce!==t;)U.push(ce),ce=Me();U!==t?(Re=C,b=fe(N),C=b):(Q=C,C=t)}else Q=C,C=t}else Q=C,C=t;return C}function dU(){var C,b,N;for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();if(b!==t?(N=rd(),N!==t?(Re=C,b=le(N),C=b):(Q=C,C=t)):(Q=C,C=t),C===t){for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();b!==t?(N=pI(),N!==t?(Re=C,b=le(N),C=b):(Q=C,C=t)):(Q=C,C=t)}return C}function rd(){var C,b,N,U,ce;for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();return b!==t?(Ge.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(ie)),N===t&&(N=null),N!==t?(U=Jge(),U!==t?(ce=pI(),ce!==t?(Re=C,b=Y(N,U,ce),C=b):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t),C}function Jge(){var C;return r.substr(Q,2)===he?(C=he,Q+=2):(C=t,I===0&&Be(te)),C===t&&(r.substr(Q,2)===me?(C=me,Q+=2):(C=t,I===0&&Be(tt)),C===t&&(r.charCodeAt(Q)===62?(C=Rt,Q++):(C=t,I===0&&Be(It)),C===t&&(r.substr(Q,3)===Kr?(C=Kr,Q+=3):(C=t,I===0&&Be(oi)),C===t&&(r.substr(Q,2)===pi?(C=pi,Q+=2):(C=t,I===0&&Be(pr)),C===t&&(r.charCodeAt(Q)===60?(C=di,Q++):(C=t,I===0&&Be(ai))))))),C}function pI(){var C,b,N;for(C=Q,b=[],N=Me();N!==t;)b.push(N),N=Me();return b!==t?(N=CU(),N!==t?(Re=C,b=le(N),C=b):(Q=C,C=t)):(Q=C,C=t),C}function CU(){var C,b,N;if(C=Q,b=[],N=mU(),N!==t)for(;N!==t;)b.push(N),N=mU();else b=t;return b!==t&&(Re=C,b=Os(b)),C=b,C}function mU(){var C,b;return C=Q,b=Wge(),b!==t&&(Re=C,b=dr(b)),C=b,C===t&&(C=Q,b=zge(),b!==t&&(Re=C,b=dr(b)),C=b,C===t&&(C=Q,b=Vge(),b!==t&&(Re=C,b=dr(b)),C=b,C===t&&(C=Q,b=Xge(),b!==t&&(Re=C,b=dr(b)),C=b))),C}function Wge(){var C,b,N,U;return C=Q,r.substr(Q,2)===Bi?(b=Bi,Q+=2):(b=t,I===0&&Be(_n)),b!==t?(N=$ge(),N!==t?(r.charCodeAt(Q)===39?(U=ga,Q++):(U=t,I===0&&Be(CA)),U!==t?(Re=C,b=Dg(N),C=b):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t),C}function zge(){var C,b,N,U;return C=Q,r.charCodeAt(Q)===39?(b=ga,Q++):(b=t,I===0&&Be(CA)),b!==t?(N=_ge(),N!==t?(r.charCodeAt(Q)===39?(U=ga,Q++):(U=t,I===0&&Be(CA)),U!==t?(Re=C,b=Dg(N),C=b):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t),C}function Vge(){var C,b,N,U;if(C=Q,r.substr(Q,2)===Zn?(b=Zn,Q+=2):(b=t,I===0&&Be(mA)),b!==t&&(Re=C,b=fa()),C=b,C===t)if(C=Q,r.charCodeAt(Q)===34?(b=jp,Q++):(b=t,I===0&&Be(EA)),b!==t){for(N=[],U=EU();U!==t;)N.push(U),U=EU();N!==t?(r.charCodeAt(Q)===34?(U=jp,Q++):(U=t,I===0&&Be(EA)),U!==t?(Re=C,b=IA(N),C=b):(Q=C,C=t)):(Q=C,C=t)}else Q=C,C=t;return C}function Xge(){var C,b,N;if(C=Q,b=[],N=IU(),N!==t)for(;N!==t;)b.push(N),N=IU();else b=t;return b!==t&&(Re=C,b=IA(b)),C=b,C}function EU(){var C,b;return C=Q,b=QU(),b!==t&&(Re=C,b=wr(b)),C=b,C===t&&(C=Q,b=bU(),b!==t&&(Re=C,b=zl(b)),C=b,C===t&&(C=Q,b=KS(),b!==t&&(Re=C,b=kg(b)),C=b,C===t&&(C=Q,b=Zge(),b!==t&&(Re=C,b=mo(b)),C=b))),C}function IU(){var C,b;return C=Q,b=QU(),b!==t&&(Re=C,b=Rg(b)),C=b,C===t&&(C=Q,b=bU(),b!==t&&(Re=C,b=qp(b)),C=b,C===t&&(C=Q,b=KS(),b!==t&&(Re=C,b=Jp(b)),C=b,C===t&&(C=Q,b=rfe(),b!==t&&(Re=C,b=xr(b)),C=b,C===t&&(C=Q,b=tfe(),b!==t&&(Re=C,b=mo(b)),C=b)))),C}function _ge(){var C,b,N;for(C=Q,b=[],oe.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(Eo));N!==t;)b.push(N),oe.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(Eo));return b!==t&&(Re=C,b=Dn(b)),C=b,C}function Zge(){var C,b,N;if(C=Q,b=[],N=yU(),N===t&&(Fg.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(Qt))),N!==t)for(;N!==t;)b.push(N),N=yU(),N===t&&(Fg.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(Qt)));else b=t;return b!==t&&(Re=C,b=Dn(b)),C=b,C}function yU(){var C,b,N;return C=Q,r.substr(Q,2)===Vl?(b=Vl,Q+=2):(b=t,I===0&&Be(kn)),b!==t&&(Re=C,b=$n()),C=b,C===t&&(C=Q,r.charCodeAt(Q)===92?(b=es,Q++):(b=t,I===0&&Be(ut)),b!==t?(Io.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(at)),N!==t?(Re=C,b=ln(N),C=b):(Q=C,C=t)):(Q=C,C=t)),C}function $ge(){var C,b,N;for(C=Q,b=[],N=wU(),N===t&&(oe.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(Eo)));N!==t;)b.push(N),N=wU(),N===t&&(oe.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(Eo)));return b!==t&&(Re=C,b=Dn(b)),C=b,C}function wU(){var C,b,N;return C=Q,r.substr(Q,2)===S?(b=S,Q+=2):(b=t,I===0&&Be(Tt)),b!==t&&(Re=C,b=Ng()),C=b,C===t&&(C=Q,r.substr(Q,2)===Xl?(b=Xl,Q+=2):(b=t,I===0&&Be(Wp)),b!==t&&(Re=C,b=zp()),C=b,C===t&&(C=Q,r.charCodeAt(Q)===92?(b=es,Q++):(b=t,I===0&&Be(ut)),b!==t?(Vp.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(Xp)),N!==t?(Re=C,b=_p(),C=b):(Q=C,C=t)):(Q=C,C=t),C===t&&(C=Q,r.substr(Q,2)===G?(b=G,Q+=2):(b=t,I===0&&Be(yt)),b!==t&&(Re=C,b=yA()),C=b,C===t&&(C=Q,r.substr(Q,2)===Wi?(b=Wi,Q+=2):(b=t,I===0&&Be(_l)),b!==t&&(Re=C,b=We()),C=b,C===t&&(C=Q,r.substr(Q,2)===ha?(b=ha,Q+=2):(b=t,I===0&&Be(Lg)),b!==t&&(Re=C,b=oI()),C=b,C===t&&(C=Q,r.substr(Q,2)===Zp?(b=Zp,Q+=2):(b=t,I===0&&Be(aI)),b!==t&&(Re=C,b=ar()),C=b,C===t&&(C=Q,r.substr(Q,2)===Rn?(b=Rn,Q+=2):(b=t,I===0&&Be(Zl)),b!==t&&(Re=C,b=$p()),C=b,C===t&&(C=Q,r.charCodeAt(Q)===92?(b=es,Q++):(b=t,I===0&&Be(ut)),b!==t?(Ms.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(pa)),N!==t?(Re=C,b=ln(N),C=b):(Q=C,C=t)):(Q=C,C=t),C===t&&(C=efe()))))))))),C}function efe(){var C,b,N,U,ce,be,ft,Bt,Vr,Ci,rs,US;return C=Q,r.charCodeAt(Q)===92?(b=es,Q++):(b=t,I===0&&Be(ut)),b!==t?(N=TS(),N!==t?(Re=C,b=cn(N),C=b):(Q=C,C=t)):(Q=C,C=t),C===t&&(C=Q,r.substr(Q,2)===De?(b=De,Q+=2):(b=t,I===0&&Be(Tg)),b!==t?(N=Q,U=Q,ce=TS(),ce!==t?(be=Ln(),be!==t?(ce=[ce,be],U=ce):(Q=U,U=t)):(Q=U,U=t),U===t&&(U=TS()),U!==t?N=r.substring(N,Q):N=U,N!==t?(Re=C,b=cn(N),C=b):(Q=C,C=t)):(Q=C,C=t),C===t&&(C=Q,r.substr(Q,2)===$l?(b=$l,Q+=2):(b=t,I===0&&Be(Ks)),b!==t?(N=Q,U=Q,ce=Ln(),ce!==t?(be=Ln(),be!==t?(ft=Ln(),ft!==t?(Bt=Ln(),Bt!==t?(ce=[ce,be,ft,Bt],U=ce):(Q=U,U=t)):(Q=U,U=t)):(Q=U,U=t)):(Q=U,U=t),U!==t?N=r.substring(N,Q):N=U,N!==t?(Re=C,b=cn(N),C=b):(Q=C,C=t)):(Q=C,C=t),C===t&&(C=Q,r.substr(Q,2)===ec?(b=ec,Q+=2):(b=t,I===0&&Be(wA)),b!==t?(N=Q,U=Q,ce=Ln(),ce!==t?(be=Ln(),be!==t?(ft=Ln(),ft!==t?(Bt=Ln(),Bt!==t?(Vr=Ln(),Vr!==t?(Ci=Ln(),Ci!==t?(rs=Ln(),rs!==t?(US=Ln(),US!==t?(ce=[ce,be,ft,Bt,Vr,Ci,rs,US],U=ce):(Q=U,U=t)):(Q=U,U=t)):(Q=U,U=t)):(Q=U,U=t)):(Q=U,U=t)):(Q=U,U=t)):(Q=U,U=t)):(Q=U,U=t),U!==t?N=r.substring(N,Q):N=U,N!==t?(Re=C,b=Og(N),C=b):(Q=C,C=t)):(Q=C,C=t)))),C}function TS(){var C;return Mg.test(r.charAt(Q))?(C=r.charAt(Q),Q++):(C=t,I===0&&Be(da)),C}function Ln(){var C;return Ca.test(r.charAt(Q))?(C=r.charAt(Q),Q++):(C=t,I===0&&Be($e)),C}function tfe(){var C,b,N,U,ce;if(C=Q,b=[],N=Q,r.charCodeAt(Q)===92?(U=es,Q++):(U=t,I===0&&Be(ut)),U!==t?(r.length>Q?(ce=r.charAt(Q),Q++):(ce=t,I===0&&Be(yo)),ce!==t?(Re=N,U=ln(ce),N=U):(Q=N,N=t)):(Q=N,N=t),N===t&&(N=Q,U=Q,I++,ce=vU(),I--,ce===t?U=void 0:(Q=U,U=t),U!==t?(r.length>Q?(ce=r.charAt(Q),Q++):(ce=t,I===0&&Be(yo)),ce!==t?(Re=N,U=ln(ce),N=U):(Q=N,N=t)):(Q=N,N=t)),N!==t)for(;N!==t;)b.push(N),N=Q,r.charCodeAt(Q)===92?(U=es,Q++):(U=t,I===0&&Be(ut)),U!==t?(r.length>Q?(ce=r.charAt(Q),Q++):(ce=t,I===0&&Be(yo)),ce!==t?(Re=N,U=ln(ce),N=U):(Q=N,N=t)):(Q=N,N=t),N===t&&(N=Q,U=Q,I++,ce=vU(),I--,ce===t?U=void 0:(Q=U,U=t),U!==t?(r.length>Q?(ce=r.charAt(Q),Q++):(ce=t,I===0&&Be(yo)),ce!==t?(Re=N,U=ln(ce),N=U):(Q=N,N=t)):(Q=N,N=t));else b=t;return b!==t&&(Re=C,b=Dn(b)),C=b,C}function OS(){var C,b,N,U,ce,be;if(C=Q,r.charCodeAt(Q)===45?(b=BA,Q++):(b=t,I===0&&Be(tc)),b===t&&(r.charCodeAt(Q)===43?(b=Us,Q++):(b=t,I===0&&Be(rc))),b===t&&(b=null),b!==t){if(N=[],Ge.test(r.charAt(Q))?(U=r.charAt(Q),Q++):(U=t,I===0&&Be(ie)),U!==t)for(;U!==t;)N.push(U),Ge.test(r.charAt(Q))?(U=r.charAt(Q),Q++):(U=t,I===0&&Be(ie));else N=t;if(N!==t)if(r.charCodeAt(Q)===46?(U=AI,Q++):(U=t,I===0&&Be(ed)),U!==t){if(ce=[],Ge.test(r.charAt(Q))?(be=r.charAt(Q),Q++):(be=t,I===0&&Be(ie)),be!==t)for(;be!==t;)ce.push(be),Ge.test(r.charAt(Q))?(be=r.charAt(Q),Q++):(be=t,I===0&&Be(ie));else ce=t;ce!==t?(Re=C,b=Kg(b,N,ce),C=b):(Q=C,C=t)}else Q=C,C=t;else Q=C,C=t}else Q=C,C=t;if(C===t){if(C=Q,r.charCodeAt(Q)===45?(b=BA,Q++):(b=t,I===0&&Be(tc)),b===t&&(r.charCodeAt(Q)===43?(b=Us,Q++):(b=t,I===0&&Be(rc))),b===t&&(b=null),b!==t){if(N=[],Ge.test(r.charAt(Q))?(U=r.charAt(Q),Q++):(U=t,I===0&&Be(ie)),U!==t)for(;U!==t;)N.push(U),Ge.test(r.charAt(Q))?(U=r.charAt(Q),Q++):(U=t,I===0&&Be(ie));else N=t;N!==t?(Re=C,b=td(b,N),C=b):(Q=C,C=t)}else Q=C,C=t;if(C===t&&(C=Q,b=KS(),b!==t&&(Re=C,b=lI(b)),C=b,C===t&&(C=Q,b=nc(),b!==t&&(Re=C,b=ic(b)),C=b,C===t)))if(C=Q,r.charCodeAt(Q)===40?(b=ue,Q++):(b=t,I===0&&Be(_)),b!==t){for(N=[],U=Me();U!==t;)N.push(U),U=Me();if(N!==t)if(U=BU(),U!==t){for(ce=[],be=Me();be!==t;)ce.push(be),be=Me();ce!==t?(r.charCodeAt(Q)===41?(be=T,Q++):(be=t,I===0&&Be(L)),be!==t?(Re=C,b=cI(U),C=b):(Q=C,C=t)):(Q=C,C=t)}else Q=C,C=t;else Q=C,C=t}else Q=C,C=t}return C}function MS(){var C,b,N,U,ce,be,ft,Bt;if(C=Q,b=OS(),b!==t){for(N=[],U=Q,ce=[],be=Me();be!==t;)ce.push(be),be=Me();if(ce!==t)if(r.charCodeAt(Q)===42?(be=Ug,Q++):(be=t,I===0&&Be(QA)),be===t&&(r.charCodeAt(Q)===47?(be=Rr,Q++):(be=t,I===0&&Be(uI))),be!==t){for(ft=[],Bt=Me();Bt!==t;)ft.push(Bt),Bt=Me();ft!==t?(Bt=OS(),Bt!==t?(Re=U,ce=Hs(b,be,Bt),U=ce):(Q=U,U=t)):(Q=U,U=t)}else Q=U,U=t;else Q=U,U=t;for(;U!==t;){for(N.push(U),U=Q,ce=[],be=Me();be!==t;)ce.push(be),be=Me();if(ce!==t)if(r.charCodeAt(Q)===42?(be=Ug,Q++):(be=t,I===0&&Be(QA)),be===t&&(r.charCodeAt(Q)===47?(be=Rr,Q++):(be=t,I===0&&Be(uI))),be!==t){for(ft=[],Bt=Me();Bt!==t;)ft.push(Bt),Bt=Me();ft!==t?(Bt=OS(),Bt!==t?(Re=U,ce=Hs(b,be,Bt),U=ce):(Q=U,U=t)):(Q=U,U=t)}else Q=U,U=t;else Q=U,U=t}N!==t?(Re=C,b=Gs(b,N),C=b):(Q=C,C=t)}else Q=C,C=t;return C}function BU(){var C,b,N,U,ce,be,ft,Bt;if(C=Q,b=MS(),b!==t){for(N=[],U=Q,ce=[],be=Me();be!==t;)ce.push(be),be=Me();if(ce!==t)if(r.charCodeAt(Q)===43?(be=Us,Q++):(be=t,I===0&&Be(rc)),be===t&&(r.charCodeAt(Q)===45?(be=BA,Q++):(be=t,I===0&&Be(tc))),be!==t){for(ft=[],Bt=Me();Bt!==t;)ft.push(Bt),Bt=Me();ft!==t?(Bt=MS(),Bt!==t?(Re=U,ce=Hg(b,be,Bt),U=ce):(Q=U,U=t)):(Q=U,U=t)}else Q=U,U=t;else Q=U,U=t;for(;U!==t;){for(N.push(U),U=Q,ce=[],be=Me();be!==t;)ce.push(be),be=Me();if(ce!==t)if(r.charCodeAt(Q)===43?(be=Us,Q++):(be=t,I===0&&Be(rc)),be===t&&(r.charCodeAt(Q)===45?(be=BA,Q++):(be=t,I===0&&Be(tc))),be!==t){for(ft=[],Bt=Me();Bt!==t;)ft.push(Bt),Bt=Me();ft!==t?(Bt=MS(),Bt!==t?(Re=U,ce=Hg(b,be,Bt),U=ce):(Q=U,U=t)):(Q=U,U=t)}else Q=U,U=t;else Q=U,U=t}N!==t?(Re=C,b=Gs(b,N),C=b):(Q=C,C=t)}else Q=C,C=t;return C}function QU(){var C,b,N,U,ce,be;if(C=Q,r.substr(Q,3)===bA?(b=bA,Q+=3):(b=t,I===0&&Be(R)),b!==t){for(N=[],U=Me();U!==t;)N.push(U),U=Me();if(N!==t)if(U=BU(),U!==t){for(ce=[],be=Me();be!==t;)ce.push(be),be=Me();ce!==t?(r.substr(Q,2)===q?(be=q,Q+=2):(be=t,I===0&&Be(pe)),be!==t?(Re=C,b=Ne(U),C=b):(Q=C,C=t)):(Q=C,C=t)}else Q=C,C=t;else Q=C,C=t}else Q=C,C=t;return C}function bU(){var C,b,N,U;return C=Q,r.substr(Q,2)===xe?(b=xe,Q+=2):(b=t,I===0&&Be(qe)),b!==t?(N=Ur(),N!==t?(r.charCodeAt(Q)===41?(U=T,Q++):(U=t,I===0&&Be(L)),U!==t?(Re=C,b=dt(N),C=b):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t),C}function KS(){var C,b,N,U,ce,be;return C=Q,r.substr(Q,2)===Ft?(b=Ft,Q+=2):(b=t,I===0&&Be(Fn)),b!==t?(N=nc(),N!==t?(r.substr(Q,2)===QS?(U=QS,Q+=2):(U=t,I===0&&Be(tU)),U!==t?(ce=pU(),ce!==t?(r.charCodeAt(Q)===125?(be=Pe,Q++):(be=t,I===0&&Be(Te)),be!==t?(Re=C,b=rU(N,ce),C=b):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t),C===t&&(C=Q,r.substr(Q,2)===Ft?(b=Ft,Q+=2):(b=t,I===0&&Be(Fn)),b!==t?(N=nc(),N!==t?(r.substr(Q,3)===bS?(U=bS,Q+=3):(U=t,I===0&&Be(iU)),U!==t?(Re=C,b=nU(N),C=b):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t),C===t&&(C=Q,r.substr(Q,2)===Ft?(b=Ft,Q+=2):(b=t,I===0&&Be(Fn)),b!==t?(N=nc(),N!==t?(r.substr(Q,2)===SS?(U=SS,Q+=2):(U=t,I===0&&Be(sU)),U!==t?(ce=pU(),ce!==t?(r.charCodeAt(Q)===125?(be=Pe,Q++):(be=t,I===0&&Be(Te)),be!==t?(Re=C,b=oU(N,ce),C=b):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t),C===t&&(C=Q,r.substr(Q,2)===Ft?(b=Ft,Q+=2):(b=t,I===0&&Be(Fn)),b!==t?(N=nc(),N!==t?(r.substr(Q,3)===vS?(U=vS,Q+=3):(U=t,I===0&&Be(aU)),U!==t?(Re=C,b=AU(N),C=b):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t),C===t&&(C=Q,r.substr(Q,2)===Ft?(b=Ft,Q+=2):(b=t,I===0&&Be(Fn)),b!==t?(N=nc(),N!==t?(r.charCodeAt(Q)===125?(U=Pe,Q++):(U=t,I===0&&Be(Te)),U!==t?(Re=C,b=xS(N),C=b):(Q=C,C=t)):(Q=C,C=t)):(Q=C,C=t),C===t&&(C=Q,r.charCodeAt(Q)===36?(b=lU,Q++):(b=t,I===0&&Be(cU)),b!==t?(N=nc(),N!==t?(Re=C,b=xS(N),C=b):(Q=C,C=t)):(Q=C,C=t)))))),C}function rfe(){var C,b,N;return C=Q,b=ife(),b!==t?(Re=Q,N=uU(b),N?N=void 0:N=t,N!==t?(Re=C,b=gU(b),C=b):(Q=C,C=t)):(Q=C,C=t),C}function ife(){var C,b,N,U,ce;if(C=Q,b=[],N=Q,U=Q,I++,ce=xU(),I--,ce===t?U=void 0:(Q=U,U=t),U!==t?(r.length>Q?(ce=r.charAt(Q),Q++):(ce=t,I===0&&Be(yo)),ce!==t?(Re=N,U=ln(ce),N=U):(Q=N,N=t)):(Q=N,N=t),N!==t)for(;N!==t;)b.push(N),N=Q,U=Q,I++,ce=xU(),I--,ce===t?U=void 0:(Q=U,U=t),U!==t?(r.length>Q?(ce=r.charAt(Q),Q++):(ce=t,I===0&&Be(yo)),ce!==t?(Re=N,U=ln(ce),N=U):(Q=N,N=t)):(Q=N,N=t);else b=t;return b!==t&&(Re=C,b=Dn(b)),C=b,C}function SU(){var C,b,N;if(C=Q,b=[],PS.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(DS)),N!==t)for(;N!==t;)b.push(N),PS.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(DS));else b=t;return b!==t&&(Re=C,b=kS()),C=b,C}function nc(){var C,b,N;if(C=Q,b=[],RS.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(FS)),N!==t)for(;N!==t;)b.push(N),RS.test(r.charAt(Q))?(N=r.charAt(Q),Q++):(N=t,I===0&&Be(FS));else b=t;return b!==t&&(Re=C,b=kS()),C=b,C}function vU(){var C;return fU.test(r.charAt(Q))?(C=r.charAt(Q),Q++):(C=t,I===0&&Be(Gg)),C}function xU(){var C;return NS.test(r.charAt(Q))?(C=r.charAt(Q),Q++):(C=t,I===0&&Be(LS)),C}function Me(){var C,b;if(C=[],gI.test(r.charAt(Q))?(b=r.charAt(Q),Q++):(b=t,I===0&&Be(fI)),b!==t)for(;b!==t;)C.push(b),gI.test(r.charAt(Q))?(b=r.charAt(Q),Q++):(b=t,I===0&&Be(fI));else C=t;return C}if(k=n(),k!==t&&Q===r.length)return k;throw k!==t&&Q{"use strict";function ihe(r,e){function t(){this.constructor=r}t.prototype=e.prototype,r.prototype=new t}function gc(r,e,t,i){this.message=r,this.expected=e,this.found=t,this.location=i,this.name="SyntaxError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,gc)}ihe(gc,Error);gc.buildMessage=function(r,e){var t={literal:function(c){return'"'+n(c.text)+'"'},class:function(c){var u="",g;for(g=0;g0){for(g=1,f=1;gH&&(H=v,j=[]),j.push(ie))}function Te(ie,Y){return new gc(ie,null,null,Y)}function se(ie,Y,he){return new gc(gc.buildMessage(ie,Y),ie,Y,he)}function Ae(){var ie,Y,he,te;return ie=v,Y=Qe(),Y!==t?(r.charCodeAt(v)===47?(he=s,v++):(he=t,$===0&&Pe(o)),he!==t?(te=Qe(),te!==t?(D=ie,Y=a(Y,te),ie=Y):(v=ie,ie=t)):(v=ie,ie=t)):(v=ie,ie=t),ie===t&&(ie=v,Y=Qe(),Y!==t&&(D=ie,Y=l(Y)),ie=Y),ie}function Qe(){var ie,Y,he,te;return ie=v,Y=fe(),Y!==t?(r.charCodeAt(v)===64?(he=c,v++):(he=t,$===0&&Pe(u)),he!==t?(te=Ge(),te!==t?(D=ie,Y=g(Y,te),ie=Y):(v=ie,ie=t)):(v=ie,ie=t)):(v=ie,ie=t),ie===t&&(ie=v,Y=fe(),Y!==t&&(D=ie,Y=f(Y)),ie=Y),ie}function fe(){var ie,Y,he,te,me;return ie=v,r.charCodeAt(v)===64?(Y=c,v++):(Y=t,$===0&&Pe(u)),Y!==t?(he=le(),he!==t?(r.charCodeAt(v)===47?(te=s,v++):(te=t,$===0&&Pe(o)),te!==t?(me=le(),me!==t?(D=ie,Y=h(),ie=Y):(v=ie,ie=t)):(v=ie,ie=t)):(v=ie,ie=t)):(v=ie,ie=t),ie===t&&(ie=v,Y=le(),Y!==t&&(D=ie,Y=h()),ie=Y),ie}function le(){var ie,Y,he;if(ie=v,Y=[],p.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Pe(m)),he!==t)for(;he!==t;)Y.push(he),p.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Pe(m));else Y=t;return Y!==t&&(D=ie,Y=h()),ie=Y,ie}function Ge(){var ie,Y,he;if(ie=v,Y=[],w.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Pe(B)),he!==t)for(;he!==t;)Y.push(he),w.test(r.charAt(v))?(he=r.charAt(v),v++):(he=t,$===0&&Pe(B));else Y=t;return Y!==t&&(D=ie,Y=h()),ie=Y,ie}if(z=n(),z!==t&&v===r.length)return z;throw z!==t&&v{"use strict";function H1(r){return typeof r>"u"||r===null}function she(r){return typeof r=="object"&&r!==null}function ohe(r){return Array.isArray(r)?r:H1(r)?[]:[r]}function ahe(r,e){var t,i,n,s;if(e)for(s=Object.keys(e),t=0,i=s.length;t{"use strict";function dd(r,e){Error.call(this),this.name="YAMLException",this.reason=r,this.mark=e,this.message=(this.reason||"(unknown reason)")+(this.mark?" "+this.mark.toString():""),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack||""}dd.prototype=Object.create(Error.prototype);dd.prototype.constructor=dd;dd.prototype.toString=function(e){var t=this.name+": ";return t+=this.reason||"(unknown reason)",!e&&this.mark&&(t+=" "+this.mark.toString()),t};G1.exports=dd});var q1=y((kZe,j1)=>{"use strict";var Y1=hc();function Ev(r,e,t,i,n){this.name=r,this.buffer=e,this.position=t,this.line=i,this.column=n}Ev.prototype.getSnippet=function(e,t){var i,n,s,o,a;if(!this.buffer)return null;for(e=e||4,t=t||75,i="",n=this.position;n>0&&`\0\r diff --git a/docs/api/actionCreatorMiddleware.mdx b/docs/api/actionCreatorMiddleware.mdx index 50570ae109..7378947a1e 100644 --- a/docs/api/actionCreatorMiddleware.mdx +++ b/docs/api/actionCreatorMiddleware.mdx @@ -53,7 +53,7 @@ import reducer from './reducer' // Augment middleware to consider all functions with a static type property to be action creators const isActionCreator = ( - action: unknown + action: unknown, ): action is Function & { type: unknown } => typeof action === 'function' && 'type' in action diff --git a/docs/api/combineSlices.mdx b/docs/api/combineSlices.mdx index b308a0e36f..81f8cb168a 100644 --- a/docs/api/combineSlices.mdx +++ b/docs/api/combineSlices.mdx @@ -235,7 +235,7 @@ declare module '.' { const withInjected = rootReducer.inject( { reducerPath: 'removable', reducer: removableReducer }, - { overrideExisting: true } + { overrideExisting: true }, ) const emptyReducer = () => null @@ -243,7 +243,7 @@ const emptyReducer = () => null const removeReducer = () => rootReducer.inject( { reducerPath: 'removable', reducer: emptyReducer }, - { overrideExisting: true } + { overrideExisting: true }, ) ``` @@ -273,14 +273,14 @@ const withCounter = rootReducer.inject(counterSlice) const selectCounterValue = (rootState: RootState) => rootState.counter?.value // number | undefined const wrappedSelectCounterValue = withCounter.selector( - (rootState) => rootState.counter.value // number + (rootState) => rootState.counter.value, // number ) console.log( selectCounterValue({}), // undefined selectCounterValue({ counter: { value: 2 } }), // 2 wrappedSelectCounterValue({}), // 0 - wrappedSelectCounterValue({ counter: { value: 2 } }) // 2 + wrappedSelectCounterValue({ counter: { value: 2 } }), // 2 ) ``` @@ -303,7 +303,7 @@ interface RootState { const selectCounterValue = withCounter.selector( (combinedState) => combinedState.counter.value, - (rootState: RootState) => rootState.innerCombined + (rootState: RootState) => rootState.innerCombined, ) console.log( @@ -316,7 +316,7 @@ console.log( value: 2, }, }, - }) // 2 + }), // 2 ) ``` @@ -365,6 +365,6 @@ If the slice state is undefined in the store state passed, the selector will ins console.log( injectedCounterSlice.selectors.selectValue({}), // 0 injectedCounterSlice.selectors.selectValue({ counter: { value: 2 } }), // 2 - aCounterSlice.selectors.selectValue({ aCounter: { value: 2 } }) // 2 + aCounterSlice.selectors.selectValue({ aCounter: { value: 2 } }), // 2 ) ``` diff --git a/docs/api/configureStore.mdx b/docs/api/configureStore.mdx index 08aa0f089c..c6364c9833 100644 --- a/docs/api/configureStore.mdx +++ b/docs/api/configureStore.mdx @@ -46,6 +46,10 @@ interface ConfigureStoreOptions< P = S > { /** + * A single reducer function that will be used as the root reducer, or an + * object of slice reducers that will be passed to `combineReducers()`. + */ + reducer: Reducer | ReducersMapObject /** * An array of Redux middleware to install. If not supplied, defaults to diff --git a/docs/api/createAction.mdx b/docs/api/createAction.mdx index 15776024ae..6fbec5d955 100644 --- a/docs/api/createAction.mdx +++ b/docs/api/createAction.mdx @@ -148,6 +148,6 @@ export const epic = (actions$: Observable) => map((action) => { // action.payload can be safely used as number here (and will also be correctly inferred by TypeScript) // ... - }) + }), ) ``` diff --git a/docs/api/createAsyncThunk.mdx b/docs/api/createAsyncThunk.mdx index c44803fda0..67cdd33984 100644 --- a/docs/api/createAsyncThunk.mdx +++ b/docs/api/createAsyncThunk.mdx @@ -35,7 +35,7 @@ const fetchUserById = createAsyncThunk( async (userId: number, thunkAPI) => { const response = await userAPI.fetchById(userId) return response.data - } + }, ) interface UsersState { @@ -190,23 +190,23 @@ interface RejectedWithValueAction { type Pending = ( requestId: string, - arg: ThunkArg + arg: ThunkArg, ) => PendingAction type Fulfilled = ( payload: PromiseResult, requestId: string, - arg: ThunkArg + arg: ThunkArg, ) => FulfilledAction type Rejected = ( requestId: string, - arg: ThunkArg + arg: ThunkArg, ) => RejectedAction type RejectedWithValue = ( requestId: string, - arg: ThunkArg + arg: ThunkArg, ) => RejectedWithValueAction ``` @@ -365,7 +365,7 @@ const updateUser = createAsyncThunk( // by explicitly returning it using the `rejectWithValue()` utility return rejectWithValue(err.response.data) } - } + }, ) ``` @@ -391,7 +391,7 @@ const fetchUserById = createAsyncThunk( return false } }, - } + }, ) ``` @@ -419,7 +419,7 @@ export const fetchUserById = createAsyncThunk( 'fetchUserById', (userId: string) => { /* ... */ - } + }, ) // file: MyComponent.ts @@ -456,7 +456,7 @@ const fetchUserById = createAsyncThunk( signal: thunkAPI.signal, }) return await response.json() - } + }, ) ``` @@ -486,7 +486,7 @@ const readStream = createAsyncThunk( done = read.done } return result - } + }, ) ``` @@ -510,7 +510,7 @@ const fetchUserById = createAsyncThunk( cancelToken: source.token, }) return response.data - } + }, ) ``` @@ -527,7 +527,7 @@ If a thunk was cancelled, the result of the promise will be a `rejected` action So if you wanted to test that a thunk was cancelled before executing, you can do the following: ```ts no-transpile -import { createAsyncThunk, isRejected } from '@reduxjs/toolkit' +import { createAsyncThunk } from '@reduxjs/toolkit' test('this thunk should always be skipped', async () => { const thunk = createAsyncThunk( @@ -749,7 +749,7 @@ const UsersComponent = (props: { id: string }) => { // This is an example of an onSubmit handler using Formik meant to demonstrate accessing the payload of the rejected action const handleUpdateUser = async ( values: FormValues, - formikHelpers: FormikHelpers + formikHelpers: FormikHelpers, ) => { const resultAction = await dispatch(updateUser({ id: props.id, ...values })) if (updateUser.fulfilled.match(resultAction)) { diff --git a/docs/api/createDynamicMiddleware.mdx b/docs/api/createDynamicMiddleware.mdx index 2f2150f2b6..199e8418a4 100644 --- a/docs/api/createDynamicMiddleware.mdx +++ b/docs/api/createDynamicMiddleware.mdx @@ -80,7 +80,7 @@ The "dynamic middleware instance" returned from `createDynamicMiddleware` is an ```ts no-transpile export type DynamicMiddlewareInstance< State = unknown, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, > = { middleware: DynamicMiddleware addMiddleware: AddMiddleware @@ -116,7 +116,7 @@ Accepts a set of middleware, and creates an action. When dispatched, it injects ```ts no-transpile const listenerDispatch = store.dispatch( - withMiddleware(listenerMiddleware.middleware) + withMiddleware(listenerMiddleware.middleware), ) const unsubscribe = listenerDispatch(addListener({ type, effect })) @@ -131,7 +131,7 @@ _These depend on having `react-redux` installed._ ```ts no-transpile interface ReactDynamicMiddlewareInstance< State = any, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, > extends DynamicMiddlewareInstance { createDispatchWithMiddlewareHook: CreateDispatchWithMiddlewareHook< State, @@ -140,7 +140,7 @@ interface ReactDynamicMiddlewareInstance< createDispatchWithMiddlewareHookFactory: ( context?: Context< ReactReduxContextValue> - > + >, ) => CreateDispatchWithMiddlewareHook } ``` @@ -151,7 +151,7 @@ Accepts a set of middleware, and returns a [`useDispatch`](https://react-redux.j ```ts no-transpile const useListenerDispatch = createDispatchWithMiddlewareHook( - listenerInstance.middleware + listenerInstance.middleware, ) const Component = () => { diff --git a/docs/api/createEntityAdapter.mdx b/docs/api/createEntityAdapter.mdx index 4b9cbc4134..ffd7d19ede 100644 --- a/docs/api/createEntityAdapter.mdx +++ b/docs/api/createEntityAdapter.mdx @@ -82,7 +82,7 @@ console.log(store.getState().books) // Can create a set of memoized selectors based on the location of this entity state const booksSelectors = booksAdapter.getSelectors( - (state) => state.books + (state) => state.books, ) // And then use the selectors to retrieve values @@ -148,7 +148,7 @@ export interface EntityStateAdapter { removeMany>(state: S, keys: EntityId[]): S removeMany>( state: S, - keys: PayloadAction + keys: PayloadAction, ): S removeAll>(state: S): S @@ -156,13 +156,13 @@ export interface EntityStateAdapter { updateOne>(state: S, update: Update): S updateOne>( state: S, - update: PayloadAction> + update: PayloadAction>, ): S updateMany>(state: S, updates: Update[]): S updateMany>( state: S, - updates: PayloadAction[]> + updates: PayloadAction[]>, ): S upsertOne>(state: S, entity: T): S @@ -171,7 +171,7 @@ export interface EntityStateAdapter { upsertMany>(state: S, entities: T[]): S upsertMany>( state: S, - entities: PayloadAction + entities: PayloadAction, ): S } @@ -190,7 +190,7 @@ export interface EntityAdapter extends EntityStateAdapter { getInitialState(state: S): EntityState & S getSelectors(): EntitySelectors> getSelectors( - selectState: (state: V) => EntityState + selectState: (state: V) => EntityState, ): EntitySelectors } ``` @@ -225,7 +225,8 @@ All three options will insert _new_ entities into the list. However they differ Each method has a signature that looks like: ```ts no-transpile -(state: EntityState, argument: TypeOrPayloadAction>) => EntityState +;(state: EntityState, argument: TypeOrPayloadAction>) => + EntityState ``` In other words, they accept a state that looks like `{ids: [], entities: {}}`, and calculate and return a new state. @@ -407,7 +408,7 @@ store.dispatch( booksReceived([ { id: 'b', title: 'Book 3' }, { id: 'c', title: 'Book 2' }, - ]) + ]), ) console.log(booksSelectors.selectIds(store.getState())) diff --git a/docs/api/createListenerMiddleware.mdx b/docs/api/createListenerMiddleware.mdx index 7c626174c4..050fbd20b9 100644 --- a/docs/api/createListenerMiddleware.mdx +++ b/docs/api/createListenerMiddleware.mdx @@ -100,7 +100,7 @@ interface CreateListenerMiddlewareOptions { type ListenerErrorHandler = ( error: unknown, - errorInfo: ListenerErrorInfo + errorInfo: ListenerErrorInfo, ) => void interface ListenerErrorInfo { @@ -125,12 +125,12 @@ interface ListenerMiddlewareInstance< unknown, UnknownAction >, - ExtraArgument = unknown + ExtraArgument = unknown, > { middleware: ListenerMiddleware startListening: (options: AddListenerOptions) => Unsubscribe stopListening: ( - options: AddListenerOptions & UnsubscribeListenerOptions + options: AddListenerOptions & UnsubscribeListenerOptions, ) => boolean clearListeners: () => void } @@ -184,11 +184,11 @@ interface AddListenerOptions { type ListenerPredicate = ( action: Action, currentState?: State, - originalState?: State + originalState?: State, ) => boolean type UnsubscribeListener = ( - unsubscribeOptions?: UnsubscribeListenerOptions + unsubscribeOptions?: UnsubscribeListenerOptions, ) => void interface UnsubscribeListenerOptions { @@ -241,7 +241,7 @@ By default, this does _not_ cancel any active running instances. However, you ma ```ts no-transpile const stopListening = ( - options: AddListenerOptions & UnsubscribeListenerOptions + options: AddListenerOptions & UnsubscribeListenerOptions, ) => boolean interface UnsubscribeListenerOptions { @@ -302,7 +302,7 @@ Returns `true` if the listener entry has been removed, `false` if no subscriptio ```js const wasRemoved = store.dispatch( - removeListener({ predicate, effect, cancelActive: true }) + removeListener({ predicate, effect, cancelActive: true }), ) ``` @@ -322,7 +322,7 @@ The `listenerApi` object is the second argument to each listener callback. It co export interface ListenerEffectAPI< State, Dispatch extends ReduxDispatch, - ExtraArgument = unknown + ExtraArgument = unknown, > extends MiddlewareAPI { // NOTE: MiddlewareAPI contains `dispatch` and `getState` already @@ -579,12 +579,12 @@ The signatures are: ```ts no-transpile type ConditionFunction = ( predicate: ListenerPredicate | (() => boolean), - timeout?: number + timeout?: number, ) => Promise type TakeFunction = ( predicate: ListenerPredicate | (() => boolean), - timeout?: number + timeout?: number, ) => Promise<[Action, State, State] | null> ``` @@ -612,7 +612,7 @@ test('condition method resolves promise when there is a timeout', async () => { (action, currentState: CounterState) => { return currentState.value === 3 }, - 50 + 50, ) // In this test, we expect the timeout to happen first @@ -818,7 +818,7 @@ useEffect(() => { effect: (action, listenerApi) => { // do some useful logic here }, - }) + }), ) return unsubscribe }, []) diff --git a/docs/api/createReducer.mdx b/docs/api/createReducer.mdx index 2526b9a3d9..13a17e00ec 100644 --- a/docs/api/createReducer.mdx +++ b/docs/api/createReducer.mdx @@ -243,11 +243,11 @@ const reducer = createReducer(0, (builder) => { .addCase('increment', (state) => state + 1) .addMatcher( (action) => action.type.startsWith('i'), - (state) => state * 5 + (state) => state * 5, ) .addMatcher( (action) => action.type.endsWith('t'), - (state) => state + 2 + (state) => state + 2, ) }) diff --git a/docs/api/createSelector.mdx b/docs/api/createSelector.mdx index b0679f1ad0..f18410dae8 100644 --- a/docs/api/createSelector.mdx +++ b/docs/api/createSelector.mdx @@ -44,7 +44,7 @@ const selectSelf = (state: State) => state const unsafeSelector = createSelector(selectSelf, (state) => state.value) const draftSafeSelector = createDraftSafeSelector( selectSelf, - (state) => state.value + (state) => state.value, ) // in your reducer: @@ -81,7 +81,7 @@ const createWeakMapDraftSafeSelector = const selectSelf = (state: State) => state const draftSafeSelector = createWeakMapDraftSafeSelector( selectSelf, - (state) => state.value + (state) => state.value, ) ``` diff --git a/docs/api/createSlice.mdx b/docs/api/createSlice.mdx index 45786f3d51..577f34d75d 100644 --- a/docs/api/createSlice.mdx +++ b/docs/api/createSlice.mdx @@ -171,7 +171,7 @@ const todosSlice = createSlice({ // action type is inferred from prepare callback (state, action) => { state.todos.push(action.payload) - } + }, ), fetchTodo: create.asyncThunk( async (id: string, thunkApi) => { @@ -189,7 +189,7 @@ const todosSlice = createSlice({ state.loading = false state.todos.push(action.payload) }, - } + }, ), }), }) @@ -232,7 +232,7 @@ create.preparedReducer( }, (state, action) => { state.todos.push(action.payload) - } + }, ) ``` @@ -322,7 +322,7 @@ create.asyncThunk( error: 'Oh no!', }) } - } + }, ) ``` @@ -330,8 +330,9 @@ For common thunk API configuration options, a [`withTypes` helper](../usage/usag ```ts no-transpile reducers: (create) => { - const createAThunk = - create.asyncThunk.withTypes<{ rejectValue: { error: string } }>() + const createAThunk = create.asyncThunk.withTypes<{ + rejectValue: { error: string } + }>() return { fetchTodo: createAThunk(async (id, thunkApi) => { @@ -432,7 +433,7 @@ const counterSlice = createSlice({ reducers: (create) => ({ getCountData: create.asyncThunk(async (_arg, { getState }) => { const currentCount = counterSlice.selectors.selectValue( - getState() as RootState + getState() as RootState, ) // highlight-start // this would cause a circular type, but the type annotation breaks the circle @@ -548,7 +549,7 @@ const counterSlice = createSlice({ selectors: { selectDouble: createSelector( (sliceState: CounterState) => sliceState.value, - (value) => value * 2 + (value) => value * 2, ), }, }) @@ -568,7 +569,7 @@ console.log(selectDouble.unwrapped.recomputations) // 2 ```ts no-transpile const { selectValue } = counterSlice.getSelectors( - (rootState: RootState) => rootState.aCounter + (rootState: RootState) => rootState.aCounter, ) console.log(selectValue({ aCounter: { value: 2 } })) // 2 @@ -589,7 +590,7 @@ The [`slice.selectors`](#selectors-2) object is the equivalent of calling const { selectValue } = counterSlice.getSelectors(counterSlice.selectSlice) // or const { selectValue } = counterSlice.getSelectors( - (state: RootState) => state[counterSlice.reducerPath] + (state: RootState) => state[counterSlice.reducerPath], ) ``` diff --git a/docs/api/getDefaultEnhancers.mdx b/docs/api/getDefaultEnhancers.mdx index 6863d4168e..075e0d85fb 100644 --- a/docs/api/getDefaultEnhancers.mdx +++ b/docs/api/getDefaultEnhancers.mdx @@ -109,6 +109,6 @@ interface GetDefaultEnhancersOptions { } function getDefaultEnhancers>( - options: GetDefaultEnhancersOptions = {} + options: GetDefaultEnhancersOptions = {}, ): EnhancerArray<[StoreEnhancer<{ dispatch: ExtractDispatchExtensions }>]> ``` diff --git a/docs/api/getDefaultMiddleware.mdx b/docs/api/getDefaultMiddleware.mdx index 7e51cf618f..921c27c2fa 100644 --- a/docs/api/getDefaultMiddleware.mdx +++ b/docs/api/getDefaultMiddleware.mdx @@ -166,6 +166,6 @@ interface GetDefaultMiddlewareOptions { } function getDefaultMiddleware( - options: GetDefaultMiddlewareOptions = {} + options: GetDefaultMiddlewareOptions = {}, ): Middleware<{}, S>[] ``` diff --git a/docs/api/matching-utilities.mdx b/docs/api/matching-utilities.mdx index 12808beecc..2c928f86a4 100644 --- a/docs/api/matching-utilities.mdx +++ b/docs/api/matching-utilities.mdx @@ -126,7 +126,7 @@ import { requestThunk1, requestThunk2 } from '@virtual/matchers' const isARejectedWithValueAction = isRejectedWithValue( requestThunk1, - requestThunk2 + requestThunk2, ) function handleRejectedWithValueAction(action: UnknownAction) { @@ -162,13 +162,13 @@ interface Interesting extends Data { } function isSpecial( - action: PayloadAction + action: PayloadAction, ): action is PayloadAction { return action.payload.isSpecial } function isInteresting( - action: PayloadAction + action: PayloadAction, ): action is PayloadAction { return action.payload.isInteresting } @@ -190,7 +190,7 @@ export const isSpecialAndInterestingThunk = createAsyncThunk( isSpecial: true, isInteresting: true, } - } + }, ) // This has unnecessary complexity @@ -224,13 +224,13 @@ const loadingReducer = createReducer(initialState, (builder) => { isAllOf(isSpecialAndInterestingThunk.fulfilled, isSpecial), (state, action) => { state.isSpecial = true - } + }, ) .addMatcher( isAllOf(isSpecialAndInterestingThunk.fulfilled, isInteresting), (state, action) => { state.isInteresting = true - } + }, ) }) ``` diff --git a/docs/components/DetailedExplanation.jsx b/docs/components/DetailedExplanation.jsx index b3701555ee..da47f48a28 100644 --- a/docs/components/DetailedExplanation.jsx +++ b/docs/components/DetailedExplanation.jsx @@ -2,7 +2,7 @@ import React from 'react' export const DetailedExplanation = ({ children, - title = 'Detailed Explanation' + title = 'Detailed Explanation', }) => { return (
diff --git a/docs/introduction/why-rtk-is-redux-today.md b/docs/introduction/why-rtk-is-redux-today.md index 8f4e918032..a8d3f23119 100644 --- a/docs/introduction/why-rtk-is-redux-today.md +++ b/docs/introduction/why-rtk-is-redux-today.md @@ -29,7 +29,7 @@ See these pages to learn how to use "modern Redux" with Redux Toolkit: ::: -## How Redux Toolkit Is Different Than the Redux Core +## How Redux Toolkit Is Different From the Redux Core ### What Is "Redux"? diff --git a/docs/rtk-query/api/createApi.mdx b/docs/rtk-query/api/createApi.mdx index dc76754f4d..24b205556d 100644 --- a/docs/rtk-query/api/createApi.mdx +++ b/docs/rtk-query/api/createApi.mdx @@ -101,11 +101,11 @@ export type BaseQueryFn< Result = unknown, Error = unknown, DefinitionExtraOptions = {}, - Meta = {} + Meta = {}, > = ( args: Args, api: BaseQueryApi, - extraOptions: DefinitionExtraOptions + extraOptions: DefinitionExtraOptions, ) => MaybePromise> export interface BaseQueryApi { @@ -148,7 +148,7 @@ export type QueryDefinition< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > = { query(arg: QueryArg): BaseQueryArg @@ -157,21 +157,21 @@ export type QueryDefinition< arg: QueryArg, api: BaseQueryApi, extraOptions: BaseQueryExtraOptions, - baseQuery: (arg: Parameters[0]) => ReturnType + baseQuery: (arg: Parameters[0]) => ReturnType, ): MaybePromise>> /* transformResponse only available with `query`, not `queryFn` */ transformResponse?( baseQueryReturnValue: BaseQueryResult, meta: BaseQueryMeta, - arg: QueryArg + arg: QueryArg, ): ResultType | Promise /* transformErrorResponse only available with `query`, not `queryFn` */ transformErrorResponse?( baseQueryReturnValue: BaseQueryError, meta: BaseQueryMeta, - arg: QueryArg + arg: QueryArg, ): unknown extraOptions?: BaseQueryExtraOptions @@ -195,7 +195,7 @@ export type QueryDefinition< queryFulfilled, getCacheEntry, updateCachedData, // available for query endpoints only - }: QueryLifecycleApi + }: QueryLifecycleApi, ): Promise onCacheEntryAdded?( @@ -209,7 +209,7 @@ export type QueryDefinition< cacheDataLoaded, getCacheEntry, updateCachedData, // available for query endpoints only - }: QueryCacheLifecycleApi + }: QueryCacheLifecycleApi, ): Promise } ``` @@ -223,7 +223,7 @@ export type MutationDefinition< TagTypes extends string, ResultType, ReducerPath extends string = string, - Context = Record + Context = Record, > = { query(arg: QueryArg): BaseQueryArg @@ -232,21 +232,21 @@ export type MutationDefinition< arg: QueryArg, api: BaseQueryApi, extraOptions: BaseQueryExtraOptions, - baseQuery: (arg: Parameters[0]) => ReturnType + baseQuery: (arg: Parameters[0]) => ReturnType, ): MaybePromise>> /* transformResponse only available with `query`, not `queryFn` */ transformResponse?( baseQueryReturnValue: BaseQueryResult, meta: BaseQueryMeta, - arg: QueryArg + arg: QueryArg, ): ResultType | Promise /* transformErrorResponse only available with `query`, not `queryFn` */ transformErrorResponse?( baseQueryReturnValue: BaseQueryError, meta: BaseQueryMeta, - arg: QueryArg + arg: QueryArg, ): unknown extraOptions?: BaseQueryExtraOptions @@ -262,7 +262,7 @@ export type MutationDefinition< requestId, queryFulfilled, getCacheEntry, - }: MutationLifecycleApi + }: MutationLifecycleApi, ): Promise onCacheEntryAdded?( @@ -275,7 +275,7 @@ export type MutationDefinition< cacheEntryRemoved, cacheDataLoaded, getCacheEntry, - }: MutationCacheLifecycleApi + }: MutationCacheLifecycleApi, ): Promise } ``` @@ -391,7 +391,7 @@ _(required if no `queryFn` provided)_ ```ts title="query signature" no-transpile export type query = ( - arg: QueryArg + arg: QueryArg, ) => string | Record // with `fetchBaseQuery` @@ -579,7 +579,7 @@ async function onQueryStarted( requestId, queryFulfilled, getCacheEntry, - }: MutationLifecycleApi + }: MutationLifecycleApi, ): Promise ``` @@ -594,7 +594,7 @@ async function onQueryStarted( queryFulfilled, getCacheEntry, updateCachedData, // available for query endpoints only - }: QueryLifecycleApi + }: QueryLifecycleApi, ): Promise ``` @@ -671,7 +671,7 @@ async function onCacheEntryAdded( cacheEntryRemoved, cacheDataLoaded, getCacheEntry, - }: MutationCacheLifecycleApi + }: MutationCacheLifecycleApi, ): Promise ``` @@ -687,7 +687,7 @@ async function onCacheEntryAdded( cacheDataLoaded, getCacheEntry, updateCachedData, // available for query endpoints only - }: QueryCacheLifecycleApi + }: QueryCacheLifecycleApi, ): Promise ``` diff --git a/docs/rtk-query/api/created-api/api-slice-utils.mdx b/docs/rtk-query/api/created-api/api-slice-utils.mdx index 816d5298a2..5ce2f72e07 100644 --- a/docs/rtk-query/api/created-api/api-slice-utils.mdx +++ b/docs/rtk-query/api/created-api/api-slice-utils.mdx @@ -30,13 +30,13 @@ const updateQueryData = ( endpointName: string, args: any, updateRecipe: (draft: Draft) => void, - updateProvided?: boolean -) => ThunkAction; + updateProvided?: boolean, +) => ThunkAction interface PatchCollection { - patches: Patch[]; - inversePatches: Patch[]; - undo: () => void; + patches: Patch[] + inversePatches: Patch[] + undo: () => void } ``` @@ -64,7 +64,7 @@ Note that the first two arguments (`endpointName` and `args`) are used to determ const patchCollection = dispatch( api.util.updateQueryData('getPosts', undefined, (draftPosts) => { draftPosts.push({ id: 1, name: 'Teddy' }) - }) + }), ) ``` @@ -91,7 +91,7 @@ dispatch(api.endpoints.getPosts.initiate(undefined, { ...options })) const patchCollection = dispatch( api.util.updateQueryData('getPostById', 1, (draftPost) => { draftPost.name = 'Lilly' - }) + }), ) ``` @@ -117,11 +117,8 @@ dispatch(api.endpoints.getPostById.initiate(1, { ...options })) #### Signature ```ts no-transpile -const upsertQueryData = ( - endpointName: string, - args: any, - newEntryData: T -) => ThunkAction>, PartialState, any, UnknownAction>; +const upsertQueryData = (endpointName: string, args: any, newEntryData: T) => + ThunkAction>, PartialState, any, UnknownAction> ``` - **Parameters** @@ -145,7 +142,7 @@ If dispatched while an actual request is in progress, both the upsert and reques ```ts no-transpile await dispatch( - api.util.upsertQueryData('getPost', { id: 1 }, { id: 1, text: 'Hello!' }) + api.util.upsertQueryData('getPost', { id: 1 }, { id: 1, text: 'Hello!' }), ) ``` @@ -184,12 +181,16 @@ In cases where it is desired to simply revert the previous changes, it may be pr const patchCollection = dispatch( api.util.updateQueryData('getPosts', undefined, (draftPosts) => { draftPosts.push({ id: 1, name: 'Teddy' }) - }) + }), ) // later dispatch( - api.util.patchQueryData('getPosts', undefined, patchCollection.inversePatches) + api.util.patchQueryData( + 'getPosts', + undefined, + patchCollection.inversePatches, + ), ) // or @@ -201,13 +202,10 @@ patchCollection.undo() #### Signature ```ts no-transpile -type PrefetchOptions = { ifOlderThan?: false | number } | { force?: boolean }; +type PrefetchOptions = { ifOlderThan?: false | number } | { force?: boolean } -const prefetch = ( - endpointName: string, - arg: any, - options: PrefetchOptions -) => ThunkAction; +const prefetch = (endpointName: string, arg: any, options: PrefetchOptions) => + ThunkAction ``` - **Parameters** @@ -239,7 +237,7 @@ dispatch(api.util.prefetch('getPosts', undefined, { force: true })) ```ts no-transpile function selectInvalidatedBy( state: RootState, - tags: ReadonlyArray> + tags: ReadonlyArray>, ): Array<{ endpointName: string originalArgs: any @@ -286,7 +284,7 @@ const entries = api.util.selectInvalidatedBy(state, [ ```ts no-transpile const invalidateTags = ( - tags: Array> + tags: Array>, ) => ({ type: string, payload: tags, @@ -316,7 +314,7 @@ dispatch( api.util.invalidateTags([ { type: 'Post', id: 1 }, { type: 'Post', id: 'LIST' }, - ]) + ]), ) ``` @@ -327,7 +325,7 @@ dispatch( ```ts no-transpile function selectCachedArgsForQuery( state: RootState, - queryName: QueryName + queryName: QueryName, ): Array ``` diff --git a/docs/rtk-query/api/created-api/endpoints.mdx b/docs/rtk-query/api/created-api/endpoints.mdx index ed4178467d..c57cc783fd 100644 --- a/docs/rtk-query/api/created-api/endpoints.mdx +++ b/docs/rtk-query/api/created-api/endpoints.mdx @@ -156,14 +156,14 @@ type CreateCacheSelectorFactory = | MutationResultSelectorFactory type QueryResultSelectorFactory = ( - queryArg: QueryArg | SkipToken + queryArg: QueryArg | SkipToken, ) => (state: RootState) => QueryResultSelectorResult type MutationResultSelectorFactory< Definition extends MutationDefinition, - RootState + RootState, > = ( - requestId: string | SkipToken + requestId: string | SkipToken, ) => (state: RootState) => MutationSubState & RequestStatusFlags type SkipToken = typeof Symbol @@ -200,7 +200,7 @@ function App() { // Each call will create a new selector function instance const selectPost = useMemo( () => api.endpoints.getPost.select(postId), - [postId] + [postId], ) const { data, isLoading } = useAppSelector(selectPost) // highlight-end @@ -234,14 +234,14 @@ function App() { const dispatch = useAppDispatch() const [newPost, setNewPost] = useState({ name: 'Ash' }) const [requestId, setRequestId] = useState( - skipToken + skipToken, ) // highlight-start // useMemo is used to only call `.select(..)` when required. // Each call will create a new selector function instance const selectMutationResult = useMemo( () => api.endpoints.addPost.select(requestId), - [requestId] + [requestId], ) const { isLoading } = useAppSelector(selectMutationResult) // highlight-end diff --git a/docs/rtk-query/api/created-api/hooks.mdx b/docs/rtk-query/api/created-api/hooks.mdx index d6a9426466..cd45e4951c 100644 --- a/docs/rtk-query/api/created-api/hooks.mdx +++ b/docs/rtk-query/api/created-api/hooks.mdx @@ -246,7 +246,7 @@ const useQueryResult = api.useGetPostsQuery(arg, options) ```ts no-transpile type UseQuery = ( arg: any | SkipToken, - options?: UseQueryOptions + options?: UseQueryOptions, ) => UseQueryResult type UseQueryOptions = { @@ -309,7 +309,7 @@ const useMutationResult = api.useUpdatePostMutation(options) ```ts no-transpile type UseMutation = ( - options?: UseMutationStateOptions + options?: UseMutationStateOptions, ) => [UseMutationTrigger, UseMutationResult | SelectedUseMutationResult] type UseMutationStateOptions = { @@ -387,7 +387,7 @@ const useQueryStateResult = api.endpoints.getPosts.useQueryState(arg, options) ```ts no-transpile type UseQueryState = ( arg: any | SkipToken, - options?: UseQueryStateOptions + options?: UseQueryStateOptions, ) => UseQueryStateResult | SelectedQueryStateResult type UseQueryStateOptions = { @@ -438,7 +438,7 @@ const { refetch } = api.endpoints.getPosts.useQuerySubscription(arg, options) ```ts no-transpile type UseQuerySubscription = ( arg: any | SkipToken, - options?: UseQuerySubscriptionOptions + options?: UseQuerySubscriptionOptions, ) => UseQuerySubscriptionResult type UseQuerySubscriptionOptions = { @@ -550,7 +550,7 @@ const [trigger, lastArg] = ```ts no-transpile type UseLazyQuerySubscription = ( - options?: UseLazyQuerySubscriptionOptions + options?: UseLazyQuerySubscriptionOptions, ) => [UseLazyQuerySubscriptionTrigger, LastArg] type UseLazyQuerySubscriptionOptions = { @@ -561,7 +561,7 @@ type UseLazyQuerySubscriptionOptions = { type UseLazyQuerySubscriptionTrigger = ( arg: any, - preferCacheValue?: boolean + preferCacheValue?: boolean, ) => void ``` @@ -588,7 +588,7 @@ const prefetchCallback = api.usePrefetch(endpointName, options) ```ts no-transpile type UsePrefetch = ( endpointName: string, - options?: UsePrefetchOptions + options?: UsePrefetchOptions, ) => PrefetchCallback type UsePrefetchOptions = diff --git a/docs/rtk-query/api/created-api/overview.mdx b/docs/rtk-query/api/created-api/overview.mdx index b515a2f5c8..5db80993b2 100644 --- a/docs/rtk-query/api/created-api/overview.mdx +++ b/docs/rtk-query/api/created-api/overview.mdx @@ -55,7 +55,7 @@ type Api = { > selectInvalidatedBy: ( state: FullState, - tags: Array> + tags: Array>, ) => Array<{ endpointName: string originalArgs: any @@ -63,16 +63,16 @@ type Api = { }> selectCachedArgsForQuery: ( state: FullState, - endpointName: EndpointName + endpointName: EndpointName, ) => Array resetApiState: ActionCreator getRunningQueryThunk( endpointName: EndpointName, - args: QueryArg + args: QueryArg, ): ThunkWithReturnValue getRunningMutationThunk( endpointName: EndpointName, - fixedCacheKeyOrRequestId: string + fixedCacheKeyOrRequestId: string, ): ThunkWithReturnValue getRunningQueriesThunk(): ThunkWithReturnValue< Array> diff --git a/docs/rtk-query/api/fetchBaseQuery.mdx b/docs/rtk-query/api/fetchBaseQuery.mdx index eea7ad4f37..0f668ea145 100644 --- a/docs/rtk-query/api/fetchBaseQuery.mdx +++ b/docs/rtk-query/api/fetchBaseQuery.mdx @@ -50,11 +50,11 @@ export const pokemonApi = createApi({ ```ts title="fetchBaseQuery signature" no-transpile type FetchBaseQuery = ( - args: FetchBaseQueryArgs + args: FetchBaseQueryArgs, ) => ( args: string | FetchArgs, api: BaseQueryApi, - extraOptions: ExtraOptions + extraOptions: ExtraOptions, ) => FetchBaseQueryResult type FetchBaseQueryArgs = { @@ -64,11 +64,11 @@ type FetchBaseQueryArgs = { api: Pick< BaseQueryApi, 'getState' | 'extra' | 'endpoint' | 'type' | 'forced' - > + >, ) => MaybePromise fetchFn?: ( input: RequestInfo, - init?: RequestInit | undefined + init?: RequestInit | undefined, ) => Promise paramsSerializer?: (params: Record) => string isJsonContentType?: (headers: Headers) => boolean @@ -118,7 +118,7 @@ type prepareHeaders = ( endpoint: string type: 'query' | 'mutation' forced: boolean | undefined - } + }, ) => Headers | void ``` diff --git a/docs/rtk-query/api/setupListeners.mdx b/docs/rtk-query/api/setupListeners.mdx index 5e9fe04bef..feb44c12e0 100644 --- a/docs/rtk-query/api/setupListeners.mdx +++ b/docs/rtk-query/api/setupListeners.mdx @@ -24,8 +24,8 @@ export function setupListeners( onFocusLost: typeof onFocusLost onOnline: typeof onOnline onOffline: typeof onOffline - } - ) => () => void + }, + ) => () => void, ) { function defaultHandler() { const handleFocus = () => dispatch(onFocus()) @@ -46,7 +46,7 @@ export function setupListeners( window.addEventListener( 'visibilitychange', handleVisibilityChange, - false + false, ) window.addEventListener('focus', handleFocus, false) diff --git a/docs/rtk-query/usage-with-typescript.mdx b/docs/rtk-query/usage-with-typescript.mdx index 366da13818..178a50495e 100644 --- a/docs/rtk-query/usage-with-typescript.mdx +++ b/docs/rtk-query/usage-with-typescript.mdx @@ -103,11 +103,11 @@ export type BaseQueryFn< Result = unknown, Error = unknown, DefinitionExtraOptions = {}, - Meta = {} + Meta = {}, > = ( args: Args, api: BaseQueryApi, - extraOptions: DefinitionExtraOptions + extraOptions: DefinitionExtraOptions, ) => MaybePromise> export interface BaseQueryApi { @@ -649,7 +649,7 @@ import { FetchBaseQueryError } from '@reduxjs/toolkit/query' * Type predicate to narrow an unknown error to `FetchBaseQueryError` */ export function isFetchBaseQueryError( - error: unknown + error: unknown, ): error is FetchBaseQueryError { return typeof error === 'object' && error != null && 'status' in error } @@ -658,7 +658,7 @@ export function isFetchBaseQueryError( * Type predicate to narrow an unknown error to an object with a string 'message' property */ export function isErrorWithMessage( - error: unknown + error: unknown, ): error is { message: string } { return ( typeof error === 'object' && diff --git a/docs/rtk-query/usage/automated-refetching.mdx b/docs/rtk-query/usage/automated-refetching.mdx index 5d589934cf..846b32598d 100644 --- a/docs/rtk-query/usage/automated-refetching.mdx +++ b/docs/rtk-query/usage/automated-refetching.mdx @@ -809,8 +809,8 @@ const api = createApi({ result ? [{ type: 'Post', id }] : error?.status === 401 - ? ['UNAUTHORIZED'] - : ['UNKNOWN_ERROR'], + ? ['UNAUTHORIZED'] + : ['UNKNOWN_ERROR'], }), login: build.mutation({ query: () => '/login', @@ -908,7 +908,7 @@ import type { Post, User } from './types' // highlight-start function providesList( resultsWithIds: R | undefined, - tagType: T + tagType: T, ) { return resultsWithIds ? [ diff --git a/docs/rtk-query/usage/cache-behavior.mdx b/docs/rtk-query/usage/cache-behavior.mdx index e6815b5271..caa8774f08 100644 --- a/docs/rtk-query/usage/cache-behavior.mdx +++ b/docs/rtk-query/usage/cache-behavior.mdx @@ -138,8 +138,8 @@ const Component = () => { dispatch( api.endpoints.getPosts.initiate( { count: 5 }, - { subscribe: false, forceRefetch: true } - ) + { subscribe: false, forceRefetch: true }, + ), ) } @@ -206,7 +206,7 @@ const Component = () => { // highlight-start // this overrules the api definition setting, // forcing the query to always fetch when this component is mounted - { refetchOnMountOrArgChange: true } + { refetchOnMountOrArgChange: true }, // highlight-end ) diff --git a/docs/rtk-query/usage/code-generation.mdx b/docs/rtk-query/usage/code-generation.mdx index efd4551e05..4ee69e0d34 100644 --- a/docs/rtk-query/usage/code-generation.mdx +++ b/docs/rtk-query/usage/code-generation.mdx @@ -112,7 +112,7 @@ interface SimpleUsage { export type EndpointMatcherFunction = ( operationName: string, - operationDefinition: OperationDefinition + operationDefinition: OperationDefinition, ) => boolean ``` diff --git a/docs/rtk-query/usage/customizing-create-api.mdx b/docs/rtk-query/usage/customizing-create-api.mdx index 2f4d53cfb8..cce3b8f339 100644 --- a/docs/rtk-query/usage/customizing-create-api.mdx +++ b/docs/rtk-query/usage/customizing-create-api.mdx @@ -44,7 +44,28 @@ const customCreateApi = buildCreateApi( useSelector: createSelectorHook(MyContext), useStore: createStoreHook(MyContext), }, - }) + }), +) +``` + +## Customizing `createSelector` for RTKQ + +Both `coreModule` and `reactHooksModule` accept a `createSelector` option which should be a selector creator instance from Reselect or with an equivalent signature. + +```ts +import * as React from 'react' +import { createSelectorCreator, lruMemoize } from '@reduxjs/toolkit' +import { + buildCreateApi, + coreModule, + reactHooksModule, +} from '@reduxjs/toolkit/query/react' + +const createLruSelector = createSelectorCreator(lruMemoize) + +const customCreateApi = buildCreateApi( + coreModule({ createSelector: createLruSelector }), + reactHooksModule({ createSelector: createLruSelector }), ) ``` @@ -73,7 +94,7 @@ declare module '../apiTypes' { BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, - TagTypes extends string + TagTypes extends string, > { [customModuleName]: { endpoints: { diff --git a/docs/rtk-query/usage/customizing-queries.mdx b/docs/rtk-query/usage/customizing-queries.mdx index 8734cc8d2e..8532ecf26c 100644 --- a/docs/rtk-query/usage/customizing-queries.mdx +++ b/docs/rtk-query/usage/customizing-queries.mdx @@ -57,7 +57,7 @@ const customBaseQuery = ( // highlight-start args, { signal, dispatch, getState }, - extraOptions + extraOptions, // highlight-end ) => { // omitted @@ -77,7 +77,7 @@ const customBaseQuery = ( const customBaseQuery = ( args, { signal, dispatch, getState }, - extraOptions + extraOptions, ) => { // highlight-start if (Math.random() > 0.5) return { error: 'Too high!' } @@ -97,18 +97,21 @@ At its core, a `baseQuery` function only needs to have the minimum return value For [`fetchBaseQuery`](../api/fetchBaseQuery) specifically, the return type is as follows: ```ts title="Return types of fetchBaseQuery" no-transpile -Promise<{ - data: any; - error?: undefined; - meta?: { request: Request; response: Response }; -} | { - error: { - status: number; - data: any; - }; - data?: undefined; - meta?: { request: Request; response: Response }; -}> +Promise< + | { + data: any + error?: undefined + meta?: { request: Request; response: Response } + } + | { + error: { + status: number + data: any + } + data?: undefined + meta?: { request: Request; response: Response } + } +> ``` 1. ```ts title="Expected success result format with fetchBaseQuery" no-transpile @@ -130,7 +133,7 @@ By default, the payload from the server is returned directly. function defaultTransformResponse( baseQueryReturnValue: unknown, meta: unknown, - arg: unknown + arg: unknown, ) { return baseQueryReturnValue } @@ -211,7 +214,7 @@ By default, the payload from the server is returned directly. function defaultTransformResponse( baseQueryReturnValue: unknown, meta: unknown, - arg: unknown + arg: unknown, ) { return baseQueryReturnValue } @@ -232,7 +235,7 @@ dependent on the `baseQuery` used. transformErrorResponse: ( response: { data: { sideA: Tracks; sideB: Tracks } }, meta, - arg + arg, ) => { if (meta?.coinFlip === 'heads') { return response.data.sideA @@ -317,7 +320,7 @@ const queryFn = ( args, { signal, dispatch, getState }, extraOptions, - baseQuery + baseQuery, // highlight-end ) => { // omitted @@ -338,7 +341,7 @@ const queryFn = ( args, { signal, dispatch, getState }, extraOptions, - baseQuery + baseQuery, ) => { // highlight-start if (Math.random() > 0.5) return { error: 'Too high!' } @@ -362,7 +365,7 @@ import type { AxiosRequestConfig, AxiosError } from 'axios' // highlight-start const axiosBaseQuery = ( - { baseUrl }: { baseUrl: string } = { baseUrl: '' } + { baseUrl }: { baseUrl: string } = { baseUrl: '' }, ): BaseQueryFn< { url: string @@ -565,7 +568,7 @@ const baseQueryWithReauth: BaseQueryFn< const refreshResult = await baseQuery( '/refreshToken', api, - extraOptions + extraOptions, ) if (refreshResult.data) { api.dispatch(tokenReceived(refreshResult.data)) @@ -627,7 +630,7 @@ const staggeredBaseQueryWithBailOut = retry( const result = await fetchBaseQuery({ baseUrl: '/api/' })( args, api, - extraOptions + extraOptions, ) // bail out of re-tries immediately if unauthorized, @@ -640,7 +643,7 @@ const staggeredBaseQueryWithBailOut = retry( }, { maxRetries: 5, - } + }, ) // highlight-end @@ -711,7 +714,7 @@ const metaBaseQuery: BaseQueryFn< const baseResult = await fetchBaseQuery({ baseUrl: '/' })( args, api, - extraOptions + extraOptions, ) return { @@ -746,7 +749,7 @@ const api = createApi({ // These properties can be used to transform the response as desired. if (!meta) return [] return returnValue.filter( - (post) => post.timestamp >= meta.timestamp - DAY_MS + (post) => post.timestamp >= meta.timestamp - DAY_MS, ) }, // highlight-end diff --git a/docs/rtk-query/usage/manual-cache-updates.mdx b/docs/rtk-query/usage/manual-cache-updates.mdx index ac6cb96bab..7f05b88a1e 100644 --- a/docs/rtk-query/usage/manual-cache-updates.mdx +++ b/docs/rtk-query/usage/manual-cache-updates.mdx @@ -12,7 +12,7 @@ description: 'RTK Query > Usage > Manual Cache Updates: Updating and creating ca ## Overview -For most cases, in order to receive up to date data after a triggering a change in the backend, you can take advantage of cache tag invalidation to perform [automated re-fetching](./automated-refetching). This will cause a query to re-fetch its data when it has been told that a mutation has occurred which would cause its data to become out of date. +For most cases, in order to receive up to date data after a triggering a change in the backend, you can take advantage of cache tag invalidation to perform [automated re-fetching](./automated-refetching). This will cause a query to re-fetch its data when it has been told that a mutation has occurred which would cause its data to become out of date. We recommend using automated re-fetching as a preference over manual cache updates in most situations. @@ -20,7 +20,7 @@ However, there _are_ use cases when manual cache updates are necessary, such as RTK Query exports thunks for these use cases, attached to `api.utils`: -- [`updateQueryData`](../api/created-api/api-slice-utils.mdx#updatequerydata): updates an already existing cache entry +- [`updateQueryData`](../api/created-api/api-slice-utils.mdx#updatequerydata): updates an already existing cache entry - [`upsertQueryData`](../api/created-api/api-slice-utils.mdx#upsertquerydata): creates or replaces cache entries Since these are thunks, you can dispatch them anywhere you have access to `dispatch`. @@ -32,6 +32,7 @@ For updates of existing cache entries, use [`updateQueryData`](../api/created-ap `updateQueryData` is strictly intended to perform _updates_ to existing cache entries, not create new entries. If an `updateQueryData` thunk action is dispatched and the `endpointName` + `args` combination that does not match any existing cache entry, the provided `recipe` callback will not be called, and no `patches` or `inversePatches` will be returned. Use cases for manual update of cache entries: + - Providing immediate feedback to the user when a mutation is attempted - After a mutation, updating a single item in a large list of items that is already cached, rather than re-fetching the whole list - Debouncing a large number of mutations with immediate feedback as though they are being applied, followed by a single request sent to the server to update the debounced attempts @@ -42,8 +43,7 @@ To create or replace existing cache entries, use [`upsertQueryData`](../api/crea `upsertQueryData` is intended to perform _replacements_ to existing cache entries or _creation_ of new ones. Since `upsertQueryData` does not have access to the previous state of the cache entry, the update may be performed only as a replacement. In comparison, `updateQueryData` allows patching of the existing cache entry, but cannot create a new one. - -One example use case is [pessimistic updates](../usage/manual-cache-updates.mdx#pessimistic-updates). If the client makes an API call to create a `Post`, the backend could return its complete data including the `id`. Then we can use `upsertQueryData` to create a new cache entry for the `getPostById(id)` query, preventing an extra fetch to retrieve the item later. +One example use case is [pessimistic updates](../usage/manual-cache-updates.mdx#pessimistic-updates). If the client makes an API call to create a `Post`, the backend could return its complete data including the `id`. Then we can use `upsertQueryData` to create a new cache entry for the `getPostById(id)` query, preventing an extra fetch to retrieve the item later. ## Recipes @@ -102,7 +102,7 @@ const api = createApi({ const patchResult = dispatch( api.util.updateQueryData('getPost', id, (draft) => { Object.assign(draft, patch) - }) + }), ) try { await queryFulfilled @@ -197,7 +197,7 @@ const api = createApi({ const patchResult = dispatch( api.util.updateQueryData('getPost', id, (draft) => { Object.assign(draft, updatedPost) - }) + }), ) } catch {} }, @@ -214,7 +214,7 @@ const api = createApi({ try { const { data: createdPost } = await queryFulfilled const patchResult = dispatch( - api.util.upsertQueryData('getPost', id, createdPost) + api.util.upsertQueryData('getPost', id, createdPost), ) } catch {} }, @@ -253,7 +253,7 @@ function App() { const patchCollection = dispatch( api.util.updateQueryData('getPosts', undefined, (draftPosts) => { draftPosts.push({ id: 1, name: 'Teddy' }) - }) + }), ) } diff --git a/docs/rtk-query/usage/migrating-to-rtk-query.mdx b/docs/rtk-query/usage/migrating-to-rtk-query.mdx index 11b993c78b..e5f2a655bc 100644 --- a/docs/rtk-query/usage/migrating-to-rtk-query.mdx +++ b/docs/rtk-query/usage/migrating-to-rtk-query.mdx @@ -72,7 +72,7 @@ export const fetchPokemonByName = createAsyncThunk( return rejectWithValue(data) } return data - } + }, ) // highlight-end @@ -187,7 +187,7 @@ render( , // highlight-end - rootElement + rootElement, ) ``` @@ -201,7 +201,7 @@ import { AsyncThunkAction } from '@reduxjs/toolkit' import { RootState } from '../store' interface Pokemon {} export declare const fetchPokemonByName: ( - arg: string + arg: string, ) => AsyncThunkAction export const selectStatusByName = (state: RootState, name: string) => @@ -243,7 +243,7 @@ export function useGetPokemonByNameQuery(name: string) { const dispatch = useAppDispatch() // select the current status from the store state for the provided name const status = useSelector((state: RootState) => - selectStatusByName(state, name) + selectStatusByName(state, name), ) // select the current data from the store state for the provided name const data = useSelector((state: RootState) => selectDataByName(state, name)) diff --git a/docs/rtk-query/usage/mutations.mdx b/docs/rtk-query/usage/mutations.mdx index c018056832..3dd4f73f53 100644 --- a/docs/rtk-query/usage/mutations.mdx +++ b/docs/rtk-query/usage/mutations.mdx @@ -58,14 +58,14 @@ const api = createApi({ transformErrorResponse: ( response: { status: string | number }, meta, - arg + arg, ) => response.status, invalidatesTags: ['Post'], // onQueryStarted is useful for optimistic updates // The 2nd parameter is the destructured `MutationLifecycleApi` async onQueryStarted( arg, - { dispatch, getState, queryFulfilled, requestId, extra, getCacheEntry } + { dispatch, getState, queryFulfilled, requestId, extra, getCacheEntry }, ) {}, // The 2nd parameter is the destructured `MutationCacheLifecycleApi` async onCacheEntryAdded( @@ -78,7 +78,7 @@ const api = createApi({ cacheEntryRemoved, cacheDataLoaded, getCacheEntry, - } + }, ) {}, // highlight-end }), @@ -256,7 +256,7 @@ export const postApi = createApi({ result ? // successful query [ - ...result.map(({ id }) => ({ type: 'Posts', id } as const)), + ...result.map(({ id }) => ({ type: 'Posts', id }) as const), { type: 'Posts', id: 'LIST' }, ] : // an error occurred, but we still want to refetch this query when `{ type: 'Posts', id: 'LIST' }` is invalidated diff --git a/docs/rtk-query/usage/polling.mdx b/docs/rtk-query/usage/polling.mdx index 2e85c1ed6d..8a59db5ca8 100644 --- a/docs/rtk-query/usage/polling.mdx +++ b/docs/rtk-query/usage/polling.mdx @@ -34,7 +34,7 @@ In an action creator without React Hooks: const { data, status, error, refetch } = store.dispatch( endpoints.getCountById.initiate(id, { subscriptionOptions: { pollingInterval: 3000 }, - }) + }), ) ``` diff --git a/docs/rtk-query/usage/prefetching.mdx b/docs/rtk-query/usage/prefetching.mdx index fbdc3b21fb..405109fb9c 100644 --- a/docs/rtk-query/usage/prefetching.mdx +++ b/docs/rtk-query/usage/prefetching.mdx @@ -86,8 +86,8 @@ type EndpointNames = keyof typeof api.endpoints export function usePrefetchImmediately( endpoint: T, - arg: Parameters[0], - options: PrefetchOptions = {} + arg: Parameters<(typeof api.endpoints)[T]['initiate']>[0], + options: PrefetchOptions = {}, ) { const dispatch = useAppDispatch() useEffect(() => { @@ -107,7 +107,7 @@ When dispatching the `prefetch` thunk as shown below you will see the same exact ```ts title="Non-hook prefetching example" no-transpile store.dispatch( - api.util.prefetch(endpointName, arg, { force: false, ifOlderThan: 10 }) + api.util.prefetch(endpointName, arg, { force: false, ifOlderThan: 10 }), ) ``` diff --git a/docs/rtk-query/usage/queries.mdx b/docs/rtk-query/usage/queries.mdx index 1eca72047e..b0568e3047 100644 --- a/docs/rtk-query/usage/queries.mdx +++ b/docs/rtk-query/usage/queries.mdx @@ -65,7 +65,7 @@ const api = createApi({ transformErrorResponse: ( response: { status: string | number }, meta, - arg + arg, ) => response.status, providesTags: (result, error, id) => [{ type: 'Post', id }], // The 2nd parameter is the destructured `QueryLifecycleApi` @@ -79,7 +79,7 @@ const api = createApi({ queryFulfilled, getCacheEntry, updateCachedData, - } + }, ) {}, // The 2nd parameter is the destructured `QueryCacheLifecycleApi` async onCacheEntryAdded( @@ -93,7 +93,7 @@ const api = createApi({ cacheDataLoaded, getCacheEntry, updateCachedData, - } + }, ) {}, // highlight-end }), @@ -287,9 +287,7 @@ function PostsList() { return (
    - {posts?.data?.map((post) => ( - - ))} + {posts?.data?.map((post) => )}
) } @@ -346,7 +344,7 @@ If you're not using React Hooks, you can access `refetch` like this: ```ts no-transpile const { status, data, error, refetch } = dispatch( - pokemonApi.endpoints.getPokemon.initiate('bulbasaur') + pokemonApi.endpoints.getPokemon.initiate('bulbasaur'), ) ``` diff --git a/docs/rtk-query/usage/streaming-updates.mdx b/docs/rtk-query/usage/streaming-updates.mdx index 88ed09082e..880a78bfd6 100644 --- a/docs/rtk-query/usage/streaming-updates.mdx +++ b/docs/rtk-query/usage/streaming-updates.mdx @@ -78,7 +78,7 @@ export const api = createApi({ // highlight-start async onCacheEntryAdded( arg, - { updateCachedData, cacheDataLoaded, cacheEntryRemoved } + { updateCachedData, cacheDataLoaded, cacheEntryRemoved }, ) { // create a websocket connection when the cache subscription starts const ws = new WebSocket('ws://localhost:8080') @@ -165,13 +165,13 @@ export const api = createApi({ transformResponse(response: Message[]) { return messagesAdapter.addMany( messagesAdapter.getInitialState(), - response + response, ) }, // highlight-end async onCacheEntryAdded( arg, - { updateCachedData, cacheDataLoaded, cacheEntryRemoved } + { updateCachedData, cacheDataLoaded, cacheEntryRemoved }, ) { const ws = new WebSocket('ws://localhost:8080') try { diff --git a/docs/rtk-query/usage/usage-without-react-hooks.mdx b/docs/rtk-query/usage/usage-without-react-hooks.mdx index 319e4a0f95..45617d383a 100644 --- a/docs/rtk-query/usage/usage-without-react-hooks.mdx +++ b/docs/rtk-query/usage/usage-without-react-hooks.mdx @@ -71,13 +71,13 @@ Because the `endpoint.select(arg)` function returns a new selector each time it' ```ts title="Creating a memoized selector creator" no-transpile const createGetPostSelector = createSelector( (id: string) => id, - (id) => api.endpoints.getPost.select(id) + (id) => api.endpoints.getPost.select(id), ) const selectGetPostError = createSelector( (state: RootState) => state, (state: RootState, id: string) => createGetPostSelector(id), - (state, selectGetPost) => selectGetPost(state).error + (state, selectGetPost) => selectGetPost(state).error, ) ``` diff --git a/docs/tsconfig.json b/docs/tsconfig.json index 80bf4d4a7d..200ffa3ffe 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -18,36 +18,20 @@ "baseUrl": "..", "jsx": "preserve", "paths": { - "react": [ - "../node_modules/@types/react" - ], - "react-dom": [ - "../node_modules/@types/react-dom" - ], - "@reduxjs/toolkit": [ - "packages/toolkit/src/index.ts" - ], - "@reduxjs/toolkit/query": [ - "packages/toolkit/src/query/index.ts" - ], + "react": ["../node_modules/@types/react"], + "react-dom": ["../node_modules/@types/react-dom"], + "@reduxjs/toolkit": ["packages/toolkit/src/index.ts"], + "@reduxjs/toolkit/query": ["packages/toolkit/src/query/index.ts"], "@reduxjs/toolkit/query/react": [ - "packages/toolkit/src/query/react/index.ts" - ], - "@reduxjs/toolkit/dist/query/*": [ - "packages/toolkit/src/query/*" - ], - "@virtual/*": [ - "docs/virtual/*" - ], - "your-cool-library": [ - "docs/virtual/your-cool-library/index.ts" - ], - "redux-logger": [ - "docs/virtual/redux-logger/index.ts" + "packages/toolkit/src/query/react/index.ts", ], + "@reduxjs/toolkit/dist/query/*": ["packages/toolkit/src/query/*"], + "@virtual/*": ["docs/virtual/*"], + "your-cool-library": ["docs/virtual/your-cool-library/index.ts"], + "redux-logger": ["docs/virtual/redux-logger/index.ts"], "petstore-api.generated": [ - "docs/virtual/petstore-api.generated/index.ts" - ] - } - } -} \ No newline at end of file + "docs/virtual/petstore-api.generated/index.ts", + ], + }, + }, +} diff --git a/docs/tutorials/rtk-query.mdx b/docs/tutorials/rtk-query.mdx index 8f2c97962e..17dcbae065 100644 --- a/docs/tutorials/rtk-query.mdx +++ b/docs/tutorials/rtk-query.mdx @@ -23,7 +23,7 @@ hide_title: true ## Introduction -Welcome to the Redux Toolkit Query tutorial! **This tutorial will briefly introduce you to Redux Toolkit's "RTK Query" data fetching capability and teach you how to start using it correctly**. +Welcome to the Redux Toolkit Query tutorial! **This tutorial will briefly introduce you to Redux Toolkit's "RTK Query" data fetching capability and teach you how to start using it correctly**. :::info diff --git a/docs/usage/migrating-rtk-2.md b/docs/usage/migrating-rtk-2.md index b537ec9d41..bbdedaa9bf 100644 --- a/docs/usage/migrating-rtk-2.md +++ b/docs/usage/migrating-rtk-2.md @@ -145,7 +145,7 @@ First, the `Reducer` type now has a `PreloadedState` possible generic: ```ts type Reducer = ( state: S | PreloadedState | undefined, - action: A + action: A, ) => S ``` @@ -319,7 +319,7 @@ const customCreateApi = buildCreateApi( useDispatch: createDispatchHook(MyContext), useSelector: createSelectorHook(MyContext), useStore: createStoreHook(MyContext), - }) + }), ) // now @@ -331,7 +331,7 @@ const customCreateApi = buildCreateApi( useSelector: createSelectorHook(MyContext), useStore: createStoreHook(MyContext), }, - }) + }), ) ``` @@ -406,7 +406,7 @@ const addNumbers = createSelector( // this input selector will always return a new reference when run // so cache will never be used (a, b) => ({ a, b }), - ({ a, b }) => ({ total: a + b }) + ({ a, b }) => ({ total: a + b }), ) // instead, you should have an input selector for each stable piece of data const addNumbersStable = createSelector( @@ -414,7 +414,7 @@ const addNumbersStable = createSelector( (a, b) => b, (a, b) => ({ total: a + b, - }) + }), ) ``` @@ -537,7 +537,7 @@ const combinedReducer = combineSlices( num: numberSlice.reducer, boolean: booleanReducer, }, - api + api, ) expect(combinedReducer(undefined, dummyAction())).toEqual({ string: stringSlice.getInitialState(), @@ -564,12 +564,12 @@ const injectedReducer = combinedReducer.inject(numberSlice) // `state.number` now exists, and injectedReducer's type no longer marks it as optional expect(injectedReducer(undefined, dummyAction()).number).toBe( - numberSlice.getInitialState() + numberSlice.getInitialState(), ) // original reducer has also been changed (type is still optional) expect(combinedReducer(undefined, dummyAction()).number).toBe( - numberSlice.getInitialState() + numberSlice.getInitialState(), ) ``` @@ -603,7 +603,7 @@ const customState = { number: slice.getInitialState(), } const { selectSlice, selectMultiple } = slice.getSelectors( - (state: typeof customState) => state.number + (state: typeof customState) => state.number, ) expect(selectSlice(customState)).toBe(slice.getInitialState()) expect(selectMultiple(customState, 2)).toBe(slice.getInitialState() * 2) @@ -620,7 +620,7 @@ const fetchUserById = createAsyncThunk( async (userId: number, thunkAPI) => { const response = await userAPI.fetchById(userId) return response.data - } + }, ) const usersSlice = createSlice({ @@ -682,7 +682,7 @@ const todosSlice = createAppSlice({ // action type is inferred from prepare callback (state, action) => { state.todos.push(action.payload) - } + }, ), // An async thunk fetchTodo: create.asyncThunk( @@ -706,7 +706,7 @@ const todosSlice = createAppSlice({ settled: (state, action) => { state.loading = false }, - } + }, ), }), }) @@ -872,7 +872,7 @@ For example, with `redux-observable`: const epic = (action$: Observable) => action$.pipe( ofType(todoAdded), - map((action) => action) + map((action) => action), // ^? still Action ) @@ -880,7 +880,7 @@ const epic = (action$: Observable) => const epic = (action$: Observable) => action$.pipe( filter(todoAdded.match), - map((action) => action) + map((action) => action), // ^? now PayloadAction ) ``` @@ -931,7 +931,7 @@ const asyncThunkCreator = { // the definition from define() definition, // methods to modify slice - context + context, ) { const { payloadCreator, options, pending, fulfilled, rejected, settled } = definition @@ -976,7 +976,7 @@ const todoSlice = createSlice({ selectTodosByAuthor = createSelector( (state: TodoState) => state.todos, (state: TodoState, author: string) => author, - (todos, author) => todos.filter((todo) => todo.author === author) + (todos, author) => todos.filter((todo) => todo.author === author), ), }, }) @@ -991,7 +991,7 @@ export const makeSelectTodosByAuthor = () => createSelector( (state: RootState) => state.todos.todos, (state: RootState, author: string) => author, - (todos, author) => todos.filter((todo) => todo.author === author) + (todos, author) => todos.filter((todo) => todo.author === author), ) function AuthorTodos({ author }: { author: string }) { diff --git a/docs/usage/migrating-to-modern-redux.mdx b/docs/usage/migrating-to-modern-redux.mdx index 57c4758b31..4241f2d22f 100644 --- a/docs/usage/migrating-to-modern-redux.mdx +++ b/docs/usage/migrating-to-modern-redux.mdx @@ -298,7 +298,7 @@ const todosSlice = createSlice({ // In this case, `action.payload` is the default field in the action, // and can hold the `id` value - no need for `action.id` separately const matchingTodo = state.todos.find( - (todo) => todo.id === action.payload + (todo) => todo.id === action.payload, ) if (matchingTodo) { @@ -796,7 +796,7 @@ const initialState: TodosState = [] export default function todosReducer( state = initialState, - action: TodoActions + action: TodoActions, ) { switch (action.type) { // omit reducer logic @@ -944,7 +944,7 @@ const mapDispatchToProps2 = (dispatch) => { todoDeleted, todoToggled, }, - dispatch + dispatch, ) } diff --git a/docs/usage/usage-guide.md b/docs/usage/usage-guide.md index 8baf6c938a..113c732a54 100644 --- a/docs/usage/usage-guide.md +++ b/docs/usage/usage-guide.md @@ -651,7 +651,7 @@ const fetchUserById = createAsyncThunk( async (userId, thunkAPI) => { const response = await userAPI.fetchById(userId) return response.data - } + }, ) // Then, handle actions in your reducers: @@ -1084,7 +1084,7 @@ ReactDOM.render( , - document.getElementById('root') + document.getElementById('root'), ) ``` @@ -1137,10 +1137,10 @@ const store = configureStore({ ignoredActions: [ // just ignore every redux-firebase and react-redux-firebase action type ...Object.keys(rfConstants.actionTypes).map( - (type) => `${rfConstants.actionsPrefix}/${type}` + (type) => `${rfConstants.actionsPrefix}/${type}`, ), ...Object.keys(rrfActionTypes).map( - (type) => `@@reactReduxFirebase/${type}` + (type) => `@@reactReduxFirebase/${type}`, ), ], ignoredPaths: ['firebase', 'firestore'], diff --git a/docs/usage/usage-with-typescript.md b/docs/usage/usage-with-typescript.md index aadec00ccd..0194fd787e 100644 --- a/docs/usage/usage-with-typescript.md +++ b/docs/usage/usage-with-typescript.md @@ -122,7 +122,7 @@ const store = configureStore({ untypedMiddleware as Middleware< (action: Action<'specialAction'>) => number, RootState - > + >, ) // prepend and concat calls can be chained .concat(logger), @@ -213,7 +213,7 @@ createReducer(0, (builder) => }) .addCase(decrement, (state, action: PayloadAction) => { // this would error out - }) + }), ) ``` @@ -311,7 +311,7 @@ const blogSlice = createSlice({ receivedAll: { reducer( state, - action: PayloadAction + action: PayloadAction, ) { state.all = action.payload state.meta = action.meta @@ -364,7 +364,7 @@ const fetchUserById = createAsyncThunk( async (userId: number) => { const response = await fetch(`https://reqres.in/api/users/${userId}`) return (await response.json()) as Returned - } + }, ) interface UsersState { @@ -438,7 +438,7 @@ create.asyncThunk( error: 'Oh no!', }) } - } + }, ) ``` @@ -446,8 +446,9 @@ For common thunk API configuration options, a [`withTypes` helper](../usage/usag ```ts no-transpile reducers: (create) => { - const createAThunk = - create.asyncThunk.withTypes<{ rejectValue: { error: string } }>() + const createAThunk = create.asyncThunk.withTypes<{ + rejectValue: { error: string } + }>() return { fetchTodo: createAThunk(async (id, thunkApi) => { @@ -478,7 +479,7 @@ interface GenericState { const createGenericSlice = < T, - Reducers extends SliceCaseReducers> + Reducers extends SliceCaseReducers>, >({ name = '', initialState, @@ -547,7 +548,7 @@ const fetchUserById = createAsyncThunk( // Inferred return type: Promise // highlight-next-line return (await response.json()) as MyData - } + }, ) // the parameter of `fetchUserById` is automatically inferred to `number` here @@ -791,7 +792,7 @@ export const fetchArticle = createAsyncThunk( } >(data, articleEntity) return normalized.entities - } + }, ) export const slice = createSlice({ diff --git a/docs/virtual/matchers/index.ts b/docs/virtual/matchers/index.ts index 501de36c1f..ff1e4fdba5 100644 --- a/docs/virtual/matchers/index.ts +++ b/docs/virtual/matchers/index.ts @@ -1,7 +1,7 @@ import { createAsyncThunk, createReducer, - PayloadAction + PayloadAction, } from '@reduxjs/toolkit' export interface Data { @@ -18,13 +18,13 @@ export interface Interesting extends Data { } export function isSpecial( - action: PayloadAction + action: PayloadAction, ): action is PayloadAction { return action.payload.isSpecial } export function isInteresting( - action: PayloadAction + action: PayloadAction, ): action is PayloadAction { return action.payload.isInteresting } @@ -36,7 +36,7 @@ export interface ExampleState { export const initialState = { isSpecial: false, - isInteresting: false + isInteresting: false, } as ExampleState export const isSpecialAndInterestingThunk = createAsyncThunk( @@ -44,16 +44,16 @@ export const isSpecialAndInterestingThunk = createAsyncThunk( () => { return { isSpecial: true, - isInteresting: true + isInteresting: true, } - } + }, ) export const requestThunk1 = createAsyncThunk('requestThunk1', () => ({})) export const requestThunk2 = createAsyncThunk('requestThunk2', () => ({})) -export const loadingReducer = createReducer(initialState, builder => { +export const loadingReducer = createReducer(initialState, (builder) => { builder.addCase(isSpecialAndInterestingThunk.fulfilled, (state, action) => { if (isSpecial(action)) { state.isSpecial = true diff --git a/examples/action-listener/counter/public/index.html b/examples/action-listener/counter/public/index.html index c1b40227ed..5e1a99228a 100644 --- a/examples/action-listener/counter/public/index.html +++ b/examples/action-listener/counter/public/index.html @@ -1,26 +1,28 @@ - + - + Counter Example - Action Middleware -
diff --git a/examples/publish-ci/react-native/android/app/build.gradle b/examples/publish-ci/react-native/android/app/build.gradle new file mode 100644 index 0000000000..0899b674ad --- /dev/null +++ b/examples/publish-ci/react-native/android/app/build.gradle @@ -0,0 +1,119 @@ +apply plugin: "com.android.application" +apply plugin: "org.jetbrains.kotlin.android" +apply plugin: "com.facebook.react" + +/** + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. + */ +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '..' + // root = file("../") + // The folder where the react-native NPM package is. Default is ../node_modules/react-native + // reactNativeDir = file("../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen + // codegenDir = file("../node_modules/@react-native/codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js + // cliFile = file("../node_modules/react-native/cli.js") + + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] +} + +/** + * Set this to true to Run Proguard on Release builds to minify the Java bytecode. + */ +def enableProguardInReleaseBuilds = false + +/** + * The preferred build flavor of JavaScriptCore (JSC) + * + * For example, to use the international variant, you can use: + * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'org.webkit:android-jsc:+' + +android { + ndkVersion rootProject.ext.ndkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + compileSdk rootProject.ext.compileSdkVersion + + namespace "com.reduxTemplate" + defaultConfig { + applicationId "com.reduxTemplate" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } +} + +dependencies { + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") + implementation("com.facebook.react:flipper-integration") + + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") + } else { + implementation jscFlavor + } +} + +apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) diff --git a/examples/publish-ci/react-native/android/app/debug.keystore b/examples/publish-ci/react-native/android/app/debug.keystore new file mode 100644 index 0000000000..364e105ed3 Binary files /dev/null and b/examples/publish-ci/react-native/android/app/debug.keystore differ diff --git a/examples/publish-ci/react-native/android/app/proguard-rules.pro b/examples/publish-ci/react-native/android/app/proguard-rules.pro new file mode 100644 index 0000000000..11b025724a --- /dev/null +++ b/examples/publish-ci/react-native/android/app/proguard-rules.pro @@ -0,0 +1,10 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: diff --git a/examples/publish-ci/react-native/android/app/src/debug/AndroidManifest.xml b/examples/publish-ci/react-native/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000000..eb98c01afd --- /dev/null +++ b/examples/publish-ci/react-native/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/examples/publish-ci/react-native/android/app/src/main/AndroidManifest.xml b/examples/publish-ci/react-native/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..4122f36a59 --- /dev/null +++ b/examples/publish-ci/react-native/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + diff --git a/examples/publish-ci/react-native/android/app/src/main/java/com/rr/MainActivity.kt b/examples/publish-ci/react-native/android/app/src/main/java/com/rr/MainActivity.kt new file mode 100644 index 0000000000..69d5655a0f --- /dev/null +++ b/examples/publish-ci/react-native/android/app/src/main/java/com/rr/MainActivity.kt @@ -0,0 +1,22 @@ +package com.reduxTemplate + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MainActivity : ReactActivity() { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "reduxTemplate" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate = + DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) +} diff --git a/examples/publish-ci/react-native/android/app/src/main/java/com/rr/MainApplication.kt b/examples/publish-ci/react-native/android/app/src/main/java/com/rr/MainApplication.kt new file mode 100644 index 0000000000..cbb688f4fe --- /dev/null +++ b/examples/publish-ci/react-native/android/app/src/main/java/com/rr/MainApplication.kt @@ -0,0 +1,45 @@ +package com.reduxTemplate + +import android.app.Application +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost +import com.facebook.react.flipper.ReactNativeFlipper +import com.facebook.soloader.SoLoader + +class MainApplication : Application(), ReactApplication { + + override val reactNativeHost: ReactNativeHost = + object : DefaultReactNativeHost(this) { + override fun getPackages(): List { + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + return PackageList(this).packages + } + + override fun getJSMainModuleName(): String = "index" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + + override val reactHost: ReactHost + get() = getDefaultReactHost(this.applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() + SoLoader.init(this, false) + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + load() + } + ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager) + } +} diff --git a/examples/publish-ci/react-native/android/app/src/main/res/drawable/rn_edit_text_material.xml b/examples/publish-ci/react-native/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 0000000000..73b37e4d99 --- /dev/null +++ b/examples/publish-ci/react-native/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/examples/publish-ci/react-native/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000..a2f5908281 Binary files /dev/null and b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/examples/publish-ci/react-native/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000..1b52399808 Binary files /dev/null and b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/examples/publish-ci/react-native/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000..ff10afd6e1 Binary files /dev/null and b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/examples/publish-ci/react-native/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000..115a4c768a Binary files /dev/null and b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000..dcd3cd8083 Binary files /dev/null and b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..459ca609d3 Binary files /dev/null and b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000..8ca12fe024 Binary files /dev/null and b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..8e19b410a1 Binary files /dev/null and b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000..b824ebdd48 Binary files /dev/null and b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000..4c19a13c23 Binary files /dev/null and b/examples/publish-ci/react-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/examples/publish-ci/react-native/android/app/src/main/res/values/strings.xml b/examples/publish-ci/react-native/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000000..4b35bb92d3 --- /dev/null +++ b/examples/publish-ci/react-native/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + reduxTemplate + diff --git a/examples/publish-ci/react-native/android/app/src/main/res/values/styles.xml b/examples/publish-ci/react-native/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000000..7ba83a2ad5 --- /dev/null +++ b/examples/publish-ci/react-native/android/app/src/main/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/examples/publish-ci/react-native/android/build.gradle b/examples/publish-ci/react-native/android/build.gradle new file mode 100644 index 0000000000..cb9d6232a7 --- /dev/null +++ b/examples/publish-ci/react-native/android/build.gradle @@ -0,0 +1,21 @@ +buildscript { + ext { + buildToolsVersion = "34.0.0" + minSdkVersion = 21 + compileSdkVersion = 34 + targetSdkVersion = 34 + ndkVersion = "25.1.8937393" + kotlinVersion = "1.8.0" + } + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle") + classpath("com.facebook.react:react-native-gradle-plugin") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") + } +} + +apply plugin: "com.facebook.react.rootproject" diff --git a/examples/publish-ci/react-native/android/gradle.properties b/examples/publish-ci/react-native/android/gradle.properties new file mode 100644 index 0000000000..a46a5b90fa --- /dev/null +++ b/examples/publish-ci/react-native/android/gradle.properties @@ -0,0 +1,41 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=false + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true diff --git a/examples/publish-ci/react-native/android/gradle/wrapper/gradle-wrapper.jar b/examples/publish-ci/react-native/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..7f93135c49 Binary files /dev/null and b/examples/publish-ci/react-native/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/examples/publish-ci/react-native/android/gradle/wrapper/gradle-wrapper.properties b/examples/publish-ci/react-native/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..d11cdd907d --- /dev/null +++ b/examples/publish-ci/react-native/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/examples/publish-ci/react-native/android/gradlew b/examples/publish-ci/react-native/android/gradlew new file mode 100644 index 0000000000..0adc8e1a53 --- /dev/null +++ b/examples/publish-ci/react-native/android/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/examples/publish-ci/react-native/android/gradlew.bat b/examples/publish-ci/react-native/android/gradlew.bat new file mode 100644 index 0000000000..6689b85bee --- /dev/null +++ b/examples/publish-ci/react-native/android/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/examples/publish-ci/react-native/android/settings.gradle b/examples/publish-ci/react-native/android/settings.gradle new file mode 100644 index 0000000000..3bccdf847e --- /dev/null +++ b/examples/publish-ci/react-native/android/settings.gradle @@ -0,0 +1,4 @@ +rootProject.name = 'reduxTemplate' +apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) +include ':app' +includeBuild('../node_modules/@react-native/gradle-plugin') diff --git a/examples/publish-ci/react-native/app.json b/examples/publish-ci/react-native/app.json new file mode 100644 index 0000000000..ae29bbd5ce --- /dev/null +++ b/examples/publish-ci/react-native/app.json @@ -0,0 +1,4 @@ +{ + "name": "reduxTemplate", + "displayName": "reduxTemplate" +} diff --git a/examples/publish-ci/react-native/babel.config.cts b/examples/publish-ci/react-native/babel.config.cts new file mode 100644 index 0000000000..f47f36ed05 --- /dev/null +++ b/examples/publish-ci/react-native/babel.config.cts @@ -0,0 +1,7 @@ +import type { TransformOptions } from "@babel/core" + +const config: TransformOptions = { + presets: ["module:@react-native/babel-preset"], +} + +export default config diff --git a/examples/publish-ci/react-native/globals.d.ts b/examples/publish-ci/react-native/globals.d.ts new file mode 100644 index 0000000000..41c7f89385 --- /dev/null +++ b/examples/publish-ci/react-native/globals.d.ts @@ -0,0 +1,13 @@ +declare module "*.gif" { + const logo: number + export default logo +} + +declare module "react-native/Libraries/NewAppScreen" { + import type { FC } from "react" + export const HermesBadge: FC +} + +declare module "react-native/Libraries/Core/Devtools/openURLInBrowser" { + export default function openURLInBrowser(url: string): void +} diff --git a/examples/publish-ci/react-native/index.js b/examples/publish-ci/react-native/index.js new file mode 100644 index 0000000000..affdc01fc3 --- /dev/null +++ b/examples/publish-ci/react-native/index.js @@ -0,0 +1,14 @@ +import React from "react" +import { AppRegistry } from "react-native" +import { Provider } from "react-redux" +import { App } from "./App" +import { name as appName } from "./app.json" +import { store } from "./src/app/store" + +AppRegistry.registerComponent(appName, () => () => ( + + + + + +)) diff --git a/examples/publish-ci/react-native/ios/.xcode.env b/examples/publish-ci/react-native/ios/.xcode.env new file mode 100644 index 0000000000..3d5782c715 --- /dev/null +++ b/examples/publish-ci/react-native/ios/.xcode.env @@ -0,0 +1,11 @@ +# This `.xcode.env` file is versioned and is used to source the environment +# used when running script phases inside Xcode. +# To customize your local environment, you can create an `.xcode.env.local` +# file that is not versioned. + +# NODE_BINARY variable contains the PATH to the node executable. +# +# Customize the NODE_BINARY variable here. +# For example, to use nvm with brew, add the following line +# . "$(brew --prefix nvm)/nvm.sh" --no-use +export NODE_BINARY=$(command -v node) diff --git a/examples/publish-ci/react-native/ios/Podfile b/examples/publish-ci/react-native/ios/Podfile new file mode 100644 index 0000000000..c5ef878269 --- /dev/null +++ b/examples/publish-ci/react-native/ios/Podfile @@ -0,0 +1,55 @@ +# Resolve react_native_pods.rb with node to allow for hoisting +require Pod::Executable.execute_command('node', ['-p', + 'require.resolve( + "react-native/scripts/react_native_pods.rb", + {paths: [process.argv[1]]}, + )', __dir__]).strip + +platform :ios, min_ios_version_supported +prepare_react_native_project! + +# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. +# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded +# +# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` +# ```js +# module.exports = { +# dependencies: { +# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), +# ``` +flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled + +linkage = ENV['USE_FRAMEWORKS'] +if linkage != nil + Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green + use_frameworks! :linkage => linkage.to_sym +end + +target 'reduxTemplate' do + config = use_native_modules! + + use_react_native!( + :path => config[:reactNativePath], + # Enables Flipper. + # + # Note that if you have use_frameworks! enabled, Flipper will not work and + # you should disable the next line. + :flipper_configuration => flipper_config, + # An absolute path to your application root. + :app_path => "#{Pod::Config.instance.installation_root}/.." + ) + + target 'reduxTemplateTests' do + inherit! :complete + # Pods for testing + end + + post_install do |installer| + # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 + react_native_post_install( + installer, + config[:reactNativePath], + :mac_catalyst_enabled => false + ) + end +end diff --git a/examples/publish-ci/react-native/ios/reactnativetemplate.xcodeproj/project.pbxproj b/examples/publish-ci/react-native/ios/reactnativetemplate.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..197d5f624a --- /dev/null +++ b/examples/publish-ci/react-native/ios/reactnativetemplate.xcodeproj/project.pbxproj @@ -0,0 +1,686 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 00E356F31AD99517003FC87E /* reactnativetemplateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* reactnativetemplateTests.m */; }; + 0C80B921A6F3F58F76C31292 /* libPods-reactnativetemplate.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-reactnativetemplate.a */; }; + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 7699B88040F8A987B510C191 /* libPods-reactnativetemplate-reactnativetemplateTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-reactnativetemplate-reactnativetemplateTests.a */; }; + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 13B07F861A680F5B00A75B9A; + remoteInfo = "reactnativetemplate"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 00E356EE1AD99517003FC87E /* reactnativetemplateTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "reactnativetemplateTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 00E356F21AD99517003FC87E /* reactnativetemplateTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "reactnativetemplateTests.m"; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* reactnativetemplate.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "reactnativetemplate.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = "reactnativetemplate/AppDelegate.h"; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = "reactnativetemplate/AppDelegate.mm"; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = "reactnativetemplate/Images.xcassets"; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = "reactnativetemplate/Info.plist"; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = "reactnativetemplate/main.m"; sourceTree = ""; }; + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-reactnativetemplate-reactnativetemplateTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-reactnativetemplate-reactnativetemplateTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B4392A12AC88292D35C810B /* Pods-reactnativetemplate.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-reactnativetemplate.debug.xcconfig"; path = "Target Support Files/Pods-reactnativetemplate/Pods-reactnativetemplate.debug.xcconfig"; sourceTree = ""; }; + 5709B34CF0A7D63546082F79 /* Pods-reactnativetemplate.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-reactnativetemplate.release.xcconfig"; path = "Target Support Files/Pods-reactnativetemplate/Pods-reactnativetemplate.release.xcconfig"; sourceTree = ""; }; + 5B7EB9410499542E8C5724F5 /* Pods-reactnativetemplate-reactnativetemplateTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-reactnativetemplate-reactnativetemplateTests.debug.xcconfig"; path = "Target Support Files/Pods-reactnativetemplate-reactnativetemplateTests/Pods-reactnativetemplate-reactnativetemplateTests.debug.xcconfig"; sourceTree = ""; }; + 5DCACB8F33CDC322A6C60F78 /* libPods-reactnativetemplate.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-reactnativetemplate.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = "reactnativetemplate/LaunchScreen.storyboard"; sourceTree = ""; }; + 89C6BE57DB24E9ADA2F236DE /* Pods-reactnativetemplate-reactnativetemplateTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-reactnativetemplate-reactnativetemplateTests.release.xcconfig"; path = "Target Support Files/Pods-reactnativetemplate-reactnativetemplateTests/Pods-reactnativetemplate-reactnativetemplateTests.release.xcconfig"; sourceTree = ""; }; + ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 00E356EB1AD99517003FC87E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7699B88040F8A987B510C191 /* libPods-reactnativetemplate-reactnativetemplateTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C80B921A6F3F58F76C31292 /* libPods-reactnativetemplate.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00E356EF1AD99517003FC87E /* reactnativetemplateTests */ = { + isa = PBXGroup; + children = ( + 00E356F21AD99517003FC87E /* reactnativetemplateTests.m */, + 00E356F01AD99517003FC87E /* Supporting Files */, + ); + path = "reactnativetemplateTests"; + sourceTree = ""; + }; + 00E356F01AD99517003FC87E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 00E356F11AD99517003FC87E /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* reactnativetemplate */ = { + isa = PBXGroup; + children = ( + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.mm */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, + 13B07FB71A68108700A75B9A /* main.m */, + ); + name = "reactnativetemplate"; + sourceTree = ""; + }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + 5DCACB8F33CDC322A6C60F78 /* libPods-reactnativetemplate.a */, + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-reactnativetemplate-reactnativetemplateTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + ); + name = Libraries; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* reactnativetemplate */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 00E356EF1AD99517003FC87E /* reactnativetemplateTests */, + 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, + BBD78D7AC51CEA395F1C20DB /* Pods */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* reactnativetemplate.app */, + 00E356EE1AD99517003FC87E /* reactnativetemplateTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + BBD78D7AC51CEA395F1C20DB /* Pods */ = { + isa = PBXGroup; + children = ( + 3B4392A12AC88292D35C810B /* Pods-reactnativetemplate.debug.xcconfig */, + 5709B34CF0A7D63546082F79 /* Pods-reactnativetemplate.release.xcconfig */, + 5B7EB9410499542E8C5724F5 /* Pods-reactnativetemplate-reactnativetemplateTests.debug.xcconfig */, + 89C6BE57DB24E9ADA2F236DE /* Pods-reactnativetemplate-reactnativetemplateTests.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 00E356ED1AD99517003FC87E /* reactnativetemplateTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "reactnativetemplateTests" */; + buildPhases = ( + A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */, + 00E356EA1AD99517003FC87E /* Sources */, + 00E356EB1AD99517003FC87E /* Frameworks */, + 00E356EC1AD99517003FC87E /* Resources */, + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */, + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 00E356F51AD99517003FC87E /* PBXTargetDependency */, + ); + name = reactnativetemplateTests; + productName = reactnativetemplateTests; + productReference = 00E356EE1AD99517003FC87E /* reactnativetemplateTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 13B07F861A680F5B00A75B9A /* reactnativetemplate */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "reactnativetemplate" */; + buildPhases = ( + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "reactnativetemplate"; + productName = "reactnativetemplate"; + productReference = 13B07F961A680F5B00A75B9A /* reactnativetemplate.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1210; + TargetAttributes = { + 00E356ED1AD99517003FC87E = { + CreatedOnToolsVersion = 6.2; + TestTargetID = 13B07F861A680F5B00A75B9A; + }; + 13B07F861A680F5B00A75B9A = { + LastSwiftMigration = 1120; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "reactnativetemplate" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* reactnativetemplate */, + 00E356ED1AD99517003FC87E /* reactnativetemplateTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 00E356EC1AD99517003FC87E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/.xcode.env", + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; + }; + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate/Pods-reactnativetemplate-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate/Pods-reactnativetemplate-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate/Pods-reactnativetemplate-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-reactnativetemplate-reactnativetemplateTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-reactnativetemplate-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate-reactnativetemplateTests/Pods-reactnativetemplate-reactnativetemplateTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate-reactnativetemplateTests/Pods-reactnativetemplate-reactnativetemplateTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate-reactnativetemplateTests/Pods-reactnativetemplate-reactnativetemplateTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate/Pods-reactnativetemplate-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate/Pods-reactnativetemplate-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate/Pods-reactnativetemplate-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate-reactnativetemplateTests/Pods-reactnativetemplate-reactnativetemplateTests-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate-reactnativetemplateTests/Pods-reactnativetemplate-reactnativetemplateTests-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-reactnativetemplate-reactnativetemplateTests/Pods-reactnativetemplate-reactnativetemplateTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 00E356EA1AD99517003FC87E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 00E356F31AD99517003FC87E /* reactnativetemplateTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, + 13B07FC11A68108700A75B9A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 13B07F861A680F5B00A75B9A /* reactnativetemplate */; + targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 00E356F61AD99517003FC87E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-reactnativetemplate-reactnativetemplateTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "reactnativetemplateTests/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/reactnativetemplate.app/reactnativetemplate"; + }; + name = Debug; + }; + 00E356F71AD99517003FC87E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-reactnativetemplate-reactnativetemplateTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COPY_PHASE_STRIP = NO; + INFOPLIST_FILE = "reactnativetemplateTests/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/reactnativetemplate.app/reactnativetemplate"; + }; + name = Release; + }; + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-reactnativetemplate.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = "reactnativetemplate/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "reduxTemplate"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "reactnativetemplate"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-reactnativetemplate.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + INFOPLIST_FILE = "reactnativetemplate/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "reduxTemplate"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "reactnativetemplate"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + ); + SDKROOT = iphoneos; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + ); + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "reactnativetemplateTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 00E356F61AD99517003FC87E /* Debug */, + 00E356F71AD99517003FC87E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "reactnativetemplate" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "reactnativetemplate" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/examples/publish-ci/react-native/ios/reactnativetemplate/AppDelegate.mm b/examples/publish-ci/react-native/ios/reactnativetemplate/AppDelegate.mm new file mode 100644 index 0000000000..fabca9073a --- /dev/null +++ b/examples/publish-ci/react-native/ios/reactnativetemplate/AppDelegate.mm @@ -0,0 +1,31 @@ +#import "AppDelegate.h" + +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.moduleName = @"reduxTemplate"; + // You can add your custom initial props in the dictionary below. + // They will be passed down to the ViewController used by React Native. + self.initialProps = @{}; + + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge +{ + return [self getBundleURL]; +} + +- (NSURL *)getBundleURL +{ +#if DEBUG + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; +#else + return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; +#endif +} + +@end diff --git a/examples/publish-ci/react-native/ios/reactnativetemplate/Info.plist b/examples/publish-ci/react-native/ios/reactnativetemplate/Info.plist new file mode 100644 index 0000000000..201411477c --- /dev/null +++ b/examples/publish-ci/react-native/ios/reactnativetemplate/Info.plist @@ -0,0 +1,52 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + reduxTemplate + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + + NSAllowsArbitraryLoads + + NSAllowsLocalNetworking + + + NSLocationWhenInUseUsageDescription + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/examples/publish-ci/react-native/ios/reactnativetemplate/LaunchScreen.storyboard b/examples/publish-ci/react-native/ios/reactnativetemplate/LaunchScreen.storyboard new file mode 100644 index 0000000000..a3202c1149 --- /dev/null +++ b/examples/publish-ci/react-native/ios/reactnativetemplate/LaunchScreen.storyboard @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/publish-ci/react-native/ios/reduxTemplate.xcodeproj/project.pbxproj b/examples/publish-ci/react-native/ios/reduxTemplate.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..f379fd6523 --- /dev/null +++ b/examples/publish-ci/react-native/ios/reduxTemplate.xcodeproj/project.pbxproj @@ -0,0 +1,686 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 00E356F31AD99517003FC87E /* reduxTemplateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* reduxTemplateTests.m */; }; + 0C80B921A6F3F58F76C31292 /* libPods-reduxTemplate.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-reduxTemplate.a */; }; + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 7699B88040F8A987B510C191 /* libPods-reduxTemplate-reduxTemplateTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-reduxTemplate-reduxTemplateTests.a */; }; + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 13B07F861A680F5B00A75B9A; + remoteInfo = "reduxTemplate"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 00E356EE1AD99517003FC87E /* reduxTemplateTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "reduxTemplateTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 00E356F21AD99517003FC87E /* reduxTemplateTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "reduxTemplateTests.m"; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* reduxTemplate.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "reduxTemplate.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = "reduxTemplate/AppDelegate.h"; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = "reduxTemplate/AppDelegate.mm"; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = "reduxTemplate/Images.xcassets"; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = "reduxTemplate/Info.plist"; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = "reduxTemplate/main.m"; sourceTree = ""; }; + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-reduxTemplate-reduxTemplateTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-reduxTemplate-reduxTemplateTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B4392A12AC88292D35C810B /* Pods-reduxTemplate.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-reduxTemplate.debug.xcconfig"; path = "Target Support Files/Pods-reduxTemplate/Pods-reduxTemplate.debug.xcconfig"; sourceTree = ""; }; + 5709B34CF0A7D63546082F79 /* Pods-reduxTemplate.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-reduxTemplate.release.xcconfig"; path = "Target Support Files/Pods-reduxTemplate/Pods-reduxTemplate.release.xcconfig"; sourceTree = ""; }; + 5B7EB9410499542E8C5724F5 /* Pods-reduxTemplate-reduxTemplateTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-reduxTemplate-reduxTemplateTests.debug.xcconfig"; path = "Target Support Files/Pods-reduxTemplate-reduxTemplateTests/Pods-reduxTemplate-reduxTemplateTests.debug.xcconfig"; sourceTree = ""; }; + 5DCACB8F33CDC322A6C60F78 /* libPods-reduxTemplate.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-reduxTemplate.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = "reduxTemplate/LaunchScreen.storyboard"; sourceTree = ""; }; + 89C6BE57DB24E9ADA2F236DE /* Pods-reduxTemplate-reduxTemplateTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-reduxTemplate-reduxTemplateTests.release.xcconfig"; path = "Target Support Files/Pods-reduxTemplate-reduxTemplateTests/Pods-reduxTemplate-reduxTemplateTests.release.xcconfig"; sourceTree = ""; }; + ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 00E356EB1AD99517003FC87E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7699B88040F8A987B510C191 /* libPods-reduxTemplate-reduxTemplateTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C80B921A6F3F58F76C31292 /* libPods-reduxTemplate.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00E356EF1AD99517003FC87E /* reduxTemplateTests */ = { + isa = PBXGroup; + children = ( + 00E356F21AD99517003FC87E /* reduxTemplateTests.m */, + 00E356F01AD99517003FC87E /* Supporting Files */, + ); + path = "reduxTemplateTests"; + sourceTree = ""; + }; + 00E356F01AD99517003FC87E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 00E356F11AD99517003FC87E /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* reduxTemplate */ = { + isa = PBXGroup; + children = ( + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.mm */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, + 13B07FB71A68108700A75B9A /* main.m */, + ); + name = "reduxTemplate"; + sourceTree = ""; + }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + 5DCACB8F33CDC322A6C60F78 /* libPods-reduxTemplate.a */, + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-reduxTemplate-reduxTemplateTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + ); + name = Libraries; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* reduxTemplate */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 00E356EF1AD99517003FC87E /* reduxTemplateTests */, + 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, + BBD78D7AC51CEA395F1C20DB /* Pods */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* reduxTemplate.app */, + 00E356EE1AD99517003FC87E /* reduxTemplateTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + BBD78D7AC51CEA395F1C20DB /* Pods */ = { + isa = PBXGroup; + children = ( + 3B4392A12AC88292D35C810B /* Pods-reduxTemplate.debug.xcconfig */, + 5709B34CF0A7D63546082F79 /* Pods-reduxTemplate.release.xcconfig */, + 5B7EB9410499542E8C5724F5 /* Pods-reduxTemplate-reduxTemplateTests.debug.xcconfig */, + 89C6BE57DB24E9ADA2F236DE /* Pods-reduxTemplate-reduxTemplateTests.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 00E356ED1AD99517003FC87E /* reduxTemplateTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "reduxTemplateTests" */; + buildPhases = ( + A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */, + 00E356EA1AD99517003FC87E /* Sources */, + 00E356EB1AD99517003FC87E /* Frameworks */, + 00E356EC1AD99517003FC87E /* Resources */, + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */, + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 00E356F51AD99517003FC87E /* PBXTargetDependency */, + ); + name = "reduxTemplateTests"; + productname = "reduxTemplateTests"; + productReference = 00E356EE1AD99517003FC87E /* reduxTemplateTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 13B07F861A680F5B00A75B9A /* reduxTemplate */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "reduxTemplate" */; + buildPhases = ( + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "reduxTemplate"; + productName = "reduxTemplate"; + productReference = 13B07F961A680F5B00A75B9A /* reduxTemplate.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1210; + TargetAttributes = { + 00E356ED1AD99517003FC87E = { + CreatedOnToolsVersion = 6.2; + TestTargetID = 13B07F861A680F5B00A75B9A; + }; + 13B07F861A680F5B00A75B9A = { + LastSwiftMigration = 1120; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "reduxTemplate" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* reduxTemplate */, + 00E356ED1AD99517003FC87E /* reduxTemplateTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 00E356EC1AD99517003FC87E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/.xcode.env", + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; + }; + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reduxTemplate/Pods-reduxTemplate-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reduxTemplate/Pods-reduxTemplate-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-reduxTemplate/Pods-reduxTemplate-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-reduxTemplate-reduxTemplateTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-reduxTemplate-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reduxTemplate-reduxTemplateTests/Pods-reduxTemplate-reduxTemplateTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reduxTemplate-reduxTemplateTests/Pods-reduxTemplate-reduxTemplateTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-reduxTemplate-reduxTemplateTests/Pods-reduxTemplate-reduxTemplateTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reduxTemplate/Pods-reduxTemplate-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reduxTemplate/Pods-reduxTemplate-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-reduxTemplate/Pods-reduxTemplate-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reduxTemplate-reduxTemplateTests/Pods-reduxTemplate-reduxTemplateTests-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-reduxTemplate-reduxTemplateTests/Pods-reduxTemplate-reduxTemplateTests-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-reduxTemplate-reduxTemplateTests/Pods-reduxTemplate-reduxTemplateTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 00E356EA1AD99517003FC87E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 00E356F31AD99517003FC87E /* reduxTemplateTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, + 13B07FC11A68108700A75B9A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 13B07F861A680F5B00A75B9A /* reduxTemplate */; + targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 00E356F61AD99517003FC87E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-reduxTemplate-reduxTemplateTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "reduxTemplateTests/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/reduxTemplate.app/reduxTemplate"; + }; + name = Debug; + }; + 00E356F71AD99517003FC87E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-reduxTemplate-reduxTemplateTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COPY_PHASE_STRIP = NO; + INFOPLIST_FILE = "reduxTemplateTests/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/reduxTemplate.app/reduxTemplate"; + }; + name = Release; + }; + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-reduxTemplate.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = "reduxTemplate/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "reduxTemplate"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "reduxTemplate"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-reduxTemplate.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + INFOPLIST_FILE = "reduxTemplate/Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "reduxTemplate"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "reduxTemplate"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + ); + SDKROOT = iphoneos; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + ); + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "reduxTemplateTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 00E356F61AD99517003FC87E /* Debug */, + 00E356F71AD99517003FC87E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "reduxTemplate" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "reduxTemplate" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/examples/publish-ci/react-native/ios/reduxTemplate.xcodeproj/xcshareddata/xcschemes/reduxTemplate.xcscheme b/examples/publish-ci/react-native/ios/reduxTemplate.xcodeproj/xcshareddata/xcschemes/reduxTemplate.xcscheme new file mode 100644 index 0000000000..974dd99db4 --- /dev/null +++ b/examples/publish-ci/react-native/ios/reduxTemplate.xcodeproj/xcshareddata/xcschemes/reduxTemplate.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/publish-ci/react-native/ios/reduxTemplate/AppDelegate.h b/examples/publish-ci/react-native/ios/reduxTemplate/AppDelegate.h new file mode 100644 index 0000000000..5d2808256c --- /dev/null +++ b/examples/publish-ci/react-native/ios/reduxTemplate/AppDelegate.h @@ -0,0 +1,6 @@ +#import +#import + +@interface AppDelegate : RCTAppDelegate + +@end diff --git a/examples/publish-ci/react-native/ios/reduxTemplate/AppDelegate.mm b/examples/publish-ci/react-native/ios/reduxTemplate/AppDelegate.mm new file mode 100644 index 0000000000..fabca9073a --- /dev/null +++ b/examples/publish-ci/react-native/ios/reduxTemplate/AppDelegate.mm @@ -0,0 +1,31 @@ +#import "AppDelegate.h" + +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.moduleName = @"reduxTemplate"; + // You can add your custom initial props in the dictionary below. + // They will be passed down to the ViewController used by React Native. + self.initialProps = @{}; + + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge +{ + return [self getBundleURL]; +} + +- (NSURL *)getBundleURL +{ +#if DEBUG + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; +#else + return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; +#endif +} + +@end diff --git a/examples/publish-ci/react-native/ios/reduxTemplate/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/publish-ci/react-native/ios/reduxTemplate/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..ddd7fca89e --- /dev/null +++ b/examples/publish-ci/react-native/ios/reduxTemplate/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,53 @@ +{ + "images": [ + { + "idiom": "iphone", + "scale": "2x", + "size": "20x20" + }, + { + "idiom": "iphone", + "scale": "3x", + "size": "20x20" + }, + { + "idiom": "iphone", + "scale": "2x", + "size": "29x29" + }, + { + "idiom": "iphone", + "scale": "3x", + "size": "29x29" + }, + { + "idiom": "iphone", + "scale": "2x", + "size": "40x40" + }, + { + "idiom": "iphone", + "scale": "3x", + "size": "40x40" + }, + { + "idiom": "iphone", + "scale": "2x", + "size": "60x60" + }, + { + "idiom": "iphone", + "scale": "3x", + "size": "60x60" + }, + { + "idiom": "ios-marketing", + "scale": "1x", + "size": "1024x1024" + } + ], + "info": { + "author": "xcode", + "version": 1 + } +} diff --git a/examples/publish-ci/react-native/ios/reduxTemplate/Images.xcassets/Contents.json b/examples/publish-ci/react-native/ios/reduxTemplate/Images.xcassets/Contents.json new file mode 100644 index 0000000000..97a8662ebd --- /dev/null +++ b/examples/publish-ci/react-native/ios/reduxTemplate/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/examples/publish-ci/react-native/ios/reduxTemplate/Info.plist b/examples/publish-ci/react-native/ios/reduxTemplate/Info.plist new file mode 100644 index 0000000000..201411477c --- /dev/null +++ b/examples/publish-ci/react-native/ios/reduxTemplate/Info.plist @@ -0,0 +1,52 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + reduxTemplate + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + + NSAllowsArbitraryLoads + + NSAllowsLocalNetworking + + + NSLocationWhenInUseUsageDescription + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/examples/publish-ci/react-native/ios/reduxTemplate/LaunchScreen.storyboard b/examples/publish-ci/react-native/ios/reduxTemplate/LaunchScreen.storyboard new file mode 100644 index 0000000000..a3202c1149 --- /dev/null +++ b/examples/publish-ci/react-native/ios/reduxTemplate/LaunchScreen.storyboard @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/publish-ci/react-native/ios/reduxTemplate/main.m b/examples/publish-ci/react-native/ios/reduxTemplate/main.m new file mode 100644 index 0000000000..d645c7246c --- /dev/null +++ b/examples/publish-ci/react-native/ios/reduxTemplate/main.m @@ -0,0 +1,10 @@ +#import + +#import "AppDelegate.h" + +int main(int argc, char *argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/publish-ci/react-native/ios/reduxTemplateTests/Info.plist b/examples/publish-ci/react-native/ios/reduxTemplateTests/Info.plist new file mode 100644 index 0000000000..ba72822e87 --- /dev/null +++ b/examples/publish-ci/react-native/ios/reduxTemplateTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/examples/publish-ci/react-native/ios/reduxTemplateTests/reduxTemplateTests.m b/examples/publish-ci/react-native/ios/reduxTemplateTests/reduxTemplateTests.m new file mode 100644 index 0000000000..e4a8819c3f --- /dev/null +++ b/examples/publish-ci/react-native/ios/reduxTemplateTests/reduxTemplateTests.m @@ -0,0 +1,66 @@ +#import +#import + +#import +#import + +#define TIMEOUT_SECONDS 600 +#define TEXT_TO_LOOK_FOR @"Welcome to React" + +@interface reduxTemplateTests : XCTestCase + +@end + +@implementation reduxTemplateTests + +- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test +{ + if (test(view)) { + return YES; + } + for (UIView *subview in [view subviews]) { + if ([self findSubviewInView:subview matching:test]) { + return YES; + } + } + return NO; +} + +- (void)testRendersWelcomeScreen +{ + UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; + BOOL foundElement = NO; + + __block NSString *redboxError = nil; +#ifdef DEBUG + RCTSetLogFunction( + ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { + if (level >= RCTLogLevelError) { + redboxError = message; + } + }); +#endif + + while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + + foundElement = [self findSubviewInView:vc.view + matching:^BOOL(UIView *view) { + if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { + return YES; + } + return NO; + }]; + } + +#ifdef DEBUG + RCTSetLogFunction(RCTDefaultLogFunction); +#endif + + XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); + XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); +} + +@end diff --git a/examples/publish-ci/react-native/jest-setup.ts b/examples/publish-ci/react-native/jest-setup.ts new file mode 100644 index 0000000000..39b76127b7 --- /dev/null +++ b/examples/publish-ci/react-native/jest-setup.ts @@ -0,0 +1 @@ +import "@testing-library/react-native/extend-expect" diff --git a/examples/publish-ci/react-native/jest.config.ts b/examples/publish-ci/react-native/jest.config.ts new file mode 100644 index 0000000000..efdcf5d53e --- /dev/null +++ b/examples/publish-ci/react-native/jest.config.ts @@ -0,0 +1,10 @@ +import type { Config } from "jest" + +const config: Config = { + preset: "react-native", + testEnvironment: "node", + setupFilesAfterEnv: ["/jest-setup.ts"], + fakeTimers: { enableGlobally: true }, +} + +export default config diff --git a/examples/publish-ci/react-native/metro.config.js b/examples/publish-ci/react-native/metro.config.js new file mode 100644 index 0000000000..e8ac2c799c --- /dev/null +++ b/examples/publish-ci/react-native/metro.config.js @@ -0,0 +1,12 @@ +/** @type {Pick & { getDefaultConfig: import('metro-config').getDefaultConfig }} */ +const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config") + +/** + * Metro configuration + * https://facebook.github.io/metro/docs/configuration + * + * @type {import('metro-config').MetroConfig} + */ +const config = {} + +module.exports = mergeConfig(getDefaultConfig(__dirname), config) diff --git a/examples/publish-ci/react-native/package.json b/examples/publish-ci/react-native/package.json new file mode 100644 index 0000000000..7aef98431f --- /dev/null +++ b/examples/publish-ci/react-native/package.json @@ -0,0 +1,49 @@ +{ + "name": "react-native-template-redux-typescript", + "version": "0.0.1", + "private": true, + "scripts": { + "build": "cd android && chmod +x ./gradlew && ./gradlew bundleRelease --no-daemon && cd .. && react-native build-android", + "android": "react-native run-android", + "ios": "react-native run-ios", + "lint": "eslint .", + "lint:fix": "eslint --fix .", + "format": "prettier --write .", + "start": "react-native start", + "test": "jest", + "type-check": "tsc --noEmit" + }, + "dependencies": { + "@reduxjs/toolkit": "^2.0.1", + "react": "18.2.0", + "react-native": "^0.73.2", + "react-redux": "^9.1.0" + }, + "devDependencies": { + "@babel/core": "^7.23.7", + "@babel/preset-env": "^7.23.8", + "@babel/runtime": "^7.23.8", + "@react-native/babel-preset": "^0.73.19", + "@react-native/eslint-config": "^0.74.0", + "@react-native/metro-config": "^0.73.3", + "@react-native/typescript-config": "^0.74.0", + "@testing-library/react-native": "^12.4.3", + "@types/jest": "^29.5.11", + "@types/react": "^18.2.47", + "@types/react-test-renderer": "^18.0.7", + "@typescript-eslint/eslint-plugin": "^6.18.1", + "@typescript-eslint/parser": "^6.18.1", + "babel-jest": "^29.7.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "jest": "^29.7.0", + "prettier": "^3.2.4", + "react-test-renderer": "18.2.0", + "ts-node": "^10.9.2", + "typescript": "^5.3.3" + }, + "engines": { + "node": ">=18" + } +} diff --git a/examples/publish-ci/react-native/react-native.config.mjs b/examples/publish-ci/react-native/react-native.config.mjs new file mode 100644 index 0000000000..cd913c6fc8 --- /dev/null +++ b/examples/publish-ci/react-native/react-native.config.mjs @@ -0,0 +1,10 @@ +/** @type {import('@react-native-community/cli-types').UserConfig } */ +const config = { + project: { + ios: { + automaticPodsInstallation: true, + }, + }, +} + +export default config diff --git a/examples/publish-ci/react-native/src/app/createAppSlice.ts b/examples/publish-ci/react-native/src/app/createAppSlice.ts new file mode 100644 index 0000000000..64afebbb60 --- /dev/null +++ b/examples/publish-ci/react-native/src/app/createAppSlice.ts @@ -0,0 +1,6 @@ +import { asyncThunkCreator, buildCreateSlice } from "@reduxjs/toolkit" + +// `buildCreateSlice` allows us to create a slice with async thunks. +export const createAppSlice = buildCreateSlice({ + creators: { asyncThunk: asyncThunkCreator }, +}) diff --git a/examples/publish-ci/react-native/src/app/hooks.ts b/examples/publish-ci/react-native/src/app/hooks.ts new file mode 100644 index 0000000000..428211afbf --- /dev/null +++ b/examples/publish-ci/react-native/src/app/hooks.ts @@ -0,0 +1,63 @@ +// This file serves as a central hub for re-exporting pre-typed Redux hooks. +// These imports are restricted elsewhere to ensure consistent +// usage of typed hooks throughout the application. +// We disable the ESLint rule here because this is the designated place +// for importing and re-exporting the typed versions of hooks. +/* eslint-disable @typescript-eslint/no-restricted-imports */ +import { useEffect, useRef } from "react" +import { Animated, useWindowDimensions } from "react-native" +import { useDispatch, useSelector } from "react-redux" +import type { AppDispatch, RootState } from "./store" + +// Use throughout your app instead of plain `useDispatch` and `useSelector` +export const useAppDispatch = useDispatch.withTypes() +export const useAppSelector = useSelector.withTypes() + +/** + * Custom React hook for calculating viewport units + * based on the current window dimensions. + * + * @returns An object containing the calculated viewport heigh and width values. + */ +export const useViewportUnits = () => { + const { width, height } = useWindowDimensions() + + const vh = height / 100 + const vw = width / 100 + + return { vh, vw } +} + +/** + * Custom React hook for creating a bounce animation effect. + * + * @param value - The maximum height to which the object should bounce. Defaults to 10 if not provided. + * @returns The `Animated.Value` object that can be used to drive animations. + */ +export const useBounceAnimation = (value = 10) => { + const bounce = useRef(new Animated.Value(0)).current + + bounce.interpolate({ + inputRange: [-300, -100, 0, 100, 101], + outputRange: [300, 0, 1, 0, 0], + }) + + useEffect(() => { + Animated.loop( + Animated.sequence([ + Animated.timing(bounce, { + toValue: value, + duration: 1500, + useNativeDriver: true, + }), + Animated.timing(bounce, { + toValue: 0, + duration: 1500, + useNativeDriver: true, + }), + ]), + ).start() + }, [bounce, value]) + + return bounce +} diff --git a/examples/publish-ci/react-native/src/app/store.ts b/examples/publish-ci/react-native/src/app/store.ts new file mode 100644 index 0000000000..9de880233d --- /dev/null +++ b/examples/publish-ci/react-native/src/app/store.ts @@ -0,0 +1,42 @@ +import type { Action, ThunkAction } from "@reduxjs/toolkit" +import { combineSlices, configureStore } from "@reduxjs/toolkit" +import { setupListeners } from "@reduxjs/toolkit/query" +import { counterSlice } from "../features/counter/counterSlice" +import { quotesApiSlice } from "../features/quotes/quotesApiSlice" + +// `combineSlices` automatically combines the reducers using +// their `reducerPath`s, therefore we no longer need to call `combineReducers`. +const rootReducer = combineSlices(counterSlice, quotesApiSlice) +// Infer the `RootState` type from the root reducer +export type RootState = ReturnType + +// The store setup is wrapped in `makeStore` to allow reuse +// when setting up tests that need the same store config +export const makeStore = (preloadedState?: Partial) => { + const store = configureStore({ + reducer: rootReducer, + // Adding the api middleware enables caching, invalidation, polling, + // and other useful features of `rtk-query`. + middleware: getDefaultMiddleware => { + return getDefaultMiddleware().concat(quotesApiSlice.middleware) + }, + preloadedState, + }) + // configure listeners using the provided defaults + // optional, but required for `refetchOnFocus`/`refetchOnReconnect` behaviors + setupListeners(store.dispatch) + return store +} + +export const store = makeStore() + +// Infer the type of `store` +export type AppStore = typeof store +// Infer the `AppDispatch` type from the store itself +export type AppDispatch = AppStore["dispatch"] +export type AppThunk = ThunkAction< + ThunkReturnType, + RootState, + unknown, + Action +> diff --git a/examples/publish-ci/react-native/src/components/AsyncButton.tsx b/examples/publish-ci/react-native/src/components/AsyncButton.tsx new file mode 100644 index 0000000000..138c0a3e18 --- /dev/null +++ b/examples/publish-ci/react-native/src/components/AsyncButton.tsx @@ -0,0 +1,73 @@ +import type { PropsWithChildren } from "react" +import { useRef } from "react" +import type { + GestureResponderEvent, + PressableProps, + ViewStyle, +} from "react-native" +import { Animated, Pressable, StyleSheet, View } from "react-native" + +type AsyncButtonProps = PressableProps & PropsWithChildren + +export const AsyncButton = ({ + onPress, + style, + children, + ...restProps +}: AsyncButtonProps) => { + const progress = useRef(new Animated.Value(0)).current + const opacity = useRef(new Animated.Value(1)).current + + const _onPress = (e: GestureResponderEvent) => { + progress.setValue(0) + opacity.setValue(1) + + onPress?.(e) + + Animated.timing(progress, { + toValue: 1, + duration: 1000, + useNativeDriver: false, + }).start(({ finished }) => { + if (!finished) { + return + } + + Animated.timing(opacity, { + toValue: 0, + duration: 200, + useNativeDriver: false, + }).start() + }) + } + + const progressInterpolate = progress.interpolate({ + inputRange: [0, 1], + outputRange: ["0%", "100%"], + extrapolate: "clamp", + }) + + const progressStyle: Animated.WithAnimatedObject = { + width: progressInterpolate, + opacity, + } + + return ( + + + + + {children} + + ) +} + +const styles = StyleSheet.create({ + progress: { + position: "absolute", + top: 0, + bottom: 0, + left: 0, + backgroundColor: "rgba(112,76,182, 0.15)", + }, +}) diff --git a/examples/publish-ci/react-native/src/components/Header.tsx b/examples/publish-ci/react-native/src/components/Header.tsx new file mode 100644 index 0000000000..ce2373cdd1 --- /dev/null +++ b/examples/publish-ci/react-native/src/components/Header.tsx @@ -0,0 +1,33 @@ +import { Animated, StyleSheet, View, useColorScheme } from "react-native" +import { useBounceAnimation, useViewportUnits } from "../app/hooks" +import { TypedColors } from "../constants/TypedColors" +import logo from "./logo.gif" + +export const Header = () => { + const isDarkMode = useColorScheme() === "dark" + const { vh } = useViewportUnits() + const bounce = useBounceAnimation() + const height = 40 * vh + + return ( + + + + ) +} + +const styles = StyleSheet.create({ + container: { + flexDirection: "row", + justifyContent: "center", + }, +}) diff --git a/examples/publish-ci/react-native/src/components/LearnReduxLinks.tsx b/examples/publish-ci/react-native/src/components/LearnReduxLinks.tsx new file mode 100644 index 0000000000..065f27ac36 --- /dev/null +++ b/examples/publish-ci/react-native/src/components/LearnReduxLinks.tsx @@ -0,0 +1,116 @@ +import { Fragment } from "react" +import { + StyleSheet, + Text, + TouchableOpacity, + View, + useColorScheme, +} from "react-native" +import openURLInBrowser from "react-native/Libraries/Core/Devtools/openURLInBrowser" +import { TypedColors } from "../constants/TypedColors" + +interface Link { + title: string + link: string + description: string +} + +const links: Link[] = [ + { + title: "React", + link: "https://reactjs.org", + description: "JavaScript library for building user interfaces", + }, + { + title: "Redux", + link: "https://redux.js.org", + description: "A Predictable State Container for JS Apps", + }, + { + title: "Redux Toolkit", + link: "https://redux-toolkit.js.org", + description: + "The official, opinionated, batteries-included toolset for efficient Redux development", + }, + { + title: "React Redux", + link: "https://react-redux.js.org", + description: "Official React bindings for Redux", + }, + { + title: "Reselect", + link: "https://reselect.js.org", + description: "A memoized selector library for Redux", + }, +] + +export const LearnReduxLinks = () => { + const isDarkMode = useColorScheme() === "dark" + + return ( + + {links.map((item, index) => { + return ( + + + { + openURLInBrowser(item.link) + }} + style={styles.linkContainer} + > + {item.title} + + {item.description} + + + + ) + })} + + ) +} + +const styles = StyleSheet.create({ + container: { + marginTop: 32, + paddingHorizontal: 24, + }, + linkContainer: { + flexWrap: "wrap", + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + paddingVertical: 8, + }, + link: { + flex: 2, + fontSize: 18, + fontWeight: "400", + color: TypedColors.primary, + }, + description: { + flex: 3, + paddingVertical: 16, + fontWeight: "400", + fontSize: 18, + }, + separator: { + height: 1, + }, +}) diff --git a/examples/publish-ci/react-native/src/components/Section.tsx b/examples/publish-ci/react-native/src/components/Section.tsx new file mode 100644 index 0000000000..c3246059fd --- /dev/null +++ b/examples/publish-ci/react-native/src/components/Section.tsx @@ -0,0 +1,48 @@ +import type { PropsWithChildren } from "react" +import { StyleSheet, Text, View, useColorScheme } from "react-native" +import { TypedColors } from "../constants/TypedColors" + +type SectionProps = PropsWithChildren<{ + title: string +}> + +export const Section = ({ children, title }: SectionProps) => { + const isDarkMode = useColorScheme() === "dark" + + return ( + + + {title} + + + {children} + + + ) +} + +const styles = StyleSheet.create({ + sectionContainer: { + marginTop: 32, + paddingHorizontal: 24, + }, + sectionTitle: { + fontSize: 24, + fontWeight: "600", + }, + sectionDescription: { + marginTop: 8, + fontSize: 18, + fontWeight: "400", + }, +}) diff --git a/examples/publish-ci/react-native/src/components/logo.gif b/examples/publish-ci/react-native/src/components/logo.gif new file mode 100644 index 0000000000..f0722c62fe Binary files /dev/null and b/examples/publish-ci/react-native/src/components/logo.gif differ diff --git a/examples/publish-ci/react-native/src/constants/TypedColors.ts b/examples/publish-ci/react-native/src/constants/TypedColors.ts new file mode 100644 index 0000000000..6d9addf872 --- /dev/null +++ b/examples/publish-ci/react-native/src/constants/TypedColors.ts @@ -0,0 +1,13 @@ +import { Colors } from "react-native/Libraries/NewAppScreen" + +interface AllColors { + primary: string + white: string + lighter: string + light: string + dark: string + darker: string + black: string +} + +export const TypedColors = Colors as AllColors diff --git a/examples/publish-ci/react-native/src/features/counter/Counter.tsx b/examples/publish-ci/react-native/src/features/counter/Counter.tsx new file mode 100644 index 0000000000..a50dab2cee --- /dev/null +++ b/examples/publish-ci/react-native/src/features/counter/Counter.tsx @@ -0,0 +1,130 @@ +import { useState } from "react" +import { + StyleSheet, + Text, + TextInput, + TouchableOpacity, + View, + useColorScheme, +} from "react-native" +import { useAppDispatch, useAppSelector } from "../../app/hooks" +import { AsyncButton } from "../../components/AsyncButton" +import { TypedColors } from "../../constants/TypedColors" +import { + decrement, + increment, + incrementAsync, + incrementByAmount, + incrementIfOdd, + selectCount, + selectStatus, +} from "./counterSlice" + +export const Counter = () => { + const isDarkMode = useColorScheme() === "dark" + const textStyle = { + color: isDarkMode ? TypedColors.light : TypedColors.dark, + } + + const dispatch = useAppDispatch() + const count = useAppSelector(selectCount) + const status = useAppSelector(selectStatus) + const [incrementAmount, setIncrementAmount] = useState("2") + + const incrementValue = Number(incrementAmount) || 0 + + return ( + + + dispatch(decrement())} + > + - + + + {count} + + dispatch(increment())} + > + + + + + + + + dispatch(incrementByAmount(incrementValue))} + > + Add Amount + + { + dispatch(incrementAsync(incrementValue)) + }} + > + Add Async + + { + dispatch(incrementIfOdd(incrementValue)) + }} + > + Add If Odd + + + + + ) +} + +const styles = StyleSheet.create({ + row: { + flexDirection: "row", + alignItems: "center", + justifyContent: "center", + flexWrap: "wrap", + }, + value: { + fontSize: 78, + paddingHorizontal: 16, + marginTop: 2, + }, + button: { + backgroundColor: "rgba(112, 76, 182, 0.1)", + borderRadius: 2, + paddingLeft: 12, + paddingRight: 12, + paddingBottom: 4, + margin: 2, + }, + buttonText: { + color: "rgb(112, 76, 182)", + fontSize: 32, + textAlign: "center", + }, + textbox: { + fontSize: 48, + padding: 2, + width: 64, + textAlign: "center", + marginRight: 8, + borderWidth: 1, + justifyContent: "center", + }, +}) diff --git a/examples/publish-ci/react-native/src/features/counter/counterAPI.ts b/examples/publish-ci/react-native/src/features/counter/counterAPI.ts new file mode 100644 index 0000000000..3b5174d147 --- /dev/null +++ b/examples/publish-ci/react-native/src/features/counter/counterAPI.ts @@ -0,0 +1,8 @@ +// A mock function to mimic making an async request for data +export const fetchCount = (amount = 1) => { + return new Promise<{ data: number }>(resolve => + setTimeout(() => { + resolve({ data: amount }) + }, 500), + ) +} diff --git a/examples/publish-ci/react-native/src/features/counter/counterSlice.test.ts b/examples/publish-ci/react-native/src/features/counter/counterSlice.test.ts new file mode 100644 index 0000000000..3b150132f8 --- /dev/null +++ b/examples/publish-ci/react-native/src/features/counter/counterSlice.test.ts @@ -0,0 +1,53 @@ +import { makeStore } from "../../app/store" +import type { CounterSliceState } from "./counterSlice" +import { + counterSlice, + decrement, + increment, + incrementByAmount, + selectCount, +} from "./counterSlice" + +describe("counter reducer", () => { + const initialState: CounterSliceState = { + value: 3, + status: "idle", + } + + let store = makeStore() + + beforeEach(() => { + store = makeStore({ counter: initialState }) + }) + + it("should handle initial state", () => { + expect(counterSlice.reducer(undefined, { type: "unknown" })).toStrictEqual({ + value: 0, + status: "idle", + }) + }) + + it("should handle increment", () => { + expect(selectCount(store.getState())).toBe(3) + + store.dispatch(increment()) + + expect(selectCount(store.getState())).toBe(4) + }) + + it("should handle decrement", () => { + expect(selectCount(store.getState())).toBe(3) + + store.dispatch(decrement()) + + expect(selectCount(store.getState())).toBe(2) + }) + + it("should handle incrementByAmount", () => { + expect(selectCount(store.getState())).toBe(3) + + store.dispatch(incrementByAmount(2)) + + expect(selectCount(store.getState())).toBe(5) + }) +}) diff --git a/examples/publish-ci/react-native/src/features/counter/counterSlice.ts b/examples/publish-ci/react-native/src/features/counter/counterSlice.ts new file mode 100644 index 0000000000..07bc1f5c3d --- /dev/null +++ b/examples/publish-ci/react-native/src/features/counter/counterSlice.ts @@ -0,0 +1,89 @@ +import type { PayloadAction } from "@reduxjs/toolkit" +import { createAppSlice } from "../../app/createAppSlice" +import type { AppThunk } from "../../app/store" +import { fetchCount } from "./counterAPI" + +export interface CounterSliceState { + value: number + status: "idle" | "loading" | "failed" +} + +const initialState: CounterSliceState = { + value: 0, + status: "idle", +} + +// If you are not using async thunks you can use the standalone `createSlice`. +export const counterSlice = createAppSlice({ + name: "counter", + // `createSlice` will infer the state type from the `initialState` argument + initialState, + // The `reducers` field lets us define reducers and generate associated actions + reducers: create => ({ + increment: create.reducer(state => { + // Redux Toolkit allows us to write "mutating" logic in reducers. It + // doesn't actually mutate the state because it uses the Immer library, + // which detects changes to a "draft state" and produces a brand new + // immutable state based off those changes + state.value += 1 + }), + decrement: create.reducer(state => { + state.value -= 1 + }), + // Use the `PayloadAction` type to declare the contents of `action.payload` + incrementByAmount: create.reducer( + (state, action: PayloadAction) => { + state.value += action.payload + }, + ), + // The function below is called a thunk and allows us to perform async logic. It + // can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This + // will call the thunk with the `dispatch` function as the first argument. Async + // code can then be executed and other actions can be dispatched. Thunks are + // typically used to make async requests. + incrementAsync: create.asyncThunk( + async (amount: number) => { + const response = await fetchCount(amount) + // The value we return becomes the `fulfilled` action payload + return response.data + }, + { + pending: state => { + state.status = "loading" + }, + fulfilled: (state, action) => { + state.status = "idle" + state.value += action.payload + }, + rejected: state => { + state.status = "failed" + }, + }, + ), + }), + // You can define your selectors here. These selectors receive the slice + // state as their first argument. + selectors: { + selectCount: counter => counter.value, + selectStatus: counter => counter.status, + }, +}) + +// Action creators are generated for each case reducer function. +export const { decrement, increment, incrementByAmount, incrementAsync } = + counterSlice.actions + +// Selectors returned by `slice.selectors` take the root state as their first argument. +export const { selectCount, selectStatus } = counterSlice.selectors + +// We can also write thunks by hand, which may contain both sync and async logic. +// Here's an example of conditionally dispatching actions based on current state. +export const incrementIfOdd = + (amount: number): AppThunk => + (dispatch, getState) => { + const currentValue = selectCount(getState()) + + if (currentValue % 2 === 1 || currentValue % 2 === -1) { + dispatch(incrementByAmount(amount)) + } + } diff --git a/examples/publish-ci/react-native/src/features/quotes/Quotes.tsx b/examples/publish-ci/react-native/src/features/quotes/Quotes.tsx new file mode 100644 index 0000000000..f27db6077e --- /dev/null +++ b/examples/publish-ci/react-native/src/features/quotes/Quotes.tsx @@ -0,0 +1,153 @@ +import { useState } from "react" +import { + Modal, + ScrollView, + StyleSheet, + Text, + TouchableOpacity, + View, + useColorScheme, +} from "react-native" +import { TypedColors } from "../../constants/TypedColors" +import { useGetQuotesQuery } from "./quotesApiSlice" + +const options = [5, 10, 20, 30] + +export const Quotes = () => { + const isDarkMode = useColorScheme() === "dark" + const textStyle = { + color: isDarkMode ? TypedColors.light : TypedColors.dark, + } + const backgroundStyle = { + backgroundColor: isDarkMode ? TypedColors.darker : TypedColors.lighter, + } + + const [numberOfQuotes, setNumberOfQuotes] = useState(10) + const [modalVisible, setModalVisible] = useState(false) + // Using a query hook automatically fetches data and returns query values + const { data, isError, isLoading, isSuccess } = + useGetQuotesQuery(numberOfQuotes) + + if (isError) { + return There was an error!!! + } + + if (isLoading) { + return Loading... + } + + const pickNumberOfQuotes = (value: number) => { + setNumberOfQuotes(value) + setModalVisible(false) + } + + if (isSuccess) { + return ( + + { + setModalVisible(true) + }} + style={styles.button} + > + + Select the Quantity of Quotes to Fetch: {numberOfQuotes} + + + + { + setModalVisible(false) + }} + > + + + {options.map(option => ( + { + pickNumberOfQuotes(option) + }} + > + {option} + + ))} + + + + + { + + {data.quotes.map(({ author, quote, id }) => ( + + {`"${quote}"`} + - {author} + + ))} + + } + + ) + } + + return null +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: "center", + justifyContent: "center", + padding: 20, + }, + button: { + padding: 10, + backgroundColor: "rgba(112, 76, 182, 0.1)", + borderRadius: 5, + }, + buttonText: { + color: "rgb(112, 76, 182)", + fontSize: 18, + textAlign: "center", + margin: 5, + }, + modalView: { + margin: 20, + borderRadius: 5, + padding: 20, + alignItems: "center", + elevation: 5, + }, + option: { + fontSize: 30, + padding: 10, + borderBottomWidth: 1, + borderBottomColor: "#CCC", + }, + optionText: { + fontSize: 20, + }, + quotesList: { + width: "auto", + }, + quoteContainer: { + padding: 10, + borderRadius: 5, + marginVertical: 5, + }, + quoteText: { + fontStyle: "italic", + }, + author: { + fontWeight: "bold", + textAlign: "right", + marginTop: 5, + }, +}) diff --git a/examples/publish-ci/react-native/src/features/quotes/quotesApiSlice.ts b/examples/publish-ci/react-native/src/features/quotes/quotesApiSlice.ts new file mode 100644 index 0000000000..a1c7b5a248 --- /dev/null +++ b/examples/publish-ci/react-native/src/features/quotes/quotesApiSlice.ts @@ -0,0 +1,38 @@ +// Need to use the React-specific entry point to import `createApi` +import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react" + +interface Quote { + id: number + quote: string + author: string +} + +interface QuotesApiResponse { + quotes: Quote[] + total: number + skip: number + limit: number +} + +// Define a service using a base URL and expected endpoints +export const quotesApiSlice = createApi({ + baseQuery: fetchBaseQuery({ baseUrl: "https://dummyjson.com/quotes" }), + reducerPath: "quotesApi", + // Tag types are used for caching and invalidation. + tagTypes: ["Quotes"], + endpoints: build => ({ + // Supply generics for the return type (in this case `QuotesApiResponse`) + // and the expected query argument. If there is no argument, use `void` + // for the argument type instead. + getQuotes: build.query({ + query: (limit = 10) => `?limit=${limit}`, + // `providesTags` determines which 'tag' is attached to the + // cached data returned by the query. + providesTags: (result, error, id) => [{ type: "Quotes", id }], + }), + }), +}) + +// Hooks are auto-generated by RTK-Query +// Same as `quotesApiSlice.endpoints.getQuotes.useQuery` +export const { useGetQuotesQuery } = quotesApiSlice diff --git a/examples/publish-ci/react-native/src/utils/test-utils.tsx b/examples/publish-ci/react-native/src/utils/test-utils.tsx new file mode 100644 index 0000000000..8b4ba76544 --- /dev/null +++ b/examples/publish-ci/react-native/src/utils/test-utils.tsx @@ -0,0 +1,64 @@ +import type { RenderOptions } from "@testing-library/react-native" +import { render, userEvent } from "@testing-library/react-native" +import type { PropsWithChildren, ReactElement } from "react" +import { Provider } from "react-redux" +import type { AppStore, RootState } from "../app/store" +import { makeStore } from "../app/store" + +/** + * This type extends the default options for + * React Testing Library's render function. It allows for + * additional configuration such as specifying an initial Redux state and + * a custom store instance. + */ +interface ExtendedRenderOptions extends Omit { + /** + * Defines a specific portion or the entire initial state for the Redux store. + * This is particularly useful for initializing the state in a + * controlled manner during testing, allowing components to be rendered + * with predetermined state conditions. + */ + preloadedState?: Partial + + /** + * Allows the use of a specific Redux store instance instead of a + * default or global store. This flexibility is beneficial when + * testing components with unique store requirements or when isolating + * tests from a global store state. The custom store should be configured + * to match the structure and middleware of the store used by the application. + * + * @default makeStore(preloadedState) + */ + store?: AppStore +} + +/** + * Renders the given React element with Redux Provider and custom store. + * This function is useful for testing components that are connected to the Redux store. + * + * @param ui - The React component or element to render. + * @param extendedRenderOptions - Optional configuration options for rendering. This includes `preloadedState` for initial Redux state and `store` for a specific Redux store instance. Any additional properties are passed to React Testing Library's render function. + * @returns An object containing the Redux store used in the render, User event API for simulating user interactions in tests, and all of React Testing Library's query functions for testing the component. + */ +export const renderWithProviders = ( + ui: ReactElement, + extendedRenderOptions: ExtendedRenderOptions = {}, +) => { + const { + preloadedState = {}, + // Automatically create a store instance if no store was passed in + store = makeStore(preloadedState), + ...renderOptions + } = extendedRenderOptions + + const Wrapper = ({ children }: PropsWithChildren) => ( + {children} + ) + + // Return an object with the store and all of RTL's query functions + return { + store, + user: userEvent.setup(), + ...render(ui, { wrapper: Wrapper, ...renderOptions }), + } +} diff --git a/examples/publish-ci/react-native/tsconfig.json b/examples/publish-ci/react-native/tsconfig.json new file mode 100644 index 0000000000..13b5ca4f73 --- /dev/null +++ b/examples/publish-ci/react-native/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@react-native/typescript-config/tsconfig.json", +} diff --git a/examples/publish-ci/react-native/yarn.lock b/examples/publish-ci/react-native/yarn.lock new file mode 100644 index 0000000000..02cd5be44e --- /dev/null +++ b/examples/publish-ci/react-native/yarn.lock @@ -0,0 +1,9799 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + +__metadata: + version: 6 + cacheKey: 8 + +"@aashutoshrathi/word-wrap@npm:^1.2.3": + version: 1.2.6 + resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" + checksum: ada901b9e7c680d190f1d012c84217ce0063d8f5c5a7725bb91ec3c5ed99bb7572680eb2d2938a531ccbaec39a95422fcd8a6b4a13110c7d98dd75402f66a0cd + languageName: node + linkType: hard + +"@ampproject/remapping@npm:^2.2.0": + version: 2.2.1 + resolution: "@ampproject/remapping@npm:2.2.1" + dependencies: + "@jridgewell/gen-mapping": ^0.3.0 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 03c04fd526acc64a1f4df22651186f3e5ef0a9d6d6530ce4482ec9841269cf7a11dbb8af79237c282d721c5312024ff17529cd72cc4768c11e999b58e2302079 + languageName: node + linkType: hard + +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/code-frame@npm:7.23.5" + dependencies: + "@babel/highlight": ^7.23.4 + chalk: ^2.4.2 + checksum: d90981fdf56a2824a9b14d19a4c0e8db93633fd488c772624b4e83e0ceac6039a27cd298a247c3214faa952bf803ba23696172ae7e7235f3b97f43ba278c569a + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.20.5, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.23.3, @babel/compat-data@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/compat-data@npm:7.23.5" + checksum: 06ce244cda5763295a0ea924728c09bae57d35713b675175227278896946f922a63edf803c322f855a3878323d48d0255a2a3023409d2a123483c8a69ebb4744 + languageName: node + linkType: hard + +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.13.16, @babel/core@npm:^7.20.0, @babel/core@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/core@npm:7.23.7" + dependencies: + "@ampproject/remapping": ^2.2.0 + "@babel/code-frame": ^7.23.5 + "@babel/generator": ^7.23.6 + "@babel/helper-compilation-targets": ^7.23.6 + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helpers": ^7.23.7 + "@babel/parser": ^7.23.6 + "@babel/template": ^7.22.15 + "@babel/traverse": ^7.23.7 + "@babel/types": ^7.23.6 + convert-source-map: ^2.0.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.2 + json5: ^2.2.3 + semver: ^6.3.1 + checksum: 32d5bf73372a47429afaae9adb0af39e47bcea6a831c4b5dcbb4791380cda6949cb8cb1a2fea8b60bb1ebe189209c80e333903df1fa8e9dcb04798c0ce5bf59e + languageName: node + linkType: hard + +"@babel/eslint-parser@npm:^7.20.0": + version: 7.23.3 + resolution: "@babel/eslint-parser@npm:7.23.3" + dependencies: + "@nicolo-ribaudo/eslint-scope-5-internals": 5.1.1-v1 + eslint-visitor-keys: ^2.1.0 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 + checksum: 9573daebe21af5123c302c307be80cacf1c2bf236a9497068a14726d3944ef55e1282519d0ccf51882dfc369359a3442299c98cb22a419e209924db39d4030fd + languageName: node + linkType: hard + +"@babel/generator@npm:^7.20.0, @babel/generator@npm:^7.23.6, @babel/generator@npm:^7.7.2": + version: 7.23.6 + resolution: "@babel/generator@npm:7.23.6" + dependencies: + "@babel/types": ^7.23.6 + "@jridgewell/gen-mapping": ^0.3.2 + "@jridgewell/trace-mapping": ^0.3.17 + jsesc: ^2.5.1 + checksum: 1a1a1c4eac210f174cd108d479464d053930a812798e09fee069377de39a893422df5b5b146199ead7239ae6d3a04697b45fc9ac6e38e0f6b76374390f91fc6c + languageName: node + linkType: hard + +"@babel/helper-annotate-as-pure@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 53da330f1835c46f26b7bf4da31f7a496dee9fd8696cca12366b94ba19d97421ce519a74a837f687749318f94d1a37f8d1abcbf35e8ed22c32d16373b2f6198d + languageName: node + linkType: hard + +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.22.15" + dependencies: + "@babel/types": ^7.22.15 + checksum: 639c697a1c729f9fafa2dd4c9af2e18568190299b5907bd4c2d0bc818fcbd1e83ffeecc2af24327a7faa7ac4c34edd9d7940510a5e66296c19bad17001cf5c7a + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.20.7, @babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.23.6": + version: 7.23.6 + resolution: "@babel/helper-compilation-targets@npm:7.23.6" + dependencies: + "@babel/compat-data": ^7.23.5 + "@babel/helper-validator-option": ^7.23.5 + browserslist: ^4.22.2 + lru-cache: ^5.1.1 + semver: ^6.3.1 + checksum: c630b98d4527ac8fe2c58d9a06e785dfb2b73ec71b7c4f2ddf90f814b5f75b547f3c015f110a010fd31f76e3864daaf09f3adcd2f6acdbfb18a8de3a48717590 + languageName: node + linkType: hard + +"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.6": + version: 7.23.7 + resolution: "@babel/helper-create-class-features-plugin@npm:7.23.7" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-member-expression-to-functions": ^7.23.0 + "@babel/helper-optimise-call-expression": ^7.22.5 + "@babel/helper-replace-supers": ^7.22.20 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 33e60714b856c3816a7965d4c76278cc8f430644a2dfc4eeafad2f7167c4fbd2becdb74cbfeb04b02efd6bbd07176ef53c6683262b588e65d378438e9c55c26b + languageName: node + linkType: hard + +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.15, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": + version: 7.22.15 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.15" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + regexpu-core: ^5.3.1 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 0243b8d4854f1dc8861b1029a46d3f6393ad72f366a5a08e36a4648aa682044f06da4c6e87a456260e1e1b33c999f898ba591a0760842c1387bcc93fbf2151a6 + languageName: node + linkType: hard + +"@babel/helper-define-polyfill-provider@npm:^0.4.4": + version: 0.4.4 + resolution: "@babel/helper-define-polyfill-provider@npm:0.4.4" + dependencies: + "@babel/helper-compilation-targets": ^7.22.6 + "@babel/helper-plugin-utils": ^7.22.5 + debug: ^4.1.1 + lodash.debounce: ^4.0.8 + resolve: ^1.14.2 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 2453cdd79f18a4cb8653d8a7e06b2eb0d8e31bae0d35070fc5abadbddca246a36d82b758064b421cca49b48d0e696d331d54520ba8582c1d61fb706d6d831817 + languageName: node + linkType: hard + +"@babel/helper-environment-visitor@npm:^7.18.9, @babel/helper-environment-visitor@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-environment-visitor@npm:7.22.20" + checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 + languageName: node + linkType: hard + +"@babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" + dependencies: + "@babel/template": ^7.22.15 + "@babel/types": ^7.23.0 + checksum: e44542257b2d4634a1f979244eb2a4ad8e6d75eb6761b4cfceb56b562f7db150d134bc538c8e6adca3783e3bc31be949071527aa8e3aab7867d1ad2d84a26e10 + languageName: node + linkType: hard + +"@babel/helper-hoist-variables@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-hoist-variables@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 394ca191b4ac908a76e7c50ab52102669efe3a1c277033e49467913c7ed6f7c64d7eacbeabf3bed39ea1f41731e22993f763b1edce0f74ff8563fd1f380d92cc + languageName: node + linkType: hard + +"@babel/helper-member-expression-to-functions@npm:^7.22.15, @babel/helper-member-expression-to-functions@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0" + dependencies: + "@babel/types": ^7.23.0 + checksum: 494659361370c979ada711ca685e2efe9460683c36db1b283b446122596602c901e291e09f2f980ecedfe6e0f2bd5386cb59768285446530df10c14df1024e75 + languageName: node + linkType: hard + +"@babel/helper-module-imports@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-module-imports@npm:7.22.15" + dependencies: + "@babel/types": ^7.22.15 + checksum: ecd7e457df0a46f889228f943ef9b4a47d485d82e030676767e6a2fdcbdaa63594d8124d4b55fd160b41c201025aec01fc27580352b1c87a37c9c6f33d116702 + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/helper-module-transforms@npm:7.23.3" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-simple-access": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + "@babel/helper-validator-identifier": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 5d0895cfba0e16ae16f3aa92fee108517023ad89a855289c4eb1d46f7aef4519adf8e6f971e1d55ac20c5461610e17213f1144097a8f932e768a9132e2278d71 + languageName: node + linkType: hard + +"@babel/helper-optimise-call-expression@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: c70ef6cc6b6ed32eeeec4482127e8be5451d0e5282d5495d5d569d39eb04d7f1d66ec99b327f45d1d5842a9ad8c22d48567e93fc502003a47de78d122e355f7c + languageName: node + linkType: hard + +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": + version: 7.22.5 + resolution: "@babel/helper-plugin-utils@npm:7.22.5" + checksum: c0fc7227076b6041acd2f0e818145d2e8c41968cc52fb5ca70eed48e21b8fe6dd88a0a91cbddf4951e33647336eb5ae184747ca706817ca3bef5e9e905151ff5 + languageName: node + linkType: hard + +"@babel/helper-remap-async-to-generator@npm:^7.18.9, @babel/helper-remap-async-to-generator@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-remap-async-to-generator@npm:7.22.20" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-wrap-function": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 2fe6300a6f1b58211dffa0aed1b45d4958506d096543663dba83bd9251fe8d670fa909143a65b45e72acb49e7e20fbdb73eae315d9ddaced467948c3329986e7 + languageName: node + linkType: hard + +"@babel/helper-replace-supers@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-replace-supers@npm:7.22.20" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-member-expression-to-functions": ^7.22.15 + "@babel/helper-optimise-call-expression": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: a0008332e24daedea2e9498733e3c39b389d6d4512637e000f96f62b797e702ee24a407ccbcd7a236a551590a38f31282829a8ef35c50a3c0457d88218cae639 + languageName: node + linkType: hard + +"@babel/helper-simple-access@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-simple-access@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: fe9686714caf7d70aedb46c3cce090f8b915b206e09225f1e4dbc416786c2fdbbee40b38b23c268b7ccef749dd2db35f255338fb4f2444429874d900dede5ad2 + languageName: node + linkType: hard + +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.20.0, @babel/helper-skip-transparent-expression-wrappers@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 1012ef2295eb12dc073f2b9edf3425661e9b8432a3387e62a8bc27c42963f1f216ab3124228015c748770b2257b4f1fda882ca8fa34c0bf485e929ae5bc45244 + languageName: node + linkType: hard + +"@babel/helper-split-export-declaration@npm:^7.22.6": + version: 7.22.6 + resolution: "@babel/helper-split-export-declaration@npm:7.22.6" + dependencies: + "@babel/types": ^7.22.5 + checksum: e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921 + languageName: node + linkType: hard + +"@babel/helper-string-parser@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/helper-string-parser@npm:7.23.4" + checksum: c0641144cf1a7e7dc93f3d5f16d5327465b6cf5d036b48be61ecba41e1eece161b48f46b7f960951b67f8c3533ce506b16dece576baef4d8b3b49f8c65410f90 + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-validator-identifier@npm:7.22.20" + checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.22.15, @babel/helper-validator-option@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helper-validator-option@npm:7.23.5" + checksum: 537cde2330a8aede223552510e8a13e9c1c8798afee3757995a7d4acae564124fe2bf7e7c3d90d62d3657434a74340a274b3b3b1c6f17e9a2be1f48af29cb09e + languageName: node + linkType: hard + +"@babel/helper-wrap-function@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-wrap-function@npm:7.22.20" + dependencies: + "@babel/helper-function-name": ^7.22.5 + "@babel/template": ^7.22.15 + "@babel/types": ^7.22.19 + checksum: 221ed9b5572612aeb571e4ce6a256f2dee85b3c9536f1dd5e611b0255e5f59a3d0ec392d8d46d4152149156a8109f92f20379b1d6d36abb613176e0e33f05fca + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.23.7": + version: 7.23.8 + resolution: "@babel/helpers@npm:7.23.8" + dependencies: + "@babel/template": ^7.22.15 + "@babel/traverse": ^7.23.7 + "@babel/types": ^7.23.6 + checksum: 8b522d527921f8df45a983dc7b8e790c021250addf81ba7900ba016e165442a527348f6f877aa55e1debb3eef9e860a334b4e8d834e6c9b438ed61a63d9a7ad4 + languageName: node + linkType: hard + +"@babel/highlight@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/highlight@npm:7.23.4" + dependencies: + "@babel/helper-validator-identifier": ^7.22.20 + chalk: ^2.4.2 + js-tokens: ^4.0.0 + checksum: 643acecdc235f87d925979a979b539a5d7d1f31ae7db8d89047269082694122d11aa85351304c9c978ceeb6d250591ccadb06c366f358ccee08bb9c122476b89 + languageName: node + linkType: hard + +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.6": + version: 7.23.6 + resolution: "@babel/parser@npm:7.23.6" + bin: + parser: ./bin/babel-parser.js + checksum: 140801c43731a6c41fd193f5c02bc71fd647a0360ca616b23d2db8be4b9739b9f951a03fc7c2db4f9b9214f4b27c1074db0f18bc3fa653783082d5af7c8860d5 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: ddbaf2c396b7780f15e80ee01d6dd790db076985f3dfeb6527d1a8d4cacf370e49250396a3aa005b2c40233cac214a106232f83703d5e8491848bde273938232 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/plugin-transform-optional-chaining": ^7.23.3 + peerDependencies: + "@babel/core": ^7.13.0 + checksum: 434b9d710ae856fa1a456678cc304fbc93915af86d581ee316e077af746a709a741ea39d7e1d4f5b98861b629cc7e87f002d3138f5e836775632466d4c74aef2 + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.23.7" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: f88e400b548202a6f8c5dfd25bc4949a13ea1ccb64a170d7dea4deaa655a0fcb001d3fd61c35e1ad9c09a3d5f0d43f783400425471fe6d660ccaf33dabea9aba + languageName: node + linkType: hard + +"@babel/plugin-proposal-async-generator-functions@npm:^7.0.0": + version: 7.20.7 + resolution: "@babel/plugin-proposal-async-generator-functions@npm:7.20.7" + dependencies: + "@babel/helper-environment-visitor": ^7.18.9 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-remap-async-to-generator": ^7.18.9 + "@babel/plugin-syntax-async-generators": ^7.8.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 111109ee118c9e69982f08d5e119eab04190b36a0f40e22e873802d941956eee66d2aa5a15f5321e51e3f9aa70a91136451b987fe15185ef8cc547ac88937723 + languageName: node + linkType: hard + +"@babel/plugin-proposal-class-properties@npm:^7.13.0, @babel/plugin-proposal-class-properties@npm:^7.18.0": + version: 7.18.6 + resolution: "@babel/plugin-proposal-class-properties@npm:7.18.6" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 49a78a2773ec0db56e915d9797e44fd079ab8a9b2e1716e0df07c92532f2c65d76aeda9543883916b8e0ff13606afeffa67c5b93d05b607bc87653ad18a91422 + languageName: node + linkType: hard + +"@babel/plugin-proposal-export-default-from@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-proposal-export-default-from@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-export-default-from": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f5a438413b8728cbf5a76ef65510418e5e2e1c82292ee4a031a0c941bee488f7e7dec960c1fd314a42bfadf40ffa9a4ef5c1aa1b3c906b9bc140d4530e7bc8be + languageName: node + linkType: hard + +"@babel/plugin-proposal-nullish-coalescing-operator@npm:^7.13.8, @babel/plugin-proposal-nullish-coalescing-operator@npm:^7.18.0": + version: 7.18.6 + resolution: "@babel/plugin-proposal-nullish-coalescing-operator@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 949c9ddcdecdaec766ee610ef98f965f928ccc0361dd87cf9f88cf4896a6ccd62fce063d4494778e50da99dea63d270a1be574a62d6ab81cbe9d85884bf55a7d + languageName: node + linkType: hard + +"@babel/plugin-proposal-numeric-separator@npm:^7.0.0": + version: 7.18.6 + resolution: "@babel/plugin-proposal-numeric-separator@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f370ea584c55bf4040e1f78c80b4eeb1ce2e6aaa74f87d1a48266493c33931d0b6222d8cee3a082383d6bb648ab8d6b7147a06f974d3296ef3bc39c7851683ec + languageName: node + linkType: hard + +"@babel/plugin-proposal-object-rest-spread@npm:^7.20.0": + version: 7.20.7 + resolution: "@babel/plugin-proposal-object-rest-spread@npm:7.20.7" + dependencies: + "@babel/compat-data": ^7.20.5 + "@babel/helper-compilation-targets": ^7.20.7 + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-transform-parameters": ^7.20.7 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 1329db17009964bc644484c660eab717cb3ca63ac0ab0f67c651a028d1bc2ead51dc4064caea283e46994f1b7221670a35cbc0b4beb6273f55e915494b5aa0b2 + languageName: node + linkType: hard + +"@babel/plugin-proposal-optional-catch-binding@npm:^7.0.0": + version: 7.18.6 + resolution: "@babel/plugin-proposal-optional-catch-binding@npm:7.18.6" + dependencies: + "@babel/helper-plugin-utils": ^7.18.6 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7b5b39fb5d8d6d14faad6cb68ece5eeb2fd550fb66b5af7d7582402f974f5bc3684641f7c192a5a57e0f59acfae4aada6786be1eba030881ddc590666eff4d1e + languageName: node + linkType: hard + +"@babel/plugin-proposal-optional-chaining@npm:^7.13.12, @babel/plugin-proposal-optional-chaining@npm:^7.20.0": + version: 7.21.0 + resolution: "@babel/plugin-proposal-optional-chaining@npm:7.21.0" + dependencies: + "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-skip-transparent-expression-wrappers": ^7.20.0 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 11c5449e01b18bb8881e8e005a577fa7be2fe5688e2382c8822d51f8f7005342a301a46af7b273b1f5645f9a7b894c428eee8526342038a275ef6ba4c8d8d746 + languageName: node + linkType: hard + +"@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2": + version: 7.21.0-placeholder-for-preset-env.2 + resolution: "@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d97745d098b835d55033ff3a7fb2b895b9c5295b08a5759e4f20df325aa385a3e0bc9bd5ad8f2ec554a44d4e6525acfc257b8c5848a1345cb40f26a30e277e91 + languageName: node + linkType: hard + +"@babel/plugin-syntax-async-generators@npm:^7.8.4": + version: 7.8.4 + resolution: "@babel/plugin-syntax-async-generators@npm:7.8.4" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7ed1c1d9b9e5b64ef028ea5e755c0be2d4e5e4e3d6cf7df757b9a8c4cfa4193d268176d0f1f7fbecdda6fe722885c7fda681f480f3741d8a2d26854736f05367 + languageName: node + linkType: hard + +"@babel/plugin-syntax-bigint@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-bigint@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3a10849d83e47aec50f367a9e56a6b22d662ddce643334b087f9828f4c3dd73bdc5909aaeabe123fed78515767f9ca43498a0e621c438d1cd2802d7fae3c9648 + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-properties@npm:^7.12.13, @babel/plugin-syntax-class-properties@npm:^7.8.3": + version: 7.12.13 + resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" + dependencies: + "@babel/helper-plugin-utils": ^7.12.13 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 24f34b196d6342f28d4bad303612d7ff566ab0a013ce89e775d98d6f832969462e7235f3e7eaf17678a533d4be0ba45d3ae34ab4e5a9dcbda5d98d49e5efa2fc + languageName: node + linkType: hard + +"@babel/plugin-syntax-class-static-block@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-class-static-block@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3e80814b5b6d4fe17826093918680a351c2d34398a914ce6e55d8083d72a9bdde4fbaf6a2dcea0e23a03de26dc2917ae3efd603d27099e2b98380345703bf948 + languageName: node + linkType: hard + +"@babel/plugin-syntax-dynamic-import@npm:^7.8.0, @babel/plugin-syntax-dynamic-import@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-dynamic-import@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ce307af83cf433d4ec42932329fad25fa73138ab39c7436882ea28742e1c0066626d224e0ad2988724c82644e41601cef607b36194f695cb78a1fcdc959637bd + languageName: node + linkType: hard + +"@babel/plugin-syntax-export-default-from@npm:^7.0.0, @babel/plugin-syntax-export-default-from@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-export-default-from@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 415b752a4c096e1eb65328b5dddde4848178f992356ab058828dfb12267c00f0880b4a4a272edf51f6344af1cc1565ea6dc184063e9454acf3160b9b1a9ef669 + languageName: node + linkType: hard + +"@babel/plugin-syntax-export-namespace-from@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-export-namespace-from@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 85740478be5b0de185228e7814451d74ab8ce0a26fcca7613955262a26e99e8e15e9da58f60c754b84515d4c679b590dbd3f2148f0f58025f4ae706f1c5a5d4a + languageName: node + linkType: hard + +"@babel/plugin-syntax-flow@npm:^7.12.1, @babel/plugin-syntax-flow@npm:^7.18.0, @babel/plugin-syntax-flow@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-flow@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c6e6f355d6ace5f4a9e7bb19f1fed2398aeb9b62c4c671a189d81b124f9f5bb77c4225b6e85e19339268c60a021c1e49104e450375de5e6bb70612190d9678af + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-assertions@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 883e6b35b2da205138caab832d54505271a3fee3fc1e8dc0894502434fc2b5d517cbe93bbfbfef8068a0fb6ec48ebc9eef3f605200a489065ba43d8cddc1c9a7 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-attributes@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9aed7661ffb920ca75df9f494757466ca92744e43072e0848d87fa4aa61a3f2ee5a22198ac1959856c036434b5614a8f46f1fb70298835dbe28220cdd1d4c11e + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-meta@npm:^7.10.4, @babel/plugin-syntax-import-meta@npm:^7.8.3": + version: 7.10.4 + resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 166ac1125d10b9c0c430e4156249a13858c0366d38844883d75d27389621ebe651115cb2ceb6dc011534d5055719fa1727b59f39e1ab3ca97820eef3dcab5b9b + languageName: node + linkType: hard + +"@babel/plugin-syntax-json-strings@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-json-strings@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bf5aea1f3188c9a507e16efe030efb996853ca3cadd6512c51db7233cc58f3ac89ff8c6bdfb01d30843b161cfe7d321e1bf28da82f7ab8d7e6bc5464666f354a + languageName: node + linkType: hard + +"@babel/plugin-syntax-jsx@npm:^7.23.3, @babel/plugin-syntax-jsx@npm:^7.7.2": + version: 7.23.3 + resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 89037694314a74e7f0e7a9c8d3793af5bf6b23d80950c29b360db1c66859d67f60711ea437e70ad6b5b4b29affe17eababda841b6c01107c2b638e0493bafb4e + languageName: node + linkType: hard + +"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4, @babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3": + version: 7.10.4 + resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: aff33577037e34e515911255cdbb1fd39efee33658aa00b8a5fd3a4b903585112d037cce1cc9e4632f0487dc554486106b79ccd5ea63a2e00df4363f6d4ff886 + languageName: node + linkType: hard + +"@babel/plugin-syntax-nullish-coalescing-operator@npm:^7.0.0, @babel/plugin-syntax-nullish-coalescing-operator@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-nullish-coalescing-operator@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 87aca4918916020d1fedba54c0e232de408df2644a425d153be368313fdde40d96088feed6c4e5ab72aac89be5d07fef2ddf329a15109c5eb65df006bf2580d1 + languageName: node + linkType: hard + +"@babel/plugin-syntax-numeric-separator@npm:^7.10.4, @babel/plugin-syntax-numeric-separator@npm:^7.8.3": + version: 7.10.4 + resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 01ec5547bd0497f76cc903ff4d6b02abc8c05f301c88d2622b6d834e33a5651aa7c7a3d80d8d57656a4588f7276eba357f6b7e006482f5b564b7a6488de493a1 + languageName: node + linkType: hard + +"@babel/plugin-syntax-object-rest-spread@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-object-rest-spread@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: fddcf581a57f77e80eb6b981b10658421bc321ba5f0a5b754118c6a92a5448f12a0c336f77b8abf734841e102e5126d69110a306eadb03ca3e1547cab31f5cbf + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-catch-binding@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-catch-binding@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 910d90e72bc90ea1ce698e89c1027fed8845212d5ab588e35ef91f13b93143845f94e2539d831dc8d8ededc14ec02f04f7bd6a8179edd43a326c784e7ed7f0b9 + languageName: node + linkType: hard + +"@babel/plugin-syntax-optional-chaining@npm:^7.0.0, @babel/plugin-syntax-optional-chaining@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-optional-chaining@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": ^7.8.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: eef94d53a1453361553c1f98b68d17782861a04a392840341bc91780838dd4e695209c783631cf0de14c635758beafb6a3a65399846ffa4386bff90639347f30 + languageName: node + linkType: hard + +"@babel/plugin-syntax-private-property-in-object@npm:^7.14.5": + version: 7.14.5 + resolution: "@babel/plugin-syntax-private-property-in-object@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b317174783e6e96029b743ccff2a67d63d38756876e7e5d0ba53a322e38d9ca452c13354a57de1ad476b4c066dbae699e0ca157441da611117a47af88985ecda + languageName: node + linkType: hard + +"@babel/plugin-syntax-top-level-await@npm:^7.14.5, @babel/plugin-syntax-top-level-await@npm:^7.8.3": + version: 7.14.5 + resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" + dependencies: + "@babel/helper-plugin-utils": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bbd1a56b095be7820029b209677b194db9b1d26691fe999856462e66b25b281f031f3dfd91b1619e9dcf95bebe336211833b854d0fb8780d618e35667c2d0d7e + languageName: node + linkType: hard + +"@babel/plugin-syntax-typescript@npm:^7.23.3, @babel/plugin-syntax-typescript@npm:^7.7.2": + version: 7.23.3 + resolution: "@babel/plugin-syntax-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: abfad3a19290d258b028e285a1f34c9b8a0cbe46ef79eafed4ed7ffce11b5d0720b5e536c82f91cbd8442cde35a3dd8e861fa70366d87ff06fdc0d4756e30876 + languageName: node + linkType: hard + +"@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6": + version: 7.18.6 + resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.18.6 + "@babel/helper-plugin-utils": ^7.18.6 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: a651d700fe63ff0ddfd7186f4ebc24447ca734f114433139e3c027bc94a900d013cf1ef2e2db8430425ba542e39ae160c3b05f06b59fd4656273a3df97679e9c + languageName: node + linkType: hard + +"@babel/plugin-transform-arrow-functions@npm:^7.0.0, @babel/plugin-transform-arrow-functions@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 1e99118176e5366c2636064d09477016ab5272b2a92e78b8edb571d20bc3eaa881789a905b20042942c3c2d04efc530726cf703f937226db5ebc495f5d067e66 + languageName: node + linkType: hard + +"@babel/plugin-transform-async-generator-functions@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.23.7" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-remap-async-to-generator": ^7.22.20 + "@babel/plugin-syntax-async-generators": ^7.8.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b1f66b23423933c27336b1161ac92efef46683321caea97e2255a666f992979376f47a5559f64188d3831fa66a4b24c2a7a40838cc0e9737e90eebe20e8e6372 + languageName: node + linkType: hard + +"@babel/plugin-transform-async-to-generator@npm:^7.20.0, @babel/plugin-transform-async-to-generator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.23.3" + dependencies: + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-remap-async-to-generator": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2e9d9795d4b3b3d8090332104e37061c677f29a1ce65bcbda4099a32d243e5d9520270a44bbabf0fb1fb40d463bd937685b1a1042e646979086c546d55319c3c + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoped-functions@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e63b16d94ee5f4d917e669da3db5ea53d1e7e79141a2ec873c1e644678cdafe98daa556d0d359963c827863d6b3665d23d4938a94a4c5053a1619c4ebd01d020 + languageName: node + linkType: hard + +"@babel/plugin-transform-block-scoping@npm:^7.0.0, @babel/plugin-transform-block-scoping@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-block-scoping@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: fc4b2100dd9f2c47d694b4b35ae8153214ccb4e24ef545c259a9db17211b18b6a430f22799b56db8f6844deaeaa201af45a03331d0c80cc28b0c4e3c814570e4 + languageName: node + linkType: hard + +"@babel/plugin-transform-class-properties@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-class-properties@npm:7.23.3" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9c6f8366f667897541d360246de176dd29efc7a13d80a5b48361882f7173d9173be4646c3b7d9b003ccc0e01e25df122330308f33db921fa553aa17ad544b3fc + languageName: node + linkType: hard + +"@babel/plugin-transform-class-static-block@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-class-static-block@npm:7.23.4" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + peerDependencies: + "@babel/core": ^7.12.0 + checksum: c8bfaba19a674fc2eb54edad71e958647360474e3163e8226f1acd63e4e2dbec32a171a0af596c1dc5359aee402cc120fea7abd1fb0e0354b6527f0fc9e8aa1e + languageName: node + linkType: hard + +"@babel/plugin-transform-classes@npm:^7.0.0, @babel/plugin-transform-classes@npm:^7.23.8": + version: 7.23.8 + resolution: "@babel/plugin-transform-classes@npm:7.23.8" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-compilation-targets": ^7.23.6 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-replace-supers": ^7.22.20 + "@babel/helper-split-export-declaration": ^7.22.6 + globals: ^11.1.0 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7dee6cebe52131d2d16944f36e1fdb9d4b24f44d0e7e450f93a44435d001f17cc0789a4cb6b15ec67c8e484581b8a730b5c3ec374470f29ff0133086955b8c58 + languageName: node + linkType: hard + +"@babel/plugin-transform-computed-properties@npm:^7.0.0, @babel/plugin-transform-computed-properties@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-computed-properties@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/template": ^7.22.15 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 80452661dc25a0956f89fe98cb562e8637a9556fb6c00d312c57653ce7df8798f58d138603c7e1aad96614ee9ccd10c47e50ab9ded6b6eded5adeb230d2a982e + languageName: node + linkType: hard + +"@babel/plugin-transform-destructuring@npm:^7.20.0, @babel/plugin-transform-destructuring@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-destructuring@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9e015099877272501162419bfe781689aec5c462cd2aec752ee22288f209eec65969ff11b8fdadca2eaddea71d705d3bba5b9c60752fcc1be67874fcec687105 + languageName: node + linkType: hard + +"@babel/plugin-transform-dotall-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.23.3" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a2dbbf7f1ea16a97948c37df925cb364337668c41a3948b8d91453f140507bd8a3429030c7ce66d09c299987b27746c19a2dd18b6f17dcb474854b14fd9159a3 + languageName: node + linkType: hard + +"@babel/plugin-transform-duplicate-keys@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c2a21c34dc0839590cd945192cbc46fde541a27e140c48fe1808315934664cdbf18db64889e23c4eeb6bad9d3e049482efdca91d29de5734ffc887c4fbabaa16 + languageName: node + linkType: hard + +"@babel/plugin-transform-dynamic-import@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 57a722604c430d9f3dacff22001a5f31250e34785d4969527a2ae9160fa86858d0892c5b9ff7a06a04076f8c76c9e6862e0541aadca9c057849961343aab0845 + languageName: node + linkType: hard + +"@babel/plugin-transform-exponentiation-operator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.23.3" + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 00d05ab14ad0f299160fcf9d8f55a1cc1b740e012ab0b5ce30207d2365f091665115557af7d989cd6260d075a252d9e4283de5f2b247dfbbe0e42ae586e6bf66 + languageName: node + linkType: hard + +"@babel/plugin-transform-export-namespace-from@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9f770a81bfd03b48d6ba155d452946fd56d6ffe5b7d871e9ec2a0b15e0f424273b632f3ed61838b90015b25bbda988896b7a46c7d964fbf8f6feb5820b309f93 + languageName: node + linkType: hard + +"@babel/plugin-transform-flow-strip-types@npm:^7.20.0, @babel/plugin-transform-flow-strip-types@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-flow-strip-types@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-flow": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: de38cc5cf948bc19405ea041292181527a36f59f08d787a590415fac36e9b0c7992f0d3e2fd3b9402089bafdaa1a893291a0edf15beebfd29bdedbbe582fee9b + languageName: node + linkType: hard + +"@babel/plugin-transform-for-of@npm:^7.23.6": + version: 7.23.6 + resolution: "@babel/plugin-transform-for-of@npm:7.23.6" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 228c060aa61f6aa89dc447170075f8214863b94f830624e74ade99c1a09316897c12d76e848460b0b506593e58dbc42739af6dc4cb0fe9b84dffe4a596050a36 + languageName: node + linkType: hard + +"@babel/plugin-transform-function-name@npm:^7.0.0, @babel/plugin-transform-function-name@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-function-name@npm:7.23.3" + dependencies: + "@babel/helper-compilation-targets": ^7.22.15 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 355c6dbe07c919575ad42b2f7e020f320866d72f8b79181a16f8e0cd424a2c761d979f03f47d583d9471b55dcd68a8a9d829b58e1eebcd572145b934b48975a6 + languageName: node + linkType: hard + +"@babel/plugin-transform-json-strings@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-json-strings@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-json-strings": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f9019820233cf8955d8ba346df709a0683c120fe86a24ed1c9f003f2db51197b979efc88f010d558a12e1491210fc195a43cd1c7fee5e23b92da38f793a875de + languageName: node + linkType: hard + +"@babel/plugin-transform-literals@npm:^7.0.0, @babel/plugin-transform-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-literals@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 519a544cd58586b9001c4c9b18da25a62f17d23c48600ff7a685d75ca9eb18d2c5e8f5476f067f0a8f1fea2a31107eff950b9864833061e6076dcc4bdc3e71ed + languageName: node + linkType: hard + +"@babel/plugin-transform-logical-assignment-operators@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2ae1dc9b4ff3bf61a990ff3accdecb2afe3a0ca649b3e74c010078d1cdf29ea490f50ac0a905306a2bcf9ac177889a39ac79bdcc3a0fdf220b3b75fac18d39b5 + languageName: node + linkType: hard + +"@babel/plugin-transform-member-expression-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 95cec13c36d447c5aa6b8e4c778b897eeba66dcb675edef01e0d2afcec9e8cb9726baf4f81b4bbae7a782595aed72e6a0d44ffb773272c3ca180fada99bf92db + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-amd@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-amd@npm:7.23.3" + dependencies: + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d163737b6a3d67ea579c9aa3b83d4df4b5c34d9dcdf25f415f027c0aa8cded7bac2750d2de5464081f67a042ad9e1c03930c2fab42acd79f9e57c00cf969ddff + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-commonjs@npm:^7.0.0, @babel/plugin-transform-modules-commonjs@npm:^7.13.8, @babel/plugin-transform-modules-commonjs@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" + dependencies: + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-simple-access": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 720a231ceade4ae4d2632478db4e7fecf21987d444942b72d523487ac8d715ca97de6c8f415c71e939595e1a4776403e7dc24ed68fe9125ad4acf57753c9bff7 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-systemjs@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.23.3" + dependencies: + "@babel/helper-hoist-variables": ^7.22.5 + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-identifier": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0d2fdd993c785aecac9e0850cd5ed7f7d448f0fbb42992a950cc0590167144df25d82af5aac9a5c99ef913d2286782afa44e577af30c10901c5ee8984910fa1f + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-umd@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-umd@npm:7.23.3" + dependencies: + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 586a7a2241e8b4e753a37af9466a9ffa8a67b4ba9aa756ad7500712c05d8fa9a8c1ed4f7bd25fae2a8265e6cf8fe781ec85a8ee885dd34cf50d8955ee65f12dc + languageName: node + linkType: hard + +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.0.0, @babel/plugin-transform-named-capturing-groups-regex@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.22.5" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 3ee564ddee620c035b928fdc942c5d17e9c4b98329b76f9cefac65c111135d925eb94ed324064cd7556d4f5123beec79abea1d4b97d1c8a2a5c748887a2eb623 + languageName: node + linkType: hard + +"@babel/plugin-transform-new-target@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-new-target@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e5053389316fce73ad5201b7777437164f333e24787fbcda4ae489cd2580dbbbdfb5694a7237bad91fabb46b591d771975d69beb1c740b82cb4761625379f00b + languageName: node + linkType: hard + +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a27d73ea134d3d9560a6b2e26ab60012fba15f1db95865aa0153c18f5ec82cfef6a7b3d8df74e3c2fca81534fa5efeb6cacaf7b08bdb7d123e3dafdd079886a3 + languageName: node + linkType: hard + +"@babel/plugin-transform-numeric-separator@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 6ba0e5db3c620a3ec81f9e94507c821f483c15f196868df13fa454cbac719a5449baf73840f5b6eb7d77311b24a2cf8e45db53700d41727f693d46f7caf3eec3 + languageName: node + linkType: hard + +"@babel/plugin-transform-object-rest-spread@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.23.4" + dependencies: + "@babel/compat-data": ^7.23.3 + "@babel/helper-compilation-targets": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-transform-parameters": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 73fec495e327ca3959c1c03d07a621be09df00036c69fff0455af9a008291677ee9d368eec48adacdc6feac703269a649747568b4af4c4e9f134aa71cc5b378d + languageName: node + linkType: hard + +"@babel/plugin-transform-object-super@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-object-super@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-replace-supers": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e495497186f621fa79026e183b4f1fbb172fd9df812cbd2d7f02c05b08adbe58012b1a6eb6dd58d11a30343f6ec80d0f4074f9b501d70aa1c94df76d59164c53 + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-catch-binding@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d50b5ee142cdb088d8b5de1ccf7cea85b18b85d85b52f86618f6e45226372f01ad4cdb29abd4fd35ea99a71fefb37009e0107db7a787dcc21d4d402f97470faf + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-chaining@npm:^7.23.3, @babel/plugin-transform-optional-chaining@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e7a4c08038288057b7a08d68c4d55396ada9278095509ca51ed8dfb72a7f13f26bdd7c5185de21079fe0a9d60d22c227cb32e300d266c1bda40f70eee9f4bc1e + languageName: node + linkType: hard + +"@babel/plugin-transform-parameters@npm:^7.0.0, @babel/plugin-transform-parameters@npm:^7.20.7, @babel/plugin-transform-parameters@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-parameters@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a735b3e85316d17ec102e3d3d1b6993b429bdb3b494651c9d754e3b7d270462ee1f1a126ccd5e3d871af5e683727e9ef98c9d34d4a42204fffaabff91052ed16 + languageName: node + linkType: hard + +"@babel/plugin-transform-private-methods@npm:^7.22.5, @babel/plugin-transform-private-methods@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-private-methods@npm:7.23.3" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: cedc1285c49b5a6d9a3d0e5e413b756ac40b3ac2f8f68bdfc3ae268bc8d27b00abd8bb0861c72756ff5dd8bf1eb77211b7feb5baf4fdae2ebbaabe49b9adc1d0 + languageName: node + linkType: hard + +"@babel/plugin-transform-private-property-in-object@npm:^7.22.11, @babel/plugin-transform-private-property-in-object@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.23.4" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-create-class-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: fb7adfe94ea97542f250a70de32bddbc3e0b802381c92be947fec83ebffda57e68533c4d0697152719a3496fdd3ebf3798d451c024cd4ac848fc15ac26b70aa7 + languageName: node + linkType: hard + +"@babel/plugin-transform-property-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-property-literals@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 16b048c8e87f25095f6d53634ab7912992f78e6997a6ff549edc3cf519db4fca01c7b4e0798530d7f6a05228ceee479251245cdd850a5531c6e6f404104d6cc9 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-display-name@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-display-name@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7f86964e8434d3ddbd3c81d2690c9b66dbf1cd8bd9512e2e24500e9fa8cf378bc52c0853270b3b82143aba5965aec04721df7abdb768f952b44f5c6e0b198779 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx-self@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-jsx-self@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 882bf56bc932d015c2d83214133939ddcf342e5bcafa21f1a93b19f2e052145115e1e0351730897fd66e5f67cad7875b8a8d81ceb12b6e2a886ad0102cb4eb1f + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx-source@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-jsx-source@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 92287fb797e522d99bdc77eaa573ce79ff0ad9f1cf4e7df374645e28e51dce0adad129f6f075430b129b5bac8dad843f65021970e12e992d6d6671f0d65bb1e0 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx@npm:^7.0.0": + version: 7.23.4 + resolution: "@babel/plugin-transform-react-jsx@npm:7.23.4" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-jsx": ^7.23.3 + "@babel/types": ^7.23.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d8b8c52e8e22e833bf77c8d1a53b0a57d1fd52ba9596a319d572de79446a8ed9d95521035bc1175c1589d1a6a34600d2e678fa81d81bac8fac121137097f1f0a + languageName: node + linkType: hard + +"@babel/plugin-transform-regenerator@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-regenerator@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + regenerator-transform: ^0.15.2 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7fdacc7b40008883871b519c9e5cdea493f75495118ccc56ac104b874983569a24edd024f0f5894ba1875c54ee2b442f295d6241c3280e61c725d0dd3317c8e6 + languageName: node + linkType: hard + +"@babel/plugin-transform-reserved-words@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-reserved-words@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 298c4440ddc136784ff920127cea137168e068404e635dc946ddb5d7b2a27b66f1dd4c4acb01f7184478ff7d5c3e7177a127279479926519042948fb7fa0fa48 + languageName: node + linkType: hard + +"@babel/plugin-transform-runtime@npm:^7.0.0": + version: 7.23.7 + resolution: "@babel/plugin-transform-runtime@npm:7.23.7" + dependencies: + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + babel-plugin-polyfill-corejs2: ^0.4.7 + babel-plugin-polyfill-corejs3: ^0.8.7 + babel-plugin-polyfill-regenerator: ^0.5.4 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b3cc760afbfdddac5fec3ba3a3916a448d152ada213dcb3ffe54115eaa09db1249f1661b7f271d79c8e6b03ebd5315c049800287cde372900f2557a6e2fe3333 + languageName: node + linkType: hard + +"@babel/plugin-transform-shorthand-properties@npm:^7.0.0, @babel/plugin-transform-shorthand-properties@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 5d677a03676f9fff969b0246c423d64d77502e90a832665dc872a5a5e05e5708161ce1effd56bb3c0f2c20a1112fca874be57c8a759d8b08152755519281f326 + languageName: node + linkType: hard + +"@babel/plugin-transform-spread@npm:^7.0.0, @babel/plugin-transform-spread@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-spread@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8fd5cac201e77a0b4825745f4e07a25f923842f282f006b3a79223c00f61075c8868d12eafec86b2642cd0b32077cdd32314e27bcb75ee5e6a68c0144140dcf2 + languageName: node + linkType: hard + +"@babel/plugin-transform-sticky-regex@npm:^7.0.0, @babel/plugin-transform-sticky-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 53e55eb2575b7abfdb4af7e503a2bf7ef5faf8bf6b92d2cd2de0700bdd19e934e5517b23e6dfed94ba50ae516b62f3f916773ef7d9bc81f01503f585051e2949 + languageName: node + linkType: hard + +"@babel/plugin-transform-template-literals@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-template-literals@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b16c5cb0b8796be0118e9c144d15bdc0d20a7f3f59009c6303a6e9a8b74c146eceb3f05186f5b97afcba7cfa87e34c1585a22186e3d5b22f2fd3d27d959d92b2 + languageName: node + linkType: hard + +"@babel/plugin-transform-typeof-symbol@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0af7184379d43afac7614fc89b1bdecce4e174d52f4efaeee8ec1a4f2c764356c6dba3525c0685231f1cbf435b6dd4ee9e738d7417f3b10ce8bbe869c32f4384 + languageName: node + linkType: hard + +"@babel/plugin-transform-typescript@npm:^7.23.3, @babel/plugin-transform-typescript@npm:^7.5.0": + version: 7.23.6 + resolution: "@babel/plugin-transform-typescript@npm:7.23.6" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-create-class-features-plugin": ^7.23.6 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-typescript": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0462241843d14dff9f1a4c49ab182a6f01a5f7679957c786b08165dac3e8d49184011f05ca204183d164c54b9d3496d1b3005f904fa8708e394e6f15bf5548e6 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-escapes@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 561c429183a54b9e4751519a3dfba6014431e9cdc1484fad03bdaf96582dfc72c76a4f8661df2aeeae7c34efd0fa4d02d3b83a2f63763ecf71ecc925f9cc1f60 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-property-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.23.3" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2298461a194758086d17c23c26c7de37aa533af910f9ebf31ebd0893d4aa317468043d23f73edc782ec21151d3c46cf0ff8098a83b725c49a59de28a1d4d6225 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-regex@npm:^7.0.0, @babel/plugin-transform-unicode-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.23.3" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c5f835d17483ba899787f92e313dfa5b0055e3deab332f1d254078a2bba27ede47574b6599fcf34d3763f0c048ae0779dc21d2d8db09295edb4057478dc80a9a + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-sets-regex@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.23.3" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 79d0b4c951955ca68235c87b91ab2b393c96285f8aeaa34d6db416d2ddac90000c9bd6e8c4d82b60a2b484da69930507245035f28ba63c6cae341cf3ba68fdef + languageName: node + linkType: hard + +"@babel/preset-env@npm:^7.23.8": + version: 7.23.8 + resolution: "@babel/preset-env@npm:7.23.8" + dependencies: + "@babel/compat-data": ^7.23.5 + "@babel/helper-compilation-targets": ^7.23.6 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.23.5 + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.23.3 + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.23.3 + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.23.7 + "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2 + "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/plugin-syntax-class-properties": ^7.12.13 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + "@babel/plugin-syntax-import-assertions": ^7.23.3 + "@babel/plugin-syntax-import-attributes": ^7.23.3 + "@babel/plugin-syntax-import-meta": ^7.10.4 + "@babel/plugin-syntax-json-strings": ^7.8.3 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + "@babel/plugin-syntax-top-level-await": ^7.14.5 + "@babel/plugin-syntax-unicode-sets-regex": ^7.18.6 + "@babel/plugin-transform-arrow-functions": ^7.23.3 + "@babel/plugin-transform-async-generator-functions": ^7.23.7 + "@babel/plugin-transform-async-to-generator": ^7.23.3 + "@babel/plugin-transform-block-scoped-functions": ^7.23.3 + "@babel/plugin-transform-block-scoping": ^7.23.4 + "@babel/plugin-transform-class-properties": ^7.23.3 + "@babel/plugin-transform-class-static-block": ^7.23.4 + "@babel/plugin-transform-classes": ^7.23.8 + "@babel/plugin-transform-computed-properties": ^7.23.3 + "@babel/plugin-transform-destructuring": ^7.23.3 + "@babel/plugin-transform-dotall-regex": ^7.23.3 + "@babel/plugin-transform-duplicate-keys": ^7.23.3 + "@babel/plugin-transform-dynamic-import": ^7.23.4 + "@babel/plugin-transform-exponentiation-operator": ^7.23.3 + "@babel/plugin-transform-export-namespace-from": ^7.23.4 + "@babel/plugin-transform-for-of": ^7.23.6 + "@babel/plugin-transform-function-name": ^7.23.3 + "@babel/plugin-transform-json-strings": ^7.23.4 + "@babel/plugin-transform-literals": ^7.23.3 + "@babel/plugin-transform-logical-assignment-operators": ^7.23.4 + "@babel/plugin-transform-member-expression-literals": ^7.23.3 + "@babel/plugin-transform-modules-amd": ^7.23.3 + "@babel/plugin-transform-modules-commonjs": ^7.23.3 + "@babel/plugin-transform-modules-systemjs": ^7.23.3 + "@babel/plugin-transform-modules-umd": ^7.23.3 + "@babel/plugin-transform-named-capturing-groups-regex": ^7.22.5 + "@babel/plugin-transform-new-target": ^7.23.3 + "@babel/plugin-transform-nullish-coalescing-operator": ^7.23.4 + "@babel/plugin-transform-numeric-separator": ^7.23.4 + "@babel/plugin-transform-object-rest-spread": ^7.23.4 + "@babel/plugin-transform-object-super": ^7.23.3 + "@babel/plugin-transform-optional-catch-binding": ^7.23.4 + "@babel/plugin-transform-optional-chaining": ^7.23.4 + "@babel/plugin-transform-parameters": ^7.23.3 + "@babel/plugin-transform-private-methods": ^7.23.3 + "@babel/plugin-transform-private-property-in-object": ^7.23.4 + "@babel/plugin-transform-property-literals": ^7.23.3 + "@babel/plugin-transform-regenerator": ^7.23.3 + "@babel/plugin-transform-reserved-words": ^7.23.3 + "@babel/plugin-transform-shorthand-properties": ^7.23.3 + "@babel/plugin-transform-spread": ^7.23.3 + "@babel/plugin-transform-sticky-regex": ^7.23.3 + "@babel/plugin-transform-template-literals": ^7.23.3 + "@babel/plugin-transform-typeof-symbol": ^7.23.3 + "@babel/plugin-transform-unicode-escapes": ^7.23.3 + "@babel/plugin-transform-unicode-property-regex": ^7.23.3 + "@babel/plugin-transform-unicode-regex": ^7.23.3 + "@babel/plugin-transform-unicode-sets-regex": ^7.23.3 + "@babel/preset-modules": 0.1.6-no-external-plugins + babel-plugin-polyfill-corejs2: ^0.4.7 + babel-plugin-polyfill-corejs3: ^0.8.7 + babel-plugin-polyfill-regenerator: ^0.5.4 + core-js-compat: ^3.31.0 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b850f99fc4aed4ba22c7d9207bd2bbc7a729b49ea6f2c2c36e819fe209e309b96fba336096e555b46f791b39f7cdd5ac41246b556283d435a99106eb825a209f + languageName: node + linkType: hard + +"@babel/preset-flow@npm:^7.13.13": + version: 7.23.3 + resolution: "@babel/preset-flow@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.22.15 + "@babel/plugin-transform-flow-strip-types": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 60b5dde79621ae89943af459c4dc5b6030795f595a20ca438c8100f8d82c9ebc986881719030521ff5925799518ac5aa7f3fe62af8c33ab96be3681a71f88d03 + languageName: node + linkType: hard + +"@babel/preset-modules@npm:0.1.6-no-external-plugins": + version: 0.1.6-no-external-plugins + resolution: "@babel/preset-modules@npm:0.1.6-no-external-plugins" + dependencies: + "@babel/helper-plugin-utils": ^7.0.0 + "@babel/types": ^7.4.4 + esutils: ^2.0.2 + peerDependencies: + "@babel/core": ^7.0.0-0 || ^8.0.0-0 <8.0.0 + checksum: 4855e799bc50f2449fb5210f78ea9e8fd46cf4f242243f1e2ed838e2bd702e25e73e822e7f8447722a5f4baa5e67a8f7a0e403f3e7ce04540ff743a9c411c375 + languageName: node + linkType: hard + +"@babel/preset-typescript@npm:^7.13.0": + version: 7.23.3 + resolution: "@babel/preset-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.22.15 + "@babel/plugin-syntax-jsx": ^7.23.3 + "@babel/plugin-transform-modules-commonjs": ^7.23.3 + "@babel/plugin-transform-typescript": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 105a2d39bbc464da0f7e1ad7f535c77c5f62d6b410219355b20e552e7d29933567a5c55339b5d0aec1a5c7a0a7dfdf1b54aae601a4fe15a157d54dcbfcb3e854 + languageName: node + linkType: hard + +"@babel/register@npm:^7.13.16": + version: 7.23.7 + resolution: "@babel/register@npm:7.23.7" + dependencies: + clone-deep: ^4.0.1 + find-cache-dir: ^2.0.0 + make-dir: ^2.1.0 + pirates: ^4.0.6 + source-map-support: ^0.5.16 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c72a6d4856ef04f13490370d805854d2d98a77786bfaec7d85e2c585e1217011c4f3df18197a890e14520906c9111bef95551ba1a9b59c88df4dfc2dfe2c8d1b + languageName: node + linkType: hard + +"@babel/regjsgen@npm:^0.8.0": + version: 0.8.0 + resolution: "@babel/regjsgen@npm:0.8.0" + checksum: 89c338fee774770e5a487382170711014d49a68eb281e74f2b5eac88f38300a4ad545516a7786a8dd5702e9cf009c94c2f582d200f077ac5decd74c56b973730 + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.23.8, @babel/runtime@npm:^7.8.4": + version: 7.23.8 + resolution: "@babel/runtime@npm:7.23.8" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: 0bd5543c26811153822a9f382fd39886f66825ff2a397a19008011376533747cd05c33a91f6248c0b8b0edf0448d7c167ebfba34786088f1b7eb11c65be7dfc3 + languageName: node + linkType: hard + +"@babel/template@npm:^7.0.0, @babel/template@npm:^7.22.15, @babel/template@npm:^7.3.3": + version: 7.22.15 + resolution: "@babel/template@npm:7.22.15" + dependencies: + "@babel/code-frame": ^7.22.13 + "@babel/parser": ^7.22.15 + "@babel/types": ^7.22.15 + checksum: 1f3e7dcd6c44f5904c184b3f7fe280394b191f2fed819919ffa1e529c259d5b197da8981b6ca491c235aee8dbad4a50b7e31304aa531271cb823a4a24a0dd8fd + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.20.0, @babel/traverse@npm:^7.23.7": + version: 7.23.7 + resolution: "@babel/traverse@npm:7.23.7" + dependencies: + "@babel/code-frame": ^7.23.5 + "@babel/generator": ^7.23.6 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-hoist-variables": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + "@babel/parser": ^7.23.6 + "@babel/types": ^7.23.6 + debug: ^4.3.1 + globals: ^11.1.0 + checksum: d4a7afb922361f710efc97b1e25ec343fab8b2a4ddc81ca84f9a153f22d4482112cba8f263774be8d297918b6c4767c7a98988ab4e53ac73686c986711dd002e + languageName: node + linkType: hard + +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.4, @babel/types@npm:^7.23.6, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.23.6 + resolution: "@babel/types@npm:7.23.6" + dependencies: + "@babel/helper-string-parser": ^7.23.4 + "@babel/helper-validator-identifier": ^7.22.20 + to-fast-properties: ^2.0.0 + checksum: 68187dbec0d637f79bc96263ac95ec8b06d424396678e7e225492be866414ce28ebc918a75354d4c28659be6efe30020b4f0f6df81cc418a2d30645b690a8de0 + languageName: node + linkType: hard + +"@bcoe/v8-coverage@npm:^0.2.3": + version: 0.2.3 + resolution: "@bcoe/v8-coverage@npm:0.2.3" + checksum: 850f9305536d0f2bd13e9e0881cb5f02e4f93fad1189f7b2d4bebf694e3206924eadee1068130d43c11b750efcc9405f88a8e42ef098b6d75239c0f047de1a27 + languageName: node + linkType: hard + +"@cspotcode/source-map-support@npm:^0.8.0": + version: 0.8.1 + resolution: "@cspotcode/source-map-support@npm:0.8.1" + dependencies: + "@jridgewell/trace-mapping": 0.3.9 + checksum: 5718f267085ed8edb3e7ef210137241775e607ee18b77d95aa5bd7514f47f5019aa2d82d96b3bf342ef7aa890a346fa1044532ff7cc3009e7d24fce3ce6200fa + languageName: node + linkType: hard + +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": + version: 4.4.0 + resolution: "@eslint-community/eslint-utils@npm:4.4.0" + dependencies: + eslint-visitor-keys: ^3.3.0 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: cdfe3ae42b4f572cbfb46d20edafe6f36fc5fb52bf2d90875c58aefe226892b9677fef60820e2832caf864a326fe4fc225714c46e8389ccca04d5f9288aabd22 + languageName: node + linkType: hard + +"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": + version: 4.10.0 + resolution: "@eslint-community/regexpp@npm:4.10.0" + checksum: 2a6e345429ea8382aaaf3a61f865cae16ed44d31ca917910033c02dc00d505d939f10b81e079fa14d43b51499c640138e153b7e40743c4c094d9df97d4e56f7b + languageName: node + linkType: hard + +"@eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" + dependencies: + ajv: ^6.12.4 + debug: ^4.3.2 + espree: ^9.6.0 + globals: ^13.19.0 + ignore: ^5.2.0 + import-fresh: ^3.2.1 + js-yaml: ^4.1.0 + minimatch: ^3.1.2 + strip-json-comments: ^3.1.1 + checksum: 10957c7592b20ca0089262d8c2a8accbad14b4f6507e35416c32ee6b4dbf9cad67dfb77096bbd405405e9ada2b107f3797fe94362e1c55e0b09d6e90dd149127 + languageName: node + linkType: hard + +"@eslint/js@npm:8.56.0": + version: 8.56.0 + resolution: "@eslint/js@npm:8.56.0" + checksum: 5804130574ef810207bdf321c265437814e7a26f4e6fac9b496de3206afd52f533e09ec002a3be06cd9adcc9da63e727f1883938e663c4e4751c007d5b58e539 + languageName: node + linkType: hard + +"@hapi/hoek@npm:^9.0.0": + version: 9.3.0 + resolution: "@hapi/hoek@npm:9.3.0" + checksum: 4771c7a776242c3c022b168046af4e324d116a9d2e1d60631ee64f474c6e38d1bb07092d898bf95c7bc5d334c5582798a1456321b2e53ca817d4e7c88bc25b43 + languageName: node + linkType: hard + +"@hapi/topo@npm:^5.0.0": + version: 5.1.0 + resolution: "@hapi/topo@npm:5.1.0" + dependencies: + "@hapi/hoek": ^9.0.0 + checksum: 604dfd5dde76d5c334bd03f9001fce69c7ce529883acf92da96f4fe7e51221bf5e5110e964caca287a6a616ba027c071748ab636ff178ad750547fba611d6014 + languageName: node + linkType: hard + +"@humanwhocodes/config-array@npm:^0.11.13": + version: 0.11.14 + resolution: "@humanwhocodes/config-array@npm:0.11.14" + dependencies: + "@humanwhocodes/object-schema": ^2.0.2 + debug: ^4.3.1 + minimatch: ^3.0.5 + checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 + languageName: node + linkType: hard + +"@humanwhocodes/module-importer@npm:^1.0.1": + version: 1.0.1 + resolution: "@humanwhocodes/module-importer@npm:1.0.1" + checksum: 0fd22007db8034a2cdf2c764b140d37d9020bbfce8a49d3ec5c05290e77d4b0263b1b972b752df8c89e5eaa94073408f2b7d977aed131faf6cf396ebb5d7fb61 + languageName: node + linkType: hard + +"@humanwhocodes/object-schema@npm:^2.0.2": + version: 2.0.2 + resolution: "@humanwhocodes/object-schema@npm:2.0.2" + checksum: 2fc11503361b5fb4f14714c700c02a3f4c7c93e9acd6b87a29f62c522d90470f364d6161b03d1cc618b979f2ae02aed1106fd29d302695d8927e2fc8165ba8ee + languageName: node + linkType: hard + +"@isaacs/cliui@npm:^8.0.2": + version: 8.0.2 + resolution: "@isaacs/cliui@npm:8.0.2" + dependencies: + string-width: ^5.1.2 + string-width-cjs: "npm:string-width@^4.2.0" + strip-ansi: ^7.0.1 + strip-ansi-cjs: "npm:strip-ansi@^6.0.1" + wrap-ansi: ^8.1.0 + wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" + checksum: 4a473b9b32a7d4d3cfb7a614226e555091ff0c5a29a1734c28c72a182c2f6699b26fc6b5c2131dfd841e86b185aea714c72201d7c98c2fba5f17709333a67aeb + languageName: node + linkType: hard + +"@isaacs/ttlcache@npm:^1.4.1": + version: 1.4.1 + resolution: "@isaacs/ttlcache@npm:1.4.1" + checksum: b99f0918faf1eba405b6bc3421584282b2edc46cca23f8d8e112a643bf6e4506c6c53a4525901118e229d19c5719bbec3028ec438d758fd71081f6c32af871ec + languageName: node + linkType: hard + +"@istanbuljs/load-nyc-config@npm:^1.0.0": + version: 1.1.0 + resolution: "@istanbuljs/load-nyc-config@npm:1.1.0" + dependencies: + camelcase: ^5.3.1 + find-up: ^4.1.0 + get-package-type: ^0.1.0 + js-yaml: ^3.13.1 + resolve-from: ^5.0.0 + checksum: d578da5e2e804d5c93228450a1380e1a3c691de4953acc162f387b717258512a3e07b83510a936d9fab03eac90817473917e24f5d16297af3867f59328d58568 + languageName: node + linkType: hard + +"@istanbuljs/schema@npm:^0.1.2": + version: 0.1.3 + resolution: "@istanbuljs/schema@npm:0.1.3" + checksum: 5282759d961d61350f33d9118d16bcaed914ebf8061a52f4fa474b2cb08720c9c81d165e13b82f2e5a8a212cc5af482f0c6fc1ac27b9e067e5394c9a6ed186c9 + languageName: node + linkType: hard + +"@jest/console@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/console@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 + slash: ^3.0.0 + checksum: 0e3624e32c5a8e7361e889db70b170876401b7d70f509a2538c31d5cd50deb0c1ae4b92dc63fe18a0902e0a48c590c21d53787a0df41a52b34fa7cab96c384d6 + languageName: node + linkType: hard + +"@jest/core@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/core@npm:29.7.0" + dependencies: + "@jest/console": ^29.7.0 + "@jest/reporters": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + ci-info: ^3.2.0 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + jest-changed-files: ^29.7.0 + jest-config: ^29.7.0 + jest-haste-map: ^29.7.0 + jest-message-util: ^29.7.0 + jest-regex-util: ^29.6.3 + jest-resolve: ^29.7.0 + jest-resolve-dependencies: ^29.7.0 + jest-runner: ^29.7.0 + jest-runtime: ^29.7.0 + jest-snapshot: ^29.7.0 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 + jest-watcher: ^29.7.0 + micromatch: ^4.0.4 + pretty-format: ^29.7.0 + slash: ^3.0.0 + strip-ansi: ^6.0.0 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: af759c9781cfc914553320446ce4e47775ae42779e73621c438feb1e4231a5d4862f84b1d8565926f2d1aab29b3ec3dcfdc84db28608bdf5f29867124ebcfc0d + languageName: node + linkType: hard + +"@jest/create-cache-key-function@npm:^29.6.3": + version: 29.7.0 + resolution: "@jest/create-cache-key-function@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + checksum: 681bc761fa1d6fa3dd77578d444f97f28296ea80755e90e46d1c8fa68661b9e67f54dd38b988742db636d26cf160450dc6011892cec98b3a7ceb58cad8ff3aae + languageName: node + linkType: hard + +"@jest/environment@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/environment@npm:29.7.0" + dependencies: + "@jest/fake-timers": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + jest-mock: ^29.7.0 + checksum: 6fb398143b2543d4b9b8d1c6dbce83fa5247f84f550330604be744e24c2bd2178bb893657d62d1b97cf2f24baf85c450223f8237cccb71192c36a38ea2272934 + languageName: node + linkType: hard + +"@jest/expect-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect-utils@npm:29.7.0" + dependencies: + jest-get-type: ^29.6.3 + checksum: 75eb177f3d00b6331bcaa057e07c0ccb0733a1d0a1943e1d8db346779039cb7f103789f16e502f888a3096fb58c2300c38d1f3748b36a7fa762eb6f6d1b160ed + languageName: node + linkType: hard + +"@jest/expect@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/expect@npm:29.7.0" + dependencies: + expect: ^29.7.0 + jest-snapshot: ^29.7.0 + checksum: a01cb85fd9401bab3370618f4b9013b90c93536562222d920e702a0b575d239d74cecfe98010aaec7ad464f67cf534a353d92d181646a4b792acaa7e912ae55e + languageName: node + linkType: hard + +"@jest/fake-timers@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/fake-timers@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + "@sinonjs/fake-timers": ^10.0.2 + "@types/node": "*" + jest-message-util: ^29.7.0 + jest-mock: ^29.7.0 + jest-util: ^29.7.0 + checksum: caf2bbd11f71c9241b458d1b5a66cbe95debc5a15d96442444b5d5c7ba774f523c76627c6931cca5e10e76f0d08761f6f1f01a608898f4751a0eee54fc3d8d00 + languageName: node + linkType: hard + +"@jest/globals@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/globals@npm:29.7.0" + dependencies: + "@jest/environment": ^29.7.0 + "@jest/expect": ^29.7.0 + "@jest/types": ^29.6.3 + jest-mock: ^29.7.0 + checksum: 97dbb9459135693ad3a422e65ca1c250f03d82b2a77f6207e7fa0edd2c9d2015fbe4346f3dc9ebff1678b9d8da74754d4d440b7837497f8927059c0642a22123 + languageName: node + linkType: hard + +"@jest/reporters@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/reporters@npm:29.7.0" + dependencies: + "@bcoe/v8-coverage": ^0.2.3 + "@jest/console": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 + "@jest/types": ^29.6.3 + "@jridgewell/trace-mapping": ^0.3.18 + "@types/node": "*" + chalk: ^4.0.0 + collect-v8-coverage: ^1.0.0 + exit: ^0.1.2 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + istanbul-lib-coverage: ^3.0.0 + istanbul-lib-instrument: ^6.0.0 + istanbul-lib-report: ^3.0.0 + istanbul-lib-source-maps: ^4.0.0 + istanbul-reports: ^3.1.3 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 + jest-worker: ^29.7.0 + slash: ^3.0.0 + string-length: ^4.0.1 + strip-ansi: ^6.0.0 + v8-to-istanbul: ^9.0.1 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + checksum: 7eadabd62cc344f629024b8a268ecc8367dba756152b761bdcb7b7e570a3864fc51b2a9810cd310d85e0a0173ef002ba4528d5ea0329fbf66ee2a3ada9c40455 + languageName: node + linkType: hard + +"@jest/schemas@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/schemas@npm:29.6.3" + dependencies: + "@sinclair/typebox": ^0.27.8 + checksum: 910040425f0fc93cd13e68c750b7885590b8839066dfa0cd78e7def07bbb708ad869381f725945d66f2284de5663bbecf63e8fdd856e2ae6e261ba30b1687e93 + languageName: node + linkType: hard + +"@jest/source-map@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/source-map@npm:29.6.3" + dependencies: + "@jridgewell/trace-mapping": ^0.3.18 + callsites: ^3.0.0 + graceful-fs: ^4.2.9 + checksum: bcc5a8697d471396c0003b0bfa09722c3cd879ad697eb9c431e6164e2ea7008238a01a07193dfe3cbb48b1d258eb7251f6efcea36f64e1ebc464ea3c03ae2deb + languageName: node + linkType: hard + +"@jest/test-result@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-result@npm:29.7.0" + dependencies: + "@jest/console": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/istanbul-lib-coverage": ^2.0.0 + collect-v8-coverage: ^1.0.0 + checksum: 67b6317d526e335212e5da0e768e3b8ab8a53df110361b80761353ad23b6aea4432b7c5665bdeb87658ea373b90fb1afe02ed3611ef6c858c7fba377505057fa + languageName: node + linkType: hard + +"@jest/test-sequencer@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/test-sequencer@npm:29.7.0" + dependencies: + "@jest/test-result": ^29.7.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.7.0 + slash: ^3.0.0 + checksum: 73f43599017946be85c0b6357993b038f875b796e2f0950487a82f4ebcb115fa12131932dd9904026b4ad8be131fe6e28bd8d0aa93b1563705185f9804bff8bd + languageName: node + linkType: hard + +"@jest/transform@npm:^29.7.0": + version: 29.7.0 + resolution: "@jest/transform@npm:29.7.0" + dependencies: + "@babel/core": ^7.11.6 + "@jest/types": ^29.6.3 + "@jridgewell/trace-mapping": ^0.3.18 + babel-plugin-istanbul: ^6.1.1 + chalk: ^4.0.0 + convert-source-map: ^2.0.0 + fast-json-stable-stringify: ^2.1.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.7.0 + jest-regex-util: ^29.6.3 + jest-util: ^29.7.0 + micromatch: ^4.0.4 + pirates: ^4.0.4 + slash: ^3.0.0 + write-file-atomic: ^4.0.2 + checksum: 0f8ac9f413903b3cb6d240102db848f2a354f63971ab885833799a9964999dd51c388162106a807f810071f864302cdd8e3f0c241c29ce02d85a36f18f3f40ab + languageName: node + linkType: hard + +"@jest/types@npm:^26.6.2": + version: 26.6.2 + resolution: "@jest/types@npm:26.6.2" + dependencies: + "@types/istanbul-lib-coverage": ^2.0.0 + "@types/istanbul-reports": ^3.0.0 + "@types/node": "*" + "@types/yargs": ^15.0.0 + chalk: ^4.0.0 + checksum: a0bd3d2f22f26ddb23f41fddf6e6a30bf4fab2ce79ec1cb6ce6fdfaf90a72e00f4c71da91ec61e13db3b10c41de22cf49d07c57ff2b59171d64b29f909c1d8d6 + languageName: node + linkType: hard + +"@jest/types@npm:^29.6.3": + version: 29.6.3 + resolution: "@jest/types@npm:29.6.3" + dependencies: + "@jest/schemas": ^29.6.3 + "@types/istanbul-lib-coverage": ^2.0.0 + "@types/istanbul-reports": ^3.0.0 + "@types/node": "*" + "@types/yargs": ^17.0.8 + chalk: ^4.0.0 + checksum: a0bcf15dbb0eca6bdd8ce61a3fb055349d40268622a7670a3b2eb3c3dbafe9eb26af59938366d520b86907b9505b0f9b29b85cec11579a9e580694b87cd90fcc + languageName: node + linkType: hard + +"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": + version: 0.3.3 + resolution: "@jridgewell/gen-mapping@npm:0.3.3" + dependencies: + "@jridgewell/set-array": ^1.0.1 + "@jridgewell/sourcemap-codec": ^1.4.10 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 4a74944bd31f22354fc01c3da32e83c19e519e3bbadafa114f6da4522ea77dd0c2842607e923a591d60a76699d819a2fbb6f3552e277efdb9b58b081390b60ab + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0": + version: 3.1.1 + resolution: "@jridgewell/resolve-uri@npm:3.1.1" + checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 + languageName: node + linkType: hard + +"@jridgewell/set-array@npm:^1.0.1": + version: 1.1.2 + resolution: "@jridgewell/set-array@npm:1.1.2" + checksum: 69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e + languageName: node + linkType: hard + +"@jridgewell/source-map@npm:^0.3.3": + version: 0.3.5 + resolution: "@jridgewell/source-map@npm:0.3.5" + dependencies: + "@jridgewell/gen-mapping": ^0.3.0 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 1ad4dec0bdafbade57920a50acec6634f88a0eb735851e0dda906fa9894e7f0549c492678aad1a10f8e144bfe87f238307bf2a914a1bc85b7781d345417e9f6f + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": + version: 1.4.15 + resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" + checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:0.3.9": + version: 0.3.9 + resolution: "@jridgewell/trace-mapping@npm:0.3.9" + dependencies: + "@jridgewell/resolve-uri": ^3.0.3 + "@jridgewell/sourcemap-codec": ^1.4.10 + checksum: d89597752fd88d3f3480845691a05a44bd21faac18e2185b6f436c3b0fd0c5a859fbbd9aaa92050c4052caf325ad3e10e2e1d1b64327517471b7d51babc0ddef + languageName: node + linkType: hard + +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.21 + resolution: "@jridgewell/trace-mapping@npm:0.3.21" + dependencies: + "@jridgewell/resolve-uri": ^3.1.0 + "@jridgewell/sourcemap-codec": ^1.4.14 + checksum: e91d3943c6d84687503ba033600d42b2a81d9eaf32758fee06449cd1415c59b944af08841e99f030b71f83bb5f814969e96fc8aa29e469eb3ea1b46597d13cff + languageName: node + linkType: hard + +"@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1": + version: 5.1.1-v1 + resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1" + dependencies: + eslint-scope: 5.1.1 + checksum: f2e3b2d6a6e2d9f163ca22105910c9f850dc4897af0aea3ef0a5886b63d8e1ba6505b71c99cb78a3bba24a09557d601eb21c8dede3f3213753fcfef364eb0e57 + languageName: node + linkType: hard + +"@nodelib/fs.scandir@npm:2.1.5": + version: 2.1.5 + resolution: "@nodelib/fs.scandir@npm:2.1.5" + dependencies: + "@nodelib/fs.stat": 2.0.5 + run-parallel: ^1.1.9 + checksum: a970d595bd23c66c880e0ef1817791432dbb7acbb8d44b7e7d0e7a22f4521260d4a83f7f9fd61d44fda4610105577f8f58a60718105fb38352baed612fd79e59 + languageName: node + linkType: hard + +"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": + version: 2.0.5 + resolution: "@nodelib/fs.stat@npm:2.0.5" + checksum: 012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0 + languageName: node + linkType: hard + +"@nodelib/fs.walk@npm:^1.2.3, @nodelib/fs.walk@npm:^1.2.8": + version: 1.2.8 + resolution: "@nodelib/fs.walk@npm:1.2.8" + dependencies: + "@nodelib/fs.scandir": 2.1.5 + fastq: ^1.6.0 + checksum: 190c643f156d8f8f277bf2a6078af1ffde1fd43f498f187c2db24d35b4b4b5785c02c7dc52e356497b9a1b65b13edc996de08de0b961c32844364da02986dc53 + languageName: node + linkType: hard + +"@npmcli/agent@npm:^2.0.0": + version: 2.2.0 + resolution: "@npmcli/agent@npm:2.2.0" + dependencies: + agent-base: ^7.1.0 + http-proxy-agent: ^7.0.0 + https-proxy-agent: ^7.0.1 + lru-cache: ^10.0.1 + socks-proxy-agent: ^8.0.1 + checksum: 3b25312edbdfaa4089af28e2d423b6f19838b945e47765b0c8174c1395c79d43c3ad6d23cb364b43f59fd3acb02c93e3b493f72ddbe3dfea04c86843a7311fc4 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^3.1.0": + version: 3.1.0 + resolution: "@npmcli/fs@npm:3.1.0" + dependencies: + semver: ^7.3.5 + checksum: a50a6818de5fc557d0b0e6f50ec780a7a02ab8ad07e5ac8b16bf519e0ad60a144ac64f97d05c443c3367235d337182e1d012bbac0eb8dbae8dc7b40b193efd0e + languageName: node + linkType: hard + +"@pkgjs/parseargs@npm:^0.11.0": + version: 0.11.0 + resolution: "@pkgjs/parseargs@npm:0.11.0" + checksum: 6ad6a00fc4f2f2cfc6bff76fb1d88b8ee20bc0601e18ebb01b6d4be583733a860239a521a7fbca73b612e66705078809483549d2b18f370eb346c5155c8e4a0f + languageName: node + linkType: hard + +"@pkgr/core@npm:^0.1.0": + version: 0.1.0 + resolution: "@pkgr/core@npm:0.1.0" + checksum: eeff0e0e517b1ed10eb4c1a8971413a8349bbfdab727dbe7d4085fd94eab95f0c3beb51b9245fef30562849d2a7a119e07ca48c343c8c4ec4e64ee289f50fe5e + languageName: node + linkType: hard + +"@react-native-community/cli-clean@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli-clean@npm:12.3.0" + dependencies: + "@react-native-community/cli-tools": 12.3.0 + chalk: ^4.1.2 + execa: ^5.0.0 + checksum: e2e993f4273457b9edd5dadc64d6d12afd78af9c947331f1e56fb46097e34006bf07ea348ce5a5f7f5e1b957af69593c304572e7cc50f19ba170f943de38c128 + languageName: node + linkType: hard + +"@react-native-community/cli-config@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli-config@npm:12.3.0" + dependencies: + "@react-native-community/cli-tools": 12.3.0 + chalk: ^4.1.2 + cosmiconfig: ^5.1.0 + deepmerge: ^4.3.0 + glob: ^7.1.3 + joi: ^17.2.1 + checksum: 43f02674969d55448bc4222a6eb01c730f8aef95f49a47789c5cce809e128e90580e99fd727ba798c9c889db8ec491d428290173ffb9cb352e3d004bd7a1bdab + languageName: node + linkType: hard + +"@react-native-community/cli-debugger-ui@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli-debugger-ui@npm:12.3.0" + dependencies: + serve-static: ^1.13.1 + checksum: d1a3103667b5dd427f95e9b7148ffd86e28285af06eb66d091522ebfab4b842d3da51a8f7dc154f3bca6a4f768eacda5a53a62155bc106e52f543b58e9882842 + languageName: node + linkType: hard + +"@react-native-community/cli-doctor@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli-doctor@npm:12.3.0" + dependencies: + "@react-native-community/cli-config": 12.3.0 + "@react-native-community/cli-platform-android": 12.3.0 + "@react-native-community/cli-platform-ios": 12.3.0 + "@react-native-community/cli-tools": 12.3.0 + chalk: ^4.1.2 + command-exists: ^1.2.8 + deepmerge: ^4.3.0 + envinfo: ^7.10.0 + execa: ^5.0.0 + hermes-profile-transformer: ^0.0.6 + ip: ^1.1.5 + node-stream-zip: ^1.9.1 + ora: ^5.4.1 + semver: ^7.5.2 + strip-ansi: ^5.2.0 + wcwidth: ^1.0.1 + yaml: ^2.2.1 + checksum: cd0ccdf9da63853a2099de90ed3b1264fd3a311ff2a2b61d0882de02e0fb1bb2d854e474497347de8454479f9fb891aaea739f2a4dd1d5bc1142a1f30a1da721 + languageName: node + linkType: hard + +"@react-native-community/cli-hermes@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli-hermes@npm:12.3.0" + dependencies: + "@react-native-community/cli-platform-android": 12.3.0 + "@react-native-community/cli-tools": 12.3.0 + chalk: ^4.1.2 + hermes-profile-transformer: ^0.0.6 + ip: ^1.1.5 + checksum: 8b9c17184f023466a072bbe5d4bbed76c40b36feab4b3359c526cd561b9231c0b936ee934b2c1bd1c969d6ba1421241a29975f3210b403fc1532f643d7a14447 + languageName: node + linkType: hard + +"@react-native-community/cli-platform-android@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli-platform-android@npm:12.3.0" + dependencies: + "@react-native-community/cli-tools": 12.3.0 + chalk: ^4.1.2 + execa: ^5.0.0 + fast-xml-parser: ^4.2.4 + glob: ^7.1.3 + logkitty: ^0.7.1 + checksum: 21bf7edd73e1aef598a3d443bd7341eff2050fa61f3eed358dbc779620fb77677e0b002470e571812336fe00198c24563b55b3af728c72ebac5df86b344a25b6 + languageName: node + linkType: hard + +"@react-native-community/cli-platform-ios@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli-platform-ios@npm:12.3.0" + dependencies: + "@react-native-community/cli-tools": 12.3.0 + chalk: ^4.1.2 + execa: ^5.0.0 + fast-xml-parser: ^4.0.12 + glob: ^7.1.3 + ora: ^5.4.1 + checksum: 2bc5d4955363e0f41d7bfd42b6a61820ae813ecf1d5e057ec42b60175c7b0deac1456fe4c4734b7df353101bfc24745a32a7d0986315fce22b0c89e36bff2bd2 + languageName: node + linkType: hard + +"@react-native-community/cli-plugin-metro@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli-plugin-metro@npm:12.3.0" + checksum: 6a9f34be596271c4e37729f70099f5996339bf8ceb5023597beb253e43115db394d3ec669a2a6635ab659d3571a7aa1ba5e5ea31d2b460f68edf1b0a82fb2950 + languageName: node + linkType: hard + +"@react-native-community/cli-server-api@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli-server-api@npm:12.3.0" + dependencies: + "@react-native-community/cli-debugger-ui": 12.3.0 + "@react-native-community/cli-tools": 12.3.0 + compression: ^1.7.1 + connect: ^3.6.5 + errorhandler: ^1.5.1 + nocache: ^3.0.1 + pretty-format: ^26.6.2 + serve-static: ^1.13.1 + ws: ^7.5.1 + checksum: 606989b678036e6290ff613f0506d2c6b07870a62f68d6f35bf41b9ff9b60bc5e85f8275e3b7c10bad00ee2fb92b1f7764e7d8f93a9a79eb45f86ccf042ed6b4 + languageName: node + linkType: hard + +"@react-native-community/cli-tools@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli-tools@npm:12.3.0" + dependencies: + appdirsjs: ^1.2.4 + chalk: ^4.1.2 + find-up: ^5.0.0 + mime: ^2.4.1 + node-fetch: ^2.6.0 + open: ^6.2.0 + ora: ^5.4.1 + semver: ^7.5.2 + shell-quote: ^1.7.3 + sudo-prompt: ^9.0.0 + checksum: df9d3e721689644749099e3217bf202143eeaf0e0ea2aa283ce9130445ba7e65c2a9aae22ae194a5c1cef2ff08cbaf7638c3f267af80f92cdff4edf8eae68e22 + languageName: node + linkType: hard + +"@react-native-community/cli-types@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli-types@npm:12.3.0" + dependencies: + joi: ^17.2.1 + checksum: 001bd07cc93e9248ee324334d0c3f55415c7174aae51f62f6884a7f2edc4b39a31c66420b2006d9980a4481da466c048c91cf2b936cc220a6dbc7726e614f981 + languageName: node + linkType: hard + +"@react-native-community/cli@npm:12.3.0": + version: 12.3.0 + resolution: "@react-native-community/cli@npm:12.3.0" + dependencies: + "@react-native-community/cli-clean": 12.3.0 + "@react-native-community/cli-config": 12.3.0 + "@react-native-community/cli-debugger-ui": 12.3.0 + "@react-native-community/cli-doctor": 12.3.0 + "@react-native-community/cli-hermes": 12.3.0 + "@react-native-community/cli-plugin-metro": 12.3.0 + "@react-native-community/cli-server-api": 12.3.0 + "@react-native-community/cli-tools": 12.3.0 + "@react-native-community/cli-types": 12.3.0 + chalk: ^4.1.2 + commander: ^9.4.1 + deepmerge: ^4.3.0 + execa: ^5.0.0 + find-up: ^4.1.0 + fs-extra: ^8.1.0 + graceful-fs: ^4.1.3 + prompts: ^2.4.2 + semver: ^7.5.2 + bin: + react-native: build/bin.js + checksum: 30ab321b69977c8ac4d0a4634dd6af893c2f055734eed486aaacc93ab85fe9a6dd124bc0c72a32f750bb7dfb3fd4ac5ce30a7ec916905b47efc443598afdae00 + languageName: node + linkType: hard + +"@react-native/assets-registry@npm:0.73.1": + version: 0.73.1 + resolution: "@react-native/assets-registry@npm:0.73.1" + checksum: d9d09774d497bae13b1fb6a1c977bf6e442858639ee66fe4e8f955cfc903a16f79de6129471114a918a4b814eb5150bd808a5a7dc9f8b12d49795d9488d4cb67 + languageName: node + linkType: hard + +"@react-native/babel-plugin-codegen@npm:0.73.2": + version: 0.73.2 + resolution: "@react-native/babel-plugin-codegen@npm:0.73.2" + dependencies: + "@react-native/codegen": 0.73.2 + checksum: 0951dd53499342d2ac7c10bf7a764dac9e534b38d0bba673f9fa9cec80171a9bc8ad9dcea86e832453f04bcfa2bf7bf607a1b33056aa431e8666c05aa5f668af + languageName: node + linkType: hard + +"@react-native/babel-preset@npm:0.73.19, @react-native/babel-preset@npm:^0.73.19": + version: 0.73.19 + resolution: "@react-native/babel-preset@npm:0.73.19" + dependencies: + "@babel/core": ^7.20.0 + "@babel/plugin-proposal-async-generator-functions": ^7.0.0 + "@babel/plugin-proposal-class-properties": ^7.18.0 + "@babel/plugin-proposal-export-default-from": ^7.0.0 + "@babel/plugin-proposal-nullish-coalescing-operator": ^7.18.0 + "@babel/plugin-proposal-numeric-separator": ^7.0.0 + "@babel/plugin-proposal-object-rest-spread": ^7.20.0 + "@babel/plugin-proposal-optional-catch-binding": ^7.0.0 + "@babel/plugin-proposal-optional-chaining": ^7.20.0 + "@babel/plugin-syntax-dynamic-import": ^7.8.0 + "@babel/plugin-syntax-export-default-from": ^7.0.0 + "@babel/plugin-syntax-flow": ^7.18.0 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.0.0 + "@babel/plugin-syntax-optional-chaining": ^7.0.0 + "@babel/plugin-transform-arrow-functions": ^7.0.0 + "@babel/plugin-transform-async-to-generator": ^7.20.0 + "@babel/plugin-transform-block-scoping": ^7.0.0 + "@babel/plugin-transform-classes": ^7.0.0 + "@babel/plugin-transform-computed-properties": ^7.0.0 + "@babel/plugin-transform-destructuring": ^7.20.0 + "@babel/plugin-transform-flow-strip-types": ^7.20.0 + "@babel/plugin-transform-function-name": ^7.0.0 + "@babel/plugin-transform-literals": ^7.0.0 + "@babel/plugin-transform-modules-commonjs": ^7.0.0 + "@babel/plugin-transform-named-capturing-groups-regex": ^7.0.0 + "@babel/plugin-transform-parameters": ^7.0.0 + "@babel/plugin-transform-private-methods": ^7.22.5 + "@babel/plugin-transform-private-property-in-object": ^7.22.11 + "@babel/plugin-transform-react-display-name": ^7.0.0 + "@babel/plugin-transform-react-jsx": ^7.0.0 + "@babel/plugin-transform-react-jsx-self": ^7.0.0 + "@babel/plugin-transform-react-jsx-source": ^7.0.0 + "@babel/plugin-transform-runtime": ^7.0.0 + "@babel/plugin-transform-shorthand-properties": ^7.0.0 + "@babel/plugin-transform-spread": ^7.0.0 + "@babel/plugin-transform-sticky-regex": ^7.0.0 + "@babel/plugin-transform-typescript": ^7.5.0 + "@babel/plugin-transform-unicode-regex": ^7.0.0 + "@babel/template": ^7.0.0 + "@react-native/babel-plugin-codegen": 0.73.2 + babel-plugin-transform-flow-enums: ^0.0.2 + react-refresh: ^0.14.0 + peerDependencies: + "@babel/core": "*" + checksum: 3c3d09f6e0c88efc3cf372ac7d866c1410c60e3dd0a5aeb63a02e732eccefe670ebc8127a60235639590568c2a3343e0f24b7159ad174091932177121cc59e1e + languageName: node + linkType: hard + +"@react-native/codegen@npm:0.73.2": + version: 0.73.2 + resolution: "@react-native/codegen@npm:0.73.2" + dependencies: + "@babel/parser": ^7.20.0 + flow-parser: ^0.206.0 + glob: ^7.1.1 + invariant: ^2.2.4 + jscodeshift: ^0.14.0 + mkdirp: ^0.5.1 + nullthrows: ^1.1.1 + peerDependencies: + "@babel/preset-env": ^7.1.6 + checksum: 92a40fc695ba0c19790e9e7e73c064b4ae48f4300f5d258fdf746d4fd34ef028fc1e10ce487f9fb54ff36710c5e3b032bd496147564a0369b2d5689b12fbc6bb + languageName: node + linkType: hard + +"@react-native/community-cli-plugin@npm:0.73.12": + version: 0.73.12 + resolution: "@react-native/community-cli-plugin@npm:0.73.12" + dependencies: + "@react-native-community/cli-server-api": 12.3.0 + "@react-native-community/cli-tools": 12.3.0 + "@react-native/dev-middleware": 0.73.7 + "@react-native/metro-babel-transformer": 0.73.13 + chalk: ^4.0.0 + execa: ^5.1.1 + metro: ^0.80.3 + metro-config: ^0.80.3 + metro-core: ^0.80.3 + node-fetch: ^2.2.0 + readline: ^1.3.0 + checksum: 503936ea343d4c5d3f6234e59cbd36e750174a9bc80a38f308d2fe317b646b18da6ea3780caffb676320e23be808e529f7bee11667052a86ed75b1cacf5b8b1c + languageName: node + linkType: hard + +"@react-native/debugger-frontend@npm:0.73.3": + version: 0.73.3 + resolution: "@react-native/debugger-frontend@npm:0.73.3" + checksum: 71ecf6fdf3ecf2cae80818e2b8717acb22e291fd19edf89f570e695a165660a749244fb03465b3b8b9b7166cbdee627577dd75321f6793649b0a255aec722d92 + languageName: node + linkType: hard + +"@react-native/dev-middleware@npm:0.73.7": + version: 0.73.7 + resolution: "@react-native/dev-middleware@npm:0.73.7" + dependencies: + "@isaacs/ttlcache": ^1.4.1 + "@react-native/debugger-frontend": 0.73.3 + chrome-launcher: ^0.15.2 + chromium-edge-launcher: ^1.0.0 + connect: ^3.6.5 + debug: ^2.2.0 + node-fetch: ^2.2.0 + open: ^7.0.3 + serve-static: ^1.13.1 + temp-dir: ^2.0.0 + checksum: fd22acc763282c0cec8776cf1604a063b016b96fce0922c1f6690cd6df1cfde4540f3df3364721a13d12777e84bfc218a2a3b71f9965ee6be6bfad51c5a0d07e + languageName: node + linkType: hard + +"@react-native/eslint-config@npm:^0.74.0": + version: 0.74.0 + resolution: "@react-native/eslint-config@npm:0.74.0" + dependencies: + "@babel/core": ^7.20.0 + "@babel/eslint-parser": ^7.20.0 + "@react-native/eslint-plugin": ^0.74.0 + "@typescript-eslint/eslint-plugin": ^6.7.4 + "@typescript-eslint/parser": ^6.7.4 + eslint-config-prettier: ^8.5.0 + eslint-plugin-eslint-comments: ^3.2.0 + eslint-plugin-ft-flow: ^2.0.1 + eslint-plugin-jest: ^26.5.3 + eslint-plugin-prettier: ^4.2.1 + eslint-plugin-react: ^7.30.1 + eslint-plugin-react-hooks: ^4.6.0 + eslint-plugin-react-native: ^4.0.0 + peerDependencies: + eslint: ">=8" + prettier: ">=2" + checksum: c384da1f3613d5c801f6be2e9e1693ecf22834b69fbfd6ddb726ce43c504def8283ac984e9c09100935f2b42f014d2202ecdb361f9bffbb5c490bb5de82c0788 + languageName: node + linkType: hard + +"@react-native/eslint-plugin@npm:^0.74.0": + version: 0.74.0 + resolution: "@react-native/eslint-plugin@npm:0.74.0" + checksum: 2ac8713e602d2ec993f03b1f5b161f0739a71a9b36bf185de48ddcdff6c1e30c61729ad48c11a963d39a60d10d2a2ecf4c4f922ef1ea40a8f2b1e8d71626fd2f + languageName: node + linkType: hard + +"@react-native/gradle-plugin@npm:0.73.4": + version: 0.73.4 + resolution: "@react-native/gradle-plugin@npm:0.73.4" + checksum: f72e2a9fc44f7a848142f09e939686b85f7f51edb0634407635b742f152f2d5162eb08579a6a03c37f2550397a64915578d185dac1b95c7cf1ba8729fa51f389 + languageName: node + linkType: hard + +"@react-native/js-polyfills@npm:0.73.1": + version: 0.73.1 + resolution: "@react-native/js-polyfills@npm:0.73.1" + checksum: ec5899c3f2480475a6dccb252f3de6cc0b2eccc32d3d4a61a479e5f09d6458d86860fd60af472448b417d6e19f75c6b4008de245ab7fbb6d9c4300f452a37fd5 + languageName: node + linkType: hard + +"@react-native/metro-babel-transformer@npm:0.73.13": + version: 0.73.13 + resolution: "@react-native/metro-babel-transformer@npm:0.73.13" + dependencies: + "@babel/core": ^7.20.0 + "@react-native/babel-preset": 0.73.19 + hermes-parser: 0.15.0 + nullthrows: ^1.1.1 + peerDependencies: + "@babel/core": "*" + checksum: 56b7330dd7fef32ede05471bccbab1b3fe73902b165add4150c4302eff19f1d35b196b98cc3dbcff183b5d8ef814a472806ee36d81204c43c920ea832185c123 + languageName: node + linkType: hard + +"@react-native/metro-config@npm:^0.73.3": + version: 0.73.3 + resolution: "@react-native/metro-config@npm:0.73.3" + dependencies: + "@react-native/js-polyfills": 0.73.1 + "@react-native/metro-babel-transformer": 0.73.13 + metro-config: ^0.80.3 + metro-runtime: ^0.80.3 + checksum: f22ef2957235d98898c305b3f9acb0a521f3bd1c759ec9d7f52fd1745f636c6915d224a69ee909e58e6336059c8dee91a66a065a558514d2eff753902edb1c80 + languageName: node + linkType: hard + +"@react-native/normalize-colors@npm:0.73.2, @react-native/normalize-colors@npm:^0.73.0": + version: 0.73.2 + resolution: "@react-native/normalize-colors@npm:0.73.2" + checksum: ddf9384ad41adc4f3c8eb61ddd27113130c8060bd2f4255bee284a52aa7ddcff8a5e751f569dd416c45f8b9d4062392fa7219b221f2f7f0b229d02b8d2a5b974 + languageName: node + linkType: hard + +"@react-native/typescript-config@npm:^0.74.0": + version: 0.74.0 + resolution: "@react-native/typescript-config@npm:0.74.0" + checksum: 4b027641316d7fa9975f35982a55f9de49df462845cb4b84f4e668ec034c22d22ecf4a79d4a017d7a3d11ca770e288a6ba7ad6ab7758ff7990cfc96ef0e38771 + languageName: node + linkType: hard + +"@react-native/virtualized-lists@npm:0.73.4": + version: 0.73.4 + resolution: "@react-native/virtualized-lists@npm:0.73.4" + dependencies: + invariant: ^2.2.4 + nullthrows: ^1.1.1 + peerDependencies: + react-native: "*" + checksum: 59826b146cdcff358f27b118b9dcc6fa23534f3880b5e8546c79aedff8cb4e028af652b0371e0080610e30a250c69607f45b2066c83762788783ccf2031938e3 + languageName: node + linkType: hard + +"@reduxjs/toolkit@npm:^2.0.1": + version: 2.0.1 + resolution: "@reduxjs/toolkit@npm:2.0.1" + dependencies: + immer: ^10.0.3 + redux: ^5.0.0 + redux-thunk: ^3.1.0 + reselect: ^5.0.1 + peerDependencies: + react: ^16.9.0 || ^17.0.0 || ^18 + react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0 + peerDependenciesMeta: + react: + optional: true + react-redux: + optional: true + checksum: d7e4783263dc79cb85c8d50db41209f16f0994520193ac2b378e63dc12f336cc6f58323e37d66ccf09493c49ead2f4827aac3e8d9c6ca7def21f842efb4f5f3d + languageName: node + linkType: hard + +"@sideway/address@npm:^4.1.3": + version: 4.1.4 + resolution: "@sideway/address@npm:4.1.4" + dependencies: + "@hapi/hoek": ^9.0.0 + checksum: b9fca2a93ac2c975ba12e0a6d97853832fb1f4fb02393015e012b47fa916a75ca95102d77214b2a29a2784740df2407951af8c5dde054824c65577fd293c4cdb + languageName: node + linkType: hard + +"@sideway/formula@npm:^3.0.1": + version: 3.0.1 + resolution: "@sideway/formula@npm:3.0.1" + checksum: e4beeebc9dbe2ff4ef0def15cec0165e00d1612e3d7cea0bc9ce5175c3263fc2c818b679bd558957f49400ee7be9d4e5ac90487e1625b4932e15c4aa7919c57a + languageName: node + linkType: hard + +"@sideway/pinpoint@npm:^2.0.0": + version: 2.0.0 + resolution: "@sideway/pinpoint@npm:2.0.0" + checksum: 0f4491e5897fcf5bf02c46f5c359c56a314e90ba243f42f0c100437935daa2488f20482f0f77186bd6bf43345095a95d8143ecf8b1f4d876a7bc0806aba9c3d2 + languageName: node + linkType: hard + +"@sinclair/typebox@npm:^0.27.8": + version: 0.27.8 + resolution: "@sinclair/typebox@npm:0.27.8" + checksum: 00bd7362a3439021aa1ea51b0e0d0a0e8ca1351a3d54c606b115fdcc49b51b16db6e5f43b4fe7a28c38688523e22a94d49dd31168868b655f0d4d50f032d07a1 + languageName: node + linkType: hard + +"@sinonjs/commons@npm:^3.0.0": + version: 3.0.0 + resolution: "@sinonjs/commons@npm:3.0.0" + dependencies: + type-detect: 4.0.8 + checksum: b4b5b73d4df4560fb8c0c7b38c7ad4aeabedd362f3373859d804c988c725889cde33550e4bcc7cd316a30f5152a2d1d43db71b6d0c38f5feef71fd8d016763f8 + languageName: node + linkType: hard + +"@sinonjs/fake-timers@npm:^10.0.2": + version: 10.3.0 + resolution: "@sinonjs/fake-timers@npm:10.3.0" + dependencies: + "@sinonjs/commons": ^3.0.0 + checksum: 614d30cb4d5201550c940945d44c9e0b6d64a888ff2cd5b357f95ad6721070d6b8839cd10e15b76bf5e14af0bcc1d8f9ec00d49a46318f1f669a4bec1d7f3148 + languageName: node + linkType: hard + +"@testing-library/react-native@npm:^12.4.3": + version: 12.4.3 + resolution: "@testing-library/react-native@npm:12.4.3" + dependencies: + jest-matcher-utils: ^29.7.0 + pretty-format: ^29.7.0 + redent: ^3.0.0 + peerDependencies: + jest: ">=28.0.0" + react: ">=16.8.0" + react-native: ">=0.59" + react-test-renderer: ">=16.8.0" + peerDependenciesMeta: + jest: + optional: true + checksum: bd1c06b200063ffad26245cbc61b7256b5bfcc2c69a32f7e6dc9ff1bf44c3743117d5010b8dbc8f9a1b660c3ee22ccf9ecc320c03db52f9ec75ba7e52c1d8ba3 + languageName: node + linkType: hard + +"@tsconfig/node10@npm:^1.0.7": + version: 1.0.9 + resolution: "@tsconfig/node10@npm:1.0.9" + checksum: a33ae4dc2a621c0678ac8ac4bceb8e512ae75dac65417a2ad9b022d9b5411e863c4c198b6ba9ef659e14b9fb609bbec680841a2e84c1172df7a5ffcf076539df + languageName: node + linkType: hard + +"@tsconfig/node12@npm:^1.0.7": + version: 1.0.11 + resolution: "@tsconfig/node12@npm:1.0.11" + checksum: 5ce29a41b13e7897a58b8e2df11269c5395999e588b9a467386f99d1d26f6c77d1af2719e407621412520ea30517d718d5192a32403b8dfcc163bf33e40a338a + languageName: node + linkType: hard + +"@tsconfig/node14@npm:^1.0.0": + version: 1.0.3 + resolution: "@tsconfig/node14@npm:1.0.3" + checksum: 19275fe80c4c8d0ad0abed6a96dbf00642e88b220b090418609c4376e1cef81bf16237bf170ad1b341452feddb8115d8dd2e5acdfdea1b27422071163dc9ba9d + languageName: node + linkType: hard + +"@tsconfig/node16@npm:^1.0.2": + version: 1.0.4 + resolution: "@tsconfig/node16@npm:1.0.4" + checksum: 202319785901f942a6e1e476b872d421baec20cf09f4b266a1854060efbf78cde16a4d256e8bc949d31e6cd9a90f1e8ef8fb06af96a65e98338a2b6b0de0a0ff + languageName: node + linkType: hard + +"@types/babel__core@npm:^7.1.14": + version: 7.20.5 + resolution: "@types/babel__core@npm:7.20.5" + dependencies: + "@babel/parser": ^7.20.7 + "@babel/types": ^7.20.7 + "@types/babel__generator": "*" + "@types/babel__template": "*" + "@types/babel__traverse": "*" + checksum: a3226f7930b635ee7a5e72c8d51a357e799d19cbf9d445710fa39ab13804f79ab1a54b72ea7d8e504659c7dfc50675db974b526142c754398d7413aa4bc30845 + languageName: node + linkType: hard + +"@types/babel__generator@npm:*": + version: 7.6.8 + resolution: "@types/babel__generator@npm:7.6.8" + dependencies: + "@babel/types": ^7.0.0 + checksum: 5b332ea336a2efffbdeedb92b6781949b73498606ddd4205462f7d96dafd45ff3618770b41de04c4881e333dd84388bfb8afbdf6f2764cbd98be550d85c6bb48 + languageName: node + linkType: hard + +"@types/babel__template@npm:*": + version: 7.4.4 + resolution: "@types/babel__template@npm:7.4.4" + dependencies: + "@babel/parser": ^7.1.0 + "@babel/types": ^7.0.0 + checksum: d7a02d2a9b67e822694d8e6a7ddb8f2b71a1d6962dfd266554d2513eefbb205b33ca71a0d163b1caea3981ccf849211f9964d8bd0727124d18ace45aa6c9ae29 + languageName: node + linkType: hard + +"@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": + version: 7.20.5 + resolution: "@types/babel__traverse@npm:7.20.5" + dependencies: + "@babel/types": ^7.20.7 + checksum: 608e0ab4fc31cd47011d98942e6241b34d461608c0c0e153377c5fd822c436c475f1ded76a56bfa76a1adf8d9266b727bbf9bfac90c4cb152c97f30dadc5b7e8 + languageName: node + linkType: hard + +"@types/graceful-fs@npm:^4.1.3": + version: 4.1.9 + resolution: "@types/graceful-fs@npm:4.1.9" + dependencies: + "@types/node": "*" + checksum: 79d746a8f053954bba36bd3d94a90c78de995d126289d656fb3271dd9f1229d33f678da04d10bce6be440494a5a73438e2e363e92802d16b8315b051036c5256 + languageName: node + linkType: hard + +"@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": + version: 2.0.6 + resolution: "@types/istanbul-lib-coverage@npm:2.0.6" + checksum: 3feac423fd3e5449485afac999dcfcb3d44a37c830af898b689fadc65d26526460bedb889db278e0d4d815a670331796494d073a10ee6e3a6526301fe7415778 + languageName: node + linkType: hard + +"@types/istanbul-lib-report@npm:*": + version: 3.0.3 + resolution: "@types/istanbul-lib-report@npm:3.0.3" + dependencies: + "@types/istanbul-lib-coverage": "*" + checksum: b91e9b60f865ff08cb35667a427b70f6c2c63e88105eadd29a112582942af47ed99c60610180aa8dcc22382fa405033f141c119c69b95db78c4c709fbadfeeb4 + languageName: node + linkType: hard + +"@types/istanbul-reports@npm:^3.0.0": + version: 3.0.4 + resolution: "@types/istanbul-reports@npm:3.0.4" + dependencies: + "@types/istanbul-lib-report": "*" + checksum: 93eb18835770b3431f68ae9ac1ca91741ab85f7606f310a34b3586b5a34450ec038c3eed7ab19266635499594de52ff73723a54a72a75b9f7d6a956f01edee95 + languageName: node + linkType: hard + +"@types/jest@npm:^29.5.11": + version: 29.5.11 + resolution: "@types/jest@npm:29.5.11" + dependencies: + expect: ^29.0.0 + pretty-format: ^29.0.0 + checksum: f892a06ec9f0afa9a61cd7fa316ec614e21d4df1ad301b5a837787e046fcb40dfdf7f264a55e813ac6b9b633cb9d366bd5b8d1cea725e84102477b366df23fdd + languageName: node + linkType: hard + +"@types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.9": + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98 + languageName: node + linkType: hard + +"@types/node@npm:*": + version: 20.11.0 + resolution: "@types/node@npm:20.11.0" + dependencies: + undici-types: ~5.26.4 + checksum: 1bd6890db7e0404d11c33d28f46f19f73256f0ba35d19f0ef2a0faba09f366f188915fb9338eebebcc472075c1c4941e17c7002786aa69afa44980737846b200 + languageName: node + linkType: hard + +"@types/prop-types@npm:*": + version: 15.7.11 + resolution: "@types/prop-types@npm:15.7.11" + checksum: 7519ff11d06fbf6b275029fe03fff9ec377b4cb6e864cac34d87d7146c7f5a7560fd164bdc1d2dbe00b60c43713631251af1fd3d34d46c69cd354602bc0c7c54 + languageName: node + linkType: hard + +"@types/react-test-renderer@npm:^18.0.7": + version: 18.0.7 + resolution: "@types/react-test-renderer@npm:18.0.7" + dependencies: + "@types/react": "*" + checksum: 701d7d815fe7b921712ebdb2c4434e99b92403d37c51b33a01ce1b62fed7d1efbf9f749971d9031a5b137c6d5e194249c378106768aa69725a01f150fef0ec7f + languageName: node + linkType: hard + +"@types/react@npm:*, @types/react@npm:^18.2.47": + version: 18.2.47 + resolution: "@types/react@npm:18.2.47" + dependencies: + "@types/prop-types": "*" + "@types/scheduler": "*" + csstype: ^3.0.2 + checksum: 49608f07f73374e535b21f99fee28e6cfd5801d887c6ed88c41b4dc701dbcee9f0c4d289d9af7b2b23114f76dbf203ffe2c9191bfb4958cf18dae5a25daedbd0 + languageName: node + linkType: hard + +"@types/scheduler@npm:*": + version: 0.16.8 + resolution: "@types/scheduler@npm:0.16.8" + checksum: 6c091b096daa490093bf30dd7947cd28e5b2cd612ec93448432b33f724b162587fed9309a0acc104d97b69b1d49a0f3fc755a62282054d62975d53d7fd13472d + languageName: node + linkType: hard + +"@types/semver@npm:^7.3.12, @types/semver@npm:^7.5.0": + version: 7.5.6 + resolution: "@types/semver@npm:7.5.6" + checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 + languageName: node + linkType: hard + +"@types/stack-utils@npm:^2.0.0": + version: 2.0.3 + resolution: "@types/stack-utils@npm:2.0.3" + checksum: 72576cc1522090fe497337c2b99d9838e320659ac57fa5560fcbdcbafcf5d0216c6b3a0a8a4ee4fdb3b1f5e3420aa4f6223ab57b82fef3578bec3206425c6cf5 + languageName: node + linkType: hard + +"@types/use-sync-external-store@npm:^0.0.3": + version: 0.0.3 + resolution: "@types/use-sync-external-store@npm:0.0.3" + checksum: 161ddb8eec5dbe7279ac971531217e9af6b99f7783213566d2b502e2e2378ea19cf5e5ea4595039d730aa79d3d35c6567d48599f69773a02ffcff1776ec2a44e + languageName: node + linkType: hard + +"@types/yargs-parser@npm:*": + version: 21.0.3 + resolution: "@types/yargs-parser@npm:21.0.3" + checksum: ef236c27f9432983e91432d974243e6c4cdae227cb673740320eff32d04d853eed59c92ca6f1142a335cfdc0e17cccafa62e95886a8154ca8891cc2dec4ee6fc + languageName: node + linkType: hard + +"@types/yargs@npm:^15.0.0": + version: 15.0.19 + resolution: "@types/yargs@npm:15.0.19" + dependencies: + "@types/yargs-parser": "*" + checksum: 6a509db36304825674f4f00300323dce2b4d850e75819c3db87e9e9f213ac2c4c6ed3247a3e4eed6e8e45b3f191b133a356d3391dd694d9ea27a0507d914ef4c + languageName: node + linkType: hard + +"@types/yargs@npm:^17.0.8": + version: 17.0.32 + resolution: "@types/yargs@npm:17.0.32" + dependencies: + "@types/yargs-parser": "*" + checksum: 4505bdebe8716ff383640c6e928f855b5d337cb3c68c81f7249fc6b983d0aa48de3eee26062b84f37e0d75a5797bc745e0c6e76f42f81771252a758c638f36ba + languageName: node + linkType: hard + +"@typescript-eslint/eslint-plugin@npm:^6.18.1, @typescript-eslint/eslint-plugin@npm:^6.7.4": + version: 6.18.1 + resolution: "@typescript-eslint/eslint-plugin@npm:6.18.1" + dependencies: + "@eslint-community/regexpp": ^4.5.1 + "@typescript-eslint/scope-manager": 6.18.1 + "@typescript-eslint/type-utils": 6.18.1 + "@typescript-eslint/utils": 6.18.1 + "@typescript-eslint/visitor-keys": 6.18.1 + debug: ^4.3.4 + graphemer: ^1.4.0 + ignore: ^5.2.4 + natural-compare: ^1.4.0 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependencies: + "@typescript-eslint/parser": ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 933ede339bfac8377f94b211253bce40ace272a01466c290b38e681ec4752128ce63f827bbe6cc70cc0383d01655c8a22b25c640841fe90dfa4e57f73baaf2a9 + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:^6.18.1, @typescript-eslint/parser@npm:^6.7.4": + version: 6.18.1 + resolution: "@typescript-eslint/parser@npm:6.18.1" + dependencies: + "@typescript-eslint/scope-manager": 6.18.1 + "@typescript-eslint/types": 6.18.1 + "@typescript-eslint/typescript-estree": 6.18.1 + "@typescript-eslint/visitor-keys": 6.18.1 + debug: ^4.3.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: f123310976a73d9f08470dbad917c9e7b038e9e1362924a225a29d35fac1a2726d447952ca77b914d47f50791d235bb66f5171c7a4a0536e9c170fb20e73a2e4 + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/scope-manager@npm:5.62.0" + dependencies: + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/visitor-keys": 5.62.0 + checksum: 6062d6b797fe1ce4d275bb0d17204c827494af59b5eaf09d8a78cdd39dadddb31074dded4297aaf5d0f839016d601032857698b0e4516c86a41207de606e9573 + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/scope-manager@npm:6.18.1" + dependencies: + "@typescript-eslint/types": 6.18.1 + "@typescript-eslint/visitor-keys": 6.18.1 + checksum: d6708f9f2658ab68f9f4628b93c4131fb82c362383b4d5d671491082ff610258f2fc9e293739618dc76ed6d2c5909f000a54b9b905e58a5172e6e2f731666245 + languageName: node + linkType: hard + +"@typescript-eslint/type-utils@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/type-utils@npm:6.18.1" + dependencies: + "@typescript-eslint/typescript-estree": 6.18.1 + "@typescript-eslint/utils": 6.18.1 + debug: ^4.3.4 + ts-api-utils: ^1.0.1 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 44d7e14460f8a22a0c5c58ff7004cb40061e722dfcec3ac4ee15d40dafe68c61e555a79e81af8ffa0ca845fb3caf3ed5376853b9a94e2f3c823ac5e8267230c8 + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/types@npm:5.62.0" + checksum: 48c87117383d1864766486f24de34086155532b070f6264e09d0e6139449270f8a9559cfef3c56d16e3bcfb52d83d42105d61b36743626399c7c2b5e0ac3b670 + languageName: node + linkType: hard + +"@typescript-eslint/types@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/types@npm:6.18.1" + checksum: f1713785c4dd49e6aae4186042679d205312a1c6cbfcdad133abf5c61f71c115e04c6643aa6a8aacd732e6b64030d71bbc92762164b7f231d98fc2e31c3f8ed8 + languageName: node + linkType: hard + +"@typescript-eslint/typescript-estree@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" + dependencies: + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/visitor-keys": 5.62.0 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + semver: ^7.3.7 + tsutils: ^3.21.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 3624520abb5807ed8f57b1197e61c7b1ed770c56dfcaca66372d584ff50175225798bccb701f7ef129d62c5989070e1ee3a0aa2d84e56d9524dcf011a2bb1a52 + languageName: node + linkType: hard + +"@typescript-eslint/typescript-estree@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/typescript-estree@npm:6.18.1" + dependencies: + "@typescript-eslint/types": 6.18.1 + "@typescript-eslint/visitor-keys": 6.18.1 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + minimatch: 9.0.3 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependenciesMeta: + typescript: + optional: true + checksum: fc5fb8abea9a6c3b774f62989b9a463569d141c32f6f2febef11d4161acaff946b204226234077b1126294fcf86a83c5fc9227f34ea3ba4cc9d39ca843dfae97 + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/utils@npm:6.18.1" + dependencies: + "@eslint-community/eslint-utils": ^4.4.0 + "@types/json-schema": ^7.0.12 + "@types/semver": ^7.5.0 + "@typescript-eslint/scope-manager": 6.18.1 + "@typescript-eslint/types": 6.18.1 + "@typescript-eslint/typescript-estree": 6.18.1 + semver: ^7.5.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + checksum: b7265b0cae099feb98e233dd518b54408fde01b9703535c9e9b84c24e9af6fff0fd9a61f0f7d7b24fb738151ad25a7f57210e83a5a2700cac38ee627f5b856d4 + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:^5.10.0": + version: 5.62.0 + resolution: "@typescript-eslint/utils@npm:5.62.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@types/json-schema": ^7.0.9 + "@types/semver": ^7.3.12 + "@typescript-eslint/scope-manager": 5.62.0 + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/typescript-estree": 5.62.0 + eslint-scope: ^5.1.1 + semver: ^7.3.7 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: ee9398c8c5db6d1da09463ca7bf36ed134361e20131ea354b2da16a5fdb6df9ba70c62a388d19f6eebb421af1786dbbd79ba95ddd6ab287324fc171c3e28d931 + languageName: node + linkType: hard + +"@typescript-eslint/visitor-keys@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/visitor-keys@npm:5.62.0" + dependencies: + "@typescript-eslint/types": 5.62.0 + eslint-visitor-keys: ^3.3.0 + checksum: 976b05d103fe8335bef5c93ad3f76d781e3ce50329c0243ee0f00c0fcfb186c81df50e64bfdd34970148113f8ade90887f53e3c4938183afba830b4ba8e30a35 + languageName: node + linkType: hard + +"@typescript-eslint/visitor-keys@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/visitor-keys@npm:6.18.1" + dependencies: + "@typescript-eslint/types": 6.18.1 + eslint-visitor-keys: ^3.4.1 + checksum: 4befc450fd459e9dc368c3da7066a4948946e8b24383bf0fbaacd059cbe69ff0f71cac4f6d5d1f99a523c1fb20d39bef907e522d2c8e8315a8ce4ce678a58540 + languageName: node + linkType: hard + +"@ungap/structured-clone@npm:^1.2.0": + version: 1.2.0 + resolution: "@ungap/structured-clone@npm:1.2.0" + checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 + languageName: node + linkType: hard + +"abbrev@npm:^2.0.0": + version: 2.0.0 + resolution: "abbrev@npm:2.0.0" + checksum: 0e994ad2aa6575f94670d8a2149afe94465de9cedaaaac364e7fb43a40c3691c980ff74899f682f4ca58fa96b4cbd7421a015d3a6defe43a442117d7821a2f36 + languageName: node + linkType: hard + +"abort-controller@npm:^3.0.0": + version: 3.0.0 + resolution: "abort-controller@npm:3.0.0" + dependencies: + event-target-shim: ^5.0.0 + checksum: 170bdba9b47b7e65906a28c8ce4f38a7a369d78e2271706f020849c1bfe0ee2067d4261df8bbb66eb84f79208fd5b710df759d64191db58cfba7ce8ef9c54b75 + languageName: node + linkType: hard + +"accepts@npm:^1.3.7, accepts@npm:~1.3.5, accepts@npm:~1.3.7": + version: 1.3.8 + resolution: "accepts@npm:1.3.8" + dependencies: + mime-types: ~2.1.34 + negotiator: 0.6.3 + checksum: 50c43d32e7b50285ebe84b613ee4a3aa426715a7d131b65b786e2ead0fd76b6b60091b9916d3478a75f11f162628a2139991b6c03ab3f1d9ab7c86075dc8eab4 + languageName: node + linkType: hard + +"acorn-jsx@npm:^5.3.2": + version: 5.3.2 + resolution: "acorn-jsx@npm:5.3.2" + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: c3d3b2a89c9a056b205b69530a37b972b404ee46ec8e5b341666f9513d3163e2a4f214a71f4dfc7370f5a9c07472d2fd1c11c91c3f03d093e37637d95da98950 + languageName: node + linkType: hard + +"acorn-walk@npm:^8.1.1": + version: 8.3.2 + resolution: "acorn-walk@npm:8.3.2" + checksum: 3626b9d26a37b1b427796feaa5261faf712307a8920392c8dce9a5739fb31077667f4ad2ec71c7ac6aaf9f61f04a9d3d67ff56f459587206fc04aa31c27ef392 + languageName: node + linkType: hard + +"acorn@npm:^8.4.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0": + version: 8.11.3 + resolution: "acorn@npm:8.11.3" + bin: + acorn: bin/acorn + checksum: 76d8e7d559512566b43ab4aadc374f11f563f0a9e21626dd59cb2888444e9445923ae9f3699972767f18af61df89cd89f5eaaf772d1327b055b45cb829b4a88c + languageName: node + linkType: hard + +"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0": + version: 7.1.0 + resolution: "agent-base@npm:7.1.0" + dependencies: + debug: ^4.3.4 + checksum: f7828f991470a0cc22cb579c86a18cbae83d8a3cbed39992ab34fc7217c4d126017f1c74d0ab66be87f71455318a8ea3e757d6a37881b8d0f2a2c6aa55e5418f + languageName: node + linkType: hard + +"aggregate-error@npm:^3.0.0": + version: 3.1.0 + resolution: "aggregate-error@npm:3.1.0" + dependencies: + clean-stack: ^2.0.0 + indent-string: ^4.0.0 + checksum: 1101a33f21baa27a2fa8e04b698271e64616b886795fd43c31068c07533c7b3facfcaf4e9e0cab3624bd88f729a592f1c901a1a229c9e490eafce411a8644b79 + languageName: node + linkType: hard + +"ajv@npm:^6.12.4": + version: 6.12.6 + resolution: "ajv@npm:6.12.6" + dependencies: + fast-deep-equal: ^3.1.1 + fast-json-stable-stringify: ^2.0.0 + json-schema-traverse: ^0.4.1 + uri-js: ^4.2.2 + checksum: 874972efe5c4202ab0a68379481fbd3d1b5d0a7bd6d3cc21d40d3536ebff3352a2a1fabb632d4fd2cc7fe4cbdcd5ed6782084c9bbf7f32a1536d18f9da5007d4 + languageName: node + linkType: hard + +"anser@npm:^1.4.9": + version: 1.4.10 + resolution: "anser@npm:1.4.10" + checksum: 3823c64f8930d3d97f36e56cdf646fa6351f1227e25eee70c3a17697447cae4238fc3a309bb3bc2003cf930687fa72aed71426dbcf3c0a15565e120a7fee5507 + languageName: node + linkType: hard + +"ansi-escapes@npm:^4.2.1": + version: 4.3.2 + resolution: "ansi-escapes@npm:4.3.2" + dependencies: + type-fest: ^0.21.3 + checksum: 93111c42189c0a6bed9cdb4d7f2829548e943827ee8479c74d6e0b22ee127b2a21d3f8b5ca57723b8ef78ce011fbfc2784350eb2bde3ccfccf2f575fa8489815 + languageName: node + linkType: hard + +"ansi-fragments@npm:^0.2.1": + version: 0.2.1 + resolution: "ansi-fragments@npm:0.2.1" + dependencies: + colorette: ^1.0.7 + slice-ansi: ^2.0.0 + strip-ansi: ^5.0.0 + checksum: 22c3eb8a0aec6bcc15f4e78d77a264ee0c92160b09c94260d1161d051eb8c77c7ecfeb3c8ec44ca180bad554fef3489528c509a644a7589635fc36bcaf08234f + languageName: node + linkType: hard + +"ansi-regex@npm:^4.1.0": + version: 4.1.1 + resolution: "ansi-regex@npm:4.1.1" + checksum: b1a6ee44cb6ecdabaa770b2ed500542714d4395d71c7e5c25baa631f680fb2ad322eb9ba697548d498a6fd366949fc8b5bfcf48d49a32803611f648005b01888 + languageName: node + linkType: hard + +"ansi-regex@npm:^5.0.0, ansi-regex@npm:^5.0.1": + version: 5.0.1 + resolution: "ansi-regex@npm:5.0.1" + checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b + languageName: node + linkType: hard + +"ansi-regex@npm:^6.0.1": + version: 6.0.1 + resolution: "ansi-regex@npm:6.0.1" + checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 + languageName: node + linkType: hard + +"ansi-styles@npm:^3.2.0, ansi-styles@npm:^3.2.1": + version: 3.2.1 + resolution: "ansi-styles@npm:3.2.1" + dependencies: + color-convert: ^1.9.0 + checksum: d85ade01c10e5dd77b6c89f34ed7531da5830d2cb5882c645f330079975b716438cd7ebb81d0d6e6b4f9c577f19ae41ab55f07f19786b02f9dfd9e0377395665 + languageName: node + linkType: hard + +"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": + version: 4.3.0 + resolution: "ansi-styles@npm:4.3.0" + dependencies: + color-convert: ^2.0.1 + checksum: 513b44c3b2105dd14cc42a19271e80f386466c4be574bccf60b627432f9198571ebf4ab1e4c3ba17347658f4ee1711c163d574248c0c1cdc2d5917a0ad582ec4 + languageName: node + linkType: hard + +"ansi-styles@npm:^5.0.0": + version: 5.2.0 + resolution: "ansi-styles@npm:5.2.0" + checksum: d7f4e97ce0623aea6bc0d90dcd28881ee04cba06c570b97fd3391bd7a268eedfd9d5e2dd4fdcbdd82b8105df5faf6f24aaedc08eaf3da898e702db5948f63469 + languageName: node + linkType: hard + +"ansi-styles@npm:^6.1.0": + version: 6.2.1 + resolution: "ansi-styles@npm:6.2.1" + checksum: ef940f2f0ced1a6347398da88a91da7930c33ecac3c77b72c5905f8b8fe402c52e6fde304ff5347f616e27a742da3f1dc76de98f6866c69251ad0b07a66776d9 + languageName: node + linkType: hard + +"anymatch@npm:^3.0.3": + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" + dependencies: + normalize-path: ^3.0.0 + picomatch: ^2.0.4 + checksum: 3e044fd6d1d26545f235a9fe4d7a534e2029d8e59fa7fd9f2a6eb21230f6b5380ea1eaf55136e60cbf8e613544b3b766e7a6fa2102e2a3a117505466e3025dc2 + languageName: node + linkType: hard + +"appdirsjs@npm:^1.2.4": + version: 1.2.7 + resolution: "appdirsjs@npm:1.2.7" + checksum: 3411b4e31edf8687ad69638ef81b92b4889ad31e527b673a364990c28c99b6b8c3ea81b2b2b636d5b08e166a18706c4464fd8436b298f85384d499ba6b8dc4b7 + languageName: node + linkType: hard + +"arg@npm:^4.1.0": + version: 4.1.3 + resolution: "arg@npm:4.1.3" + checksum: 544af8dd3f60546d3e4aff084d451b96961d2267d668670199692f8d054f0415d86fc5497d0e641e91546f0aa920e7c29e5250e99fc89f5552a34b5d93b77f43 + languageName: node + linkType: hard + +"argparse@npm:^1.0.7": + version: 1.0.10 + resolution: "argparse@npm:1.0.10" + dependencies: + sprintf-js: ~1.0.2 + checksum: 7ca6e45583a28de7258e39e13d81e925cfa25d7d4aacbf806a382d3c02fcb13403a07fb8aeef949f10a7cfe4a62da0e2e807b348a5980554cc28ee573ef95945 + languageName: node + linkType: hard + +"argparse@npm:^2.0.1": + version: 2.0.1 + resolution: "argparse@npm:2.0.1" + checksum: 83644b56493e89a254bae05702abf3a1101b4fa4d0ca31df1c9985275a5a5bd47b3c27b7fa0b71098d41114d8ca000e6ed90cad764b306f8a503665e4d517ced + languageName: node + linkType: hard + +"array-buffer-byte-length@npm:^1.0.0": + version: 1.0.0 + resolution: "array-buffer-byte-length@npm:1.0.0" + dependencies: + call-bind: ^1.0.2 + is-array-buffer: ^3.0.1 + checksum: 044e101ce150f4804ad19c51d6c4d4cfa505c5b2577bd179256e4aa3f3f6a0a5e9874c78cd428ee566ac574c8a04d7ce21af9fe52e844abfdccb82b33035a7c3 + languageName: node + linkType: hard + +"array-includes@npm:^3.1.6": + version: 3.1.7 + resolution: "array-includes@npm:3.1.7" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + get-intrinsic: ^1.2.1 + is-string: ^1.0.7 + checksum: 06f9e4598fac12a919f7c59a3f04f010ea07f0b7f0585465ed12ef528a60e45f374e79d1bddbb34cdd4338357d00023ddbd0ac18b0be36964f5e726e8965d7fc + languageName: node + linkType: hard + +"array-union@npm:^2.1.0": + version: 2.1.0 + resolution: "array-union@npm:2.1.0" + checksum: 5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d + languageName: node + linkType: hard + +"array.prototype.flat@npm:^1.3.1": + version: 1.3.2 + resolution: "array.prototype.flat@npm:1.3.2" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + es-shim-unscopables: ^1.0.0 + checksum: 5d6b4bf102065fb3f43764bfff6feb3295d372ce89591e6005df3d0ce388527a9f03c909af6f2a973969a4d178ab232ffc9236654149173e0e187ec3a1a6b87b + languageName: node + linkType: hard + +"array.prototype.flatmap@npm:^1.3.1": + version: 1.3.2 + resolution: "array.prototype.flatmap@npm:1.3.2" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + es-shim-unscopables: ^1.0.0 + checksum: ce09fe21dc0bcd4f30271f8144083aa8c13d4639074d6c8dc82054b847c7fc9a0c97f857491f4da19d4003e507172a78f4bcd12903098adac8b9cd374f734be3 + languageName: node + linkType: hard + +"array.prototype.tosorted@npm:^1.1.1": + version: 1.1.2 + resolution: "array.prototype.tosorted@npm:1.1.2" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + es-shim-unscopables: ^1.0.0 + get-intrinsic: ^1.2.1 + checksum: 3607a7d6b117f0ffa6f4012457b7af0d47d38cf05e01d50e09682fd2fb782a66093a5e5fbbdbad77c8c824794a9d892a51844041641f719ad41e3a974f0764de + languageName: node + linkType: hard + +"arraybuffer.prototype.slice@npm:^1.0.2": + version: 1.0.2 + resolution: "arraybuffer.prototype.slice@npm:1.0.2" + dependencies: + array-buffer-byte-length: ^1.0.0 + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + get-intrinsic: ^1.2.1 + is-array-buffer: ^3.0.2 + is-shared-array-buffer: ^1.0.2 + checksum: c200faf437786f5b2c80d4564ff5481c886a16dee642ef02abdc7306c7edd523d1f01d1dd12b769c7eb42ac9bc53874510db19a92a2c035c0f6696172aafa5d3 + languageName: node + linkType: hard + +"asap@npm:~2.0.6": + version: 2.0.6 + resolution: "asap@npm:2.0.6" + checksum: b296c92c4b969e973260e47523207cd5769abd27c245a68c26dc7a0fe8053c55bb04360237cb51cab1df52be939da77150ace99ad331fb7fb13b3423ed73ff3d + languageName: node + linkType: hard + +"ast-types@npm:0.15.2": + version: 0.15.2 + resolution: "ast-types@npm:0.15.2" + dependencies: + tslib: ^2.0.1 + checksum: 24f0d86bf9e4c8dae16fa24b13c1776f2c2677040bcfbd4eb4f27911db49020be4876885e45e6cfcc548ed4dfea3a0742d77e3346b84fae47379cb0b89e9daa0 + languageName: node + linkType: hard + +"astral-regex@npm:^1.0.0": + version: 1.0.0 + resolution: "astral-regex@npm:1.0.0" + checksum: 93417fc0879531cd95ace2560a54df865c9461a3ac0714c60cbbaa5f1f85d2bee85489e78d82f70b911b71ac25c5f05fc5a36017f44c9bb33c701bee229ff848 + languageName: node + linkType: hard + +"async-limiter@npm:~1.0.0": + version: 1.0.1 + resolution: "async-limiter@npm:1.0.1" + checksum: 2b849695b465d93ad44c116220dee29a5aeb63adac16c1088983c339b0de57d76e82533e8e364a93a9f997f28bbfc6a92948cefc120652bd07f3b59f8d75cf2b + languageName: node + linkType: hard + +"asynciterator.prototype@npm:^1.0.0": + version: 1.0.0 + resolution: "asynciterator.prototype@npm:1.0.0" + dependencies: + has-symbols: ^1.0.3 + checksum: e8ebfd9493ac651cf9b4165e9d64030b3da1d17181bb1963627b59e240cdaf021d9b59d44b827dc1dde4e22387ec04c2d0f8720cf58a1c282e34e40cc12721b3 + languageName: node + linkType: hard + +"available-typed-arrays@npm:^1.0.5": + version: 1.0.5 + resolution: "available-typed-arrays@npm:1.0.5" + checksum: 20eb47b3cefd7db027b9bbb993c658abd36d4edd3fe1060e83699a03ee275b0c9b216cc076ff3f2db29073225fb70e7613987af14269ac1fe2a19803ccc97f1a + languageName: node + linkType: hard + +"babel-core@npm:^7.0.0-bridge.0": + version: 7.0.0-bridge.0 + resolution: "babel-core@npm:7.0.0-bridge.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2a1cb879019dffb08d17bec36e13c3a6d74c94773f41c1fd8b14de13f149cc34b705b0a1e07b42fcf35917b49d78db6ff0c5c3b00b202a5235013d517b5c6bbb + languageName: node + linkType: hard + +"babel-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "babel-jest@npm:29.7.0" + dependencies: + "@jest/transform": ^29.7.0 + "@types/babel__core": ^7.1.14 + babel-plugin-istanbul: ^6.1.1 + babel-preset-jest: ^29.6.3 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + slash: ^3.0.0 + peerDependencies: + "@babel/core": ^7.8.0 + checksum: ee6f8e0495afee07cac5e4ee167be705c711a8cc8a737e05a587a131fdae2b3c8f9aa55dfd4d9c03009ac2d27f2de63d8ba96d3e8460da4d00e8af19ef9a83f7 + languageName: node + linkType: hard + +"babel-plugin-istanbul@npm:^6.1.1": + version: 6.1.1 + resolution: "babel-plugin-istanbul@npm:6.1.1" + dependencies: + "@babel/helper-plugin-utils": ^7.0.0 + "@istanbuljs/load-nyc-config": ^1.0.0 + "@istanbuljs/schema": ^0.1.2 + istanbul-lib-instrument: ^5.0.4 + test-exclude: ^6.0.0 + checksum: cb4fd95738219f232f0aece1116628cccff16db891713c4ccb501cddbbf9272951a5df81f2f2658dfdf4b3e7b236a9d5cbcf04d5d8c07dd5077297339598061a + languageName: node + linkType: hard + +"babel-plugin-jest-hoist@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-plugin-jest-hoist@npm:29.6.3" + dependencies: + "@babel/template": ^7.3.3 + "@babel/types": ^7.3.3 + "@types/babel__core": ^7.1.14 + "@types/babel__traverse": ^7.0.6 + checksum: 51250f22815a7318f17214a9d44650ba89551e6d4f47a2dc259128428324b52f5a73979d010cefd921fd5a720d8c1d55ad74ff601cd94c7bd44d5f6292fde2d1 + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs2@npm:^0.4.7": + version: 0.4.7 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.7" + dependencies: + "@babel/compat-data": ^7.22.6 + "@babel/helper-define-polyfill-provider": ^0.4.4 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: b3c84ce44d00211c919a94f76453fb2065861612f3e44862eb7acf854e325c738a7441ad82690deba2b6fddfa2ad2cf2c46960f46fab2e3b17c6ed4fd2d73b38 + languageName: node + linkType: hard + +"babel-plugin-polyfill-corejs3@npm:^0.8.7": + version: 0.8.7 + resolution: "babel-plugin-polyfill-corejs3@npm:0.8.7" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.4.4 + core-js-compat: ^3.33.1 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 51bc215ab0c062bbb2225d912f69f8a6705d1837c8e01f9651307b5b937804287c1d73ebd8015689efcc02c3c21f37688b9ee6f5997635619b7a9cc4b7d9908d + languageName: node + linkType: hard + +"babel-plugin-polyfill-regenerator@npm:^0.5.4": + version: 0.5.4 + resolution: "babel-plugin-polyfill-regenerator@npm:0.5.4" + dependencies: + "@babel/helper-define-polyfill-provider": ^0.4.4 + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 461b735c6c0eca3c7b4434d14bfa98c2ab80f00e2bdc1c69eb46d1d300092a9786d76bbd3ee55e26d2d1a2380c14592d8d638e271dfd2a2b78a9eacffa3645d1 + languageName: node + linkType: hard + +"babel-plugin-transform-flow-enums@npm:^0.0.2": + version: 0.0.2 + resolution: "babel-plugin-transform-flow-enums@npm:0.0.2" + dependencies: + "@babel/plugin-syntax-flow": ^7.12.1 + checksum: fd52aef54448e01948a9d1cca0c8f87d064970c8682458962b7a222c372704bc2ce26ae8109e0ab2566e7ea5106856460f04c1a5ed794ab3bcd2f42cae1d9845 + languageName: node + linkType: hard + +"babel-preset-current-node-syntax@npm:^1.0.0": + version: 1.0.1 + resolution: "babel-preset-current-node-syntax@npm:1.0.1" + dependencies: + "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/plugin-syntax-bigint": ^7.8.3 + "@babel/plugin-syntax-class-properties": ^7.8.3 + "@babel/plugin-syntax-import-meta": ^7.8.3 + "@babel/plugin-syntax-json-strings": ^7.8.3 + "@babel/plugin-syntax-logical-assignment-operators": ^7.8.3 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + "@babel/plugin-syntax-numeric-separator": ^7.8.3 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + "@babel/plugin-syntax-top-level-await": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: d118c2742498c5492c095bc8541f4076b253e705b5f1ad9a2e7d302d81a84866f0070346662355c8e25fc02caa28dc2da8d69bcd67794a0d60c4d6fab6913cc8 + languageName: node + linkType: hard + +"babel-preset-jest@npm:^29.6.3": + version: 29.6.3 + resolution: "babel-preset-jest@npm:29.6.3" + dependencies: + babel-plugin-jest-hoist: ^29.6.3 + babel-preset-current-node-syntax: ^1.0.0 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: aa4ff2a8a728d9d698ed521e3461a109a1e66202b13d3494e41eea30729a5e7cc03b3a2d56c594423a135429c37bf63a9fa8b0b9ce275298be3095a88c69f6fb + languageName: node + linkType: hard + +"balanced-match@npm:^1.0.0": + version: 1.0.2 + resolution: "balanced-match@npm:1.0.2" + checksum: 9706c088a283058a8a99e0bf91b0a2f75497f185980d9ffa8b304de1d9e58ebda7c72c07ebf01dadedaac5b2907b2c6f566f660d62bd336c3468e960403b9d65 + languageName: node + linkType: hard + +"base64-js@npm:^1.3.1, base64-js@npm:^1.5.1": + version: 1.5.1 + resolution: "base64-js@npm:1.5.1" + checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005 + languageName: node + linkType: hard + +"bl@npm:^4.1.0": + version: 4.1.0 + resolution: "bl@npm:4.1.0" + dependencies: + buffer: ^5.5.0 + inherits: ^2.0.4 + readable-stream: ^3.4.0 + checksum: 9e8521fa7e83aa9427c6f8ccdcba6e8167ef30cc9a22df26effcc5ab682ef91d2cbc23a239f945d099289e4bbcfae7a192e9c28c84c6202e710a0dfec3722662 + languageName: node + linkType: hard + +"brace-expansion@npm:^1.1.7": + version: 1.1.11 + resolution: "brace-expansion@npm:1.1.11" + dependencies: + balanced-match: ^1.0.0 + concat-map: 0.0.1 + checksum: faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 + languageName: node + linkType: hard + +"brace-expansion@npm:^2.0.1": + version: 2.0.1 + resolution: "brace-expansion@npm:2.0.1" + dependencies: + balanced-match: ^1.0.0 + checksum: a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 + languageName: node + linkType: hard + +"braces@npm:^3.0.2": + version: 3.0.2 + resolution: "braces@npm:3.0.2" + dependencies: + fill-range: ^7.0.1 + checksum: e2a8e769a863f3d4ee887b5fe21f63193a891c68b612ddb4b68d82d1b5f3ff9073af066c343e9867a393fe4c2555dcb33e89b937195feb9c1613d259edfcd459 + languageName: node + linkType: hard + +"browserslist@npm:^4.22.2": + version: 4.22.2 + resolution: "browserslist@npm:4.22.2" + dependencies: + caniuse-lite: ^1.0.30001565 + electron-to-chromium: ^1.4.601 + node-releases: ^2.0.14 + update-browserslist-db: ^1.0.13 + bin: + browserslist: cli.js + checksum: 33ddfcd9145220099a7a1ac533cecfe5b7548ffeb29b313e1b57be6459000a1f8fa67e781cf4abee97268ac594d44134fcc4a6b2b4750ceddc9796e3a22076d9 + languageName: node + linkType: hard + +"bser@npm:2.1.1": + version: 2.1.1 + resolution: "bser@npm:2.1.1" + dependencies: + node-int64: ^0.4.0 + checksum: 9ba4dc58ce86300c862bffc3ae91f00b2a03b01ee07f3564beeeaf82aa243b8b03ba53f123b0b842c190d4399b94697970c8e7cf7b1ea44b61aa28c3526a4449 + languageName: node + linkType: hard + +"buffer-from@npm:^1.0.0": + version: 1.1.2 + resolution: "buffer-from@npm:1.1.2" + checksum: 0448524a562b37d4d7ed9efd91685a5b77a50672c556ea254ac9a6d30e3403a517d8981f10e565db24e8339413b43c97ca2951f10e399c6125a0d8911f5679bb + languageName: node + linkType: hard + +"buffer@npm:^5.5.0": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: ^1.3.1 + ieee754: ^1.1.13 + checksum: e2cf8429e1c4c7b8cbd30834ac09bd61da46ce35f5c22a78e6c2f04497d6d25541b16881e30a019c6fd3154150650ccee27a308eff3e26229d788bbdeb08ab84 + languageName: node + linkType: hard + +"bytes@npm:3.0.0": + version: 3.0.0 + resolution: "bytes@npm:3.0.0" + checksum: a2b386dd8188849a5325f58eef69c3b73c51801c08ffc6963eddc9be244089ba32d19347caf6d145c86f315ae1b1fc7061a32b0c1aa6379e6a719090287ed101 + languageName: node + linkType: hard + +"cacache@npm:^18.0.0": + version: 18.0.2 + resolution: "cacache@npm:18.0.2" + dependencies: + "@npmcli/fs": ^3.1.0 + fs-minipass: ^3.0.0 + glob: ^10.2.2 + lru-cache: ^10.0.1 + minipass: ^7.0.3 + minipass-collect: ^2.0.1 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + p-map: ^4.0.0 + ssri: ^10.0.0 + tar: ^6.1.11 + unique-filename: ^3.0.0 + checksum: 0250df80e1ad0c828c956744850c5f742c24244e9deb5b7dc81bca90f8c10e011e132ecc58b64497cc1cad9a98968676147fb6575f4f94722f7619757b17a11b + languageName: node + linkType: hard + +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.4, call-bind@npm:^1.0.5": + version: 1.0.5 + resolution: "call-bind@npm:1.0.5" + dependencies: + function-bind: ^1.1.2 + get-intrinsic: ^1.2.1 + set-function-length: ^1.1.1 + checksum: 449e83ecbd4ba48e7eaac5af26fea3b50f8f6072202c2dd7c5a6e7a6308f2421abe5e13a3bbd55221087f76320c5e09f25a8fdad1bab2b77c68ae74d92234ea5 + languageName: node + linkType: hard + +"caller-callsite@npm:^2.0.0": + version: 2.0.0 + resolution: "caller-callsite@npm:2.0.0" + dependencies: + callsites: ^2.0.0 + checksum: b685e9d126d9247b320cfdfeb3bc8da0c4be28d8fb98c471a96bc51aab3130099898a2fe3bf0308f0fe048d64c37d6d09f563958b9afce1a1e5e63d879c128a2 + languageName: node + linkType: hard + +"caller-path@npm:^2.0.0": + version: 2.0.0 + resolution: "caller-path@npm:2.0.0" + dependencies: + caller-callsite: ^2.0.0 + checksum: 3e12ccd0c71ec10a057aac69e3ec175b721ca858c640df021ef0d25999e22f7c1d864934b596b7d47038e9b56b7ec315add042abbd15caac882998b50102fb12 + languageName: node + linkType: hard + +"callsites@npm:^2.0.0": + version: 2.0.0 + resolution: "callsites@npm:2.0.0" + checksum: be2f67b247df913732b7dec1ec0bbfcdbaea263e5a95968b19ec7965affae9496b970e3024317e6d4baa8e28dc6ba0cec03f46fdddc2fdcc51396600e53c2623 + languageName: node + linkType: hard + +"callsites@npm:^3.0.0": + version: 3.1.0 + resolution: "callsites@npm:3.1.0" + checksum: 072d17b6abb459c2ba96598918b55868af677154bec7e73d222ef95a8fdb9bbf7dae96a8421085cdad8cd190d86653b5b6dc55a4484f2e5b2e27d5e0c3fc15b3 + languageName: node + linkType: hard + +"camelcase@npm:^5.0.0, camelcase@npm:^5.3.1": + version: 5.3.1 + resolution: "camelcase@npm:5.3.1" + checksum: e6effce26b9404e3c0f301498184f243811c30dfe6d0b9051863bd8e4034d09c8c2923794f280d6827e5aa055f6c434115ff97864a16a963366fb35fd673024b + languageName: node + linkType: hard + +"camelcase@npm:^6.2.0": + version: 6.3.0 + resolution: "camelcase@npm:6.3.0" + checksum: 8c96818a9076434998511251dcb2761a94817ea17dbdc37f47ac080bd088fc62c7369429a19e2178b993497132c8cbcf5cc1f44ba963e76782ba469c0474938d + languageName: node + linkType: hard + +"caniuse-lite@npm:^1.0.30001565": + version: 1.0.30001576 + resolution: "caniuse-lite@npm:1.0.30001576" + checksum: b8b332675fe703d5e57b02df5f100345f2a3796c537a42422f5bfc82d3256b8bad3f4e2788553656d2650006d13a4b5db99725e2a9462cc0c8035ba494ba1857 + languageName: node + linkType: hard + +"chalk@npm:^2.4.2": + version: 2.4.2 + resolution: "chalk@npm:2.4.2" + dependencies: + ansi-styles: ^3.2.1 + escape-string-regexp: ^1.0.5 + supports-color: ^5.3.0 + checksum: ec3661d38fe77f681200f878edbd9448821924e0f93a9cefc0e26a33b145f1027a2084bf19967160d11e1f03bfe4eaffcabf5493b89098b2782c3fe0b03d80c2 + languageName: node + linkType: hard + +"chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.2": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: ^4.1.0 + supports-color: ^7.1.0 + checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc + languageName: node + linkType: hard + +"char-regex@npm:^1.0.2": + version: 1.0.2 + resolution: "char-regex@npm:1.0.2" + checksum: b563e4b6039b15213114626621e7a3d12f31008bdce20f9c741d69987f62aeaace7ec30f6018890ad77b2e9b4d95324c9f5acfca58a9441e3b1dcdd1e2525d17 + languageName: node + linkType: hard + +"chownr@npm:^2.0.0": + version: 2.0.0 + resolution: "chownr@npm:2.0.0" + checksum: c57cf9dd0791e2f18a5ee9c1a299ae6e801ff58fee96dc8bfd0dcb4738a6ce58dd252a3605b1c93c6418fe4f9d5093b28ffbf4d66648cb2a9c67eaef9679be2f + languageName: node + linkType: hard + +"chrome-launcher@npm:^0.15.2": + version: 0.15.2 + resolution: "chrome-launcher@npm:0.15.2" + dependencies: + "@types/node": "*" + escape-string-regexp: ^4.0.0 + is-wsl: ^2.2.0 + lighthouse-logger: ^1.0.0 + bin: + print-chrome-path: bin/print-chrome-path.js + checksum: e1f8131b9f7bd931248ea85f413c6cdb93a0d41440ff5bf0987f36afb081d2b2c7b60ba6062ee7ae2dd9b052143f6b275b38c9eb115d11b49c3ea8829bad7db0 + languageName: node + linkType: hard + +"chromium-edge-launcher@npm:^1.0.0": + version: 1.0.0 + resolution: "chromium-edge-launcher@npm:1.0.0" + dependencies: + "@types/node": "*" + escape-string-regexp: ^4.0.0 + is-wsl: ^2.2.0 + lighthouse-logger: ^1.0.0 + mkdirp: ^1.0.4 + rimraf: ^3.0.2 + checksum: 77ce4fc03e7ee6f72383cc23c9b34a18ff368fcce8d23bcdc777c603c6d48ae25d3b79be5a1256e7edeec65f6e2250245a5372175454a329bcc99df672160ee4 + languageName: node + linkType: hard + +"ci-info@npm:^2.0.0": + version: 2.0.0 + resolution: "ci-info@npm:2.0.0" + checksum: 3b374666a85ea3ca43fa49aa3a048d21c9b475c96eb13c133505d2324e7ae5efd6a454f41efe46a152269e9b6a00c9edbe63ec7fa1921957165aae16625acd67 + languageName: node + linkType: hard + +"ci-info@npm:^3.2.0": + version: 3.9.0 + resolution: "ci-info@npm:3.9.0" + checksum: 6b19dc9b2966d1f8c2041a838217299718f15d6c4b63ae36e4674edd2bee48f780e94761286a56aa59eb305a85fbea4ddffb7630ec063e7ec7e7e5ad42549a87 + languageName: node + linkType: hard + +"cjs-module-lexer@npm:^1.0.0": + version: 1.2.3 + resolution: "cjs-module-lexer@npm:1.2.3" + checksum: 5ea3cb867a9bb609b6d476cd86590d105f3cfd6514db38ff71f63992ab40939c2feb68967faa15a6d2b1f90daa6416b79ea2de486e9e2485a6f8b66a21b4fb0a + languageName: node + linkType: hard + +"clean-stack@npm:^2.0.0": + version: 2.2.0 + resolution: "clean-stack@npm:2.2.0" + checksum: 2ac8cd2b2f5ec986a3c743935ec85b07bc174d5421a5efc8017e1f146a1cf5f781ae962618f416352103b32c9cd7e203276e8c28241bbe946160cab16149fb68 + languageName: node + linkType: hard + +"cli-cursor@npm:^3.1.0": + version: 3.1.0 + resolution: "cli-cursor@npm:3.1.0" + dependencies: + restore-cursor: ^3.1.0 + checksum: 2692784c6cd2fd85cfdbd11f53aea73a463a6d64a77c3e098b2b4697a20443f430c220629e1ca3b195ea5ac4a97a74c2ee411f3807abf6df2b66211fec0c0a29 + languageName: node + linkType: hard + +"cli-spinners@npm:^2.5.0": + version: 2.9.2 + resolution: "cli-spinners@npm:2.9.2" + checksum: 1bd588289b28432e4676cb5d40505cfe3e53f2e4e10fbe05c8a710a154d6fe0ce7836844b00d6858f740f2ffe67cdc36e0fce9c7b6a8430e80e6388d5aa4956c + languageName: node + linkType: hard + +"cliui@npm:^6.0.0": + version: 6.0.0 + resolution: "cliui@npm:6.0.0" + dependencies: + string-width: ^4.2.0 + strip-ansi: ^6.0.0 + wrap-ansi: ^6.2.0 + checksum: 4fcfd26d292c9f00238117f39fc797608292ae36bac2168cfee4c85923817d0607fe21b3329a8621e01aedf512c99b7eaa60e363a671ffd378df6649fb48ae42 + languageName: node + linkType: hard + +"cliui@npm:^8.0.1": + version: 8.0.1 + resolution: "cliui@npm:8.0.1" + dependencies: + string-width: ^4.2.0 + strip-ansi: ^6.0.1 + wrap-ansi: ^7.0.0 + checksum: 79648b3b0045f2e285b76fb2e24e207c6db44323581e421c3acbd0e86454cba1b37aea976ab50195a49e7384b871e6dfb2247ad7dec53c02454ac6497394cb56 + languageName: node + linkType: hard + +"clone-deep@npm:^4.0.1": + version: 4.0.1 + resolution: "clone-deep@npm:4.0.1" + dependencies: + is-plain-object: ^2.0.4 + kind-of: ^6.0.2 + shallow-clone: ^3.0.0 + checksum: 770f912fe4e6f21873c8e8fbb1e99134db3b93da32df271d00589ea4a29dbe83a9808a322c93f3bcaf8584b8b4fa6fc269fc8032efbaa6728e0c9886c74467d2 + languageName: node + linkType: hard + +"clone@npm:^1.0.2": + version: 1.0.4 + resolution: "clone@npm:1.0.4" + checksum: d06418b7335897209e77bdd430d04f882189582e67bd1f75a04565f3f07f5b3f119a9d670c943b6697d0afb100f03b866b3b8a1f91d4d02d72c4ecf2bb64b5dd + languageName: node + linkType: hard + +"co@npm:^4.6.0": + version: 4.6.0 + resolution: "co@npm:4.6.0" + checksum: 5210d9223010eb95b29df06a91116f2cf7c8e0748a9013ed853b53f362ea0e822f1e5bb054fb3cefc645239a4cf966af1f6133a3b43f40d591f3b68ed6cf0510 + languageName: node + linkType: hard + +"collect-v8-coverage@npm:^1.0.0": + version: 1.0.2 + resolution: "collect-v8-coverage@npm:1.0.2" + checksum: c10f41c39ab84629d16f9f6137bc8a63d332244383fc368caf2d2052b5e04c20cd1fd70f66fcf4e2422b84c8226598b776d39d5f2d2a51867cc1ed5d1982b4da + languageName: node + linkType: hard + +"color-convert@npm:^1.9.0": + version: 1.9.3 + resolution: "color-convert@npm:1.9.3" + dependencies: + color-name: 1.1.3 + checksum: fd7a64a17cde98fb923b1dd05c5f2e6f7aefda1b60d67e8d449f9328b4e53b228a428fd38bfeaeb2db2ff6b6503a776a996150b80cdf224062af08a5c8a3a203 + languageName: node + linkType: hard + +"color-convert@npm:^2.0.1": + version: 2.0.1 + resolution: "color-convert@npm:2.0.1" + dependencies: + color-name: ~1.1.4 + checksum: 79e6bdb9fd479a205c71d89574fccfb22bd9053bd98c6c4d870d65c132e5e904e6034978e55b43d69fcaa7433af2016ee203ce76eeba9cfa554b373e7f7db336 + languageName: node + linkType: hard + +"color-name@npm:1.1.3": + version: 1.1.3 + resolution: "color-name@npm:1.1.3" + checksum: 09c5d3e33d2105850153b14466501f2bfb30324a2f76568a408763a3b7433b0e50e5b4ab1947868e65cb101bb7cb75029553f2c333b6d4b8138a73fcc133d69d + languageName: node + linkType: hard + +"color-name@npm:~1.1.4": + version: 1.1.4 + resolution: "color-name@npm:1.1.4" + checksum: b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 + languageName: node + linkType: hard + +"colorette@npm:^1.0.7": + version: 1.4.0 + resolution: "colorette@npm:1.4.0" + checksum: 01c3c16058b182a4ab4c126a65a75faa4d38a20fa7c845090b25453acec6c371bb2c5dceb0a2338511f17902b9d1a9af0cadd8509c9403894b79311032c256c3 + languageName: node + linkType: hard + +"command-exists@npm:^1.2.8": + version: 1.2.9 + resolution: "command-exists@npm:1.2.9" + checksum: 729ae3d88a2058c93c58840f30341b7f82688a573019535d198b57a4d8cb0135ced0ad7f52b591e5b28a90feb2c675080ce916e56254a0f7c15cb2395277cac3 + languageName: node + linkType: hard + +"commander@npm:^2.20.0": + version: 2.20.3 + resolution: "commander@npm:2.20.3" + checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e + languageName: node + linkType: hard + +"commander@npm:^9.4.1": + version: 9.5.0 + resolution: "commander@npm:9.5.0" + checksum: c7a3e27aa59e913b54a1bafd366b88650bc41d6651f0cbe258d4ff09d43d6a7394232a4dadd0bf518b3e696fdf595db1028a0d82c785b88bd61f8a440cecfade + languageName: node + linkType: hard + +"commondir@npm:^1.0.1": + version: 1.0.1 + resolution: "commondir@npm:1.0.1" + checksum: 59715f2fc456a73f68826285718503340b9f0dd89bfffc42749906c5cf3d4277ef11ef1cca0350d0e79204f00f1f6d83851ececc9095dc88512a697ac0b9bdcb + languageName: node + linkType: hard + +"compressible@npm:~2.0.16": + version: 2.0.18 + resolution: "compressible@npm:2.0.18" + dependencies: + mime-db: ">= 1.43.0 < 2" + checksum: 58321a85b375d39230405654721353f709d0c1442129e9a17081771b816302a012471a9b8f4864c7dbe02eef7f2aaac3c614795197092262e94b409c9be108f0 + languageName: node + linkType: hard + +"compression@npm:^1.7.1": + version: 1.7.4 + resolution: "compression@npm:1.7.4" + dependencies: + accepts: ~1.3.5 + bytes: 3.0.0 + compressible: ~2.0.16 + debug: 2.6.9 + on-headers: ~1.0.2 + safe-buffer: 5.1.2 + vary: ~1.1.2 + checksum: 35c0f2eb1f28418978615dc1bc02075b34b1568f7f56c62d60f4214d4b7cc00d0f6d282b5f8a954f59872396bd770b6b15ffd8aa94c67d4bce9b8887b906999b + languageName: node + linkType: hard + +"concat-map@npm:0.0.1": + version: 0.0.1 + resolution: "concat-map@npm:0.0.1" + checksum: 902a9f5d8967a3e2faf138d5cb784b9979bad2e6db5357c5b21c568df4ebe62bcb15108af1b2253744844eb964fc023fbd9afbbbb6ddd0bcc204c6fb5b7bf3af + languageName: node + linkType: hard + +"connect@npm:^3.6.5": + version: 3.7.0 + resolution: "connect@npm:3.7.0" + dependencies: + debug: 2.6.9 + finalhandler: 1.1.2 + parseurl: ~1.3.3 + utils-merge: 1.0.1 + checksum: 96e1c4effcf219b065c7823e57351c94366d2e2a6952fa95e8212bffb35c86f1d5a3f9f6c5796d4cd3a5fdda628368b1c3cc44bf19c66cfd68fe9f9cab9177e2 + languageName: node + linkType: hard + +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 63ae9933be5a2b8d4509daca5124e20c14d023c820258e484e32dc324d34c2754e71297c94a05784064ad27615037ef677e3f0c00469fb55f409d2bb21261035 + languageName: node + linkType: hard + +"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1": + version: 3.35.0 + resolution: "core-js-compat@npm:3.35.0" + dependencies: + browserslist: ^4.22.2 + checksum: 64c41ce6870aa9130b9d0cb8f00c05204094f46db7e345d520ec2e38f8b6e1d51e921d4974ceb880948f19c0a79e5639e55be0e56f88ea20e32e9a6274da7f82 + languageName: node + linkType: hard + +"core-util-is@npm:~1.0.0": + version: 1.0.3 + resolution: "core-util-is@npm:1.0.3" + checksum: 9de8597363a8e9b9952491ebe18167e3b36e7707569eed0ebf14f8bba773611376466ae34575bca8cfe3c767890c859c74056084738f09d4e4a6f902b2ad7d99 + languageName: node + linkType: hard + +"cosmiconfig@npm:^5.0.5, cosmiconfig@npm:^5.1.0": + version: 5.2.1 + resolution: "cosmiconfig@npm:5.2.1" + dependencies: + import-fresh: ^2.0.0 + is-directory: ^0.3.1 + js-yaml: ^3.13.1 + parse-json: ^4.0.0 + checksum: 8b6f1d3c8a5ffdf663a952f17af0761adf210b7a5933d0fe8988f3ca3a1f0e1e5cbbb74d5b419c15933dd2fdcaec31dbc5cc85cb8259a822342b93b529eff89c + languageName: node + linkType: hard + +"create-jest@npm:^29.7.0": + version: 29.7.0 + resolution: "create-jest@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + chalk: ^4.0.0 + exit: ^0.1.2 + graceful-fs: ^4.2.9 + jest-config: ^29.7.0 + jest-util: ^29.7.0 + prompts: ^2.0.1 + bin: + create-jest: bin/create-jest.js + checksum: 1427d49458adcd88547ef6fa39041e1fe9033a661293aa8d2c3aa1b4967cb5bf4f0c00436c7a61816558f28ba2ba81a94d5c962e8022ea9a883978fc8e1f2945 + languageName: node + linkType: hard + +"create-require@npm:^1.1.0": + version: 1.1.1 + resolution: "create-require@npm:1.1.1" + checksum: a9a1503d4390d8b59ad86f4607de7870b39cad43d929813599a23714831e81c520bddf61bcdd1f8e30f05fd3a2b71ae8538e946eb2786dc65c2bbc520f692eff + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: ^3.1.0 + shebang-command: ^2.0.0 + which: ^2.0.1 + checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 + languageName: node + linkType: hard + +"csstype@npm:^3.0.2": + version: 3.1.3 + resolution: "csstype@npm:3.1.3" + checksum: 8db785cc92d259102725b3c694ec0c823f5619a84741b5c7991b8ad135dfaa66093038a1cc63e03361a6cd28d122be48f2106ae72334e067dd619a51f49eddf7 + languageName: node + linkType: hard + +"dayjs@npm:^1.8.15": + version: 1.11.10 + resolution: "dayjs@npm:1.11.10" + checksum: a6b5a3813b8884f5cd557e2e6b7fa569f4c5d0c97aca9558e38534af4f2d60daafd3ff8c2000fed3435cfcec9e805bcebd99f90130c6d1c5ef524084ced588c4 + languageName: node + linkType: hard + +"debug@npm:2.6.9, debug@npm:^2.2.0, debug@npm:^2.6.9": + version: 2.6.9 + resolution: "debug@npm:2.6.9" + dependencies: + ms: 2.0.0 + checksum: d2f51589ca66df60bf36e1fa6e4386b318c3f1e06772280eea5b1ae9fd3d05e9c2b7fd8a7d862457d00853c75b00451aa2d7459b924629ee385287a650f58fe6 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": + version: 4.3.4 + resolution: "debug@npm:4.3.4" + dependencies: + ms: 2.1.2 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 3dbad3f94ea64f34431a9cbf0bafb61853eda57bff2880036153438f50fb5a84f27683ba0d8e5426bf41a8c6ff03879488120cf5b3a761e77953169c0600a708 + languageName: node + linkType: hard + +"decamelize@npm:^1.2.0": + version: 1.2.0 + resolution: "decamelize@npm:1.2.0" + checksum: ad8c51a7e7e0720c70ec2eeb1163b66da03e7616d7b98c9ef43cce2416395e84c1e9548dd94f5f6ffecfee9f8b94251fc57121a8b021f2ff2469b2bae247b8aa + languageName: node + linkType: hard + +"dedent@npm:^1.0.0": + version: 1.5.1 + resolution: "dedent@npm:1.5.1" + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + checksum: c3c300a14edf1bdf5a873f9e4b22e839d62490bc5c8d6169c1f15858a1a76733d06a9a56930e963d677a2ceeca4b6b0894cc5ea2f501aa382ca5b92af3413c2a + languageName: node + linkType: hard + +"deep-is@npm:^0.1.3": + version: 0.1.4 + resolution: "deep-is@npm:0.1.4" + checksum: edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 + languageName: node + linkType: hard + +"deepmerge@npm:^4.2.2, deepmerge@npm:^4.3.0": + version: 4.3.1 + resolution: "deepmerge@npm:4.3.1" + checksum: 2024c6a980a1b7128084170c4cf56b0fd58a63f2da1660dcfe977415f27b17dbe5888668b59d0b063753f3220719d5e400b7f113609489c90160bb9a5518d052 + languageName: node + linkType: hard + +"defaults@npm:^1.0.3": + version: 1.0.4 + resolution: "defaults@npm:1.0.4" + dependencies: + clone: ^1.0.2 + checksum: 3a88b7a587fc076b84e60affad8b85245c01f60f38fc1d259e7ac1d89eb9ce6abb19e27215de46b98568dd5bc48471730b327637e6f20b0f1bc85cf00440c80a + languageName: node + linkType: hard + +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": + version: 1.1.1 + resolution: "define-data-property@npm:1.1.1" + dependencies: + get-intrinsic: ^1.2.1 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.0 + checksum: a29855ad3f0630ea82e3c5012c812efa6ca3078d5c2aa8df06b5f597c1cde6f7254692df41945851d903e05a1668607b6d34e778f402b9ff9ffb38111f1a3f0d + languageName: node + linkType: hard + +"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": + version: 1.2.1 + resolution: "define-properties@npm:1.2.1" + dependencies: + define-data-property: ^1.0.1 + has-property-descriptors: ^1.0.0 + object-keys: ^1.1.1 + checksum: b4ccd00597dd46cb2d4a379398f5b19fca84a16f3374e2249201992f36b30f6835949a9429669ee6b41b6e837205a163eadd745e472069e70dfc10f03e5fcc12 + languageName: node + linkType: hard + +"denodeify@npm:^1.2.1": + version: 1.2.1 + resolution: "denodeify@npm:1.2.1" + checksum: a85c8f7fce5626e311edd897c27ad571b29393c4a739dc29baee48328e09edd82364ff697272dd612462c67e48b4766389642b5bdfaea0dc114b7c6a276c0eae + languageName: node + linkType: hard + +"depd@npm:2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: abbe19c768c97ee2eed6282d8ce3031126662252c58d711f646921c9623f9052e3e1906443066beec1095832f534e57c523b7333f8e7e0d93051ab6baef5ab3a + languageName: node + linkType: hard + +"deprecated-react-native-prop-types@npm:^5.0.0": + version: 5.0.0 + resolution: "deprecated-react-native-prop-types@npm:5.0.0" + dependencies: + "@react-native/normalize-colors": ^0.73.0 + invariant: ^2.2.4 + prop-types: ^15.8.1 + checksum: ccbd4214733a178ef51934c4e0149f5c3ab60aa318d68500b6d6b4b59be9d6c25b844f808ed7095d82e1bbef6fc4bc49e0dea14d55d3ebd1ff383011ac2a1576 + languageName: node + linkType: hard + +"destroy@npm:1.2.0": + version: 1.2.0 + resolution: "destroy@npm:1.2.0" + checksum: 0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 + languageName: node + linkType: hard + +"detect-newline@npm:^3.0.0": + version: 3.1.0 + resolution: "detect-newline@npm:3.1.0" + checksum: ae6cd429c41ad01b164c59ea36f264a2c479598e61cba7c99da24175a7ab80ddf066420f2bec9a1c57a6bead411b4655ff15ad7d281c000a89791f48cbe939e7 + languageName: node + linkType: hard + +"diff-sequences@npm:^29.6.3": + version: 29.6.3 + resolution: "diff-sequences@npm:29.6.3" + checksum: f4914158e1f2276343d98ff5b31fc004e7304f5470bf0f1adb2ac6955d85a531a6458d33e87667f98f6ae52ebd3891bb47d420bb48a5bd8b7a27ee25b20e33aa + languageName: node + linkType: hard + +"diff@npm:^4.0.1": + version: 4.0.2 + resolution: "diff@npm:4.0.2" + checksum: f2c09b0ce4e6b301c221addd83bf3f454c0bc00caa3dd837cf6c127d6edf7223aa2bbe3b688feea110b7f262adbfc845b757c44c8a9f8c0c5b15d8fa9ce9d20d + languageName: node + linkType: hard + +"dir-glob@npm:^3.0.1": + version: 3.0.1 + resolution: "dir-glob@npm:3.0.1" + dependencies: + path-type: ^4.0.0 + checksum: fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 + languageName: node + linkType: hard + +"doctrine@npm:^2.1.0": + version: 2.1.0 + resolution: "doctrine@npm:2.1.0" + dependencies: + esutils: ^2.0.2 + checksum: a45e277f7feaed309fe658ace1ff286c6e2002ac515af0aaf37145b8baa96e49899638c7cd47dccf84c3d32abfc113246625b3ac8f552d1046072adee13b0dc8 + languageName: node + linkType: hard + +"doctrine@npm:^3.0.0": + version: 3.0.0 + resolution: "doctrine@npm:3.0.0" + dependencies: + esutils: ^2.0.2 + checksum: fd7673ca77fe26cd5cba38d816bc72d641f500f1f9b25b83e8ce28827fe2da7ad583a8da26ab6af85f834138cf8dae9f69b0cd6ab925f52ddab1754db44d99ce + languageName: node + linkType: hard + +"eastasianwidth@npm:^0.2.0": + version: 0.2.0 + resolution: "eastasianwidth@npm:0.2.0" + checksum: 7d00d7cd8e49b9afa762a813faac332dee781932d6f2c848dc348939c4253f1d4564341b7af1d041853bc3f32c2ef141b58e0a4d9862c17a7f08f68df1e0f1ed + languageName: node + linkType: hard + +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 1b4cac778d64ce3b582a7e26b218afe07e207a0f9bfe13cc7395a6d307849cfe361e65033c3251e00c27dd060cab43014c2d6b2647676135e18b77d2d05b3f4f + languageName: node + linkType: hard + +"electron-to-chromium@npm:^1.4.601": + version: 1.4.630 + resolution: "electron-to-chromium@npm:1.4.630" + checksum: 9bf16b06b245d6937845bbef17c0babdf8e01845c8aa31eb2d7dc3a88cd34291d2dec0d8e329450a5b8dfcf5d3dc96c56aa1c8b224d942e3b1d508e9e3cb9788 + languageName: node + linkType: hard + +"emittery@npm:^0.13.1": + version: 0.13.1 + resolution: "emittery@npm:0.13.1" + checksum: 2b089ab6306f38feaabf4f6f02792f9ec85fc054fda79f44f6790e61bbf6bc4e1616afb9b232e0c5ec5289a8a452f79bfa6d905a6fd64e94b49981f0934001c6 + languageName: node + linkType: hard + +"emoji-regex@npm:^8.0.0": + version: 8.0.0 + resolution: "emoji-regex@npm:8.0.0" + checksum: d4c5c39d5a9868b5fa152f00cada8a936868fd3367f33f71be515ecee4c803132d11b31a6222b2571b1e5f7e13890156a94880345594d0ce7e3c9895f560f192 + languageName: node + linkType: hard + +"emoji-regex@npm:^9.2.2": + version: 9.2.2 + resolution: "emoji-regex@npm:9.2.2" + checksum: 8487182da74aabd810ac6d6f1994111dfc0e331b01271ae01ec1eb0ad7b5ecc2bbbbd2f053c05cb55a1ac30449527d819bbfbf0e3de1023db308cbcb47f86601 + languageName: node + linkType: hard + +"encodeurl@npm:~1.0.2": + version: 1.0.2 + resolution: "encodeurl@npm:1.0.2" + checksum: e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c + languageName: node + linkType: hard + +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" + dependencies: + iconv-lite: ^0.6.2 + checksum: bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 65b5df55a8bab92229ab2b40dad3b387fad24613263d103a97f91c9fe43ceb21965cd3392b1ccb5d77088021e525c4e0481adb309625d0cb94ade1d1fb8dc17e + languageName: node + linkType: hard + +"envinfo@npm:^7.10.0": + version: 7.11.0 + resolution: "envinfo@npm:7.11.0" + bin: + envinfo: dist/cli.js + checksum: c45a7d20409d5f4cda72483b150d3816b15b434f2944d72c1495d8838bd7c4e7b2f32c12128ffb9b92b5f66f436237b8a525eb3a9a5da2d20013bc4effa28aef + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 8b7b1be20d2de12d2255c0bc2ca638b7af5171142693299416e6a9339bd7d88fc8d7707d913d78e0993176005405a236b066b45666b27b797252c771156ace54 + languageName: node + linkType: hard + +"error-ex@npm:^1.3.1": + version: 1.3.2 + resolution: "error-ex@npm:1.3.2" + dependencies: + is-arrayish: ^0.2.1 + checksum: c1c2b8b65f9c91b0f9d75f0debaa7ec5b35c266c2cac5de412c1a6de86d4cbae04ae44e510378cb14d032d0645a36925d0186f8bb7367bcc629db256b743a001 + languageName: node + linkType: hard + +"error-stack-parser@npm:^2.0.6": + version: 2.1.4 + resolution: "error-stack-parser@npm:2.1.4" + dependencies: + stackframe: ^1.3.4 + checksum: 3b916d2d14c6682f287c8bfa28e14672f47eafe832701080e420e7cdbaebb2c50293868256a95706ac2330fe078cf5664713158b49bc30d7a5f2ac229ded0e18 + languageName: node + linkType: hard + +"errorhandler@npm:^1.5.1": + version: 1.5.1 + resolution: "errorhandler@npm:1.5.1" + dependencies: + accepts: ~1.3.7 + escape-html: ~1.0.3 + checksum: 73b7abb08fb751107e9bebecc33c40c0641a54be8bda8e4a045f3f5cb7b805041927fef5629ea39b1737799eb52fe2499ca531f11ac51b0294ccc4667d72cb91 + languageName: node + linkType: hard + +"es-abstract@npm:^1.22.1": + version: 1.22.3 + resolution: "es-abstract@npm:1.22.3" + dependencies: + array-buffer-byte-length: ^1.0.0 + arraybuffer.prototype.slice: ^1.0.2 + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.5 + es-set-tostringtag: ^2.0.1 + es-to-primitive: ^1.2.1 + function.prototype.name: ^1.1.6 + get-intrinsic: ^1.2.2 + get-symbol-description: ^1.0.0 + globalthis: ^1.0.3 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.0 + has-proto: ^1.0.1 + has-symbols: ^1.0.3 + hasown: ^2.0.0 + internal-slot: ^1.0.5 + is-array-buffer: ^3.0.2 + is-callable: ^1.2.7 + is-negative-zero: ^2.0.2 + is-regex: ^1.1.4 + is-shared-array-buffer: ^1.0.2 + is-string: ^1.0.7 + is-typed-array: ^1.1.12 + is-weakref: ^1.0.2 + object-inspect: ^1.13.1 + object-keys: ^1.1.1 + object.assign: ^4.1.4 + regexp.prototype.flags: ^1.5.1 + safe-array-concat: ^1.0.1 + safe-regex-test: ^1.0.0 + string.prototype.trim: ^1.2.8 + string.prototype.trimend: ^1.0.7 + string.prototype.trimstart: ^1.0.7 + typed-array-buffer: ^1.0.0 + typed-array-byte-length: ^1.0.0 + typed-array-byte-offset: ^1.0.0 + typed-array-length: ^1.0.4 + unbox-primitive: ^1.0.2 + which-typed-array: ^1.1.13 + checksum: b1bdc962856836f6e72be10b58dc128282bdf33771c7a38ae90419d920fc3b36cc5d2b70a222ad8016e3fc322c367bf4e9e89fc2bc79b7e933c05b218e83d79a + languageName: node + linkType: hard + +"es-iterator-helpers@npm:^1.0.12": + version: 1.0.15 + resolution: "es-iterator-helpers@npm:1.0.15" + dependencies: + asynciterator.prototype: ^1.0.0 + call-bind: ^1.0.2 + define-properties: ^1.2.1 + es-abstract: ^1.22.1 + es-set-tostringtag: ^2.0.1 + function-bind: ^1.1.1 + get-intrinsic: ^1.2.1 + globalthis: ^1.0.3 + has-property-descriptors: ^1.0.0 + has-proto: ^1.0.1 + has-symbols: ^1.0.3 + internal-slot: ^1.0.5 + iterator.prototype: ^1.1.2 + safe-array-concat: ^1.0.1 + checksum: 50081ae5c549efe62e5c1d244df0194b40b075f7897fc2116b7e1aa437eb3c41f946d2afda18c33f9b31266ec544765932542765af839f76fa6d7b7855d1e0e1 + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.0.1": + version: 2.0.2 + resolution: "es-set-tostringtag@npm:2.0.2" + dependencies: + get-intrinsic: ^1.2.2 + has-tostringtag: ^1.0.0 + hasown: ^2.0.0 + checksum: afcec3a4c9890ae14d7ec606204858441c801ff84f312538e1d1ccf1e5493c8b17bd672235df785f803756472cb4f2d49b87bde5237aef33411e74c22f194e07 + languageName: node + linkType: hard + +"es-shim-unscopables@npm:^1.0.0": + version: 1.0.2 + resolution: "es-shim-unscopables@npm:1.0.2" + dependencies: + hasown: ^2.0.0 + checksum: 432bd527c62065da09ed1d37a3f8e623c423683285e6188108286f4a1e8e164a5bcbfbc0051557c7d14633cd2a41ce24c7048e6bbb66a985413fd32f1be72626 + languageName: node + linkType: hard + +"es-to-primitive@npm:^1.2.1": + version: 1.2.1 + resolution: "es-to-primitive@npm:1.2.1" + dependencies: + is-callable: ^1.1.4 + is-date-object: ^1.0.1 + is-symbol: ^1.0.2 + checksum: 4ead6671a2c1402619bdd77f3503991232ca15e17e46222b0a41a5d81aebc8740a77822f5b3c965008e631153e9ef0580540007744521e72de8e33599fca2eed + languageName: node + linkType: hard + +"escalade@npm:^3.1.1": + version: 3.1.1 + resolution: "escalade@npm:3.1.1" + checksum: a3e2a99f07acb74b3ad4989c48ca0c3140f69f923e56d0cba0526240ee470b91010f9d39001f2a4a313841d237ede70a729e92125191ba5d21e74b106800b133 + languageName: node + linkType: hard + +"escape-html@npm:~1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 6213ca9ae00d0ab8bccb6d8d4e0a98e76237b2410302cf7df70aaa6591d509a2a37ce8998008cbecae8fc8ffaadf3fb0229535e6a145f3ce0b211d060decbb24 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^1.0.5": + version: 1.0.5 + resolution: "escape-string-regexp@npm:1.0.5" + checksum: 6092fda75c63b110c706b6a9bfde8a612ad595b628f0bd2147eea1d3406723020810e591effc7db1da91d80a71a737a313567c5abb3813e8d9c71f4aa595b410 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^2.0.0": + version: 2.0.0 + resolution: "escape-string-regexp@npm:2.0.0" + checksum: 9f8a2d5743677c16e85c810e3024d54f0c8dea6424fad3c79ef6666e81dd0846f7437f5e729dfcdac8981bc9e5294c39b4580814d114076b8d36318f46ae4395 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-string-regexp@npm:4.0.0" + checksum: 98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 + languageName: node + linkType: hard + +"eslint-config-prettier@npm:^8.5.0": + version: 8.10.0 + resolution: "eslint-config-prettier@npm:8.10.0" + peerDependencies: + eslint: ">=7.0.0" + bin: + eslint-config-prettier: bin/cli.js + checksum: 153266badd477e49b0759816246b2132f1dbdb6c7f313ca60a9af5822fd1071c2bc5684a3720d78b725452bbac04bb130878b2513aea5e72b1b792de5a69fec8 + languageName: node + linkType: hard + +"eslint-config-prettier@npm:^9.1.0": + version: 9.1.0 + resolution: "eslint-config-prettier@npm:9.1.0" + peerDependencies: + eslint: ">=7.0.0" + bin: + eslint-config-prettier: bin/cli.js + checksum: 9229b768c879f500ee54ca05925f31b0c0bafff3d9f5521f98ff05127356de78c81deb9365c86a5ec4efa990cb72b74df8612ae15965b14136044c73e1f6a907 + languageName: node + linkType: hard + +"eslint-plugin-eslint-comments@npm:^3.2.0": + version: 3.2.0 + resolution: "eslint-plugin-eslint-comments@npm:3.2.0" + dependencies: + escape-string-regexp: ^1.0.5 + ignore: ^5.0.5 + peerDependencies: + eslint: ">=4.19.1" + checksum: c9fe273dd56699abdf7e416cfad0344eb50aa01564a5a9133e72d982defb89310bc2e9b0b148ce19c5190d7ff641223b0ba9e667a194bc48467c3dd0d471e657 + languageName: node + linkType: hard + +"eslint-plugin-ft-flow@npm:^2.0.1": + version: 2.0.3 + resolution: "eslint-plugin-ft-flow@npm:2.0.3" + dependencies: + lodash: ^4.17.21 + string-natural-compare: ^3.0.1 + peerDependencies: + "@babel/eslint-parser": ^7.12.0 + eslint: ^8.1.0 + checksum: 6272f7c352154875dc85c7dcd7cf66f6ed926a9a6aba81c675583bcc6695147597d6b9a6db0f643a387d14eccd61dc36daf20eec1c49e91ce1c63c01ffe295f7 + languageName: node + linkType: hard + +"eslint-plugin-jest@npm:^26.5.3": + version: 26.9.0 + resolution: "eslint-plugin-jest@npm:26.9.0" + dependencies: + "@typescript-eslint/utils": ^5.10.0 + peerDependencies: + "@typescript-eslint/eslint-plugin": ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + "@typescript-eslint/eslint-plugin": + optional: true + jest: + optional: true + checksum: 6d5fd5c95368f1ca2640389aeb7ce703d6202493c3ec6bdedb4eaca37233710508b0c75829e727765a16fd27029a466d34202bc7f2811c752038ccbbce224400 + languageName: node + linkType: hard + +"eslint-plugin-prettier@npm:^4.2.1": + version: 4.2.1 + resolution: "eslint-plugin-prettier@npm:4.2.1" + dependencies: + prettier-linter-helpers: ^1.0.0 + peerDependencies: + eslint: ">=7.28.0" + prettier: ">=2.0.0" + peerDependenciesMeta: + eslint-config-prettier: + optional: true + checksum: b9e839d2334ad8ec7a5589c5cb0f219bded260839a857d7a486997f9870e95106aa59b8756ff3f37202085ebab658de382b0267cae44c3a7f0eb0bcc03a4f6d6 + languageName: node + linkType: hard + +"eslint-plugin-prettier@npm:^5.1.3": + version: 5.1.3 + resolution: "eslint-plugin-prettier@npm:5.1.3" + dependencies: + prettier-linter-helpers: ^1.0.0 + synckit: ^0.8.6 + peerDependencies: + "@types/eslint": ">=8.0.0" + eslint: ">=8.0.0" + eslint-config-prettier: "*" + prettier: ">=3.0.0" + peerDependenciesMeta: + "@types/eslint": + optional: true + eslint-config-prettier: + optional: true + checksum: eb2a7d46a1887e1b93788ee8f8eb81e0b6b2a6f5a66a62bc6f375b033fc4e7ca16448da99380be800042786e76cf5c0df9c87a51a2c9b960ed47acbd7c0b9381 + languageName: node + linkType: hard + +"eslint-plugin-react-hooks@npm:^4.6.0": + version: 4.6.0 + resolution: "eslint-plugin-react-hooks@npm:4.6.0" + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + checksum: 23001801f14c1d16bf0a837ca7970d9dd94e7b560384b41db378b49b6e32dc43d6e2790de1bd737a652a86f81a08d6a91f402525061b47719328f586a57e86c3 + languageName: node + linkType: hard + +"eslint-plugin-react-native-globals@npm:^0.1.1": + version: 0.1.2 + resolution: "eslint-plugin-react-native-globals@npm:0.1.2" + checksum: ab91e8ecbb51718fb0763f29226b1c2d402251ab2c4730a8bf85f38b805e32d4243da46d07ccdb12cb9dcce9e7514364a1706142cf970f58dcc9a820bcf4b732 + languageName: node + linkType: hard + +"eslint-plugin-react-native@npm:^4.0.0": + version: 4.1.0 + resolution: "eslint-plugin-react-native@npm:4.1.0" + dependencies: + eslint-plugin-react-native-globals: ^0.1.1 + peerDependencies: + eslint: ^3.17.0 || ^4 || ^5 || ^6 || ^7 || ^8 + checksum: b6acc5aa91f95cb4600d6ab4c00cf22577083e72c61aabcf010f4388d97e4fc53ba075db54eeee53cba25b297e1a6ec611434f2c2d0bfb3e8dc6419400663fe9 + languageName: node + linkType: hard + +"eslint-plugin-react@npm:^7.30.1": + version: 7.33.2 + resolution: "eslint-plugin-react@npm:7.33.2" + dependencies: + array-includes: ^3.1.6 + array.prototype.flatmap: ^1.3.1 + array.prototype.tosorted: ^1.1.1 + doctrine: ^2.1.0 + es-iterator-helpers: ^1.0.12 + estraverse: ^5.3.0 + jsx-ast-utils: ^2.4.1 || ^3.0.0 + minimatch: ^3.1.2 + object.entries: ^1.1.6 + object.fromentries: ^2.0.6 + object.hasown: ^1.1.2 + object.values: ^1.1.6 + prop-types: ^15.8.1 + resolve: ^2.0.0-next.4 + semver: ^6.3.1 + string.prototype.matchall: ^4.0.8 + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + checksum: b4c3d76390b0ae6b6f9fed78170604cc2c04b48e6778a637db339e8e3911ec9ef22510b0ae77c429698151d0f1b245f282177f384105b6830e7b29b9c9b26610 + languageName: node + linkType: hard + +"eslint-scope@npm:5.1.1, eslint-scope@npm:^5.1.1": + version: 5.1.1 + resolution: "eslint-scope@npm:5.1.1" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^4.1.1 + checksum: 47e4b6a3f0cc29c7feedee6c67b225a2da7e155802c6ea13bbef4ac6b9e10c66cd2dcb987867ef176292bf4e64eccc680a49e35e9e9c669f4a02bac17e86abdb + languageName: node + linkType: hard + +"eslint-scope@npm:^7.2.2": + version: 7.2.2 + resolution: "eslint-scope@npm:7.2.2" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^5.2.0 + checksum: ec97dbf5fb04b94e8f4c5a91a7f0a6dd3c55e46bfc7bbcd0e3138c3a76977570e02ed89a1810c778dcd72072ff0e9621ba1379b4babe53921d71e2e4486fda3e + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^2.1.0": + version: 2.1.0 + resolution: "eslint-visitor-keys@npm:2.1.0" + checksum: e3081d7dd2611a35f0388bbdc2f5da60b3a3c5b8b6e928daffff7391146b434d691577aa95064c8b7faad0b8a680266bcda0a42439c18c717b80e6718d7e267d + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": + version: 3.4.3 + resolution: "eslint-visitor-keys@npm:3.4.3" + checksum: 36e9ef87fca698b6fd7ca5ca35d7b2b6eeaaf106572e2f7fd31c12d3bfdaccdb587bba6d3621067e5aece31c8c3a348b93922ab8f7b2cbc6aaab5e1d89040c60 + languageName: node + linkType: hard + +"eslint@npm:^8.56.0": + version: 8.56.0 + resolution: "eslint@npm:8.56.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@eslint-community/regexpp": ^4.6.1 + "@eslint/eslintrc": ^2.1.4 + "@eslint/js": 8.56.0 + "@humanwhocodes/config-array": ^0.11.13 + "@humanwhocodes/module-importer": ^1.0.1 + "@nodelib/fs.walk": ^1.2.8 + "@ungap/structured-clone": ^1.2.0 + ajv: ^6.12.4 + chalk: ^4.0.0 + cross-spawn: ^7.0.2 + debug: ^4.3.2 + doctrine: ^3.0.0 + escape-string-regexp: ^4.0.0 + eslint-scope: ^7.2.2 + eslint-visitor-keys: ^3.4.3 + espree: ^9.6.1 + esquery: ^1.4.2 + esutils: ^2.0.2 + fast-deep-equal: ^3.1.3 + file-entry-cache: ^6.0.1 + find-up: ^5.0.0 + glob-parent: ^6.0.2 + globals: ^13.19.0 + graphemer: ^1.4.0 + ignore: ^5.2.0 + imurmurhash: ^0.1.4 + is-glob: ^4.0.0 + is-path-inside: ^3.0.3 + js-yaml: ^4.1.0 + json-stable-stringify-without-jsonify: ^1.0.1 + levn: ^0.4.1 + lodash.merge: ^4.6.2 + minimatch: ^3.1.2 + natural-compare: ^1.4.0 + optionator: ^0.9.3 + strip-ansi: ^6.0.1 + text-table: ^0.2.0 + bin: + eslint: bin/eslint.js + checksum: 883436d1e809b4a25d9eb03d42f584b84c408dbac28b0019f6ea07b5177940bf3cca86208f749a6a1e0039b63e085ee47aca1236c30721e91f0deef5cc5a5136 + languageName: node + linkType: hard + +"espree@npm:^9.6.0, espree@npm:^9.6.1": + version: 9.6.1 + resolution: "espree@npm:9.6.1" + dependencies: + acorn: ^8.9.0 + acorn-jsx: ^5.3.2 + eslint-visitor-keys: ^3.4.1 + checksum: eb8c149c7a2a77b3f33a5af80c10875c3abd65450f60b8af6db1bfcfa8f101e21c1e56a561c6dc13b848e18148d43469e7cd208506238554fb5395a9ea5a1ab9 + languageName: node + linkType: hard + +"esprima@npm:^4.0.0, esprima@npm:~4.0.0": + version: 4.0.1 + resolution: "esprima@npm:4.0.1" + bin: + esparse: ./bin/esparse.js + esvalidate: ./bin/esvalidate.js + checksum: b45bc805a613dbea2835278c306b91aff6173c8d034223fa81498c77dcbce3b2931bf6006db816f62eacd9fd4ea975dfd85a5b7f3c6402cfd050d4ca3c13a628 + languageName: node + linkType: hard + +"esquery@npm:^1.4.2": + version: 1.5.0 + resolution: "esquery@npm:1.5.0" + dependencies: + estraverse: ^5.1.0 + checksum: aefb0d2596c230118656cd4ec7532d447333a410a48834d80ea648b1e7b5c9bc9ed8b5e33a89cb04e487b60d622f44cf5713bf4abed7c97343edefdc84a35900 + languageName: node + linkType: hard + +"esrecurse@npm:^4.3.0": + version: 4.3.0 + resolution: "esrecurse@npm:4.3.0" + dependencies: + estraverse: ^5.2.0 + checksum: ebc17b1a33c51cef46fdc28b958994b1dc43cd2e86237515cbc3b4e5d2be6a811b2315d0a1a4d9d340b6d2308b15322f5c8291059521cc5f4802f65e7ec32837 + languageName: node + linkType: hard + +"estraverse@npm:^4.1.1": + version: 4.3.0 + resolution: "estraverse@npm:4.3.0" + checksum: a6299491f9940bb246124a8d44b7b7a413a8336f5436f9837aaa9330209bd9ee8af7e91a654a3545aee9c54b3308e78ee360cef1d777d37cfef77d2fa33b5827 + languageName: node + linkType: hard + +"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0, estraverse@npm:^5.3.0": + version: 5.3.0 + resolution: "estraverse@npm:5.3.0" + checksum: 072780882dc8416ad144f8fe199628d2b3e7bbc9989d9ed43795d2c90309a2047e6bc5979d7e2322a341163d22cfad9e21f4110597fe487519697389497e4e2b + languageName: node + linkType: hard + +"esutils@npm:^2.0.2": + version: 2.0.3 + resolution: "esutils@npm:2.0.3" + checksum: 22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 + languageName: node + linkType: hard + +"etag@npm:~1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 571aeb3dbe0f2bbd4e4fadbdb44f325fc75335cd5f6f6b6a091e6a06a9f25ed5392f0863c5442acb0646787446e816f13cbfc6edce5b07658541dff573cab1ff + languageName: node + linkType: hard + +"event-target-shim@npm:^5.0.0, event-target-shim@npm:^5.0.1": + version: 5.0.1 + resolution: "event-target-shim@npm:5.0.1" + checksum: 1ffe3bb22a6d51bdeb6bf6f7cf97d2ff4a74b017ad12284cc9e6a279e727dc30a5de6bb613e5596ff4dc3e517841339ad09a7eec44266eccb1aa201a30448166 + languageName: node + linkType: hard + +"execa@npm:^5.0.0, execa@npm:^5.1.1": + version: 5.1.1 + resolution: "execa@npm:5.1.1" + dependencies: + cross-spawn: ^7.0.3 + get-stream: ^6.0.0 + human-signals: ^2.1.0 + is-stream: ^2.0.0 + merge-stream: ^2.0.0 + npm-run-path: ^4.0.1 + onetime: ^5.1.2 + signal-exit: ^3.0.3 + strip-final-newline: ^2.0.0 + checksum: fba9022c8c8c15ed862847e94c252b3d946036d7547af310e344a527e59021fd8b6bb0723883ea87044dc4f0201f949046993124a42ccb0855cae5bf8c786343 + languageName: node + linkType: hard + +"exit@npm:^0.1.2": + version: 0.1.2 + resolution: "exit@npm:0.1.2" + checksum: abc407f07a875c3961e4781dfcb743b58d6c93de9ab263f4f8c9d23bb6da5f9b7764fc773f86b43dd88030444d5ab8abcb611cb680fba8ca075362b77114bba3 + languageName: node + linkType: hard + +"expect@npm:^29.0.0, expect@npm:^29.7.0": + version: 29.7.0 + resolution: "expect@npm:29.7.0" + dependencies: + "@jest/expect-utils": ^29.7.0 + jest-get-type: ^29.6.3 + jest-matcher-utils: ^29.7.0 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 + checksum: 9257f10288e149b81254a0fda8ffe8d54a7061cd61d7515779998b012579d2b8c22354b0eb901daf0145f347403da582f75f359f4810c007182ad3fb318b5c0c + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 3d21519a4f8207c99f7457287291316306255a328770d320b401114ec8481986e4e467e854cb9914dd965e0a1ca810a23ccb559c642c88f4c7f55c55778a9b48 + languageName: node + linkType: hard + +"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": + version: 3.1.3 + resolution: "fast-deep-equal@npm:3.1.3" + checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d + languageName: node + linkType: hard + +"fast-diff@npm:^1.1.2": + version: 1.3.0 + resolution: "fast-diff@npm:1.3.0" + checksum: d22d371b994fdc8cce9ff510d7b8dc4da70ac327bcba20df607dd5b9cae9f908f4d1028f5fe467650f058d1e7270235ae0b8230809a262b4df587a3b3aa216c3 + languageName: node + linkType: hard + +"fast-glob@npm:^3.2.9": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" + dependencies: + "@nodelib/fs.stat": ^2.0.2 + "@nodelib/fs.walk": ^1.2.3 + glob-parent: ^5.1.2 + merge2: ^1.3.0 + micromatch: ^4.0.4 + checksum: 900e4979f4dbc3313840078419245621259f349950411ca2fa445a2f9a1a6d98c3b5e7e0660c5ccd563aa61abe133a21765c6c0dec8e57da1ba71d8000b05ec1 + languageName: node + linkType: hard + +"fast-json-stable-stringify@npm:^2.0.0, fast-json-stable-stringify@npm:^2.1.0": + version: 2.1.0 + resolution: "fast-json-stable-stringify@npm:2.1.0" + checksum: b191531e36c607977e5b1c47811158733c34ccb3bfde92c44798929e9b4154884378536d26ad90dfecd32e1ffc09c545d23535ad91b3161a27ddbb8ebe0cbecb + languageName: node + linkType: hard + +"fast-levenshtein@npm:^2.0.6": + version: 2.0.6 + resolution: "fast-levenshtein@npm:2.0.6" + checksum: 92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c + languageName: node + linkType: hard + +"fast-xml-parser@npm:^4.0.12, fast-xml-parser@npm:^4.2.4": + version: 4.3.3 + resolution: "fast-xml-parser@npm:4.3.3" + dependencies: + strnum: ^1.0.5 + bin: + fxparser: src/cli/cli.js + checksum: 5e272a0dbb73c4341487935cd6f37df360999f680c0638efec0974dfc58071fb803919f7a030941a7f5bb894794a2f3356d4b863ba2fb9438191795004cdf36e + languageName: node + linkType: hard + +"fastq@npm:^1.6.0": + version: 1.16.0 + resolution: "fastq@npm:1.16.0" + dependencies: + reusify: ^1.0.4 + checksum: 1d40ed1f100ae625e5720484e8602b7ad07649370f1cbc3e34a6b9630a0bfed6946bab0322d8a368a1e3cde87bb9bbb8d3bc2ae01a0c1f022fac1d07c04e4feb + languageName: node + linkType: hard + +"fb-watchman@npm:^2.0.0": + version: 2.0.2 + resolution: "fb-watchman@npm:2.0.2" + dependencies: + bser: 2.1.1 + checksum: b15a124cef28916fe07b400eb87cbc73ca082c142abf7ca8e8de6af43eca79ca7bd13eb4d4d48240b3bd3136eaac40d16e42d6edf87a8e5d1dd8070626860c78 + languageName: node + linkType: hard + +"file-entry-cache@npm:^6.0.1": + version: 6.0.1 + resolution: "file-entry-cache@npm:6.0.1" + dependencies: + flat-cache: ^3.0.4 + checksum: f49701feaa6314c8127c3c2f6173cfefff17612f5ed2daaafc6da13b5c91fd43e3b2a58fd0d63f9f94478a501b167615931e7200e31485e320f74a33885a9c74 + languageName: node + linkType: hard + +"fill-range@npm:^7.0.1": + version: 7.0.1 + resolution: "fill-range@npm:7.0.1" + dependencies: + to-regex-range: ^5.0.1 + checksum: cc283f4e65b504259e64fd969bcf4def4eb08d85565e906b7d36516e87819db52029a76b6363d0f02d0d532f0033c9603b9e2d943d56ee3b0d4f7ad3328ff917 + languageName: node + linkType: hard + +"finalhandler@npm:1.1.2": + version: 1.1.2 + resolution: "finalhandler@npm:1.1.2" + dependencies: + debug: 2.6.9 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + on-finished: ~2.3.0 + parseurl: ~1.3.3 + statuses: ~1.5.0 + unpipe: ~1.0.0 + checksum: 617880460c5138dd7ccfd555cb5dde4d8f170f4b31b8bd51e4b646bb2946c30f7db716428a1f2882d730d2b72afb47d1f67cc487b874cb15426f95753a88965e + languageName: node + linkType: hard + +"find-cache-dir@npm:^2.0.0": + version: 2.1.0 + resolution: "find-cache-dir@npm:2.1.0" + dependencies: + commondir: ^1.0.1 + make-dir: ^2.0.0 + pkg-dir: ^3.0.0 + checksum: 60ad475a6da9f257df4e81900f78986ab367d4f65d33cf802c5b91e969c28a8762f098693d7a571b6e4dd4c15166c2da32ae2d18b6766a18e2071079448fdce4 + languageName: node + linkType: hard + +"find-up@npm:^3.0.0": + version: 3.0.0 + resolution: "find-up@npm:3.0.0" + dependencies: + locate-path: ^3.0.0 + checksum: 38eba3fe7a66e4bc7f0f5a1366dc25508b7cfc349f852640e3678d26ad9a6d7e2c43eff0a472287de4a9753ef58f066a0ea892a256fa3636ad51b3fe1e17fae9 + languageName: node + linkType: hard + +"find-up@npm:^4.0.0, find-up@npm:^4.1.0": + version: 4.1.0 + resolution: "find-up@npm:4.1.0" + dependencies: + locate-path: ^5.0.0 + path-exists: ^4.0.0 + checksum: 4c172680e8f8c1f78839486e14a43ef82e9decd0e74145f40707cc42e7420506d5ec92d9a11c22bd2c48fb0c384ea05dd30e10dd152fefeec6f2f75282a8b844 + languageName: node + linkType: hard + +"find-up@npm:^5.0.0": + version: 5.0.0 + resolution: "find-up@npm:5.0.0" + dependencies: + locate-path: ^6.0.0 + path-exists: ^4.0.0 + checksum: 07955e357348f34660bde7920783204ff5a26ac2cafcaa28bace494027158a97b9f56faaf2d89a6106211a8174db650dd9f503f9c0d526b1202d5554a00b9095 + languageName: node + linkType: hard + +"flat-cache@npm:^3.0.4": + version: 3.2.0 + resolution: "flat-cache@npm:3.2.0" + dependencies: + flatted: ^3.2.9 + keyv: ^4.5.3 + rimraf: ^3.0.2 + checksum: e7e0f59801e288b54bee5cb9681e9ee21ee28ef309f886b312c9d08415b79fc0f24ac842f84356ce80f47d6a53de62197ce0e6e148dc42d5db005992e2a756ec + languageName: node + linkType: hard + +"flatted@npm:^3.2.9": + version: 3.2.9 + resolution: "flatted@npm:3.2.9" + checksum: f14167fbe26a9d20f6fca8d998e8f1f41df72c8e81f9f2c9d61ed2bea058248f5e1cbd05e7f88c0e5087a6a0b822a1e5e2b446e879f3cfbe0b07ba2d7f80b026 + languageName: node + linkType: hard + +"flow-enums-runtime@npm:^0.0.6": + version: 0.0.6 + resolution: "flow-enums-runtime@npm:0.0.6" + checksum: c60412ed6d43b26bf5dfa66be8e588c3ccdb20191fd269e02ca7e8e1d350c73a327cc9a7edb626c80c31eb906981945d12a87ca37118985f33406303806dab79 + languageName: node + linkType: hard + +"flow-parser@npm:0.*": + version: 0.226.0 + resolution: "flow-parser@npm:0.226.0" + checksum: 88addf65749a6322fa54b6ed807d3d26e8f899ff6e9f644407149f9cc0e3729d1aa4d2312dbc6f93011a7becb7679aa61a682d0441f32f95a02d56b45d464c8d + languageName: node + linkType: hard + +"flow-parser@npm:^0.206.0": + version: 0.206.0 + resolution: "flow-parser@npm:0.206.0" + checksum: 1b87d87b59815b09852a6981543ad222da7f4d0e0c26702f9d5e0065174f5f64d2563db76d07a487c6b55e1979344e3845ac42929db70f77a82e8c9171a62a86 + languageName: node + linkType: hard + +"for-each@npm:^0.3.3": + version: 0.3.3 + resolution: "for-each@npm:0.3.3" + dependencies: + is-callable: ^1.1.3 + checksum: 6c48ff2bc63362319c65e2edca4a8e1e3483a2fabc72fbe7feaf8c73db94fc7861bd53bc02c8a66a0c1dd709da6b04eec42e0abdd6b40ce47305ae92a25e5d28 + languageName: node + linkType: hard + +"foreground-child@npm:^3.1.0": + version: 3.1.1 + resolution: "foreground-child@npm:3.1.1" + dependencies: + cross-spawn: ^7.0.0 + signal-exit: ^4.0.1 + checksum: 139d270bc82dc9e6f8bc045fe2aae4001dc2472157044fdfad376d0a3457f77857fa883c1c8b21b491c6caade9a926a4bed3d3d2e8d3c9202b151a4cbbd0bcd5 + languageName: node + linkType: hard + +"fresh@npm:0.5.2": + version: 0.5.2 + resolution: "fresh@npm:0.5.2" + checksum: 13ea8b08f91e669a64e3ba3a20eb79d7ca5379a81f1ff7f4310d54e2320645503cc0c78daedc93dfb6191287295f6479544a649c64d8e41a1c0fb0c221552346 + languageName: node + linkType: hard + +"fs-extra@npm:^8.1.0": + version: 8.1.0 + resolution: "fs-extra@npm:8.1.0" + dependencies: + graceful-fs: ^4.2.0 + jsonfile: ^4.0.0 + universalify: ^0.1.0 + checksum: bf44f0e6cea59d5ce071bba4c43ca76d216f89e402dc6285c128abc0902e9b8525135aa808adad72c9d5d218e9f4bcc63962815529ff2f684ad532172a284880 + languageName: node + linkType: hard + +"fs-minipass@npm:^2.0.0": + version: 2.1.0 + resolution: "fs-minipass@npm:2.1.0" + dependencies: + minipass: ^3.0.0 + checksum: 1b8d128dae2ac6cc94230cc5ead341ba3e0efaef82dab46a33d171c044caaa6ca001364178d42069b2809c35a1c3c35079a32107c770e9ffab3901b59af8c8b1 + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: ^7.0.3 + checksum: 8722a41109130851d979222d3ec88aabaceeaaf8f57b2a8f744ef8bd2d1ce95453b04a61daa0078822bc5cd21e008814f06fe6586f56fef511e71b8d2394d802 + languageName: node + linkType: hard + +"fs.realpath@npm:^1.0.0": + version: 1.0.0 + resolution: "fs.realpath@npm:1.0.0" + checksum: 99ddea01a7e75aa276c250a04eedeffe5662bce66c65c07164ad6264f9de18fb21be9433ead460e54cff20e31721c811f4fb5d70591799df5f85dce6d6746fd0 + languageName: node + linkType: hard + +"fsevents@npm:^2.3.2": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: latest + checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@^2.3.2#~builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=18f3a7" + dependencies: + node-gyp: latest + conditions: os=darwin + languageName: node + linkType: hard + +"function-bind@npm:^1.1.1, function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 2b0ff4ce708d99715ad14a6d1f894e2a83242e4a52ccfcefaee5e40050562e5f6dafc1adbb4ce2d4ab47279a45dc736ab91ea5042d843c3c092820dfe032efb1 + languageName: node + linkType: hard + +"function.prototype.name@npm:^1.1.5, function.prototype.name@npm:^1.1.6": + version: 1.1.6 + resolution: "function.prototype.name@npm:1.1.6" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + functions-have-names: ^1.2.3 + checksum: 7a3f9bd98adab09a07f6e1f03da03d3f7c26abbdeaeee15223f6c04a9fb5674792bdf5e689dac19b97ac71de6aad2027ba3048a9b883aa1b3173eed6ab07f479 + languageName: node + linkType: hard + +"functions-have-names@npm:^1.2.3": + version: 1.2.3 + resolution: "functions-have-names@npm:1.2.3" + checksum: c3f1f5ba20f4e962efb71344ce0a40722163e85bee2101ce25f88214e78182d2d2476aa85ef37950c579eb6cf6ee811c17b3101bb84004bb75655f3e33f3fdb5 + languageName: node + linkType: hard + +"gensync@npm:^1.0.0-beta.2": + version: 1.0.0-beta.2 + resolution: "gensync@npm:1.0.0-beta.2" + checksum: a7437e58c6be12aa6c90f7730eac7fa9833dc78872b4ad2963d2031b00a3367a93f98aec75f9aaac7220848e4026d67a8655e870b24f20a543d103c0d65952ec + languageName: node + linkType: hard + +"get-caller-file@npm:^2.0.1, get-caller-file@npm:^2.0.5": + version: 2.0.5 + resolution: "get-caller-file@npm:2.0.5" + checksum: b9769a836d2a98c3ee734a88ba712e62703f1df31b94b784762c433c27a386dd6029ff55c2a920c392e33657d80191edbf18c61487e198844844516f843496b9 + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": + version: 1.2.2 + resolution: "get-intrinsic@npm:1.2.2" + dependencies: + function-bind: ^1.1.2 + has-proto: ^1.0.1 + has-symbols: ^1.0.3 + hasown: ^2.0.0 + checksum: 447ff0724df26829908dc033b62732359596fcf66027bc131ab37984afb33842d9cd458fd6cecadfe7eac22fd8a54b349799ed334cf2726025c921c7250e7417 + languageName: node + linkType: hard + +"get-package-type@npm:^0.1.0": + version: 0.1.0 + resolution: "get-package-type@npm:0.1.0" + checksum: bba0811116d11e56d702682ddef7c73ba3481f114590e705fc549f4d868972263896af313c57a25c076e3c0d567e11d919a64ba1b30c879be985fc9d44f96148 + languageName: node + linkType: hard + +"get-stream@npm:^6.0.0": + version: 6.0.1 + resolution: "get-stream@npm:6.0.1" + checksum: e04ecece32c92eebf5b8c940f51468cd53554dcbb0ea725b2748be583c9523d00128137966afce410b9b051eb2ef16d657cd2b120ca8edafcf5a65e81af63cad + languageName: node + linkType: hard + +"get-symbol-description@npm:^1.0.0": + version: 1.0.0 + resolution: "get-symbol-description@npm:1.0.0" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.1.1 + checksum: 9ceff8fe968f9270a37a1f73bf3f1f7bda69ca80f4f80850670e0e7b9444ff99323f7ac52f96567f8b5f5fbe7ac717a0d81d3407c7313e82810c6199446a5247 + languageName: node + linkType: hard + +"glob-parent@npm:^5.1.2": + version: 5.1.2 + resolution: "glob-parent@npm:5.1.2" + dependencies: + is-glob: ^4.0.1 + checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e + languageName: node + linkType: hard + +"glob-parent@npm:^6.0.2": + version: 6.0.2 + resolution: "glob-parent@npm:6.0.2" + dependencies: + is-glob: ^4.0.3 + checksum: c13ee97978bef4f55106b71e66428eb1512e71a7466ba49025fc2aec59a5bfb0954d5abd58fc5ee6c9b076eef4e1f6d3375c2e964b88466ca390da4419a786a8 + languageName: node + linkType: hard + +"glob@npm:^10.2.2, glob@npm:^10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^2.3.5 + minimatch: ^9.0.1 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + path-scurry: ^1.10.1 + bin: + glob: dist/esm/bin.mjs + checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 + languageName: node + linkType: hard + +"glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.4": + version: 7.2.3 + resolution: "glob@npm:7.2.3" + dependencies: + fs.realpath: ^1.0.0 + inflight: ^1.0.4 + inherits: 2 + minimatch: ^3.1.1 + once: ^1.3.0 + path-is-absolute: ^1.0.0 + checksum: 29452e97b38fa704dabb1d1045350fb2467cf0277e155aa9ff7077e90ad81d1ea9d53d3ee63bd37c05b09a065e90f16aec4a65f5b8de401d1dac40bc5605d133 + languageName: node + linkType: hard + +"globals@npm:^11.1.0": + version: 11.12.0 + resolution: "globals@npm:11.12.0" + checksum: 67051a45eca3db904aee189dfc7cd53c20c7d881679c93f6146ddd4c9f4ab2268e68a919df740d39c71f4445d2b38ee360fc234428baea1dbdfe68bbcb46979e + languageName: node + linkType: hard + +"globals@npm:^13.19.0": + version: 13.24.0 + resolution: "globals@npm:13.24.0" + dependencies: + type-fest: ^0.20.2 + checksum: 56066ef058f6867c04ff203b8a44c15b038346a62efbc3060052a1016be9f56f4cf0b2cd45b74b22b81e521a889fc7786c73691b0549c2f3a6e825b3d394f43c + languageName: node + linkType: hard + +"globalthis@npm:^1.0.3": + version: 1.0.3 + resolution: "globalthis@npm:1.0.3" + dependencies: + define-properties: ^1.1.3 + checksum: fbd7d760dc464c886d0196166d92e5ffb4c84d0730846d6621a39fbbc068aeeb9c8d1421ad330e94b7bca4bb4ea092f5f21f3d36077812af5d098b4dc006c998 + languageName: node + linkType: hard + +"globby@npm:^11.1.0": + version: 11.1.0 + resolution: "globby@npm:11.1.0" + dependencies: + array-union: ^2.1.0 + dir-glob: ^3.0.1 + fast-glob: ^3.2.9 + ignore: ^5.2.0 + merge2: ^1.4.1 + slash: ^3.0.0 + checksum: b4be8885e0cfa018fc783792942d53926c35c50b3aefd3fdcfb9d22c627639dc26bd2327a40a0b74b074100ce95bb7187bfeae2f236856aa3de183af7a02aea6 + languageName: node + linkType: hard + +"gopd@npm:^1.0.1": + version: 1.0.1 + resolution: "gopd@npm:1.0.1" + dependencies: + get-intrinsic: ^1.1.3 + checksum: a5ccfb8806e0917a94e0b3de2af2ea4979c1da920bc381667c260e00e7cafdbe844e2cb9c5bcfef4e5412e8bf73bab837285bc35c7ba73aaaf0134d4583393a6 + languageName: node + linkType: hard + +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.3, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 + languageName: node + linkType: hard + +"graphemer@npm:^1.4.0": + version: 1.4.0 + resolution: "graphemer@npm:1.4.0" + checksum: bab8f0be9b568857c7bec9fda95a89f87b783546d02951c40c33f84d05bb7da3fd10f863a9beb901463669b6583173a8c8cc6d6b306ea2b9b9d5d3d943c3a673 + languageName: node + linkType: hard + +"has-bigints@npm:^1.0.1, has-bigints@npm:^1.0.2": + version: 1.0.2 + resolution: "has-bigints@npm:1.0.2" + checksum: 390e31e7be7e5c6fe68b81babb73dfc35d413604d7ee5f56da101417027a4b4ce6a27e46eff97ad040c835b5d228676eae99a9b5c3bc0e23c8e81a49241ff45b + languageName: node + linkType: hard + +"has-flag@npm:^3.0.0": + version: 3.0.0 + resolution: "has-flag@npm:3.0.0" + checksum: 4a15638b454bf086c8148979aae044dd6e39d63904cd452d970374fa6a87623423da485dfb814e7be882e05c096a7ccf1ebd48e7e7501d0208d8384ff4dea73b + languageName: node + linkType: hard + +"has-flag@npm:^4.0.0": + version: 4.0.0 + resolution: "has-flag@npm:4.0.0" + checksum: 261a1357037ead75e338156b1f9452c016a37dcd3283a972a30d9e4a87441ba372c8b81f818cd0fbcd9c0354b4ae7e18b9e1afa1971164aef6d18c2b6095a8ad + languageName: node + linkType: hard + +"has-property-descriptors@npm:^1.0.0": + version: 1.0.1 + resolution: "has-property-descriptors@npm:1.0.1" + dependencies: + get-intrinsic: ^1.2.2 + checksum: 2bcc6bf6ec6af375add4e4b4ef586e43674850a91ad4d46666d0b28ba8e1fd69e424c7677d24d60f69470ad0afaa2f3197f508b20b0bb7dd99a8ab77ffc4b7c4 + languageName: node + linkType: hard + +"has-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "has-proto@npm:1.0.1" + checksum: febc5b5b531de8022806ad7407935e2135f1cc9e64636c3916c6842bd7995994ca3b29871ecd7954bd35f9e2986c17b3b227880484d22259e2f8e6ce63fd383e + languageName: node + linkType: hard + +"has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": + version: 1.0.3 + resolution: "has-symbols@npm:1.0.3" + checksum: a054c40c631c0d5741a8285010a0777ea0c068f99ed43e5d6eb12972da223f8af553a455132fdb0801bdcfa0e0f443c0c03a68d8555aa529b3144b446c3f2410 + languageName: node + linkType: hard + +"has-tostringtag@npm:^1.0.0": + version: 1.0.0 + resolution: "has-tostringtag@npm:1.0.0" + dependencies: + has-symbols: ^1.0.2 + checksum: cc12eb28cb6ae22369ebaad3a8ab0799ed61270991be88f208d508076a1e99abe4198c965935ce85ea90b60c94ddda73693b0920b58e7ead048b4a391b502c1c + languageName: node + linkType: hard + +"hasown@npm:^2.0.0": + version: 2.0.0 + resolution: "hasown@npm:2.0.0" + dependencies: + function-bind: ^1.1.2 + checksum: 6151c75ca12554565098641c98a40f4cc86b85b0fd5b6fe92360967e4605a4f9610f7757260b4e8098dd1c2ce7f4b095f2006fe72a570e3b6d2d28de0298c176 + languageName: node + linkType: hard + +"hermes-estree@npm:0.15.0": + version: 0.15.0 + resolution: "hermes-estree@npm:0.15.0" + checksum: 227d7ac117a00b4f02cdadf33f4ca73dd263bb05e692065f6709ef5a348b283d0fc319fc5d188438c84c688c4e1245cd990ade27f229abd4e9f94dda1abe147d + languageName: node + linkType: hard + +"hermes-estree@npm:0.18.2": + version: 0.18.2 + resolution: "hermes-estree@npm:0.18.2" + checksum: 6723aa4c475df27f964cde86518c097075a1b18168834b9329392a8ded4a9f09a854c31bc7720b0656550c05369d1d24d2fa7bee6a8d7ab35d78e1ec283ffe1f + languageName: node + linkType: hard + +"hermes-parser@npm:0.15.0": + version: 0.15.0 + resolution: "hermes-parser@npm:0.15.0" + dependencies: + hermes-estree: 0.15.0 + checksum: 6c06a57a3998edd8c3aff05bbacdc8ec80f930360fa82ab75021b4b20edce8d76d30232babb7d6e7a0fcb758b0b36d7ee0f25936c9accf0b977542a079cb39cf + languageName: node + linkType: hard + +"hermes-parser@npm:0.18.2": + version: 0.18.2 + resolution: "hermes-parser@npm:0.18.2" + dependencies: + hermes-estree: 0.18.2 + checksum: d628f207e8951ee8bdf5b3c798ea9e18e2f4e49f9a5aaed639868207b7163eafb3a55b999c6ed8b4f0c4e39b474c2e1bd1bcb69303f095cab56e1711368bcbdf + languageName: node + linkType: hard + +"hermes-profile-transformer@npm:^0.0.6": + version: 0.0.6 + resolution: "hermes-profile-transformer@npm:0.0.6" + dependencies: + source-map: ^0.7.3 + checksum: b5f874eaa65b70d88df7a4ce3b20d73312bb0bc73410f1b63d708f02e1c532ae16975da84e23b977eab8592ac95d7e6fc0c4094c78604fd0a092ed886c62aa7a + languageName: node + linkType: hard + +"html-escaper@npm:^2.0.0": + version: 2.0.2 + resolution: "html-escaper@npm:2.0.2" + checksum: d2df2da3ad40ca9ee3a39c5cc6475ef67c8f83c234475f24d8e9ce0dc80a2c82df8e1d6fa78ddd1e9022a586ea1bd247a615e80a5cd9273d90111ddda7d9e974 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 + languageName: node + linkType: hard + +"http-errors@npm:2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + checksum: 9b0a3782665c52ce9dc658a0d1560bcb0214ba5699e4ea15aefb2a496e2ca83db03ebc42e1cce4ac1f413e4e0d2d736a3fd755772c556a9a06853ba2a0b7d920 + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.0 + resolution: "http-proxy-agent@npm:7.0.0" + dependencies: + agent-base: ^7.1.0 + debug: ^4.3.4 + checksum: 48d4fac997917e15f45094852b63b62a46d0c8a4f0b9c6c23ca26d27b8df8d178bed88389e604745e748bd9a01f5023e25093722777f0593c3f052009ff438b6 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.2 + resolution: "https-proxy-agent@npm:7.0.2" + dependencies: + agent-base: ^7.0.2 + debug: 4 + checksum: 088969a0dd476ea7a0ed0a2cf1283013682b08f874c3bc6696c83fa061d2c157d29ef0ad3eb70a2046010bb7665573b2388d10fdcb3e410a66995e5248444292 + languageName: node + linkType: hard + +"human-signals@npm:^2.1.0": + version: 2.1.0 + resolution: "human-signals@npm:2.1.0" + checksum: b87fd89fce72391625271454e70f67fe405277415b48bcc0117ca73d31fa23a4241787afdc8d67f5a116cf37258c052f59ea82daffa72364d61351423848e3b8 + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: ">= 2.1.2 < 3.0.0" + checksum: 3f60d47a5c8fc3313317edfd29a00a692cc87a19cac0159e2ce711d0ebc9019064108323b5e493625e25594f11c6236647d8e256fbe7a58f4a3b33b89e6d30bf + languageName: node + linkType: hard + +"ieee754@npm:^1.1.13": + version: 1.2.1 + resolution: "ieee754@npm:1.2.1" + checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e + languageName: node + linkType: hard + +"ignore@npm:^5.0.5, ignore@npm:^5.2.0, ignore@npm:^5.2.4": + version: 5.3.0 + resolution: "ignore@npm:5.3.0" + checksum: 2736da6621f14ced652785cb05d86301a66d70248597537176612bd0c8630893564bd5f6421f8806b09e8472e75c591ef01672ab8059c07c6eb2c09cefe04bf9 + languageName: node + linkType: hard + +"image-size@npm:^1.0.2": + version: 1.1.1 + resolution: "image-size@npm:1.1.1" + dependencies: + queue: 6.0.2 + bin: + image-size: bin/image-size.js + checksum: 23b3a515dded89e7f967d52b885b430d6a5a903da954fce703130bfb6069d738d80e6588efd29acfaf5b6933424a56535aa7bf06867e4ebd0250c2ee51f19a4a + languageName: node + linkType: hard + +"immer@npm:^10.0.3": + version: 10.0.3 + resolution: "immer@npm:10.0.3" + checksum: 76acabe6f40e752028313762ba477a5d901e57b669f3b8fb406b87b9bb9b14e663a6fbbf5a6d1ab323737dd38f4b2494a4e28002045b88948da8dbf482309f28 + languageName: node + linkType: hard + +"import-fresh@npm:^2.0.0": + version: 2.0.0 + resolution: "import-fresh@npm:2.0.0" + dependencies: + caller-path: ^2.0.0 + resolve-from: ^3.0.0 + checksum: 610255f9753cc6775df00be08e9f43691aa39f7703e3636c45afe22346b8b545e600ccfe100c554607546fc8e861fa149a0d1da078c8adedeea30fff326eef79 + languageName: node + linkType: hard + +"import-fresh@npm:^3.2.1": + version: 3.3.0 + resolution: "import-fresh@npm:3.3.0" + dependencies: + parent-module: ^1.0.0 + resolve-from: ^4.0.0 + checksum: 2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa + languageName: node + linkType: hard + +"import-local@npm:^3.0.2": + version: 3.1.0 + resolution: "import-local@npm:3.1.0" + dependencies: + pkg-dir: ^4.2.0 + resolve-cwd: ^3.0.0 + bin: + import-local-fixture: fixtures/cli.js + checksum: bfcdb63b5e3c0e245e347f3107564035b128a414c4da1172a20dc67db2504e05ede4ac2eee1252359f78b0bfd7b19ef180aec427c2fce6493ae782d73a04cddd + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 7cae75c8cd9a50f57dadd77482359f659eaebac0319dd9368bcd1714f55e65badd6929ca58569da2b6494ef13fdd5598cd700b1eba23f8b79c5f19d195a3ecf7 + languageName: node + linkType: hard + +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 824cfb9929d031dabf059bebfe08cf3137365e112019086ed3dcff6a0a7b698cb80cf67ccccde0e25b9e2d7527aa6cc1fed1ac490c752162496caba3e6699612 + languageName: node + linkType: hard + +"inflight@npm:^1.0.4": + version: 1.0.6 + resolution: "inflight@npm:1.0.6" + dependencies: + once: ^1.3.0 + wrappy: 1 + checksum: f4f76aa072ce19fae87ce1ef7d221e709afb59d445e05d47fba710e85470923a75de35bfae47da6de1b18afc3ce83d70facf44cfb0aff89f0a3f45c0a0244dfd + languageName: node + linkType: hard + +"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 4a48a733847879d6cf6691860a6b1e3f0f4754176e4d71494c41f3475553768b10f84b5ce1d40fbd0e34e6bfbb864ee35858ad4dd2cf31e02fc4a154b724d7f1 + languageName: node + linkType: hard + +"internal-slot@npm:^1.0.5": + version: 1.0.6 + resolution: "internal-slot@npm:1.0.6" + dependencies: + get-intrinsic: ^1.2.2 + hasown: ^2.0.0 + side-channel: ^1.0.4 + checksum: 7872454888047553ce97a3fa1da7cc054a28ec5400a9c2e9f4dbe4fe7c1d041cb8e8301467614b80d4246d50377aad2fb58860b294ed74d6700cc346b6f89549 + languageName: node + linkType: hard + +"invariant@npm:^2.2.4": + version: 2.2.4 + resolution: "invariant@npm:2.2.4" + dependencies: + loose-envify: ^1.0.0 + checksum: cc3182d793aad82a8d1f0af697b462939cb46066ec48bbf1707c150ad5fad6406137e91a262022c269702e01621f35ef60269f6c0d7fd178487959809acdfb14 + languageName: node + linkType: hard + +"ip@npm:^1.1.5": + version: 1.1.8 + resolution: "ip@npm:1.1.8" + checksum: a2ade53eb339fb0cbe9e69a44caab10d6e3784662285eb5d2677117ee4facc33a64679051c35e0dfdb1a3983a51ce2f5d2cb36446d52e10d01881789b76e28fb + languageName: node + linkType: hard + +"ip@npm:^2.0.0": + version: 2.0.0 + resolution: "ip@npm:2.0.0" + checksum: cfcfac6b873b701996d71ec82a7dd27ba92450afdb421e356f44044ed688df04567344c36cbacea7d01b1c39a4c732dc012570ebe9bebfb06f27314bca625349 + languageName: node + linkType: hard + +"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2": + version: 3.0.2 + resolution: "is-array-buffer@npm:3.0.2" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.2.0 + is-typed-array: ^1.1.10 + checksum: dcac9dda66ff17df9cabdc58214172bf41082f956eab30bb0d86bc0fab1e44b690fc8e1f855cf2481245caf4e8a5a006a982a71ddccec84032ed41f9d8da8c14 + languageName: node + linkType: hard + +"is-arrayish@npm:^0.2.1": + version: 0.2.1 + resolution: "is-arrayish@npm:0.2.1" + checksum: eef4417e3c10e60e2c810b6084942b3ead455af16c4509959a27e490e7aee87cfb3f38e01bbde92220b528a0ee1a18d52b787e1458ee86174d8c7f0e58cd488f + languageName: node + linkType: hard + +"is-async-function@npm:^2.0.0": + version: 2.0.0 + resolution: "is-async-function@npm:2.0.0" + dependencies: + has-tostringtag: ^1.0.0 + checksum: e3471d95e6c014bf37cad8a93f2f4b6aac962178e0a5041e8903147166964fdc1c5c1d2ef87e86d77322c370ca18f2ea004fa7420581fa747bcaf7c223069dbd + languageName: node + linkType: hard + +"is-bigint@npm:^1.0.1": + version: 1.0.4 + resolution: "is-bigint@npm:1.0.4" + dependencies: + has-bigints: ^1.0.1 + checksum: c56edfe09b1154f8668e53ebe8252b6f185ee852a50f9b41e8d921cb2bed425652049fbe438723f6cb48a63ca1aa051e948e7e401e093477c99c84eba244f666 + languageName: node + linkType: hard + +"is-boolean-object@npm:^1.1.0": + version: 1.1.2 + resolution: "is-boolean-object@npm:1.1.2" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: c03b23dbaacadc18940defb12c1c0e3aaece7553ef58b162a0f6bba0c2a7e1551b59f365b91e00d2dbac0522392d576ef322628cb1d036a0fe51eb466db67222 + languageName: node + linkType: hard + +"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 61fd57d03b0d984e2ed3720fb1c7a897827ea174bd44402878e059542ea8c4aeedee0ea0985998aa5cc2736b2fa6e271c08587addb5b3959ac52cf665173d1ac + languageName: node + linkType: hard + +"is-core-module@npm:^2.13.0": + version: 2.13.1 + resolution: "is-core-module@npm:2.13.1" + dependencies: + hasown: ^2.0.0 + checksum: 256559ee8a9488af90e4bad16f5583c6d59e92f0742e9e8bb4331e758521ee86b810b93bae44f390766ffbc518a0488b18d9dab7da9a5ff997d499efc9403f7c + languageName: node + linkType: hard + +"is-date-object@npm:^1.0.1, is-date-object@npm:^1.0.5": + version: 1.0.5 + resolution: "is-date-object@npm:1.0.5" + dependencies: + has-tostringtag: ^1.0.0 + checksum: baa9077cdf15eb7b58c79398604ca57379b2fc4cf9aa7a9b9e295278648f628c9b201400c01c5e0f7afae56507d741185730307cbe7cad3b9f90a77e5ee342fc + languageName: node + linkType: hard + +"is-directory@npm:^0.3.1": + version: 0.3.1 + resolution: "is-directory@npm:0.3.1" + checksum: dce9a9d3981e38f2ded2a80848734824c50ee8680cd09aa477bef617949715cfc987197a2ca0176c58a9fb192a1a0d69b535c397140d241996a609d5906ae524 + languageName: node + linkType: hard + +"is-docker@npm:^2.0.0": + version: 2.2.1 + resolution: "is-docker@npm:2.2.1" + bin: + is-docker: cli.js + checksum: 3fef7ddbf0be25958e8991ad941901bf5922ab2753c46980b60b05c1bf9c9c2402d35e6dc32e4380b980ef5e1970a5d9d5e5aa2e02d77727c3b6b5e918474c56 + languageName: node + linkType: hard + +"is-extglob@npm:^2.1.1": + version: 2.1.1 + resolution: "is-extglob@npm:2.1.1" + checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85 + languageName: node + linkType: hard + +"is-finalizationregistry@npm:^1.0.2": + version: 1.0.2 + resolution: "is-finalizationregistry@npm:1.0.2" + dependencies: + call-bind: ^1.0.2 + checksum: 4f243a8e06228cd45bdab8608d2cb7abfc20f6f0189c8ac21ea8d603f1f196eabd531ce0bb8e08cbab047e9845ef2c191a3761c9a17ad5cabf8b35499c4ad35d + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^2.0.0": + version: 2.0.0 + resolution: "is-fullwidth-code-point@npm:2.0.0" + checksum: eef9c6e15f68085fec19ff6a978a6f1b8f48018fd1265035552078ee945573594933b09bbd6f562553e2a241561439f1ef5339276eba68d272001343084cfab8 + languageName: node + linkType: hard + +"is-fullwidth-code-point@npm:^3.0.0": + version: 3.0.0 + resolution: "is-fullwidth-code-point@npm:3.0.0" + checksum: 44a30c29457c7fb8f00297bce733f0a64cd22eca270f83e58c105e0d015e45c019491a4ab2faef91ab51d4738c670daff901c799f6a700e27f7314029e99e348 + languageName: node + linkType: hard + +"is-generator-fn@npm:^2.0.0": + version: 2.1.0 + resolution: "is-generator-fn@npm:2.1.0" + checksum: a6ad5492cf9d1746f73b6744e0c43c0020510b59d56ddcb78a91cbc173f09b5e6beff53d75c9c5a29feb618bfef2bf458e025ecf3a57ad2268e2fb2569f56215 + languageName: node + linkType: hard + +"is-generator-function@npm:^1.0.10": + version: 1.0.10 + resolution: "is-generator-function@npm:1.0.10" + dependencies: + has-tostringtag: ^1.0.0 + checksum: d54644e7dbaccef15ceb1e5d91d680eb5068c9ee9f9eb0a9e04173eb5542c9b51b5ab52c5537f5703e48d5fddfd376817c1ca07a84a407b7115b769d4bdde72b + languageName: node + linkType: hard + +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": + version: 4.0.3 + resolution: "is-glob@npm:4.0.3" + dependencies: + is-extglob: ^2.1.1 + checksum: d381c1319fcb69d341cc6e6c7cd588e17cd94722d9a32dbd60660b993c4fb7d0f19438674e68dfec686d09b7c73139c9166b47597f846af387450224a8101ab4 + languageName: node + linkType: hard + +"is-interactive@npm:^1.0.0": + version: 1.0.0 + resolution: "is-interactive@npm:1.0.0" + checksum: 824808776e2d468b2916cdd6c16acacebce060d844c35ca6d82267da692e92c3a16fdba624c50b54a63f38bdc4016055b6f443ce57d7147240de4f8cdabaf6f9 + languageName: node + linkType: hard + +"is-lambda@npm:^1.0.1": + version: 1.0.1 + resolution: "is-lambda@npm:1.0.1" + checksum: 93a32f01940220532e5948538699ad610d5924ac86093fcee83022252b363eb0cc99ba53ab084a04e4fb62bf7b5731f55496257a4c38adf87af9c4d352c71c35 + languageName: node + linkType: hard + +"is-map@npm:^2.0.1": + version: 2.0.2 + resolution: "is-map@npm:2.0.2" + checksum: ace3d0ecd667bbdefdb1852de601268f67f2db725624b1958f279316e13fecb8fa7df91fd60f690d7417b4ec180712f5a7ee967008e27c65cfd475cc84337728 + languageName: node + linkType: hard + +"is-negative-zero@npm:^2.0.2": + version: 2.0.2 + resolution: "is-negative-zero@npm:2.0.2" + checksum: f3232194c47a549da60c3d509c9a09be442507616b69454716692e37ae9f37c4dea264fb208ad0c9f3efd15a796a46b79df07c7e53c6227c32170608b809149a + languageName: node + linkType: hard + +"is-number-object@npm:^1.0.4": + version: 1.0.7 + resolution: "is-number-object@npm:1.0.7" + dependencies: + has-tostringtag: ^1.0.0 + checksum: d1e8d01bb0a7134c74649c4e62da0c6118a0bfc6771ea3c560914d52a627873e6920dd0fd0ebc0e12ad2ff4687eac4c308f7e80320b973b2c8a2c8f97a7524f7 + languageName: node + linkType: hard + +"is-number@npm:^7.0.0": + version: 7.0.0 + resolution: "is-number@npm:7.0.0" + checksum: 456ac6f8e0f3111ed34668a624e45315201dff921e5ac181f8ec24923b99e9f32ca1a194912dc79d539c97d33dba17dc635202ff0b2cf98326f608323276d27a + languageName: node + linkType: hard + +"is-path-inside@npm:^3.0.3": + version: 3.0.3 + resolution: "is-path-inside@npm:3.0.3" + checksum: abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9 + languageName: node + linkType: hard + +"is-plain-object@npm:^2.0.4": + version: 2.0.4 + resolution: "is-plain-object@npm:2.0.4" + dependencies: + isobject: ^3.0.1 + checksum: 2a401140cfd86cabe25214956ae2cfee6fbd8186809555cd0e84574f88de7b17abacb2e477a6a658fa54c6083ecbda1e6ae404c7720244cd198903848fca70ca + languageName: node + linkType: hard + +"is-regex@npm:^1.1.4": + version: 1.1.4 + resolution: "is-regex@npm:1.1.4" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: 362399b33535bc8f386d96c45c9feb04cf7f8b41c182f54174c1a45c9abbbe5e31290bbad09a458583ff6bf3b2048672cdb1881b13289569a7c548370856a652 + languageName: node + linkType: hard + +"is-set@npm:^2.0.1": + version: 2.0.2 + resolution: "is-set@npm:2.0.2" + checksum: b64343faf45e9387b97a6fd32be632ee7b269bd8183701f3b3f5b71a7cf00d04450ed8669d0bd08753e08b968beda96fca73a10fd0ff56a32603f64deba55a57 + languageName: node + linkType: hard + +"is-shared-array-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "is-shared-array-buffer@npm:1.0.2" + dependencies: + call-bind: ^1.0.2 + checksum: 9508929cf14fdc1afc9d61d723c6e8d34f5e117f0bffda4d97e7a5d88c3a8681f633a74f8e3ad1fe92d5113f9b921dc5ca44356492079612f9a247efbce7032a + languageName: node + linkType: hard + +"is-stream@npm:^2.0.0": + version: 2.0.1 + resolution: "is-stream@npm:2.0.1" + checksum: b8e05ccdf96ac330ea83c12450304d4a591f9958c11fd17bed240af8d5ffe08aedafa4c0f4cfccd4d28dc9d4d129daca1023633d5c11601a6cbc77521f6fae66 + languageName: node + linkType: hard + +"is-string@npm:^1.0.5, is-string@npm:^1.0.7": + version: 1.0.7 + resolution: "is-string@npm:1.0.7" + dependencies: + has-tostringtag: ^1.0.0 + checksum: 323b3d04622f78d45077cf89aab783b2f49d24dc641aa89b5ad1a72114cfeff2585efc8c12ef42466dff32bde93d839ad321b26884cf75e5a7892a938b089989 + languageName: node + linkType: hard + +"is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": + version: 1.0.4 + resolution: "is-symbol@npm:1.0.4" + dependencies: + has-symbols: ^1.0.2 + checksum: 92805812ef590738d9de49d677cd17dfd486794773fb6fa0032d16452af46e9b91bb43ffe82c983570f015b37136f4b53b28b8523bfb10b0ece7a66c31a54510 + languageName: node + linkType: hard + +"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.12, is-typed-array@npm:^1.1.9": + version: 1.1.12 + resolution: "is-typed-array@npm:1.1.12" + dependencies: + which-typed-array: ^1.1.11 + checksum: 4c89c4a3be07186caddadf92197b17fda663a9d259ea0d44a85f171558270d36059d1c386d34a12cba22dfade5aba497ce22778e866adc9406098c8fc4771796 + languageName: node + linkType: hard + +"is-unicode-supported@npm:^0.1.0": + version: 0.1.0 + resolution: "is-unicode-supported@npm:0.1.0" + checksum: a2aab86ee7712f5c2f999180daaba5f361bdad1efadc9610ff5b8ab5495b86e4f627839d085c6530363c6d6d4ecbde340fb8e54bdb83da4ba8e0865ed5513c52 + languageName: node + linkType: hard + +"is-weakmap@npm:^2.0.1": + version: 2.0.1 + resolution: "is-weakmap@npm:2.0.1" + checksum: 1222bb7e90c32bdb949226e66d26cb7bce12e1e28e3e1b40bfa6b390ba3e08192a8664a703dff2a00a84825f4e022f9cd58c4599ff9981ab72b1d69479f4f7f6 + languageName: node + linkType: hard + +"is-weakref@npm:^1.0.2": + version: 1.0.2 + resolution: "is-weakref@npm:1.0.2" + dependencies: + call-bind: ^1.0.2 + checksum: 95bd9a57cdcb58c63b1c401c60a474b0f45b94719c30f548c891860f051bc2231575c290a6b420c6bc6e7ed99459d424c652bd5bf9a1d5259505dc35b4bf83de + languageName: node + linkType: hard + +"is-weakset@npm:^2.0.1": + version: 2.0.2 + resolution: "is-weakset@npm:2.0.2" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.1.1 + checksum: 5d8698d1fa599a0635d7ca85be9c26d547b317ed8fd83fc75f03efbe75d50001b5eececb1e9971de85fcde84f69ae6f8346bc92d20d55d46201d328e4c74a367 + languageName: node + linkType: hard + +"is-wsl@npm:^1.1.0": + version: 1.1.0 + resolution: "is-wsl@npm:1.1.0" + checksum: ea157d232351e68c92bd62fc541771096942fe72f69dff452dd26dcc31466258c570a3b04b8cda2e01cd2968255b02951b8670d08ea4ed76d6b1a646061ac4fe + languageName: node + linkType: hard + +"is-wsl@npm:^2.1.1, is-wsl@npm:^2.2.0": + version: 2.2.0 + resolution: "is-wsl@npm:2.2.0" + dependencies: + is-docker: ^2.0.0 + checksum: 20849846ae414997d290b75e16868e5261e86ff5047f104027026fd61d8b5a9b0b3ade16239f35e1a067b3c7cc02f70183cb661010ed16f4b6c7c93dad1b19d8 + languageName: node + linkType: hard + +"isarray@npm:^2.0.5": + version: 2.0.5 + resolution: "isarray@npm:2.0.5" + checksum: bd5bbe4104438c4196ba58a54650116007fa0262eccef13a4c55b2e09a5b36b59f1e75b9fcc49883dd9d4953892e6fc007eef9e9155648ceea036e184b0f930a + languageName: node + linkType: hard + +"isarray@npm:~1.0.0": + version: 1.0.0 + resolution: "isarray@npm:1.0.0" + checksum: f032df8e02dce8ec565cf2eb605ea939bdccea528dbcf565cdf92bfa2da9110461159d86a537388ef1acef8815a330642d7885b29010e8f7eac967c9993b65ab + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 26bf6c5480dda5161c820c5b5c751ae1e766c587b1f951ea3fcfc973bafb7831ae5b54a31a69bd670220e42e99ec154475025a468eae58ea262f813fdc8d1c62 + languageName: node + linkType: hard + +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + +"isobject@npm:^3.0.1": + version: 3.0.1 + resolution: "isobject@npm:3.0.1" + checksum: db85c4c970ce30693676487cca0e61da2ca34e8d4967c2e1309143ff910c207133a969f9e4ddb2dc6aba670aabce4e0e307146c310350b298e74a31f7d464703 + languageName: node + linkType: hard + +"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": + version: 3.2.2 + resolution: "istanbul-lib-coverage@npm:3.2.2" + checksum: 2367407a8d13982d8f7a859a35e7f8dd5d8f75aae4bb5484ede3a9ea1b426dc245aff28b976a2af48ee759fdd9be374ce2bd2669b644f31e76c5f46a2e29a831 + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^5.0.4": + version: 5.2.1 + resolution: "istanbul-lib-instrument@npm:5.2.1" + dependencies: + "@babel/core": ^7.12.3 + "@babel/parser": ^7.14.7 + "@istanbuljs/schema": ^0.1.2 + istanbul-lib-coverage: ^3.2.0 + semver: ^6.3.0 + checksum: bf16f1803ba5e51b28bbd49ed955a736488381e09375d830e42ddeb403855b2006f850711d95ad726f2ba3f1ae8e7366de7e51d2b9ac67dc4d80191ef7ddf272 + languageName: node + linkType: hard + +"istanbul-lib-instrument@npm:^6.0.0": + version: 6.0.1 + resolution: "istanbul-lib-instrument@npm:6.0.1" + dependencies: + "@babel/core": ^7.12.3 + "@babel/parser": ^7.14.7 + "@istanbuljs/schema": ^0.1.2 + istanbul-lib-coverage: ^3.2.0 + semver: ^7.5.4 + checksum: fb23472e739cfc9b027cefcd7d551d5e7ca7ff2817ae5150fab99fe42786a7f7b56a29a2aa8309c37092e18297b8003f9c274f50ca4360949094d17fbac81472 + languageName: node + linkType: hard + +"istanbul-lib-report@npm:^3.0.0": + version: 3.0.1 + resolution: "istanbul-lib-report@npm:3.0.1" + dependencies: + istanbul-lib-coverage: ^3.0.0 + make-dir: ^4.0.0 + supports-color: ^7.1.0 + checksum: fd17a1b879e7faf9bb1dc8f80b2a16e9f5b7b8498fe6ed580a618c34df0bfe53d2abd35bf8a0a00e628fb7405462576427c7df20bbe4148d19c14b431c974b21 + languageName: node + linkType: hard + +"istanbul-lib-source-maps@npm:^4.0.0": + version: 4.0.1 + resolution: "istanbul-lib-source-maps@npm:4.0.1" + dependencies: + debug: ^4.1.1 + istanbul-lib-coverage: ^3.0.0 + source-map: ^0.6.1 + checksum: 21ad3df45db4b81852b662b8d4161f6446cd250c1ddc70ef96a585e2e85c26ed7cd9c2a396a71533cfb981d1a645508bc9618cae431e55d01a0628e7dec62ef2 + languageName: node + linkType: hard + +"istanbul-reports@npm:^3.1.3": + version: 3.1.6 + resolution: "istanbul-reports@npm:3.1.6" + dependencies: + html-escaper: ^2.0.0 + istanbul-lib-report: ^3.0.0 + checksum: 44c4c0582f287f02341e9720997f9e82c071627e1e862895745d5f52ec72c9b9f38e1d12370015d2a71dcead794f34c7732aaef3fab80a24bc617a21c3d911d6 + languageName: node + linkType: hard + +"iterator.prototype@npm:^1.1.2": + version: 1.1.2 + resolution: "iterator.prototype@npm:1.1.2" + dependencies: + define-properties: ^1.2.1 + get-intrinsic: ^1.2.1 + has-symbols: ^1.0.3 + reflect.getprototypeof: ^1.0.4 + set-function-name: ^2.0.1 + checksum: d8a507e2ccdc2ce762e8a1d3f4438c5669160ac72b88b648e59a688eec6bc4e64b22338e74000518418d9e693faf2a092d2af21b9ec7dbf7763b037a54701168 + languageName: node + linkType: hard + +"jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" + dependencies: + "@isaacs/cliui": ^8.0.2 + "@pkgjs/parseargs": ^0.11.0 + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 57d43ad11eadc98cdfe7496612f6bbb5255ea69fe51ea431162db302c2a11011642f50cfad57288bd0aea78384a0612b16e131944ad8ecd09d619041c8531b54 + languageName: node + linkType: hard + +"jest-changed-files@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-changed-files@npm:29.7.0" + dependencies: + execa: ^5.0.0 + jest-util: ^29.7.0 + p-limit: ^3.1.0 + checksum: 963e203893c396c5dfc75e00a49426688efea7361b0f0e040035809cecd2d46b3c01c02be2d9e8d38b1138357d2de7719ea5b5be21f66c10f2e9685a5a73bb99 + languageName: node + linkType: hard + +"jest-circus@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-circus@npm:29.7.0" + dependencies: + "@jest/environment": ^29.7.0 + "@jest/expect": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + co: ^4.6.0 + dedent: ^1.0.0 + is-generator-fn: ^2.0.0 + jest-each: ^29.7.0 + jest-matcher-utils: ^29.7.0 + jest-message-util: ^29.7.0 + jest-runtime: ^29.7.0 + jest-snapshot: ^29.7.0 + jest-util: ^29.7.0 + p-limit: ^3.1.0 + pretty-format: ^29.7.0 + pure-rand: ^6.0.0 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: 349437148924a5a109c9b8aad6d393a9591b4dac1918fc97d81b7fc515bc905af9918495055071404af1fab4e48e4b04ac3593477b1d5dcf48c4e71b527c70a7 + languageName: node + linkType: hard + +"jest-cli@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-cli@npm:29.7.0" + dependencies: + "@jest/core": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/types": ^29.6.3 + chalk: ^4.0.0 + create-jest: ^29.7.0 + exit: ^0.1.2 + import-local: ^3.0.2 + jest-config: ^29.7.0 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 + yargs: ^17.3.1 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 664901277a3f5007ea4870632ed6e7889db9da35b2434e7cb488443e6bf5513889b344b7fddf15112135495b9875892b156faeb2d7391ddb9e2a849dcb7b6c36 + languageName: node + linkType: hard + +"jest-config@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-config@npm:29.7.0" + dependencies: + "@babel/core": ^7.11.6 + "@jest/test-sequencer": ^29.7.0 + "@jest/types": ^29.6.3 + babel-jest: ^29.7.0 + chalk: ^4.0.0 + ci-info: ^3.2.0 + deepmerge: ^4.2.2 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + jest-circus: ^29.7.0 + jest-environment-node: ^29.7.0 + jest-get-type: ^29.6.3 + jest-regex-util: ^29.6.3 + jest-resolve: ^29.7.0 + jest-runner: ^29.7.0 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 + micromatch: ^4.0.4 + parse-json: ^5.2.0 + pretty-format: ^29.7.0 + slash: ^3.0.0 + strip-json-comments: ^3.1.1 + peerDependencies: + "@types/node": "*" + ts-node: ">=9.0.0" + peerDependenciesMeta: + "@types/node": + optional: true + ts-node: + optional: true + checksum: 4cabf8f894c180cac80b7df1038912a3fc88f96f2622de33832f4b3314f83e22b08fb751da570c0ab2b7988f21604bdabade95e3c0c041068ac578c085cf7dff + languageName: node + linkType: hard + +"jest-diff@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-diff@npm:29.7.0" + dependencies: + chalk: ^4.0.0 + diff-sequences: ^29.6.3 + jest-get-type: ^29.6.3 + pretty-format: ^29.7.0 + checksum: 08e24a9dd43bfba1ef07a6374e5af138f53137b79ec3d5cc71a2303515335898888fa5409959172e1e05de966c9e714368d15e8994b0af7441f0721ee8e1bb77 + languageName: node + linkType: hard + +"jest-docblock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-docblock@npm:29.7.0" + dependencies: + detect-newline: ^3.0.0 + checksum: 66390c3e9451f8d96c5da62f577a1dad701180cfa9b071c5025acab2f94d7a3efc2515cfa1654ebe707213241541ce9c5530232cdc8017c91ed64eea1bd3b192 + languageName: node + linkType: hard + +"jest-each@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-each@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + chalk: ^4.0.0 + jest-get-type: ^29.6.3 + jest-util: ^29.7.0 + pretty-format: ^29.7.0 + checksum: e88f99f0184000fc8813f2a0aa79e29deeb63700a3b9b7928b8a418d7d93cd24933608591dbbdea732b473eb2021c72991b5cc51a17966842841c6e28e6f691c + languageName: node + linkType: hard + +"jest-environment-node@npm:^29.6.3, jest-environment-node@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-environment-node@npm:29.7.0" + dependencies: + "@jest/environment": ^29.7.0 + "@jest/fake-timers": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + jest-mock: ^29.7.0 + jest-util: ^29.7.0 + checksum: 501a9966292cbe0ca3f40057a37587cb6def25e1e0c5e39ac6c650fe78d3c70a2428304341d084ac0cced5041483acef41c477abac47e9a290d5545fd2f15646 + languageName: node + linkType: hard + +"jest-get-type@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-get-type@npm:29.6.3" + checksum: 88ac9102d4679d768accae29f1e75f592b760b44277df288ad76ce5bf038c3f5ce3719dea8aa0f035dac30e9eb034b848ce716b9183ad7cc222d029f03e92205 + languageName: node + linkType: hard + +"jest-haste-map@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-haste-map@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + "@types/graceful-fs": ^4.1.3 + "@types/node": "*" + anymatch: ^3.0.3 + fb-watchman: ^2.0.0 + fsevents: ^2.3.2 + graceful-fs: ^4.2.9 + jest-regex-util: ^29.6.3 + jest-util: ^29.7.0 + jest-worker: ^29.7.0 + micromatch: ^4.0.4 + walker: ^1.0.8 + dependenciesMeta: + fsevents: + optional: true + checksum: c2c8f2d3e792a963940fbdfa563ce14ef9e14d4d86da645b96d3cd346b8d35c5ce0b992ee08593939b5f718cf0a1f5a90011a056548a1dbf58397d4356786f01 + languageName: node + linkType: hard + +"jest-leak-detector@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-leak-detector@npm:29.7.0" + dependencies: + jest-get-type: ^29.6.3 + pretty-format: ^29.7.0 + checksum: e3950e3ddd71e1d0c22924c51a300a1c2db6cf69ec1e51f95ccf424bcc070f78664813bef7aed4b16b96dfbdeea53fe358f8aeaaea84346ae15c3735758f1605 + languageName: node + linkType: hard + +"jest-matcher-utils@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-matcher-utils@npm:29.7.0" + dependencies: + chalk: ^4.0.0 + jest-diff: ^29.7.0 + jest-get-type: ^29.6.3 + pretty-format: ^29.7.0 + checksum: d7259e5f995d915e8a37a8fd494cb7d6af24cd2a287b200f831717ba0d015190375f9f5dc35393b8ba2aae9b2ebd60984635269c7f8cff7d85b077543b7744cd + languageName: node + linkType: hard + +"jest-message-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-message-util@npm:29.7.0" + dependencies: + "@babel/code-frame": ^7.12.13 + "@jest/types": ^29.6.3 + "@types/stack-utils": ^2.0.0 + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + micromatch: ^4.0.4 + pretty-format: ^29.7.0 + slash: ^3.0.0 + stack-utils: ^2.0.3 + checksum: a9d025b1c6726a2ff17d54cc694de088b0489456c69106be6b615db7a51b7beb66788bea7a59991a019d924fbf20f67d085a445aedb9a4d6760363f4d7d09930 + languageName: node + linkType: hard + +"jest-mock@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-mock@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + "@types/node": "*" + jest-util: ^29.7.0 + checksum: 81ba9b68689a60be1482212878973700347cb72833c5e5af09895882b9eb5c4e02843a1bbdf23f94c52d42708bab53a30c45a3482952c9eec173d1eaac5b86c5 + languageName: node + linkType: hard + +"jest-pnp-resolver@npm:^1.2.2": + version: 1.2.3 + resolution: "jest-pnp-resolver@npm:1.2.3" + peerDependencies: + jest-resolve: "*" + peerDependenciesMeta: + jest-resolve: + optional: true + checksum: db1a8ab2cb97ca19c01b1cfa9a9c8c69a143fde833c14df1fab0766f411b1148ff0df878adea09007ac6a2085ec116ba9a996a6ad104b1e58c20adbf88eed9b2 + languageName: node + linkType: hard + +"jest-regex-util@npm:^29.6.3": + version: 29.6.3 + resolution: "jest-regex-util@npm:29.6.3" + checksum: 0518beeb9bf1228261695e54f0feaad3606df26a19764bc19541e0fc6e2a3737191904607fb72f3f2ce85d9c16b28df79b7b1ec9443aa08c3ef0e9efda6f8f2a + languageName: node + linkType: hard + +"jest-resolve-dependencies@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve-dependencies@npm:29.7.0" + dependencies: + jest-regex-util: ^29.6.3 + jest-snapshot: ^29.7.0 + checksum: aeb75d8150aaae60ca2bb345a0d198f23496494677cd6aefa26fc005faf354061f073982175daaf32b4b9d86b26ca928586344516e3e6969aa614cb13b883984 + languageName: node + linkType: hard + +"jest-resolve@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-resolve@npm:29.7.0" + dependencies: + chalk: ^4.0.0 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.7.0 + jest-pnp-resolver: ^1.2.2 + jest-util: ^29.7.0 + jest-validate: ^29.7.0 + resolve: ^1.20.0 + resolve.exports: ^2.0.0 + slash: ^3.0.0 + checksum: 0ca218e10731aa17920526ec39deaec59ab9b966237905ffc4545444481112cd422f01581230eceb7e82d86f44a543d520a71391ec66e1b4ef1a578bd5c73487 + languageName: node + linkType: hard + +"jest-runner@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runner@npm:29.7.0" + dependencies: + "@jest/console": ^29.7.0 + "@jest/environment": ^29.7.0 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + emittery: ^0.13.1 + graceful-fs: ^4.2.9 + jest-docblock: ^29.7.0 + jest-environment-node: ^29.7.0 + jest-haste-map: ^29.7.0 + jest-leak-detector: ^29.7.0 + jest-message-util: ^29.7.0 + jest-resolve: ^29.7.0 + jest-runtime: ^29.7.0 + jest-util: ^29.7.0 + jest-watcher: ^29.7.0 + jest-worker: ^29.7.0 + p-limit: ^3.1.0 + source-map-support: 0.5.13 + checksum: f0405778ea64812bf9b5c50b598850d94ccf95d7ba21f090c64827b41decd680ee19fcbb494007cdd7f5d0d8906bfc9eceddd8fa583e753e736ecd462d4682fb + languageName: node + linkType: hard + +"jest-runtime@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-runtime@npm:29.7.0" + dependencies: + "@jest/environment": ^29.7.0 + "@jest/fake-timers": ^29.7.0 + "@jest/globals": ^29.7.0 + "@jest/source-map": ^29.6.3 + "@jest/test-result": ^29.7.0 + "@jest/transform": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + cjs-module-lexer: ^1.0.0 + collect-v8-coverage: ^1.0.0 + glob: ^7.1.3 + graceful-fs: ^4.2.9 + jest-haste-map: ^29.7.0 + jest-message-util: ^29.7.0 + jest-mock: ^29.7.0 + jest-regex-util: ^29.6.3 + jest-resolve: ^29.7.0 + jest-snapshot: ^29.7.0 + jest-util: ^29.7.0 + slash: ^3.0.0 + strip-bom: ^4.0.0 + checksum: d19f113d013e80691e07047f68e1e3448ef024ff2c6b586ce4f90cd7d4c62a2cd1d460110491019719f3c59bfebe16f0e201ed005ef9f80e2cf798c374eed54e + languageName: node + linkType: hard + +"jest-snapshot@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-snapshot@npm:29.7.0" + dependencies: + "@babel/core": ^7.11.6 + "@babel/generator": ^7.7.2 + "@babel/plugin-syntax-jsx": ^7.7.2 + "@babel/plugin-syntax-typescript": ^7.7.2 + "@babel/types": ^7.3.3 + "@jest/expect-utils": ^29.7.0 + "@jest/transform": ^29.7.0 + "@jest/types": ^29.6.3 + babel-preset-current-node-syntax: ^1.0.0 + chalk: ^4.0.0 + expect: ^29.7.0 + graceful-fs: ^4.2.9 + jest-diff: ^29.7.0 + jest-get-type: ^29.6.3 + jest-matcher-utils: ^29.7.0 + jest-message-util: ^29.7.0 + jest-util: ^29.7.0 + natural-compare: ^1.4.0 + pretty-format: ^29.7.0 + semver: ^7.5.3 + checksum: 86821c3ad0b6899521ce75ee1ae7b01b17e6dfeff9166f2cf17f012e0c5d8c798f30f9e4f8f7f5bed01ea7b55a6bc159f5eda778311162cbfa48785447c237ad + languageName: node + linkType: hard + +"jest-util@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-util@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + "@types/node": "*" + chalk: ^4.0.0 + ci-info: ^3.2.0 + graceful-fs: ^4.2.9 + picomatch: ^2.2.3 + checksum: 042ab4980f4ccd4d50226e01e5c7376a8556b472442ca6091a8f102488c0f22e6e8b89ea874111d2328a2080083bf3225c86f3788c52af0bd0345a00eb57a3ca + languageName: node + linkType: hard + +"jest-validate@npm:^29.6.3, jest-validate@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-validate@npm:29.7.0" + dependencies: + "@jest/types": ^29.6.3 + camelcase: ^6.2.0 + chalk: ^4.0.0 + jest-get-type: ^29.6.3 + leven: ^3.1.0 + pretty-format: ^29.7.0 + checksum: 191fcdc980f8a0de4dbdd879fa276435d00eb157a48683af7b3b1b98b0f7d9de7ffe12689b617779097ff1ed77601b9f7126b0871bba4f776e222c40f62e9dae + languageName: node + linkType: hard + +"jest-watcher@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-watcher@npm:29.7.0" + dependencies: + "@jest/test-result": ^29.7.0 + "@jest/types": ^29.6.3 + "@types/node": "*" + ansi-escapes: ^4.2.1 + chalk: ^4.0.0 + emittery: ^0.13.1 + jest-util: ^29.7.0 + string-length: ^4.0.1 + checksum: 67e6e7fe695416deff96b93a14a561a6db69389a0667e9489f24485bb85e5b54e12f3b2ba511ec0b777eca1e727235b073e3ebcdd473d68888650489f88df92f + languageName: node + linkType: hard + +"jest-worker@npm:^29.6.3, jest-worker@npm:^29.7.0": + version: 29.7.0 + resolution: "jest-worker@npm:29.7.0" + dependencies: + "@types/node": "*" + jest-util: ^29.7.0 + merge-stream: ^2.0.0 + supports-color: ^8.0.0 + checksum: 30fff60af49675273644d408b650fc2eb4b5dcafc5a0a455f238322a8f9d8a98d847baca9d51ff197b6747f54c7901daa2287799230b856a0f48287d131f8c13 + languageName: node + linkType: hard + +"jest@npm:^29.7.0": + version: 29.7.0 + resolution: "jest@npm:29.7.0" + dependencies: + "@jest/core": ^29.7.0 + "@jest/types": ^29.6.3 + import-local: ^3.0.2 + jest-cli: ^29.7.0 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 17ca8d67504a7dbb1998cf3c3077ec9031ba3eb512da8d71cb91bcabb2b8995c4e4b292b740cb9bf1cbff5ce3e110b3f7c777b0cefb6f41ab05445f248d0ee0b + languageName: node + linkType: hard + +"joi@npm:^17.2.1": + version: 17.11.0 + resolution: "joi@npm:17.11.0" + dependencies: + "@hapi/hoek": ^9.0.0 + "@hapi/topo": ^5.0.0 + "@sideway/address": ^4.1.3 + "@sideway/formula": ^3.0.1 + "@sideway/pinpoint": ^2.0.0 + checksum: 3a4e9ecba345cdafe585e7ed8270a44b39718e11dff3749aa27e0001a63d578b75100c062be28e6f48f960b594864034e7a13833f33fbd7ad56d5ce6b617f9bf + languageName: node + linkType: hard + +"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": + version: 4.0.0 + resolution: "js-tokens@npm:4.0.0" + checksum: 8a95213a5a77deb6cbe94d86340e8d9ace2b93bc367790b260101d2f36a2eaf4e4e22d9fa9cf459b38af3a32fb4190e638024cf82ec95ef708680e405ea7cc78 + languageName: node + linkType: hard + +"js-yaml@npm:^3.13.1": + version: 3.14.1 + resolution: "js-yaml@npm:3.14.1" + dependencies: + argparse: ^1.0.7 + esprima: ^4.0.0 + bin: + js-yaml: bin/js-yaml.js + checksum: bef146085f472d44dee30ec34e5cf36bf89164f5d585435a3d3da89e52622dff0b188a580e4ad091c3341889e14cb88cac6e4deb16dc5b1e9623bb0601fc255c + languageName: node + linkType: hard + +"js-yaml@npm:^4.1.0": + version: 4.1.0 + resolution: "js-yaml@npm:4.1.0" + dependencies: + argparse: ^2.0.1 + bin: + js-yaml: bin/js-yaml.js + checksum: c7830dfd456c3ef2c6e355cc5a92e6700ceafa1d14bba54497b34a99f0376cecbb3e9ac14d3e5849b426d5a5140709a66237a8c991c675431271c4ce5504151a + languageName: node + linkType: hard + +"jsc-android@npm:^250231.0.0": + version: 250231.0.0 + resolution: "jsc-android@npm:250231.0.0" + checksum: 6c3f0f6f02fa37a19935b2fbe651e9d6ecc370eb30f2ecee76379337bbf084abb568a1ef1133fe622c5b76f43cf54bb7716f92a94dca010985da38edc48841e2 + languageName: node + linkType: hard + +"jsc-safe-url@npm:^0.2.2": + version: 0.2.4 + resolution: "jsc-safe-url@npm:0.2.4" + checksum: 53b5741ba2c0a54da1722929dc80becb2c6fcc9525124fb6c2aec1a00f48e79afffd26816c278111e7b938e37ace029e33cbb8cdaa4ac1f528a87e58022284af + languageName: node + linkType: hard + +"jscodeshift@npm:^0.14.0": + version: 0.14.0 + resolution: "jscodeshift@npm:0.14.0" + dependencies: + "@babel/core": ^7.13.16 + "@babel/parser": ^7.13.16 + "@babel/plugin-proposal-class-properties": ^7.13.0 + "@babel/plugin-proposal-nullish-coalescing-operator": ^7.13.8 + "@babel/plugin-proposal-optional-chaining": ^7.13.12 + "@babel/plugin-transform-modules-commonjs": ^7.13.8 + "@babel/preset-flow": ^7.13.13 + "@babel/preset-typescript": ^7.13.0 + "@babel/register": ^7.13.16 + babel-core: ^7.0.0-bridge.0 + chalk: ^4.1.2 + flow-parser: 0.* + graceful-fs: ^4.2.4 + micromatch: ^4.0.4 + neo-async: ^2.5.0 + node-dir: ^0.1.17 + recast: ^0.21.0 + temp: ^0.8.4 + write-file-atomic: ^2.3.0 + peerDependencies: + "@babel/preset-env": ^7.1.6 + bin: + jscodeshift: bin/jscodeshift.js + checksum: 54ea6d639455883336f80b38a70648821c88b7942315dc0fbab01bc34a9ad0f0f78e3bd69304b5ab167e4262d6ed7e6284c6d32525ab01c89d9118df89b3e2a0 + languageName: node + linkType: hard + +"jsesc@npm:^2.5.1": + version: 2.5.2 + resolution: "jsesc@npm:2.5.2" + bin: + jsesc: bin/jsesc + checksum: 4dc190771129e12023f729ce20e1e0bfceac84d73a85bc3119f7f938843fe25a4aeccb54b6494dce26fcf263d815f5f31acdefac7cc9329efb8422a4f4d9fa9d + languageName: node + linkType: hard + +"jsesc@npm:~0.5.0": + version: 0.5.0 + resolution: "jsesc@npm:0.5.0" + bin: + jsesc: bin/jsesc + checksum: b8b44cbfc92f198ad972fba706ee6a1dfa7485321ee8c0b25f5cedd538dcb20cde3197de16a7265430fce8277a12db066219369e3d51055038946039f6e20e17 + languageName: node + linkType: hard + +"json-buffer@npm:3.0.1": + version: 3.0.1 + resolution: "json-buffer@npm:3.0.1" + checksum: 9026b03edc2847eefa2e37646c579300a1f3a4586cfb62bf857832b60c852042d0d6ae55d1afb8926163fa54c2b01d83ae24705f34990348bdac6273a29d4581 + languageName: node + linkType: hard + +"json-parse-better-errors@npm:^1.0.1": + version: 1.0.2 + resolution: "json-parse-better-errors@npm:1.0.2" + checksum: ff2b5ba2a70e88fd97a3cb28c1840144c5ce8fae9cbeeddba15afa333a5c407cf0e42300cd0a2885dbb055227fe68d405070faad941beeffbfde9cf3b2c78c5d + languageName: node + linkType: hard + +"json-parse-even-better-errors@npm:^2.3.0": + version: 2.3.1 + resolution: "json-parse-even-better-errors@npm:2.3.1" + checksum: 798ed4cf3354a2d9ccd78e86d2169515a0097a5c133337807cdf7f1fc32e1391d207ccfc276518cc1d7d8d4db93288b8a50ba4293d212ad1336e52a8ec0a941f + languageName: node + linkType: hard + +"json-schema-traverse@npm:^0.4.1": + version: 0.4.1 + resolution: "json-schema-traverse@npm:0.4.1" + checksum: 7486074d3ba247769fda17d5181b345c9fb7d12e0da98b22d1d71a5db9698d8b4bd900a3ec1a4ffdd60846fc2556274a5c894d0c48795f14cb03aeae7b55260b + languageName: node + linkType: hard + +"json-stable-stringify-without-jsonify@npm:^1.0.1": + version: 1.0.1 + resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" + checksum: cff44156ddce9c67c44386ad5cddf91925fe06b1d217f2da9c4910d01f358c6e3989c4d5a02683c7a5667f9727ff05831f7aa8ae66c8ff691c556f0884d49215 + languageName: node + linkType: hard + +"json5@npm:^2.2.3": + version: 2.2.3 + resolution: "json5@npm:2.2.3" + bin: + json5: lib/cli.js + checksum: 2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349 + languageName: node + linkType: hard + +"jsonfile@npm:^4.0.0": + version: 4.0.0 + resolution: "jsonfile@npm:4.0.0" + dependencies: + graceful-fs: ^4.1.6 + dependenciesMeta: + graceful-fs: + optional: true + checksum: 6447d6224f0d31623eef9b51185af03ac328a7553efcee30fa423d98a9e276ca08db87d71e17f2310b0263fd3ffa6c2a90a6308367f661dc21580f9469897c9e + languageName: node + linkType: hard + +"jsx-ast-utils@npm:^2.4.1 || ^3.0.0": + version: 3.3.5 + resolution: "jsx-ast-utils@npm:3.3.5" + dependencies: + array-includes: ^3.1.6 + array.prototype.flat: ^1.3.1 + object.assign: ^4.1.4 + object.values: ^1.1.6 + checksum: f4b05fa4d7b5234230c905cfa88d36dc8a58a6666975a3891429b1a8cdc8a140bca76c297225cb7a499fad25a2c052ac93934449a2c31a44fc9edd06c773780a + languageName: node + linkType: hard + +"keyv@npm:^4.5.3": + version: 4.5.4 + resolution: "keyv@npm:4.5.4" + dependencies: + json-buffer: 3.0.1 + checksum: 74a24395b1c34bd44ad5cb2b49140d087553e170625240b86755a6604cd65aa16efdbdeae5cdb17ba1284a0fbb25ad06263755dbc71b8d8b06f74232ce3cdd72 + languageName: node + linkType: hard + +"kind-of@npm:^6.0.2": + version: 6.0.3 + resolution: "kind-of@npm:6.0.3" + checksum: 3ab01e7b1d440b22fe4c31f23d8d38b4d9b91d9f291df683476576493d5dfd2e03848a8b05813dd0c3f0e835bc63f433007ddeceb71f05cb25c45ae1b19c6d3b + languageName: node + linkType: hard + +"kleur@npm:^3.0.3": + version: 3.0.3 + resolution: "kleur@npm:3.0.3" + checksum: df82cd1e172f957bae9c536286265a5cdbd5eeca487cb0a3b2a7b41ef959fc61f8e7c0e9aeea9c114ccf2c166b6a8dd45a46fd619c1c569d210ecd2765ad5169 + languageName: node + linkType: hard + +"leven@npm:^3.1.0": + version: 3.1.0 + resolution: "leven@npm:3.1.0" + checksum: 638401d534585261b6003db9d99afd244dfe82d75ddb6db5c0df412842d5ab30b2ef18de471aaec70fe69a46f17b4ae3c7f01d8a4e6580ef7adb9f4273ad1e55 + languageName: node + linkType: hard + +"levn@npm:^0.4.1": + version: 0.4.1 + resolution: "levn@npm:0.4.1" + dependencies: + prelude-ls: ^1.2.1 + type-check: ~0.4.0 + checksum: 12c5021c859bd0f5248561bf139121f0358285ec545ebf48bb3d346820d5c61a4309535c7f387ed7d84361cf821e124ce346c6b7cef8ee09a67c1473b46d0fc4 + languageName: node + linkType: hard + +"lighthouse-logger@npm:^1.0.0": + version: 1.4.2 + resolution: "lighthouse-logger@npm:1.4.2" + dependencies: + debug: ^2.6.9 + marky: ^1.2.2 + checksum: ba6b73d93424318fab58b4e07c9ed246e3e969a3313f26b69515ed4c06457dd9a0b11bc706948398fdaef26aa4ba5e65cb848c37ce59f470d3c6c450b9b79a33 + languageName: node + linkType: hard + +"lines-and-columns@npm:^1.1.6": + version: 1.2.4 + resolution: "lines-and-columns@npm:1.2.4" + checksum: 0c37f9f7fa212b38912b7145e1cd16a5f3cd34d782441c3e6ca653485d326f58b3caccda66efce1c5812bde4961bbde3374fae4b0d11bf1226152337f3894aa5 + languageName: node + linkType: hard + +"locate-path@npm:^3.0.0": + version: 3.0.0 + resolution: "locate-path@npm:3.0.0" + dependencies: + p-locate: ^3.0.0 + path-exists: ^3.0.0 + checksum: 53db3996672f21f8b0bf2a2c645ae2c13ffdae1eeecfcd399a583bce8516c0b88dcb4222ca6efbbbeb6949df7e46860895be2c02e8d3219abd373ace3bfb4e11 + languageName: node + linkType: hard + +"locate-path@npm:^5.0.0": + version: 5.0.0 + resolution: "locate-path@npm:5.0.0" + dependencies: + p-locate: ^4.1.0 + checksum: 83e51725e67517287d73e1ded92b28602e3ae5580b301fe54bfb76c0c723e3f285b19252e375712316774cf52006cb236aed5704692c32db0d5d089b69696e30 + languageName: node + linkType: hard + +"locate-path@npm:^6.0.0": + version: 6.0.0 + resolution: "locate-path@npm:6.0.0" + dependencies: + p-locate: ^5.0.0 + checksum: 72eb661788a0368c099a184c59d2fee760b3831c9c1c33955e8a19ae4a21b4116e53fa736dc086cdeb9fce9f7cc508f2f92d2d3aae516f133e16a2bb59a39f5a + languageName: node + linkType: hard + +"lodash.debounce@npm:^4.0.8": + version: 4.0.8 + resolution: "lodash.debounce@npm:4.0.8" + checksum: a3f527d22c548f43ae31c861ada88b2637eb48ac6aa3eb56e82d44917971b8aa96fbb37aa60efea674dc4ee8c42074f90f7b1f772e9db375435f6c83a19b3bc6 + languageName: node + linkType: hard + +"lodash.merge@npm:^4.6.2": + version: 4.6.2 + resolution: "lodash.merge@npm:4.6.2" + checksum: ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005 + languageName: node + linkType: hard + +"lodash.throttle@npm:^4.1.1": + version: 4.1.1 + resolution: "lodash.throttle@npm:4.1.1" + checksum: 129c0a28cee48b348aef146f638ef8a8b197944d4e9ec26c1890c19d9bf5a5690fe11b655c77a4551268819b32d27f4206343e30c78961f60b561b8608c8c805 + languageName: node + linkType: hard + +"lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 + languageName: node + linkType: hard + +"log-symbols@npm:^4.1.0": + version: 4.1.0 + resolution: "log-symbols@npm:4.1.0" + dependencies: + chalk: ^4.1.0 + is-unicode-supported: ^0.1.0 + checksum: fce1497b3135a0198803f9f07464165e9eb83ed02ceb2273930a6f8a508951178d8cf4f0378e9d28300a2ed2bc49050995d2bd5f53ab716bb15ac84d58c6ef74 + languageName: node + linkType: hard + +"logkitty@npm:^0.7.1": + version: 0.7.1 + resolution: "logkitty@npm:0.7.1" + dependencies: + ansi-fragments: ^0.2.1 + dayjs: ^1.8.15 + yargs: ^15.1.0 + bin: + logkitty: bin/logkitty.js + checksum: f1af990ff09564ef5122597a52bba6d233302c49865e6ddea1343d2a0e2efe3005127e58e93e25c98b6b1f192731fc5c52e3204876a15fc9a52abc8b4f1af931 + languageName: node + linkType: hard + +"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.4.0": + version: 1.4.0 + resolution: "loose-envify@npm:1.4.0" + dependencies: + js-tokens: ^3.0.0 || ^4.0.0 + bin: + loose-envify: cli.js + checksum: 6517e24e0cad87ec9888f500c5b5947032cdfe6ef65e1c1936a0c48a524b81e65542c9c3edc91c97d5bddc806ee2a985dbc79be89215d613b1de5db6d1cfe6f4 + languageName: node + linkType: hard + +"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.1.0 + resolution: "lru-cache@npm:10.1.0" + checksum: 58056d33e2500fbedce92f8c542e7c11b50d7d086578f14b7074d8c241422004af0718e08a6eaae8705cee09c77e39a61c1c79e9370ba689b7010c152e6a76ab + languageName: node + linkType: hard + +"lru-cache@npm:^5.1.1": + version: 5.1.1 + resolution: "lru-cache@npm:5.1.1" + dependencies: + yallist: ^3.0.2 + checksum: c154ae1cbb0c2206d1501a0e94df349653c92c8cbb25236d7e85190bcaf4567a03ac6eb43166fabfa36fd35623694da7233e88d9601fbf411a9a481d85dbd2cb + languageName: node + linkType: hard + +"lru-cache@npm:^6.0.0": + version: 6.0.0 + resolution: "lru-cache@npm:6.0.0" + dependencies: + yallist: ^4.0.0 + checksum: f97f499f898f23e4585742138a22f22526254fdba6d75d41a1c2526b3b6cc5747ef59c5612ba7375f42aca4f8461950e925ba08c991ead0651b4918b7c978297 + languageName: node + linkType: hard + +"make-dir@npm:^2.0.0, make-dir@npm:^2.1.0": + version: 2.1.0 + resolution: "make-dir@npm:2.1.0" + dependencies: + pify: ^4.0.1 + semver: ^5.6.0 + checksum: 043548886bfaf1820323c6a2997e6d2fa51ccc2586ac14e6f14634f7458b4db2daf15f8c310e2a0abd3e0cddc64df1890d8fc7263033602c47bb12cbfcf86aab + languageName: node + linkType: hard + +"make-dir@npm:^4.0.0": + version: 4.0.0 + resolution: "make-dir@npm:4.0.0" + dependencies: + semver: ^7.5.3 + checksum: bf0731a2dd3aab4db6f3de1585cea0b746bb73eb5a02e3d8d72757e376e64e6ada190b1eddcde5b2f24a81b688a9897efd5018737d05e02e2a671dda9cff8a8a + languageName: node + linkType: hard + +"make-error@npm:^1.1.1": + version: 1.3.6 + resolution: "make-error@npm:1.3.6" + checksum: b86e5e0e25f7f777b77fabd8e2cbf15737972869d852a22b7e73c17623928fccb826d8e46b9951501d3f20e51ad74ba8c59ed584f610526a48f8ccf88aaec402 + languageName: node + linkType: hard + +"make-fetch-happen@npm:^13.0.0": + version: 13.0.0 + resolution: "make-fetch-happen@npm:13.0.0" + dependencies: + "@npmcli/agent": ^2.0.0 + cacache: ^18.0.0 + http-cache-semantics: ^4.1.1 + is-lambda: ^1.0.1 + minipass: ^7.0.2 + minipass-fetch: ^3.0.0 + minipass-flush: ^1.0.5 + minipass-pipeline: ^1.2.4 + negotiator: ^0.6.3 + promise-retry: ^2.0.1 + ssri: ^10.0.0 + checksum: 7c7a6d381ce919dd83af398b66459a10e2fe8f4504f340d1d090d3fa3d1b0c93750220e1d898114c64467223504bd258612ba83efbc16f31b075cd56de24b4af + languageName: node + linkType: hard + +"makeerror@npm:1.0.12": + version: 1.0.12 + resolution: "makeerror@npm:1.0.12" + dependencies: + tmpl: 1.0.5 + checksum: b38a025a12c8146d6eeea5a7f2bf27d51d8ad6064da8ca9405fcf7bf9b54acd43e3b30ddd7abb9b1bfa4ddb266019133313482570ddb207de568f71ecfcf6060 + languageName: node + linkType: hard + +"marky@npm:^1.2.2": + version: 1.2.5 + resolution: "marky@npm:1.2.5" + checksum: 823b946677749551cdfc3b5221685478b5d1b9cc0dc03eff977c6f9a615fb05c67559f9556cb3c0fcb941a9ea0e195e37befd83026443396ccee8b724f54f4c5 + languageName: node + linkType: hard + +"memoize-one@npm:^5.0.0": + version: 5.2.1 + resolution: "memoize-one@npm:5.2.1" + checksum: a3cba7b824ebcf24cdfcd234aa7f86f3ad6394b8d9be4c96ff756dafb8b51c7f71320785fbc2304f1af48a0467cbbd2a409efc9333025700ed523f254cb52e3d + languageName: node + linkType: hard + +"merge-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-stream@npm:2.0.0" + checksum: 6fa4dcc8d86629705cea944a4b88ef4cb0e07656ebf223fa287443256414283dd25d91c1cd84c77987f2aec5927af1a9db6085757cb43d90eb170ebf4b47f4f4 + languageName: node + linkType: hard + +"merge2@npm:^1.3.0, merge2@npm:^1.4.1": + version: 1.4.1 + resolution: "merge2@npm:1.4.1" + checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 + languageName: node + linkType: hard + +"metro-babel-transformer@npm:0.80.4": + version: 0.80.4 + resolution: "metro-babel-transformer@npm:0.80.4" + dependencies: + "@babel/core": ^7.20.0 + hermes-parser: 0.18.2 + nullthrows: ^1.1.1 + checksum: eee402bfc85b7fe1a9362bf5908bef3388ff62643102de5a36e02e0d07c6841c6250a43edc4068ce8b97fb6ce6b11eca91ab46fbf566265ba75bfc2a2d1c5804 + languageName: node + linkType: hard + +"metro-cache-key@npm:0.80.4": + version: 0.80.4 + resolution: "metro-cache-key@npm:0.80.4" + checksum: 674b0a1e570c35d05602eeef16dcbb6e7b80ae5d67d414db347a3214c0436afe142afaf1393f39651cbef9a54a095ac100ecf0a96a6e59f59536b06911bb78af + languageName: node + linkType: hard + +"metro-cache@npm:0.80.4": + version: 0.80.4 + resolution: "metro-cache@npm:0.80.4" + dependencies: + metro-core: 0.80.4 + rimraf: ^3.0.2 + checksum: 52be5695e4f043bbb0316121db020afa4a12ea2a65c7a090417daeda3dbed1e1ddcfa6f66d2526f6b6f0ee1bc22b7c7400eca1cb512af244dd85a16fdc082366 + languageName: node + linkType: hard + +"metro-config@npm:0.80.4, metro-config@npm:^0.80.3": + version: 0.80.4 + resolution: "metro-config@npm:0.80.4" + dependencies: + connect: ^3.6.5 + cosmiconfig: ^5.0.5 + jest-validate: ^29.6.3 + metro: 0.80.4 + metro-cache: 0.80.4 + metro-core: 0.80.4 + metro-runtime: 0.80.4 + checksum: 38c34da0ceeb0e9f6a3793f06ac4ea9bcc06bb4e48f1eff59befb469760f433e6f1fd8a35824eb547ae4413f8746ea1c4ef84d807e15148eba09de252c018459 + languageName: node + linkType: hard + +"metro-core@npm:0.80.4, metro-core@npm:^0.80.3": + version: 0.80.4 + resolution: "metro-core@npm:0.80.4" + dependencies: + lodash.throttle: ^4.1.1 + metro-resolver: 0.80.4 + checksum: e8789d047a55e9e2e5777d9aacdeaaf385153012d1eb7a832e68d3f69dfafc1757d24ee5747a39072f48c31e1b92fa126a57669adc74427f667ff1af6e24577e + languageName: node + linkType: hard + +"metro-file-map@npm:0.80.4": + version: 0.80.4 + resolution: "metro-file-map@npm:0.80.4" + dependencies: + anymatch: ^3.0.3 + debug: ^2.2.0 + fb-watchman: ^2.0.0 + fsevents: ^2.3.2 + graceful-fs: ^4.2.4 + invariant: ^2.2.4 + jest-worker: ^29.6.3 + micromatch: ^4.0.4 + node-abort-controller: ^3.1.1 + nullthrows: ^1.1.1 + walker: ^1.0.7 + dependenciesMeta: + fsevents: + optional: true + checksum: 624832cf02c41fe55b8977cf52b7bbd0c47b00953f9b2e8be6b6f0df7eac67e563795d3b1c39e2ee7265a30be141ffa0320f5dcc7d72db805857bfad71d44c95 + languageName: node + linkType: hard + +"metro-minify-terser@npm:0.80.4": + version: 0.80.4 + resolution: "metro-minify-terser@npm:0.80.4" + dependencies: + terser: ^5.15.0 + checksum: 1a8e3dcefce1c4a599e948641fee58cc03f4121371d50adb32af5f8fc3e62958c1a0d9d16a9179a9bab62b9e82c82f8cb5dfb8b517d37552f7de78dc7e0524bf + languageName: node + linkType: hard + +"metro-resolver@npm:0.80.4": + version: 0.80.4 + resolution: "metro-resolver@npm:0.80.4" + checksum: d56009e4ca9e8b0ce1bcb84891fbe98e5ca80a2f43e20a9bcdff565916503546646ed6eb9cb39c072cbb14de2e85acb978ccc9d19ada6a176fc95a7cfd84ee6b + languageName: node + linkType: hard + +"metro-runtime@npm:0.80.4, metro-runtime@npm:^0.80.3": + version: 0.80.4 + resolution: "metro-runtime@npm:0.80.4" + dependencies: + "@babel/runtime": ^7.0.0 + checksum: 9c6f56c809d60914123eb60b0be4e14428acb94ade70c2e2bf66cedb7d7bf455d2667ca96f9fdbf2fea34229f194dbee6bae3b2020fd4bfc06b8c796f36d4520 + languageName: node + linkType: hard + +"metro-source-map@npm:0.80.4, metro-source-map@npm:^0.80.3": + version: 0.80.4 + resolution: "metro-source-map@npm:0.80.4" + dependencies: + "@babel/traverse": ^7.20.0 + "@babel/types": ^7.20.0 + invariant: ^2.2.4 + metro-symbolicate: 0.80.4 + nullthrows: ^1.1.1 + ob1: 0.80.4 + source-map: ^0.5.6 + vlq: ^1.0.0 + checksum: 881cf9c15c4bedb0cf784ffbdb6e83a73b9c83171f6990f6a2955a8c4382e33bb4175f5989dcd81846636a476517a4db97cee4e1a3b9c8199c0e426926cc8f0f + languageName: node + linkType: hard + +"metro-symbolicate@npm:0.80.4": + version: 0.80.4 + resolution: "metro-symbolicate@npm:0.80.4" + dependencies: + invariant: ^2.2.4 + metro-source-map: 0.80.4 + nullthrows: ^1.1.1 + source-map: ^0.5.6 + through2: ^2.0.1 + vlq: ^1.0.0 + bin: + metro-symbolicate: src/index.js + checksum: 112c77c75b521e45c3e8c3e71e7b352293f892b7a3e2151df43ebf2d7c01165570031468ba40a9d6e0e632af35e3cc764caf5a054a5a4b28f8d24f9407ab7be6 + languageName: node + linkType: hard + +"metro-transform-plugins@npm:0.80.4": + version: 0.80.4 + resolution: "metro-transform-plugins@npm:0.80.4" + dependencies: + "@babel/core": ^7.20.0 + "@babel/generator": ^7.20.0 + "@babel/template": ^7.0.0 + "@babel/traverse": ^7.20.0 + nullthrows: ^1.1.1 + checksum: bcd3c6e08db2b8b0b3310dbe7f6163d79fc0408b42dfe85b1a2e97c8bd1a99e59d793cf97e9c0c959766dd3b0ccae12bd6adb73cc82e4fd66ebfdcc07957623c + languageName: node + linkType: hard + +"metro-transform-worker@npm:0.80.4": + version: 0.80.4 + resolution: "metro-transform-worker@npm:0.80.4" + dependencies: + "@babel/core": ^7.20.0 + "@babel/generator": ^7.20.0 + "@babel/parser": ^7.20.0 + "@babel/types": ^7.20.0 + metro: 0.80.4 + metro-babel-transformer: 0.80.4 + metro-cache: 0.80.4 + metro-cache-key: 0.80.4 + metro-source-map: 0.80.4 + metro-transform-plugins: 0.80.4 + nullthrows: ^1.1.1 + checksum: 8a6ec8d4b94edce5cda1f2a1e054f77372bc12db72d158c8c796abdd1bbc10409068a7100fa96d96c1566e208b86353b19c1ba657cefe467fc340881e5612747 + languageName: node + linkType: hard + +"metro@npm:0.80.4, metro@npm:^0.80.3": + version: 0.80.4 + resolution: "metro@npm:0.80.4" + dependencies: + "@babel/code-frame": ^7.0.0 + "@babel/core": ^7.20.0 + "@babel/generator": ^7.20.0 + "@babel/parser": ^7.20.0 + "@babel/template": ^7.0.0 + "@babel/traverse": ^7.20.0 + "@babel/types": ^7.20.0 + accepts: ^1.3.7 + chalk: ^4.0.0 + ci-info: ^2.0.0 + connect: ^3.6.5 + debug: ^2.2.0 + denodeify: ^1.2.1 + error-stack-parser: ^2.0.6 + graceful-fs: ^4.2.4 + hermes-parser: 0.18.2 + image-size: ^1.0.2 + invariant: ^2.2.4 + jest-worker: ^29.6.3 + jsc-safe-url: ^0.2.2 + lodash.throttle: ^4.1.1 + metro-babel-transformer: 0.80.4 + metro-cache: 0.80.4 + metro-cache-key: 0.80.4 + metro-config: 0.80.4 + metro-core: 0.80.4 + metro-file-map: 0.80.4 + metro-minify-terser: 0.80.4 + metro-resolver: 0.80.4 + metro-runtime: 0.80.4 + metro-source-map: 0.80.4 + metro-symbolicate: 0.80.4 + metro-transform-plugins: 0.80.4 + metro-transform-worker: 0.80.4 + mime-types: ^2.1.27 + node-fetch: ^2.2.0 + nullthrows: ^1.1.1 + rimraf: ^3.0.2 + serialize-error: ^2.1.0 + source-map: ^0.5.6 + strip-ansi: ^6.0.0 + throat: ^5.0.0 + ws: ^7.5.1 + yargs: ^17.6.2 + bin: + metro: src/cli.js + checksum: cb73294f3fc315e81e6b050e679d2ac8f28a245d16634eb43ef6ff9eb71b52526ce93b1bd372a4e489eee9ba6568422bddbb9e97f2559bbfd30b11c8f5b96471 + languageName: node + linkType: hard + +"micromatch@npm:^4.0.4": + version: 4.0.5 + resolution: "micromatch@npm:4.0.5" + dependencies: + braces: ^3.0.2 + picomatch: ^2.3.1 + checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc + languageName: node + linkType: hard + +"mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f + languageName: node + linkType: hard + +"mime-types@npm:^2.1.27, mime-types@npm:~2.1.34": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: 1.52.0 + checksum: 89a5b7f1def9f3af5dad6496c5ed50191ae4331cc5389d7c521c8ad28d5fdad2d06fd81baf38fed813dc4e46bb55c8145bb0ff406330818c9cf712fb2e9b3836 + languageName: node + linkType: hard + +"mime@npm:1.6.0": + version: 1.6.0 + resolution: "mime@npm:1.6.0" + bin: + mime: cli.js + checksum: fef25e39263e6d207580bdc629f8872a3f9772c923c7f8c7e793175cee22777bbe8bba95e5d509a40aaa292d8974514ce634ae35769faa45f22d17edda5e8557 + languageName: node + linkType: hard + +"mime@npm:^2.4.1": + version: 2.6.0 + resolution: "mime@npm:2.6.0" + bin: + mime: cli.js + checksum: 1497ba7b9f6960694268a557eae24b743fd2923da46ec392b042469f4b901721ba0adcf8b0d3c2677839d0e243b209d76e5edcbd09cfdeffa2dfb6bb4df4b862 + languageName: node + linkType: hard + +"mimic-fn@npm:^2.1.0": + version: 2.1.0 + resolution: "mimic-fn@npm:2.1.0" + checksum: d2421a3444848ce7f84bd49115ddacff29c15745db73f54041edc906c14b131a38d05298dae3081667627a59b2eb1ca4b436ff2e1b80f69679522410418b478a + languageName: node + linkType: hard + +"min-indent@npm:^1.0.0": + version: 1.0.1 + resolution: "min-indent@npm:1.0.1" + checksum: bfc6dd03c5eaf623a4963ebd94d087f6f4bbbfd8c41329a7f09706b0cb66969c4ddd336abeb587bc44bc6f08e13bf90f0b374f9d71f9f01e04adc2cd6f083ef1 + languageName: node + linkType: hard + +"minimatch@npm:9.0.3, minimatch@npm:^9.0.1": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" + dependencies: + brace-expansion: ^2.0.1 + checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 + languageName: node + linkType: hard + +"minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": + version: 3.1.2 + resolution: "minimatch@npm:3.1.2" + dependencies: + brace-expansion: ^1.1.7 + checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a + languageName: node + linkType: hard + +"minimist@npm:^1.2.6": + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 75a6d645fb122dad29c06a7597bddea977258957ed88d7a6df59b5cd3fe4a527e253e9bbf2e783e4b73657f9098b96a5fe96ab8a113655d4109108577ecf85b0 + languageName: node + linkType: hard + +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: ^7.0.3 + checksum: b251bceea62090f67a6cced7a446a36f4cd61ee2d5cea9aee7fff79ba8030e416327a1c5aa2908dc22629d06214b46d88fdab8c51ac76bacbf5703851b5ad342 + languageName: node + linkType: hard + +"minipass-fetch@npm:^3.0.0": + version: 3.0.4 + resolution: "minipass-fetch@npm:3.0.4" + dependencies: + encoding: ^0.1.13 + minipass: ^7.0.3 + minipass-sized: ^1.0.3 + minizlib: ^2.1.2 + dependenciesMeta: + encoding: + optional: true + checksum: af7aad15d5c128ab1ebe52e043bdf7d62c3c6f0cecb9285b40d7b395e1375b45dcdfd40e63e93d26a0e8249c9efd5c325c65575aceee192883970ff8cb11364a + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: ^3.0.0 + checksum: 56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: ^3.0.0 + checksum: b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: ^3.0.0 + checksum: 79076749fcacf21b5d16dd596d32c3b6bf4d6e62abb43868fac21674078505c8b15eaca4e47ed844985a4514854f917d78f588fcd029693709417d8f98b2bd60 + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: ^4.0.0 + checksum: a30d083c8054cee83cdcdc97f97e4641a3f58ae743970457b1489ce38ee1167b3aaf7d815cd39ec7a99b9c40397fd4f686e83750e73e652b21cb516f6d845e48 + languageName: node + linkType: hard + +"minipass@npm:^5.0.0": + version: 5.0.0 + resolution: "minipass@npm:5.0.0" + checksum: 425dab288738853fded43da3314a0b5c035844d6f3097a8e3b5b29b328da8f3c1af6fc70618b32c29ff906284cf6406b6841376f21caaadd0793c1d5a6a620ea + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3": + version: 7.0.4 + resolution: "minipass@npm:7.0.4" + checksum: 87585e258b9488caf2e7acea242fd7856bbe9a2c84a7807643513a338d66f368c7d518200ad7b70a508664d408aa000517647b2930c259a8b1f9f0984f344a21 + languageName: node + linkType: hard + +"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2": + version: 2.1.2 + resolution: "minizlib@npm:2.1.2" + dependencies: + minipass: ^3.0.0 + yallist: ^4.0.0 + checksum: f1fdeac0b07cf8f30fcf12f4b586795b97be856edea22b5e9072707be51fc95d41487faec3f265b42973a304fe3a64acd91a44a3826a963e37b37bafde0212c3 + languageName: node + linkType: hard + +"mkdirp@npm:^0.5.1": + version: 0.5.6 + resolution: "mkdirp@npm:0.5.6" + dependencies: + minimist: ^1.2.6 + bin: + mkdirp: bin/cmd.js + checksum: 0c91b721bb12c3f9af4b77ebf73604baf350e64d80df91754dc509491ae93bf238581e59c7188360cec7cb62fc4100959245a42cfe01834efedc5e9d068376c2 + languageName: node + linkType: hard + +"mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": + version: 1.0.4 + resolution: "mkdirp@npm:1.0.4" + bin: + mkdirp: bin/cmd.js + checksum: a96865108c6c3b1b8e1d5e9f11843de1e077e57737602de1b82030815f311be11f96f09cce59bd5b903d0b29834733e5313f9301e3ed6d6f6fba2eae0df4298f + languageName: node + linkType: hard + +"ms@npm:2.0.0": + version: 2.0.0 + resolution: "ms@npm:2.0.0" + checksum: 0e6a22b8b746d2e0b65a430519934fefd41b6db0682e3477c10f60c76e947c4c0ad06f63ffdf1d78d335f83edee8c0aa928aa66a36c7cd95b69b26f468d527f4 + languageName: node + linkType: hard + +"ms@npm:2.1.2": + version: 2.1.2 + resolution: "ms@npm:2.1.2" + checksum: 673cdb2c3133eb050c745908d8ce632ed2c02d85640e2edb3ace856a2266a813b30c613569bf3354fdf4ea7d1a1494add3bfa95e2713baa27d0c2c71fc44f58f + languageName: node + linkType: hard + +"ms@npm:2.1.3": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d + languageName: node + linkType: hard + +"natural-compare@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare@npm:1.4.0" + checksum: 23ad088b08f898fc9b53011d7bb78ec48e79de7627e01ab5518e806033861bef68d5b0cd0e2205c2f36690ac9571ff6bcb05eb777ced2eeda8d4ac5b44592c3d + languageName: node + linkType: hard + +"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 + languageName: node + linkType: hard + +"neo-async@npm:^2.5.0": + version: 2.6.2 + resolution: "neo-async@npm:2.6.2" + checksum: deac9f8d00eda7b2e5cd1b2549e26e10a0faa70adaa6fdadca701cc55f49ee9018e427f424bac0c790b7c7e2d3068db97f3093f1093975f2acb8f8818b936ed9 + languageName: node + linkType: hard + +"nocache@npm:^3.0.1": + version: 3.0.4 + resolution: "nocache@npm:3.0.4" + checksum: 6be9ee67eb561ecedc56d805c024c0fda55b9836ecba659c720073b067929aa4fe04bb7121480e004c9cf52989e62d8720f29a7fe0269f1a4941221a1e4be1c2 + languageName: node + linkType: hard + +"node-abort-controller@npm:^3.1.1": + version: 3.1.1 + resolution: "node-abort-controller@npm:3.1.1" + checksum: 2c340916af9710328b11c0828223fc65ba320e0d082214a211311bf64c2891028e42ef276b9799188c4ada9e6e1c54cf7a0b7c05dd9d59fcdc8cd633304c8047 + languageName: node + linkType: hard + +"node-dir@npm:^0.1.17": + version: 0.1.17 + resolution: "node-dir@npm:0.1.17" + dependencies: + minimatch: ^3.0.2 + checksum: 29de9560e52cdac8d3f794d38d782f6799e13d4d11aaf96d3da8c28458e1c5e33bb5f8edfb42dc34172ec5516c50c5b8850c9e1526542616757a969267263328 + languageName: node + linkType: hard + +"node-fetch@npm:^2.2.0, node-fetch@npm:^2.6.0": + version: 2.7.0 + resolution: "node-fetch@npm:2.7.0" + dependencies: + whatwg-url: ^5.0.0 + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: d76d2f5edb451a3f05b15115ec89fc6be39de37c6089f1b6368df03b91e1633fd379a7e01b7ab05089a25034b2023d959b47e59759cb38d88341b2459e89d6e5 + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 10.0.1 + resolution: "node-gyp@npm:10.0.1" + dependencies: + env-paths: ^2.2.0 + exponential-backoff: ^3.1.1 + glob: ^10.3.10 + graceful-fs: ^4.2.6 + make-fetch-happen: ^13.0.0 + nopt: ^7.0.0 + proc-log: ^3.0.0 + semver: ^7.3.5 + tar: ^6.1.2 + which: ^4.0.0 + bin: + node-gyp: bin/node-gyp.js + checksum: 60a74e66d364903ce02049966303a57f898521d139860ac82744a5fdd9f7b7b3b61f75f284f3bfe6e6add3b8f1871ce305a1d41f775c7482de837b50c792223f + languageName: node + linkType: hard + +"node-int64@npm:^0.4.0": + version: 0.4.0 + resolution: "node-int64@npm:0.4.0" + checksum: d0b30b1ee6d961851c60d5eaa745d30b5c95d94bc0e74b81e5292f7c42a49e3af87f1eb9e89f59456f80645d679202537de751b7d72e9e40ceea40c5e449057e + languageName: node + linkType: hard + +"node-releases@npm:^2.0.14": + version: 2.0.14 + resolution: "node-releases@npm:2.0.14" + checksum: 59443a2f77acac854c42d321bf1b43dea0aef55cd544c6a686e9816a697300458d4e82239e2d794ea05f7bbbc8a94500332e2d3ac3f11f52e4b16cbe638b3c41 + languageName: node + linkType: hard + +"node-stream-zip@npm:^1.9.1": + version: 1.15.0 + resolution: "node-stream-zip@npm:1.15.0" + checksum: 0b73ffbb09490e479c8f47038d7cba803e6242618fbc1b71c26782009d388742ed6fb5ce6e9d31f528b410249e7eb1c6e7534e9d3792a0cafd99813ac5a35107 + languageName: node + linkType: hard + +"nopt@npm:^7.0.0": + version: 7.2.0 + resolution: "nopt@npm:7.2.0" + dependencies: + abbrev: ^2.0.0 + bin: + nopt: bin/nopt.js + checksum: a9c0f57fb8cb9cc82ae47192ca2b7ef00e199b9480eed202482c962d61b59a7fbe7541920b2a5839a97b42ee39e288c0aed770e38057a608d7f579389dfde410 + languageName: node + linkType: hard + +"normalize-path@npm:^3.0.0": + version: 3.0.0 + resolution: "normalize-path@npm:3.0.0" + checksum: 88eeb4da891e10b1318c4b2476b6e2ecbeb5ff97d946815ffea7794c31a89017c70d7f34b3c2ebf23ef4e9fc9fb99f7dffe36da22011b5b5c6ffa34f4873ec20 + languageName: node + linkType: hard + +"npm-run-path@npm:^4.0.1": + version: 4.0.1 + resolution: "npm-run-path@npm:4.0.1" + dependencies: + path-key: ^3.0.0 + checksum: 5374c0cea4b0bbfdfae62da7bbdf1e1558d338335f4cacf2515c282ff358ff27b2ecb91ffa5330a8b14390ac66a1e146e10700440c1ab868208430f56b5f4d23 + languageName: node + linkType: hard + +"nullthrows@npm:^1.1.1": + version: 1.1.1 + resolution: "nullthrows@npm:1.1.1" + checksum: 10806b92121253eb1b08ecf707d92480f5331ba8ae5b23fa3eb0548ad24196eb797ed47606153006568a5733ea9e528a3579f21421f7828e09e7756f4bdd386f + languageName: node + linkType: hard + +"ob1@npm:0.80.4": + version: 0.80.4 + resolution: "ob1@npm:0.80.4" + checksum: 2b089440537f1babae86edf51f0990fa91e0410ab1a27f1baea9b0a362d14216935ad6f66afb2e532b57fd4972870d86473d38c0576b52d98adc893e456b872f + languageName: node + linkType: hard + +"object-assign@npm:^4.1.1": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f + languageName: node + linkType: hard + +"object-inspect@npm:^1.13.1, object-inspect@npm:^1.9.0": + version: 1.13.1 + resolution: "object-inspect@npm:1.13.1" + checksum: 7d9fa9221de3311dcb5c7c307ee5dc011cdd31dc43624b7c184b3840514e118e05ef0002be5388304c416c0eb592feb46e983db12577fc47e47d5752fbbfb61f + languageName: node + linkType: hard + +"object-keys@npm:^1.1.1": + version: 1.1.1 + resolution: "object-keys@npm:1.1.1" + checksum: b363c5e7644b1e1b04aa507e88dcb8e3a2f52b6ffd0ea801e4c7a62d5aa559affe21c55a07fd4b1fd55fc03a33c610d73426664b20032405d7b92a1414c34d6a + languageName: node + linkType: hard + +"object.assign@npm:^4.1.4": + version: 4.1.5 + resolution: "object.assign@npm:4.1.5" + dependencies: + call-bind: ^1.0.5 + define-properties: ^1.2.1 + has-symbols: ^1.0.3 + object-keys: ^1.1.1 + checksum: f9aeac0541661370a1fc86e6a8065eb1668d3e771f7dbb33ee54578201336c057b21ee61207a186dd42db0c62201d91aac703d20d12a79fc79c353eed44d4e25 + languageName: node + linkType: hard + +"object.entries@npm:^1.1.6": + version: 1.1.7 + resolution: "object.entries@npm:1.1.7" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + checksum: da287d434e7e32989586cd734382364ba826a2527f2bc82e6acbf9f9bfafa35d51018b66ec02543ffdfa2a5ba4af2b6f1ca6e588c65030cb4fd9c67d6ced594c + languageName: node + linkType: hard + +"object.fromentries@npm:^2.0.6": + version: 2.0.7 + resolution: "object.fromentries@npm:2.0.7" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + checksum: 7341ce246e248b39a431b87a9ddd331ff52a454deb79afebc95609f94b1f8238966cf21f52188f2a353f0fdf83294f32f1ebf1f7826aae915ebad21fd0678065 + languageName: node + linkType: hard + +"object.hasown@npm:^1.1.2": + version: 1.1.3 + resolution: "object.hasown@npm:1.1.3" + dependencies: + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + checksum: 76bc17356f6124542fb47e5d0e78d531eafa4bba3fc2d6fc4b1a8ce8b6878912366c0d99f37ce5c84ada8fd79df7aa6ea1214fddf721f43e093ad2df51f27da1 + languageName: node + linkType: hard + +"object.values@npm:^1.1.6": + version: 1.1.7 + resolution: "object.values@npm:1.1.7" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + checksum: f3e4ae4f21eb1cc7cebb6ce036d4c67b36e1c750428d7b7623c56a0db90edced63d08af8a316d81dfb7c41a3a5fa81b05b7cc9426e98d7da986b1682460f0777 + languageName: node + linkType: hard + +"on-finished@npm:2.4.1": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: 1.1.1 + checksum: d20929a25e7f0bb62f937a425b5edeb4e4cde0540d77ba146ec9357f00b0d497cdb3b9b05b9c8e46222407d1548d08166bff69cc56dfa55ba0e4469228920ff0 + languageName: node + linkType: hard + +"on-finished@npm:~2.3.0": + version: 2.3.0 + resolution: "on-finished@npm:2.3.0" + dependencies: + ee-first: 1.1.1 + checksum: 1db595bd963b0124d6fa261d18320422407b8f01dc65863840f3ddaaf7bcad5b28ff6847286703ca53f4ec19595bd67a2f1253db79fc4094911ec6aa8df1671b + languageName: node + linkType: hard + +"on-headers@npm:~1.0.2": + version: 1.0.2 + resolution: "on-headers@npm:1.0.2" + checksum: 2bf13467215d1e540a62a75021e8b318a6cfc5d4fc53af8e8f84ad98dbcea02d506c6d24180cd62e1d769c44721ba542f3154effc1f7579a8288c9f7873ed8e5 + languageName: node + linkType: hard + +"once@npm:^1.3.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: 1 + checksum: cd0a88501333edd640d95f0d2700fbde6bff20b3d4d9bdc521bdd31af0656b5706570d6c6afe532045a20bb8dc0849f8332d6f2a416e0ba6d3d3b98806c7db68 + languageName: node + linkType: hard + +"onetime@npm:^5.1.0, onetime@npm:^5.1.2": + version: 5.1.2 + resolution: "onetime@npm:5.1.2" + dependencies: + mimic-fn: ^2.1.0 + checksum: 2478859ef817fc5d4e9c2f9e5728512ddd1dbc9fb7829ad263765bb6d3b91ce699d6e2332eef6b7dff183c2f490bd3349f1666427eaba4469fba0ac38dfd0d34 + languageName: node + linkType: hard + +"open@npm:^6.2.0": + version: 6.4.0 + resolution: "open@npm:6.4.0" + dependencies: + is-wsl: ^1.1.0 + checksum: e5037facf3e03ed777537db3e2511ada37f351c4394e1dadccf9cac11d63b28447ae8b495b7b138659910fd78d918bafed546e47163673c4a4e43dbb5ac53c5d + languageName: node + linkType: hard + +"open@npm:^7.0.3": + version: 7.4.2 + resolution: "open@npm:7.4.2" + dependencies: + is-docker: ^2.0.0 + is-wsl: ^2.1.1 + checksum: 3333900ec0e420d64c23b831bc3467e57031461d843c801f569b2204a1acc3cd7b3ec3c7897afc9dde86491dfa289708eb92bba164093d8bd88fb2c231843c91 + languageName: node + linkType: hard + +"optionator@npm:^0.9.3": + version: 0.9.3 + resolution: "optionator@npm:0.9.3" + dependencies: + "@aashutoshrathi/word-wrap": ^1.2.3 + deep-is: ^0.1.3 + fast-levenshtein: ^2.0.6 + levn: ^0.4.1 + prelude-ls: ^1.2.1 + type-check: ^0.4.0 + checksum: 09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a + languageName: node + linkType: hard + +"ora@npm:^5.4.1": + version: 5.4.1 + resolution: "ora@npm:5.4.1" + dependencies: + bl: ^4.1.0 + chalk: ^4.1.0 + cli-cursor: ^3.1.0 + cli-spinners: ^2.5.0 + is-interactive: ^1.0.0 + is-unicode-supported: ^0.1.0 + log-symbols: ^4.1.0 + strip-ansi: ^6.0.0 + wcwidth: ^1.0.1 + checksum: 28d476ee6c1049d68368c0dc922e7225e3b5600c3ede88fade8052837f9ed342625fdaa84a6209302587c8ddd9b664f71f0759833cbdb3a4cf81344057e63c63 + languageName: node + linkType: hard + +"p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": + version: 2.3.0 + resolution: "p-limit@npm:2.3.0" + dependencies: + p-try: ^2.0.0 + checksum: 84ff17f1a38126c3314e91ecfe56aecbf36430940e2873dadaa773ffe072dc23b7af8e46d4b6485d302a11673fe94c6b67ca2cfbb60c989848b02100d0594ac1 + languageName: node + linkType: hard + +"p-limit@npm:^3.0.2, p-limit@npm:^3.1.0": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: ^0.1.0 + checksum: 7c3690c4dbf62ef625671e20b7bdf1cbc9534e83352a2780f165b0d3ceba21907e77ad63401708145ca4e25bfc51636588d89a8c0aeb715e6c37d1c066430360 + languageName: node + linkType: hard + +"p-locate@npm:^3.0.0": + version: 3.0.0 + resolution: "p-locate@npm:3.0.0" + dependencies: + p-limit: ^2.0.0 + checksum: 83991734a9854a05fe9dbb29f707ea8a0599391f52daac32b86f08e21415e857ffa60f0e120bfe7ce0cc4faf9274a50239c7895fc0d0579d08411e513b83a4ae + languageName: node + linkType: hard + +"p-locate@npm:^4.1.0": + version: 4.1.0 + resolution: "p-locate@npm:4.1.0" + dependencies: + p-limit: ^2.2.0 + checksum: 513bd14a455f5da4ebfcb819ef706c54adb09097703de6aeaa5d26fe5ea16df92b48d1ac45e01e3944ce1e6aa2a66f7f8894742b8c9d6e276e16cd2049a2b870 + languageName: node + linkType: hard + +"p-locate@npm:^5.0.0": + version: 5.0.0 + resolution: "p-locate@npm:5.0.0" + dependencies: + p-limit: ^3.0.2 + checksum: 1623088f36cf1cbca58e9b61c4e62bf0c60a07af5ae1ca99a720837356b5b6c5ba3eb1b2127e47a06865fee59dd0453cad7cc844cda9d5a62ac1a5a51b7c86d3 + languageName: node + linkType: hard + +"p-map@npm:^4.0.0": + version: 4.0.0 + resolution: "p-map@npm:4.0.0" + dependencies: + aggregate-error: ^3.0.0 + checksum: cb0ab21ec0f32ddffd31dfc250e3afa61e103ef43d957cc45497afe37513634589316de4eb88abdfd969fe6410c22c0b93ab24328833b8eb1ccc087fc0442a1c + languageName: node + linkType: hard + +"p-try@npm:^2.0.0": + version: 2.2.0 + resolution: "p-try@npm:2.2.0" + checksum: f8a8e9a7693659383f06aec604ad5ead237c7a261c18048a6e1b5b85a5f8a067e469aa24f5bc009b991ea3b058a87f5065ef4176793a200d4917349881216cae + languageName: node + linkType: hard + +"parent-module@npm:^1.0.0": + version: 1.0.1 + resolution: "parent-module@npm:1.0.1" + dependencies: + callsites: ^3.0.0 + checksum: 6ba8b255145cae9470cf5551eb74be2d22281587af787a2626683a6c20fbb464978784661478dd2a3f1dad74d1e802d403e1b03c1a31fab310259eec8ac560ff + languageName: node + linkType: hard + +"parse-json@npm:^4.0.0": + version: 4.0.0 + resolution: "parse-json@npm:4.0.0" + dependencies: + error-ex: ^1.3.1 + json-parse-better-errors: ^1.0.1 + checksum: 0fe227d410a61090c247e34fa210552b834613c006c2c64d9a05cfe9e89cf8b4246d1246b1a99524b53b313e9ac024438d0680f67e33eaed7e6f38db64cfe7b5 + languageName: node + linkType: hard + +"parse-json@npm:^5.2.0": + version: 5.2.0 + resolution: "parse-json@npm:5.2.0" + dependencies: + "@babel/code-frame": ^7.0.0 + error-ex: ^1.3.1 + json-parse-even-better-errors: ^2.3.0 + lines-and-columns: ^1.1.6 + checksum: 62085b17d64da57f40f6afc2ac1f4d95def18c4323577e1eced571db75d9ab59b297d1d10582920f84b15985cbfc6b6d450ccbf317644cfa176f3ed982ad87e2 + languageName: node + linkType: hard + +"parseurl@npm:~1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 + languageName: node + linkType: hard + +"path-exists@npm:^3.0.0": + version: 3.0.0 + resolution: "path-exists@npm:3.0.0" + checksum: 96e92643aa34b4b28d0de1cd2eba52a1c5313a90c6542d03f62750d82480e20bfa62bc865d5cfc6165f5fcd5aeb0851043c40a39be5989646f223300021bae0a + languageName: node + linkType: hard + +"path-exists@npm:^4.0.0": + version: 4.0.0 + resolution: "path-exists@npm:4.0.0" + checksum: 505807199dfb7c50737b057dd8d351b82c033029ab94cb10a657609e00c1bc53b951cfdbccab8de04c5584d5eff31128ce6afd3db79281874a5ef2adbba55ed1 + languageName: node + linkType: hard + +"path-is-absolute@npm:^1.0.0": + version: 1.0.1 + resolution: "path-is-absolute@npm:1.0.1" + checksum: 060840f92cf8effa293bcc1bea81281bd7d363731d214cbe5c227df207c34cd727430f70c6037b5159c8a870b9157cba65e775446b0ab06fd5ecc7e54615a3b8 + languageName: node + linkType: hard + +"path-key@npm:^3.0.0, path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 55cd7a9dd4b343412a8386a743f9c746ef196e57c823d90ca3ab917f90ab9f13dd0ded27252ba49dbdfcab2b091d998bc446f6220cd3cea65db407502a740020 + languageName: node + linkType: hard + +"path-parse@npm:^1.0.7": + version: 1.0.7 + resolution: "path-parse@npm:1.0.7" + checksum: 49abf3d81115642938a8700ec580da6e830dde670be21893c62f4e10bd7dd4c3742ddc603fe24f898cba7eb0c6bc1777f8d9ac14185d34540c6d4d80cd9cae8a + languageName: node + linkType: hard + +"path-scurry@npm:^1.10.1": + version: 1.10.1 + resolution: "path-scurry@npm:1.10.1" + dependencies: + lru-cache: ^9.1.1 || ^10.0.0 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + checksum: e2557cff3a8fb8bc07afdd6ab163a92587884f9969b05bbbaf6fe7379348bfb09af9ed292af12ed32398b15fb443e81692047b786d1eeb6d898a51eb17ed7d90 + languageName: node + linkType: hard + +"path-type@npm:^4.0.0": + version: 4.0.0 + resolution: "path-type@npm:4.0.0" + checksum: 5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 + languageName: node + linkType: hard + +"picocolors@npm:^1.0.0": + version: 1.0.0 + resolution: "picocolors@npm:1.0.0" + checksum: a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 + languageName: node + linkType: hard + +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.3, picomatch@npm:^2.3.1": + version: 2.3.1 + resolution: "picomatch@npm:2.3.1" + checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf + languageName: node + linkType: hard + +"pify@npm:^4.0.1": + version: 4.0.1 + resolution: "pify@npm:4.0.1" + checksum: 9c4e34278cb09987685fa5ef81499c82546c033713518f6441778fbec623fc708777fe8ac633097c72d88470d5963094076c7305cafc7ad340aae27cfacd856b + languageName: node + linkType: hard + +"pirates@npm:^4.0.4, pirates@npm:^4.0.6": + version: 4.0.6 + resolution: "pirates@npm:4.0.6" + checksum: 46a65fefaf19c6f57460388a5af9ab81e3d7fd0e7bc44ca59d753cb5c4d0df97c6c6e583674869762101836d68675f027d60f841c105d72734df9dfca97cbcc6 + languageName: node + linkType: hard + +"pkg-dir@npm:^3.0.0": + version: 3.0.0 + resolution: "pkg-dir@npm:3.0.0" + dependencies: + find-up: ^3.0.0 + checksum: 70c9476ffefc77552cc6b1880176b71ad70bfac4f367604b2b04efd19337309a4eec985e94823271c7c0e83946fa5aeb18cd360d15d10a5d7533e19344bfa808 + languageName: node + linkType: hard + +"pkg-dir@npm:^4.2.0": + version: 4.2.0 + resolution: "pkg-dir@npm:4.2.0" + dependencies: + find-up: ^4.0.0 + checksum: 9863e3f35132bf99ae1636d31ff1e1e3501251d480336edb1c211133c8d58906bed80f154a1d723652df1fda91e01c7442c2eeaf9dc83157c7ae89087e43c8d6 + languageName: node + linkType: hard + +"prelude-ls@npm:^1.2.1": + version: 1.2.1 + resolution: "prelude-ls@npm:1.2.1" + checksum: cd192ec0d0a8e4c6da3bb80e4f62afe336df3f76271ac6deb0e6a36187133b6073a19e9727a1ff108cd8b9982e4768850d413baa71214dd80c7979617dca827a + languageName: node + linkType: hard + +"prettier-linter-helpers@npm:^1.0.0": + version: 1.0.0 + resolution: "prettier-linter-helpers@npm:1.0.0" + dependencies: + fast-diff: ^1.1.2 + checksum: 00ce8011cf6430158d27f9c92cfea0a7699405633f7f1d4a45f07e21bf78e99895911cbcdc3853db3a824201a7c745bd49bfea8abd5fb9883e765a90f74f8392 + languageName: node + linkType: hard + +"prettier@npm:^3.2.4": + version: 3.2.4 + resolution: "prettier@npm:3.2.4" + bin: + prettier: bin/prettier.cjs + checksum: 6ec9385a836e0b9bac549e585101c086d1521c31d7b882d5c8bb7d7646da0693da5f31f4fff6dc080710e5e2d34c85e6fb2f8766876b3645c8be2f33b9c3d1a3 + languageName: node + linkType: hard + +"pretty-format@npm:^26.5.2, pretty-format@npm:^26.6.2": + version: 26.6.2 + resolution: "pretty-format@npm:26.6.2" + dependencies: + "@jest/types": ^26.6.2 + ansi-regex: ^5.0.0 + ansi-styles: ^4.0.0 + react-is: ^17.0.1 + checksum: e3b808404d7e1519f0df1aa1f25cee0054ab475775c6b2b8c5568ff23194a92d54bf93274139b6f584ca70fd773be4eaa754b0e03f12bb0a8d1426b07f079976 + languageName: node + linkType: hard + +"pretty-format@npm:^29.0.0, pretty-format@npm:^29.7.0": + version: 29.7.0 + resolution: "pretty-format@npm:29.7.0" + dependencies: + "@jest/schemas": ^29.6.3 + ansi-styles: ^5.0.0 + react-is: ^18.0.0 + checksum: 032c1602383e71e9c0c02a01bbd25d6759d60e9c7cf21937dde8357aa753da348fcec5def5d1002c9678a8524d5fe099ad98861286550ef44de8808cc61e43b6 + languageName: node + linkType: hard + +"proc-log@npm:^3.0.0": + version: 3.0.0 + resolution: "proc-log@npm:3.0.0" + checksum: 02b64e1b3919e63df06f836b98d3af002b5cd92655cab18b5746e37374bfb73e03b84fe305454614b34c25b485cc687a9eebdccf0242cda8fda2475dd2c97e02 + languageName: node + linkType: hard + +"process-nextick-args@npm:~2.0.0": + version: 2.0.1 + resolution: "process-nextick-args@npm:2.0.1" + checksum: 1d38588e520dab7cea67cbbe2efdd86a10cc7a074c09657635e34f035277b59fbb57d09d8638346bf7090f8e8ebc070c96fa5fd183b777fff4f5edff5e9466cf + languageName: node + linkType: hard + +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: ^2.0.2 + retry: ^0.12.0 + checksum: f96a3f6d90b92b568a26f71e966cbbc0f63ab85ea6ff6c81284dc869b41510e6cdef99b6b65f9030f0db422bf7c96652a3fff9f2e8fb4a0f069d8f4430359429 + languageName: node + linkType: hard + +"promise@npm:^8.3.0": + version: 8.3.0 + resolution: "promise@npm:8.3.0" + dependencies: + asap: ~2.0.6 + checksum: a69f0ddbddf78ffc529cffee7ad950d307347615970564b17988ce43fbe767af5c738a9439660b24a9a8cbea106c0dcbb6c2b20e23b7e96a8e89e5c2679e94d5 + languageName: node + linkType: hard + +"prompts@npm:^2.0.1, prompts@npm:^2.4.2": + version: 2.4.2 + resolution: "prompts@npm:2.4.2" + dependencies: + kleur: ^3.0.3 + sisteransi: ^1.0.5 + checksum: d8fd1fe63820be2412c13bfc5d0a01909acc1f0367e32396962e737cb2fc52d004f3302475d5ce7d18a1e8a79985f93ff04ee03007d091029c3f9104bffc007d + languageName: node + linkType: hard + +"prop-types@npm:^15.8.1": + version: 15.8.1 + resolution: "prop-types@npm:15.8.1" + dependencies: + loose-envify: ^1.4.0 + object-assign: ^4.1.1 + react-is: ^16.13.1 + checksum: c056d3f1c057cb7ff8344c645450e14f088a915d078dcda795041765047fa080d38e5d626560ccaac94a4e16e3aa15f3557c1a9a8d1174530955e992c675e459 + languageName: node + linkType: hard + +"punycode@npm:^2.1.0": + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2 + languageName: node + linkType: hard + +"pure-rand@npm:^6.0.0": + version: 6.0.4 + resolution: "pure-rand@npm:6.0.4" + checksum: e1c4e69f8bf7303e5252756d67c3c7551385cd34d94a1f511fe099727ccbab74c898c03a06d4c4a24a89b51858781057b83ebbfe740d984240cdc04fead36068 + languageName: node + linkType: hard + +"queue-microtask@npm:^1.2.2": + version: 1.2.3 + resolution: "queue-microtask@npm:1.2.3" + checksum: b676f8c040cdc5b12723ad2f91414d267605b26419d5c821ff03befa817ddd10e238d22b25d604920340fd73efd8ba795465a0377c4adf45a4a41e4234e42dc4 + languageName: node + linkType: hard + +"queue@npm:6.0.2": + version: 6.0.2 + resolution: "queue@npm:6.0.2" + dependencies: + inherits: ~2.0.3 + checksum: ebc23639248e4fe40a789f713c20548e513e053b3dc4924b6cb0ad741e3f264dcff948225c8737834dd4f9ec286dbc06a1a7c13858ea382d9379f4303bcc0916 + languageName: node + linkType: hard + +"range-parser@npm:~1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 0a268d4fea508661cf5743dfe3d5f47ce214fd6b7dec1de0da4d669dd4ef3d2144468ebe4179049eff253d9d27e719c88dae55be64f954e80135a0cada804ec9 + languageName: node + linkType: hard + +"react-devtools-core@npm:^4.27.7": + version: 4.28.5 + resolution: "react-devtools-core@npm:4.28.5" + dependencies: + shell-quote: ^1.6.1 + ws: ^7 + checksum: d8e4b32ffcfe1ada5c9f7decffd04afc4707a3d6261953a92b8aed1c8abe15cd57d6eb4ce711f842180a2f5c60d2947209e3c1202f7ea29303ee150c55da59e0 + languageName: node + linkType: hard + +"react-is@npm:^16.12.0 || ^17.0.0 || ^18.0.0, react-is@npm:^18.0.0, react-is@npm:^18.2.0": + version: 18.2.0 + resolution: "react-is@npm:18.2.0" + checksum: e72d0ba81b5922759e4aff17e0252bd29988f9642ed817f56b25a3e217e13eea8a7f2322af99a06edb779da12d5d636e9fda473d620df9a3da0df2a74141d53e + languageName: node + linkType: hard + +"react-is@npm:^16.13.1": + version: 16.13.1 + resolution: "react-is@npm:16.13.1" + checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f + languageName: node + linkType: hard + +"react-is@npm:^17.0.1": + version: 17.0.2 + resolution: "react-is@npm:17.0.2" + checksum: 9d6d111d8990dc98bc5402c1266a808b0459b5d54830bbea24c12d908b536df7883f268a7868cfaedde3dd9d4e0d574db456f84d2e6df9c4526f99bb4b5344d8 + languageName: node + linkType: hard + +"react-native-template-redux-typescript@workspace:.": + version: 0.0.0-use.local + resolution: "react-native-template-redux-typescript@workspace:." + dependencies: + "@babel/core": ^7.23.7 + "@babel/preset-env": ^7.23.8 + "@babel/runtime": ^7.23.8 + "@react-native/babel-preset": ^0.73.19 + "@react-native/eslint-config": ^0.74.0 + "@react-native/metro-config": ^0.73.3 + "@react-native/typescript-config": ^0.74.0 + "@reduxjs/toolkit": ^2.0.1 + "@testing-library/react-native": ^12.4.3 + "@types/jest": ^29.5.11 + "@types/react": ^18.2.47 + "@types/react-test-renderer": ^18.0.7 + "@typescript-eslint/eslint-plugin": ^6.18.1 + "@typescript-eslint/parser": ^6.18.1 + babel-jest: ^29.7.0 + eslint: ^8.56.0 + eslint-config-prettier: ^9.1.0 + eslint-plugin-prettier: ^5.1.3 + jest: ^29.7.0 + prettier: ^3.2.4 + react: 18.2.0 + react-native: ^0.73.2 + react-redux: ^9.1.0 + react-test-renderer: 18.2.0 + ts-node: ^10.9.2 + typescript: ^5.3.3 + languageName: unknown + linkType: soft + +"react-native@npm:^0.73.2": + version: 0.73.2 + resolution: "react-native@npm:0.73.2" + dependencies: + "@jest/create-cache-key-function": ^29.6.3 + "@react-native-community/cli": 12.3.0 + "@react-native-community/cli-platform-android": 12.3.0 + "@react-native-community/cli-platform-ios": 12.3.0 + "@react-native/assets-registry": 0.73.1 + "@react-native/codegen": 0.73.2 + "@react-native/community-cli-plugin": 0.73.12 + "@react-native/gradle-plugin": 0.73.4 + "@react-native/js-polyfills": 0.73.1 + "@react-native/normalize-colors": 0.73.2 + "@react-native/virtualized-lists": 0.73.4 + abort-controller: ^3.0.0 + anser: ^1.4.9 + ansi-regex: ^5.0.0 + base64-js: ^1.5.1 + deprecated-react-native-prop-types: ^5.0.0 + event-target-shim: ^5.0.1 + flow-enums-runtime: ^0.0.6 + invariant: ^2.2.4 + jest-environment-node: ^29.6.3 + jsc-android: ^250231.0.0 + memoize-one: ^5.0.0 + metro-runtime: ^0.80.3 + metro-source-map: ^0.80.3 + mkdirp: ^0.5.1 + nullthrows: ^1.1.1 + pretty-format: ^26.5.2 + promise: ^8.3.0 + react-devtools-core: ^4.27.7 + react-refresh: ^0.14.0 + react-shallow-renderer: ^16.15.0 + regenerator-runtime: ^0.13.2 + scheduler: 0.24.0-canary-efb381bbf-20230505 + stacktrace-parser: ^0.1.10 + whatwg-fetch: ^3.0.0 + ws: ^6.2.2 + yargs: ^17.6.2 + peerDependencies: + react: 18.2.0 + bin: + react-native: cli.js + checksum: a9ebbb7879118c2f4d749d7c252606d323b1ee22567348ff833260dcbd73d5a2c3fbd80280cb770b438e5fe63478f85f18876df0410859d37ee18b6080de9ed2 + languageName: node + linkType: hard + +"react-redux@npm:^9.1.0": + version: 9.1.0 + resolution: "react-redux@npm:9.1.0" + dependencies: + "@types/use-sync-external-store": ^0.0.3 + use-sync-external-store: ^1.0.0 + peerDependencies: + "@types/react": ^18.2.25 + react: ^18.0 + react-native: ">=0.69" + redux: ^5.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + react-native: + optional: true + redux: + optional: true + checksum: 1b07714379ff0087b4fb43ffd138cc84efb7608c874d632a4e2162e1874f3e0f6b69a0a9b0f24f93cbf122c694ac9cfd315770676d4cabb167d159f1ef419560 + languageName: node + linkType: hard + +"react-refresh@npm:^0.14.0": + version: 0.14.0 + resolution: "react-refresh@npm:0.14.0" + checksum: dc69fa8c993df512f42dd0f1b604978ae89bd747c0ed5ec595c0cc50d535fb2696619ccd98ae28775cc01d0a7c146a532f0f7fb81dc22e1977c242a4912312f4 + languageName: node + linkType: hard + +"react-shallow-renderer@npm:^16.15.0": + version: 16.15.0 + resolution: "react-shallow-renderer@npm:16.15.0" + dependencies: + object-assign: ^4.1.1 + react-is: ^16.12.0 || ^17.0.0 || ^18.0.0 + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 + checksum: 6052c7e3e9627485120ebd8257f128aad8f56386fe8d42374b7743eac1be457c33506d153c7886b4e32923c0c352d402ab805ef9ca02dbcd8393b2bdeb6e5af8 + languageName: node + linkType: hard + +"react-test-renderer@npm:18.2.0": + version: 18.2.0 + resolution: "react-test-renderer@npm:18.2.0" + dependencies: + react-is: ^18.2.0 + react-shallow-renderer: ^16.15.0 + scheduler: ^0.23.0 + peerDependencies: + react: ^18.2.0 + checksum: 6b6980ced93fa2b72662d5e4ab3b4896833586940047ce52ca9aca801e5432adf05fcbe28289b0af3ce6a2a7c590974e25dcc8aa43d0de658bfe8bbcd686f958 + languageName: node + linkType: hard + +"react@npm:18.2.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" + dependencies: + loose-envify: ^1.1.0 + checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b + languageName: node + linkType: hard + +"readable-stream@npm:^3.4.0": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: ^2.0.3 + string_decoder: ^1.1.1 + util-deprecate: ^1.0.1 + checksum: bdcbe6c22e846b6af075e32cf8f4751c2576238c5043169a1c221c92ee2878458a816a4ea33f4c67623c0b6827c8a400409bfb3cf0bf3381392d0b1dfb52ac8d + languageName: node + linkType: hard + +"readable-stream@npm:~2.3.6": + version: 2.3.8 + resolution: "readable-stream@npm:2.3.8" + dependencies: + core-util-is: ~1.0.0 + inherits: ~2.0.3 + isarray: ~1.0.0 + process-nextick-args: ~2.0.0 + safe-buffer: ~5.1.1 + string_decoder: ~1.1.1 + util-deprecate: ~1.0.1 + checksum: 65645467038704f0c8aaf026a72fbb588a9e2ef7a75cd57a01702ee9db1c4a1e4b03aaad36861a6a0926546a74d174149c8c207527963e0c2d3eee2f37678a42 + languageName: node + linkType: hard + +"readline@npm:^1.3.0": + version: 1.3.0 + resolution: "readline@npm:1.3.0" + checksum: dfaf8e6ac20408ea00d650e95f7bb47f77c4c62dd12ed7fb51731ee84532a2f3675fcdc4cab4923dc1eef227520a2e082a093215190907758bea9f585b19438e + languageName: node + linkType: hard + +"recast@npm:^0.21.0": + version: 0.21.5 + resolution: "recast@npm:0.21.5" + dependencies: + ast-types: 0.15.2 + esprima: ~4.0.0 + source-map: ~0.6.1 + tslib: ^2.0.1 + checksum: 03cc7f57562238ba258d468be67bf7446ce7a707bc87a087891dad15afead46c36e9aaeedf2130e2ab5a465244a9c62bfd4127849761cf8f4085abe2f3e5f485 + languageName: node + linkType: hard + +"redent@npm:^3.0.0": + version: 3.0.0 + resolution: "redent@npm:3.0.0" + dependencies: + indent-string: ^4.0.0 + strip-indent: ^3.0.0 + checksum: fa1ef20404a2d399235e83cc80bd55a956642e37dd197b4b612ba7327bf87fa32745aeb4a1634b2bab25467164ab4ed9c15be2c307923dd08b0fe7c52431ae6b + languageName: node + linkType: hard + +"redux-thunk@npm:^3.1.0": + version: 3.1.0 + resolution: "redux-thunk@npm:3.1.0" + peerDependencies: + redux: ^5.0.0 + checksum: bea96f8233975aad4c9f24ca1ffd08ac7ec91eaefc26e7ba9935544dc55d7f09ba2aa726676dab53dc79d0c91e8071f9729cddfea927f4c41839757d2ade0f50 + languageName: node + linkType: hard + +"redux@npm:^5.0.0": + version: 5.0.1 + resolution: "redux@npm:5.0.1" + checksum: e74affa9009dd5d994878b9a1ce30d6569d986117175056edb003de2651c05b10fe7819d6fa94aea1a94de9a82f252f986547f007a2fbeb35c317a2e5f5ecf2c + languageName: node + linkType: hard + +"reflect.getprototypeof@npm:^1.0.4": + version: 1.0.4 + resolution: "reflect.getprototypeof@npm:1.0.4" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + get-intrinsic: ^1.2.1 + globalthis: ^1.0.3 + which-builtin-type: ^1.1.3 + checksum: 16e2361988dbdd23274b53fb2b1b9cefeab876c3941a2543b4cadac6f989e3db3957b07a44aac46cfceb3e06e2871785ec2aac992d824f76292f3b5ee87f66f2 + languageName: node + linkType: hard + +"regenerate-unicode-properties@npm:^10.1.0": + version: 10.1.1 + resolution: "regenerate-unicode-properties@npm:10.1.1" + dependencies: + regenerate: ^1.4.2 + checksum: b80958ef40f125275824c2c47d5081dfaefebd80bff26c76761e9236767c748a4a95a69c053fe29d2df881177f2ca85df4a71fe70a82360388b31159ef19adcf + languageName: node + linkType: hard + +"regenerate@npm:^1.4.2": + version: 1.4.2 + resolution: "regenerate@npm:1.4.2" + checksum: 3317a09b2f802da8db09aa276e469b57a6c0dd818347e05b8862959c6193408242f150db5de83c12c3fa99091ad95fb42a6db2c3329bfaa12a0ea4cbbeb30cb0 + languageName: node + linkType: hard + +"regenerator-runtime@npm:^0.13.2": + version: 0.13.11 + resolution: "regenerator-runtime@npm:0.13.11" + checksum: 27481628d22a1c4e3ff551096a683b424242a216fee44685467307f14d58020af1e19660bf2e26064de946bad7eff28950eae9f8209d55723e2d9351e632bbb4 + languageName: node + linkType: hard + +"regenerator-runtime@npm:^0.14.0": + version: 0.14.1 + resolution: "regenerator-runtime@npm:0.14.1" + checksum: 9f57c93277b5585d3c83b0cf76be47b473ae8c6d9142a46ce8b0291a04bb2cf902059f0f8445dcabb3fb7378e5fe4bb4ea1e008876343d42e46d3b484534ce38 + languageName: node + linkType: hard + +"regenerator-transform@npm:^0.15.2": + version: 0.15.2 + resolution: "regenerator-transform@npm:0.15.2" + dependencies: + "@babel/runtime": ^7.8.4 + checksum: 20b6f9377d65954980fe044cfdd160de98df415b4bff38fbade67b3337efaf078308c4fed943067cd759827cc8cfeca9cb28ccda1f08333b85d6a2acbd022c27 + languageName: node + linkType: hard + +"regexp.prototype.flags@npm:^1.5.0, regexp.prototype.flags@npm:^1.5.1": + version: 1.5.1 + resolution: "regexp.prototype.flags@npm:1.5.1" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + set-function-name: ^2.0.0 + checksum: 869edff00288442f8d7fa4c9327f91d85f3b3acf8cbbef9ea7a220345cf23e9241b6def9263d2c1ebcf3a316b0aa52ad26a43a84aa02baca3381717b3e307f47 + languageName: node + linkType: hard + +"regexpu-core@npm:^5.3.1": + version: 5.3.2 + resolution: "regexpu-core@npm:5.3.2" + dependencies: + "@babel/regjsgen": ^0.8.0 + regenerate: ^1.4.2 + regenerate-unicode-properties: ^10.1.0 + regjsparser: ^0.9.1 + unicode-match-property-ecmascript: ^2.0.0 + unicode-match-property-value-ecmascript: ^2.1.0 + checksum: 95bb97088419f5396e07769b7de96f995f58137ad75fac5811fb5fe53737766dfff35d66a0ee66babb1eb55386ef981feaef392f9df6d671f3c124812ba24da2 + languageName: node + linkType: hard + +"regjsparser@npm:^0.9.1": + version: 0.9.1 + resolution: "regjsparser@npm:0.9.1" + dependencies: + jsesc: ~0.5.0 + bin: + regjsparser: bin/parser + checksum: 5e1b76afe8f1d03c3beaf9e0d935dd467589c3625f6d65fb8ffa14f224d783a0fed4bf49c2c1b8211043ef92b6117313419edf055a098ed8342e340586741afc + languageName: node + linkType: hard + +"require-directory@npm:^2.1.1": + version: 2.1.1 + resolution: "require-directory@npm:2.1.1" + checksum: fb47e70bf0001fdeabdc0429d431863e9475e7e43ea5f94ad86503d918423c1543361cc5166d713eaa7029dd7a3d34775af04764bebff99ef413111a5af18c80 + languageName: node + linkType: hard + +"require-main-filename@npm:^2.0.0": + version: 2.0.0 + resolution: "require-main-filename@npm:2.0.0" + checksum: e9e294695fea08b076457e9ddff854e81bffbe248ed34c1eec348b7abbd22a0d02e8d75506559e2265e96978f3c4720bd77a6dad84755de8162b357eb6c778c7 + languageName: node + linkType: hard + +"reselect@npm:^5.0.1": + version: 5.1.0 + resolution: "reselect@npm:5.1.0" + checksum: 5bc9c5d03d7caea00d0c0e24330bf23d91801227346fec1cef6a60988ab8d3dd7cee76e6994ca0915bc1c20845bb2bd929b95753763e0a9db74c0f9dff5cb845 + languageName: node + linkType: hard + +"resolve-cwd@npm:^3.0.0": + version: 3.0.0 + resolution: "resolve-cwd@npm:3.0.0" + dependencies: + resolve-from: ^5.0.0 + checksum: 546e0816012d65778e580ad62b29e975a642989108d9a3c5beabfb2304192fa3c9f9146fbdfe213563c6ff51975ae41bac1d3c6e047dd9572c94863a057b4d81 + languageName: node + linkType: hard + +"resolve-from@npm:^3.0.0": + version: 3.0.0 + resolution: "resolve-from@npm:3.0.0" + checksum: fff9819254d2d62b57f74e5c2ca9c0bdd425ca47287c4d801bc15f947533148d858229ded7793b0f59e61e49e782fffd6722048add12996e1bd4333c29669062 + languageName: node + linkType: hard + +"resolve-from@npm:^4.0.0": + version: 4.0.0 + resolution: "resolve-from@npm:4.0.0" + checksum: f4ba0b8494846a5066328ad33ef8ac173801a51739eb4d63408c847da9a2e1c1de1e6cbbf72699211f3d13f8fc1325648b169bd15eb7da35688e30a5fb0e4a7f + languageName: node + linkType: hard + +"resolve-from@npm:^5.0.0": + version: 5.0.0 + resolution: "resolve-from@npm:5.0.0" + checksum: 4ceeb9113e1b1372d0cd969f3468fa042daa1dd9527b1b6bb88acb6ab55d8b9cd65dbf18819f9f9ddf0db804990901dcdaade80a215e7b2c23daae38e64f5bdf + languageName: node + linkType: hard + +"resolve.exports@npm:^2.0.0": + version: 2.0.2 + resolution: "resolve.exports@npm:2.0.2" + checksum: 1c7778ca1b86a94f8ab4055d196c7d87d1874b96df4d7c3e67bbf793140f0717fd506dcafd62785b079cd6086b9264424ad634fb904409764c3509c3df1653f2 + languageName: node + linkType: hard + +"resolve@npm:^1.14.2, resolve@npm:^1.20.0": + version: 1.22.8 + resolution: "resolve@npm:1.22.8" + dependencies: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: f8a26958aa572c9b064562750b52131a37c29d072478ea32e129063e2da7f83e31f7f11e7087a18225a8561cfe8d2f0df9dbea7c9d331a897571c0a2527dbb4c + languageName: node + linkType: hard + +"resolve@npm:^2.0.0-next.4": + version: 2.0.0-next.5 + resolution: "resolve@npm:2.0.0-next.5" + dependencies: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: a73ac69a1c4bd34c56b213d91f5b17ce390688fdb4a1a96ed3025cc7e08e7bfb90b3a06fcce461780cb0b589c958afcb0080ab802c71c01a7ecc8c64feafc89f + languageName: node + linkType: hard + +"resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.20.0#~builtin": + version: 1.22.8 + resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=07638b" + dependencies: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: 5479b7d431cacd5185f8db64bfcb7286ae5e31eb299f4c4f404ad8aa6098b77599563ac4257cb2c37a42f59dfc06a1bec2bcf283bb448f319e37f0feb9a09847 + languageName: node + linkType: hard + +"resolve@patch:resolve@^2.0.0-next.4#~builtin": + version: 2.0.0-next.5 + resolution: "resolve@patch:resolve@npm%3A2.0.0-next.5#~builtin::version=2.0.0-next.5&hash=07638b" + dependencies: + is-core-module: ^2.13.0 + path-parse: ^1.0.7 + supports-preserve-symlinks-flag: ^1.0.0 + bin: + resolve: bin/resolve + checksum: 064d09c1808d0c51b3d90b5d27e198e6d0c5dad0eb57065fd40803d6a20553e5398b07f76739d69cbabc12547058bec6b32106ea66622375fb0d7e8fca6a846c + languageName: node + linkType: hard + +"restore-cursor@npm:^3.1.0": + version: 3.1.0 + resolution: "restore-cursor@npm:3.1.0" + dependencies: + onetime: ^5.1.0 + signal-exit: ^3.0.2 + checksum: f877dd8741796b909f2a82454ec111afb84eb45890eb49ac947d87991379406b3b83ff9673a46012fca0d7844bb989f45cc5b788254cf1a39b6b5a9659de0630 + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 623bd7d2e5119467ba66202d733ec3c2e2e26568074923bc0585b6b99db14f357e79bdedb63cab56cec47491c4a0da7e6021a7465ca6dc4f481d3898fdd3158c + languageName: node + linkType: hard + +"reusify@npm:^1.0.4": + version: 1.0.4 + resolution: "reusify@npm:1.0.4" + checksum: c3076ebcc22a6bc252cb0b9c77561795256c22b757f40c0d8110b1300723f15ec0fc8685e8d4ea6d7666f36c79ccc793b1939c748bf36f18f542744a4e379fcc + languageName: node + linkType: hard + +"rimraf@npm:^3.0.2": + version: 3.0.2 + resolution: "rimraf@npm:3.0.2" + dependencies: + glob: ^7.1.3 + bin: + rimraf: bin.js + checksum: 87f4164e396f0171b0a3386cc1877a817f572148ee13a7e113b238e48e8a9f2f31d009a92ec38a591ff1567d9662c6b67fd8818a2dbbaed74bc26a87a2a4a9a0 + languageName: node + linkType: hard + +"rimraf@npm:~2.6.2": + version: 2.6.3 + resolution: "rimraf@npm:2.6.3" + dependencies: + glob: ^7.1.3 + bin: + rimraf: ./bin.js + checksum: 3ea587b981a19016297edb96d1ffe48af7e6af69660e3b371dbfc73722a73a0b0e9be5c88089fbeeb866c389c1098e07f64929c7414290504b855f54f901ab10 + languageName: node + linkType: hard + +"run-parallel@npm:^1.1.9": + version: 1.2.0 + resolution: "run-parallel@npm:1.2.0" + dependencies: + queue-microtask: ^1.2.2 + checksum: cb4f97ad25a75ebc11a8ef4e33bb962f8af8516bb2001082ceabd8902e15b98f4b84b4f8a9b222e5d57fc3bd1379c483886ed4619367a7680dad65316993021d + languageName: node + linkType: hard + +"safe-array-concat@npm:^1.0.1": + version: 1.0.1 + resolution: "safe-array-concat@npm:1.0.1" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.2.1 + has-symbols: ^1.0.3 + isarray: ^2.0.5 + checksum: 001ecf1d8af398251cbfabaf30ed66e3855127fbceee178179524b24160b49d15442f94ed6c0db0b2e796da76bb05b73bf3cc241490ec9c2b741b41d33058581 + languageName: node + linkType: hard + +"safe-buffer@npm:5.1.2, safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c + languageName: node + linkType: hard + +"safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: b99c4b41fdd67a6aaf280fcd05e9ffb0813654894223afb78a31f14a19ad220bba8aba1cb14eddce1fcfb037155fe6de4e861784eb434f7d11ed58d1e70dd491 + languageName: node + linkType: hard + +"safe-regex-test@npm:^1.0.0": + version: 1.0.2 + resolution: "safe-regex-test@npm:1.0.2" + dependencies: + call-bind: ^1.0.5 + get-intrinsic: ^1.2.2 + is-regex: ^1.1.4 + checksum: 4af5ce05a2daa4f6d4bfd5a3c64fc33d6b886f6592122e93c0efad52f7147b9b605e5ffc03c269a1e3d1f8db2a23bc636628a961c9fd65bafdc09503330673fd + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: cab8f25ae6f1434abee8d80023d7e72b598cf1327164ddab31003c51215526801e40b66c5e65d658a0af1e9d6478cadcb4c745f4bd6751f97d8644786c0978b0 + languageName: node + linkType: hard + +"scheduler@npm:0.24.0-canary-efb381bbf-20230505": + version: 0.24.0-canary-efb381bbf-20230505 + resolution: "scheduler@npm:0.24.0-canary-efb381bbf-20230505" + dependencies: + loose-envify: ^1.1.0 + checksum: 232149125c10f10193b1340ec4bbf14a8e6a845152790d6fd6f58207642db801abdb5a21227561a0a93871b98ba47539a6233b4e6155aae72d6db6db9f9f09b3 + languageName: node + linkType: hard + +"scheduler@npm:^0.23.0": + version: 0.23.0 + resolution: "scheduler@npm:0.23.0" + dependencies: + loose-envify: ^1.1.0 + checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a + languageName: node + linkType: hard + +"semver@npm:^5.6.0": + version: 5.7.2 + resolution: "semver@npm:5.7.2" + bin: + semver: bin/semver + checksum: fb4ab5e0dd1c22ce0c937ea390b4a822147a9c53dbd2a9a0132f12fe382902beef4fbf12cf51bb955248d8d15874ce8cd89532569756384f994309825f10b686 + languageName: node + linkType: hard + +"semver@npm:^6.3.0, semver@npm:^6.3.1": + version: 6.3.1 + resolution: "semver@npm:6.3.1" + bin: + semver: bin/semver.js + checksum: ae47d06de28836adb9d3e25f22a92943477371292d9b665fb023fae278d345d508ca1958232af086d85e0155aee22e313e100971898bbb8d5d89b8b1d4054ca2 + languageName: node + linkType: hard + +"semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4": + version: 7.5.4 + resolution: "semver@npm:7.5.4" + dependencies: + lru-cache: ^6.0.0 + bin: + semver: bin/semver.js + checksum: 12d8ad952fa353b0995bf180cdac205a4068b759a140e5d3c608317098b3575ac2f1e09182206bf2eb26120e1c0ed8fb92c48c592f6099680de56bb071423ca3 + languageName: node + linkType: hard + +"send@npm:0.18.0": + version: 0.18.0 + resolution: "send@npm:0.18.0" + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + etag: ~1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: ~1.2.1 + statuses: 2.0.1 + checksum: 74fc07ebb58566b87b078ec63e5a3e41ecd987e4272ba67b7467e86c6ad51bc6b0b0154133b6d8b08a2ddda360464f71382f7ef864700f34844a76c8027817a8 + languageName: node + linkType: hard + +"serialize-error@npm:^2.1.0": + version: 2.1.0 + resolution: "serialize-error@npm:2.1.0" + checksum: 28464a6f65e6becd6e49fb782aff06573fdbf3d19f161a20228179842fed05c75a34110e54c3ee020b00240f9e11d8bee9b9fee5d04e0bc0bef1fdbf2baa297e + languageName: node + linkType: hard + +"serve-static@npm:^1.13.1": + version: 1.15.0 + resolution: "serve-static@npm:1.15.0" + dependencies: + encodeurl: ~1.0.2 + escape-html: ~1.0.3 + parseurl: ~1.3.3 + send: 0.18.0 + checksum: af57fc13be40d90a12562e98c0b7855cf6e8bd4c107fe9a45c212bf023058d54a1871b1c89511c3958f70626fff47faeb795f5d83f8cf88514dbaeb2b724464d + languageName: node + linkType: hard + +"set-blocking@npm:^2.0.0": + version: 2.0.0 + resolution: "set-blocking@npm:2.0.0" + checksum: 6e65a05f7cf7ebdf8b7c75b101e18c0b7e3dff4940d480efed8aad3a36a4005140b660fa1d804cb8bce911cac290441dc728084a30504d3516ac2ff7ad607b02 + languageName: node + linkType: hard + +"set-function-length@npm:^1.1.1": + version: 1.1.1 + resolution: "set-function-length@npm:1.1.1" + dependencies: + define-data-property: ^1.1.1 + get-intrinsic: ^1.2.1 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.0 + checksum: c131d7569cd7e110cafdfbfbb0557249b538477624dfac4fc18c376d879672fa52563b74029ca01f8f4583a8acb35bb1e873d573a24edb80d978a7ee607c6e06 + languageName: node + linkType: hard + +"set-function-name@npm:^2.0.0, set-function-name@npm:^2.0.1": + version: 2.0.1 + resolution: "set-function-name@npm:2.0.1" + dependencies: + define-data-property: ^1.0.1 + functions-have-names: ^1.2.3 + has-property-descriptors: ^1.0.0 + checksum: 4975d17d90c40168eee2c7c9c59d023429f0a1690a89d75656306481ece0c3c1fb1ebcc0150ea546d1913e35fbd037bace91372c69e543e51fc5d1f31a9fa126 + languageName: node + linkType: hard + +"setprototypeof@npm:1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: be18cbbf70e7d8097c97f713a2e76edf84e87299b40d085c6bf8b65314e994cc15e2e317727342fa6996e38e1f52c59720b53fe621e2eb593a6847bf0356db89 + languageName: node + linkType: hard + +"shallow-clone@npm:^3.0.0": + version: 3.0.1 + resolution: "shallow-clone@npm:3.0.1" + dependencies: + kind-of: ^6.0.2 + checksum: 39b3dd9630a774aba288a680e7d2901f5c0eae7b8387fc5c8ea559918b29b3da144b7bdb990d7ccd9e11be05508ac9e459ce51d01fd65e583282f6ffafcba2e7 + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: ^3.0.0 + checksum: 6b52fe87271c12968f6a054e60f6bde5f0f3d2db483a1e5c3e12d657c488a15474121a1d55cd958f6df026a54374ec38a4a963988c213b7570e1d51575cea7fa + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 1a2bcae50de99034fcd92ad4212d8e01eedf52c7ec7830eedcf886622804fe36884278f2be8be0ea5fde3fd1c23911643a4e0f726c8685b61871c8908af01222 + languageName: node + linkType: hard + +"shell-quote@npm:^1.6.1, shell-quote@npm:^1.7.3": + version: 1.8.1 + resolution: "shell-quote@npm:1.8.1" + checksum: 5f01201f4ef504d4c6a9d0d283fa17075f6770bfbe4c5850b074974c68062f37929ca61700d95ad2ac8822e14e8c4b990ca0e6e9272e64befd74ce5e19f0736b + languageName: node + linkType: hard + +"side-channel@npm:^1.0.4": + version: 1.0.4 + resolution: "side-channel@npm:1.0.4" + dependencies: + call-bind: ^1.0.0 + get-intrinsic: ^1.0.2 + object-inspect: ^1.9.0 + checksum: 351e41b947079c10bd0858364f32bb3a7379514c399edb64ab3dce683933483fc63fb5e4efe0a15a2e8a7e3c436b6a91736ddb8d8c6591b0460a24bb4a1ee245 + languageName: node + linkType: hard + +"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318 + languageName: node + linkType: hard + +"signal-exit@npm:^4.0.1": + version: 4.1.0 + resolution: "signal-exit@npm:4.1.0" + checksum: 64c757b498cb8629ffa5f75485340594d2f8189e9b08700e69199069c8e3070fb3e255f7ab873c05dc0b3cec412aea7402e10a5990cb6a050bd33ba062a6c549 + languageName: node + linkType: hard + +"sisteransi@npm:^1.0.5": + version: 1.0.5 + resolution: "sisteransi@npm:1.0.5" + checksum: aba6438f46d2bfcef94cf112c835ab395172c75f67453fe05c340c770d3c402363018ae1ab4172a1026a90c47eaccf3af7b6ff6fa749a680c2929bd7fa2b37a4 + languageName: node + linkType: hard + +"slash@npm:^3.0.0": + version: 3.0.0 + resolution: "slash@npm:3.0.0" + checksum: 94a93fff615f25a999ad4b83c9d5e257a7280c90a32a7cb8b4a87996e4babf322e469c42b7f649fd5796edd8687652f3fb452a86dc97a816f01113183393f11c + languageName: node + linkType: hard + +"slice-ansi@npm:^2.0.0": + version: 2.1.0 + resolution: "slice-ansi@npm:2.1.0" + dependencies: + ansi-styles: ^3.2.0 + astral-regex: ^1.0.0 + is-fullwidth-code-point: ^2.0.0 + checksum: 4e82995aa59cef7eb03ef232d73c2239a15efa0ace87a01f3012ebb942e963fbb05d448ce7391efcd52ab9c32724164aba2086f5143e0445c969221dde3b6b1e + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: b5167a7142c1da704c0e3af85c402002b597081dd9575031a90b4f229ca5678e9a36e8a374f1814c8156a725d17008ae3bde63b92f9cfd132526379e580bec8b + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.1": + version: 8.0.2 + resolution: "socks-proxy-agent@npm:8.0.2" + dependencies: + agent-base: ^7.0.2 + debug: ^4.3.4 + socks: ^2.7.1 + checksum: 4fb165df08f1f380881dcd887b3cdfdc1aba3797c76c1e9f51d29048be6e494c5b06d68e7aea2e23df4572428f27a3ec22b3d7c75c570c5346507433899a4b6d + languageName: node + linkType: hard + +"socks@npm:^2.7.1": + version: 2.7.1 + resolution: "socks@npm:2.7.1" + dependencies: + ip: ^2.0.0 + smart-buffer: ^4.2.0 + checksum: 259d9e3e8e1c9809a7f5c32238c3d4d2a36b39b83851d0f573bfde5f21c4b1288417ce1af06af1452569cd1eb0841169afd4998f0e04ba04656f6b7f0e46d748 + languageName: node + linkType: hard + +"source-map-support@npm:0.5.13": + version: 0.5.13 + resolution: "source-map-support@npm:0.5.13" + dependencies: + buffer-from: ^1.0.0 + source-map: ^0.6.0 + checksum: 933550047b6c1a2328599a21d8b7666507427c0f5ef5eaadd56b5da0fd9505e239053c66fe181bf1df469a3b7af9d775778eee283cbb7ae16b902ddc09e93a97 + languageName: node + linkType: hard + +"source-map-support@npm:^0.5.16, source-map-support@npm:~0.5.20": + version: 0.5.21 + resolution: "source-map-support@npm:0.5.21" + dependencies: + buffer-from: ^1.0.0 + source-map: ^0.6.0 + checksum: 43e98d700d79af1d36f859bdb7318e601dfc918c7ba2e98456118ebc4c4872b327773e5a1df09b0524e9e5063bb18f0934538eace60cca2710d1fa687645d137 + languageName: node + linkType: hard + +"source-map@npm:^0.5.6": + version: 0.5.7 + resolution: "source-map@npm:0.5.7" + checksum: 5dc2043b93d2f194142c7f38f74a24670cd7a0063acdaf4bf01d2964b402257ae843c2a8fa822ad5b71013b5fcafa55af7421383da919752f22ff488bc553f4d + languageName: node + linkType: hard + +"source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.1": + version: 0.6.1 + resolution: "source-map@npm:0.6.1" + checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 + languageName: node + linkType: hard + +"source-map@npm:^0.7.3": + version: 0.7.4 + resolution: "source-map@npm:0.7.4" + checksum: 01cc5a74b1f0e1d626a58d36ad6898ea820567e87f18dfc9d24a9843a351aaa2ec09b87422589906d6ff1deed29693e176194dc88bcae7c9a852dc74b311dbf5 + languageName: node + linkType: hard + +"sprintf-js@npm:~1.0.2": + version: 1.0.3 + resolution: "sprintf-js@npm:1.0.3" + checksum: 19d79aec211f09b99ec3099b5b2ae2f6e9cdefe50bc91ac4c69144b6d3928a640bb6ae5b3def70c2e85a2c3d9f5ec2719921e3a59d3ca3ef4b2fd1a4656a0df3 + languageName: node + linkType: hard + +"ssri@npm:^10.0.0": + version: 10.0.5 + resolution: "ssri@npm:10.0.5" + dependencies: + minipass: ^7.0.3 + checksum: 0a31b65f21872dea1ed3f7c200d7bc1c1b91c15e419deca14f282508ba917cbb342c08a6814c7f68ca4ca4116dd1a85da2bbf39227480e50125a1ceffeecb750 + languageName: node + linkType: hard + +"stack-utils@npm:^2.0.3": + version: 2.0.6 + resolution: "stack-utils@npm:2.0.6" + dependencies: + escape-string-regexp: ^2.0.0 + checksum: 052bf4d25bbf5f78e06c1d5e67de2e088b06871fa04107ca8d3f0e9d9263326e2942c8bedee3545795fc77d787d443a538345eef74db2f8e35db3558c6f91ff7 + languageName: node + linkType: hard + +"stackframe@npm:^1.3.4": + version: 1.3.4 + resolution: "stackframe@npm:1.3.4" + checksum: bae1596873595c4610993fa84f86a3387d67586401c1816ea048c0196800c0646c4d2da98c2ee80557fd9eff05877efe33b91ba6cd052658ed96ddc85d19067d + languageName: node + linkType: hard + +"stacktrace-parser@npm:^0.1.10": + version: 0.1.10 + resolution: "stacktrace-parser@npm:0.1.10" + dependencies: + type-fest: ^0.7.1 + checksum: f4fbddfc09121d91e587b60de4beb4941108e967d71ad3a171812dc839b010ca374d064ad0a296295fed13acd103609d99a4224a25b4e67de13cae131f1901ee + languageName: node + linkType: hard + +"statuses@npm:2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb + languageName: node + linkType: hard + +"statuses@npm:~1.5.0": + version: 1.5.0 + resolution: "statuses@npm:1.5.0" + checksum: c469b9519de16a4bb19600205cffb39ee471a5f17b82589757ca7bd40a8d92ebb6ed9f98b5a540c5d302ccbc78f15dc03cc0280dd6e00df1335568a5d5758a5c + languageName: node + linkType: hard + +"string-length@npm:^4.0.1": + version: 4.0.2 + resolution: "string-length@npm:4.0.2" + dependencies: + char-regex: ^1.0.2 + strip-ansi: ^6.0.0 + checksum: ce85533ef5113fcb7e522bcf9e62cb33871aa99b3729cec5595f4447f660b0cefd542ca6df4150c97a677d58b0cb727a3fe09ac1de94071d05526c73579bf505 + languageName: node + linkType: hard + +"string-natural-compare@npm:^3.0.1": + version: 3.0.1 + resolution: "string-natural-compare@npm:3.0.1" + checksum: 65910d9995074086e769a68728395effbba9b7186be5b4c16a7fad4f4ef50cae95ca16e3e9086e019cbb636ae8daac9c7b8fe91b5f21865c5c0f26e3c0725406 + languageName: node + linkType: hard + +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": + version: 4.2.3 + resolution: "string-width@npm:4.2.3" + dependencies: + emoji-regex: ^8.0.0 + is-fullwidth-code-point: ^3.0.0 + strip-ansi: ^6.0.1 + checksum: e52c10dc3fbfcd6c3a15f159f54a90024241d0f149cf8aed2982a2d801d2e64df0bf1dc351cf8e95c3319323f9f220c16e740b06faecd53e2462df1d2b5443fb + languageName: node + linkType: hard + +"string-width@npm:^5.0.1, string-width@npm:^5.1.2": + version: 5.1.2 + resolution: "string-width@npm:5.1.2" + dependencies: + eastasianwidth: ^0.2.0 + emoji-regex: ^9.2.2 + strip-ansi: ^7.0.1 + checksum: 7369deaa29f21dda9a438686154b62c2c5f661f8dda60449088f9f980196f7908fc39fdd1803e3e01541970287cf5deae336798337e9319a7055af89dafa7193 + languageName: node + linkType: hard + +"string.prototype.matchall@npm:^4.0.8": + version: 4.0.10 + resolution: "string.prototype.matchall@npm:4.0.10" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + get-intrinsic: ^1.2.1 + has-symbols: ^1.0.3 + internal-slot: ^1.0.5 + regexp.prototype.flags: ^1.5.0 + set-function-name: ^2.0.0 + side-channel: ^1.0.4 + checksum: 3c78bdeff39360c8e435d7c4c6ea19f454aa7a63eda95fa6fadc3a5b984446a2f9f2c02d5c94171ce22268a573524263fbd0c8edbe3ce2e9890d7cc036cdc3ed + languageName: node + linkType: hard + +"string.prototype.trim@npm:^1.2.8": + version: 1.2.8 + resolution: "string.prototype.trim@npm:1.2.8" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + checksum: 49eb1a862a53aba73c3fb6c2a53f5463173cb1f4512374b623bcd6b43ad49dd559a06fb5789bdec771a40fc4d2a564411c0a75d35fb27e76bbe738c211ecff07 + languageName: node + linkType: hard + +"string.prototype.trimend@npm:^1.0.7": + version: 1.0.7 + resolution: "string.prototype.trimend@npm:1.0.7" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + checksum: 2375516272fd1ba75992f4c4aa88a7b5f3c7a9ca308d963bcd5645adf689eba6f8a04ebab80c33e30ec0aefc6554181a3a8416015c38da0aa118e60ec896310c + languageName: node + linkType: hard + +"string.prototype.trimstart@npm:^1.0.7": + version: 1.0.7 + resolution: "string.prototype.trimstart@npm:1.0.7" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.2.0 + es-abstract: ^1.22.1 + checksum: 13d0c2cb0d5ff9e926fa0bec559158b062eed2b68cd5be777ffba782c96b2b492944e47057274e064549b94dd27cf81f48b27a31fee8af5b574cff253e7eb613 + languageName: node + linkType: hard + +"string_decoder@npm:^1.1.1": + version: 1.3.0 + resolution: "string_decoder@npm:1.3.0" + dependencies: + safe-buffer: ~5.2.0 + checksum: 8417646695a66e73aefc4420eb3b84cc9ffd89572861fe004e6aeb13c7bc00e2f616247505d2dbbef24247c372f70268f594af7126f43548565c68c117bdeb56 + languageName: node + linkType: hard + +"string_decoder@npm:~1.1.1": + version: 1.1.1 + resolution: "string_decoder@npm:1.1.1" + dependencies: + safe-buffer: ~5.1.0 + checksum: 9ab7e56f9d60a28f2be697419917c50cac19f3e8e6c28ef26ed5f4852289fe0de5d6997d29becf59028556f2c62983790c1d9ba1e2a3cc401768ca12d5183a5b + languageName: node + linkType: hard + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": + version: 6.0.1 + resolution: "strip-ansi@npm:6.0.1" + dependencies: + ansi-regex: ^5.0.1 + checksum: f3cd25890aef3ba6e1a74e20896c21a46f482e93df4a06567cebf2b57edabb15133f1f94e57434e0a958d61186087b1008e89c94875d019910a213181a14fc8c + languageName: node + linkType: hard + +"strip-ansi@npm:^5.0.0, strip-ansi@npm:^5.2.0": + version: 5.2.0 + resolution: "strip-ansi@npm:5.2.0" + dependencies: + ansi-regex: ^4.1.0 + checksum: bdb5f76ade97062bd88e7723aa019adbfacdcba42223b19ccb528ffb9fb0b89a5be442c663c4a3fb25268eaa3f6ea19c7c3fbae830bd1562d55adccae1fcec46 + languageName: node + linkType: hard + +"strip-ansi@npm:^7.0.1": + version: 7.1.0 + resolution: "strip-ansi@npm:7.1.0" + dependencies: + ansi-regex: ^6.0.1 + checksum: 859c73fcf27869c22a4e4d8c6acfe690064659e84bef9458aa6d13719d09ca88dcfd40cbf31fd0be63518ea1a643fe070b4827d353e09533a5b0b9fd4553d64d + languageName: node + linkType: hard + +"strip-bom@npm:^4.0.0": + version: 4.0.0 + resolution: "strip-bom@npm:4.0.0" + checksum: 9dbcfbaf503c57c06af15fe2c8176fb1bf3af5ff65003851a102749f875a6dbe0ab3b30115eccf6e805e9d756830d3e40ec508b62b3f1ddf3761a20ebe29d3f3 + languageName: node + linkType: hard + +"strip-final-newline@npm:^2.0.0": + version: 2.0.0 + resolution: "strip-final-newline@npm:2.0.0" + checksum: 69412b5e25731e1938184b5d489c32e340605bb611d6140344abc3421b7f3c6f9984b21dff296dfcf056681b82caa3bb4cc996a965ce37bcfad663e92eae9c64 + languageName: node + linkType: hard + +"strip-indent@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-indent@npm:3.0.0" + dependencies: + min-indent: ^1.0.0 + checksum: 18f045d57d9d0d90cd16f72b2313d6364fd2cb4bf85b9f593523ad431c8720011a4d5f08b6591c9d580f446e78855c5334a30fb91aa1560f5d9f95ed1b4a0530 + languageName: node + linkType: hard + +"strip-json-comments@npm:^3.1.1": + version: 3.1.1 + resolution: "strip-json-comments@npm:3.1.1" + checksum: 492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 + languageName: node + linkType: hard + +"strnum@npm:^1.0.5": + version: 1.0.5 + resolution: "strnum@npm:1.0.5" + checksum: 651b2031db5da1bf4a77fdd2f116a8ac8055157c5420f5569f64879133825915ad461513e7202a16d7fec63c54fd822410d0962f8ca12385c4334891b9ae6dd2 + languageName: node + linkType: hard + +"sudo-prompt@npm:^9.0.0": + version: 9.2.1 + resolution: "sudo-prompt@npm:9.2.1" + checksum: 50a29eec2f264f2b78d891452a64112d839a30bffbff4ec065dba4af691a35b23cdb8f9107d413e25c1a9f1925644a19994c00602495cab033d53f585fdfd665 + languageName: node + linkType: hard + +"supports-color@npm:^5.3.0": + version: 5.5.0 + resolution: "supports-color@npm:5.5.0" + dependencies: + has-flag: ^3.0.0 + checksum: 95f6f4ba5afdf92f495b5a912d4abee8dcba766ae719b975c56c084f5004845f6f5a5f7769f52d53f40e21952a6d87411bafe34af4a01e65f9926002e38e1dac + languageName: node + linkType: hard + +"supports-color@npm:^7.1.0": + version: 7.2.0 + resolution: "supports-color@npm:7.2.0" + dependencies: + has-flag: ^4.0.0 + checksum: 3dda818de06ebbe5b9653e07842d9479f3555ebc77e9a0280caf5a14fb877ffee9ed57007c3b78f5a6324b8dbeec648d9e97a24e2ed9fdb81ddc69ea07100f4a + languageName: node + linkType: hard + +"supports-color@npm:^8.0.0": + version: 8.1.1 + resolution: "supports-color@npm:8.1.1" + dependencies: + has-flag: ^4.0.0 + checksum: c052193a7e43c6cdc741eb7f378df605636e01ad434badf7324f17fb60c69a880d8d8fcdcb562cf94c2350e57b937d7425ab5b8326c67c2adc48f7c87c1db406 + languageName: node + linkType: hard + +"supports-preserve-symlinks-flag@npm:^1.0.0": + version: 1.0.0 + resolution: "supports-preserve-symlinks-flag@npm:1.0.0" + checksum: 53b1e247e68e05db7b3808b99b892bd36fb096e6fba213a06da7fab22045e97597db425c724f2bbd6c99a3c295e1e73f3e4de78592289f38431049e1277ca0ae + languageName: node + linkType: hard + +"synckit@npm:^0.8.6": + version: 0.8.8 + resolution: "synckit@npm:0.8.8" + dependencies: + "@pkgr/core": ^0.1.0 + tslib: ^2.6.2 + checksum: 9ed5d33abb785f5f24e2531efd53b2782ca77abf7912f734d170134552b99001915531be5a50297aa45c5701b5c9041e8762e6cd7a38e41e2461c1e7fccdedf8 + languageName: node + linkType: hard + +"tar@npm:^6.1.11, tar@npm:^6.1.2": + version: 6.2.0 + resolution: "tar@npm:6.2.0" + dependencies: + chownr: ^2.0.0 + fs-minipass: ^2.0.0 + minipass: ^5.0.0 + minizlib: ^2.1.1 + mkdirp: ^1.0.3 + yallist: ^4.0.0 + checksum: db4d9fe74a2082c3a5016630092c54c8375ff3b280186938cfd104f2e089c4fd9bad58688ef6be9cf186a889671bf355c7cda38f09bbf60604b281715ca57f5c + languageName: node + linkType: hard + +"temp-dir@npm:^2.0.0": + version: 2.0.0 + resolution: "temp-dir@npm:2.0.0" + checksum: cc4f0404bf8d6ae1a166e0e64f3f409b423f4d1274d8c02814a59a5529f07db6cd070a749664141b992b2c1af337fa9bb451a460a43bb9bcddc49f235d3115aa + languageName: node + linkType: hard + +"temp@npm:^0.8.4": + version: 0.8.4 + resolution: "temp@npm:0.8.4" + dependencies: + rimraf: ~2.6.2 + checksum: f35bed78565355dfdf95f730b7b489728bd6b7e35071bcc6497af7c827fb6c111fbe9063afc7b8cbc19522a072c278679f9a0ee81e684aa2c8617cc0f2e9c191 + languageName: node + linkType: hard + +"terser@npm:^5.15.0": + version: 5.26.0 + resolution: "terser@npm:5.26.0" + dependencies: + "@jridgewell/source-map": ^0.3.3 + acorn: ^8.8.2 + commander: ^2.20.0 + source-map-support: ~0.5.20 + bin: + terser: bin/terser + checksum: 02a9bb896f04df828025af8f0eced36c315d25d310b6c2418e7dad2bed19ddeb34a9cea9b34e7c24789830fa51e1b6a9be26679980987a9c817a7e6d9cd4154b + languageName: node + linkType: hard + +"test-exclude@npm:^6.0.0": + version: 6.0.0 + resolution: "test-exclude@npm:6.0.0" + dependencies: + "@istanbuljs/schema": ^0.1.2 + glob: ^7.1.4 + minimatch: ^3.0.4 + checksum: 3b34a3d77165a2cb82b34014b3aba93b1c4637a5011807557dc2f3da826c59975a5ccad765721c4648b39817e3472789f9b0fa98fc854c5c1c7a1e632aacdc28 + languageName: node + linkType: hard + +"text-table@npm:^0.2.0": + version: 0.2.0 + resolution: "text-table@npm:0.2.0" + checksum: b6937a38c80c7f84d9c11dd75e49d5c44f71d95e810a3250bd1f1797fc7117c57698204adf676b71497acc205d769d65c16ae8fa10afad832ae1322630aef10a + languageName: node + linkType: hard + +"throat@npm:^5.0.0": + version: 5.0.0 + resolution: "throat@npm:5.0.0" + checksum: 031ff7f4431618036c1dedd99c8aa82f5c33077320a8358ed829e84b320783781d1869fe58e8f76e948306803de966f5f7573766a437562c9f5c033297ad2fe2 + languageName: node + linkType: hard + +"through2@npm:^2.0.1": + version: 2.0.5 + resolution: "through2@npm:2.0.5" + dependencies: + readable-stream: ~2.3.6 + xtend: ~4.0.1 + checksum: beb0f338aa2931e5660ec7bf3ad949e6d2e068c31f4737b9525e5201b824ac40cac6a337224856b56bd1ddd866334bbfb92a9f57cd6f66bc3f18d3d86fc0fe50 + languageName: node + linkType: hard + +"tmpl@npm:1.0.5": + version: 1.0.5 + resolution: "tmpl@npm:1.0.5" + checksum: cd922d9b853c00fe414c5a774817be65b058d54a2d01ebb415840960406c669a0fc632f66df885e24cb022ec812739199ccbdb8d1164c3e513f85bfca5ab2873 + languageName: node + linkType: hard + +"to-fast-properties@npm:^2.0.0": + version: 2.0.0 + resolution: "to-fast-properties@npm:2.0.0" + checksum: be2de62fe58ead94e3e592680052683b1ec986c72d589e7b21e5697f8744cdbf48c266fa72f6c15932894c10187b5f54573a3bcf7da0bfd964d5caf23d436168 + languageName: node + linkType: hard + +"to-regex-range@npm:^5.0.1": + version: 5.0.1 + resolution: "to-regex-range@npm:5.0.1" + dependencies: + is-number: ^7.0.0 + checksum: f76fa01b3d5be85db6a2a143e24df9f60dd047d151062d0ba3df62953f2f697b16fe5dad9b0ac6191c7efc7b1d9dcaa4b768174b7b29da89d4428e64bc0a20ed + languageName: node + linkType: hard + +"toidentifier@npm:1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45 + languageName: node + linkType: hard + +"tr46@npm:~0.0.3": + version: 0.0.3 + resolution: "tr46@npm:0.0.3" + checksum: 726321c5eaf41b5002e17ffbd1fb7245999a073e8979085dacd47c4b4e8068ff5777142fc6726d6ca1fd2ff16921b48788b87225cbc57c72636f6efa8efbffe3 + languageName: node + linkType: hard + +"ts-api-utils@npm:^1.0.1": + version: 1.0.3 + resolution: "ts-api-utils@npm:1.0.3" + peerDependencies: + typescript: ">=4.2.0" + checksum: 441cc4489d65fd515ae6b0f4eb8690057add6f3b6a63a36073753547fb6ce0c9ea0e0530220a0b282b0eec535f52c4dfc315d35f8a4c9a91c0def0707a714ca6 + languageName: node + linkType: hard + +"ts-node@npm:^10.9.2": + version: 10.9.2 + resolution: "ts-node@npm:10.9.2" + dependencies: + "@cspotcode/source-map-support": ^0.8.0 + "@tsconfig/node10": ^1.0.7 + "@tsconfig/node12": ^1.0.7 + "@tsconfig/node14": ^1.0.0 + "@tsconfig/node16": ^1.0.2 + acorn: ^8.4.1 + acorn-walk: ^8.1.1 + arg: ^4.1.0 + create-require: ^1.1.0 + diff: ^4.0.1 + make-error: ^1.1.1 + v8-compile-cache-lib: ^3.0.1 + yn: 3.1.1 + peerDependencies: + "@swc/core": ">=1.2.50" + "@swc/wasm": ">=1.2.50" + "@types/node": "*" + typescript: ">=2.7" + peerDependenciesMeta: + "@swc/core": + optional: true + "@swc/wasm": + optional: true + bin: + ts-node: dist/bin.js + ts-node-cwd: dist/bin-cwd.js + ts-node-esm: dist/bin-esm.js + ts-node-script: dist/bin-script.js + ts-node-transpile-only: dist/bin-transpile.js + ts-script: dist/bin-script-deprecated.js + checksum: fde256c9073969e234526e2cfead42591b9a2aec5222bac154b0de2fa9e4ceb30efcd717ee8bc785a56f3a119bdd5aa27b333d9dbec94ed254bd26f8944c67ac + languageName: node + linkType: hard + +"tslib@npm:^1.8.1": + version: 1.14.1 + resolution: "tslib@npm:1.14.1" + checksum: dbe628ef87f66691d5d2959b3e41b9ca0045c3ee3c7c7b906cc1e328b39f199bb1ad9e671c39025bd56122ac57dfbf7385a94843b1cc07c60a4db74795829acd + languageName: node + linkType: hard + +"tslib@npm:^2.0.1, tslib@npm:^2.6.2": + version: 2.6.2 + resolution: "tslib@npm:2.6.2" + checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad + languageName: node + linkType: hard + +"tsutils@npm:^3.21.0": + version: 3.21.0 + resolution: "tsutils@npm:3.21.0" + dependencies: + tslib: ^1.8.1 + peerDependencies: + typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + checksum: 1843f4c1b2e0f975e08c4c21caa4af4f7f65a12ac1b81b3b8489366826259323feb3fc7a243123453d2d1a02314205a7634e048d4a8009921da19f99755cdc48 + languageName: node + linkType: hard + +"type-check@npm:^0.4.0, type-check@npm:~0.4.0": + version: 0.4.0 + resolution: "type-check@npm:0.4.0" + dependencies: + prelude-ls: ^1.2.1 + checksum: ec688ebfc9c45d0c30412e41ca9c0cdbd704580eb3a9ccf07b9b576094d7b86a012baebc95681999dd38f4f444afd28504cb3a89f2ef16b31d4ab61a0739025a + languageName: node + linkType: hard + +"type-detect@npm:4.0.8": + version: 4.0.8 + resolution: "type-detect@npm:4.0.8" + checksum: 62b5628bff67c0eb0b66afa371bd73e230399a8d2ad30d852716efcc4656a7516904570cd8631a49a3ce57c10225adf5d0cbdcb47f6b0255fe6557c453925a15 + languageName: node + linkType: hard + +"type-fest@npm:^0.20.2": + version: 0.20.2 + resolution: "type-fest@npm:0.20.2" + checksum: 4fb3272df21ad1c552486f8a2f8e115c09a521ad7a8db3d56d53718d0c907b62c6e9141ba5f584af3f6830d0872c521357e512381f24f7c44acae583ad517d73 + languageName: node + linkType: hard + +"type-fest@npm:^0.21.3": + version: 0.21.3 + resolution: "type-fest@npm:0.21.3" + checksum: e6b32a3b3877f04339bae01c193b273c62ba7bfc9e325b8703c4ee1b32dc8fe4ef5dfa54bf78265e069f7667d058e360ae0f37be5af9f153b22382cd55a9afe0 + languageName: node + linkType: hard + +"type-fest@npm:^0.7.1": + version: 0.7.1 + resolution: "type-fest@npm:0.7.1" + checksum: 5b1b113529d59949d97b76977d545989ddc11b81bb0c766b6d2ccc65473cb4b4a5c7d24f5be2c2bb2de302a5d7a13c1732ea1d34c8c59b7e0ec1f890cf7fc424 + languageName: node + linkType: hard + +"typed-array-buffer@npm:^1.0.0": + version: 1.0.0 + resolution: "typed-array-buffer@npm:1.0.0" + dependencies: + call-bind: ^1.0.2 + get-intrinsic: ^1.2.1 + is-typed-array: ^1.1.10 + checksum: 3e0281c79b2a40cd97fe715db803884301993f4e8c18e8d79d75fd18f796e8cd203310fec8c7fdb5e6c09bedf0af4f6ab8b75eb3d3a85da69328f28a80456bd3 + languageName: node + linkType: hard + +"typed-array-byte-length@npm:^1.0.0": + version: 1.0.0 + resolution: "typed-array-byte-length@npm:1.0.0" + dependencies: + call-bind: ^1.0.2 + for-each: ^0.3.3 + has-proto: ^1.0.1 + is-typed-array: ^1.1.10 + checksum: b03db16458322b263d87a702ff25388293f1356326c8a678d7515767ef563ef80e1e67ce648b821ec13178dd628eb2afdc19f97001ceae7a31acf674c849af94 + languageName: node + linkType: hard + +"typed-array-byte-offset@npm:^1.0.0": + version: 1.0.0 + resolution: "typed-array-byte-offset@npm:1.0.0" + dependencies: + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.2 + for-each: ^0.3.3 + has-proto: ^1.0.1 + is-typed-array: ^1.1.10 + checksum: 04f6f02d0e9a948a95fbfe0d5a70b002191fae0b8fe0fe3130a9b2336f043daf7a3dda56a31333c35a067a97e13f539949ab261ca0f3692c41603a46a94e960b + languageName: node + linkType: hard + +"typed-array-length@npm:^1.0.4": + version: 1.0.4 + resolution: "typed-array-length@npm:1.0.4" + dependencies: + call-bind: ^1.0.2 + for-each: ^0.3.3 + is-typed-array: ^1.1.9 + checksum: 2228febc93c7feff142b8c96a58d4a0d7623ecde6c7a24b2b98eb3170e99f7c7eff8c114f9b283085cd59dcd2bd43aadf20e25bba4b034a53c5bb292f71f8956 + languageName: node + linkType: hard + +"typescript@npm:^5.3.3": + version: 5.3.3 + resolution: "typescript@npm:5.3.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 2007ccb6e51bbbf6fde0a78099efe04dc1c3dfbdff04ca3b6a8bc717991862b39fd6126c0c3ebf2d2d98ac5e960bcaa873826bb2bb241f14277034148f41f6a2 + languageName: node + linkType: hard + +"typescript@patch:typescript@^5.3.3#~builtin": + version: 5.3.3 + resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=701156" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: f61375590b3162599f0f0d5b8737877ac0a7bc52761dbb585d67e7b8753a3a4c42d9a554c4cc929f591ffcf3a2b0602f65ae3ce74714fd5652623a816862b610 + languageName: node + linkType: hard + +"unbox-primitive@npm:^1.0.2": + version: 1.0.2 + resolution: "unbox-primitive@npm:1.0.2" + dependencies: + call-bind: ^1.0.2 + has-bigints: ^1.0.2 + has-symbols: ^1.0.3 + which-boxed-primitive: ^1.0.2 + checksum: b7a1cf5862b5e4b5deb091672ffa579aa274f648410009c81cca63fed3b62b610c4f3b773f912ce545bb4e31edc3138975b5bc777fc6e4817dca51affb6380e9 + languageName: node + linkType: hard + +"undici-types@npm:~5.26.4": + version: 5.26.5 + resolution: "undici-types@npm:5.26.5" + checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 + languageName: node + linkType: hard + +"unicode-canonical-property-names-ecmascript@npm:^2.0.0": + version: 2.0.0 + resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" + checksum: 39be078afd014c14dcd957a7a46a60061bc37c4508ba146517f85f60361acf4c7539552645ece25de840e17e293baa5556268d091ca6762747fdd0c705001a45 + languageName: node + linkType: hard + +"unicode-match-property-ecmascript@npm:^2.0.0": + version: 2.0.0 + resolution: "unicode-match-property-ecmascript@npm:2.0.0" + dependencies: + unicode-canonical-property-names-ecmascript: ^2.0.0 + unicode-property-aliases-ecmascript: ^2.0.0 + checksum: 1f34a7434a23df4885b5890ac36c5b2161a809887000be560f56ad4b11126d433c0c1c39baf1016bdabed4ec54829a6190ee37aa24919aa116dc1a5a8a62965a + languageName: node + linkType: hard + +"unicode-match-property-value-ecmascript@npm:^2.1.0": + version: 2.1.0 + resolution: "unicode-match-property-value-ecmascript@npm:2.1.0" + checksum: 8d6f5f586b9ce1ed0e84a37df6b42fdba1317a05b5df0c249962bd5da89528771e2d149837cad11aa26bcb84c35355cb9f58a10c3d41fa3b899181ece6c85220 + languageName: node + linkType: hard + +"unicode-property-aliases-ecmascript@npm:^2.0.0": + version: 2.1.0 + resolution: "unicode-property-aliases-ecmascript@npm:2.1.0" + checksum: 243524431893649b62cc674d877bd64ef292d6071dd2fd01ab4d5ad26efbc104ffcd064f93f8a06b7e4ec54c172bf03f6417921a0d8c3a9994161fe1f88f815b + languageName: node + linkType: hard + +"unique-filename@npm:^3.0.0": + version: 3.0.0 + resolution: "unique-filename@npm:3.0.0" + dependencies: + unique-slug: ^4.0.0 + checksum: 8e2f59b356cb2e54aab14ff98a51ac6c45781d15ceaab6d4f1c2228b780193dc70fae4463ce9e1df4479cb9d3304d7c2043a3fb905bdeca71cc7e8ce27e063df + languageName: node + linkType: hard + +"unique-slug@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-slug@npm:4.0.0" + dependencies: + imurmurhash: ^0.1.4 + checksum: 0884b58365af59f89739e6f71e3feacb5b1b41f2df2d842d0757933620e6de08eff347d27e9d499b43c40476cbaf7988638d3acb2ffbcb9d35fd035591adfd15 + languageName: node + linkType: hard + +"universalify@npm:^0.1.0": + version: 0.1.2 + resolution: "universalify@npm:0.1.2" + checksum: 40cdc60f6e61070fe658ca36016a8f4ec216b29bf04a55dce14e3710cc84c7448538ef4dad3728d0bfe29975ccd7bfb5f414c45e7b78883567fb31b246f02dff + languageName: node + linkType: hard + +"unpipe@npm:~1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 + languageName: node + linkType: hard + +"update-browserslist-db@npm:^1.0.13": + version: 1.0.13 + resolution: "update-browserslist-db@npm:1.0.13" + dependencies: + escalade: ^3.1.1 + picocolors: ^1.0.0 + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 1e47d80182ab6e4ad35396ad8b61008ae2a1330221175d0abd37689658bdb61af9b705bfc41057fd16682474d79944fb2d86767c5ed5ae34b6276b9bed353322 + languageName: node + linkType: hard + +"uri-js@npm:^4.2.2": + version: 4.4.1 + resolution: "uri-js@npm:4.4.1" + dependencies: + punycode: ^2.1.0 + checksum: 7167432de6817fe8e9e0c9684f1d2de2bb688c94388f7569f7dbdb1587c9f4ca2a77962f134ec90be0cc4d004c939ff0d05acc9f34a0db39a3c797dada262633 + languageName: node + linkType: hard + +"use-sync-external-store@npm:^1.0.0": + version: 1.2.0 + resolution: "use-sync-external-store@npm:1.2.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + checksum: 5c639e0f8da3521d605f59ce5be9e094ca772bd44a4ce7322b055a6f58eeed8dda3c94cabd90c7a41fb6fa852210092008afe48f7038792fd47501f33299116a + languageName: node + linkType: hard + +"util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 + languageName: node + linkType: hard + +"utils-merge@npm:1.0.1": + version: 1.0.1 + resolution: "utils-merge@npm:1.0.1" + checksum: c81095493225ecfc28add49c106ca4f09cdf56bc66731aa8dabc2edbbccb1e1bfe2de6a115e5c6a380d3ea166d1636410b62ef216bb07b3feb1cfde1d95d5080 + languageName: node + linkType: hard + +"v8-compile-cache-lib@npm:^3.0.1": + version: 3.0.1 + resolution: "v8-compile-cache-lib@npm:3.0.1" + checksum: 78089ad549e21bcdbfca10c08850022b22024cdcc2da9b168bcf5a73a6ed7bf01a9cebb9eac28e03cd23a684d81e0502797e88f3ccd27a32aeab1cfc44c39da0 + languageName: node + linkType: hard + +"v8-to-istanbul@npm:^9.0.1": + version: 9.2.0 + resolution: "v8-to-istanbul@npm:9.2.0" + dependencies: + "@jridgewell/trace-mapping": ^0.3.12 + "@types/istanbul-lib-coverage": ^2.0.1 + convert-source-map: ^2.0.0 + checksum: 31ef98c6a31b1dab6be024cf914f235408cd4c0dc56a5c744a5eea1a9e019ba279e1b6f90d695b78c3186feed391ed492380ccf095009e2eb91f3d058f0b4491 + languageName: node + linkType: hard + +"vary@npm:~1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: ae0123222c6df65b437669d63dfa8c36cee20a504101b2fcd97b8bf76f91259c17f9f2b4d70a1e3c6bbcee7f51b28392833adb6b2770b23b01abec84e369660b + languageName: node + linkType: hard + +"vlq@npm:^1.0.0": + version: 1.0.1 + resolution: "vlq@npm:1.0.1" + checksum: 67ab6dd35c787eaa02c0ff1a869dd07a230db08722fb6014adaaf432634808ddb070765f70958b47997e438c331790cfcf20902411b0d6453f1a2a5923522f55 + languageName: node + linkType: hard + +"walker@npm:^1.0.7, walker@npm:^1.0.8": + version: 1.0.8 + resolution: "walker@npm:1.0.8" + dependencies: + makeerror: 1.0.12 + checksum: ad7a257ea1e662e57ef2e018f97b3c02a7240ad5093c392186ce0bcf1f1a60bbadd520d073b9beb921ed99f64f065efb63dfc8eec689a80e569f93c1c5d5e16c + languageName: node + linkType: hard + +"wcwidth@npm:^1.0.1": + version: 1.0.1 + resolution: "wcwidth@npm:1.0.1" + dependencies: + defaults: ^1.0.3 + checksum: 814e9d1ddcc9798f7377ffa448a5a3892232b9275ebb30a41b529607691c0491de47cba426e917a4d08ded3ee7e9ba2f3fe32e62ee3cd9c7d3bafb7754bd553c + languageName: node + linkType: hard + +"webidl-conversions@npm:^3.0.0": + version: 3.0.1 + resolution: "webidl-conversions@npm:3.0.1" + checksum: c92a0a6ab95314bde9c32e1d0a6dfac83b578f8fa5f21e675bc2706ed6981bc26b7eb7e6a1fab158e5ce4adf9caa4a0aee49a52505d4d13c7be545f15021b17c + languageName: node + linkType: hard + +"whatwg-fetch@npm:^3.0.0": + version: 3.6.20 + resolution: "whatwg-fetch@npm:3.6.20" + checksum: c58851ea2c4efe5c2235f13450f426824cf0253c1d45da28f45900290ae602a20aff2ab43346f16ec58917d5562e159cd691efa368354b2e82918c2146a519c5 + languageName: node + linkType: hard + +"whatwg-url@npm:^5.0.0": + version: 5.0.0 + resolution: "whatwg-url@npm:5.0.0" + dependencies: + tr46: ~0.0.3 + webidl-conversions: ^3.0.0 + checksum: b8daed4ad3356cc4899048a15b2c143a9aed0dfae1f611ebd55073310c7b910f522ad75d727346ad64203d7e6c79ef25eafd465f4d12775ca44b90fa82ed9e2c + languageName: node + linkType: hard + +"which-boxed-primitive@npm:^1.0.2": + version: 1.0.2 + resolution: "which-boxed-primitive@npm:1.0.2" + dependencies: + is-bigint: ^1.0.1 + is-boolean-object: ^1.1.0 + is-number-object: ^1.0.4 + is-string: ^1.0.5 + is-symbol: ^1.0.3 + checksum: 53ce774c7379071729533922adcca47220228405e1895f26673bbd71bdf7fb09bee38c1d6399395927c6289476b5ae0629863427fd151491b71c4b6cb04f3a5e + languageName: node + linkType: hard + +"which-builtin-type@npm:^1.1.3": + version: 1.1.3 + resolution: "which-builtin-type@npm:1.1.3" + dependencies: + function.prototype.name: ^1.1.5 + has-tostringtag: ^1.0.0 + is-async-function: ^2.0.0 + is-date-object: ^1.0.5 + is-finalizationregistry: ^1.0.2 + is-generator-function: ^1.0.10 + is-regex: ^1.1.4 + is-weakref: ^1.0.2 + isarray: ^2.0.5 + which-boxed-primitive: ^1.0.2 + which-collection: ^1.0.1 + which-typed-array: ^1.1.9 + checksum: 43730f7d8660ff9e33d1d3f9f9451c4784265ee7bf222babc35e61674a11a08e1c2925019d6c03154fcaaca4541df43abe35d2720843b9b4cbcebdcc31408f36 + languageName: node + linkType: hard + +"which-collection@npm:^1.0.1": + version: 1.0.1 + resolution: "which-collection@npm:1.0.1" + dependencies: + is-map: ^2.0.1 + is-set: ^2.0.1 + is-weakmap: ^2.0.1 + is-weakset: ^2.0.1 + checksum: c815bbd163107ef9cb84f135e6f34453eaf4cca994e7ba85ddb0d27cea724c623fae2a473ceccfd5549c53cc65a5d82692de418166df3f858e1e5dc60818581c + languageName: node + linkType: hard + +"which-module@npm:^2.0.0": + version: 2.0.1 + resolution: "which-module@npm:2.0.1" + checksum: 1967b7ce17a2485544a4fdd9063599f0f773959cca24176dbe8f405e55472d748b7c549cd7920ff6abb8f1ab7db0b0f1b36de1a21c57a8ff741f4f1e792c52be + languageName: node + linkType: hard + +"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.9": + version: 1.1.13 + resolution: "which-typed-array@npm:1.1.13" + dependencies: + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.4 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-tostringtag: ^1.0.0 + checksum: 3828a0d5d72c800e369d447e54c7620742a4cc0c9baf1b5e8c17e9b6ff90d8d861a3a6dd4800f1953dbf80e5e5cec954a289e5b4a223e3bee4aeb1f8c5f33309 + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: ^2.0.0 + bin: + node-which: ./bin/node-which + checksum: 1a5c563d3c1b52d5f893c8b61afe11abc3bab4afac492e8da5bde69d550de701cf9806235f20a47b5c8fa8a1d6a9135841de2596535e998027a54589000e66d1 + languageName: node + linkType: hard + +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: ^3.1.1 + bin: + node-which: bin/which.js + checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 + languageName: node + linkType: hard + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": + version: 7.0.0 + resolution: "wrap-ansi@npm:7.0.0" + dependencies: + ansi-styles: ^4.0.0 + string-width: ^4.1.0 + strip-ansi: ^6.0.0 + checksum: a790b846fd4505de962ba728a21aaeda189b8ee1c7568ca5e817d85930e06ef8d1689d49dbf0e881e8ef84436af3a88bc49115c2e2788d841ff1b8b5b51a608b + languageName: node + linkType: hard + +"wrap-ansi@npm:^6.2.0": + version: 6.2.0 + resolution: "wrap-ansi@npm:6.2.0" + dependencies: + ansi-styles: ^4.0.0 + string-width: ^4.1.0 + strip-ansi: ^6.0.0 + checksum: 6cd96a410161ff617b63581a08376f0cb9162375adeb7956e10c8cd397821f7eb2a6de24eb22a0b28401300bf228c86e50617cd568209b5f6775b93c97d2fe3a + languageName: node + linkType: hard + +"wrap-ansi@npm:^8.1.0": + version: 8.1.0 + resolution: "wrap-ansi@npm:8.1.0" + dependencies: + ansi-styles: ^6.1.0 + string-width: ^5.0.1 + strip-ansi: ^7.0.1 + checksum: 371733296dc2d616900ce15a0049dca0ef67597d6394c57347ba334393599e800bab03c41d4d45221b6bc967b8c453ec3ae4749eff3894202d16800fdfe0e238 + languageName: node + linkType: hard + +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 159da4805f7e84a3d003d8841557196034155008f817172d4e986bd591f74aa82aa7db55929a54222309e01079a65a92a9e6414da5a6aa4b01ee44a511ac3ee5 + languageName: node + linkType: hard + +"write-file-atomic@npm:^2.3.0": + version: 2.4.3 + resolution: "write-file-atomic@npm:2.4.3" + dependencies: + graceful-fs: ^4.1.11 + imurmurhash: ^0.1.4 + signal-exit: ^3.0.2 + checksum: 2db81f92ae974fd87ab4a5e7932feacaca626679a7c98fcc73ad8fcea5a1950eab32fa831f79e9391ac99b562ca091ad49be37a79045bd65f595efbb8f4596ae + languageName: node + linkType: hard + +"write-file-atomic@npm:^4.0.2": + version: 4.0.2 + resolution: "write-file-atomic@npm:4.0.2" + dependencies: + imurmurhash: ^0.1.4 + signal-exit: ^3.0.7 + checksum: 5da60bd4eeeb935eec97ead3df6e28e5917a6bd317478e4a85a5285e8480b8ed96032bbcc6ecd07b236142a24f3ca871c924ec4a6575e623ec1b11bf8c1c253c + languageName: node + linkType: hard + +"ws@npm:^6.2.2": + version: 6.2.2 + resolution: "ws@npm:6.2.2" + dependencies: + async-limiter: ~1.0.0 + checksum: aec3154ec51477c094ac2cb5946a156e17561a581fa27005cbf22c53ac57f8d4e5f791dd4bbba6a488602cb28778c8ab7df06251d590507c3c550fd8ebeee949 + languageName: node + linkType: hard + +"ws@npm:^7, ws@npm:^7.5.1": + version: 7.5.9 + resolution: "ws@npm:7.5.9" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: c3c100a181b731f40b7f2fddf004aa023f79d64f489706a28bc23ff88e87f6a64b3c6651fbec3a84a53960b75159574d7a7385709847a62ddb7ad6af76f49138 + languageName: node + linkType: hard + +"xtend@npm:~4.0.1": + version: 4.0.2 + resolution: "xtend@npm:4.0.2" + checksum: ac5dfa738b21f6e7f0dd6e65e1b3155036d68104e67e5d5d1bde74892e327d7e5636a076f625599dc394330a731861e87343ff184b0047fef1360a7ec0a5a36a + languageName: node + linkType: hard + +"y18n@npm:^4.0.0": + version: 4.0.3 + resolution: "y18n@npm:4.0.3" + checksum: 014dfcd9b5f4105c3bb397c1c8c6429a9df004aa560964fb36732bfb999bfe83d45ae40aeda5b55d21b1ee53d8291580a32a756a443e064317953f08025b1aa4 + languageName: node + linkType: hard + +"y18n@npm:^5.0.5": + version: 5.0.8 + resolution: "y18n@npm:5.0.8" + checksum: 54f0fb95621ee60898a38c572c515659e51cc9d9f787fb109cef6fde4befbe1c4602dc999d30110feee37456ad0f1660fa2edcfde6a9a740f86a290999550d30 + languageName: node + linkType: hard + +"yallist@npm:^3.0.2": + version: 3.1.1 + resolution: "yallist@npm:3.1.1" + checksum: 48f7bb00dc19fc635a13a39fe547f527b10c9290e7b3e836b9a8f1ca04d4d342e85714416b3c2ab74949c9c66f9cebb0473e6bc353b79035356103b47641285d + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 343617202af32df2a15a3be36a5a8c0c8545208f3d3dfbc6bb7c3e3b7e8c6f8e7485432e4f3b88da3031a6e20afa7c711eded32ddfb122896ac5d914e75848d5 + languageName: node + linkType: hard + +"yaml@npm:^2.2.1": + version: 2.3.4 + resolution: "yaml@npm:2.3.4" + checksum: e6d1dae1c6383bcc8ba11796eef3b8c02d5082911c6723efeeb5ba50fc8e881df18d645e64de68e421b577296000bea9c75d6d9097c2f6699da3ae0406c030d8 + languageName: node + linkType: hard + +"yargs-parser@npm:^18.1.2": + version: 18.1.3 + resolution: "yargs-parser@npm:18.1.3" + dependencies: + camelcase: ^5.0.0 + decamelize: ^1.2.0 + checksum: 60e8c7d1b85814594d3719300ecad4e6ae3796748b0926137bfec1f3042581b8646d67e83c6fc80a692ef08b8390f21ddcacb9464476c39bbdf52e34961dd4d9 + languageName: node + linkType: hard + +"yargs-parser@npm:^21.1.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: ed2d96a616a9e3e1cc7d204c62ecc61f7aaab633dcbfab2c6df50f7f87b393993fe6640d017759fe112d0cb1e0119f2b4150a87305cc873fd90831c6a58ccf1c + languageName: node + linkType: hard + +"yargs@npm:^15.1.0": + version: 15.4.1 + resolution: "yargs@npm:15.4.1" + dependencies: + cliui: ^6.0.0 + decamelize: ^1.2.0 + find-up: ^4.1.0 + get-caller-file: ^2.0.1 + require-directory: ^2.1.1 + require-main-filename: ^2.0.0 + set-blocking: ^2.0.0 + string-width: ^4.2.0 + which-module: ^2.0.0 + y18n: ^4.0.0 + yargs-parser: ^18.1.2 + checksum: 40b974f508d8aed28598087720e086ecd32a5fd3e945e95ea4457da04ee9bdb8bdd17fd91acff36dc5b7f0595a735929c514c40c402416bbb87c03f6fb782373 + languageName: node + linkType: hard + +"yargs@npm:^17.3.1, yargs@npm:^17.6.2": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + dependencies: + cliui: ^8.0.1 + escalade: ^3.1.1 + get-caller-file: ^2.0.5 + require-directory: ^2.1.1 + string-width: ^4.2.3 + y18n: ^5.0.5 + yargs-parser: ^21.1.1 + checksum: 73b572e863aa4a8cbef323dd911d79d193b772defd5a51aab0aca2d446655216f5002c42c5306033968193bdbf892a7a4c110b0d77954a7fdf563e653967b56a + languageName: node + linkType: hard + +"yn@npm:3.1.1": + version: 3.1.1 + resolution: "yn@npm:3.1.1" + checksum: 2c487b0e149e746ef48cda9f8bad10fc83693cd69d7f9dcd8be4214e985de33a29c9e24f3c0d6bcf2288427040a8947406ab27f7af67ee9456e6b84854f02dd6 + languageName: node + linkType: hard + +"yocto-queue@npm:^0.1.0": + version: 0.1.0 + resolution: "yocto-queue@npm:0.1.0" + checksum: f77b3d8d00310def622123df93d4ee654fc6a0096182af8bd60679ddcdfb3474c56c6c7190817c84a2785648cdee9d721c0154eb45698c62176c322fb46fc700 + languageName: node + linkType: hard diff --git a/examples/publish-ci/vite/index.html b/examples/publish-ci/vite/index.html index e0d1c84080..e4b78eae12 100644 --- a/examples/publish-ci/vite/index.html +++ b/examples/publish-ci/vite/index.html @@ -1,4 +1,4 @@ - + diff --git a/examples/publish-ci/vite/package.json b/examples/publish-ci/vite/package.json index 3689f436e5..b1bb636e5c 100644 --- a/examples/publish-ci/vite/package.json +++ b/examples/publish-ci/vite/package.json @@ -28,7 +28,7 @@ "@types/react-dom": "^18.0.10", "@vitejs/plugin-react": "^3.0.0", "playwright": "^1.31.1", - "prettier": "^2.8.4", + "prettier": "^3.2.4", "serve": "^14.2.0", "typescript": "^4.9.4", "vite": "^4.2.1" diff --git a/examples/publish-ci/vite/src/features/counter/Counter.module.css b/examples/publish-ci/vite/src/features/counter/Counter.module.css index ce3e2d3a25..521dc6580b 100644 --- a/examples/publish-ci/vite/src/features/counter/Counter.module.css +++ b/examples/publish-ci/vite/src/features/counter/Counter.module.css @@ -18,7 +18,7 @@ padding-left: 16px; padding-right: 16px; margin-top: 2px; - font-family: "Courier New", Courier, monospace; + font-family: 'Courier New', Courier, monospace; } .button { @@ -60,7 +60,7 @@ } .asyncButton:after { - content: ""; + content: ''; background-color: rgba(112, 76, 182, 0.15); display: block; position: absolute; @@ -69,7 +69,9 @@ left: 0; top: 0; opacity: 0; - transition: width 1s linear, opacity 0.5s ease 1s; + transition: + width 1s linear, + opacity 0.5s ease 1s; } .asyncButton:active:after { diff --git a/examples/publish-ci/vite/src/features/counter/counterAPI.ts b/examples/publish-ci/vite/src/features/counter/counterAPI.ts index 01e8caaf51..c5c2a7e026 100644 --- a/examples/publish-ci/vite/src/features/counter/counterAPI.ts +++ b/examples/publish-ci/vite/src/features/counter/counterAPI.ts @@ -1,6 +1,6 @@ // A mock function to mimic making an async request for data export function fetchCount(amount = 1) { return new Promise<{ data: number }>((resolve) => - setTimeout(() => resolve({ data: amount }), 500) + setTimeout(() => resolve({ data: amount }), 500), ) } diff --git a/examples/publish-ci/vite/src/features/counter/counterSlice.ts b/examples/publish-ci/vite/src/features/counter/counterSlice.ts index 54a1a894fa..28ff82eaf9 100644 --- a/examples/publish-ci/vite/src/features/counter/counterSlice.ts +++ b/examples/publish-ci/vite/src/features/counter/counterSlice.ts @@ -23,7 +23,7 @@ export const incrementAsync = createAsyncThunk( const response = await fetchCount(amount) // The value we return becomes the `fulfilled` action payload return response.data - } + }, ) export const counterSlice = createSlice({ diff --git a/examples/publish-ci/vite/src/index.css b/examples/publish-ci/vite/src/index.css index 4a1df4db71..ec2585e8c0 100644 --- a/examples/publish-ci/vite/src/index.css +++ b/examples/publish-ci/vite/src/index.css @@ -1,13 +1,13 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } diff --git a/examples/publish-ci/vite/src/main.tsx b/examples/publish-ci/vite/src/main.tsx index a7da211294..57034ae35e 100644 --- a/examples/publish-ci/vite/src/main.tsx +++ b/examples/publish-ci/vite/src/main.tsx @@ -12,7 +12,7 @@ async function render() { await worker.start() const rootNode = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById('root') as HTMLElement, ) rootNode.render( @@ -20,7 +20,7 @@ async function render() { - + , ) } diff --git a/examples/publish-ci/vite/src/mocks/handlers.ts b/examples/publish-ci/vite/src/mocks/handlers.ts index f519dcf7d2..e682accda3 100644 --- a/examples/publish-ci/vite/src/mocks/handlers.ts +++ b/examples/publish-ci/vite/src/mocks/handlers.ts @@ -29,7 +29,7 @@ export const handlers = [ const target = localDate + localOffset + 3600000 * formattedOffset return res( ctx.json({ time: new Date(target).toUTCString() }), - ctx.delay(400) + ctx.delay(400), ) }), diff --git a/examples/publish-ci/vite/tsconfig.json b/examples/publish-ci/vite/tsconfig.json index 3d0a51a86e..b5eaa05e05 100644 --- a/examples/publish-ci/vite/tsconfig.json +++ b/examples/publish-ci/vite/tsconfig.json @@ -14,8 +14,8 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react-jsx" + "jsx": "react-jsx", }, "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] + "references": [{ "path": "./tsconfig.node.json" }], } diff --git a/examples/publish-ci/vite/vite.config.ts b/examples/publish-ci/vite/vite.config.ts index 6ade36dc78..82f3829a2c 100644 --- a/examples/publish-ci/vite/vite.config.ts +++ b/examples/publish-ci/vite/vite.config.ts @@ -5,6 +5,6 @@ import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], build: { - sourcemap: true - } + sourcemap: true, + }, }) diff --git a/examples/publish-ci/vite/yarn.lock b/examples/publish-ci/vite/yarn.lock index 69d4f11162..9795f23cd6 100644 --- a/examples/publish-ci/vite/yarn.lock +++ b/examples/publish-ci/vite/yarn.lock @@ -3316,12 +3316,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^2.8.4": - version: 2.8.4 - resolution: "prettier@npm:2.8.4" +"prettier@npm:^3.2.4": + version: 3.2.4 + resolution: "prettier@npm:3.2.4" bin: - prettier: bin-prettier.js - checksum: c173064bf3df57b6d93d19aa98753b9b9dd7657212e33b41ada8e2e9f9884066bb9ca0b4005b89b3ab137efffdf8fbe0b462785aba20364798ff4303aadda57e + prettier: bin/prettier.cjs + checksum: 6ec9385a836e0b9bac549e585101c086d1521c31d7b882d5c8bb7d7646da0693da5f31f4fff6dc080710e5e2d34c85e6fb2f8766876b3645c8be2f33b9c3d1a3 languageName: node linkType: hard @@ -3657,7 +3657,7 @@ __metadata: "@vitejs/plugin-react": ^3.0.0 msw: ^1.3.2 playwright: ^1.31.1 - prettier: ^2.8.4 + prettier: ^3.2.4 react: ^18.2.0 react-dom: ^18.2.0 react-redux: ^9.0.0-rc.0 diff --git a/examples/query/react/advanced/public/index.html b/examples/query/react/advanced/public/index.html index 42ae2d2dcb..efbc007a8b 100644 --- a/examples/query/react/advanced/public/index.html +++ b/examples/query/react/advanced/public/index.html @@ -1,17 +1,19 @@ - + - - - - - - - - - - React App - + React App + - - -
- - - - \ No newline at end of file + + diff --git a/examples/query/react/advanced/src/Pokemon.tsx b/examples/query/react/advanced/src/Pokemon.tsx index 0506e6c79a..4e848e960b 100644 --- a/examples/query/react/advanced/src/Pokemon.tsx +++ b/examples/query/react/advanced/src/Pokemon.tsx @@ -11,7 +11,7 @@ export const Pokemon = ({ name, { pollingInterval, - } + }, ) return ( diff --git a/examples/query/react/advanced/src/index.tsx b/examples/query/react/advanced/src/index.tsx index b5a9e97285..568f62e54d 100644 --- a/examples/query/react/advanced/src/index.tsx +++ b/examples/query/react/advanced/src/index.tsx @@ -10,5 +10,5 @@ const reactRoot = ReactDOM.createRoot(rootElement as HTMLElement) reactRoot.render( - + , ) diff --git a/examples/query/react/advanced/tsconfig.json b/examples/query/react/advanced/tsconfig.json index d4eea2ea4b..7f331f6806 100644 --- a/examples/query/react/advanced/tsconfig.json +++ b/examples/query/react/advanced/tsconfig.json @@ -1,25 +1,20 @@ { - "include": [ - "./src/**/*" - ], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } -} \ No newline at end of file + "include": ["./src/**/*"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "lib": ["dom", "es2015"], + "jsx": "react-jsx", + "target": "es5", + "allowJs": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + }, +} diff --git a/examples/query/react/authentication-with-extrareducers/public/index.html b/examples/query/react/authentication-with-extrareducers/public/index.html index 09e975e218..e65acb3de5 100644 --- a/examples/query/react/authentication-with-extrareducers/public/index.html +++ b/examples/query/react/authentication-with-extrareducers/public/index.html @@ -1,4 +1,4 @@ - + @@ -41,4 +41,3 @@ --> - diff --git a/examples/query/react/authentication-with-extrareducers/src/features/auth/authSlice.tsx b/examples/query/react/authentication-with-extrareducers/src/features/auth/authSlice.tsx index 3c854bedad..dfbc2182ec 100644 --- a/examples/query/react/authentication-with-extrareducers/src/features/auth/authSlice.tsx +++ b/examples/query/react/authentication-with-extrareducers/src/features/auth/authSlice.tsx @@ -17,7 +17,7 @@ const slice = createSlice({ (state, { payload }) => { state.token = payload.token state.user = payload.user - } + }, ) }, }) diff --git a/examples/query/react/authentication-with-extrareducers/src/index.tsx b/examples/query/react/authentication-with-extrareducers/src/index.tsx index 2bf5b85aa3..2b302a9654 100644 --- a/examples/query/react/authentication-with-extrareducers/src/index.tsx +++ b/examples/query/react/authentication-with-extrareducers/src/index.tsx @@ -20,6 +20,6 @@ worker.start({ quiet: true }).then(() => - - ) + , + ), ) diff --git a/examples/query/react/authentication-with-extrareducers/src/mocks/handlers.ts b/examples/query/react/authentication-with-extrareducers/src/mocks/handlers.ts index 7415cb72fd..4efb7fdf88 100644 --- a/examples/query/react/authentication-with-extrareducers/src/mocks/handlers.ts +++ b/examples/query/react/authentication-with-extrareducers/src/mocks/handlers.ts @@ -11,14 +11,14 @@ export const handlers = [ ctx.json({ message: 'You shall not pass. Please login first.', }), - ctx.status(401) + ctx.status(401), ) } return res( ctx.json({ message: 'Join us on the Reactiflux Discord server in #redux if you have any questions.', - }) + }), ) }), rest.post('/login', (req, res, ctx) => { @@ -30,7 +30,7 @@ export const handlers = [ last_name: 'User', }, token, - }) + }), ) }), ] diff --git a/examples/query/react/authentication-with-extrareducers/tsconfig.json b/examples/query/react/authentication-with-extrareducers/tsconfig.json index 5f488e8e73..7f331f6806 100644 --- a/examples/query/react/authentication-with-extrareducers/tsconfig.json +++ b/examples/query/react/authentication-with-extrareducers/tsconfig.json @@ -1,14 +1,9 @@ { - "include": [ - "./src/**/*" - ], + "include": ["./src/**/*"], "compilerOptions": { "strict": true, "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], + "lib": ["dom", "es2015"], "jsx": "react-jsx", "target": "es5", "allowJs": true, @@ -20,6 +15,6 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "noEmit": true - } + "noEmit": true, + }, } diff --git a/examples/query/react/authentication/public/index.html b/examples/query/react/authentication/public/index.html index 09e975e218..e65acb3de5 100644 --- a/examples/query/react/authentication/public/index.html +++ b/examples/query/react/authentication/public/index.html @@ -1,4 +1,4 @@ - + @@ -41,4 +41,3 @@ --> - diff --git a/examples/query/react/authentication/src/features/auth/authSlice.tsx b/examples/query/react/authentication/src/features/auth/authSlice.tsx index 76fde9f03c..c7d17c0bd5 100644 --- a/examples/query/react/authentication/src/features/auth/authSlice.tsx +++ b/examples/query/react/authentication/src/features/auth/authSlice.tsx @@ -14,7 +14,9 @@ const slice = createSlice({ reducers: { setCredentials: ( state, - { payload: { user, token } }: PayloadAction<{ user: User; token: string }> + { + payload: { user, token }, + }: PayloadAction<{ user: User; token: string }>, ) => { state.user = user state.token = token diff --git a/examples/query/react/authentication/src/index.tsx b/examples/query/react/authentication/src/index.tsx index b55e344e50..25df0f6d58 100644 --- a/examples/query/react/authentication/src/index.tsx +++ b/examples/query/react/authentication/src/index.tsx @@ -12,7 +12,7 @@ worker .start({ quiet: true }) .then(() => { const rootNode = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById('root') as HTMLElement, ) return rootNode.render( @@ -24,7 +24,7 @@ worker - + , ) }) .catch(console.error) diff --git a/examples/query/react/authentication/src/mocks/handlers.ts b/examples/query/react/authentication/src/mocks/handlers.ts index 7415cb72fd..4efb7fdf88 100644 --- a/examples/query/react/authentication/src/mocks/handlers.ts +++ b/examples/query/react/authentication/src/mocks/handlers.ts @@ -11,14 +11,14 @@ export const handlers = [ ctx.json({ message: 'You shall not pass. Please login first.', }), - ctx.status(401) + ctx.status(401), ) } return res( ctx.json({ message: 'Join us on the Reactiflux Discord server in #redux if you have any questions.', - }) + }), ) }), rest.post('/login', (req, res, ctx) => { @@ -30,7 +30,7 @@ export const handlers = [ last_name: 'User', }, token, - }) + }), ) }), ] diff --git a/examples/query/react/authentication/tsconfig.json b/examples/query/react/authentication/tsconfig.json index 5f488e8e73..7f331f6806 100644 --- a/examples/query/react/authentication/tsconfig.json +++ b/examples/query/react/authentication/tsconfig.json @@ -1,14 +1,9 @@ { - "include": [ - "./src/**/*" - ], + "include": ["./src/**/*"], "compilerOptions": { "strict": true, "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], + "lib": ["dom", "es2015"], "jsx": "react-jsx", "target": "es5", "allowJs": true, @@ -20,6 +15,6 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "noEmit": true - } + "noEmit": true, + }, } diff --git a/examples/query/react/basic/public/index.html b/examples/query/react/basic/public/index.html index 42ae2d2dcb..efbc007a8b 100644 --- a/examples/query/react/basic/public/index.html +++ b/examples/query/react/basic/public/index.html @@ -1,17 +1,19 @@ - + - - - - - - - - - - React App - + React App + - - -
- - - - \ No newline at end of file + + diff --git a/examples/query/react/basic/src/App.test.tsx b/examples/query/react/basic/src/App.test.tsx index 3225b3e090..4fd1a19675 100644 --- a/examples/query/react/basic/src/App.test.tsx +++ b/examples/query/react/basic/src/App.test.tsx @@ -18,7 +18,7 @@ describe('App', () => { }) as HTMLImageElement expect(img.src).toBe( - 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/1.png' + 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/shiny/1.png', ) }) @@ -29,8 +29,8 @@ describe('App', () => { 'https://pokeapi.co/api/v2/pokemon/bulbasaur', (req, res, ctx) => { return res(ctx.status(500)) - } - ) + }, + ), ) renderWithProviders() diff --git a/examples/query/react/basic/src/index.tsx b/examples/query/react/basic/src/index.tsx index 970d6ba2b4..589c537b24 100644 --- a/examples/query/react/basic/src/index.tsx +++ b/examples/query/react/basic/src/index.tsx @@ -7,10 +7,10 @@ import { setupStore } from './store' const store = setupStore() const reactRoot = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById('root') as HTMLElement, ) reactRoot.render( - + , ) diff --git a/examples/query/react/basic/src/test/test-utils.tsx b/examples/query/react/basic/src/test/test-utils.tsx index cf36650812..1e90c11a87 100644 --- a/examples/query/react/basic/src/test/test-utils.tsx +++ b/examples/query/react/basic/src/test/test-utils.tsx @@ -21,7 +21,7 @@ function renderWithProviders( preloadedState = {}, store = setupStore(preloadedState), ...renderOptions - }: ExtendedRenderOptions = {} + }: ExtendedRenderOptions = {}, ) { function Wrapper({ children }: PropsWithChildren<{}>): JSX.Element { return {children} diff --git a/examples/query/react/basic/tsconfig.json b/examples/query/react/basic/tsconfig.json index d4eea2ea4b..7f331f6806 100644 --- a/examples/query/react/basic/tsconfig.json +++ b/examples/query/react/basic/tsconfig.json @@ -1,25 +1,20 @@ { - "include": [ - "./src/**/*" - ], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } -} \ No newline at end of file + "include": ["./src/**/*"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "lib": ["dom", "es2015"], + "jsx": "react-jsx", + "target": "es5", + "allowJs": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + }, +} diff --git a/examples/query/react/conditional-fetching/public/index.html b/examples/query/react/conditional-fetching/public/index.html index 42ae2d2dcb..efbc007a8b 100644 --- a/examples/query/react/conditional-fetching/public/index.html +++ b/examples/query/react/conditional-fetching/public/index.html @@ -1,17 +1,19 @@ - + - - - - - - - - - - React App - + React App + - - -
- - - - \ No newline at end of file + + diff --git a/examples/query/react/conditional-fetching/src/Pokemon.tsx b/examples/query/react/conditional-fetching/src/Pokemon.tsx index 2e2b9549a9..077d11a4b5 100644 --- a/examples/query/react/conditional-fetching/src/Pokemon.tsx +++ b/examples/query/react/conditional-fetching/src/Pokemon.tsx @@ -8,7 +8,7 @@ export const Pokemon = ({ name }: { name: PokemonName }) => { name, { skip, - } + }, ) const SkipToggle = () => ( diff --git a/examples/query/react/conditional-fetching/src/index.tsx b/examples/query/react/conditional-fetching/src/index.tsx index 1af4cef9e5..b455864950 100644 --- a/examples/query/react/conditional-fetching/src/index.tsx +++ b/examples/query/react/conditional-fetching/src/index.tsx @@ -5,10 +5,10 @@ import App from './App' import { store } from './store' const reactRoot = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById('root') as HTMLElement, ) reactRoot.render( - + , ) diff --git a/examples/query/react/conditional-fetching/src/pokemon.data.ts b/examples/query/react/conditional-fetching/src/pokemon.data.ts index 1617ce9e50..22eb3a0547 100644 --- a/examples/query/react/conditional-fetching/src/pokemon.data.ts +++ b/examples/query/react/conditional-fetching/src/pokemon.data.ts @@ -152,4 +152,4 @@ export const POKEMON_NAMES = [ 'mew', ] as const -export type PokemonName = typeof POKEMON_NAMES[number] +export type PokemonName = (typeof POKEMON_NAMES)[number] diff --git a/examples/query/react/conditional-fetching/tsconfig.json b/examples/query/react/conditional-fetching/tsconfig.json index d4eea2ea4b..7f331f6806 100644 --- a/examples/query/react/conditional-fetching/tsconfig.json +++ b/examples/query/react/conditional-fetching/tsconfig.json @@ -1,25 +1,20 @@ { - "include": [ - "./src/**/*" - ], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } -} \ No newline at end of file + "include": ["./src/**/*"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "lib": ["dom", "es2015"], + "jsx": "react-jsx", + "target": "es5", + "allowJs": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + }, +} diff --git a/examples/query/react/deduping-queries/public/index.html b/examples/query/react/deduping-queries/public/index.html index 42ae2d2dcb..efbc007a8b 100644 --- a/examples/query/react/deduping-queries/public/index.html +++ b/examples/query/react/deduping-queries/public/index.html @@ -1,17 +1,19 @@ - + - - - - - - - - - - React App - + React App + - - -
- - - - \ No newline at end of file + + diff --git a/examples/query/react/deduping-queries/src/Pokemon.tsx b/examples/query/react/deduping-queries/src/Pokemon.tsx index 624602f3a9..73e71925bd 100644 --- a/examples/query/react/deduping-queries/src/Pokemon.tsx +++ b/examples/query/react/deduping-queries/src/Pokemon.tsx @@ -1,13 +1,8 @@ import { useGetPokemonByNameQuery } from './services/pokemon' export const Pokemon = ({ name }: { name: string }) => { - const { - data, - error, - isLoading, - isFetching, - refetch, - } = useGetPokemonByNameQuery(name) + const { data, error, isLoading, isFetching, refetch } = + useGetPokemonByNameQuery(name) return (
diff --git a/examples/query/react/deduping-queries/src/index.tsx b/examples/query/react/deduping-queries/src/index.tsx index 0924558a7d..b36d809053 100644 --- a/examples/query/react/deduping-queries/src/index.tsx +++ b/examples/query/react/deduping-queries/src/index.tsx @@ -5,11 +5,11 @@ import App from './App' import { store } from './store' const reactRoot = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById('root') as HTMLElement, ) reactRoot.render( - + , ) diff --git a/examples/query/react/deduping-queries/tsconfig.json b/examples/query/react/deduping-queries/tsconfig.json index d4eea2ea4b..7f331f6806 100644 --- a/examples/query/react/deduping-queries/tsconfig.json +++ b/examples/query/react/deduping-queries/tsconfig.json @@ -1,25 +1,20 @@ { - "include": [ - "./src/**/*" - ], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } -} \ No newline at end of file + "include": ["./src/**/*"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "lib": ["dom", "es2015"], + "jsx": "react-jsx", + "target": "es5", + "allowJs": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + }, +} diff --git a/examples/query/react/graphql-codegen/.introspection.json b/examples/query/react/graphql-codegen/.introspection.json index 00aa67088e..732fa070df 100644 --- a/examples/query/react/graphql-codegen/.introspection.json +++ b/examples/query/react/graphql-codegen/.introspection.json @@ -1704,11 +1704,7 @@ "name": "include", "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", "isRepeatable": false, - "locations": [ - "FIELD", - "FRAGMENT_SPREAD", - "INLINE_FRAGMENT" - ], + "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], "args": [ { "name": "if", @@ -1732,11 +1728,7 @@ "name": "skip", "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", "isRepeatable": false, - "locations": [ - "FIELD", - "FRAGMENT_SPREAD", - "INLINE_FRAGMENT" - ], + "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], "args": [ { "name": "if", @@ -1785,9 +1777,7 @@ "name": "specifiedBy", "description": "Exposes a URL that specifies the behaviour of this scalar.", "isRepeatable": false, - "locations": [ - "SCALAR" - ], + "locations": ["SCALAR"], "args": [ { "name": "url", @@ -1809,4 +1799,4 @@ } ] } -} \ No newline at end of file +} diff --git a/examples/query/react/graphql-codegen/public/index.html b/examples/query/react/graphql-codegen/public/index.html index 09e975e218..e65acb3de5 100644 --- a/examples/query/react/graphql-codegen/public/index.html +++ b/examples/query/react/graphql-codegen/public/index.html @@ -1,4 +1,4 @@ - + @@ -41,4 +41,3 @@ --> - diff --git a/examples/query/react/graphql-codegen/src/app/services/types.generated.ts b/examples/query/react/graphql-codegen/src/app/services/types.generated.ts index f1f88bfc20..399ebbd2c9 100644 --- a/examples/query/react/graphql-codegen/src/app/services/types.generated.ts +++ b/examples/query/react/graphql-codegen/src/app/services/types.generated.ts @@ -1,119 +1,118 @@ -export type Maybe = T; -export type Exact = { [K in keyof T]: T[K] }; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; +export type Maybe = T +export type Exact = { + [K in keyof T]: T[K] +} +export type MakeOptional = Omit & { + [SubKey in K]?: Maybe +} +export type MakeMaybe = Omit & { + [SubKey in K]: Maybe +} /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { - ID: string; - String: string; - Boolean: boolean; - Int: number; - Float: number; -}; + ID: string + String: string + Boolean: boolean + Int: number + Float: number +} export type IdQueryType = { - equals?: Maybe; - notEquals?: Maybe; - contains?: Maybe; - notContains?: Maybe; - in?: Maybe; - notIn?: Maybe; -}; + equals?: Maybe + notEquals?: Maybe + contains?: Maybe + notContains?: Maybe + in?: Maybe + notIn?: Maybe +} export type Mutation = { - __typename?: 'Mutation'; - createPost?: Maybe; - updatePost?: Maybe; - updatePosts?: Maybe>>; - deletePost?: Maybe; - deletePosts?: Maybe>>; -}; - + __typename?: 'Mutation' + createPost?: Maybe + updatePost?: Maybe + updatePosts?: Maybe>> + deletePost?: Maybe + deletePosts?: Maybe>> +} export type MutationCreatePostArgs = { - data?: Maybe; -}; - + data?: Maybe +} export type MutationUpdatePostArgs = { - where?: Maybe; - data?: Maybe; -}; - + where?: Maybe + data?: Maybe +} export type MutationUpdatePostsArgs = { - where?: Maybe; - data?: Maybe; -}; - + where?: Maybe + data?: Maybe +} export type MutationDeletePostArgs = { - where?: Maybe; -}; - + where?: Maybe +} export type MutationDeletePostsArgs = { - where?: Maybe; -}; + where?: Maybe +} export type Post = { - __typename?: 'Post'; - id?: Maybe; - name?: Maybe; - title?: Maybe; - author?: Maybe; - content?: Maybe; - status?: Maybe; - created_at?: Maybe; - updated_at?: Maybe; -}; + __typename?: 'Post' + id?: Maybe + name?: Maybe + title?: Maybe + author?: Maybe + content?: Maybe + status?: Maybe + created_at?: Maybe + updated_at?: Maybe +} export type PostInput = { - id?: Maybe; - name?: Maybe; - title?: Maybe; - author?: Maybe; - content?: Maybe; - status?: Maybe; - created_at?: Maybe; - updated_at?: Maybe; -}; + id?: Maybe + name?: Maybe + title?: Maybe + author?: Maybe + content?: Maybe + status?: Maybe + created_at?: Maybe + updated_at?: Maybe +} export type PostQueryInput = { - id?: Maybe; - name?: Maybe; - title?: Maybe; - author?: Maybe; - content?: Maybe; - status?: Maybe; - created_at?: Maybe; - updated_at?: Maybe; -}; + id?: Maybe + name?: Maybe + title?: Maybe + author?: Maybe + content?: Maybe + status?: Maybe + created_at?: Maybe + updated_at?: Maybe +} export type Query = { - __typename?: 'Query'; - post?: Maybe; - posts?: Maybe>>; -}; - + __typename?: 'Query' + post?: Maybe + posts?: Maybe>> +} export type QueryPostArgs = { - where?: Maybe; -}; - + where?: Maybe +} export type QueryPostsArgs = { - take?: Maybe; - skip?: Maybe; - cursor?: Maybe; - where?: Maybe; -}; + take?: Maybe + skip?: Maybe + cursor?: Maybe + where?: Maybe +} export type StringQueryType = { - equals?: Maybe; - notEquals?: Maybe; - contains?: Maybe; - notContains?: Maybe; - in?: Maybe; - notIn?: Maybe; -}; + equals?: Maybe + notEquals?: Maybe + contains?: Maybe + notContains?: Maybe + in?: Maybe + notIn?: Maybe +} diff --git a/examples/query/react/graphql-codegen/src/features/posts/GetPost.generated.ts b/examples/query/react/graphql-codegen/src/features/posts/GetPost.generated.ts index 17a3fd7999..0ed9677e3c 100644 --- a/examples/query/react/graphql-codegen/src/features/posts/GetPost.generated.ts +++ b/examples/query/react/graphql-codegen/src/features/posts/GetPost.generated.ts @@ -9,23 +9,19 @@ * for this file to be re-created */ -import * as Types from '../../app/services/types.generated'; +import * as Types from '../../app/services/types.generated' -import { api } from 'app/services/baseApi'; -module.hot?.accept(); +import { api } from 'app/services/baseApi' +module.hot?.accept() export type GetPostQueryVariables = Types.Exact<{ - id: Types.Scalars['ID']; -}>; - - -export type GetPostQuery = ( - { __typename?: 'Query' } - & { post?: Types.Maybe<( - { __typename?: 'Post' } - & Pick - )> } -); + id: Types.Scalars['ID'] +}> +export type GetPostQuery = { __typename?: 'Query' } & { + post?: Types.Maybe< + { __typename?: 'Post' } & Pick + > +} export const GetPostDocument = ` query GetPost($id: ID!) { @@ -35,17 +31,16 @@ export const GetPostDocument = ` content } } - `; + ` const injectedRtkApi = api.injectEndpoints({ - overrideExisting: module.hot?.status() === "apply", + overrideExisting: module.hot?.status() === 'apply', endpoints: (build) => ({ GetPost: build.query({ - query: (variables) => ({ document: GetPostDocument, variables }) + query: (variables) => ({ document: GetPostDocument, variables }), }), }), -}); - -export { injectedRtkApi as api }; -export const { useGetPostQuery, useLazyGetPostQuery } = injectedRtkApi; +}) +export { injectedRtkApi as api } +export const { useGetPostQuery, useLazyGetPostQuery } = injectedRtkApi diff --git a/examples/query/react/graphql-codegen/src/features/posts/GetPosts.generated.ts b/examples/query/react/graphql-codegen/src/features/posts/GetPosts.generated.ts index 79c42956e0..6efed203a6 100644 --- a/examples/query/react/graphql-codegen/src/features/posts/GetPosts.generated.ts +++ b/examples/query/react/graphql-codegen/src/features/posts/GetPosts.generated.ts @@ -9,24 +9,24 @@ * for this file to be re-created */ -import * as Types from '../../app/services/types.generated'; +import * as Types from '../../app/services/types.generated' -import { api } from 'app/services/baseApi'; -module.hot?.accept(); +import { api } from 'app/services/baseApi' +module.hot?.accept() export type GetPostsQueryVariables = Types.Exact<{ - skip?: Types.Maybe; - take?: Types.Maybe; -}>; - - -export type GetPostsQuery = ( - { __typename?: 'Query' } - & { posts?: Types.Maybe - )>>> } -); - + skip?: Types.Maybe + take?: Types.Maybe +}> + +export type GetPostsQuery = { __typename?: 'Query' } & { + posts?: Types.Maybe< + Array< + Types.Maybe< + { __typename?: 'Post' } & Pick + > + > + > +} export const GetPostsDocument = ` query GetPosts($skip: Int = 0, $take: Int = 10) { @@ -36,17 +36,16 @@ export const GetPostsDocument = ` status } } - `; + ` const injectedRtkApi = api.injectEndpoints({ - overrideExisting: module.hot?.status() === "apply", + overrideExisting: module.hot?.status() === 'apply', endpoints: (build) => ({ GetPosts: build.query({ - query: (variables) => ({ document: GetPostsDocument, variables }) + query: (variables) => ({ document: GetPostsDocument, variables }), }), }), -}); - -export { injectedRtkApi as api }; -export const { useGetPostsQuery, useLazyGetPostsQuery } = injectedRtkApi; +}) +export { injectedRtkApi as api } +export const { useGetPostsQuery, useLazyGetPostsQuery } = injectedRtkApi diff --git a/examples/query/react/graphql-codegen/src/features/posts/PostsManager.tsx b/examples/query/react/graphql-codegen/src/features/posts/PostsManager.tsx index 907d412679..9eefa7bf48 100644 --- a/examples/query/react/graphql-codegen/src/features/posts/PostsManager.tsx +++ b/examples/query/react/graphql-codegen/src/features/posts/PostsManager.tsx @@ -23,8 +23,8 @@ const getColorForStatus = (status: string | undefined) => { return status === 'draft' ? 'gray' : status === 'pending_review' - ? 'orange' - : 'green' + ? 'orange' + : 'green' } const PostList = () => { diff --git a/examples/query/react/graphql-codegen/src/index.tsx b/examples/query/react/graphql-codegen/src/index.tsx index 88e4ff607c..a3f9271c5c 100644 --- a/examples/query/react/graphql-codegen/src/index.tsx +++ b/examples/query/react/graphql-codegen/src/index.tsx @@ -11,7 +11,7 @@ import { ApiProvider } from '@reduxjs/toolkit/query/react' // Initialize the msw worker, wait for the service worker registration to resolve, then mount worker.start({ quiet: true }).then(() => { return ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById('root') as HTMLElement, ).render( @@ -21,6 +21,6 @@ worker.start({ quiet: true }).then(() => { - + , ) }) diff --git a/examples/query/react/graphql-codegen/src/mocks/db.ts b/examples/query/react/graphql-codegen/src/mocks/db.ts index fededb9d62..78341ab30a 100644 --- a/examples/query/react/graphql-codegen/src/mocks/db.ts +++ b/examples/query/react/graphql-codegen/src/mocks/db.ts @@ -9,7 +9,7 @@ interface Post { title: string author: string content: string - status: typeof postStatuses[number] + status: (typeof postStatuses)[number] created_at: string updated_at: string } diff --git a/examples/query/react/graphql-codegen/tsconfig.json b/examples/query/react/graphql-codegen/tsconfig.json index 93e52d5db1..16a99dca49 100644 --- a/examples/query/react/graphql-codegen/tsconfig.json +++ b/examples/query/react/graphql-codegen/tsconfig.json @@ -1,14 +1,9 @@ { - "include": [ - "./src/**/*" - ], + "include": ["./src/**/*"], "compilerOptions": { "strict": true, "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], + "lib": ["dom", "es2015"], "jsx": "react-jsx", "target": "es5", "allowJs": true, @@ -21,6 +16,6 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "baseUrl": "src" - } + "baseUrl": "src", + }, } diff --git a/examples/query/react/graphql/public/index.html b/examples/query/react/graphql/public/index.html index 09e975e218..e65acb3de5 100644 --- a/examples/query/react/graphql/public/index.html +++ b/examples/query/react/graphql/public/index.html @@ -1,4 +1,4 @@ - + @@ -41,4 +41,3 @@ --> - diff --git a/examples/query/react/graphql/src/app/services/posts.ts b/examples/query/react/graphql/src/app/services/posts.ts index fbbcf0de02..0d84c75f2c 100644 --- a/examples/query/react/graphql/src/app/services/posts.ts +++ b/examples/query/react/graphql/src/app/services/posts.ts @@ -1,6 +1,6 @@ -import { createApi } from '@reduxjs/toolkit/query/react' +import { createApi } from '@reduxjs/toolkit/query/react' import { gql } from 'graphql-request' -import {graphqlRequestBaseQuery} from '@rtk-query/graphql-request-base-query' +import { graphqlRequestBaseQuery } from '@rtk-query/graphql-request-base-query' export const postStatuses = ['draft', 'published', 'pending_review'] as const @@ -9,7 +9,7 @@ export interface Post { title: string author: string content: string - status: typeof postStatuses[number] + status: (typeof postStatuses)[number] created_at: string updated_at: string } diff --git a/examples/query/react/graphql/src/features/posts/PostsManager.tsx b/examples/query/react/graphql/src/features/posts/PostsManager.tsx index e16e6ac46c..8203ed4b3b 100644 --- a/examples/query/react/graphql/src/features/posts/PostsManager.tsx +++ b/examples/query/react/graphql/src/features/posts/PostsManager.tsx @@ -23,8 +23,8 @@ const getColorForStatus = (status: Post['status']) => { return status === 'draft' ? 'gray' : status === 'pending_review' - ? 'orange' - : 'green' + ? 'orange' + : 'green' } const PostList = () => { diff --git a/examples/query/react/graphql/src/index.tsx b/examples/query/react/graphql/src/index.tsx index a7429fe087..db33bb49a1 100644 --- a/examples/query/react/graphql/src/index.tsx +++ b/examples/query/react/graphql/src/index.tsx @@ -11,7 +11,7 @@ import { ApiProvider } from '@reduxjs/toolkit/query/react' // Initialize the msw worker, wait for the service worker registration to resolve, then mount worker.start({ quiet: true }).then(() => { return ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById('root') as HTMLElement, ).render( @@ -21,6 +21,6 @@ worker.start({ quiet: true }).then(() => { - + , ) }) diff --git a/examples/query/react/graphql/src/mocks/db.ts b/examples/query/react/graphql/src/mocks/db.ts index 0aa6a3c2a4..2ba757e6fe 100644 --- a/examples/query/react/graphql/src/mocks/db.ts +++ b/examples/query/react/graphql/src/mocks/db.ts @@ -37,7 +37,8 @@ const createPostData = (): Post => { ;[...new Array(50)].forEach((_) => db.post.create(createPostData())) type PaginationOptions = { - page: number; per_page: number + page: number + per_page: number } interface Posts extends Pagination { @@ -52,19 +53,19 @@ export const handlers = [ const posts = db.post.findMany({ take: per_page, - skip: Math.max(per_page * (page - 1), 0) + skip: Math.max(per_page * (page - 1), 0), }) return res( ctx.data({ data: { - posts + posts, } as { posts: Post[] }, per_page, page, total_pages: Math.ceil(db.post.count() / per_page), total: db.post.count(), - }) + }), ) }), ...db.post.toHandlers('graphql'), diff --git a/examples/query/react/graphql/tsconfig.json b/examples/query/react/graphql/tsconfig.json index 5f488e8e73..7f331f6806 100644 --- a/examples/query/react/graphql/tsconfig.json +++ b/examples/query/react/graphql/tsconfig.json @@ -1,14 +1,9 @@ { - "include": [ - "./src/**/*" - ], + "include": ["./src/**/*"], "compilerOptions": { "strict": true, "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], + "lib": ["dom", "es2015"], "jsx": "react-jsx", "target": "es5", "allowJs": true, @@ -20,6 +15,6 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "noEmit": true - } + "noEmit": true, + }, } diff --git a/examples/query/react/kitchen-sink/public/index.html b/examples/query/react/kitchen-sink/public/index.html index 42ae2d2dcb..efbc007a8b 100644 --- a/examples/query/react/kitchen-sink/public/index.html +++ b/examples/query/react/kitchen-sink/public/index.html @@ -1,17 +1,19 @@ - + - - - - - - - - - - React App - + React App + - - -
- - - - \ No newline at end of file + + diff --git a/examples/query/react/kitchen-sink/src/app/services/api.ts b/examples/query/react/kitchen-sink/src/app/services/api.ts index e9c9ab0c56..0cd4e2e692 100644 --- a/examples/query/react/kitchen-sink/src/app/services/api.ts +++ b/examples/query/react/kitchen-sink/src/app/services/api.ts @@ -20,7 +20,7 @@ const baseQueryWithRetry = retry(baseQuery, { maxRetries: 6 }) * Create a base API to inject endpoints into elsewhere. * Components using this API should import from the injected site, * in order to get the appropriate types, - * and to ensure that the file injecting the endpoints is loaded + * and to ensure that the file injecting the endpoints is loaded */ export const api = createApi({ /** diff --git a/examples/query/react/kitchen-sink/src/app/services/posts.ts b/examples/query/react/kitchen-sink/src/app/services/posts.ts index 08204d0062..04293c4237 100644 --- a/examples/query/react/kitchen-sink/src/app/services/posts.ts +++ b/examples/query/react/kitchen-sink/src/app/services/posts.ts @@ -34,7 +34,7 @@ export const postsApi = api.injectEndpoints({ getPosts: build.query({ query: () => ({ url: 'posts' }), providesTags: (result = []) => [ - ...result.map(({ id }) => ({ type: 'Posts', id } as const)), + ...result.map(({ id }) => ({ type: 'Posts', id }) as const), { type: 'Posts' as const, id: 'LIST' }, ], }), diff --git a/examples/query/react/kitchen-sink/src/app/store.ts b/examples/query/react/kitchen-sink/src/app/store.ts index 82232113dc..e814615c9f 100644 --- a/examples/query/react/kitchen-sink/src/app/store.ts +++ b/examples/query/react/kitchen-sink/src/app/store.ts @@ -5,7 +5,7 @@ import polling from '../features/polling/pollingSlice' import auth from '../features/auth/authSlice' export const createStore = ( - options?: ConfigureStoreOptions['preloadedState'] | undefined + options?: ConfigureStoreOptions['preloadedState'] | undefined, ) => configureStore({ reducer: { diff --git a/examples/query/react/kitchen-sink/src/features/auth/authSlice.ts b/examples/query/react/kitchen-sink/src/features/auth/authSlice.ts index 392d8bcd94..07596a6f20 100644 --- a/examples/query/react/kitchen-sink/src/features/auth/authSlice.ts +++ b/examples/query/react/kitchen-sink/src/features/auth/authSlice.ts @@ -24,6 +24,7 @@ const slice = createSlice({ console.log('fulfilled', action) state.user = action.payload.user state.token = action.payload.token + state.isAuthenticated = true }) .addMatcher(postsApi.endpoints.login.matchRejected, (state, action) => { console.log('rejected', action) diff --git a/examples/query/react/kitchen-sink/src/features/bundleSplitting/Post.tsx b/examples/query/react/kitchen-sink/src/features/bundleSplitting/Post.tsx index ececa81173..fe7de3c6cb 100644 --- a/examples/query/react/kitchen-sink/src/features/bundleSplitting/Post.tsx +++ b/examples/query/react/kitchen-sink/src/features/bundleSplitting/Post.tsx @@ -16,10 +16,7 @@ const Post = ({ id }: { id: number }) => { * This missing would be a programming error that you should * catch early anyways. */ - assert( - postApi.endpoints.getPost?.useQuery, - 'Endpoint `getPost` not loaded!' - ) + assert(postApi.endpoints.getPost?.useQuery, 'Endpoint `getPost` not loaded!') const { data, error } = postApi.endpoints.getPost.useQuery(id) return error ? ( <>there was an error diff --git a/examples/query/react/kitchen-sink/src/features/bundleSplitting/PostsList.tsx b/examples/query/react/kitchen-sink/src/features/bundleSplitting/PostsList.tsx index fc9452a7c5..2c8539fe9a 100644 --- a/examples/query/react/kitchen-sink/src/features/bundleSplitting/PostsList.tsx +++ b/examples/query/react/kitchen-sink/src/features/bundleSplitting/PostsList.tsx @@ -1,7 +1,7 @@ -import * as React from 'react'; +import * as React from 'react' -import { Post } from '.'; -import { postsApi } from '../../app/services/posts'; +import { Post } from '.' +import { postsApi } from '../../app/services/posts' const PostsList = () => { /** @@ -13,8 +13,8 @@ const PostsList = () => { * injected though. */ - const { data, error } = postsApi.endpoints.getPosts.useQuery(); - const [selected, select] = React.useState(); + const { data, error } = postsApi.endpoints.getPosts.useQuery() + const [selected, select] = React.useState() return error ? ( <>there was an error ) : !data ? ( @@ -30,6 +30,6 @@ const PostsList = () => { ))} - ); -}; -export default PostsList; + ) +} +export default PostsList diff --git a/examples/query/react/kitchen-sink/src/features/counter/Counter.module.css b/examples/query/react/kitchen-sink/src/features/counter/Counter.module.css index 2ba30ae792..7e60ca1c7f 100644 --- a/examples/query/react/kitchen-sink/src/features/counter/Counter.module.css +++ b/examples/query/react/kitchen-sink/src/features/counter/Counter.module.css @@ -13,7 +13,7 @@ padding-left: 16px; padding-right: 16px; margin-top: 2px; - font-family: "Courier New", Courier, monospace; + font-family: 'Courier New', Courier, monospace; } .button { @@ -56,7 +56,7 @@ } .asyncButton:after { - content: ""; + content: ''; background-color: rgba(112, 76, 182, 0.15); display: block; position: absolute; @@ -65,7 +65,9 @@ left: 0; top: 0; opacity: 0; - transition: width 1s linear, opacity 0.5s ease 1s; + transition: + width 1s linear, + opacity 0.5s ease 1s; } .asyncButton:active:after { diff --git a/examples/query/react/kitchen-sink/src/features/counter/Counter.tsx b/examples/query/react/kitchen-sink/src/features/counter/Counter.tsx index c192e40ca2..ed8c5bf357 100644 --- a/examples/query/react/kitchen-sink/src/features/counter/Counter.tsx +++ b/examples/query/react/kitchen-sink/src/features/counter/Counter.tsx @@ -1,32 +1,52 @@ -import React, { useState } from 'react'; -import styles from './Counter.module.css'; -import { useDecrementCountMutation, useGetCountQuery, useIncrementCountMutation } from '../../app/services/counter'; +import React, { useState } from 'react' +import styles from './Counter.module.css' +import { + useDecrementCountMutation, + useGetCountQuery, + useIncrementCountMutation, +} from '../../app/services/counter' -export function Counter({ id, onRemove }: { id?: string; onRemove?: () => void }) { - const [pollingInterval, setPollingInterval] = useState(10000); - const { data } = useGetCountQuery(undefined, { pollingInterval }); - const [increment] = useIncrementCountMutation(); +export function Counter({ + id, + onRemove, +}: { + id?: string + onRemove?: () => void +}) { + const [pollingInterval, setPollingInterval] = useState(10000) + const { data } = useGetCountQuery(undefined, { pollingInterval }) + const [increment] = useIncrementCountMutation() - const [decrement] = useDecrementCountMutation(); + const [decrement] = useDecrementCountMutation() return (
- {data?.count || 0} - setPollingInterval(valueAsNumber)} + onChange={({ target: { valueAsNumber } }) => + setPollingInterval(valueAsNumber) + } /> {onRemove && }
- ); + ) } diff --git a/examples/query/react/kitchen-sink/src/features/counter/CounterList.tsx b/examples/query/react/kitchen-sink/src/features/counter/CounterList.tsx index e917b72140..acf946b93b 100644 --- a/examples/query/react/kitchen-sink/src/features/counter/CounterList.tsx +++ b/examples/query/react/kitchen-sink/src/features/counter/CounterList.tsx @@ -1,30 +1,38 @@ -import * as React from 'react'; -import { nanoid } from '@reduxjs/toolkit'; -import { Container } from '../common/Container'; -import { Counter } from './Counter'; +import * as React from 'react' +import { nanoid } from '@reduxjs/toolkit' +import { Container } from '../common/Container' +import { Counter } from './Counter' export const CounterList = () => { - const [counters, setCounters] = React.useState([]); + const [counters, setCounters] = React.useState([]) if (!counters.length) { return (
No counters, why don't you add one?
- +
- ); + ) } return (
- +
{counters.map((id) => ( - setCounters((prev) => prev.filter((el) => el !== id))} /> + setCounters((prev) => prev.filter((el) => el !== id))} + /> ))}
- ); -}; + ) +} diff --git a/examples/query/react/kitchen-sink/src/features/polling/PollingToggles.tsx b/examples/query/react/kitchen-sink/src/features/polling/PollingToggles.tsx index dca03216bd..c67ddc7910 100644 --- a/examples/query/react/kitchen-sink/src/features/polling/PollingToggles.tsx +++ b/examples/query/react/kitchen-sink/src/features/polling/PollingToggles.tsx @@ -1,47 +1,59 @@ -import * as React from 'react'; -import { useAppDispatch, useTypedSelector } from '../../app/store'; +import * as React from 'react' +import { useAppDispatch, useTypedSelector } from '../../app/store' import { selectGlobalPollingEnabled, selectPollingConfigByApp, toggleGlobalPolling, updatePolling, -} from './pollingSlice'; +} from './pollingSlice' const PollingToggleButton = ({ enabled, onClick, children, }: { - onClick: () => void; - enabled: boolean; - children?: React.ReactNode; + onClick: () => void + enabled: boolean + children?: React.ReactNode }) => { return ( - - ); -}; + ) +} export const PollingToggles = () => { - const dispatch = useAppDispatch(); - const globalPolling = useTypedSelector(selectGlobalPollingEnabled); - const timesPolling = useTypedSelector((state) => selectPollingConfigByApp(state, 'times')); + const dispatch = useAppDispatch() + const globalPolling = useTypedSelector(selectGlobalPollingEnabled) + const timesPolling = useTypedSelector((state) => + selectPollingConfigByApp(state, 'times'), + ) return (
Global Polling Configs
- dispatch(toggleGlobalPolling())}> + dispatch(toggleGlobalPolling())} + > Global dispatch(updatePolling({ app: 'times', enabled: !timesPolling.enabled }))} + onClick={() => + dispatch( + updatePolling({ app: 'times', enabled: !timesPolling.enabled }), + ) + } > Times
- ); -}; + ) +} diff --git a/examples/query/react/kitchen-sink/src/features/polling/pollingSlice.ts b/examples/query/react/kitchen-sink/src/features/polling/pollingSlice.ts index e193c3ba01..0a43c7a474 100644 --- a/examples/query/react/kitchen-sink/src/features/polling/pollingSlice.ts +++ b/examples/query/react/kitchen-sink/src/features/polling/pollingSlice.ts @@ -1,17 +1,17 @@ -import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import type { RootState } from '../../app/store'; +import { createSlice, PayloadAction } from '@reduxjs/toolkit' +import type { RootState } from '../../app/store' type PollingConfig = { - enabled: boolean; - interval: number; -}; + enabled: boolean + interval: number +} type SliceState = { - enabled: boolean; + enabled: boolean apps: { - [key: string]: PollingConfig; - }; -}; + [key: string]: PollingConfig + } +} const initialState: SliceState = { enabled: true, @@ -29,39 +29,43 @@ const initialState: SliceState = { interval: 0, }, }, -}; +} -type PollingAppKey = keyof typeof initialState['apps']; +type PollingAppKey = keyof (typeof initialState)['apps'] const slice = createSlice({ name: 'polling', initialState, reducers: { toggleGlobalPolling(state) { - state.enabled = !state.enabled; + state.enabled = !state.enabled }, updatePolling( state, { payload, }: PayloadAction<{ - app: PollingAppKey; - enabled?: boolean; - interval?: number; - }> + app: PollingAppKey + enabled?: boolean + interval?: number + }>, ) { - const { app, ...rest } = payload; + const { app, ...rest } = payload state.apps[app] = { ...state.apps[app], ...rest, - }; + } }, }, -}); +}) -export const { toggleGlobalPolling, updatePolling } = slice.actions; +export const { toggleGlobalPolling, updatePolling } = slice.actions -export default slice.reducer; +export default slice.reducer -export const selectGlobalPollingEnabled = (state: RootState) => state.polling.enabled; -export const selectPollingConfigByApp = (state: RootState, app: PollingAppKey) => state.polling.apps[app]; +export const selectGlobalPollingEnabled = (state: RootState) => + state.polling.enabled +export const selectPollingConfigByApp = ( + state: RootState, + app: PollingAppKey, +) => state.polling.apps[app] diff --git a/examples/query/react/kitchen-sink/src/features/time/TimeList.tsx b/examples/query/react/kitchen-sink/src/features/time/TimeList.tsx index 08f3b7f99c..ecca7ca3bf 100644 --- a/examples/query/react/kitchen-sink/src/features/time/TimeList.tsx +++ b/examples/query/react/kitchen-sink/src/features/time/TimeList.tsx @@ -1,10 +1,13 @@ -import * as React from 'react'; -import { nanoid } from '@reduxjs/toolkit'; -import { useEffect } from 'react'; -import { useGetTimeQuery, usePrefetchTime } from '../../app/services/times'; -import { Container } from '../common/Container'; -import { useTypedSelector } from '../../app/store'; -import { selectGlobalPollingEnabled, selectPollingConfigByApp } from '../polling/pollingSlice'; +import * as React from 'react' +import { nanoid } from '@reduxjs/toolkit' +import { useEffect } from 'react' +import { useGetTimeQuery, usePrefetchTime } from '../../app/services/times' +import { Container } from '../common/Container' +import { useTypedSelector } from '../../app/store' +import { + selectGlobalPollingEnabled, + selectPollingConfigByApp, +} from '../polling/pollingSlice' const timezones: Record = { '-12:00': '(GMT -12:00) Eniwetok, Kwajalein', @@ -47,9 +50,13 @@ const timezones: Record = { '+12:75': '(GMT +12:45) Chatham Islands', '+13:00': '(GMT +13:00) Apia, Nukualofa', '+14:00': '(GMT +14:00) Line Islands, Tokelau', -}; +} -const TimeZoneSelector = ({ onChange }: { onChange: (event: React.ChangeEvent) => void }) => { +const TimeZoneSelector = ({ + onChange, +}: { + onChange: (event: React.ChangeEvent) => void +}) => { return ( - ); -}; + ) +} const intervalOptions = [ { label: '0 - Off', value: 0 }, @@ -69,18 +76,20 @@ const intervalOptions = [ { label: '5s', value: 5000 }, { label: '10s', value: 10000 }, { label: '1m', value: 60000 }, -]; +] const TimeDisplay = ({ offset, label }: { offset: string; label: string }) => { - const globalPolling = useTypedSelector(selectGlobalPollingEnabled); - const { enabled: timesPolling } = useTypedSelector((state) => selectPollingConfigByApp(state, 'times')); + const globalPolling = useTypedSelector(selectGlobalPollingEnabled) + const { enabled: timesPolling } = useTypedSelector((state) => + selectPollingConfigByApp(state, 'times'), + ) - const canPoll = globalPolling && timesPolling; + const canPoll = globalPolling && timesPolling - const [pollingInterval, setPollingInterval] = React.useState(0); + const [pollingInterval, setPollingInterval] = React.useState(0) const { data, refetch, isFetching } = useGetTimeQuery(offset, { pollingInterval: canPoll ? pollingInterval : 0, - }); + }) return (
@@ -89,7 +98,12 @@ const TimeDisplay = ({ offset, label }: { offset: string; label: string }) => {

Polling Interval:{' '} - + setPollingInterval(Number(value)) + } + > {intervalOptions.map(({ label, value }) => (

- ); -}; + ) +} export const TimeList = () => { const [times, setTimes] = React.useState<{ [key: string]: string }>({ [nanoid()]: '-08:00', - }); - const [selectedValue, setSelectedValue] = React.useState(''); + }) + const [selectedValue, setSelectedValue] = React.useState('') - const prefetch = usePrefetchTime('getTime'); + const prefetch = usePrefetchTime('getTime') useEffect(() => { setTimeout(() => { - setTimes((prev) => ({ ...prev, [nanoid()]: '+00:00' })); - }, 1000); - }, []); + setTimes((prev) => ({ ...prev, [nanoid()]: '+00:00' })) + }, 1000) + }, []) return ( -

Add some times, even duplicates, and watch them automatically refetch in sync!

+

+ Add some times, even duplicates, and watch them automatically refetch in + sync! +

- Notes: shared queries (aka multiple entries of the same time zone) will share the lowest polling interval - between them that is greater than 0. If all entries are set to 0, it will stop polling. If you have two entries - with a polling time of 5s and one with 0 - off, it will continue at 5s until they are removed or 0'd out. + Notes: shared queries (aka multiple entries of the same time zone) will + share the lowest polling interval between them that is greater than 0. + If all entries are set to 0, it will stop polling. If you have two + entries with a polling time of 5s and one with 0 - off, it will continue + at 5s until they are removed or 0'd out.
- Any new poll starts after the last request has either finished or failed to prevent slow-running requests to - immediately double-trigger. + Any new poll starts after the last request has either finished or failed + to prevent slow-running requests to immediately double-trigger.
* Background flashes green when query is running - +

- setSelectedValue(value)} /> -
@@ -138,5 +166,5 @@ export const TimeList = () => { ))}
- ); -}; + ) +} diff --git a/examples/query/react/kitchen-sink/src/index.tsx b/examples/query/react/kitchen-sink/src/index.tsx index 6df77c3e0a..460d6ad2b6 100644 --- a/examples/query/react/kitchen-sink/src/index.tsx +++ b/examples/query/react/kitchen-sink/src/index.tsx @@ -13,7 +13,7 @@ async function render() { } const rootNode = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement + document.getElementById('root') as HTMLElement, ) rootNode.render( @@ -23,7 +23,7 @@ async function render() { - + , ) } diff --git a/examples/query/react/kitchen-sink/src/mocks/handlers.ts b/examples/query/react/kitchen-sink/src/mocks/handlers.ts index dd5edddee7..5ede1b6f63 100644 --- a/examples/query/react/kitchen-sink/src/mocks/handlers.ts +++ b/examples/query/react/kitchen-sink/src/mocks/handlers.ts @@ -1,113 +1,125 @@ -import { rest } from 'msw'; -import { createEntityAdapter, nanoid } from '@reduxjs/toolkit'; -import { Post } from '../app/services/posts'; +import { rest } from 'msw' +import { createEntityAdapter, nanoid } from '@reduxjs/toolkit' +import { Post } from '../app/services/posts' // We're just going to use a simple in-memory store for both the counter and posts // The entity adapter will handle modifications when triggered by the MSW handlers -let count = 0; -let startingId = 3; // Just a silly counter for usage when adding new posts +let count = 0 +let startingId = 3 // Just a silly counter for usage when adding new posts -const adapter = createEntityAdapter(); +const adapter = createEntityAdapter() -let state = adapter.getInitialState(); +let state = adapter.getInitialState() state = adapter.setAll(state, [ { id: 1, name: 'A sample post', fetched_at: new Date().toUTCString() }, - { id: 2, name: 'A post about rtk-query', fetched_at: new Date().toUTCString() }, -]); + { + id: 2, + name: 'A post about rtk-query', + fetched_at: new Date().toUTCString(), + }, +]) -export { state }; +export { state } // Just use a random id for an auth token -const token = nanoid(); +const token = nanoid() export const handlers = [ rest.get('/time/:offset', (req, res, ctx) => { - const { offset } = req.params as { offset: string }; - const date = new Date(); - const localDate = date.getTime(); // users local time - const localOffset = date.getTimezoneOffset() * 60000; - const formattedOffset = Number(offset.replace(':', '.')); - const target = localDate + localOffset + 3600000 * formattedOffset; - return res(ctx.json({ time: new Date(target).toUTCString() }), ctx.delay(400)); + const { offset } = req.params as { offset: string } + const date = new Date() + const localDate = date.getTime() // users local time + const localOffset = date.getTimezoneOffset() * 60000 + const formattedOffset = Number(offset.replace(':', '.')) + const target = localDate + localOffset + 3600000 * formattedOffset + return res( + ctx.json({ time: new Date(target).toUTCString() }), + ctx.delay(400), + ) }), rest.put<{ amount: number }>('/increment', (req, res, ctx) => { - const { amount } = req.body; - count = count += amount; + const { amount } = req.body + count = count += amount - return res(ctx.json({ count })); + return res(ctx.json({ count })) }), rest.put<{ amount: number }>('/decrement', (req, res, ctx) => { - const { amount } = req.body; - count = count -= amount; + const { amount } = req.body + count = count -= amount - return res(ctx.json({ count })); + return res(ctx.json({ count })) }), rest.get('/count', (req, res, ctx) => { - return res(ctx.json({ count })); + return res(ctx.json({ count })) }), rest.post('/login', (req, res, ctx) => { - return res.once(ctx.json({ message: 'i fail once' }), ctx.status(500)); + return res.once(ctx.json({ message: 'i fail once' }), ctx.status(500)) }), rest.post('/login', (req, res, ctx) => { - return res(ctx.json({ token, user: { first_name: 'Test', last_name: 'User' } })); + return res( + ctx.json({ token, user: { first_name: 'Test', last_name: 'User' } }), + ) }), rest.get('/posts', (req, res, ctx) => { - return res(ctx.json(Object.values(state.entities))); + return res(ctx.json(Object.values(state.entities))) }), rest.post('/posts', (req, res, ctx) => { - let post = req.body as Partial; - startingId += 1; - state = adapter.addOne(state, { ...post, id: startingId } as Post); - return res(ctx.json(Object.values(state.entities)), ctx.delay(400)); + let post = req.body as Partial + startingId += 1 + state = adapter.addOne(state, { ...post, id: startingId } as Post) + return res(ctx.json(Object.values(state.entities)), ctx.delay(400)) }), rest.get('/posts/:id', (req, res, ctx) => { const { id: idParam } = req.params as { id: string } const id = parseInt(idParam, 10) - state = adapter.updateOne(state, { id, changes: { fetched_at: new Date().toUTCString() } }); - return res(ctx.json(state.entities[id]), ctx.delay(400)); + state = adapter.updateOne(state, { + id, + changes: { fetched_at: new Date().toUTCString() }, + }) + return res(ctx.json(state.entities[id]), ctx.delay(400)) }), rest.put('/posts/:id', (req, res, ctx) => { const { id: idParam } = req.params as { id: string } const id = parseInt(idParam, 10) - const changes = req.body as Partial; + const changes = req.body as Partial - state = adapter.updateOne(state, { id, changes }); + state = adapter.updateOne(state, { id, changes }) - return res(ctx.json(state.entities[id]), ctx.delay(400)); + return res(ctx.json(state.entities[id]), ctx.delay(400)) }), rest.delete('/posts/:id', (req, res, ctx) => { const { id: idParam } = req.params as { id: string } const id = parseInt(idParam, 10) - state = adapter.removeOne(state, id); + state = adapter.removeOne(state, id) return res( ctx.json({ id, success: true, }), - ctx.delay(600) - ); + ctx.delay(600), + ) }), rest.get('/error-prone', (req, res, ctx) => { if (Math.random() > 0.1) { - return res(ctx.json({ error: 'failed!' }), ctx.status(500)); + return res(ctx.json({ error: 'failed!' }), ctx.status(500)) } return res( ctx.json({ success: true, - }) - ); + }), + ) }), -]; +] diff --git a/examples/query/react/kitchen-sink/src/mocks/setupTests.tsx b/examples/query/react/kitchen-sink/src/mocks/setupTests.tsx index 899d316d61..eee2de33b0 100644 --- a/examples/query/react/kitchen-sink/src/mocks/setupTests.tsx +++ b/examples/query/react/kitchen-sink/src/mocks/setupTests.tsx @@ -24,7 +24,7 @@ export const setupTests = () => { } function renderWithProvider( children: React.ReactChild, - { route, path }: RenderOptions = { route: '/', path: '' } + { route, path }: RenderOptions = { route: '/', path: '' }, ) { const history = createMemoryHistory() history.push(route) @@ -39,7 +39,7 @@ export const setupTests = () => { children )} - + , ) } diff --git a/examples/query/react/kitchen-sink/src/setupTests.ts b/examples/query/react/kitchen-sink/src/setupTests.ts index 74b1a275a0..2eb59b05d8 100644 --- a/examples/query/react/kitchen-sink/src/setupTests.ts +++ b/examples/query/react/kitchen-sink/src/setupTests.ts @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom/extend-expect'; +import '@testing-library/jest-dom/extend-expect' diff --git a/examples/query/react/kitchen-sink/tsconfig.json b/examples/query/react/kitchen-sink/tsconfig.json index d4eea2ea4b..7f331f6806 100644 --- a/examples/query/react/kitchen-sink/tsconfig.json +++ b/examples/query/react/kitchen-sink/tsconfig.json @@ -1,25 +1,20 @@ { - "include": [ - "./src/**/*" - ], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } -} \ No newline at end of file + "include": ["./src/**/*"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "lib": ["dom", "es2015"], + "jsx": "react-jsx", + "target": "es5", + "allowJs": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + }, +} diff --git a/examples/query/react/mutations/public/index.html b/examples/query/react/mutations/public/index.html index 42ae2d2dcb..efbc007a8b 100644 --- a/examples/query/react/mutations/public/index.html +++ b/examples/query/react/mutations/public/index.html @@ -1,17 +1,19 @@ - + - - - - - - - - - - React App - + React App + - - -
- - - - \ No newline at end of file + + diff --git a/examples/query/react/mutations/src/index.tsx b/examples/query/react/mutations/src/index.tsx index 3854044b5e..ca83c0fe6d 100644 --- a/examples/query/react/mutations/src/index.tsx +++ b/examples/query/react/mutations/src/index.tsx @@ -19,6 +19,6 @@ worker.start({ quiet: true }).then(() => - - ) + , + ), ) diff --git a/examples/query/react/mutations/src/mocks/db.ts b/examples/query/react/mutations/src/mocks/db.ts index 5ade9028d0..98599624e8 100644 --- a/examples/query/react/mutations/src/mocks/db.ts +++ b/examples/query/react/mutations/src/mocks/db.ts @@ -26,7 +26,7 @@ export const handlers = [ return res( ctx.json({ error: 'Oh no, there was an error, try again.' }), ctx.status(500), - ctx.delay(300) + ctx.delay(300), ) } @@ -44,7 +44,7 @@ export const handlers = [ return res( ctx.json({ error: 'Oh no, there was an error, try again.' }), ctx.status(500), - ctx.delay(300) + ctx.delay(300), ) } diff --git a/examples/query/react/mutations/tsconfig.json b/examples/query/react/mutations/tsconfig.json index d4eea2ea4b..7f331f6806 100644 --- a/examples/query/react/mutations/tsconfig.json +++ b/examples/query/react/mutations/tsconfig.json @@ -1,25 +1,20 @@ { - "include": [ - "./src/**/*" - ], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } -} \ No newline at end of file + "include": ["./src/**/*"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "lib": ["dom", "es2015"], + "jsx": "react-jsx", + "target": "es5", + "allowJs": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + }, +} diff --git a/examples/query/react/optimistic-update/public/index.html b/examples/query/react/optimistic-update/public/index.html index 09e975e218..e65acb3de5 100644 --- a/examples/query/react/optimistic-update/public/index.html +++ b/examples/query/react/optimistic-update/public/index.html @@ -1,4 +1,4 @@ - + @@ -41,4 +41,3 @@ --> - diff --git a/examples/query/react/optimistic-update/src/app/services/posts.ts b/examples/query/react/optimistic-update/src/app/services/posts.ts index 6fa771dbfe..3033e3ad2f 100644 --- a/examples/query/react/optimistic-update/src/app/services/posts.ts +++ b/examples/query/react/optimistic-update/src/app/services/posts.ts @@ -43,7 +43,7 @@ export const api = createApi({ const patchResult = dispatch( api.util.updateQueryData('getPost', id, (draft) => { Object.assign(draft, patch) - }) + }), ) try { await queryFulfilled diff --git a/examples/query/react/optimistic-update/src/index.tsx b/examples/query/react/optimistic-update/src/index.tsx index 5d044d74eb..9440268a89 100644 --- a/examples/query/react/optimistic-update/src/index.tsx +++ b/examples/query/react/optimistic-update/src/index.tsx @@ -19,6 +19,6 @@ worker.start({ quiet: true }).then(() => - - ) + , + ), ) diff --git a/examples/query/react/optimistic-update/src/mocks/db.ts b/examples/query/react/optimistic-update/src/mocks/db.ts index 73ec3f64a7..98e6857860 100644 --- a/examples/query/react/optimistic-update/src/mocks/db.ts +++ b/examples/query/react/optimistic-update/src/mocks/db.ts @@ -19,7 +19,7 @@ export const handlers = [ return res( ctx.json({ error: 'Oh no, there was an error' }), ctx.status(500), - ctx.delay(400) + ctx.delay(400), ) } diff --git a/examples/query/react/optimistic-update/tsconfig.json b/examples/query/react/optimistic-update/tsconfig.json index 5f488e8e73..7f331f6806 100644 --- a/examples/query/react/optimistic-update/tsconfig.json +++ b/examples/query/react/optimistic-update/tsconfig.json @@ -1,14 +1,9 @@ { - "include": [ - "./src/**/*" - ], + "include": ["./src/**/*"], "compilerOptions": { "strict": true, "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], + "lib": ["dom", "es2015"], "jsx": "react-jsx", "target": "es5", "allowJs": true, @@ -20,6 +15,6 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "noEmit": true - } + "noEmit": true, + }, } diff --git a/examples/query/react/pagination/public/index.html b/examples/query/react/pagination/public/index.html index 09e975e218..e65acb3de5 100644 --- a/examples/query/react/pagination/public/index.html +++ b/examples/query/react/pagination/public/index.html @@ -1,4 +1,4 @@ - + @@ -41,4 +41,3 @@ --> - diff --git a/examples/query/react/pagination/src/app/services/posts.ts b/examples/query/react/pagination/src/app/services/posts.ts index 0b50ae3b64..b4863852b2 100644 --- a/examples/query/react/pagination/src/app/services/posts.ts +++ b/examples/query/react/pagination/src/app/services/posts.ts @@ -7,7 +7,7 @@ export interface Post { title: string author: string content: string - status: typeof postStatuses[number] + status: (typeof postStatuses)[number] created_at: string updated_at: string } diff --git a/examples/query/react/pagination/src/features/posts/PostsManager.tsx b/examples/query/react/pagination/src/features/posts/PostsManager.tsx index 9a790c7e9f..52f3b824a9 100644 --- a/examples/query/react/pagination/src/features/posts/PostsManager.tsx +++ b/examples/query/react/pagination/src/features/posts/PostsManager.tsx @@ -23,8 +23,8 @@ const getColorForStatus = (status: Post['status']) => { return status === 'draft' ? 'gray' : status === 'pending_review' - ? 'orange' - : 'green' + ? 'orange' + : 'green' } const PostList = () => { diff --git a/examples/query/react/pagination/src/index.tsx b/examples/query/react/pagination/src/index.tsx index 5d044d74eb..9440268a89 100644 --- a/examples/query/react/pagination/src/index.tsx +++ b/examples/query/react/pagination/src/index.tsx @@ -19,6 +19,6 @@ worker.start({ quiet: true }).then(() => - - ) + , + ), ) diff --git a/examples/query/react/pagination/src/mocks/db.ts b/examples/query/react/pagination/src/mocks/db.ts index 5dc3d0968b..89703a4617 100644 --- a/examples/query/react/pagination/src/mocks/db.ts +++ b/examples/query/react/pagination/src/mocks/db.ts @@ -50,7 +50,7 @@ export const handlers = [ page, total_pages: Math.ceil(db.post.count() / per_page), total: db.post.count(), - }) + }), ) }), ...db.post.toHandlers('rest'), diff --git a/examples/query/react/pagination/tsconfig.json b/examples/query/react/pagination/tsconfig.json index 5f488e8e73..7f331f6806 100644 --- a/examples/query/react/pagination/tsconfig.json +++ b/examples/query/react/pagination/tsconfig.json @@ -1,14 +1,9 @@ { - "include": [ - "./src/**/*" - ], + "include": ["./src/**/*"], "compilerOptions": { "strict": true, "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], + "lib": ["dom", "es2015"], "jsx": "react-jsx", "target": "es5", "allowJs": true, @@ -20,6 +15,6 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "noEmit": true - } + "noEmit": true, + }, } diff --git a/examples/query/react/polling/public/index.html b/examples/query/react/polling/public/index.html index 42ae2d2dcb..efbc007a8b 100644 --- a/examples/query/react/polling/public/index.html +++ b/examples/query/react/polling/public/index.html @@ -1,17 +1,19 @@ - + - - - - - - - - - - React App - + React App + - - -
- - - - \ No newline at end of file + + diff --git a/examples/query/react/polling/src/Pokemon.tsx b/examples/query/react/polling/src/Pokemon.tsx index 342023c135..e572b83cdd 100644 --- a/examples/query/react/polling/src/Pokemon.tsx +++ b/examples/query/react/polling/src/Pokemon.tsx @@ -15,18 +15,13 @@ const getRandomIntervalValue = () => export const Pokemon = ({ name }: { name: PokemonName }) => { const [pollingInterval, setPollingInterval] = React.useState( - getRandomIntervalValue() + getRandomIntervalValue(), ) - const { - data, - error, - isLoading, - isFetching, - refetch, - } = useGetPokemonByNameQuery(name, { - pollingInterval, - }) + const { data, error, isLoading, isFetching, refetch } = + useGetPokemonByNameQuery(name, { + pollingInterval, + }) return (
- + , ) diff --git a/examples/query/react/polling/src/pokemon.data.ts b/examples/query/react/polling/src/pokemon.data.ts index 1617ce9e50..22eb3a0547 100644 --- a/examples/query/react/polling/src/pokemon.data.ts +++ b/examples/query/react/polling/src/pokemon.data.ts @@ -152,4 +152,4 @@ export const POKEMON_NAMES = [ 'mew', ] as const -export type PokemonName = typeof POKEMON_NAMES[number] +export type PokemonName = (typeof POKEMON_NAMES)[number] diff --git a/examples/query/react/polling/tsconfig.json b/examples/query/react/polling/tsconfig.json index d4eea2ea4b..7f331f6806 100644 --- a/examples/query/react/polling/tsconfig.json +++ b/examples/query/react/polling/tsconfig.json @@ -1,25 +1,20 @@ { - "include": [ - "./src/**/*" - ], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } -} \ No newline at end of file + "include": ["./src/**/*"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "lib": ["dom", "es2015"], + "jsx": "react-jsx", + "target": "es5", + "allowJs": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + }, +} diff --git a/examples/query/react/prefetching-automatic-waterfall/public/index.html b/examples/query/react/prefetching-automatic-waterfall/public/index.html index 09e975e218..e65acb3de5 100644 --- a/examples/query/react/prefetching-automatic-waterfall/public/index.html +++ b/examples/query/react/prefetching-automatic-waterfall/public/index.html @@ -1,4 +1,4 @@ - + @@ -41,4 +41,3 @@ --> - diff --git a/examples/query/react/prefetching-automatic-waterfall/src/app/services/posts.ts b/examples/query/react/prefetching-automatic-waterfall/src/app/services/posts.ts index e8cb02f9e4..d4032ef9cf 100644 --- a/examples/query/react/prefetching-automatic-waterfall/src/app/services/posts.ts +++ b/examples/query/react/prefetching-automatic-waterfall/src/app/services/posts.ts @@ -7,7 +7,7 @@ export interface Post { title: string author: string content: string - status: typeof postStatuses[number] + status: (typeof postStatuses)[number] created_at: string updated_at: string } diff --git a/examples/query/react/prefetching-automatic-waterfall/src/features/posts/PostsManager.tsx b/examples/query/react/prefetching-automatic-waterfall/src/features/posts/PostsManager.tsx index e8cea9b348..eb093dade1 100644 --- a/examples/query/react/prefetching-automatic-waterfall/src/features/posts/PostsManager.tsx +++ b/examples/query/react/prefetching-automatic-waterfall/src/features/posts/PostsManager.tsx @@ -23,8 +23,8 @@ const getColorForStatus = (status: Post['status']) => { return status === 'draft' ? 'gray' : status === 'pending_review' - ? 'orange' - : 'green' + ? 'orange' + : 'green' } const PostList = () => { diff --git a/examples/query/react/prefetching-automatic-waterfall/src/index.tsx b/examples/query/react/prefetching-automatic-waterfall/src/index.tsx index 5d044d74eb..9440268a89 100644 --- a/examples/query/react/prefetching-automatic-waterfall/src/index.tsx +++ b/examples/query/react/prefetching-automatic-waterfall/src/index.tsx @@ -19,6 +19,6 @@ worker.start({ quiet: true }).then(() => - - ) + , + ), ) diff --git a/examples/query/react/prefetching-automatic-waterfall/src/mocks/db.ts b/examples/query/react/prefetching-automatic-waterfall/src/mocks/db.ts index 5dc3d0968b..89703a4617 100644 --- a/examples/query/react/prefetching-automatic-waterfall/src/mocks/db.ts +++ b/examples/query/react/prefetching-automatic-waterfall/src/mocks/db.ts @@ -50,7 +50,7 @@ export const handlers = [ page, total_pages: Math.ceil(db.post.count() / per_page), total: db.post.count(), - }) + }), ) }), ...db.post.toHandlers('rest'), diff --git a/examples/query/react/prefetching-automatic-waterfall/tsconfig.json b/examples/query/react/prefetching-automatic-waterfall/tsconfig.json index 5f488e8e73..7f331f6806 100644 --- a/examples/query/react/prefetching-automatic-waterfall/tsconfig.json +++ b/examples/query/react/prefetching-automatic-waterfall/tsconfig.json @@ -1,14 +1,9 @@ { - "include": [ - "./src/**/*" - ], + "include": ["./src/**/*"], "compilerOptions": { "strict": true, "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], + "lib": ["dom", "es2015"], "jsx": "react-jsx", "target": "es5", "allowJs": true, @@ -20,6 +15,6 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "noEmit": true - } + "noEmit": true, + }, } diff --git a/examples/query/react/prefetching-automatic/public/index.html b/examples/query/react/prefetching-automatic/public/index.html index 09e975e218..e65acb3de5 100644 --- a/examples/query/react/prefetching-automatic/public/index.html +++ b/examples/query/react/prefetching-automatic/public/index.html @@ -1,4 +1,4 @@ - + @@ -41,4 +41,3 @@ --> - diff --git a/examples/query/react/prefetching-automatic/src/app/services/posts.ts b/examples/query/react/prefetching-automatic/src/app/services/posts.ts index e8cb02f9e4..d4032ef9cf 100644 --- a/examples/query/react/prefetching-automatic/src/app/services/posts.ts +++ b/examples/query/react/prefetching-automatic/src/app/services/posts.ts @@ -7,7 +7,7 @@ export interface Post { title: string author: string content: string - status: typeof postStatuses[number] + status: (typeof postStatuses)[number] created_at: string updated_at: string } diff --git a/examples/query/react/prefetching-automatic/src/features/posts/PostsManager.tsx b/examples/query/react/prefetching-automatic/src/features/posts/PostsManager.tsx index ce01a87daf..3435481082 100644 --- a/examples/query/react/prefetching-automatic/src/features/posts/PostsManager.tsx +++ b/examples/query/react/prefetching-automatic/src/features/posts/PostsManager.tsx @@ -23,8 +23,8 @@ const getColorForStatus = (status: Post['status']) => { return status === 'draft' ? 'gray' : status === 'pending_review' - ? 'orange' - : 'green' + ? 'orange' + : 'green' } const PostList = () => { diff --git a/examples/query/react/prefetching-automatic/src/index.tsx b/examples/query/react/prefetching-automatic/src/index.tsx index 5d044d74eb..9440268a89 100644 --- a/examples/query/react/prefetching-automatic/src/index.tsx +++ b/examples/query/react/prefetching-automatic/src/index.tsx @@ -19,6 +19,6 @@ worker.start({ quiet: true }).then(() => - - ) + , + ), ) diff --git a/examples/query/react/prefetching-automatic/src/mocks/db.ts b/examples/query/react/prefetching-automatic/src/mocks/db.ts index 5dc3d0968b..89703a4617 100644 --- a/examples/query/react/prefetching-automatic/src/mocks/db.ts +++ b/examples/query/react/prefetching-automatic/src/mocks/db.ts @@ -50,7 +50,7 @@ export const handlers = [ page, total_pages: Math.ceil(db.post.count() / per_page), total: db.post.count(), - }) + }), ) }), ...db.post.toHandlers('rest'), diff --git a/examples/query/react/prefetching-automatic/tsconfig.json b/examples/query/react/prefetching-automatic/tsconfig.json index 5f488e8e73..7f331f6806 100644 --- a/examples/query/react/prefetching-automatic/tsconfig.json +++ b/examples/query/react/prefetching-automatic/tsconfig.json @@ -1,14 +1,9 @@ { - "include": [ - "./src/**/*" - ], + "include": ["./src/**/*"], "compilerOptions": { "strict": true, "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], + "lib": ["dom", "es2015"], "jsx": "react-jsx", "target": "es5", "allowJs": true, @@ -20,6 +15,6 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "noEmit": true - } + "noEmit": true, + }, } diff --git a/examples/query/react/prefetching/public/index.html b/examples/query/react/prefetching/public/index.html index 09e975e218..e65acb3de5 100644 --- a/examples/query/react/prefetching/public/index.html +++ b/examples/query/react/prefetching/public/index.html @@ -1,4 +1,4 @@ - + @@ -41,4 +41,3 @@ --> - diff --git a/examples/query/react/prefetching/src/app/services/posts.ts b/examples/query/react/prefetching/src/app/services/posts.ts index e8cb02f9e4..d4032ef9cf 100644 --- a/examples/query/react/prefetching/src/app/services/posts.ts +++ b/examples/query/react/prefetching/src/app/services/posts.ts @@ -7,7 +7,7 @@ export interface Post { title: string author: string content: string - status: typeof postStatuses[number] + status: (typeof postStatuses)[number] created_at: string updated_at: string } diff --git a/examples/query/react/prefetching/src/features/posts/PostsManager.tsx b/examples/query/react/prefetching/src/features/posts/PostsManager.tsx index 2aaebf2c7c..5999215a98 100644 --- a/examples/query/react/prefetching/src/features/posts/PostsManager.tsx +++ b/examples/query/react/prefetching/src/features/posts/PostsManager.tsx @@ -23,8 +23,8 @@ const getColorForStatus = (status: Post['status']) => { return status === 'draft' ? 'gray' : status === 'pending_review' - ? 'orange' - : 'green' + ? 'orange' + : 'green' } const PostList = () => { diff --git a/examples/query/react/prefetching/src/index.tsx b/examples/query/react/prefetching/src/index.tsx index 5d044d74eb..9440268a89 100644 --- a/examples/query/react/prefetching/src/index.tsx +++ b/examples/query/react/prefetching/src/index.tsx @@ -19,6 +19,6 @@ worker.start({ quiet: true }).then(() => - - ) + , + ), ) diff --git a/examples/query/react/prefetching/src/mocks/db.ts b/examples/query/react/prefetching/src/mocks/db.ts index 5dc3d0968b..89703a4617 100644 --- a/examples/query/react/prefetching/src/mocks/db.ts +++ b/examples/query/react/prefetching/src/mocks/db.ts @@ -50,7 +50,7 @@ export const handlers = [ page, total_pages: Math.ceil(db.post.count() / per_page), total: db.post.count(), - }) + }), ) }), ...db.post.toHandlers('rest'), diff --git a/examples/query/react/prefetching/tsconfig.json b/examples/query/react/prefetching/tsconfig.json index 5f488e8e73..7f331f6806 100644 --- a/examples/query/react/prefetching/tsconfig.json +++ b/examples/query/react/prefetching/tsconfig.json @@ -1,14 +1,9 @@ { - "include": [ - "./src/**/*" - ], + "include": ["./src/**/*"], "compilerOptions": { "strict": true, "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], + "lib": ["dom", "es2015"], "jsx": "react-jsx", "target": "es5", "allowJs": true, @@ -20,6 +15,6 @@ "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, - "noEmit": true - } + "noEmit": true, + }, } diff --git a/examples/query/react/with-apiprovider/public/index.html b/examples/query/react/with-apiprovider/public/index.html index 42ae2d2dcb..efbc007a8b 100644 --- a/examples/query/react/with-apiprovider/public/index.html +++ b/examples/query/react/with-apiprovider/public/index.html @@ -1,17 +1,19 @@ - + - - - - - - - - - - React App - + React App + - - -
- - - - \ No newline at end of file + + diff --git a/examples/query/react/with-apiprovider/src/App.tsx b/examples/query/react/with-apiprovider/src/App.tsx index a91982c4b9..f8ded9f1b6 100644 --- a/examples/query/react/with-apiprovider/src/App.tsx +++ b/examples/query/react/with-apiprovider/src/App.tsx @@ -14,9 +14,8 @@ const api = createApi({ }) function Pokemon() { - const { data, refetch, isFetching } = api.useGetPokemonByNameQuery( - 'bulbasaur' - ) + const { data, refetch, isFetching } = + api.useGetPokemonByNameQuery('bulbasaur') return (
diff --git a/examples/query/react/with-apiprovider/tsconfig.json b/examples/query/react/with-apiprovider/tsconfig.json index d4eea2ea4b..7f331f6806 100644 --- a/examples/query/react/with-apiprovider/tsconfig.json +++ b/examples/query/react/with-apiprovider/tsconfig.json @@ -1,25 +1,20 @@ { - "include": [ - "./src/**/*" - ], - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "lib": [ - "dom", - "es2015" - ], - "jsx": "react-jsx", - "target": "es5", - "allowJs": true, - "skipLibCheck": true, - "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true - } -} \ No newline at end of file + "include": ["./src/**/*"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "lib": ["dom", "es2015"], + "jsx": "react-jsx", + "target": "es5", + "allowJs": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + }, +} diff --git a/package.json b/package.json index d5fc2edd89..8434135d02 100644 --- a/package.json +++ b/package.json @@ -23,20 +23,22 @@ "examples/action-listener/*" ], "devDependencies": { + "@typescript-eslint/eslint-plugin": "6.12.0", + "@typescript-eslint/parser": "6.12.0", "eslint": "^7.25.0", - "eslint-config-prettier": "^8.3.0", + "eslint-config-prettier": "^9.1.0", "eslint-config-react-app": "^7.0.1", "eslint-plugin-flowtype": "^5.7.2", "eslint-plugin-import": "^2.22.1", "eslint-plugin-jsx-a11y": "^6.4.1", - "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.23.2", "eslint-plugin-react-hooks": "^4.2.0", "netlify-plugin-cache": "^1.0.3", - "prettier": "^2.2.1", + "prettier": "^3.2.4", "release-it": "^14.12.5", "serve": "^14.2.0", - "typescript": "5.2" + "typescript": "^5.2.2" }, "resolutions": { "@babel/core": "7.19.3", @@ -47,8 +49,6 @@ "@babel/types": "7.19.3", "esbuild": "0.19.7", "jest-snapshot": "29.3.1", - "msw": "patch:msw@npm:0.40.2#.yarn/patches/msw-npm-0.40.2-2107d48752", - "jscodeshift": "0.13.1", "react-redux": "npm:8.0.2", "react": "npm:18.2.0", "react-dom": "npm:18.2.0", @@ -66,12 +66,7 @@ "docs/@types/react-dom": "npm:17.0.11", "docs/@types/react": "npm:17.0.11", "type-fest": "2.19.0", - "console-testing-library@0.6.1": "patch:console-testing-library@npm%3A0.6.1#./.yarn/patches/console-testing-library-npm-0.6.1-4d9957d402.patch", - "@typescript-eslint/eslint-plugin": "6.12.0", - "@typescript-eslint/parser": "6.12.0", - "typescript": "5.2.2", - "size-limit@^11.0.1": "patch:size-limit@npm%3A11.0.1#./.yarn/patches/size-limit-npm-11.0.1-05996e44e7.patch", - "size-limit@11.0.1": "patch:size-limit@npm%3A11.0.1#./.yarn/patches/size-limit-npm-11.0.1-05996e44e7.patch" + "console-testing-library@0.6.1": "patch:console-testing-library@npm%3A0.6.1#./.yarn/patches/console-testing-library-npm-0.6.1-4d9957d402.patch" }, "scripts": { "build": "yarn build:packages", diff --git a/packages/rtk-codemods/.eslintignore b/packages/rtk-codemods/.eslintignore deleted file mode 100644 index 28d21228da..0000000000 --- a/packages/rtk-codemods/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -!.* -__testfixtures__ \ No newline at end of file diff --git a/packages/rtk-codemods/.eslintrc.js b/packages/rtk-codemods/.eslintrc.js deleted file mode 100644 index 475aa701d9..0000000000 --- a/packages/rtk-codemods/.eslintrc.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - parserOptions: { - ecmaVersion: 2018, - }, - - plugins: ['prettier', 'node'], - extends: ['eslint:recommended', 'plugin:prettier/recommended'], - env: { - node: true, - }, - rules: {}, - overrides: [ - { - files: ['__tests__/**/*.js'], - env: { - jest: true, - }, - }, - ], -}; diff --git a/packages/rtk-codemods/.eslintrc.json b/packages/rtk-codemods/.eslintrc.json new file mode 100644 index 0000000000..8f15e141ae --- /dev/null +++ b/packages/rtk-codemods/.eslintrc.json @@ -0,0 +1,11 @@ +{ + "env": { "node": true }, + "extends": ["eslint:recommended"], + "ignorePatterns": ["node_modules"], + "parserOptions": { "ecmaVersion": "latest" }, + "plugins": ["node"], + "rules": { + "no-unused-vars": [0], + "eol-last": [0] + } +} diff --git a/packages/rtk-codemods/.github/workflows/ci.yml b/packages/rtk-codemods/.github/workflows/ci.yml index ec853b3887..a4dd4e2ed0 100644 --- a/packages/rtk-codemods/.github/workflows/ci.yml +++ b/packages/rtk-codemods/.github/workflows/ci.yml @@ -10,7 +10,7 @@ on: - '*' pull_request: {} schedule: - - cron: '0 6 * * 0' # weekly, on sundays + - cron: '0 6 * * 0' # weekly, on sundays jobs: lint: @@ -18,14 +18,14 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 - with: - node-version: 12.x - - name: install dependencies - run: yarn install --frozen-lockfile - - name: linting - run: yarn lint + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: 12.x + - name: install dependencies + run: yarn install --frozen-lockfile + - name: linting + run: yarn lint test: name: Tests @@ -36,25 +36,25 @@ jobs: node: ['10', '12', '14'] steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node }} - - name: install dependencies - run: yarn install --frozen-lockfile - - name: test - run: yarn test + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node }} + - name: install dependencies + run: yarn install --frozen-lockfile + - name: test + run: yarn test floating-test: name: Floating dependencies runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 - with: - node-version: '12.x' - - name: install dependencies - run: yarn install --no-lockfile - - name: test - run: yarn test \ No newline at end of file + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: '12.x' + - name: install dependencies + run: yarn install --no-lockfile + - name: test + run: yarn test diff --git a/packages/rtk-codemods/.gitignore b/packages/rtk-codemods/.gitignore index 568cda7371..56fd2d9f2d 100644 --- a/packages/rtk-codemods/.gitignore +++ b/packages/rtk-codemods/.gitignore @@ -1,2 +1,32 @@ +# Dependencies /node_modules -/.eslintcache \ No newline at end of file + +# Production +/build + +# Generated files +.docusaurus +.cache-loader + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.cache +.yarnrc +.yarn/* +!.yarn/patches +!.yarn/releases +!.yarn/plugins +!.yarn/sdks +!.yarn/versions +.pnp.* +*.tgz + +/.eslintcache diff --git a/packages/rtk-codemods/.prettierrc b/packages/rtk-codemods/.prettierrc deleted file mode 100644 index 7c2b752778..0000000000 --- a/packages/rtk-codemods/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "singleQuote": true, - "trailingComma": "es5", - "printWidth": 100 -} \ No newline at end of file diff --git a/packages/rtk-codemods/.prettierrc.json b/packages/rtk-codemods/.prettierrc.json new file mode 100644 index 0000000000..44ee5173aa --- /dev/null +++ b/packages/rtk-codemods/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "singleQuote": true, + "trailingComma": "none", + "printWidth": 80, + "semi": false +} diff --git a/packages/rtk-codemods/README.md b/packages/rtk-codemods/README.md index be04f2b53b..ab7f117881 100644 --- a/packages/rtk-codemods/README.md +++ b/packages/rtk-codemods/README.md @@ -27,6 +27,7 @@ node ./bin/cli.js path/of/files/ or/some**/*glob.js - [createReducerBuilder](transforms/createReducerBuilder/README.md) - [createSliceBuilder](transforms/createSliceBuilder/README.md) +- [createSliceReducerBuilder](transforms/createSliceReducerBuilder/README.md) ## Contributing diff --git a/packages/rtk-codemods/bin/cli.js b/packages/rtk-codemods/bin/cli.js index 76d86db833..53a0f8b819 100755 --- a/packages/rtk-codemods/bin/cli.js +++ b/packages/rtk-codemods/bin/cli.js @@ -1,12 +1,39 @@ #!/usr/bin/env node -const path = require('path'); +import { execaSync } from 'execa' +import { globbySync } from 'globby' +import { createRequire } from 'node:module' +import path from 'node:path' +import { fileURLToPath } from 'node:url' -require('ts-node').register({ - project: path.join(__dirname, './tsconfig.json'), -}); +const require = createRequire(import.meta.url) -require('codemod-cli').runTransform( +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +const transformerDirectory = path.join( __dirname, - process.argv[2] /* transform name */, - process.argv.slice(3) /* paths or globs */ -); + '..', + 'transforms', + `${process.argv[2]}/index.ts` +) + +const jscodeshiftExecutable = require.resolve('.bin/jscodeshift') + +const extensions = 'ts,js,tsx,jsx' + +execaSync( + jscodeshiftExecutable, + [ + '-t', + transformerDirectory, + '--extensions', + extensions, + ...(process.argv.slice(3).length === 1 + ? globbySync(process.argv[3]) + : globbySync(process.argv.slice(3))) + ], + { + stdio: 'inherit', + stripFinalNewline: false + } +) diff --git a/packages/rtk-codemods/bin/tsconfig.json b/packages/rtk-codemods/bin/tsconfig.json deleted file mode 100644 index d472d5de40..0000000000 --- a/packages/rtk-codemods/bin/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "compilerOptions": { - "target": "es2017", - "module": "commonjs" , - "strict": true , - "noUnusedLocals": false, - "resolveJsonModule": true, - "moduleResolution": "node", - "types": ["node"], - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true - } -} diff --git a/packages/rtk-codemods/package.json b/packages/rtk-codemods/package.json index a8ac4a2acb..54f206cb24 100644 --- a/packages/rtk-codemods/package.json +++ b/packages/rtk-codemods/package.json @@ -1,11 +1,11 @@ { "name": "@reduxjs/rtk-codemods", - "version": "0.1.0", + "version": "0.1.1", "scripts": { - "lint": "eslint --cache .", - "test": "vitest", - "test:coverage": "vitest --coverage", - "update-docs": "codemod-cli update-docs" + "lint": "eslint .", + "test": "vitest --run", + "test:watch": "vitest --watch", + "test:coverage": "vitest --coverage" }, "bin": "./bin/cli.js", "files": [ @@ -22,17 +22,21 @@ "codemod" ], "dependencies": { - "@types/jscodeshift": "^0.11.5", - "codemod-cli": "^3.2.0", - "typescript": "^4.8.0" + "execa": "^8.0.1", + "globby": "^14.0.0", + "jscodeshift": "^0.15.1", + "ts-node": "^10.9.2", + "typescript": "^5.3.3" }, "devDependencies": { - "eslint": "^7.25.0", - "eslint-config-prettier": "^8.3.0", + "@types/jscodeshift": "^0.11.11", + "@typescript-eslint/parser": "^6.19.1", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^3.4.0", - "prettier": "^2.2.1", - "vitest": "^0.30.1" + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.2.4", + "vitest": "^1.2.1" }, "engines": { "node": ">= 16" diff --git a/packages/rtk-codemods/transformTestUtils.ts b/packages/rtk-codemods/transformTestUtils.ts index b49314cc73..2d4be2c0b8 100644 --- a/packages/rtk-codemods/transformTestUtils.ts +++ b/packages/rtk-codemods/transformTestUtils.ts @@ -1,61 +1,68 @@ -import { describe, vi } from 'vitest'; -import type { Transform } from 'jscodeshift'; -import globby from 'globby'; -import fs from 'fs-extra'; -import path from 'path'; -import { runInlineTest } from 'jscodeshift/dist/testUtils'; +import { globbySync } from 'globby' +import type { Transform } from 'jscodeshift' +import type { TestOptions } from 'jscodeshift/src/testUtils' +import { runInlineTest } from 'jscodeshift/src/testUtils' +import fs from 'node:fs' +import path from 'node:path' +import { describe, it } from 'vitest' -export function runTransformTest( +export const runTransformTest = ( name: string, transform: Transform, - parser: string, + parser: TestOptions['parser'], fixturePath: string -) { - describe(name, function () { - globby - .sync('**/*.input.*', { - cwd: fixturePath, - absolute: true, - }) - .map((entry) => entry.slice(fixturePath.length)) +) => { + describe(name, () => { + globbySync('**/*.input.*', { + cwd: fixturePath, + absolute: true, + objectMode: true + }) + .map((entry) => entry.name) .forEach((filename) => { - let extension = path.extname(filename); - let testName = filename.replace(`.input${extension}`, ''); - let testInputPath = path.join(fixturePath, `${testName}${extension}`); - let inputPath = path.join(fixturePath, `${testName}.input${extension}`); - let outputPath = path.join(fixturePath, `${testName}.output${extension}`); - let optionsPath = path.join(fixturePath, `${testName}.options.json`); - let options = fs.pathExistsSync(optionsPath) ? fs.readFileSync(optionsPath) : '{}'; + const extension = path.extname(filename) + const testName = filename.replace(`.input${extension}`, '') + const testInputPath = path.join(fixturePath, `${testName}${extension}`) + const inputPath = path.join( + fixturePath, + `${testName}.input${extension}` + ) + const outputPath = path.join( + fixturePath, + `${testName}.output${extension}` + ) - describe(testName, function () { - beforeEach(function () { - process.env.CODEMOD_CLI_ARGS = options; - }); + const inputFileContent = fs.readFileSync(inputPath, 'utf8') - afterEach(function () { - process.env.CODEMOD_CLI_ARGS = ''; - }); + const expectedOutput = fs.readFileSync(outputPath, 'utf8') - it('transforms correctly', function () { + describe(`${testName}${extension}`, () => { + it('transforms correctly', () => { runInlineTest( transform, {}, - { path: testInputPath, source: fs.readFileSync(inputPath, 'utf8') }, - fs.readFileSync(outputPath, 'utf8'), + { + path: testInputPath, + source: inputFileContent + }, + expectedOutput, { parser } - ); - }); + ) + }) - it('is idempotent', function () { + it('is idempotent', () => { runInlineTest( transform, {}, - { path: testInputPath, source: fs.readFileSync(outputPath, 'utf8') }, - fs.readFileSync(outputPath, 'utf8'), + { + path: testInputPath, + source: inputFileContent + }, + expectedOutput, { parser } - ); - }); - }); - }); - }); + ) + }) + }) + }) + }) } diff --git a/packages/rtk-codemods/transforms/createReducerBuilder/README.md b/packages/rtk-codemods/transforms/createReducerBuilder/README.md index 52898146e9..1c91761f45 100644 --- a/packages/rtk-codemods/transforms/createReducerBuilder/README.md +++ b/packages/rtk-codemods/transforms/createReducerBuilder/README.md @@ -39,30 +39,36 @@ node ./bin/cli.js createReducerBuilder path/of/files/ or/some**/*glob.js createReducer(initialState, { [todoAdded]: (state: SliceState, action: PayloadAction) => { // stuff - }, -}); + } +}) createReducer(initialState, { [todoAdded](state: SliceState, action: PayloadAction) { // stuff - }, -}); + } +}) ``` **Output** ([basic-ts.output.ts](transforms\createReducerBuilder__testfixtures__\basic-ts.output.ts)): ```ts createReducer(initialState, (builder) => { - builder.addCase(todoAdded, (state: SliceState, action: PayloadAction) => { - // stuff - }); -}); + builder.addCase( + todoAdded, + (state: SliceState, action: PayloadAction) => { + // stuff + } + ) +}) createReducer(initialState, (builder) => { - builder.addCase(todoAdded, (state: SliceState, action: PayloadAction) => { - // stuff - }); -}); + builder.addCase( + todoAdded, + (state: SliceState, action: PayloadAction) => { + // stuff + } + ) +}) ``` --- @@ -88,8 +94,8 @@ createReducer(initialState, { }, todoAdded1f: (state, action) => { //stuff - }, -}); + } +}) createReducer(initialState, { [todoAdded2a]: (state, action) => { @@ -100,8 +106,8 @@ createReducer(initialState, { }, [todoAdded2c]: function (state, action) { // stuff - }, -}); + } +}) ``` **Output** ([basic.output.js](transforms\createReducerBuilder__testfixtures__\basic.output.js)): @@ -110,40 +116,40 @@ createReducer(initialState, { createReducer(initialState, (builder) => { builder.addCase(todoAdded1a, (state, action) => { // stuff - }); + }) - builder.addCase(todoAdded1b, (state, action) => action.payload); + builder.addCase(todoAdded1b, (state, action) => action.payload) builder.addCase(todoAdded1c + 'test', (state, action) => { // stuff - }); + }) builder.addCase(todoAdded1d, (state, action) => { // stuff - }); + }) builder.addCase(todoAdded1e, (state, action) => { // stuff - }); + }) builder.addCase(todoAdded1f, (state, action) => { //stuff - }); -}); + }) +}) createReducer(initialState, (builder) => { builder.addCase(todoAdded2a, (state, action) => { // stuff - }); + }) builder.addCase(todoAdded2b, (state, action) => { // stuff - }); + }) builder.addCase(todoAdded2c, (state, action) => { // stuff - }); -}); + }) +}) ``` diff --git a/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic-ts.input.ts b/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic-ts.input.ts index 9d0dd79709..57f0a84cbf 100644 --- a/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic-ts.input.ts +++ b/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic-ts.input.ts @@ -1,13 +1,60 @@ -createReducer(initialState, { - [todoAdded1a]: (state: SliceState, action: PayloadAction) => { +import type { PayloadAction } from '@reduxjs/toolkit' +import { createEntityAdapter, createReducer } from '@reduxjs/toolkit' + +export interface Todo { + id: string + title: string +} + +// This only included to make sure the codemod does not +// throw a runtime error when faced with TS 4.7+ syntax such as +// the `satisfies` operator and instantiation expressions +const someString = 'someString' satisfies string + +export const todoAdapter = createEntityAdapter() + +const todoInitialState = todoAdapter.getInitialState() + +export type TodoSliceState = typeof todoInitialState + +const { addOne } = todoAdapter + +createReducer(todoInitialState, { + [todoAdded1a]: (state: TodoSliceState, action: PayloadAction) => { + // stuff + }, + [todoAdded1b]: (state: TodoSliceState, action: PayloadAction) => + action.payload, + [todoAdded1c + 'test']: (state: TodoSliceState, action: PayloadAction) => { // stuff }, - [todoAdded1b]: someFunc, - todoAdded1c: adapter.someFunc, -}); + [todoAdded1d](state: TodoSliceState, action: PayloadAction) { + // stuff + }, + [todoAdded1e]: function ( + state: TodoSliceState, + action: PayloadAction + ) { + // stuff + }, + todoAdded1f: (state: TodoSliceState, action: PayloadAction) => { + //stuff + }, + [todoAdded1g]: addOne, + todoAdded1h: todoAdapter.addOne +}) -createReducer(initialState, { - [todoAdded](state: SliceState, action: PayloadAction) { +createReducer(todoInitialState, { + [todoAdded2a]: (state: TodoSliceState, action: PayloadAction) => { + // stuff + }, + [todoAdded2b](state: TodoSliceState, action: PayloadAction) { // stuff }, -}); + [todoAdded2c]: function ( + state: TodoSliceState, + action: PayloadAction + ) { + // stuff + } +}) diff --git a/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic-ts.output.ts b/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic-ts.output.ts index b0ed567675..a3d7af1089 100644 --- a/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic-ts.output.ts +++ b/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic-ts.output.ts @@ -1,14 +1,67 @@ -createReducer(initialState, (builder) => { - builder.addCase(todoAdded1a, (state: SliceState, action: PayloadAction) => { +import type { PayloadAction } from '@reduxjs/toolkit' +import { createEntityAdapter, createReducer } from '@reduxjs/toolkit' + +export interface Todo { + id: string + title: string +} + +// This only included to make sure the codemod does not +// throw a runtime error when faced with TS 4.7+ syntax such as +// the `satisfies` operator and instantiation expressions +const someString = 'someString' satisfies string + +export const todoAdapter = createEntityAdapter() + +const todoInitialState = todoAdapter.getInitialState() + +export type TodoSliceState = typeof todoInitialState + +const { addOne } = todoAdapter + +createReducer(todoInitialState, (builder) => { + builder.addCase(todoAdded1a, (state: TodoSliceState, action: PayloadAction) => { + // stuff + }); + + builder.addCase( + todoAdded1b, + (state: TodoSliceState, action: PayloadAction) => action.payload + ); + + builder.addCase( + todoAdded1c + 'test', + (state: TodoSliceState, action: PayloadAction) => { + // stuff + } + ); + + builder.addCase(todoAdded1d, (state: TodoSliceState, action: PayloadAction) => { // stuff }); - builder.addCase(todoAdded1b, someFunc); - builder.addCase(todoAdded1c, adapter.someFunc); -}); + builder.addCase(todoAdded1e, (state: TodoSliceState, action: PayloadAction) => { + // stuff + }); + + builder.addCase(todoAdded1f, (state: TodoSliceState, action: PayloadAction) => { + //stuff + }); + + builder.addCase(todoAdded1g, addOne); + builder.addCase(todoAdded1h, todoAdapter.addOne); +}) + +createReducer(todoInitialState, (builder) => { + builder.addCase(todoAdded2a, (state: TodoSliceState, action: PayloadAction) => { + // stuff + }); + + builder.addCase(todoAdded2b, (state: TodoSliceState, action: PayloadAction) => { + // stuff + }); -createReducer(initialState, (builder) => { - builder.addCase(todoAdded, (state: SliceState, action: PayloadAction) => { + builder.addCase(todoAdded2c, (state: TodoSliceState, action: PayloadAction) => { // stuff }); -}); +}) diff --git a/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic.input.js b/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic.input.js index 29587d92ad..05897a30f3 100644 --- a/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic.input.js +++ b/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic.input.js @@ -1,33 +1,40 @@ -createReducer(initialState, { - [todoAdded1a]: (state, action) => { - // stuff - }, - [todoAdded1b]: (state, action) => action.payload, - [todoAdded1c + "test"]: (state, action) => { - // stuff - }, - [todoAdded1d](state, action) { - // stuff - }, - [todoAdded1e]: function(state, action) { - // stuff - }, - todoAdded1f: (state, action) => { - //stuff - }, - [todoAdded1g]: someFunc, - todoAdded1h: adapter.someFunc -}); +import { createEntityAdapter, createReducer } from '@reduxjs/toolkit'; + +export const todoAdapter = createEntityAdapter(); + +const todoInitialState = todoAdapter.getInitialState(); +const { addOne } = todoAdapter; -createReducer(initialState, { - [todoAdded2a]: (state, action) => { - // stuff - }, - [todoAdded2b](state, action) { - // stuff - }, - [todoAdded2c]: function(state, action) { - // stuff - } -}); \ No newline at end of file +createReducer(todoInitialState, { + [todoAdded1a]: (state, action) => { + // stuff + }, + [todoAdded1b]: (state, action) => action.payload, + [todoAdded1c + 'test']: (state, action) => { + // stuff + }, + [todoAdded1d](state, action) { + // stuff + }, + [todoAdded1e]: function (state, action) { + // stuff + }, + todoAdded1f: (state, action) => { + //stuff + }, + [todoAdded1g]: addOne, + todoAdded1h: todoAdapter.addOne, +}); + +createReducer(todoInitialState, { + [todoAdded2a]: (state, action) => { + // stuff + }, + [todoAdded2b](state, action) { + // stuff + }, + [todoAdded2c]: function (state, action) { + // stuff + } +}); diff --git a/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic.output.js b/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic.output.js index 26f3abb98b..410186ab05 100644 --- a/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic.output.js +++ b/packages/rtk-codemods/transforms/createReducerBuilder/__testfixtures__/basic.output.js @@ -1,41 +1,48 @@ -createReducer(initialState, (builder) => { - builder.addCase(todoAdded1a, (state, action) => { - // stuff - }); +import { createEntityAdapter, createReducer } from '@reduxjs/toolkit'; - builder.addCase(todoAdded1b, (state, action) => action.payload); +export const todoAdapter = createEntityAdapter(); - builder.addCase(todoAdded1c + "test", (state, action) => { - // stuff - }); +const todoInitialState = todoAdapter.getInitialState(); - builder.addCase(todoAdded1d, (state, action) => { - // stuff - }); +const { addOne } = todoAdapter; - builder.addCase(todoAdded1e, (state, action) => { - // stuff - }); +createReducer(todoInitialState, (builder) => { + builder.addCase(todoAdded1a, (state, action) => { + // stuff + }); - builder.addCase(todoAdded1f, (state, action) => { - //stuff - }); + builder.addCase(todoAdded1b, (state, action) => action.payload); - builder.addCase(todoAdded1g, someFunc); - builder.addCase(todoAdded1h, adapter.someFunc); -}); + builder.addCase(todoAdded1c + 'test', (state, action) => { + // stuff + }); + + builder.addCase(todoAdded1d, (state, action) => { + // stuff + }); + + builder.addCase(todoAdded1e, (state, action) => { + // stuff + }); + builder.addCase(todoAdded1f, (state, action) => { + //stuff + }); -createReducer(initialState, (builder) => { - builder.addCase(todoAdded2a, (state, action) => { - // stuff - }); + builder.addCase(todoAdded1g, addOne); + builder.addCase(todoAdded1h, todoAdapter.addOne); +}); + +createReducer(todoInitialState, (builder) => { + builder.addCase(todoAdded2a, (state, action) => { + // stuff + }); - builder.addCase(todoAdded2b, (state, action) => { - // stuff - }); + builder.addCase(todoAdded2b, (state, action) => { + // stuff + }); - builder.addCase(todoAdded2c, (state, action) => { - // stuff - }); -}); \ No newline at end of file + builder.addCase(todoAdded2c, (state, action) => { + // stuff + }); +}); diff --git a/packages/rtk-codemods/transforms/createReducerBuilder/createReducerBuilder.test.ts b/packages/rtk-codemods/transforms/createReducerBuilder/createReducerBuilder.test.ts index 2f1ca8f24f..24678f709a 100644 --- a/packages/rtk-codemods/transforms/createReducerBuilder/createReducerBuilder.test.ts +++ b/packages/rtk-codemods/transforms/createReducerBuilder/createReducerBuilder.test.ts @@ -1,11 +1,10 @@ -import path from 'path'; -import transform, { parser } from './index'; - -import { runTransformTest } from '../../transformTestUtils'; +import path from 'node:path' +import { runTransformTest } from '../../transformTestUtils' +import transform, { parser } from './index' runTransformTest( 'createReducerBuilder', transform, parser, path.join(__dirname, '__testfixtures__') -); +) diff --git a/packages/rtk-codemods/transforms/createReducerBuilder/index.ts b/packages/rtk-codemods/transforms/createReducerBuilder/index.ts index 715c261bd8..7fbfcff005 100644 --- a/packages/rtk-codemods/transforms/createReducerBuilder/index.ts +++ b/packages/rtk-codemods/transforms/createReducerBuilder/index.ts @@ -1,93 +1,96 @@ -import { ExpressionKind, SpreadElementKind } from 'ast-types/gen/kinds'; -import { +import type { ExpressionKind, SpreadElementKind } from 'ast-types/gen/kinds' +import type { ExpressionStatement, JSCodeshift, ObjectExpression, - ObjectMethod, - ObjectProperty, - Transform, -} from 'jscodeshift'; - -type ObjectKey = ObjectMethod['key'] & ObjectProperty['key']; + Transform +} from 'jscodeshift' +import type { TestOptions } from 'jscodeshift/src/testUtils' function wrapInAddCaseExpression( j: JSCodeshift, addCaseArgs: (ExpressionKind | SpreadElementKind)[] ) { - const identifier = j.identifier('builder'); + const identifier = j.identifier('builder') return j.expressionStatement( - j.callExpression(j.memberExpression(identifier, j.identifier('addCase'), false), addCaseArgs) - ); + j.callExpression( + j.memberExpression(identifier, j.identifier('addCase'), false), + addCaseArgs + ) + ) } -export function reducerPropsToBuilderExpression(j: JSCodeshift, defNode: ObjectExpression) { - const caseExpressions: ExpressionStatement[] = []; - for (let property of defNode.properties) { - let addCaseArgs: (ExpressionKind | SpreadElementKind)[] = []; +export function reducerPropsToBuilderExpression( + j: JSCodeshift, + defNode: ObjectExpression +) { + const caseExpressions: ExpressionStatement[] = [] + for (const property of defNode.properties) { + let addCaseArgs: (ExpressionKind | SpreadElementKind)[] = [] switch (property.type) { case 'ObjectMethod': { - const { key, params, body } = property; + const { key, params, body } = property if (body) { - addCaseArgs = [key, j.arrowFunctionExpression(params, body)]; + addCaseArgs = [key, j.arrowFunctionExpression(params, body)] } - break; + break } case 'ObjectProperty': { - const { key } = property; + const { key } = property switch (property.value.type) { case 'ArrowFunctionExpression': case 'FunctionExpression': { - const { params, body } = property.value; + const { params, body } = property.value if (body) { - addCaseArgs = [key, j.arrowFunctionExpression(params, body)]; + addCaseArgs = [key, j.arrowFunctionExpression(params, body)] } - break; + break } case 'Identifier': case 'MemberExpression': { - const { value } = property; - addCaseArgs = [key, value]; - break; + const { value } = property + addCaseArgs = [key, value] + break } } } } if (!addCaseArgs.length) { - continue; + continue } - caseExpressions.push(wrapInAddCaseExpression(j, addCaseArgs)); + caseExpressions.push(wrapInAddCaseExpression(j, addCaseArgs)) } - return j.arrowFunctionExpression([j.identifier('builder')], j.blockStatement(caseExpressions)); + return j.arrowFunctionExpression( + [j.identifier('builder')], + j.blockStatement(caseExpressions) + ) } const transform: Transform = (file, api) => { - const j = api.jscodeshift; + const j = api.jscodeshift - return ( - j(file.source) - // @ts-ignore some expression mismatch - .find(j.CallExpression, { - callee: { name: 'createReducer' }, - // @ts-ignore some expression mismatch - arguments: { 1: { type: 'ObjectExpression' } }, - }) - .forEach((path) => { - const reducerObjectExpression = path.node.arguments[1] as ObjectExpression; - j(path).replaceWith( - j.callExpression(j.identifier('createReducer'), [ - path.node.arguments[0], - reducerPropsToBuilderExpression(j, reducerObjectExpression), - ]) - ); - }) - .toSource({ - arrowParensAlways: true, - }) - ); -}; + return j(file.source) + .find(j.CallExpression, { + callee: { name: 'createReducer' }, + arguments: [{}, { type: 'ObjectExpression' }] + }) + .forEach((path) => { + const reducerObjectExpression = path.node.arguments[1] as ObjectExpression + j(path).replaceWith( + j.callExpression(j.identifier('createReducer'), [ + path.node.arguments[0], + reducerPropsToBuilderExpression(j, reducerObjectExpression) + ]) + ) + }) + .toSource({ + arrowParensAlways: true, + lineTerminator: '\n' + }) +} -export const parser = 'tsx'; +export const parser = 'tsx' satisfies TestOptions['parser'] -export default transform; +export default transform diff --git a/packages/rtk-codemods/transforms/createSliceBuilder/README.md b/packages/rtk-codemods/transforms/createSliceBuilder/README.md index 5a15c86682..1db6f8f6de 100644 --- a/packages/rtk-codemods/transforms/createSliceBuilder/README.md +++ b/packages/rtk-codemods/transforms/createSliceBuilder/README.md @@ -42,9 +42,9 @@ const slice1 = createSlice({ extraReducers: { [todoAdded]: (state: SliceState, action: PayloadAction) => { // stuff - }, - }, -}); + } + } +}) const slice2 = createSlice({ name: 'b', @@ -52,9 +52,9 @@ const slice2 = createSlice({ extraReducers: { [todoAdded](state: SliceState, action: PayloadAction) { // stuff - }, - }, -}); + } + } +}) ``` **Output** ([basic-ts.output.ts](transforms\createSliceBuilder__testfixtures__\basic-ts.output.ts)): @@ -65,22 +65,28 @@ const slice1 = createSlice({ initialState, extraReducers: (builder) => { - builder.addCase(todoAdded, (state: SliceState, action: PayloadAction) => { - // stuff - }); - }, -}); + builder.addCase( + todoAdded, + (state: SliceState, action: PayloadAction) => { + // stuff + } + ) + } +}) const slice2 = createSlice({ name: 'b', initialState, extraReducers: (builder) => { - builder.addCase(todoAdded, (state: SliceState, action: PayloadAction) => { - // stuff - }); - }, -}); + builder.addCase( + todoAdded, + (state: SliceState, action: PayloadAction) => { + // stuff + } + ) + } +}) ``` --- @@ -109,9 +115,9 @@ const slice1 = createSlice({ }, todoAdded1f: (state, action) => { //stuff - }, - }, -}); + } + } +}) const slice2 = createSlice({ name: 'b', @@ -125,9 +131,9 @@ const slice2 = createSlice({ }, [todoAdded2c]: function (state, action) { // stuff - }, - }, -}); + } + } +}) ``` **Output** ([basic.output.js](transforms\createSliceBuilder__testfixtures__\basic.output.js)): @@ -140,27 +146,27 @@ const slice1 = createSlice({ extraReducers: (builder) => { builder.addCase(todoAdded1a, (state, action) => { // stuff - }); + }) - builder.addCase(todoAdded1b, (state, action) => action.payload); + builder.addCase(todoAdded1b, (state, action) => action.payload) builder.addCase(todoAdded1c + 'test', (state, action) => { // stuff - }); + }) builder.addCase(todoAdded1d, (state, action) => { // stuff - }); + }) builder.addCase(todoAdded1e, (state, action) => { // stuff - }); + }) builder.addCase(todoAdded1f, (state, action) => { //stuff - }); - }, -}); + }) + } +}) const slice2 = createSlice({ name: 'b', @@ -169,17 +175,17 @@ const slice2 = createSlice({ extraReducers: (builder) => { builder.addCase(todoAdded2a, (state, action) => { // stuff - }); + }) builder.addCase(todoAdded2b, (state, action) => { // stuff - }); + }) builder.addCase(todoAdded2c, (state, action) => { // stuff - }); - }, -}); + }) + } +}) ``` diff --git a/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic-ts.input.ts b/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic-ts.input.ts index 9539371a75..600b625912 100644 --- a/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic-ts.input.ts +++ b/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic-ts.input.ts @@ -1,21 +1,97 @@ -const slice1 = createSlice({ - name: "a", - initialState, +import type { PayloadAction } from '@reduxjs/toolkit'; +import { + createAsyncThunk, + createEntityAdapter, + createSlice +} from '@reduxjs/toolkit'; + +export interface Todo { + id: string + title: string +} + +export const todoAdapter = createEntityAdapter() + +const todoInitialState = todoAdapter.getInitialState() + +export type TodoSliceState = typeof todoInitialState + +const fetchCount = (amount = 1) => { + return new Promise<{ data: number }>((resolve) => + setTimeout(() => resolve({ data: amount }), 500) + ) +} + +export const incrementAsync = createAsyncThunk( + 'counter/fetchCount', + async (amount: number) => { + const response = await fetchCount(amount) + return response.data + } +) + +const { addOne } = todoAdapter + +const todoSlice = createSlice({ + name: 'todo', + initialState: todoInitialState, + reducers: { + deleteTodo: todoAdapter.removeOne + }, extraReducers: { - [todoAdded1a]: (state: SliceState, action: PayloadAction) => { + [incrementAsync.pending]: ( + state: TodoSliceState, + action: PayloadAction + ) => { + // stuff + }, + [incrementAsync.rejected]: todoAdapter.removeAll, + [incrementAsync.fulfilled]( + state: TodoSliceState, + action: PayloadAction) { // stuff }, - [todoAdded1b]: someFunc, - todoAdded1c: adapter.someFunc, + todoAdded: todoAdapter.addOne, + + [todoAdded1a]: (state: TodoSliceState, action: PayloadAction) => { + // stuff + }, + [todoAdded1b]: (state: TodoSliceState, action: PayloadAction) => action.payload, + [todoAdded1c + 'test']: (state:TodoSliceState, action: PayloadAction) => { + // stuff + }, + [todoAdded1d](state: TodoSliceState, action: PayloadAction) { + // stuff + }, + [todoAdded1e]: function(state: TodoSliceState, action: PayloadAction) { + // stuff + }, + todoAdded1f: (state: TodoSliceState, action: PayloadAction) => { + //stuff + }, + [todoAdded1g]: addOne, + todoAdded1h: todoAdapter.addOne, } -}); +}) + +export const { deleteTodo } = todoSlice.actions -const slice2 = createSlice({ - name: "b", - initialState, +export interface CounterSliceState { + value: number + status: 'idle' | 'loading' | 'failed' +} + +const counterInitialState: CounterSliceState = { + value: 0, + status: 'idle' +} + +const counterSlice = createSlice({ + name: 'counter', + initialState: counterInitialState, extraReducers: { - [todoAdded](state: SliceState, action: PayloadAction) { + [deleteTodo](state: CounterSliceState, action: PayloadAction) { // stuff - }, + } } -}); +}) diff --git a/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic-ts.output.ts b/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic-ts.output.ts index 815db50bff..de45f86075 100644 --- a/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic-ts.output.ts +++ b/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic-ts.output.ts @@ -1,24 +1,116 @@ -const slice1 = createSlice({ - name: "a", - initialState, +import type { PayloadAction } from '@reduxjs/toolkit'; +import { + createAsyncThunk, + createEntityAdapter, + createSlice +} from '@reduxjs/toolkit'; + +export interface Todo { + id: string + title: string +} + +export const todoAdapter = createEntityAdapter() + +const todoInitialState = todoAdapter.getInitialState() + +export type TodoSliceState = typeof todoInitialState + +const fetchCount = (amount = 1) => { + return new Promise<{ data: number }>((resolve) => + setTimeout(() => resolve({ data: amount }), 500) + ) +} + +export const incrementAsync = createAsyncThunk( + 'counter/fetchCount', + async (amount: number) => { + const response = await fetchCount(amount) + return response.data + } +) + +const { addOne } = todoAdapter + +const todoSlice = createSlice({ + name: 'todo', + initialState: todoInitialState, + + reducers: { + deleteTodo: todoAdapter.removeOne + }, extraReducers: (builder) => { - builder.addCase(todoAdded1a, (state: SliceState, action: PayloadAction) => { + builder.addCase( + incrementAsync.pending, + (state: TodoSliceState, action: PayloadAction) => { + // stuff + } + ); + + builder.addCase(incrementAsync.rejected, todoAdapter.removeAll); + + builder.addCase( + incrementAsync.fulfilled, + (state: TodoSliceState, action: PayloadAction) => { + // stuff + } + ); + + builder.addCase(todoAdded, todoAdapter.addOne); + + builder.addCase(todoAdded1a, (state: TodoSliceState, action: PayloadAction) => { // stuff }); - builder.addCase(todoAdded1b, someFunc); - builder.addCase(todoAdded1c, adapter.someFunc); + builder.addCase( + todoAdded1b, + (state: TodoSliceState, action: PayloadAction) => action.payload + ); + + builder.addCase( + todoAdded1c + 'test', + (state:TodoSliceState, action: PayloadAction) => { + // stuff + } + ); + + builder.addCase(todoAdded1d, (state: TodoSliceState, action: PayloadAction) => { + // stuff + }); + + builder.addCase(todoAdded1e, (state: TodoSliceState, action: PayloadAction) => { + // stuff + }); + + builder.addCase(todoAdded1f, (state: TodoSliceState, action: PayloadAction) => { + //stuff + }); + + builder.addCase(todoAdded1g, addOne); + builder.addCase(todoAdded1h, todoAdapter.addOne); } -}); +}) + +export const { deleteTodo } = todoSlice.actions + +export interface CounterSliceState { + value: number + status: 'idle' | 'loading' | 'failed' +} + +const counterInitialState: CounterSliceState = { + value: 0, + status: 'idle' +} -const slice2 = createSlice({ - name: "b", - initialState, +const counterSlice = createSlice({ + name: 'counter', + initialState: counterInitialState, extraReducers: (builder) => { - builder.addCase(todoAdded, (state: SliceState, action: PayloadAction) => { + builder.addCase(deleteTodo, (state: CounterSliceState, action: PayloadAction) => { // stuff }); } -}); +}) diff --git a/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic.input.js b/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic.input.js index 23d29e537c..65a12ca914 100644 --- a/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic.input.js +++ b/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic.input.js @@ -1,41 +1,70 @@ -const slice1 = createSlice({ - name: "a", - initialState: {}, - extraReducers: { - [todoAdded1a]: (state, action) => { - // stuff - }, - [todoAdded1b]: (state, action) => action.payload, - [todoAdded1c + "test"]: (state, action) => { - // stuff - }, - [todoAdded1d](state, action) { - // stuff - }, - [todoAdded1e]: function(state, action) { - // stuff - }, - todoAdded1f: (state, action) => { - //stuff - }, - [todoAdded1g]: someFunc, - todoAdded1h: adapter.someFunc - } +import { createAsyncThunk, createEntityAdapter, createSlice } from '@reduxjs/toolkit'; + +export const todoAdapter = createEntityAdapter(); + +const todoInitialState = todoAdapter.getInitialState(); + +const fetchCount = (amount = 1) => { + return new Promise((resolve) => setTimeout(() => resolve({ data: amount }), 500)); +}; + +export const incrementAsync = createAsyncThunk('counter/fetchCount', async (amount) => { + const response = await fetchCount(amount); + return response.data; }); +const { addOne } = todoAdapter; -const slice2 = createSlice({ - name: "b", - initialState: {}, - extraReducers: { - [todoAdded2a]: (state, action) => { - // stuff +const todoSlice = createSlice({ + name: 'todo', + initialState: todoInitialState, + reducers: { + deleteTodo: todoAdapter.removeOne }, - [todoAdded2b](state, action) { - // stuff - }, - [todoAdded2c]: function(state, action) { - // stuff + extraReducers: { + [incrementAsync.pending]: (state, action) => { + // stuff + }, + [incrementAsync.rejected]: todoAdapter.removeAll, + [incrementAsync.fulfilled](state, action) { + // stuff + }, + todoAdded: todoAdapter.addOne, + + [todoAdded1a]: (state, action) => { + // stuff + }, + [todoAdded1b]: (state, action) => action.payload, + [todoAdded1c + 'test']: (state, action) => { + // stuff + }, + [todoAdded1d](state, action) { + // stuff + }, + [todoAdded1e]: function (state, action) { + // stuff + }, + todoAdded1f: (state, action) => { + //stuff + }, + [todoAdded1g]: addOne, + todoAdded1h: todoAdapter.addOne, + } +}); + +export const { deleteTodo } = todoSlice.actions; + +const counterInitialState = { + value: 0, + status: 'idle' +}; + +const counterSlice = createSlice({ + name: 'counter', + initialState: counterInitialState, + extraReducers: { + [deleteTodo](state, action) { + // stuff + } } - } -}); \ No newline at end of file +}); diff --git a/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic.output.js b/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic.output.js index 00aef88efa..f1adcf7169 100644 --- a/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic.output.js +++ b/packages/rtk-codemods/transforms/createSliceBuilder/__testfixtures__/basic.output.js @@ -1,51 +1,82 @@ -const slice1 = createSlice({ - name: "a", - initialState: {}, +import { createAsyncThunk, createEntityAdapter, createSlice } from '@reduxjs/toolkit'; - extraReducers: (builder) => { - builder.addCase(todoAdded1a, (state, action) => { - // stuff - }); +export const todoAdapter = createEntityAdapter(); - builder.addCase(todoAdded1b, (state, action) => action.payload); +const todoInitialState = todoAdapter.getInitialState(); - builder.addCase(todoAdded1c + "test", (state, action) => { - // stuff - }); +const fetchCount = (amount = 1) => { + return new Promise((resolve) => setTimeout(() => resolve({ data: amount }), 500)); +}; - builder.addCase(todoAdded1d, (state, action) => { - // stuff - }); +export const incrementAsync = createAsyncThunk('counter/fetchCount', async (amount) => { + const response = await fetchCount(amount); + return response.data; +}); - builder.addCase(todoAdded1e, (state, action) => { - // stuff - }); +const { addOne } = todoAdapter; - builder.addCase(todoAdded1f, (state, action) => { - //stuff - }); +const todoSlice = createSlice({ + name: 'todo', + initialState: todoInitialState, - builder.addCase(todoAdded1g, someFunc); - builder.addCase(todoAdded1h, adapter.someFunc); - } -}); + reducers: { + deleteTodo: todoAdapter.removeOne + }, + + extraReducers: (builder) => { + builder.addCase(incrementAsync.pending, (state, action) => { + // stuff + }); + + builder.addCase(incrementAsync.rejected, todoAdapter.removeAll); + + builder.addCase(incrementAsync.fulfilled, (state, action) => { + // stuff + }); + + builder.addCase(todoAdded, todoAdapter.addOne); + + builder.addCase(todoAdded1a, (state, action) => { + // stuff + }); + builder.addCase(todoAdded1b, (state, action) => action.payload); -const slice2 = createSlice({ - name: "b", - initialState: {}, + builder.addCase(todoAdded1c + 'test', (state, action) => { + // stuff + }); - extraReducers: (builder) => { - builder.addCase(todoAdded2a, (state, action) => { - // stuff - }); + builder.addCase(todoAdded1d, (state, action) => { + // stuff + }); - builder.addCase(todoAdded2b, (state, action) => { - // stuff - }); + builder.addCase(todoAdded1e, (state, action) => { + // stuff + }); - builder.addCase(todoAdded2c, (state, action) => { - // stuff - }); - } -}); \ No newline at end of file + builder.addCase(todoAdded1f, (state, action) => { + //stuff + }); + + builder.addCase(todoAdded1g, addOne); + builder.addCase(todoAdded1h, todoAdapter.addOne); + } +}); + +export const { deleteTodo } = todoSlice.actions; + +const counterInitialState = { + value: 0, + status: 'idle' +}; + +const counterSlice = createSlice({ + name: 'counter', + initialState: counterInitialState, + + extraReducers: (builder) => { + builder.addCase(deleteTodo, (state, action) => { + // stuff + }); + } +}); diff --git a/packages/rtk-codemods/transforms/createSliceBuilder/createSliceBuilder.test.ts b/packages/rtk-codemods/transforms/createSliceBuilder/createSliceBuilder.test.ts index 348bc3d4c9..c2164bffe5 100644 --- a/packages/rtk-codemods/transforms/createSliceBuilder/createSliceBuilder.test.ts +++ b/packages/rtk-codemods/transforms/createSliceBuilder/createSliceBuilder.test.ts @@ -1,6 +1,10 @@ -import path from 'path'; -import transform, { parser } from './index'; +import path from 'node:path' +import { runTransformTest } from '../../transformTestUtils' +import transform, { parser } from './index' -import { runTransformTest } from '../../transformTestUtils'; - -runTransformTest('createSliceBuilder', transform, parser, path.join(__dirname, '__testfixtures__')); +runTransformTest( + 'createSliceBuilder', + transform, + parser, + path.join(__dirname, '__testfixtures__') +) diff --git a/packages/rtk-codemods/transforms/createSliceBuilder/index.ts b/packages/rtk-codemods/transforms/createSliceBuilder/index.ts index 95d89337b8..80856876b5 100644 --- a/packages/rtk-codemods/transforms/createSliceBuilder/index.ts +++ b/packages/rtk-codemods/transforms/createSliceBuilder/index.ts @@ -1,119 +1,122 @@ -import { ExpressionKind, SpreadElementKind } from 'ast-types/gen/kinds'; -import { +import type { ExpressionKind, SpreadElementKind } from 'ast-types/gen/kinds' +import type { ExpressionStatement, JSCodeshift, ObjectExpression, - ObjectMethod, - ObjectProperty, - Transform, -} from 'jscodeshift'; - -type ObjectKey = ObjectMethod['key'] & ObjectProperty['key']; + Transform +} from 'jscodeshift' +import type { TestOptions } from 'jscodeshift/src/testUtils' function wrapInAddCaseExpression( j: JSCodeshift, addCaseArgs: (ExpressionKind | SpreadElementKind)[] ) { - const identifier = j.identifier('builder'); + const identifier = j.identifier('builder') return j.expressionStatement( - j.callExpression(j.memberExpression(identifier, j.identifier('addCase'), false), addCaseArgs) - ); + j.callExpression( + j.memberExpression(identifier, j.identifier('addCase'), false), + addCaseArgs + ) + ) } -export function reducerPropsToBuilderExpression(j: JSCodeshift, defNode: ObjectExpression) { - const caseExpressions: ExpressionStatement[] = []; - for (let property of defNode.properties) { - let addCaseArgs: (ExpressionKind | SpreadElementKind)[] = []; +export function reducerPropsToBuilderExpression( + j: JSCodeshift, + defNode: ObjectExpression +) { + const caseExpressions: ExpressionStatement[] = [] + for (const property of defNode.properties) { + let addCaseArgs: (ExpressionKind | SpreadElementKind)[] = [] switch (property.type) { case 'ObjectMethod': { - const { key, params, body } = property; + const { key, params, body } = property if (body) { - addCaseArgs = [key, j.arrowFunctionExpression(params, body)]; + addCaseArgs = [key, j.arrowFunctionExpression(params, body)] } - break; + break } - case 'ObjectProperty': { - const { key } = property; + case 'ObjectProperty': { + const { key } = property switch (property.value.type) { case 'ArrowFunctionExpression': case 'FunctionExpression': { - const { params, body } = property.value; + const { params, body } = property.value if (body) { - addCaseArgs = [key, j.arrowFunctionExpression(params, body)]; + addCaseArgs = [key, j.arrowFunctionExpression(params, body)] } - break; + break } case 'Identifier': case 'MemberExpression': { - const { value } = property; - addCaseArgs = [key, value]; - break; + const { value } = property + addCaseArgs = [key, value] + break } } } } if (!addCaseArgs.length) { - continue; + continue } - caseExpressions.push(wrapInAddCaseExpression(j, addCaseArgs)); + caseExpressions.push(wrapInAddCaseExpression(j, addCaseArgs)) } - return j.arrowFunctionExpression([j.identifier('builder')], j.blockStatement(caseExpressions)); + return j.arrowFunctionExpression( + [j.identifier('builder')], + j.blockStatement(caseExpressions) + ) } const transform: Transform = (file, api) => { - const j = api.jscodeshift; + const j = api.jscodeshift - return ( - j(file.source) - // @ts-ignore some expression mismatch - .find(j.CallExpression, { - callee: { name: 'createSlice' }, - // @ts-ignore some expression mismatch - arguments: { 0: { type: 'ObjectExpression' } }, - }) + return j(file.source) + .find(j.CallExpression, { + callee: { name: 'createSlice' }, + arguments: [{ type: 'ObjectExpression' }] + }) - .filter((path) => { - const createSliceArgsObject = path.node.arguments[0] as ObjectExpression; - return createSliceArgsObject.properties.some( - (p) => - p.type === 'ObjectProperty' && - p.key.type === 'Identifier' && - p.key.name === 'extraReducers' && - p.value.type === 'ObjectExpression' - ); - }) - .forEach((path) => { - const createSliceArgsObject = path.node.arguments[0] as ObjectExpression; - j(path).replaceWith( - j.callExpression(j.identifier('createSlice'), [ - j.objectExpression( - createSliceArgsObject.properties.map((p) => { - if ( - p.type === 'ObjectProperty' && - p.key.type === 'Identifier' && - p.key.name === 'extraReducers' && - p.value.type === 'ObjectExpression' - ) { - const expressionStatement = reducerPropsToBuilderExpression( - j, - p.value as ObjectExpression - ); - return j.objectProperty(p.key, expressionStatement); - } - return p; - }) - ), - ]) - ); - }) - .toSource({ - arrowParensAlways: true, - }) - ); -}; + .filter((path) => { + const createSliceArgsObject = path.node.arguments[0] as ObjectExpression + return createSliceArgsObject.properties.some( + (p) => + p.type === 'ObjectProperty' && + p.key.type === 'Identifier' && + p.key.name === 'extraReducers' && + p.value.type === 'ObjectExpression' + ) + }) + .forEach((path) => { + const createSliceArgsObject = path.node.arguments[0] as ObjectExpression + j(path).replaceWith( + j.callExpression(j.identifier('createSlice'), [ + j.objectExpression( + createSliceArgsObject.properties.map((p) => { + if ( + p.type === 'ObjectProperty' && + p.key.type === 'Identifier' && + p.key.name === 'extraReducers' && + p.value.type === 'ObjectExpression' + ) { + const expressionStatement = reducerPropsToBuilderExpression( + j, + p.value as ObjectExpression + ) + return j.objectProperty(p.key, expressionStatement) + } + return p + }) + ) + ]) + ) + }) + .toSource({ + arrowParensAlways: true, + lineTerminator: '\n' + }) +} -export const parser = 'tsx'; +export const parser = 'tsx' satisfies TestOptions['parser'] -export default transform; +export default transform diff --git a/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic-ts.input.ts b/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic-ts.input.ts index 80614bfb8c..cdc3430fe8 100644 --- a/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic-ts.input.ts +++ b/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic-ts.input.ts @@ -1,27 +1,43 @@ -const aSlice = createSlice({ - name: 'name', +import type { PayloadAction } from '@reduxjs/toolkit' +import { createEntityAdapter, createSlice, nanoid } from '@reduxjs/toolkit' + +function withPayload(): any { + throw new Error('Function not implemented.') +} + +export interface Todo { + id: string + title: string +} + +export const todoAdapter = createEntityAdapter() + +const todoSlice = createSlice({ + name: 'todo', initialState: todoAdapter.getInitialState(), reducers: { property: () => {}, method(state, action: PayloadAction) { - todoAdapter.addOne(state, action); + todoAdapter.addOne(state, action) }, identifier: todoAdapter.removeOne, preparedProperty: { - prepare: (todo: Todo) => ({ payload: { id: nanoid(), ...todo } }), + prepare: (todo: Omit) => ({ + payload: { id: nanoid(), ...todo } + }), reducer: () => {} }, preparedMethod: { - prepare(todo: Todo) { + prepare(todo: Omit) { return { payload: { id: nanoid(), ...todo } } }, reducer(state, action: PayloadAction) { - todoAdapter.addOne(state, action); + todoAdapter.addOne(state, action) } }, preparedIdentifier: { prepare: withPayload(), reducer: todoAdapter.setMany - }, + } } }) \ No newline at end of file diff --git a/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic-ts.output.ts b/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic-ts.output.ts index b84f139846..47bcf1d400 100644 --- a/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic-ts.output.ts +++ b/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic-ts.output.ts @@ -1,21 +1,38 @@ -const aSlice = createSlice({ - name: 'name', +import type { PayloadAction } from '@reduxjs/toolkit' +import { createEntityAdapter, createSlice, nanoid } from '@reduxjs/toolkit' + +function withPayload(): any { + throw new Error('Function not implemented.') +} + +export interface Todo { + id: string + title: string +} + +export const todoAdapter = createEntityAdapter() + +const todoSlice = createSlice({ + name: 'todo', initialState: todoAdapter.getInitialState(), reducers: (create) => ({ property: create.reducer(() => {}), method: create.reducer((state, action: PayloadAction) => { - todoAdapter.addOne(state, action); + todoAdapter.addOne(state, action) }), identifier: create.reducer(todoAdapter.removeOne), - preparedProperty: create.preparedReducer((todo: Todo) => ({ payload: { id: nanoid(), ...todo } }), () => {}), - preparedMethod: create.preparedReducer((todo: Todo) => { + preparedProperty: create.preparedReducer((todo: Omit) => ({ + payload: { id: nanoid(), ...todo } + }), () => {}), + + preparedMethod: create.preparedReducer((todo: Omit) => { return { payload: { id: nanoid(), ...todo } } }, (state, action: PayloadAction) => { - todoAdapter.addOne(state, action); + todoAdapter.addOne(state, action) }), preparedIdentifier: create.preparedReducer(withPayload(), todoAdapter.setMany) diff --git a/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic.input.js b/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic.input.js index 2319c0e9f3..4ea917d5b3 100644 --- a/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic.input.js +++ b/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic.input.js @@ -1,27 +1,37 @@ -const aSlice = createSlice({ - name: 'name', - initialState: todoAdapter.getInitialState(), - reducers: { - property: () => {}, - method(state, action) { - todoAdapter.setMany(state, action); - }, - identifier: todoAdapter.removeOne, - preparedProperty: { - prepare: (todo) => ({ payload: { id: nanoid(), ...todo } }), - reducer: () => {} - }, - preparedMethod: { - prepare(todo) { - return { payload: { id: nanoid(), ...todo } } - }, - reducer(state, action) { - todoAdapter.setMany(state, action); - } - }, - preparedIdentifier: { - prepare: withPayload(), - reducer: todoAdapter.setMany - }, - } -}) \ No newline at end of file +import { createEntityAdapter, createSlice, nanoid } from '@reduxjs/toolkit' + +function withPayload() { + throw new Error('Function not implemented.') +} + +export const todoAdapter = createEntityAdapter() + +const todoSlice = createSlice({ + name: 'todo', + initialState: todoAdapter.getInitialState(), + reducers: { + property: () => { }, + method(state, action) { + todoAdapter.addOne(state, action) + }, + identifier: todoAdapter.removeOne, + preparedProperty: { + prepare: (todo) => ({ + payload: { id: nanoid(), ...todo } + }), + reducer: () => { } + }, + preparedMethod: { + prepare(todo) { + return { payload: { id: nanoid(), ...todo } } + }, + reducer(state, action) { + todoAdapter.addOne(state, action) + } + }, + preparedIdentifier: { + prepare: withPayload(), + reducer: todoAdapter.setMany + } + } +}) diff --git a/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic.output.js b/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic.output.js index 24d6672386..3c527b7e21 100644 --- a/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic.output.js +++ b/packages/rtk-codemods/transforms/createSliceReducerBuilder/__testfixtures__/basic.output.js @@ -1,23 +1,34 @@ -const aSlice = createSlice({ - name: 'name', - initialState: todoAdapter.getInitialState(), +import { createEntityAdapter, createSlice, nanoid } from '@reduxjs/toolkit' - reducers: (create) => ({ - property: create.reducer(() => {}), +function withPayload() { + throw new Error('Function not implemented.') +} - method: create.reducer((state, action) => { - todoAdapter.setMany(state, action); - }), +export const todoAdapter = createEntityAdapter() - identifier: create.reducer(todoAdapter.removeOne), - preparedProperty: create.preparedReducer((todo) => ({ payload: { id: nanoid(), ...todo } }), () => {}), +const todoSlice = createSlice({ + name: 'todo', + initialState: todoAdapter.getInitialState(), - preparedMethod: create.preparedReducer((todo) => { - return { payload: { id: nanoid(), ...todo } } - }, (state, action) => { - todoAdapter.setMany(state, action); - }), + reducers: (create) => ({ + property: create.reducer(() => { }), - preparedIdentifier: create.preparedReducer(withPayload(), todoAdapter.setMany) - }) -}) \ No newline at end of file + method: create.reducer((state, action) => { + todoAdapter.addOne(state, action) + }), + + identifier: create.reducer(todoAdapter.removeOne), + + preparedProperty: create.preparedReducer((todo) => ({ + payload: { id: nanoid(), ...todo } + }), () => { }), + + preparedMethod: create.preparedReducer((todo) => { + return { payload: { id: nanoid(), ...todo } } + }, (state, action) => { + todoAdapter.addOne(state, action) + }), + + preparedIdentifier: create.preparedReducer(withPayload(), todoAdapter.setMany) + }) +}) diff --git a/packages/rtk-codemods/transforms/createSliceReducerBuilder/createSliceReducerBuilder.test.ts b/packages/rtk-codemods/transforms/createSliceReducerBuilder/createSliceReducerBuilder.test.ts index b283f1d97c..2b905aa0cc 100644 --- a/packages/rtk-codemods/transforms/createSliceReducerBuilder/createSliceReducerBuilder.test.ts +++ b/packages/rtk-codemods/transforms/createSliceReducerBuilder/createSliceReducerBuilder.test.ts @@ -1,11 +1,10 @@ -import path from 'path'; -import transform, { parser } from './index'; - -import { runTransformTest } from '../../transformTestUtils'; +import path from 'node:path' +import { runTransformTest } from '../../transformTestUtils' +import transform, { parser } from './index' runTransformTest( 'createSliceReducerBuilder', transform, parser, path.join(__dirname, '__testfixtures__') -); +) diff --git a/packages/rtk-codemods/transforms/createSliceReducerBuilder/index.ts b/packages/rtk-codemods/transforms/createSliceReducerBuilder/index.ts index 549a50e3da..e168b08eee 100644 --- a/packages/rtk-codemods/transforms/createSliceReducerBuilder/index.ts +++ b/packages/rtk-codemods/transforms/createSliceReducerBuilder/index.ts @@ -1,67 +1,70 @@ -/* eslint-disable node/no-extraneous-import */ -/* eslint-disable node/no-unsupported-features/es-syntax */ -import type { ExpressionKind, SpreadElementKind } from 'ast-types/gen/kinds'; +import type { ExpressionKind } from 'ast-types/gen/kinds' import type { - CallExpression, JSCodeshift, ObjectExpression, ObjectProperty, - Transform, -} from 'jscodeshift'; + Transform +} from 'jscodeshift' +import type { TestOptions } from 'jscodeshift/src/testUtils' -function creatorCall(j: JSCodeshift, type: 'reducer', reducer: ExpressionKind): CallExpression; -// eslint-disable-next-line no-redeclare -function creatorCall( - j: JSCodeshift, - type: 'preparedReducer', - prepare: ExpressionKind, - reducer: ExpressionKind -): CallExpression; -// eslint-disable-next-line no-redeclare -function creatorCall( - j: JSCodeshift, - type: 'reducer' | 'preparedReducer', - ...rest: Array -) { - return j.callExpression(j.memberExpression(j.identifier('create'), j.identifier(type)), rest); +type CreatorCallRestArguments = + | [type: 'reducer', reducer: ExpressionKind] + | [type: 'preparedReducer', prepare: ExpressionKind, reducer: ExpressionKind] + +function creatorCall(j: JSCodeshift, ...rest: CreatorCallRestArguments) { + const [type, ...restArgs] = rest + + return j.callExpression( + j.memberExpression(j.identifier('create'), j.identifier(type)), + restArgs + ) } -export function reducerPropsToBuilderExpression(j: JSCodeshift, defNode: ObjectExpression) { - const returnedObject = j.objectExpression([]); - for (let property of defNode.properties) { - let finalProp: ObjectProperty | undefined; +export function reducerPropsToBuilderExpression( + j: JSCodeshift, + defNode: ObjectExpression +) { + const returnedObject = j.objectExpression([]) + for (const property of defNode.properties) { + let finalProp: ObjectProperty | undefined switch (property.type) { case 'ObjectMethod': { - const { key, params, body } = property; + const { key, params, body } = property finalProp = j.objectProperty( key, creatorCall(j, 'reducer', j.arrowFunctionExpression(params, body)) - ); - break; + ) + break } case 'ObjectProperty': { - const { key } = property; + const { key } = property switch (property.value.type) { case 'ObjectExpression': { - let preparedReducerParams: { prepare?: ExpressionKind; reducer?: ExpressionKind } = {}; + const preparedReducerParams: { + prepare?: ExpressionKind + reducer?: ExpressionKind + } = {} for (const objProp of property.value.properties) { switch (objProp.type) { case 'ObjectMethod': { - const { key, params, body } = objProp; + const { key, params, body } = objProp if ( key.type === 'Identifier' && (key.name === 'reducer' || key.name === 'prepare') ) { - preparedReducerParams[key.name] = j.arrowFunctionExpression(params, body); + preparedReducerParams[key.name] = j.arrowFunctionExpression( + params, + body + ) } - break; + break } case 'ObjectProperty': { - const { key, value } = objProp; + const { key, value } = objProp - let finalExpression: ExpressionKind | undefined = undefined; + let finalExpression: ExpressionKind | undefined = undefined switch (value.type) { case 'ArrowFunctionExpression': @@ -69,7 +72,7 @@ export function reducerPropsToBuilderExpression(j: JSCodeshift, defNode: ObjectE case 'Identifier': case 'MemberExpression': case 'CallExpression': { - finalExpression = value; + finalExpression = value } } @@ -78,14 +81,17 @@ export function reducerPropsToBuilderExpression(j: JSCodeshift, defNode: ObjectE (key.name === 'reducer' || key.name === 'prepare') && finalExpression ) { - preparedReducerParams[key.name] = finalExpression; + preparedReducerParams[key.name] = finalExpression } - break; + break } } } - if (preparedReducerParams.prepare && preparedReducerParams.reducer) { + if ( + preparedReducerParams.prepare && + preparedReducerParams.reducer + ) { finalProp = j.objectProperty( key, creatorCall( @@ -94,86 +100,90 @@ export function reducerPropsToBuilderExpression(j: JSCodeshift, defNode: ObjectE preparedReducerParams.prepare, preparedReducerParams.reducer ) - ); + ) } else if (preparedReducerParams.reducer) { finalProp = j.objectProperty( key, creatorCall(j, 'reducer', preparedReducerParams.reducer) - ); + ) } - break; + break } case 'ArrowFunctionExpression': case 'FunctionExpression': case 'Identifier': case 'MemberExpression': case 'CallExpression': { - const { value } = property; - finalProp = j.objectProperty(key, creatorCall(j, 'reducer', value)); - break; + const { value } = property + finalProp = j.objectProperty(key, creatorCall(j, 'reducer', value)) + break } } - break; + break } } if (!finalProp) { - continue; + continue } - returnedObject.properties.push(finalProp); + returnedObject.properties.push(finalProp) } - return j.arrowFunctionExpression([j.identifier('create')], returnedObject, true); + return j.arrowFunctionExpression( + [j.identifier('create')], + returnedObject, + true + ) } const transform: Transform = (file, api) => { - const j = api.jscodeshift; - - return ( - j(file.source) - // @ts-ignore some expression mismatch - .find(j.CallExpression, { - callee: { name: 'createSlice' }, - // @ts-ignore some expression mismatch - arguments: { 0: { type: 'ObjectExpression' } }, - }) - - .filter((path) => { - const createSliceArgsObject = path.node.arguments[0] as ObjectExpression; - return createSliceArgsObject.properties.some( - (p) => - p.type === 'ObjectProperty' && - p.key.type === 'Identifier' && - p.key.name === 'reducers' && - p.value.type === 'ObjectExpression' - ); - }) - .forEach((path) => { - const createSliceArgsObject = path.node.arguments[0] as ObjectExpression; - j(path).replaceWith( - j.callExpression(j.identifier('createSlice'), [ - j.objectExpression( - createSliceArgsObject.properties.map((p) => { - if ( - p.type === 'ObjectProperty' && - p.key.type === 'Identifier' && - p.key.name === 'reducers' && - p.value.type === 'ObjectExpression' - ) { - const expressionStatement = reducerPropsToBuilderExpression(j, p.value); - return j.objectProperty(p.key, expressionStatement); - } - return p; - }) - ), - ]) - ); - }) - .toSource({ - arrowParensAlways: true, - }) - ); -}; - -export const parser = 'tsx'; - -export default transform; + const j = api.jscodeshift + + return j(file.source) + .find(j.CallExpression, { + callee: { name: 'createSlice' }, + arguments: [{ type: 'ObjectExpression' }] + }) + + .filter((path) => { + const createSliceArgsObject = path.node.arguments[0] as ObjectExpression + return createSliceArgsObject.properties.some( + (p) => + p.type === 'ObjectProperty' && + p.key.type === 'Identifier' && + p.key.name === 'reducers' && + p.value.type === 'ObjectExpression' + ) + }) + .forEach((path) => { + const createSliceArgsObject = path.node.arguments[0] as ObjectExpression + j(path).replaceWith( + j.callExpression(j.identifier('createSlice'), [ + j.objectExpression( + createSliceArgsObject.properties.map((p) => { + if ( + p.type === 'ObjectProperty' && + p.key.type === 'Identifier' && + p.key.name === 'reducers' && + p.value.type === 'ObjectExpression' + ) { + const expressionStatement = reducerPropsToBuilderExpression( + j, + p.value + ) + return j.objectProperty(p.key, expressionStatement) + } + return p + }) + ) + ]) + ) + }) + .toSource({ + arrowParensAlways: true, + lineTerminator: '\n' + }) +} + +export const parser = 'tsx' satisfies TestOptions['parser'] + +export default transform diff --git a/packages/rtk-codemods/transforms/createSliceReducerBuilder/test.js b/packages/rtk-codemods/transforms/createSliceReducerBuilder/test.js deleted file mode 100644 index 5e34770a22..0000000000 --- a/packages/rtk-codemods/transforms/createSliceReducerBuilder/test.js +++ /dev/null @@ -1,9 +0,0 @@ -'use strict'; - -const { runTransformTest } = require('codemod-cli'); - -runTransformTest({ - name: 'createSliceReducerBuilder', - path: require.resolve('./index.ts'), - fixtureDir: `${__dirname}/__testfixtures__/`, -}); diff --git a/packages/rtk-codemods/tsconfig.json b/packages/rtk-codemods/tsconfig.json new file mode 100644 index 0000000000..56c373cc6c --- /dev/null +++ b/packages/rtk-codemods/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "isolatedModules": true, + "checkJs": true, + "baseUrl": ".", + "noEmit": true, + "strict": true, + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "Node", + "esModuleInterop": true, + "skipLibCheck": true, + "allowJs": true, + "jsx": "preserve", + "noErrorTruncation": true, + "forceConsistentCasingInFileNames": true, + "paths": { + "@reduxjs/toolkit": ["../toolkit/src/index.ts"], // @remap-prod-remove-line + "@reduxjs/toolkit/query": ["../toolkit/src/query/index.ts"], // @remap-prod-remove-line + "@reduxjs/toolkit/react": ["../toolkit/src/react/index.ts"], // @remap-prod-remove-line + "@reduxjs/toolkit/query/react": ["../toolkit/src/query/react/index.ts"] // @remap-prod-remove-line + } + }, + "include": ["**/*.ts", "**/*.tsx", "bin/cli.js"] +} diff --git a/packages/rtk-codemods/vitest.config.mts b/packages/rtk-codemods/vitest.config.mts new file mode 100644 index 0000000000..556ad64883 --- /dev/null +++ b/packages/rtk-codemods/vitest.config.mts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + globals: true + } +}) diff --git a/packages/rtk-codemods/vitest.config.ts b/packages/rtk-codemods/vitest.config.ts deleted file mode 100644 index b744c56463..0000000000 --- a/packages/rtk-codemods/vitest.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineConfig } from 'vitest/config'; - -export default defineConfig({ - test: { - globals: true, - setupFiles: [], - include: ['./transforms/**/*.(spec|test).[jt]s?(x)'], - alias: {}, - deps: { - interopDefault: true, - }, - }, -}); diff --git a/packages/rtk-query-codegen-openapi/ChangeLog.md b/packages/rtk-query-codegen-openapi/ChangeLog.md index b4dffc2183..8e1b25535c 100644 --- a/packages/rtk-query-codegen-openapi/ChangeLog.md +++ b/packages/rtk-query-codegen-openapi/ChangeLog.md @@ -11,24 +11,28 @@ This version adds a new `mergeReadWriteOnly` configuration option (default to `f ## 1.1.3 - 2023-10-11 ### Added + - Adds a temporary workaround for [4.9.0 and 4.10.0 generate circular types oazapfts/oazapfts#491](https://github.com/oazapfts/oazapfts/issues/491) ## 1.1.2 - 2023-10-11 ### Added -- Support for Read Only Properties in the Open API spec. Previously, this property was ignored. + +- Support for Read Only Properties in the Open API spec. Previously, this property was ignored. - Now if the readOnly property is present and set to `true` in a schema, it will split the type into two types: one with the read only property suffixed as 'Read' and the other without the read only properties, using the same type name as before. - This may cause issues if you had your OpenAPI spec properly typed/configured, as it will remove the read onyl types from your existing type. You will need to switch to the new type suffixed as 'Read' to avoid missing property names. -## 1.1.1 - 2023-10-11 +## 1.1.1 - 2023-10-11 ### Changed + - Codegen: better handling of duplicate param names ([Codegen: better handling of duplicate param names #3780](https://github.com/reduxjs/redux-toolkit/pull/3780)) - If a parameter name is both used in a query and a parameter, it will be prefixed with `query`/`param` now to avoid conflicts -## 1.1.0 - 2023-10-11 +## 1.1.0 - 2023-10-11 ### Added + - Option of generating real TS enums instead of string unions [Adds the option of generating real TS enums instead of string unions #2854](https://github.com/reduxjs/redux-toolkit/pull/2854) - Compatibility with TypeScript 5.x versions as the codegen relies on the TypeScript AST for code generation - As a result also needs a higher TypeScript version to work with (old version range was 4.1-4.5) diff --git a/packages/rtk-query-codegen-openapi/src/generate.ts b/packages/rtk-query-codegen-openapi/src/generate.ts index 6e26697ac1..9c5c00c158 100644 --- a/packages/rtk-query-codegen-openapi/src/generate.ts +++ b/packages/rtk-query-codegen-openapi/src/generate.ts @@ -175,13 +175,13 @@ export async function generateApi( ...apiGen.enumAliases, ...(hooks ? [ - generateReactHooks({ - exportName: generatedApiName, - operationDefinitions, - endpointOverrides, - config: hooks, - }), - ] + generateReactHooks({ + exportName: generatedApiName, + operationDefinitions, + endpointOverrides, + config: hooks, + }), + ] : []), ], factory.createToken(ts.SyntaxKind.EndOfFileToken), @@ -301,7 +301,9 @@ export async function generateApi( const body = apiGen.resolve(requestBody); const schema = apiGen.getSchemaFromContent(body.content); const type = apiGen.getTypeFromSchema(schema); - const schemaName = camelCase((type as any).name || getReferenceName(schema) || ("title" in schema && schema.title) || 'body'); + const schemaName = camelCase( + (type as any).name || getReferenceName(schema) || ('title' in schema && schema.title) || 'body' + ); const name = generateName(schemaName in queryArg ? 'body' : schemaName, 'body'); queryArg[name] = { @@ -335,19 +337,19 @@ export async function generateApi( ? isFlatArg ? withQueryComment({ ...queryArgValues[0].type }, queryArgValues[0], false) : factory.createTypeLiteralNode( - queryArgValues.map((def) => - withQueryComment( - factory.createPropertySignature( - undefined, - propertyName(def.name), - createQuestionToken(!def.required), - def.type - ), - def, - true + queryArgValues.map((def) => + withQueryComment( + factory.createPropertySignature( + undefined, + propertyName(def.name), + createQuestionToken(!def.required), + def.type + ), + def, + true + ) ) ) - ) : factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword) ) ).name @@ -391,18 +393,18 @@ export async function generateApi( return parameters.length === 0 ? undefined : factory.createPropertyAssignment( - factory.createIdentifier(propertyName), - factory.createObjectLiteralExpression( - parameters.map( - (param) => - createPropertyAssignment( - param.originalName, - isFlatArg ? rootObject : accessProperty(rootObject, param.name) - ), - true + factory.createIdentifier(propertyName), + factory.createObjectLiteralExpression( + parameters.map( + (param) => + createPropertyAssignment( + param.originalName, + isFlatArg ? rootObject : accessProperty(rootObject, param.name) + ), + true + ) ) - ) - ); + ); } return factory.createArrowFunction( @@ -423,17 +425,17 @@ export async function generateApi( isQuery && verb.toUpperCase() === 'GET' ? undefined : factory.createPropertyAssignment( - factory.createIdentifier('method'), - factory.createStringLiteral(verb.toUpperCase()) - ), + factory.createIdentifier('method'), + factory.createStringLiteral(verb.toUpperCase()) + ), bodyParameter === undefined ? undefined : factory.createPropertyAssignment( - factory.createIdentifier('body'), - isFlatArg - ? rootObject - : factory.createPropertyAccessExpression(rootObject, factory.createIdentifier(bodyParameter.name)) - ), + factory.createIdentifier('body'), + isFlatArg + ? rootObject + : factory.createPropertyAccessExpression(rootObject, factory.createIdentifier(bodyParameter.name)) + ), createObjectLiteralProperty(pickParams('cookie'), 'cookies'), createObjectLiteralProperty(pickParams('header'), 'headers'), createObjectLiteralProperty(pickParams('query'), 'params'), @@ -445,12 +447,12 @@ export async function generateApi( } // eslint-disable-next-line no-empty-pattern - function generateQueryEndpointProps({ }: { operationDefinition: OperationDefinition }): ObjectPropertyDefinitions { + function generateQueryEndpointProps({}: { operationDefinition: OperationDefinition }): ObjectPropertyDefinitions { return {}; /* TODO needs implementation - skip for now */ } // eslint-disable-next-line no-empty-pattern - function generateMutationEndpointProps({ }: { operationDefinition: OperationDefinition }): ObjectPropertyDefinitions { + function generateMutationEndpointProps({}: { operationDefinition: OperationDefinition }): ObjectPropertyDefinitions { return {}; /* TODO needs implementation - skip for now */ } } @@ -480,16 +482,16 @@ function generatePathExpression( return expressions.length ? factory.createTemplateExpression( - factory.createTemplateHead(head), - expressions.map(([prop, literal], index) => - factory.createTemplateSpan( - isFlatArg ? rootObject : accessProperty(rootObject, prop), - index === expressions.length - 1 - ? factory.createTemplateTail(literal) - : factory.createTemplateMiddle(literal) + factory.createTemplateHead(head), + expressions.map(([prop, literal], index) => + factory.createTemplateSpan( + isFlatArg ? rootObject : accessProperty(rootObject, prop), + index === expressions.length - 1 + ? factory.createTemplateTail(literal) + : factory.createTemplateMiddle(literal) + ) ) ) - ) : factory.createNoSubstitutionTemplateLiteral(head); } @@ -500,13 +502,13 @@ type QueryArgDefinition = { required?: boolean; param?: OpenAPIV3.ParameterObject; } & ( - | { + | { origin: 'param'; param: OpenAPIV3.ParameterObject; } - | { + | { origin: 'body'; body: OpenAPIV3.RequestBodyObject; } - ); +); type QueryArgDefinitions = Record; diff --git a/packages/rtk-query-codegen-openapi/src/types.ts b/packages/rtk-query-codegen-openapi/src/types.ts index bc6fba5d74..701060a6bf 100644 --- a/packages/rtk-query-codegen-openapi/src/types.ts +++ b/packages/rtk-query-codegen-openapi/src/types.ts @@ -2,7 +2,7 @@ import type { OpenAPIV3 } from 'openapi-types'; export type OperationDefinition = { path: string; - verb: typeof operationKeys[number]; + verb: (typeof operationKeys)[number]; pathItem: OpenAPIV3.PathItemObject; operation: OpenAPIV3.OperationObject; }; diff --git a/packages/rtk-query-codegen-openapi/src/utils/getOperationDefinitions.ts b/packages/rtk-query-codegen-openapi/src/utils/getOperationDefinitions.ts index 5cd3854d28..16f1a6f3e7 100644 --- a/packages/rtk-query-codegen-openapi/src/utils/getOperationDefinitions.ts +++ b/packages/rtk-query-codegen-openapi/src/utils/getOperationDefinitions.ts @@ -7,7 +7,7 @@ export function getOperationDefinitions(v3Doc: OpenAPIV3.Document): OperationDef !pathItem ? [] : Object.entries(pathItem) - .filter((arg): arg is [typeof operationKeys[number], OpenAPIV3.OperationObject] => + .filter((arg): arg is [(typeof operationKeys)[number], OpenAPIV3.OperationObject] => operationKeys.includes(arg[0] as any) ) .map(([verb, operation]) => ({ diff --git a/packages/rtk-query-codegen-openapi/src/utils/isQuery.ts b/packages/rtk-query-codegen-openapi/src/utils/isQuery.ts index 8bb779ce17..2cf756e676 100644 --- a/packages/rtk-query-codegen-openapi/src/utils/isQuery.ts +++ b/packages/rtk-query-codegen-openapi/src/utils/isQuery.ts @@ -1,6 +1,6 @@ import type { EndpointOverrides, operationKeys } from '../types'; -export function isQuery(verb: typeof operationKeys[number], overrides: EndpointOverrides | undefined) { +export function isQuery(verb: (typeof operationKeys)[number], overrides: EndpointOverrides | undefined) { if (overrides?.type) { return overrides.type === 'query'; } diff --git a/packages/rtk-query-codegen-openapi/test/generateEndpoints.test.ts b/packages/rtk-query-codegen-openapi/test/generateEndpoints.test.ts index 8171f0ca6f..d922e7ff55 100644 --- a/packages/rtk-query-codegen-openapi/test/generateEndpoints.test.ts +++ b/packages/rtk-query-codegen-openapi/test/generateEndpoints.test.ts @@ -379,7 +379,7 @@ describe('openapi spec', () => { unionUndefined: true, schemaFile: './fixtures/readOnlyWriteOnly.yaml', apiFile: './fixtures/emptyApi.ts', - mergeReadWriteOnly: true + mergeReadWriteOnly: true, }); expect(api).toMatchSnapshot(); }); diff --git a/packages/rtk-query-codegen-openapi/test/tsconfig.json b/packages/rtk-query-codegen-openapi/test/tsconfig.json index 499c1c5631..1c8d5b68ec 100644 --- a/packages/rtk-query-codegen-openapi/test/tsconfig.json +++ b/packages/rtk-query-codegen-openapi/test/tsconfig.json @@ -3,7 +3,7 @@ "lib": ["es2019"], "paths": { "@/*": ["./test/fixtures/*"], - "@rtk-query/codegen-openapi": ["./src"] + "@rtk-query/codegen-openapi": ["./src"], }, "allowSyntheticDefaultImports": true, "esModuleInterop": true, @@ -17,6 +17,6 @@ "resolveJsonModule": true, "types": ["node", "jest"], "allowJs": true, - "checkJs": true - } + "checkJs": true, + }, } diff --git a/packages/rtk-query-codegen-openapi/tsconfig.json b/packages/rtk-query-codegen-openapi/tsconfig.json index 28cad6ed33..6527f11b9d 100644 --- a/packages/rtk-query-codegen-openapi/tsconfig.json +++ b/packages/rtk-query-codegen-openapi/tsconfig.json @@ -66,7 +66,7 @@ /* Advanced Options */ "skipLibCheck": true /* Skip type checking of declaration files. */, - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, }, - "exclude": ["test", "lib"] + "exclude": ["test", "lib"], } diff --git a/packages/rtk-query-graphql-request-base-query/src/GraphqlBaseQueryTypes.ts b/packages/rtk-query-graphql-request-base-query/src/GraphqlBaseQueryTypes.ts index 0c34984567..562d85ae32 100644 --- a/packages/rtk-query-graphql-request-base-query/src/GraphqlBaseQueryTypes.ts +++ b/packages/rtk-query-graphql-request-base-query/src/GraphqlBaseQueryTypes.ts @@ -3,21 +3,24 @@ import type { GraphQLClient, RequestOptions, RequestDocument, - ClientError + ClientError, } from 'graphql-request' export type Document = RequestDocument export type RequestHeaders = RequestOptions['requestHeaders'] export type PrepareHeaders = ( headers: Headers, - api: Pick + api: Pick< + BaseQueryApi, + 'getState' | 'endpoint' | 'type' | 'forced' | 'extra' + >, ) => MaybePromise export type ErrorResponse = { - message: string; - stack: string; - name: string; -}; + message: string + stack: string + name: string +} export type GraphqlRequestBaseQueryArgs = ( | { @@ -26,8 +29,8 @@ export type GraphqlRequestBaseQueryArgs = ( | { client: GraphQLClient } ) & { requestHeaders?: RequestHeaders - prepareHeaders?: PrepareHeaders, - customErrors?: (args: ClientError) => E; + prepareHeaders?: PrepareHeaders + customErrors?: (args: ClientError) => E } export type QueryReturnValue = diff --git a/packages/rtk-query-graphql-request-base-query/src/index.ts b/packages/rtk-query-graphql-request-base-query/src/index.ts index 481ed629ac..b796c5d6d8 100644 --- a/packages/rtk-query-graphql-request-base-query/src/index.ts +++ b/packages/rtk-query-graphql-request-base-query/src/index.ts @@ -10,7 +10,7 @@ import type { } from './GraphqlBaseQueryTypes' export const graphqlRequestBaseQuery = ( - options: GraphqlRequestBaseQueryArgs + options: GraphqlRequestBaseQueryArgs, ): BaseQueryFn< { document: string | DocumentNode; variables?: any }, unknown, @@ -24,7 +24,7 @@ export const graphqlRequestBaseQuery = ( return async ( { document, variables }, - { getState, endpoint, forced, type, signal, extra } + { getState, endpoint, forced, type, signal, extra }, ) => { try { const prepareHeaders: PrepareHeaders = diff --git a/packages/rtk-query-graphql-request-base-query/tsconfig.json b/packages/rtk-query-graphql-request-base-query/tsconfig.json index 98694b0257..076aee3602 100644 --- a/packages/rtk-query-graphql-request-base-query/tsconfig.json +++ b/packages/rtk-query-graphql-request-base-query/tsconfig.json @@ -4,8 +4,8 @@ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ - "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, // "lib": [], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ @@ -25,7 +25,7 @@ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ + "strict": true /* Enable all strict type-checking options. */, // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ @@ -51,7 +51,7 @@ // "typeRoots": [], /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ @@ -66,10 +66,8 @@ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, }, - "include": [ - "**/*.ts" - ] + "include": ["**/*.ts"], } diff --git a/packages/toolkit/.size-limit.cjs b/packages/toolkit/.size-limit.cjs index cb26663b24..5e53694fcf 100644 --- a/packages/toolkit/.size-limit.cjs +++ b/packages/toolkit/.size-limit.cjs @@ -12,19 +12,19 @@ function withRtkPath(suffix, cjs = false) { config.plugins.push( new webpack.NormalModuleReplacementPlugin( /@reduxjs\/toolkit\/query\/react/, - join(__dirname, `query/react`) + join(__dirname, `query/react`), ), new webpack.NormalModuleReplacementPlugin( /@reduxjs\/toolkit\/query/, - join(__dirname, `query`) + join(__dirname, `query`), ), new webpack.NormalModuleReplacementPlugin( /@reduxjs\/toolkit\/react/, - join(__dirname, 'react') + join(__dirname, 'react'), ), new webpack.NormalModuleReplacementPlugin( /@reduxjs\/toolkit/, - join(__dirname) + join(__dirname), ), new webpack.NormalModuleReplacementPlugin( /rtk-query-react.modern.js/, @@ -32,16 +32,16 @@ function withRtkPath(suffix, cjs = false) { const old = r.request r.request = r.request.replace( /rtk-query-react.modern.js$/, - `${cjs ? 'cjs/' : ''}rtk-query-react.${suffix}` + `${cjs ? 'cjs/' : ''}rtk-query-react.${suffix}`, ) // console.log(old, '=>', r.request) - } + }, ), new webpack.NormalModuleReplacementPlugin(/rtk-query.modern.js/, (r) => { const old = r.request r.request = r.request.replace( /rtk-query.modern.js$/, - `${cjs ? 'cjs/' : ''}rtk-query.${suffix}` + `${cjs ? 'cjs/' : ''}rtk-query.${suffix}`, ) // console.log(old, '=>', r.request) }), @@ -51,10 +51,10 @@ function withRtkPath(suffix, cjs = false) { const old = r.request r.request = r.request.replace( /redux-toolkit-react.modern.js$/, - `${cjs ? 'cjs/' : ''}redux-toolkit-react.${suffix}` + `${cjs ? 'cjs/' : ''}redux-toolkit-react.${suffix}`, ) // console.log(old, '=>', r.request) - } + }, ), new webpack.NormalModuleReplacementPlugin( /redux-toolkit.modern.js$/, @@ -62,11 +62,11 @@ function withRtkPath(suffix, cjs = false) { const old = r.request r.request = r.request.replace( /redux-toolkit.modern.js$/, - `${cjs ? 'cjs/' : ''}redux-toolkit.${suffix}` + `${cjs ? 'cjs/' : ''}redux-toolkit.${suffix}`, ) // console.log(old, '=>', r.request) - } - ) + }, + ), ) if (suffix === 'production.min.cjs') { ;(config.resolve ??= {}).mainFields = ['main', 'module'] @@ -130,7 +130,7 @@ module.exports = entryPoints ...e, name: e.name + ` (${suffix})`, modifyWebpackConfig: withRtkPath(suffix), - })) + })), ) .concat( entryPoints.flatMap((e) => @@ -138,8 +138,8 @@ module.exports = entryPoints ...e, name: e.name + ` (cjs, ${suffix})`, modifyWebpackConfig: withRtkPath(suffix, true), - })) - ) + })), + ), ) .concat( ...[ @@ -179,5 +179,5 @@ module.exports = entryPoints ...e, name: e.name + ` (.modern.mjs)`, modifyWebpackConfig: withRtkPath('.modern.mjs'), - })) + })), ) diff --git a/packages/toolkit/etc/redux-toolkit.api.md b/packages/toolkit/etc/redux-toolkit.api.md index 8628682b33..dcfe7462b0 100644 --- a/packages/toolkit/etc/redux-toolkit.api.md +++ b/packages/toolkit/etc/redux-toolkit.api.md @@ -31,7 +31,7 @@ import type { ThunkMiddleware } from 'redux-thunk' // @public export interface ActionCreatorWithNonInferrablePayload< - T extends string = string + T extends string = string, > extends BaseActionCreator { (payload: PT): PayloadAction } @@ -60,35 +60,35 @@ export interface ActionCreatorWithPreparedPayload< P, T extends string = string, E = never, - M = never + M = never, > extends BaseActionCreator { (...args: Args): PayloadAction } // @public (undocumented) export type ActionMatchingAllOf< - Matchers extends [Matcher, ...Matcher[]] + Matchers extends [Matcher, ...Matcher[]], > = UnionToIntersection> // @public (undocumented) export type ActionMatchingAnyOf< - Matchers extends [Matcher, ...Matcher[]] + Matchers extends [Matcher, ...Matcher[]], > = ActionFromMatcher // @public export interface ActionReducerMapBuilder { addCase>( actionCreator: ActionCreator, - reducer: CaseReducer> + reducer: CaseReducer>, ): ActionReducerMapBuilder addCase>( type: Type, - reducer: CaseReducer + reducer: CaseReducer, ): ActionReducerMapBuilder addDefaultCase(reducer: CaseReducer): {} addMatcher( matcher: TypeGuard | ((action: any) => boolean), - reducer: CaseReducer + reducer: CaseReducer, ): Omit, 'addCase'> } @@ -99,7 +99,7 @@ export type Actions = Record export type AsyncThunk< Returned, ThunkArg, - ThunkApiConfig extends AsyncThunkConfig + ThunkApiConfig extends AsyncThunkConfig, > = AsyncThunkActionCreator & { pending: AsyncThunkPendingActionCreator rejected: AsyncThunkRejectedActionCreator @@ -115,11 +115,11 @@ export type AsyncThunk< export type AsyncThunkAction< Returned, ThunkArg, - ThunkApiConfig extends AsyncThunkConfig + ThunkApiConfig extends AsyncThunkConfig, > = ( dispatch: GetDispatch, getState: () => GetState, - extra: GetExtra + extra: GetExtra, ) => Promise< | ReturnType> | ReturnType> @@ -133,11 +133,11 @@ export type AsyncThunkAction< // @public export type AsyncThunkOptions< ThunkArg = void, - ThunkApiConfig extends AsyncThunkConfig = {} + ThunkApiConfig extends AsyncThunkConfig = {}, > = { condition?( arg: ThunkArg, - api: Pick, 'getState' | 'extra'> + api: Pick, 'getState' | 'extra'>, ): MaybePromise dispatchConditionRejection?: boolean serializeError?: (x: unknown) => GetSerializedErrorType @@ -150,7 +150,7 @@ export type AsyncThunkOptions< arg: ThunkArg requestId: string }, - api: Pick, 'getState' | 'extra'> + api: Pick, 'getState' | 'extra'>, ): GetPendingMeta }, { @@ -159,7 +159,7 @@ export type AsyncThunkOptions< arg: ThunkArg requestId: string }, - api: Pick, 'getState' | 'extra'> + api: Pick, 'getState' | 'extra'>, ): GetPendingMeta } > @@ -168,16 +168,16 @@ export type AsyncThunkOptions< export type AsyncThunkPayloadCreator< Returned, ThunkArg = void, - ThunkApiConfig extends AsyncThunkConfig = {} + ThunkApiConfig extends AsyncThunkConfig = {}, > = ( arg: ThunkArg, - thunkAPI: GetThunkAPI + thunkAPI: GetThunkAPI, ) => AsyncThunkPayloadCreatorReturnValue // @public export type AsyncThunkPayloadCreatorReturnValue< Returned, - ThunkApiConfig extends AsyncThunkConfig + ThunkApiConfig extends AsyncThunkConfig, > = MaybePromise< | IsUnknown< GetFulfilledMeta, @@ -193,7 +193,7 @@ export type AsyncThunkPayloadCreatorReturnValue< // @public export type CaseReducer = ( state: Draft, - action: A + action: A, ) => S | void | Draft // @public @@ -221,21 +221,21 @@ export type Comparer = (a: T, b: T) => number // @public export type ConfigureEnhancersCallback = ( - defaultEnhancers: readonly StoreEnhancer[] + defaultEnhancers: readonly StoreEnhancer[], ) => StoreEnhancer[] // @public export function configureStore< S = any, A extends Action = UnknownAction, - M extends Middlewares = [ThunkMiddlewareFor] + M extends Middlewares = [ThunkMiddlewareFor], >(options: ConfigureStoreOptions): EnhancedStore // @public export interface ConfigureStoreOptions< S = any, A extends Action = UnknownAction, - M extends Middlewares = Middlewares + M extends Middlewares = Middlewares, > { devTools?: boolean | EnhancerOptions enhancers?: StoreEnhancer[] | ConfigureEnhancersCallback @@ -246,34 +246,34 @@ export interface ConfigureStoreOptions< // @public export function createAction

| void = void + PA extends PrepareAction

| void = void, > = IfPrepareActionMethodProvided< PA, _ActionCreatorWithPreparedPayload, @@ -786,7 +786,7 @@ export interface SerializedError { export interface Slice< State = any, CaseReducers extends SliceCaseReducers = SliceCaseReducers, - Name extends string = string + Name extends string = string, > { actions: CaseReducerActions caseReducers: SliceDefinedCaseReducers @@ -811,7 +811,7 @@ export { ThunkDispatch } // @public (undocumented) export function unwrapResult( - action: R + action: R, ): UnwrappedActionPayload // @public (undocumented) @@ -823,17 +823,16 @@ export type Update = { // @public export type ValidateSliceCaseReducers< S, - ACR extends SliceCaseReducers -> = ACR & - { - [T in keyof ACR]: ACR[T] extends { - reducer(s: S, action?: infer A): any - } - ? { - prepare(...a: never[]): Omit - } - : {} + ACR extends SliceCaseReducers, +> = ACR & { + [T in keyof ACR]: ACR[T] extends { + reducer(s: S, action?: infer A): any } + ? { + prepare(...a: never[]): Omit + } + : {} +} export * from 'redux' diff --git a/packages/toolkit/etc/rtk-query-react.api.md b/packages/toolkit/etc/rtk-query-react.api.md index a4e1079965..d50f544427 100644 --- a/packages/toolkit/etc/rtk-query-react.api.md +++ b/packages/toolkit/etc/rtk-query-react.api.md @@ -18,7 +18,7 @@ export type Api< Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string, - Enhancers extends ModuleName = CoreModule + Enhancers extends ModuleName = CoreModule, > = Id< Id< UnionToIntersection< @@ -27,7 +27,7 @@ export type Api< > & { injectEndpoints(_: { endpoints: ( - build: EndpointBuilder + build: EndpointBuilder, ) => NewDefinitions overrideExisting?: boolean }): Api< @@ -64,7 +64,7 @@ export interface ApiModules< BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, - TagTypes extends string + TagTypes extends string, > {} // @public @@ -80,7 +80,7 @@ export type ApiWithInjectedEndpoints< ApiDefinition extends Api, Injections extends ApiDefinition extends Api ? [Api, ...Api[]] - : never + : never, > = Omit & Omit & { endpoints: ApiDefinition['endpoints'] & @@ -91,10 +91,10 @@ export type ApiWithInjectedEndpoints< export type BaseQueryEnhancer< AdditionalArgs = unknown, AdditionalDefinitionExtraOptions = unknown, - Config = void + Config = void, > = ( baseQuery: BaseQuery, - config: Config + config: Config, ) => BaseQueryFn< BaseQueryArg & AdditionalArgs, BaseQueryResult, @@ -108,11 +108,11 @@ export type BaseQueryFn< Result = unknown, Error = unknown, DefinitionExtraOptions = {}, - Meta = {} + Meta = {}, > = ( args: Args, api: BaseQueryApi, - extraOptions: DefinitionExtraOptions + extraOptions: DefinitionExtraOptions, ) => MaybePromise> // @public @@ -132,9 +132,9 @@ export type CreateApi = { BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', - TagTypes extends string = never + TagTypes extends string = never, >( - options: CreateApiOptions + options: CreateApiOptions, ): Api } @@ -148,11 +148,11 @@ export interface CreateApiOptions< BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', - TagTypes extends string = never + TagTypes extends string = never, > { baseQuery: BaseQuery endpoints( - build: EndpointBuilder + build: EndpointBuilder, ): Definitions keepUnusedDataFor?: number reducerPath?: ReducerPath @@ -169,7 +169,7 @@ export type EndpointDefinition< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > = | QueryDefinition | MutationDefinition @@ -231,17 +231,17 @@ export type Module = { BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, - TagTypes extends string + TagTypes extends string, >( api: Api, options: Required< CreateApiOptions >, - context: ApiContext + context: ApiContext, ): { injectEndpoint( endpointName: string, - definition: EndpointDefinition + definition: EndpointDefinition, ): void } } @@ -252,7 +252,7 @@ export type MutationDefinition< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > = BaseEndpointDefinition & MutationExtraOptions @@ -262,7 +262,7 @@ export type QueryDefinition< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > = BaseEndpointDefinition & QueryExtraOptions @@ -305,8 +305,8 @@ export function setupListeners( onFocusLost: typeof onFocusLost onOnline: typeof onOnline onOffline: typeof onOffline - } - ) => () => void + }, + ) => () => void, ): () => void // @public (undocumented) diff --git a/packages/toolkit/etc/rtk-query.api.md b/packages/toolkit/etc/rtk-query.api.md index dea69f7421..160ec14fe7 100644 --- a/packages/toolkit/etc/rtk-query.api.md +++ b/packages/toolkit/etc/rtk-query.api.md @@ -14,13 +14,13 @@ export type Api< Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string, - Enhancers extends ModuleName = CoreModule + Enhancers extends ModuleName = CoreModule, > = UnionToIntersection< ApiModules[Enhancers] > & { injectEndpoints(_: { endpoints: ( - build: EndpointBuilder + build: EndpointBuilder, ) => NewDefinitions overrideExisting?: boolean }): Api< @@ -56,17 +56,17 @@ export interface ApiModules< BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, - TagTypes extends string + TagTypes extends string, > {} // @public (undocumented) export type BaseQueryEnhancer< AdditionalArgs = unknown, AdditionalDefinitionExtraOptions = unknown, - Config = void + Config = void, > = ( baseQuery: BaseQuery, - config: Config + config: Config, ) => BaseQueryFn< BaseQueryArg & AdditionalArgs, BaseQueryResult, @@ -82,11 +82,11 @@ export type BaseQueryFn< DefinitionExtraOptions = { copyWithStructuralSharing?: boolean }, - Meta = {} + Meta = {}, > = ( args: Args, api: BaseQueryApi, - extraOptions: DefinitionExtraOptions + extraOptions: DefinitionExtraOptions, ) => MaybePromise> // @public @@ -106,9 +106,9 @@ export type CreateApi = { BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', - TagTypes extends string = never + TagTypes extends string = never, >( - options: CreateApiOptions + options: CreateApiOptions, ): Api } @@ -120,11 +120,11 @@ export interface CreateApiOptions< BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', - TagTypes extends string = never + TagTypes extends string = never, > { baseQuery: BaseQuery endpoints( - build: EndpointBuilder + build: EndpointBuilder, ): Definitions extractRehydrationInfo?: ( action: UnknownAction, @@ -132,7 +132,7 @@ export interface CreateApiOptions< reducerPath, }: { reducerPath: ReducerPath - } + }, ) => | undefined | CombinedState< @@ -156,7 +156,7 @@ export type EndpointDefinition< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > = | QueryDefinition | MutationDefinition @@ -240,7 +240,7 @@ export type Module = { BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, - TagTypes extends string + TagTypes extends string, >( api: Api, options: WithRequiredProp< @@ -254,11 +254,11 @@ export type Module = { | 'tagTypes' | 'structuralSharing' >, - context: ApiContext + context: ApiContext, ): { injectEndpoint( endpointName: string, - definition: EndpointDefinition + definition: EndpointDefinition, ): void } } @@ -269,7 +269,7 @@ export type MutationDefinition< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > = BaseEndpointDefinition & MutationExtraOptions @@ -279,7 +279,7 @@ export type QueryDefinition< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > = BaseEndpointDefinition & QueryExtraOptions @@ -314,8 +314,8 @@ export function setupListeners( onFocusLost: typeof onFocusLost onOnline: typeof onOnline onOffline: typeof onOffline - } - ) => () => void + }, + ) => () => void, ): () => void // @public @deprecated (undocumented) diff --git a/packages/toolkit/package.json b/packages/toolkit/package.json index f4663a8499..3d192ab5b9 100644 --- a/packages/toolkit/package.json +++ b/packages/toolkit/package.json @@ -1,6 +1,6 @@ { "name": "@reduxjs/toolkit", - "version": "2.0.2", + "version": "2.1.0", "description": "The official, opinionated, batteries-included toolset for efficient Redux development", "author": "Mark Erikson ", "license": "MIT", @@ -49,7 +49,7 @@ } }, "devDependencies": { - "@arethetypeswrong/cli": "^0.13.1", + "@arethetypeswrong/cli": "^0.13.5", "@microsoft/api-extractor": "^7.13.2", "@phryneas/ts-version": "^1.0.2", "@size-limit/file": "^11.0.1", @@ -69,42 +69,43 @@ "console-testing-library": "0.6.1", "esbuild-extra": "^0.3.1", "eslint": "^7.25.0", - "eslint-config-prettier": "^8.3.0", + "eslint-config-prettier": "^9.1.0", "eslint-config-react-app": "^7.0.1", "eslint-plugin-flowtype": "^5.7.2", "eslint-plugin-import": "^2.22.1", "eslint-plugin-jsx-a11y": "^6.4.1", - "eslint-plugin-prettier": "^3.4.0", + "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.23.2", "eslint-plugin-react-hooks": "^4.2.0", "fs-extra": "^9.1.0", "invariant": "^2.2.4", "jsdom": "^21.0.0", "json-stringify-safe": "^5.0.1", - "msw": "^0.40.2", - "node-fetch": "^2.6.1", - "prettier": "^2.2.1", + "msw": "^2.1.4", + "node-fetch": "^3.3.2", + "prettier": "^3.2.4", "query-string": "^7.0.1", "rimraf": "^3.0.2", "size-limit": "^11.0.1", "tslib": "^1.10.0", "tsup": "^7.2.0", "tsx": "^3.12.2", - "typescript": "5.2", + "typescript": "^5.3.3", "vitest": "^1.1.3", "yargs": "^15.3.1" }, "scripts": { + "clean": "rimraf dist", "run-build": "tsup", - "build": "yarn rimraf dist && echo Compiling TS... && yarn tsc && yarn run-build", - "build-only": "yarn rimraf dist && yarn run-build", + "build": "yarn clean && echo Compiling TS... && yarn tsc -p tsconfig.build.json && yarn run-build", + "build-only": "yarn clean && yarn run-build", "format": "prettier --write \"(src|examples)/**/*.{ts,tsx}\" \"**/*.md\"", "format:check": "prettier --list-different \"(src|examples)/**/*.{ts,tsx}\" \"docs/*/**.md\"", "lint": "eslint src examples", - "test": "vitest", - "type-tests": "yarn tsc -p src/tests/tsconfig.typetests.json && yarn tsc -p src/query/tests/tsconfig.typetests.json", - "prepack": "yarn build", - "size": "size-limit" + "test": "vitest --run --typecheck", + "test:watch": "vitest --watch", + "type-tests": "yarn tsc -p tsconfig.test.json --noEmit", + "prepack": "yarn build" }, "files": [ "dist/", diff --git a/packages/toolkit/scripts/mangleErrors.cjs b/packages/toolkit/scripts/mangleErrors.cjs index 96581df353..f777995f13 100644 --- a/packages/toolkit/scripts/mangleErrors.cjs +++ b/packages/toolkit/scripts/mangleErrors.cjs @@ -22,7 +22,7 @@ const evalToString = (ast) => { return ast.quasis.reduce( (concatenatedValue, templateElement) => concatenatedValue + templateElement.value.raw, - '' + '', ) case 'Identifier': return ast.name @@ -114,20 +114,20 @@ module.exports = (babel) => { path, 'formatProdErrorMessage', '@reduxjs/toolkit', - { nameHint: 'formatProdErrorMessage' } + { nameHint: 'formatProdErrorMessage' }, ) // Creates a function call to output the message to the error code page on the website const prodMessage = t.callExpression( formatProdErrorMessageIdentifier, - [t.numericLiteral(errorIndex)] + [t.numericLiteral(errorIndex)], ) if (minify) { path.replaceWith( t.throwStatement( - t.newExpression(t.identifier('Error'), [prodMessage]) - ) + t.newExpression(t.identifier('Error'), [prodMessage]), + ), ) } else { path.replaceWith( @@ -137,13 +137,13 @@ module.exports = (babel) => { t.binaryExpression( '===', t.identifier('process.env.NODE_ENV'), - t.stringLiteral('production') + t.stringLiteral('production'), ), prodMessage, - path.node.argument.arguments[0] + path.node.argument.arguments[0], ), - ]) - ) + ]), + ), ) } } diff --git a/packages/toolkit/src/actionCreatorInvariantMiddleware.ts b/packages/toolkit/src/actionCreatorInvariantMiddleware.ts index 1f3a47e0d4..4b95495cbe 100644 --- a/packages/toolkit/src/actionCreatorInvariantMiddleware.ts +++ b/packages/toolkit/src/actionCreatorInvariantMiddleware.ts @@ -19,7 +19,7 @@ Make sure you're calling the action creator before dispatching, i.e. \`dispatch( } export function createActionCreatorInvariantMiddleware( - options: ActionCreatorInvariantMiddlewareOptions = {} + options: ActionCreatorInvariantMiddlewareOptions = {}, ): Middleware { if (process.env.NODE_ENV === 'production') { return () => (next) => (action) => next(action) diff --git a/packages/toolkit/src/autoBatchEnhancer.ts b/packages/toolkit/src/autoBatchEnhancer.ts index eb4dd8ca56..560cb49e18 100644 --- a/packages/toolkit/src/autoBatchEnhancer.ts +++ b/packages/toolkit/src/autoBatchEnhancer.ts @@ -66,10 +66,10 @@ export const autoBatchEnhancer = options.type === 'tick' ? queueMicrotask : options.type === 'raf' - ? rAF - : options.type === 'callback' - ? options.queueNotification - : createQueueWithTimer(options.timeout) + ? rAF + : options.type === 'callback' + ? options.queueNotification + : createQueueWithTimer(options.timeout) const notifyListeners = () => { // We're running at the end of the event loop tick. diff --git a/packages/toolkit/src/combineSlices.ts b/packages/toolkit/src/combineSlices.ts index 1a10538cd8..f045f14f17 100644 --- a/packages/toolkit/src/combineSlices.ts +++ b/packages/toolkit/src/combineSlices.ts @@ -17,19 +17,11 @@ type SliceLike = { type AnySliceLike = SliceLike -type SliceLikeReducerPath = A extends SliceLike< - infer ReducerPath, - any -> - ? ReducerPath - : never - -type SliceLikeState = A extends SliceLike< - any, - infer State -> - ? State - : never +type SliceLikeReducerPath = + A extends SliceLike ? ReducerPath : never + +type SliceLikeState = + A extends SliceLike ? State : never export type WithSlice = { [Path in SliceLikeReducerPath]: SliceLikeState @@ -56,7 +48,7 @@ export type InjectConfig = { */ export interface CombinedSliceReducer< InitialState, - DeclaredState = InitialState + DeclaredState = InitialState, > extends Reducer> { /** * Provide a type for slices that will be injected lazily. @@ -106,7 +98,7 @@ export interface CombinedSliceReducer< */ inject>>( slice: Sl, - config?: InjectConfig + config?: InjectConfig, ): CombinedSliceReducer>> /** @@ -126,7 +118,7 @@ export interface CombinedSliceReducer< ReducerPath, State & (ReducerPath extends keyof DeclaredState ? never : State) >, - config?: InjectConfig + config?: InjectConfig, ): CombinedSliceReducer< InitialState, Id>> @@ -212,7 +204,7 @@ export interface CombinedSliceReducer< * ``` */ unknown>( - selectorFn: Selector + selectorFn: Selector, ): ( state: WithOptionalProp< Parameters[0], @@ -276,7 +268,7 @@ export interface CombinedSliceReducer< */ < Selector extends (state: DeclaredState, ...args: any[]) => unknown, - RootState + RootState, >( selectorFn: Selector, selectState: ( @@ -285,7 +277,7 @@ export interface CombinedSliceReducer< ) => WithOptionalProp< Parameters[0], Exclude - > + >, ): ( state: RootState, ...args: Tail> @@ -310,7 +302,7 @@ type InitialState> = > const isSliceLike = ( - maybeSliceLike: AnySliceLike | ReducerMap + maybeSliceLike: AnySliceLike | ReducerMap, ): maybeSliceLike is AnySliceLike => 'reducerPath' in maybeSliceLike && typeof maybeSliceLike.reducerPath === 'string' @@ -319,7 +311,7 @@ const getReducers = (slices: Array) => slices.flatMap((sliceOrMap) => isSliceLike(sliceOrMap) ? [[sliceOrMap.reducerPath, sliceOrMap.reducer] as const] - : Object.entries(sliceOrMap) + : Object.entries(sliceOrMap), ) const ORIGINAL_STATE = Symbol.for('rtk-state-proxy-original') @@ -330,7 +322,7 @@ const stateProxyMap = new WeakMap() const createStateProxy = ( state: State, - reducerMap: Partial> + reducerMap: Partial>, ) => emplace(stateProxyMap, state, { insert: () => @@ -349,7 +341,7 @@ const createStateProxy = ( `If the state passed to the reducer is undefined, you must ` + `explicitly return the initial state. The initial state may ` + `not be undefined. If you don't want to set a value for this reducer, ` + - `you can use null instead of undefined.` + `you can use null instead of undefined.`, ) } return reducerResult @@ -370,8 +362,8 @@ const original = (state: any) => { export function combineSlices< Slices extends [ AnySliceLike | ReducerMap, - ...Array - ] + ...Array, + ], >(...slices: Slices): CombinedSliceReducer>> { const reducerMap = Object.fromEntries(getReducers(slices)) @@ -381,7 +373,7 @@ export function combineSlices< function combinedReducer( state: Record, - action: UnknownAction + action: UnknownAction, ) { return reducer(state, action) } @@ -390,7 +382,7 @@ export function combineSlices< const inject = ( slice: AnySliceLike, - config: InjectConfig = {} + config: InjectConfig = {}, ): typeof combinedReducer => { const { reducerPath, reducer: reducerToInject } = slice @@ -405,7 +397,7 @@ export function combineSlices< process.env.NODE_ENV === 'development' ) { console.error( - `called \`inject\` to override already-existing reducer ${reducerPath} without specifying \`overrideExisting: true\`` + `called \`inject\` to override already-existing reducer ${reducerPath} without specifying \`overrideExisting: true\``, ) } @@ -422,19 +414,19 @@ export function combineSlices< const selector = Object.assign( function makeSelector( selectorFn: (state: State, ...args: Args) => any, - selectState?: (rootState: RootState, ...args: Args) => State + selectState?: (rootState: RootState, ...args: Args) => State, ) { return function selector(state: State, ...args: Args) { return selectorFn( createStateProxy( selectState ? selectState(state as any, ...args) : state, - reducerMap + reducerMap, ), - ...args + ...args, ) } }, - { original } + { original }, ) return Object.assign(combinedReducer, { inject, selector }) as any diff --git a/packages/toolkit/src/configureStore.ts b/packages/toolkit/src/configureStore.ts index e1b1a491e1..05b3bb8914 100644 --- a/packages/toolkit/src/configureStore.ts +++ b/packages/toolkit/src/configureStore.ts @@ -44,7 +44,7 @@ export interface ConfigureStoreOptions< A extends Action = UnknownAction, M extends Tuple> = Tuple>, E extends Tuple = Tuple, - P = S + P = S, > { /** * A single reducer function that will be used as the root reducer, or an @@ -103,7 +103,7 @@ type Enhancers = ReadonlyArray export type EnhancedStore< S = any, A extends Action = UnknownAction, - E extends Enhancers = Enhancers + E extends Enhancers = Enhancers, > = ExtractStoreExtensions & Store>> @@ -122,7 +122,7 @@ export function configureStore< E extends Tuple = Tuple< [StoreEnhancer<{ dispatch: ExtractDispatchExtensions }>, StoreEnhancer] >, - P = S + P = S, >(options: ConfigureStoreOptions): EnhancedStore { const getDefaultMiddleware = buildGetDefaultMiddleware() @@ -142,7 +142,7 @@ export function configureStore< rootReducer = combineReducers(reducer) as unknown as Reducer } else { throw new Error( - '`reducer` is a required argument, and must be a function or an object of functions that can be passed to combineReducers' + '`reducer` is a required argument, and must be a function or an object of functions that can be passed to combineReducers', ) } @@ -156,7 +156,7 @@ export function configureStore< if (!IS_PRODUCTION && !Array.isArray(finalMiddleware)) { throw new Error( - 'when using a middleware builder function, an array of middleware must be returned' + 'when using a middleware builder function, an array of middleware must be returned', ) } } else { @@ -167,7 +167,7 @@ export function configureStore< finalMiddleware.some((item: any) => typeof item !== 'function') ) { throw new Error( - 'each middleware provided to configureStore must be a function' + 'each middleware provided to configureStore must be a function', ) } @@ -202,7 +202,7 @@ export function configureStore< storeEnhancers.some((item: any) => typeof item !== 'function') ) { throw new Error( - 'each enhancer provided to configureStore must be a function' + 'each enhancer provided to configureStore must be a function', ) } if ( @@ -211,7 +211,7 @@ export function configureStore< !storeEnhancers.includes(middlewareEnhancer) ) { console.error( - 'middlewares were provided, but middleware enhancer was not included in final enhancers - make sure to call `getDefaultEnhancers`' + 'middlewares were provided, but middleware enhancer was not included in final enhancers - make sure to call `getDefaultEnhancers`', ) } diff --git a/packages/toolkit/src/createAction.ts b/packages/toolkit/src/createAction.ts index 7e347c0472..ea8958288d 100644 --- a/packages/toolkit/src/createAction.ts +++ b/packages/toolkit/src/createAction.ts @@ -22,7 +22,7 @@ export type PayloadAction< P = void, T extends string = string, M = never, - E = never + E = never, > = { payload: P type: T @@ -57,24 +57,25 @@ export type PrepareAction

= */ export type _ActionCreatorWithPreparedPayload< PA extends PrepareAction | void, - T extends string = string -> = PA extends PrepareAction - ? ActionCreatorWithPreparedPayload< - Parameters, - P, - T, - ReturnType extends { - error: infer E - } - ? E - : never, - ReturnType extends { - meta: infer M - } - ? M - : never - > - : void + T extends string = string, +> = + PA extends PrepareAction + ? ActionCreatorWithPreparedPayload< + Parameters, + P, + T, + ReturnType extends { + error: infer E + } + ? E + : never, + ReturnType extends { + meta: infer M + } + ? M + : never + > + : void /** * Basic type for all action creators. @@ -104,7 +105,7 @@ export interface ActionCreatorWithPreparedPayload< P, T extends string = string, E = never, - M = never + M = never, > extends BaseActionCreator { /** * Calling this {@link redux#ActionCreator} with `Args` will return @@ -171,7 +172,7 @@ export interface ActionCreatorWithPayload * @public */ export interface ActionCreatorWithNonInferrablePayload< - T extends string = string + T extends string = string, > extends BaseActionCreator { /** * Calling this {@link redux#ActionCreator} with an argument will @@ -193,7 +194,7 @@ export interface ActionCreatorWithNonInferrablePayload< export type PayloadActionCreator< P = void, T extends string = string, - PA extends PrepareAction

| void = void + PA extends PrepareAction

| void = void, > = IfPrepareActionMethodProvided< PA, _ActionCreatorWithPreparedPayload, @@ -233,7 +234,7 @@ export type PayloadActionCreator< * @public */ export function createAction

( - type: T + type: T, ): PayloadActionCreator /** @@ -250,10 +251,10 @@ export function createAction

( */ export function createAction< PA extends PrepareAction, - T extends string = string + T extends string = string, >( type: T, - prepareAction: PA + prepareAction: PA, ): PayloadActionCreator['payload'], T, PA> export function createAction(type: string, prepareAction?: Function): any { @@ -288,7 +289,7 @@ export function createAction(type: string, prepareAction?: Function): any { * Returns true if value is an RTK-like action creator, with a static type property and match method. */ export function isActionCreator( - action: unknown + action: unknown, ): action is BaseActionCreator & Function { return ( typeof action === 'function' && @@ -319,5 +320,5 @@ function isValidKey(key: string) { type IfPrepareActionMethodProvided< PA extends PrepareAction | void, True, - False + False, > = PA extends (...args: any[]) => any ? True : False diff --git a/packages/toolkit/src/createAsyncThunk.ts b/packages/toolkit/src/createAsyncThunk.ts index f75653bda9..f384ab9af2 100644 --- a/packages/toolkit/src/createAsyncThunk.ts +++ b/packages/toolkit/src/createAsyncThunk.ts @@ -11,6 +11,7 @@ import type { Id, IsAny, IsUnknown, + SafePromise, TypeGuard, } from './tsHelpers' import { nanoid } from './nanoid' @@ -25,7 +26,7 @@ export type BaseThunkAPI< D extends Dispatch = Dispatch, RejectedValue = unknown, RejectedMeta = unknown, - FulfilledMeta = unknown + FulfilledMeta = unknown, > = { dispatch: D getState: () => S @@ -38,7 +39,7 @@ export type BaseThunkAPI< (value: RejectedValue) => RejectWithValue, ( value: RejectedValue, - meta: RejectedMeta + meta: RejectedMeta, ) => RejectWithValue > fulfillWithValue: IsUnknown< @@ -46,7 +47,7 @@ export type BaseThunkAPI< (value: FulfilledValue) => FulfilledValue, ( value: FulfilledValue, - meta: FulfilledMeta + meta: FulfilledMeta, ) => FulfillWithMeta > } @@ -76,7 +77,7 @@ class RejectWithValue { private readonly _type!: 'RejectWithValue' constructor( public readonly payload: Payload, - public readonly meta: RejectedMeta + public readonly meta: RejectedMeta, ) {} } @@ -88,7 +89,7 @@ class FulfillWithMeta { private readonly _type!: 'FulfillWithMeta' constructor( public readonly payload: Payload, - public readonly meta: FulfilledMeta + public readonly meta: FulfilledMeta, ) {} } @@ -198,7 +199,7 @@ type MaybePromise = T | Promise | (T extends any ? Promise : never) */ export type AsyncThunkPayloadCreatorReturnValue< Returned, - ThunkApiConfig extends AsyncThunkConfig + ThunkApiConfig extends AsyncThunkConfig, > = MaybePromise< | IsUnknown< GetFulfilledMeta, @@ -219,10 +220,10 @@ export type AsyncThunkPayloadCreatorReturnValue< export type AsyncThunkPayloadCreator< Returned, ThunkArg = void, - ThunkApiConfig extends AsyncThunkConfig = {} + ThunkApiConfig extends AsyncThunkConfig = {}, > = ( arg: ThunkArg, - thunkAPI: GetThunkAPI + thunkAPI: GetThunkAPI, ) => AsyncThunkPayloadCreatorReturnValue /** @@ -237,12 +238,12 @@ export type AsyncThunkPayloadCreator< export type AsyncThunkAction< Returned, ThunkArg, - ThunkApiConfig extends AsyncThunkConfig + ThunkApiConfig extends AsyncThunkConfig, > = ( dispatch: GetDispatch, getState: () => GetState, - extra: GetExtra -) => Promise< + extra: GetExtra, +) => SafePromise< | ReturnType> | ReturnType> > & { @@ -255,7 +256,7 @@ export type AsyncThunkAction< type AsyncThunkActionCreator< Returned, ThunkArg, - ThunkApiConfig extends AsyncThunkConfig + ThunkApiConfig extends AsyncThunkConfig, > = IsAny< ThunkArg, // any handling @@ -264,19 +265,25 @@ type AsyncThunkActionCreator< unknown extends ThunkArg ? (arg: ThunkArg) => AsyncThunkAction // argument not specified or specified as void or undefined : [ThunkArg] extends [void] | [undefined] - ? () => AsyncThunkAction // argument contains void - : [void] extends [ThunkArg] // make optional - ? (arg?: ThunkArg) => AsyncThunkAction // argument contains undefined - : [undefined] extends [ThunkArg] - ? WithStrictNullChecks< - // with strict nullChecks: make optional - ( - arg?: ThunkArg - ) => AsyncThunkAction, - // without strict null checks this will match everything, so don't make it optional - (arg: ThunkArg) => AsyncThunkAction - > // default case: normal argument - : (arg: ThunkArg) => AsyncThunkAction + ? () => AsyncThunkAction // argument contains void + : [void] extends [ThunkArg] // make optional + ? ( + arg?: ThunkArg, + ) => AsyncThunkAction // argument contains undefined + : [undefined] extends [ThunkArg] + ? WithStrictNullChecks< + // with strict nullChecks: make optional + ( + arg?: ThunkArg, + ) => AsyncThunkAction, + // without strict null checks this will match everything, so don't make it optional + ( + arg: ThunkArg, + ) => AsyncThunkAction + > // default case: normal argument + : ( + arg: ThunkArg, + ) => AsyncThunkAction > /** @@ -286,7 +293,7 @@ type AsyncThunkActionCreator< */ export type AsyncThunkOptions< ThunkArg = void, - ThunkApiConfig extends AsyncThunkConfig = {} + ThunkApiConfig extends AsyncThunkConfig = {}, > = { /** * A method to control whether the asyncThunk should be executed. Has access to the @@ -296,7 +303,7 @@ export type AsyncThunkOptions< */ condition?( arg: ThunkArg, - api: Pick, 'getState' | 'extra'> + api: Pick, 'getState' | 'extra'>, ): MaybePromise /** * If `condition` returns `false`, the asyncThunk will be skipped. @@ -329,7 +336,7 @@ export type AsyncThunkOptions< arg: ThunkArg requestId: string }, - api: Pick, 'getState' | 'extra'> + api: Pick, 'getState' | 'extra'>, ): GetPendingMeta }, { @@ -341,14 +348,14 @@ export type AsyncThunkOptions< arg: ThunkArg requestId: string }, - api: Pick, 'getState' | 'extra'> + api: Pick, 'getState' | 'extra'>, ): GetPendingMeta } > export type AsyncThunkPendingActionCreator< ThunkArg, - ThunkApiConfig = {} + ThunkApiConfig = {}, > = ActionCreatorWithPreparedPayload< [string, ThunkArg, GetPendingMeta?], undefined, @@ -363,14 +370,14 @@ export type AsyncThunkPendingActionCreator< export type AsyncThunkRejectedActionCreator< ThunkArg, - ThunkApiConfig = {} + ThunkApiConfig = {}, > = ActionCreatorWithPreparedPayload< [ Error | null, string, ThunkArg, GetRejectValue?, - GetRejectedMeta? + GetRejectedMeta?, ], GetRejectValue | undefined, string, @@ -392,7 +399,7 @@ export type AsyncThunkRejectedActionCreator< export type AsyncThunkFulfilledActionCreator< Returned, ThunkArg, - ThunkApiConfig = {} + ThunkApiConfig = {}, > = ActionCreatorWithPreparedPayload< [Returned, string, ThunkArg, GetFulfilledMeta?], Returned, @@ -414,7 +421,7 @@ export type AsyncThunkFulfilledActionCreator< export type AsyncThunk< Returned, ThunkArg, - ThunkApiConfig extends AsyncThunkConfig + ThunkApiConfig extends AsyncThunkConfig, > = AsyncThunkActionCreator & { pending: AsyncThunkPendingActionCreator rejected: AsyncThunkRejectedActionCreator @@ -425,7 +432,7 @@ export type AsyncThunk< > // matchSettled? settled: ( - action: any + action: any, ) => action is ReturnType< | AsyncThunkRejectedActionCreator | AsyncThunkFulfilledActionCreator @@ -454,7 +461,7 @@ type CreateAsyncThunk = { ThunkArg, CurriedThunkApiConfig >, - options?: AsyncThunkOptions + options?: AsyncThunkOptions, ): AsyncThunk /** @@ -475,7 +482,7 @@ type CreateAsyncThunk = { options?: AsyncThunkOptions< ThunkArg, OverrideThunkApiConfigs - > + >, ): AsyncThunk< Returned, ThunkArg, @@ -491,7 +498,7 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { function createAsyncThunk< Returned, ThunkArg, - ThunkApiConfig extends AsyncThunkConfig + ThunkApiConfig extends AsyncThunkConfig, >( typePrefix: string, payloadCreator: AsyncThunkPayloadCreator< @@ -499,7 +506,7 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { ThunkArg, ThunkApiConfig >, - options?: AsyncThunkOptions + options?: AsyncThunkOptions, ): AsyncThunk { type RejectedValue = GetRejectValue type PendingMeta = GetPendingMeta @@ -516,7 +523,7 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { payload: Returned, requestId: string, arg: ThunkArg, - meta?: FulfilledMeta + meta?: FulfilledMeta, ) => ({ payload, meta: { @@ -525,7 +532,7 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { requestId, requestStatus: 'fulfilled' as const, }, - }) + }), ) const pending: AsyncThunkPendingActionCreator = @@ -539,7 +546,7 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { requestId, requestStatus: 'pending' as const, }, - }) + }), ) const rejected: AsyncThunkRejectedActionCreator = @@ -550,11 +557,11 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { requestId: string, arg: ThunkArg, payload?: RejectedValue, - meta?: RejectedMeta + meta?: RejectedMeta, ) => ({ payload, error: ((options && options.serializeError) || miniSerializeError)( - error || 'Rejected' + error || 'Rejected', ) as GetSerializedErrorType, meta: { ...((meta as any) || {}), @@ -565,11 +572,11 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { aborted: error?.name === 'AbortError', condition: error?.name === 'ConditionError', }, - }) + }), ) function actionCreator( - arg: ThunkArg + arg: ThunkArg, ): AsyncThunkAction { return (dispatch, getState, extra) => { const requestId = options?.idGenerator @@ -577,6 +584,7 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { : nanoid() const abortController = new AbortController() + let abortHandler: (() => void) | undefined let abortReason: string | undefined function abort(reason?: string) { @@ -600,23 +608,24 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { } } - const abortedPromise = new Promise((_, reject) => - abortController.signal.addEventListener('abort', () => + const abortedPromise = new Promise((_, reject) => { + abortHandler = () => { reject({ name: 'AbortError', message: abortReason || 'Aborted', }) - ) - ) + } + abortController.signal.addEventListener('abort', abortHandler) + }) dispatch( pending( requestId, arg, options?.getPendingMeta?.( { requestId, arg }, - { getState, extra } - ) - ) as any + { getState, extra }, + ), + ) as any, ) finalAction = await Promise.race([ abortedPromise, @@ -630,14 +639,14 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { abort, rejectWithValue: (( value: RejectedValue, - meta?: RejectedMeta + meta?: RejectedMeta, ) => { return new RejectWithValue(value, meta) }) as any, fulfillWithValue: ((value: unknown, meta?: FulfilledMeta) => { return new FulfillWithMeta(value, meta) }) as any, - }) + }), ).then((result) => { if (result instanceof RejectWithValue) { throw result @@ -653,6 +662,10 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { err instanceof RejectWithValue ? rejected(null, requestId, arg, err.payload, err.meta) : rejected(err as any, requestId, arg) + } finally { + if (abortHandler) { + abortController.signal.removeEventListener('abort', abortHandler) + } } // We dispatch the result action _after_ the catch, to avoid having any errors // here get swallowed by the try/catch block, @@ -670,7 +683,7 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { } return finalAction })() - return Object.assign(promise as Promise, { + return Object.assign(promise as SafePromise, { abort, requestId, arg, @@ -693,7 +706,7 @@ export const createAsyncThunk = /* @__PURE__ */ (() => { fulfilled, settled: isAnyOf(rejected, fulfilled), typePrefix, - } + }, ) } createAsyncThunk.withTypes = () => createAsyncThunk @@ -716,7 +729,7 @@ type UnwrappedActionPayload = Exclude< * @public */ export function unwrapResult( - action: R + action: R, ): UnwrappedActionPayload { if (action.meta && action.meta.rejectedWithValue) { throw action.payload diff --git a/packages/toolkit/src/createDraftSafeSelector.ts b/packages/toolkit/src/createDraftSafeSelector.ts index 6fe8d267d2..825fc0db32 100644 --- a/packages/toolkit/src/createDraftSafeSelector.ts +++ b/packages/toolkit/src/createDraftSafeSelector.ts @@ -5,13 +5,17 @@ export const createDraftSafeSelectorCreator: typeof createSelectorCreator = ( ...args: unknown[] ) => { const createSelector = (createSelectorCreator as any)(...args) - return (...args: unknown[]) => { - const selector = createSelector(...args) - const wrappedSelector = (value: unknown, ...rest: unknown[]) => - selector(isDraft(value) ? current(value) : value, ...rest) - Object.assign(wrappedSelector, selector) - return wrappedSelector as any - } + const createDraftSafeSelector = Object.assign( + (...args: unknown[]) => { + const selector = createSelector(...args) + const wrappedSelector = (value: unknown, ...rest: unknown[]) => + selector(isDraft(value) ? current(value) : value, ...rest) + Object.assign(wrappedSelector, selector) + return wrappedSelector as any + }, + { withTypes: () => createDraftSafeSelector }, + ) + return createDraftSafeSelector } /** diff --git a/packages/toolkit/src/createReducer.ts b/packages/toolkit/src/createReducer.ts index f0f2ac50be..564a1f13b0 100644 --- a/packages/toolkit/src/createReducer.ts +++ b/packages/toolkit/src/createReducer.ts @@ -47,7 +47,7 @@ export type ActionMatcherDescriptionCollection = Array< */ export type CaseReducer = ( state: Draft, - action: A + action: A, ) => NoInfer | void | Draft> /** @@ -139,12 +139,12 @@ const reducer = createReducer( */ export function createReducer>( initialState: S | (() => S), - mapOrBuilderCallback: (builder: ActionReducerMapBuilder) => void + mapOrBuilderCallback: (builder: ActionReducerMapBuilder) => void, ): ReducerWithInitialState { if (process.env.NODE_ENV !== 'production') { if (typeof mapOrBuilderCallback === 'object') { throw new Error( - "The object notation for `createReducer` has been removed. Please use the 'builder callback' notation instead: https://redux-toolkit.js.org/api/createReducer" + "The object notation for `createReducer` has been removed. Please use the 'builder callback' notation instead: https://redux-toolkit.js.org/api/createReducer", ) } } @@ -196,7 +196,7 @@ export function createReducer>( return previousState } throw Error( - 'A case reducer on a non-draftable value must not return undefined' + 'A case reducer on a non-draftable value must not return undefined', ) } diff --git a/packages/toolkit/src/createSlice.ts b/packages/toolkit/src/createSlice.ts index ea680a9e6e..441fbbcc6a 100644 --- a/packages/toolkit/src/createSlice.ts +++ b/packages/toolkit/src/createSlice.ts @@ -50,7 +50,7 @@ export interface Slice< CaseReducers extends SliceCaseReducers = SliceCaseReducers, Name extends string = string, ReducerPath extends string = Name, - Selectors extends SliceSelectors = SliceSelectors + Selectors extends SliceSelectors = SliceSelectors, > { /** * The slice name. @@ -88,14 +88,13 @@ export interface Slice< /** * Get localised slice selectors (expects to be called with *just* the slice's state as the first parameter) */ - getSelectors(this: this): Id> + getSelectors(): Id> /** * Get globalised slice selectors (`selectState` callback is expected to receive first parameter and return slice state) */ getSelectors( - this: this, - selectState: (this: this, rootState: RootState) => State + selectState: (rootState: RootState) => State, ): Id> /** @@ -103,7 +102,7 @@ export interface Slice< * * Equivalent to `slice.getSelectors((state: RootState) => state[slice.reducerPath])`. */ - selectors: Id< + get selectors(): Id< SliceDefinedSelectors > @@ -115,10 +114,10 @@ export interface Slice< injectable: { inject: ( slice: { reducerPath: string; reducer: Reducer }, - config?: InjectConfig + config?: InjectConfig, ) => void }, - config?: InjectIntoConfig + config?: InjectIntoConfig, ): InjectedSlice /** @@ -126,7 +125,7 @@ export interface Slice< * * Will throw an error if slice is not found. */ - selectSlice(this: this, state: { [K in ReducerPath]: State }): State + selectSlice(state: { [K in ReducerPath]: State }): State } /** @@ -139,7 +138,7 @@ interface InjectedSlice< CaseReducers extends SliceCaseReducers = SliceCaseReducers, Name extends string = string, ReducerPath extends string = Name, - Selectors extends SliceSelectors = SliceSelectors + Selectors extends SliceSelectors = SliceSelectors, > extends Omit< Slice, 'getSelectors' | 'selectors' @@ -153,7 +152,7 @@ interface InjectedSlice< * Get globalised slice selectors (`selectState` callback is expected to receive first parameter and return slice state) */ getSelectors( - selectState: (this: this, rootState: RootState) => State | undefined + selectState: (rootState: RootState) => State | undefined, ): Id> /** @@ -161,7 +160,7 @@ interface InjectedSlice< * * Equivalent to `slice.getSelectors((state: RootState) => state[slice.name])`. */ - selectors: Id< + get selectors(): Id< SliceDefinedSelectors< State, Selectors, @@ -187,7 +186,7 @@ export interface CreateSliceOptions< CR extends SliceCaseReducers = SliceCaseReducers, Name extends string = string, ReducerPath extends string = Name, - Selectors extends SliceSelectors = SliceSelectors + Selectors extends SliceSelectors = SliceSelectors, > { /** * The slice's name. Used to namespace the generated action types. @@ -275,7 +274,7 @@ interface ReducerDefinition { export interface CaseReducerDefinition< S = any, - A extends Action = UnknownAction + A extends Action = UnknownAction, > extends CaseReducer, ReducerDefinition {} @@ -291,7 +290,7 @@ export type CaseReducerWithPrepare = { export interface CaseReducerWithPrepareDefinition< State, - Action extends PayloadAction + Action extends PayloadAction, > extends CaseReducerWithPrepare, ReducerDefinition {} @@ -299,7 +298,7 @@ export interface AsyncThunkSliceReducerConfig< State, ThunkArg extends any, Returned = unknown, - ThunkApiConfig extends AsyncThunkConfig = {} + ThunkApiConfig extends AsyncThunkConfig = {}, > { pending?: CaseReducer< State, @@ -326,7 +325,7 @@ export interface AsyncThunkSliceReducerDefinition< State, ThunkArg extends any, Returned = unknown, - ThunkApiConfig extends AsyncThunkConfig = {} + ThunkApiConfig extends AsyncThunkConfig = {}, > extends AsyncThunkSliceReducerConfig< State, ThunkArg, @@ -348,7 +347,8 @@ type PreventCircular = { interface AsyncThunkCreator< State, - CurriedThunkApiConfig extends PreventCircular = PreventCircular + CurriedThunkApiConfig extends + PreventCircular = PreventCircular, > { ( payloadCreator: AsyncThunkPayloadCreator< @@ -361,7 +361,7 @@ interface AsyncThunkCreator< ThunkArg, Returned, CurriedThunkApiConfig - > + >, ): AsyncThunkSliceReducerDefinition< State, ThunkArg, @@ -371,7 +371,7 @@ interface AsyncThunkCreator< < Returned, ThunkArg, - ThunkApiConfig extends PreventCircular = {} + ThunkApiConfig extends PreventCircular = {}, >( payloadCreator: AsyncThunkPayloadCreator< Returned, @@ -383,10 +383,10 @@ interface AsyncThunkCreator< ThunkArg, Returned, ThunkApiConfig - > + >, ): AsyncThunkSliceReducerDefinition withTypes< - ThunkApiConfig extends PreventCircular + ThunkApiConfig extends PreventCircular, >(): AsyncThunkCreator< State, OverrideThunkApiConfigs @@ -395,10 +395,10 @@ interface AsyncThunkCreator< export interface ReducerCreators { reducer( - caseReducer: CaseReducer + caseReducer: CaseReducer, ): CaseReducerDefinition reducer( - caseReducer: CaseReducer> + caseReducer: CaseReducer>, ): CaseReducerDefinition> asyncThunk: AsyncThunkCreator @@ -408,7 +408,7 @@ export interface ReducerCreators { reducer: CaseReducer< State, ReturnType<_ActionCreatorWithPreparedPayload> - > + >, ): { _reducerDefinitionType: ReducerType.reducerWithPrepare prepare: Prepare @@ -449,7 +449,7 @@ export type SliceSelectors = { type SliceActionType< SliceName extends string, - ActionName extends keyof any + ActionName extends keyof any, > = ActionName extends string | number ? `${SliceName}/${ActionName}` : string /** @@ -459,7 +459,7 @@ type SliceActionType< */ export type CaseReducerActions< CaseReducers extends SliceCaseReducers, - SliceName extends string + SliceName extends string, > = { [Type in keyof CaseReducers]: CaseReducers[Type] extends infer Definition ? Definition extends { prepare: any } @@ -468,21 +468,21 @@ export type CaseReducerActions< SliceActionType > : Definition extends AsyncThunkSliceReducerDefinition< - any, - infer ThunkArg, - infer Returned, - infer ThunkApiConfig - > - ? AsyncThunk - : Definition extends { reducer: any } - ? ActionCreatorForCaseReducer< - Definition['reducer'], - SliceActionType - > - : ActionCreatorForCaseReducer< - Definition, - SliceActionType - > + any, + infer ThunkArg, + infer Returned, + infer ThunkApiConfig + > + ? AsyncThunk + : Definition extends { reducer: any } + ? ActionCreatorForCaseReducer< + Definition['reducer'], + SliceActionType + > + : ActionCreatorForCaseReducer< + Definition, + SliceActionType + > : never } @@ -493,7 +493,7 @@ export type CaseReducerActions< */ type ActionCreatorForCaseReducerWithPrepare< CR extends { prepare: any }, - Type extends string + Type extends string, > = _ActionCreatorWithPreparedPayload /** @@ -503,7 +503,7 @@ type ActionCreatorForCaseReducerWithPrepare< */ type ActionCreatorForCaseReducer = CR extends ( state: any, - action: infer Action + action: infer Action, ) => any ? Action extends { payload: infer P } ? PayloadActionCreator @@ -526,20 +526,17 @@ type SliceDefinedCaseReducers> = { > > : Definition extends { - reducer: infer Reducer - } - ? Reducer - : Definition + reducer: infer Reducer + } + ? Reducer + : Definition : never } -type RemappedSelector = S extends Selector< - any, - infer R, - infer P -> - ? Selector & { unwrapped: S } - : never +type RemappedSelector = + S extends Selector + ? Selector & { unwrapped: S } + : never /** * Extracts the final selector type from the `selectors` object. @@ -549,7 +546,7 @@ type RemappedSelector = S extends Selector< type SliceDefinedSelectors< State, Selectors extends SliceSelectors, - RootState + RootState, > = { [K in keyof Selectors as string extends K ? never : K]: RemappedSelector< Selectors[K], @@ -571,17 +568,16 @@ type SliceDefinedSelectors< */ export type ValidateSliceCaseReducers< S, - ACR extends SliceCaseReducers -> = ACR & - { - [T in keyof ACR]: ACR[T] extends { - reducer(s: S, action?: infer A): any - } - ? { - prepare(...a: never[]): Omit - } - : {} + ACR extends SliceCaseReducers, +> = ACR & { + [T in keyof ACR]: ACR[T] extends { + reducer(s: S, action?: infer A): any } + ? { + prepare(...a: never[]): Omit + } + : {} +} function getType(slice: string, actionKey: string): string { return `${slice}/${actionKey}` @@ -600,7 +596,7 @@ export function buildCreateSlice({ creators }: BuildCreateSliceConfig = {}) { CaseReducers extends SliceCaseReducers, Name extends string, Selectors extends SliceSelectors, - ReducerPath extends string = Name + ReducerPath extends string = Name, >( options: CreateSliceOptions< State, @@ -608,7 +604,7 @@ export function buildCreateSlice({ creators }: BuildCreateSliceConfig = {}) { Name, ReducerPath, Selectors - > + >, ): Slice { const { name, reducerPath = name as unknown as ReducerPath } = options if (!name) { @@ -621,7 +617,7 @@ export function buildCreateSlice({ creators }: BuildCreateSliceConfig = {}) { ) { if (options.initialState === undefined) { console.error( - 'You must provide an `initialState` value that is not `undefined`. You may have misspelled `initialState`' + 'You must provide an `initialState` value that is not `undefined`. You may have misspelled `initialState`', ) } } @@ -643,7 +639,7 @@ export function buildCreateSlice({ creators }: BuildCreateSliceConfig = {}) { const contextMethods: ReducerHandlingContextMethods = { addCase( typeOrActionCreator: string | TypedActionCreator, - reducer: CaseReducer + reducer: CaseReducer, ) { const type = typeof typeOrActionCreator === 'string' @@ -651,13 +647,13 @@ export function buildCreateSlice({ creators }: BuildCreateSliceConfig = {}) { : typeOrActionCreator.type if (!type) { throw new Error( - '`context.addCase` cannot be called with an empty action type' + '`context.addCase` cannot be called with an empty action type', ) } if (type in context.sliceCaseReducersByType) { throw new Error( '`context.addCase` cannot be called with two reducers for the same action type: ' + - type + type, ) } context.sliceCaseReducersByType[type] = reducer @@ -689,13 +685,13 @@ export function buildCreateSlice({ creators }: BuildCreateSliceConfig = {}) { reducerDetails, reducerDefinition, contextMethods, - cAT + cAT, ) } else { handleNormalReducerDefinition( reducerDetails, reducerDefinition, - contextMethods + contextMethods, ) } }) @@ -704,7 +700,7 @@ export function buildCreateSlice({ creators }: BuildCreateSliceConfig = {}) { if (process.env.NODE_ENV !== 'production') { if (typeof options.extraReducers === 'object') { throw new Error( - "The object notation for `createSlice.extraReducers` has been removed. Please use the 'builder callback' notation instead: https://redux-toolkit.js.org/api/createSlice" + "The object notation for `createSlice.extraReducers` has been removed. Please use the 'builder callback' notation instead: https://redux-toolkit.js.org/api/createSlice", ) } } @@ -740,8 +736,8 @@ export function buildCreateSlice({ creators }: BuildCreateSliceConfig = {}) { const selectSelf = (state: State) => state - const injectedSelectorCache = new WeakMap< - Slice, + const injectedSelectorCache = new Map< + boolean, WeakMap< (rootState: any) => State | undefined, Record any> @@ -750,23 +746,42 @@ export function buildCreateSlice({ creators }: BuildCreateSliceConfig = {}) { let _reducer: ReducerWithInitialState - const slice: Slice = { - name, - reducerPath, - reducer(state, action) { - if (!_reducer) _reducer = buildReducer() + function reducer(state: State | undefined, action: UnknownAction) { + if (!_reducer) _reducer = buildReducer() - return _reducer(state, action) - }, - actions: context.actionCreators as any, - caseReducers: context.sliceCaseReducersByName as any, - getInitialState() { - if (!_reducer) _reducer = buildReducer() + return _reducer(state, action) + } - return _reducer.getInitialState() - }, - getSelectors(selectState: (rootState: any) => State = selectSelf) { - const selectorCache = emplace(injectedSelectorCache, this, { + function getInitialState() { + if (!_reducer) _reducer = buildReducer() + + return _reducer.getInitialState() + } + + function makeSelectorProps( + reducerPath: CurrentReducerPath, + injected = false, + ): Pick< + Slice, + 'getSelectors' | 'selectors' | 'selectSlice' | 'reducerPath' + > { + function selectSlice(state: { [K in CurrentReducerPath]: State }) { + let sliceState = state[reducerPath] + if (typeof sliceState === 'undefined') { + if (injected) { + sliceState = getInitialState() + } else if (process.env.NODE_ENV !== 'production') { + throw new Error( + 'selectSlice returned undefined for an uninjected slice reducer', + ) + } + } + return sliceState + } + function getSelectors( + selectState: (rootState: any) => State = selectSelf, + ) { + const selectorCache = emplace(injectedSelectorCache, injected, { insert: () => new WeakMap(), }) @@ -774,42 +789,42 @@ export function buildCreateSlice({ creators }: BuildCreateSliceConfig = {}) { insert: () => { const map: Record> = {} for (const [name, selector] of Object.entries( - options.selectors ?? {} + options.selectors ?? {}, )) { map[name] = wrapSelector( - this, selector, selectState, - this !== slice + getInitialState, + injected, ) } return map }, }) as any - }, - selectSlice(state) { - let sliceState = state[this.reducerPath] - if (typeof sliceState === 'undefined') { - // check if injectInto has been called - if (this !== slice) { - sliceState = this.getInitialState() - } else if (process.env.NODE_ENV !== 'production') { - throw new Error( - 'selectSlice returned undefined for an uninjected slice reducer' - ) - } - } - return sliceState - }, - get selectors() { - return this.getSelectors(this.selectSlice) - }, + } + return { + reducerPath, + getSelectors, + get selectors() { + return getSelectors(selectSlice) + }, + selectSlice, + } + } + + const slice: Slice = { + name, + reducer, + actions: context.actionCreators as any, + caseReducers: context.sliceCaseReducersByName as any, + getInitialState, + ...makeSelectorProps(reducerPath), injectInto(injectable, { reducerPath: pathOpt, ...config } = {}) { - const reducerPath = pathOpt ?? this.reducerPath - injectable.inject({ reducerPath, reducer: this.reducer }, config) + const newReducerPath = pathOpt ?? reducerPath + injectable.inject({ reducerPath: newReducerPath, reducer }, config) return { - ...this, - reducerPath, + ...slice, + ...makeSelectorProps(newReducerPath, true), } as any }, } @@ -818,19 +833,19 @@ export function buildCreateSlice({ creators }: BuildCreateSliceConfig = {}) { } function wrapSelector>( - slice: Slice, selector: S, selectState: Selector, - injected?: boolean + getInitialState: () => State, + injected?: boolean, ) { function wrapper(rootState: NewState, ...args: any[]) { - let sliceState = selectState.call(slice, rootState) + let sliceState = selectState(rootState) if (typeof sliceState === 'undefined') { if (injected) { - sliceState = slice.getInitialState() + sliceState = getInitialState() } else if (process.env.NODE_ENV !== 'production') { throw new Error( - 'selectState returned undefined for an uninjected slice reducer' + 'selectState returned undefined for an uninjected slice reducer', ) } } @@ -872,7 +887,7 @@ interface ReducerHandlingContextMethods { */ addCase>( actionCreator: ActionCreator, - reducer: CaseReducer> + reducer: CaseReducer>, ): ReducerHandlingContextMethods /** * Adds a case reducer to handle a single action type. @@ -881,7 +896,7 @@ interface ReducerHandlingContextMethods { */ addCase>( type: Type, - reducer: CaseReducer + reducer: CaseReducer, ): ReducerHandlingContextMethods /** @@ -897,7 +912,7 @@ interface ReducerHandlingContextMethods { */ addMatcher( matcher: TypeGuard, - reducer: CaseReducer + reducer: CaseReducer, ): ReducerHandlingContextMethods /** * Add an action to be exposed under the final `slice.actions` key. @@ -912,7 +927,7 @@ interface ReducerHandlingContextMethods { */ exposeAction( name: string, - actionCreator: Function + actionCreator: Function, ): ReducerHandlingContextMethods /** * Add a case reducer to be exposed under the final `slice.caseReducers` key. @@ -932,7 +947,7 @@ interface ReducerHandlingContextMethods { | Pick< AsyncThunkSliceReducerDefinition, 'fulfilled' | 'rejected' | 'pending' | 'settled' - > + >, ): ReducerHandlingContextMethods } @@ -948,7 +963,7 @@ interface ReducerDetails { function buildReducerCreators(): ReducerCreators { function asyncThunk( payloadCreator: AsyncThunkPayloadCreator, - config: AsyncThunkSliceReducerConfig + config: AsyncThunkSliceReducerConfig, ): AsyncThunkSliceReducerDefinition { return { _reducerDefinitionType: ReducerType.asyncThunk, @@ -969,7 +984,7 @@ function buildReducerCreators(): ReducerCreators { }[caseReducer.name], { _reducerDefinitionType: ReducerType.reducer, - } as const + } as const, ) }, preparedReducer(prepare, reducer) { @@ -988,7 +1003,7 @@ function handleNormalReducerDefinition( maybeReducerWithPrepare: | CaseReducer | CaseReducerWithPrepare>, - context: ReducerHandlingContextMethods + context: ReducerHandlingContextMethods, ) { let caseReducer: CaseReducer let prepareCallback: PrepareAction | undefined @@ -998,7 +1013,7 @@ function handleNormalReducerDefinition( !isCaseReducerWithPrepareDefinition(maybeReducerWithPrepare) ) { throw new Error( - 'Please use the `create.preparedReducer` notation for prepared action creators with the `create` notation.' + 'Please use the `create.preparedReducer` notation for prepared action creators with the `create` notation.', ) } caseReducer = maybeReducerWithPrepare.reducer @@ -1011,18 +1026,20 @@ function handleNormalReducerDefinition( .exposeCaseReducer(reducerName, caseReducer) .exposeAction( reducerName, - prepareCallback ? createAction(type, prepareCallback) : createAction(type) + prepareCallback + ? createAction(type, prepareCallback) + : createAction(type), ) } function isAsyncThunkSliceReducerDefinition( - reducerDefinition: any + reducerDefinition: any, ): reducerDefinition is AsyncThunkSliceReducerDefinition { return reducerDefinition._reducerDefinitionType === ReducerType.asyncThunk } function isCaseReducerWithPrepareDefinition( - reducerDefinition: any + reducerDefinition: any, ): reducerDefinition is CaseReducerWithPrepareDefinition { return ( reducerDefinition._reducerDefinitionType === ReducerType.reducerWithPrepare @@ -1033,12 +1050,12 @@ function handleThunkCaseReducerDefinition( { type, reducerName }: ReducerDetails, reducerDefinition: AsyncThunkSliceReducerDefinition, context: ReducerHandlingContextMethods, - cAT: typeof _createAsyncThunk | undefined + cAT: typeof _createAsyncThunk | undefined, ) { if (!cAT) { throw new Error( 'Cannot use `create.asyncThunk` in the built-in `createSlice`. ' + - 'Use `buildCreateSlice({ creators: { asyncThunk: asyncThunkCreator } })` to create a customised version of `createSlice`.' + 'Use `buildCreateSlice({ creators: { asyncThunk: asyncThunkCreator } })` to create a customised version of `createSlice`.', ) } const { payloadCreator, fulfilled, pending, rejected, settled, options } = diff --git a/packages/toolkit/src/dynamicMiddleware/index.ts b/packages/toolkit/src/dynamicMiddleware/index.ts index 556998d142..2ad15b6c3e 100644 --- a/packages/toolkit/src/dynamicMiddleware/index.ts +++ b/packages/toolkit/src/dynamicMiddleware/index.ts @@ -18,9 +18,9 @@ import type { const createMiddlewareEntry = < State = any, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, >( - middleware: Middleware + middleware: Middleware, ): MiddlewareEntry => ({ id: nanoid(), middleware, @@ -34,7 +34,7 @@ const matchInstance = export const createDynamicMiddleware = < State = any, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, >(): DynamicMiddlewareInstance => { const instanceId = nanoid() const middlewareMap = new Map>() @@ -47,9 +47,9 @@ export const createDynamicMiddleware = < meta: { instanceId, }, - }) + }), ), - { withTypes: () => withMiddleware } + { withTypes: () => withMiddleware }, ) as WithMiddleware const addMiddleware = Object.assign( @@ -57,7 +57,7 @@ export const createDynamicMiddleware = < middlewares.forEach((middleware) => { let entry = find( Array.from(middlewareMap.values()), - (entry) => entry.middleware === middleware + (entry) => entry.middleware === middleware, ) if (!entry) { entry = createMiddlewareEntry(middleware) @@ -65,12 +65,12 @@ export const createDynamicMiddleware = < middlewareMap.set(entry.id, entry) }) }, - { withTypes: () => addMiddleware } + { withTypes: () => addMiddleware }, ) as AddMiddleware const getFinalMiddleware: Middleware<{}, State, Dispatch> = (api) => { const appliedMiddleware = Array.from(middlewareMap.values()).map((entry) => - emplace(entry.applied, api, { insert: () => entry.middleware(api) }) + emplace(entry.applied, api, { insert: () => entry.middleware(api) }), ) return compose(...appliedMiddleware) } diff --git a/packages/toolkit/src/dynamicMiddleware/react/index.ts b/packages/toolkit/src/dynamicMiddleware/react/index.ts index ed2c4d9fe3..83a8194606 100644 --- a/packages/toolkit/src/dynamicMiddleware/react/index.ts +++ b/packages/toolkit/src/dynamicMiddleware/react/index.ts @@ -23,23 +23,23 @@ import type { export type UseDispatchWithMiddlewareHook< Middlewares extends Middleware[] = [], State = any, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, > = () => TSHelpersExtractDispatchExtensions & Dispatch export type CreateDispatchWithMiddlewareHook< State = any, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, > = { < Middlewares extends [ Middleware, - ...Middleware[] - ] + ...Middleware[], + ], >( ...middlewares: Middlewares ): UseDispatchWithMiddlewareHook withTypes< - MiddlewareConfig extends MiddlewareApiConfig + MiddlewareConfig extends MiddlewareApiConfig, >(): CreateDispatchWithMiddlewareHook< GetState, GetDispatch @@ -51,12 +51,12 @@ type ActionFromDispatch> = interface ReactDynamicMiddlewareInstance< State = any, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, > extends DynamicMiddlewareInstance { createDispatchWithMiddlewareHookFactory: ( context?: Context< ReactReduxContextValue> - > + >, ) => CreateDispatchWithMiddlewareHook createDispatchWithMiddlewareHook: CreateDispatchWithMiddlewareHook< State, @@ -66,14 +66,14 @@ interface ReactDynamicMiddlewareInstance< export const createDynamicMiddleware = < State = any, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, >(): ReactDynamicMiddlewareInstance => { const instance = cDM() const createDispatchWithMiddlewareHookFactory = ( // @ts-ignore context: Context< ReactReduxContextValue> - > = ReactReduxContext + > = ReactReduxContext, ) => { const useDispatch = // @ts-ignore @@ -81,7 +81,7 @@ export const createDynamicMiddleware = < ? useDefaultDispatch : createDispatchHook(context) function createDispatchWithMiddlewareHook< - Middlewares extends Middleware[] + Middlewares extends Middleware[], >(...middlewares: Middlewares) { instance.addMiddleware(...middlewares) return useDispatch diff --git a/packages/toolkit/src/dynamicMiddleware/tests/index.test-d.ts b/packages/toolkit/src/dynamicMiddleware/tests/index.test-d.ts new file mode 100644 index 0000000000..7273273530 --- /dev/null +++ b/packages/toolkit/src/dynamicMiddleware/tests/index.test-d.ts @@ -0,0 +1,95 @@ +import type { Action, Middleware, UnknownAction } from 'redux' +import type { ThunkDispatch } from 'redux-thunk' +import { configureStore } from '../../configureStore' +import { createDynamicMiddleware } from '../index' + +const untypedInstance = createDynamicMiddleware() + +interface AppDispatch extends ThunkDispatch { + (n: 1): 1 +} + +const typedInstance = createDynamicMiddleware() + +declare const staticMiddleware: Middleware<(n: 1) => 1> + +const store = configureStore({ + reducer: () => 0, + middleware: (gDM) => + gDM().prepend(typedInstance.middleware).concat(staticMiddleware), +}) + +declare const compatibleMiddleware: Middleware<{}, number, AppDispatch> +declare const incompatibleMiddleware: Middleware<{}, string, AppDispatch> + +declare const addedMiddleware: Middleware<(n: 2) => 2> + +describe('type tests', () => { + test('instance typed at creation ensures middleware compatibility with store', () => { + const store = configureStore({ + reducer: () => '', + // @ts-expect-error + middleware: (gDM) => gDM().prepend(typedInstance.middleware), + }) + }) + + test('instance typed at creation enforces correct middleware type', () => { + typedInstance.addMiddleware( + compatibleMiddleware, + // @ts-expect-error + incompatibleMiddleware, + ) + + const dispatch = store.dispatch( + typedInstance.withMiddleware( + compatibleMiddleware, + // @ts-expect-error + incompatibleMiddleware, + ), + ) + }) + + test('withTypes() enforces correct middleware type', () => { + const addMiddleware = untypedInstance.addMiddleware.withTypes<{ + state: number + dispatch: AppDispatch + }>() + + addMiddleware( + compatibleMiddleware, + // @ts-expect-error + incompatibleMiddleware, + ) + + const withMiddleware = untypedInstance.withMiddleware.withTypes<{ + state: number + dispatch: AppDispatch + }>() + + const dispatch = store.dispatch( + withMiddleware( + compatibleMiddleware, + // @ts-expect-error + incompatibleMiddleware, + ), + ) + }) + + test('withMiddleware returns typed dispatch, with any applicable extensions', () => { + const dispatch = store.dispatch( + typedInstance.withMiddleware(addedMiddleware), + ) + + // standard + expectTypeOf(dispatch({ type: 'foo' })).toEqualTypeOf>() + + // thunk + expectTypeOf(dispatch(() => 'foo')).toBeString() + + // static + expectTypeOf(dispatch(1)).toEqualTypeOf<1>() + + // added + expectTypeOf(dispatch(2)).toEqualTypeOf<2>() + }) +}) diff --git a/packages/toolkit/src/dynamicMiddleware/tests/index.test.ts b/packages/toolkit/src/dynamicMiddleware/tests/index.test.ts index 7f3e0885a2..5c97d834d3 100644 --- a/packages/toolkit/src/dynamicMiddleware/tests/index.test.ts +++ b/packages/toolkit/src/dynamicMiddleware/tests/index.test.ts @@ -20,7 +20,7 @@ const matchId = action.payload === id export const makeProbeableMiddleware = ( - id: Id + id: Id, ): Middleware<{ (action: PayloadAction): Id }> => { @@ -65,7 +65,7 @@ describe('createDynamicMiddleware', () => { expect(store.dispatch(probeMiddleware(2))).toEqual(probeMiddleware(2)) const dispatch = store.dispatch( - dynamicInstance.withMiddleware(makeProbeableMiddleware(2)) + dynamicInstance.withMiddleware(makeProbeableMiddleware(2)), ) expect(dispatch).toEqual(expect.any(Function)) diff --git a/packages/toolkit/src/dynamicMiddleware/tests/index.typetest.ts b/packages/toolkit/src/dynamicMiddleware/tests/index.typetest.ts deleted file mode 100644 index 386b1aaa9d..0000000000 --- a/packages/toolkit/src/dynamicMiddleware/tests/index.typetest.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* eslint-disable no-lone-blocks */ -import type { Action, UnknownAction, Middleware } from 'redux' -import type { ThunkDispatch } from 'redux-thunk' -import { createDynamicMiddleware } from '../index' -import { configureStore } from '../../configureStore' -import { expectExactType, expectType } from '../../tests/helpers' - -const untypedInstance = createDynamicMiddleware() - -interface AppDispatch extends ThunkDispatch { - (n: 1): 1 -} - -const typedInstance = createDynamicMiddleware() - -/** - * Test: instance typed at creation ensures middleware compatibility with store - */ -{ - const store = configureStore({ - reducer: () => '', - // @ts-expect-error - middleware: (gDM) => gDM().prepend(typedInstance.middleware), - }) -} - -declare const staticMiddleware: Middleware<(n: 1) => 1> - -const store = configureStore({ - reducer: () => 0, - middleware: (gDM) => - gDM().prepend(typedInstance.middleware).concat(staticMiddleware), -}) - -declare const compatibleMiddleware: Middleware<{}, number, AppDispatch> -declare const incompatibleMiddleware: Middleware<{}, string, AppDispatch> - -/** - * Test: instance typed at creation enforces correct middleware type - */ -{ - typedInstance.addMiddleware( - compatibleMiddleware, - // @ts-expect-error - incompatibleMiddleware - ) - - const dispatch = store.dispatch( - typedInstance.withMiddleware( - compatibleMiddleware, - // @ts-expect-error - incompatibleMiddleware - ) - ) -} - -/** - * Test: withTypes() enforces correct middleware type - */ -{ - const addMiddleware = untypedInstance.addMiddleware.withTypes<{ - state: number - dispatch: AppDispatch - }>() - - addMiddleware( - compatibleMiddleware, - // @ts-expect-error - incompatibleMiddleware - ) - - const withMiddleware = untypedInstance.withMiddleware.withTypes<{ - state: number - dispatch: AppDispatch - }>() - - const dispatch = store.dispatch( - withMiddleware( - compatibleMiddleware, - // @ts-expect-error - incompatibleMiddleware - ) - ) -} - -declare const addedMiddleware: Middleware<(n: 2) => 2> - -/** - * Test: withMiddleware returns typed dispatch, with any applicable extensions - */ -{ - const dispatch = store.dispatch(typedInstance.withMiddleware(addedMiddleware)) - - // standard - expectType>(dispatch({ type: 'foo' })) - // thunk - expectType(dispatch(() => 'foo')) - // static - expectExactType(1 as const)(dispatch(1)) - // added - expectExactType(2 as const)(dispatch(2)) -} diff --git a/packages/toolkit/src/dynamicMiddleware/tests/react.test-d.ts b/packages/toolkit/src/dynamicMiddleware/tests/react.test-d.ts new file mode 100644 index 0000000000..ed8955fd2d --- /dev/null +++ b/packages/toolkit/src/dynamicMiddleware/tests/react.test-d.ts @@ -0,0 +1,81 @@ +import type { Context } from 'react' +import type { ReactReduxContextValue } from 'react-redux' +import type { Action, Middleware, UnknownAction } from 'redux' +import type { ThunkDispatch } from 'redux-thunk' +import { createDynamicMiddleware } from '../react' + +interface AppDispatch extends ThunkDispatch { + (n: 1): 1 +} + +const untypedInstance = createDynamicMiddleware() + +const typedInstance = createDynamicMiddleware() + +declare const compatibleMiddleware: Middleware<{}, number, AppDispatch> +declare const incompatibleMiddleware: Middleware<{}, string, AppDispatch> + +declare const customContext: Context + +declare const addedMiddleware: Middleware<(n: 2) => 2> + +describe('type tests', () => { + test('instance typed at creation enforces correct middleware type', () => { + const useDispatch = typedInstance.createDispatchWithMiddlewareHook( + compatibleMiddleware, + // @ts-expect-error + incompatibleMiddleware, + ) + + const createDispatchWithMiddlewareHook = + typedInstance.createDispatchWithMiddlewareHookFactory(customContext) + const useDispatchWithContext = createDispatchWithMiddlewareHook( + compatibleMiddleware, + // @ts-expect-error + incompatibleMiddleware, + ) + }) + + test('withTypes() enforces correct middleware type', () => { + const createDispatchWithMiddlewareHook = + untypedInstance.createDispatchWithMiddlewareHook.withTypes<{ + state: number + dispatch: AppDispatch + }>() + const useDispatch = createDispatchWithMiddlewareHook( + compatibleMiddleware, + // @ts-expect-error + incompatibleMiddleware, + ) + + const createCustomDispatchWithMiddlewareHook = untypedInstance + .createDispatchWithMiddlewareHookFactory(customContext) + .withTypes<{ + state: number + dispatch: AppDispatch + }>() + const useCustomDispatch = createCustomDispatchWithMiddlewareHook( + compatibleMiddleware, + // @ts-expect-error + incompatibleMiddleware, + ) + }) + + test('useDispatchWithMW returns typed dispatch, with any applicable extensions', () => { + const useDispatchWithMW = + typedInstance.createDispatchWithMiddlewareHook(addedMiddleware) + const dispatch = useDispatchWithMW() + + // standard + expectTypeOf(dispatch({ type: 'foo' })).toEqualTypeOf>() + + // thunk + expectTypeOf(dispatch(() => 'foo')).toBeString() + + // static + expectTypeOf(dispatch(1)).toEqualTypeOf<1>() + + // added + expectTypeOf(dispatch(2)).toEqualTypeOf<2>() + }) +}) diff --git a/packages/toolkit/src/dynamicMiddleware/tests/react.test.tsx b/packages/toolkit/src/dynamicMiddleware/tests/react.test.tsx index 86581586d2..546c1077f5 100644 --- a/packages/toolkit/src/dynamicMiddleware/tests/react.test.tsx +++ b/packages/toolkit/src/dynamicMiddleware/tests/react.test.tsx @@ -24,7 +24,7 @@ describe('createReactDynamicMiddleware', () => { expect(store.dispatch(probeMiddleware(1))).toBe(1) const useDispatch = dynamicInstance.createDispatchWithMiddlewareHook( - makeProbeableMiddleware(2) + makeProbeableMiddleware(2), ) // injected @@ -40,7 +40,7 @@ describe('createReactDynamicMiddleware', () => { }) const useDispatch = dynamicInstance.createDispatchWithMiddlewareHook( - makeProbeableMiddleware(2) + makeProbeableMiddleware(2), ) let dispatch: Dispatch | undefined @@ -77,7 +77,7 @@ describe('createReactDynamicMiddleware', () => { dynamicInstance.createDispatchWithMiddlewareHookFactory(context) const useDispatch = createDispatchWithMiddlewareHook( - makeProbeableMiddleware(2) + makeProbeableMiddleware(2), ) let dispatch: Dispatch | undefined diff --git a/packages/toolkit/src/dynamicMiddleware/tests/react.typetest.ts b/packages/toolkit/src/dynamicMiddleware/tests/react.typetest.ts deleted file mode 100644 index 59088fd3b5..0000000000 --- a/packages/toolkit/src/dynamicMiddleware/tests/react.typetest.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* eslint-disable no-lone-blocks */ -import type { Context } from 'react' -import type { ReactReduxContextValue } from 'react-redux' -import type { Action, UnknownAction, Middleware } from 'redux' -import type { ThunkDispatch } from 'redux-thunk' -import { createDynamicMiddleware } from '../react' -import { expectExactType, expectType } from '../../tests/helpers' -/* eslint-disable no-lone-blocks */ - -interface AppDispatch extends ThunkDispatch { - (n: 1): 1 -} - -const untypedInstance = createDynamicMiddleware() - -const typedInstance = createDynamicMiddleware() - -declare const compatibleMiddleware: Middleware<{}, number, AppDispatch> -declare const incompatibleMiddleware: Middleware<{}, string, AppDispatch> - -declare const customContext: Context - -/** - * Test: instance typed at creation enforces correct middleware type - */ -{ - const useDispatch = typedInstance.createDispatchWithMiddlewareHook( - compatibleMiddleware, - // @ts-expect-error - incompatibleMiddleware - ) - - const createDispatchWithMiddlewareHook = - typedInstance.createDispatchWithMiddlewareHookFactory(customContext) - const useDispatchWithContext = createDispatchWithMiddlewareHook( - compatibleMiddleware, - // @ts-expect-error - incompatibleMiddleware - ) -} - -/** - * Test: withTypes() enforces correct middleware type - */ -{ - const createDispatchWithMiddlewareHook = - untypedInstance.createDispatchWithMiddlewareHook.withTypes<{ - state: number - dispatch: AppDispatch - }>() - const useDispatch = createDispatchWithMiddlewareHook( - compatibleMiddleware, - // @ts-expect-error - incompatibleMiddleware - ) - - const createCustomDispatchWithMiddlewareHook = untypedInstance - .createDispatchWithMiddlewareHookFactory(customContext) - .withTypes<{ - state: number - dispatch: AppDispatch - }>() - const useCustomDispatch = createCustomDispatchWithMiddlewareHook( - compatibleMiddleware, - // @ts-expect-error - incompatibleMiddleware - ) -} - -declare const addedMiddleware: Middleware<(n: 2) => 2> - -/** - * Test: useDispatchWithMW returns typed dispatch, with any applicable extensions - */ -{ - const useDispatchWithMW = - typedInstance.createDispatchWithMiddlewareHook(addedMiddleware) - // eslint-disable-next-line react-hooks/rules-of-hooks - const dispatch = useDispatchWithMW() - - // standard - expectType>(dispatch({ type: 'foo' })) - // thunk - expectType(dispatch(() => 'foo')) - // static - expectExactType(1 as const)(dispatch(1)) - // added - expectExactType(2 as const)(dispatch(2)) -} diff --git a/packages/toolkit/src/dynamicMiddleware/types.ts b/packages/toolkit/src/dynamicMiddleware/types.ts index dc3d563c3c..70590afbcb 100644 --- a/packages/toolkit/src/dynamicMiddleware/types.ts +++ b/packages/toolkit/src/dynamicMiddleware/types.ts @@ -32,7 +32,7 @@ export type GetDispatch = MiddlewareApiConfig extends { export type AddMiddleware< State = any, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, > = { (...middlewares: Middleware[]): void withTypes(): AddMiddleware< @@ -43,7 +43,7 @@ export type AddMiddleware< export interface WithMiddleware< State = any, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, > extends BaseActionCreator< Middleware[], 'dynamicMiddleware/add', @@ -61,13 +61,13 @@ export interface WithMiddleware< export interface DynamicDispatch { // return a version of dispatch that knows about middleware []>( - action: PayloadAction + action: PayloadAction, ): ExtractDispatchExtensions & this } export type MiddlewareEntry< State = unknown, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, > = { id: string middleware: Middleware @@ -79,12 +79,12 @@ export type MiddlewareEntry< export type DynamicMiddleware< State = unknown, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, > = Middleware export type DynamicMiddlewareInstance< State = unknown, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, > = { middleware: DynamicMiddleware addMiddleware: AddMiddleware diff --git a/packages/toolkit/src/entities/create_adapter.ts b/packages/toolkit/src/entities/create_adapter.ts index 83ad6c6515..726ad82c32 100644 --- a/packages/toolkit/src/entities/create_adapter.ts +++ b/packages/toolkit/src/entities/create_adapter.ts @@ -34,7 +34,7 @@ export function createEntityAdapter( options: { selectId?: IdSelector sortComparer?: false | Comparer - } = {} + } = {}, ): EntityAdapter { const { selectId, sortComparer }: EntityDefinition = { sortComparer: false, diff --git a/packages/toolkit/src/entities/entity_state.ts b/packages/toolkit/src/entities/entity_state.ts index 62ab918442..6b0744cdee 100644 --- a/packages/toolkit/src/entities/entity_state.ts +++ b/packages/toolkit/src/entities/entity_state.ts @@ -13,7 +13,7 @@ export function getInitialEntityState(): EntityState< export function createInitialStateFactory() { function getInitialState(): EntityState function getInitialState( - additionalState: S + additionalState: S, ): EntityState & S function getInitialState(additionalState: any = {}): any { return Object.assign(getInitialEntityState(), additionalState) diff --git a/packages/toolkit/src/entities/models.ts b/packages/toolkit/src/entities/models.ts index 068dfc227d..a7ec0238d9 100644 --- a/packages/toolkit/src/entities/models.ts +++ b/packages/toolkit/src/entities/models.ts @@ -43,9 +43,11 @@ export interface EntityDefinition { export type PreventAny = CastAny< S, EntityState - > +> -export type DraftableEntityState = EntityState | Draft> +export type DraftableEntityState = + | EntityState + | Draft> /** * @public @@ -53,101 +55,103 @@ export type DraftableEntityState = EntityState | export interface EntityStateAdapter { addOne>( state: PreventAny, - entity: T + entity: T, ): S addOne>( state: PreventAny, - action: PayloadAction + action: PayloadAction, ): S addMany>( state: PreventAny, - entities: readonly T[] | Record + entities: readonly T[] | Record, ): S addMany>( state: PreventAny, - entities: PayloadAction> + entities: PayloadAction>, ): S setOne>( state: PreventAny, - entity: T + entity: T, ): S setOne>( state: PreventAny, - action: PayloadAction + action: PayloadAction, ): S setMany>( state: PreventAny, - entities: readonly T[] | Record + entities: readonly T[] | Record, ): S setMany>( state: PreventAny, - entities: PayloadAction> + entities: PayloadAction>, ): S setAll>( state: PreventAny, - entities: readonly T[] | Record + entities: readonly T[] | Record, ): S setAll>( state: PreventAny, - entities: PayloadAction> + entities: PayloadAction>, ): S removeOne>( state: PreventAny, - key: Id + key: Id, ): S removeOne>( state: PreventAny, - key: PayloadAction + key: PayloadAction, ): S removeMany>( state: PreventAny, - keys: readonly Id[] + keys: readonly Id[], ): S removeMany>( state: PreventAny, - keys: PayloadAction + keys: PayloadAction, ): S - removeAll>(state: PreventAny): S + removeAll>( + state: PreventAny, + ): S updateOne>( state: PreventAny, - update: Update + update: Update, ): S updateOne>( state: PreventAny, - update: PayloadAction> + update: PayloadAction>, ): S updateMany>( state: PreventAny, - updates: ReadonlyArray> + updates: ReadonlyArray>, ): S updateMany>( state: PreventAny, - updates: PayloadAction>> + updates: PayloadAction>>, ): S upsertOne>( state: PreventAny, - entity: T + entity: T, ): S upsertOne>( state: PreventAny, - entity: PayloadAction + entity: PayloadAction, ): S upsertMany>( state: PreventAny, - entities: readonly T[] | Record + entities: readonly T[] | Record, ): S upsertMany>( state: PreventAny, - entities: PayloadAction> + entities: PayloadAction>, ): S } @@ -173,10 +177,10 @@ export interface EntityAdapter getInitialState(state: S): EntityState & S getSelectors( selectState?: undefined, - options?: GetSelectorsOptions + options?: GetSelectorsOptions, ): EntitySelectors, Id> getSelectors( selectState: (state: V) => EntityState, - options?: GetSelectorsOptions + options?: GetSelectorsOptions, ): EntitySelectors } diff --git a/packages/toolkit/src/entities/sorted_state_adapter.ts b/packages/toolkit/src/entities/sorted_state_adapter.ts index 91645d1af0..1a2af5c527 100644 --- a/packages/toolkit/src/entities/sorted_state_adapter.ts +++ b/packages/toolkit/src/entities/sorted_state_adapter.ts @@ -4,7 +4,7 @@ import type { EntityStateAdapter, Update, EntityId, - DraftableEntityState + DraftableEntityState, } from './models' import { createStateOperator } from './state_adapter' import { createUnsortedStateAdapter } from './unsorted_state_adapter' @@ -16,7 +16,7 @@ import { export function createSortedStateAdapter( selectId: IdSelector, - sort: Comparer + sort: Comparer, ): EntityStateAdapter { type R = DraftableEntityState @@ -29,12 +29,12 @@ export function createSortedStateAdapter( function addManyMutably( newEntities: readonly T[] | Record, - state: R + state: R, ): void { newEntities = ensureEntitiesArray(newEntities) const models = newEntities.filter( - (model) => !(selectIdValue(model, selectId) in state.entities) + (model) => !(selectIdValue(model, selectId) in state.entities), ) if (models.length !== 0) { @@ -48,7 +48,7 @@ export function createSortedStateAdapter( function setManyMutably( newEntities: readonly T[] | Record, - state: R + state: R, ): void { newEntities = ensureEntitiesArray(newEntities) if (newEntities.length !== 0) { @@ -58,7 +58,7 @@ export function createSortedStateAdapter( function setAllMutably( newEntities: readonly T[] | Record, - state: R + state: R, ): void { newEntities = ensureEntitiesArray(newEntities) state.entities = {} as Record @@ -73,7 +73,7 @@ export function createSortedStateAdapter( function updateManyMutably( updates: ReadonlyArray>, - state: R + state: R, ): void { let appliedUpdates = false @@ -88,8 +88,8 @@ export function createSortedStateAdapter( Object.assign(entity, update.changes) const newId = selectId(entity) if (update.id !== newId) { - delete (state.entities as Record)[update.id]; - (state.entities as Record)[newId] = entity + delete (state.entities as Record)[update.id] + ;(state.entities as Record)[newId] = entity } } @@ -104,12 +104,12 @@ export function createSortedStateAdapter( function upsertManyMutably( newEntities: readonly T[] | Record, - state: R + state: R, ): void { const [added, updated] = splitAddedUpdatedEntities( newEntities, selectId, - state + state, ) updateManyMutably(updated, state) @@ -133,7 +133,7 @@ export function createSortedStateAdapter( function merge(models: readonly T[], state: R): void { // Insert/overwrite all new/updated models.forEach((model) => { - (state.entities as Record)[selectId(model)] = model + ;(state.entities as Record)[selectId(model)] = model }) resortEntities(state) diff --git a/packages/toolkit/src/entities/state_adapter.ts b/packages/toolkit/src/entities/state_adapter.ts index 93738d21c2..f13d3e3c90 100644 --- a/packages/toolkit/src/entities/state_adapter.ts +++ b/packages/toolkit/src/entities/state_adapter.ts @@ -1,34 +1,36 @@ import { produce as createNextState, isDraft } from 'immer' -import type { Draft } from 'immer' +import type { Draft } from 'immer' import type { EntityId, DraftableEntityState, PreventAny } from './models' import type { PayloadAction } from '../createAction' import { isFSA } from '../createAction' -export const isDraftTyped = isDraft as (value: T | Draft) => value is Draft +export const isDraftTyped = isDraft as ( + value: T | Draft, +) => value is Draft export function createSingleArgumentStateOperator( - mutator: (state: DraftableEntityState) => void + mutator: (state: DraftableEntityState) => void, ) { const operator = createStateOperator( - (_: undefined, state: DraftableEntityState) => mutator(state) + (_: undefined, state: DraftableEntityState) => mutator(state), ) return function operation>( - state: PreventAny + state: PreventAny, ): S { return operator(state as S, undefined) } } export function createStateOperator( - mutator: (arg: R, state: DraftableEntityState) => void + mutator: (arg: R, state: DraftableEntityState) => void, ) { return function operation>( state: S, - arg: R | PayloadAction + arg: R | PayloadAction, ): S { function isPayloadActionArgument( - arg: R | PayloadAction + arg: R | PayloadAction, ): arg is PayloadAction { return isFSA(arg) } @@ -50,7 +52,7 @@ export function createStateOperator( // since it's a draft, we'll just return it return state } - + return createNextState(state, runMutator) } } diff --git a/packages/toolkit/src/entities/state_selectors.ts b/packages/toolkit/src/entities/state_selectors.ts index f8f04449df..bd64cf001b 100644 --- a/packages/toolkit/src/entities/state_selectors.ts +++ b/packages/toolkit/src/entities/state_selectors.ts @@ -15,17 +15,19 @@ export interface GetSelectorsOptions { export function createSelectorsFactory() { function getSelectors( selectState?: undefined, - options?: GetSelectorsOptions + options?: GetSelectorsOptions, ): EntitySelectors, Id> function getSelectors( selectState: (state: V) => EntityState, - options?: GetSelectorsOptions + options?: GetSelectorsOptions, ): EntitySelectors function getSelectors( selectState?: (state: V) => EntityState, - options: GetSelectorsOptions = {} + options: GetSelectorsOptions = {}, ): EntitySelectors { - const { createSelector = createDraftSafeSelector as AnyCreateSelectorFunction } = options + const { + createSelector = createDraftSafeSelector as AnyCreateSelectorFunction, + } = options const selectIds = (state: EntityState) => state.ids @@ -34,7 +36,7 @@ export function createSelectorsFactory() { const selectAll = createSelector( selectIds, selectEntities, - (ids, entities): T[] => ids.map((id) => entities[id]!) + (ids, entities): T[] => ids.map((id) => entities[id]!), ) const selectId = (_: unknown, id: Id) => id @@ -55,7 +57,7 @@ export function createSelectorsFactory() { const selectGlobalizedEntities = createSelector( selectState as Selector>, - selectEntities + selectEntities, ) return { @@ -66,7 +68,7 @@ export function createSelectorsFactory() { selectById: createSelector( selectGlobalizedEntities, selectId, - selectById + selectById, ), } } diff --git a/packages/toolkit/src/entities/tests/entity_slice_enhancer.test.ts b/packages/toolkit/src/entities/tests/entity_slice_enhancer.test.ts index 9e8e380815..0842a20505 100644 --- a/packages/toolkit/src/entities/tests/entity_slice_enhancer.test.ts +++ b/packages/toolkit/src/entities/tests/entity_slice_enhancer.test.ts @@ -1,15 +1,20 @@ -import { createEntityAdapter, createSlice } from "../.."; -import type { PayloadAction, Slice, SliceCaseReducers, UnknownAction } from "../.."; -import type { EntityId, EntityState, IdSelector } from "../models"; -import type { BookModel } from "./fixtures/book"; +import { createEntityAdapter, createSlice } from '../..' +import type { + PayloadAction, + Slice, + SliceCaseReducers, + UnknownAction, +} from '../..' +import type { EntityId, EntityState, IdSelector } from '../models' +import type { BookModel } from './fixtures/book' describe('Entity Slice Enhancer', () => { - let slice: Slice>; + let slice: Slice> beforeEach(() => { const indieSlice = entitySliceEnhancer({ name: 'book', - selectId: (book: BookModel) => book.id + selectId: (book: BookModel) => book.id, }) slice = indieSlice }) @@ -18,7 +23,7 @@ describe('Entity Slice Enhancer', () => { const book = { id: '0', title: 'Der Steppenwolf', - author: 'Herman Hesse' + author: 'Herman Hesse', } const action = slice.actions.oneAdded(book) const oneAdded = slice.reducer(undefined, action as UnknownAction) @@ -35,23 +40,20 @@ interface EntitySliceArgs { function entitySliceEnhancer({ name, selectId, - modelReducer + modelReducer, }: EntitySliceArgs) { const modelAdapter = createEntityAdapter({ - selectId - }); + selectId, + }) return createSlice({ name, initialState: modelAdapter.getInitialState(), reducers: { oneAdded(state, action: PayloadAction) { - modelAdapter.addOne( - state, - action.payload - ) + modelAdapter.addOne(state, action.payload) }, - ...modelReducer - } + ...modelReducer, + }, }) } diff --git a/packages/toolkit/src/entities/tests/sorted_state_adapter.test.ts b/packages/toolkit/src/entities/tests/sorted_state_adapter.test.ts index ff691a8326..9683715fb8 100644 --- a/packages/toolkit/src/entities/tests/sorted_state_adapter.test.ts +++ b/packages/toolkit/src/entities/tests/sorted_state_adapter.test.ts @@ -360,7 +360,7 @@ describe('Sorted State Adapter', () => { { id: 'C', order: 3, ts: 0 }, { id: 'D', order: 3, ts: 0 }, { id: 'E', order: 3, ts: 0 }, - ] + ], ) const updated = sortedItemsAdapter.updateOne(withInitialItems, { diff --git a/packages/toolkit/src/entities/tests/state_selectors.test.ts b/packages/toolkit/src/entities/tests/state_selectors.test.ts index f581965be3..3afba41ac6 100644 --- a/packages/toolkit/src/entities/tests/state_selectors.test.ts +++ b/packages/toolkit/src/entities/tests/state_selectors.test.ts @@ -132,7 +132,7 @@ describe('Entity State Selectors', () => { it('should use the custom createSelector function if provided', () => { const memoizeSpy = vi.fn( // test that we're allowed to pass memoizers with different options, as long as they're optional - any>(fn: F, param?: boolean) => fn + any>(fn: F, param?: boolean) => fn, ) const createCustomSelector = createDraftSafeSelectorCreator(memoizeSpy) diff --git a/packages/toolkit/src/entities/unsorted_state_adapter.ts b/packages/toolkit/src/entities/unsorted_state_adapter.ts index 1b74a01479..e2d6c31357 100644 --- a/packages/toolkit/src/entities/unsorted_state_adapter.ts +++ b/packages/toolkit/src/entities/unsorted_state_adapter.ts @@ -4,7 +4,7 @@ import type { IdSelector, Update, EntityId, - DraftableEntityState + DraftableEntityState, } from './models' import { createStateOperator, @@ -17,7 +17,7 @@ import { } from './utils' export function createUnsortedStateAdapter( - selectId: IdSelector + selectId: IdSelector, ): EntityStateAdapter { type R = DraftableEntityState @@ -28,13 +28,13 @@ export function createUnsortedStateAdapter( return } - state.ids.push(key as Id & Draft); - (state.entities as Record)[key] = entity + state.ids.push(key as Id & Draft) + ;(state.entities as Record)[key] = entity } function addManyMutably( newEntities: readonly T[] | Record, - state: R + state: R, ): void { newEntities = ensureEntitiesArray(newEntities) @@ -46,14 +46,14 @@ export function createUnsortedStateAdapter( function setOneMutably(entity: T, state: R): void { const key = selectIdValue(entity, selectId) if (!(key in state.entities)) { - state.ids.push(key as Id & Draft); + state.ids.push(key as Id & Draft) } - (state.entities as Record)[key] = entity + ;(state.entities as Record)[key] = entity } function setManyMutably( newEntities: readonly T[] | Record, - state: R + state: R, ): void { newEntities = ensureEntitiesArray(newEntities) for (const entity of newEntities) { @@ -63,7 +63,7 @@ export function createUnsortedStateAdapter( function setAllMutably( newEntities: readonly T[] | Record, - state: R + state: R, ): void { newEntities = ensureEntitiesArray(newEntities) @@ -88,7 +88,9 @@ export function createUnsortedStateAdapter( }) if (didMutate) { - state.ids = (state.ids as Id[]).filter((id) => id in state.entities) as Id[] | Draft + state.ids = (state.ids as Id[]).filter((id) => id in state.entities) as + | Id[] + | Draft } } @@ -102,7 +104,7 @@ export function createUnsortedStateAdapter( function takeNewKey( keys: { [id: string]: Id }, update: Update, - state: R + state: R, ): boolean { const original: T | undefined = (state.entities as Record)[update.id] if (original === undefined) { @@ -117,7 +119,7 @@ export function createUnsortedStateAdapter( delete (state.entities as Record)[update.id] } - (state.entities as Record)[newKey] = updated + ;(state.entities as Record)[newKey] = updated return hasNewKey } @@ -128,7 +130,7 @@ export function createUnsortedStateAdapter( function updateManyMutably( updates: ReadonlyArray>, - state: R + state: R, ): void { const newKeys: { [id: string]: Id } = {} @@ -163,7 +165,7 @@ export function createUnsortedStateAdapter( if (didMutateIds) { state.ids = Object.values(state.entities).map((e) => - selectIdValue(e as T, selectId) + selectIdValue(e as T, selectId), ) } } @@ -175,12 +177,12 @@ export function createUnsortedStateAdapter( function upsertManyMutably( newEntities: readonly T[] | Record, - state: R + state: R, ): void { const [added, updated] = splitAddedUpdatedEntities( newEntities, selectId, - state + state, ) updateManyMutably(updated, state) diff --git a/packages/toolkit/src/entities/utils.ts b/packages/toolkit/src/entities/utils.ts index 71435e3a01..5e3fb92fc1 100644 --- a/packages/toolkit/src/entities/utils.ts +++ b/packages/toolkit/src/entities/utils.ts @@ -1,8 +1,13 @@ -import type { IdSelector, Update, EntityId, DraftableEntityState } from './models' +import type { + IdSelector, + Update, + EntityId, + DraftableEntityState, +} from './models' export function selectIdValue( entity: T, - selectId: IdSelector + selectId: IdSelector, ) { const key = selectId(entity) @@ -13,7 +18,7 @@ export function selectIdValue( 'The entity that was passed:', entity, 'The `selectId` implementation:', - selectId.toString() + selectId.toString(), ) } @@ -21,7 +26,7 @@ export function selectIdValue( } export function ensureEntitiesArray( - entities: readonly T[] | Record + entities: readonly T[] | Record, ): readonly T[] { if (!Array.isArray(entities)) { entities = Object.values(entities) @@ -33,7 +38,7 @@ export function ensureEntitiesArray( export function splitAddedUpdatedEntities( newEntities: readonly T[] | Record, selectId: IdSelector, - state: DraftableEntityState + state: DraftableEntityState, ): [T[], Update[]] { newEntities = ensureEntitiesArray(newEntities) diff --git a/packages/toolkit/src/getDefaultEnhancers.ts b/packages/toolkit/src/getDefaultEnhancers.ts index 6d13646482..bfc3a3aa57 100644 --- a/packages/toolkit/src/getDefaultEnhancers.ts +++ b/packages/toolkit/src/getDefaultEnhancers.ts @@ -10,11 +10,11 @@ type GetDefaultEnhancersOptions = { } export type GetDefaultEnhancers> = ( - options?: GetDefaultEnhancersOptions + options?: GetDefaultEnhancersOptions, ) => Tuple<[StoreEnhancer<{ dispatch: ExtractDispatchExtensions }>]> export const buildGetDefaultEnhancers = >( - middlewareEnhancer: StoreEnhancer<{ dispatch: ExtractDispatchExtensions }> + middlewareEnhancer: StoreEnhancer<{ dispatch: ExtractDispatchExtensions }>, ): GetDefaultEnhancers => function getDefaultEnhancers(options) { const { autoBatch = true } = options ?? {} @@ -22,7 +22,9 @@ export const buildGetDefaultEnhancers = >( let enhancerArray = new Tuple(middlewareEnhancer) if (autoBatch) { enhancerArray.push( - autoBatchEnhancer(typeof autoBatch === 'object' ? autoBatch : undefined) + autoBatchEnhancer( + typeof autoBatch === 'object' ? autoBatch : undefined, + ), ) } return enhancerArray as any diff --git a/packages/toolkit/src/getDefaultMiddleware.ts b/packages/toolkit/src/getDefaultMiddleware.ts index 6ec507b4ce..95464ceb98 100644 --- a/packages/toolkit/src/getDefaultMiddleware.ts +++ b/packages/toolkit/src/getDefaultMiddleware.ts @@ -30,14 +30,14 @@ interface GetDefaultMiddlewareOptions { export type ThunkMiddlewareFor< S, - O extends GetDefaultMiddlewareOptions = {} + O extends GetDefaultMiddlewareOptions = {}, > = O extends { thunk: false } ? never : O extends { thunk: { extraArgument: infer E } } - ? ThunkMiddleware - : ThunkMiddleware + ? ThunkMiddleware + : ThunkMiddleware export type GetDefaultMiddleware = < O extends GetDefaultMiddlewareOptions = { @@ -45,9 +45,9 @@ export type GetDefaultMiddleware = < immutableCheck: true serializableCheck: true actionCreatorCheck: true - } + }, >( - options?: O + options?: O, ) => Tuple], never>> export const buildGetDefaultMiddleware = (): GetDefaultMiddleware => @@ -79,7 +79,7 @@ export const buildGetDefaultMiddleware = (): GetDefaultMiddleware => } middlewareArray.unshift( - createImmutableStateInvariantMiddleware(immutableOptions) + createImmutableStateInvariantMiddleware(immutableOptions), ) /* PROD_STOP_REMOVE_UMD */ } @@ -93,7 +93,7 @@ export const buildGetDefaultMiddleware = (): GetDefaultMiddleware => } middlewareArray.push( - createSerializableStateInvariantMiddleware(serializableOptions) + createSerializableStateInvariantMiddleware(serializableOptions), ) } if (actionCreatorCheck) { @@ -104,7 +104,7 @@ export const buildGetDefaultMiddleware = (): GetDefaultMiddleware => } middlewareArray.unshift( - createActionCreatorInvariantMiddleware(actionCreatorOptions) + createActionCreatorInvariantMiddleware(actionCreatorOptions), ) } } diff --git a/packages/toolkit/src/immutableStateInvariantMiddleware.ts b/packages/toolkit/src/immutableStateInvariantMiddleware.ts index 90f3a8ebe1..84fc782f56 100644 --- a/packages/toolkit/src/immutableStateInvariantMiddleware.ts +++ b/packages/toolkit/src/immutableStateInvariantMiddleware.ts @@ -15,7 +15,7 @@ export function isImmutableDefault(value: unknown): boolean { export function trackForMutations( isImmutable: IsImmutableFunc, ignorePaths: IgnorePaths | undefined, - obj: any + obj: any, ) { const trackedProperties = trackProperties(isImmutable, ignorePaths, obj) return { @@ -35,7 +35,7 @@ function trackProperties( ignorePaths: IgnorePaths = [], obj: Record, path: string = '', - checkedObjects: Set> = new Set() + checkedObjects: Set> = new Set(), ) { const tracked: Partial = { value: obj } @@ -53,7 +53,7 @@ function trackProperties( isImmutable, ignorePaths, obj[key], - childPath + childPath, ) } } @@ -68,7 +68,7 @@ function detectMutations( trackedProperty: TrackedProperty, obj: any, sameParentRef: boolean = false, - path: string = '' + path: string = '', ): { wasMutated: boolean; path?: string } { const prevObj = trackedProperty ? trackedProperty.value : undefined @@ -114,7 +114,7 @@ function detectMutations( trackedProperty.children[key], obj[key], sameRef, - nestedPath + nestedPath, ) if (result.wasMutated) { @@ -159,7 +159,7 @@ export interface ImmutableStateInvariantMiddlewareOptions { * @public */ export function createImmutableStateInvariantMiddleware( - options: ImmutableStateInvariantMiddlewareOptions = {} + options: ImmutableStateInvariantMiddlewareOptions = {}, ): Middleware { if (process.env.NODE_ENV === 'production') { return () => (next) => (action) => next(action) @@ -168,14 +168,14 @@ export function createImmutableStateInvariantMiddleware( obj: any, serializer?: EntryProcessor, indent?: string | number, - decycler?: EntryProcessor + decycler?: EntryProcessor, ): string { return JSON.stringify(obj, getSerialize(serializer, decycler), indent) } function getSerialize( serializer?: EntryProcessor, - decycler?: EntryProcessor + decycler?: EntryProcessor, ): EntryProcessor { let stack: any[] = [], keys: any[] = [] @@ -216,7 +216,7 @@ export function createImmutableStateInvariantMiddleware( return (next) => (action) => { const measureUtils = getTimeMeasureUtils( warnAfter, - 'ImmutableStateInvariantMiddleware' + 'ImmutableStateInvariantMiddleware', ) measureUtils.measureTime(() => { @@ -230,7 +230,7 @@ export function createImmutableStateInvariantMiddleware( throw new Error( `A state mutation was detected between dispatches, in the path '${ result.path || '' - }'. This may cause incorrect behavior. (https://redux.js.org/style-guide/style-guide#do-not-mutate-state)` + }'. This may cause incorrect behavior. (https://redux.js.org/style-guide/style-guide#do-not-mutate-state)`, ) } }) @@ -249,8 +249,8 @@ export function createImmutableStateInvariantMiddleware( `A state mutation was detected inside a dispatch, in the path: ${ result.path || '' }. Take a look at the reducer(s) handling the action ${stringify( - action - )}. (https://redux.js.org/style-guide/style-guide#do-not-mutate-state)` + action, + )}. (https://redux.js.org/style-guide/style-guide#do-not-mutate-state)`, ) } }) diff --git a/packages/toolkit/src/index.ts b/packages/toolkit/src/index.ts index 43ac586292..6c94d1df0c 100644 --- a/packages/toolkit/src/index.ts +++ b/packages/toolkit/src/index.ts @@ -203,6 +203,9 @@ export { combineSlices } from './combineSlices' export type { WithSlice } from './combineSlices' -export type { ExtractDispatchExtensions as TSHelpersExtractDispatchExtensions } from './tsHelpers' +export type { + ExtractDispatchExtensions as TSHelpersExtractDispatchExtensions, + SafePromise, +} from './tsHelpers' export { formatProdErrorMessage } from './formatProdErrorMessage' diff --git a/packages/toolkit/src/listenerMiddleware/index.ts b/packages/toolkit/src/listenerMiddleware/index.ts index 88d253b4cd..03d68eba0d 100644 --- a/packages/toolkit/src/listenerMiddleware/index.ts +++ b/packages/toolkit/src/listenerMiddleware/index.ts @@ -46,6 +46,7 @@ import { addAbortSignalListener, assertFunction, catchRejection, + noop, } from './utils' export { TaskAbortError } from './exceptions' export type { @@ -83,16 +84,16 @@ const alm = 'listenerMiddleware' as const const createFork = ( parentAbortSignal: AbortSignalWithReason, - parentBlockingPromises: Promise[] + parentBlockingPromises: Promise[], ) => { const linkControllers = (controller: AbortController) => addAbortSignalListener(parentAbortSignal, () => - abortControllerWithReason(controller, parentAbortSignal.reason) + abortControllerWithReason(controller, parentAbortSignal.reason), ) return ( taskExecutor: ForkedTaskExecutor, - opts?: ForkOptions + opts?: ForkOptions, ): ForkedTask => { assertFunction(taskExecutor, 'taskExecutor') const childAbortController = new AbortController() @@ -111,11 +112,11 @@ const createFork = ( validateActive(childAbortController.signal) return result }, - () => abortControllerWithReason(childAbortController, taskCompleted) + () => abortControllerWithReason(childAbortController, taskCompleted), ) if (opts?.autoJoin) { - parentBlockingPromises.push(result) + parentBlockingPromises.push(result.catch(noop)) } return { @@ -129,7 +130,7 @@ const createFork = ( const createTakePattern = ( startListening: AddListenerOverloads, - signal: AbortSignal + signal: AbortSignal, ): TakePattern => { /** * A function that takes a ListenerPredicate and an optional timeout, @@ -140,7 +141,7 @@ const createTakePattern = ( */ const take = async

>( predicate: P, - timeout: number | undefined + timeout: number | undefined, ) => { validateActive(signal) @@ -172,7 +173,7 @@ const createTakePattern = ( if (timeout != null) { promises.push( - new Promise((resolve) => setTimeout(resolve, timeout, null)) + new Promise((resolve) => setTimeout(resolve, timeout, null)), ) } @@ -205,7 +206,7 @@ const getListenerEntryPropsFrom = (options: FallbackAddListenerOptions) => { // pass } else { throw new Error( - 'Creating or removing a listener requires one of the known fields for matching an action' + 'Creating or removing a listener requires one of the known fields for matching an action', ) } @@ -234,11 +235,11 @@ export const createListenerEntry: TypedCreateListenerEntry = return entry }, - { withTypes: () => createListenerEntry } + { withTypes: () => createListenerEntry }, ) as unknown as TypedCreateListenerEntry const cancelActiveListeners = ( - entry: ListenerEntry> + entry: ListenerEntry>, ) => { entry.pending.forEach((controller) => { abortControllerWithReason(controller, listenerCancelled) @@ -246,7 +247,7 @@ const cancelActiveListeners = ( } const createClearListenerMiddleware = ( - listenerMap: Map + listenerMap: Map, ) => { return () => { listenerMap.forEach(cancelActiveListeners) @@ -265,7 +266,7 @@ const createClearListenerMiddleware = ( const safelyNotifyError = ( errorHandler: ListenerErrorHandler, errorToNotify: unknown, - errorInfo: ListenerErrorInfo + errorInfo: ListenerErrorInfo, ): void => { try { errorHandler(errorToNotify, errorInfo) @@ -311,9 +312,9 @@ export const createListenerMiddleware = < unknown, UnknownAction >, - ExtraArgument = unknown + ExtraArgument = unknown, >( - middlewareOptions: CreateListenerMiddlewareOptions = {} + middlewareOptions: CreateListenerMiddlewareOptions = {}, ) => { const listenerMap = new Map() const { extra, onError = defaultErrorHandler } = middlewareOptions @@ -335,7 +336,7 @@ export const createListenerMiddleware = < const startListening = ((options: FallbackAddListenerOptions) => { let entry = find( Array.from(listenerMap.values()), - (existingEntry) => existingEntry.effect === options.effect + (existingEntry) => existingEntry.effect === options.effect, ) if (!entry) { @@ -350,7 +351,7 @@ export const createListenerMiddleware = < }) const stopListening = ( - options: FallbackAddListenerOptions & UnsubscribeListenerOptions + options: FallbackAddListenerOptions & UnsubscribeListenerOptions, ): boolean => { const { type, effect, predicate } = getListenerEntryPropsFrom(options) @@ -381,12 +382,12 @@ export const createListenerMiddleware = < entry: ListenerEntry>, action: unknown, api: MiddlewareAPI, - getOriginalState: () => StateType + getOriginalState: () => StateType, ) => { const internalTaskController = new AbortController() const take = createTakePattern( startListening as AddListenerOverloads, - internalTaskController.signal + internalTaskController.signal, ) const autoJoinPromises: Promise[] = [] @@ -400,7 +401,7 @@ export const createListenerMiddleware = < getOriginalState, condition: ( predicate: AnyListenerPredicate, - timeout?: number + timeout?: number, ) => take(predicate, timeout).then(Boolean), take, delay: createDelay(internalTaskController.signal), @@ -423,15 +424,15 @@ export const createListenerMiddleware = < cancel: () => { abortControllerWithReason( internalTaskController, - listenerCancelled + listenerCancelled, ) entry.pending.delete(internalTaskController) }, throwIfCancelled: () => { validateActive(internalTaskController.signal) }, - }) - ) + }), + ), ) } catch (listenerError) { if (!(listenerError instanceof TaskAbortError)) { @@ -440,7 +441,7 @@ export const createListenerMiddleware = < }) } } finally { - await Promise.allSettled(autoJoinPromises) + await Promise.all(autoJoinPromises) abortControllerWithReason(internalTaskController, listenerCompleted) // Notify that the task has completed entry.pending.delete(internalTaskController) @@ -449,79 +450,82 @@ export const createListenerMiddleware = < const clearListenerMiddleware = createClearListenerMiddleware(listenerMap) - const middleware: ListenerMiddleware = - (api) => (next) => (action) => { - if (!isAction(action)) { - // we only want to notify listeners for action objects - return next(action) - } - - if (addListener.match(action)) { - return startListening(action.payload as any) - } + const middleware: ListenerMiddleware< + StateType, + DispatchType, + ExtraArgument + > = (api) => (next) => (action) => { + if (!isAction(action)) { + // we only want to notify listeners for action objects + return next(action) + } - if (clearAllListeners.match(action)) { - clearListenerMiddleware() - return - } + if (addListener.match(action)) { + return startListening(action.payload as any) + } - if (removeListener.match(action)) { - return stopListening(action.payload) - } + if (clearAllListeners.match(action)) { + clearListenerMiddleware() + return + } - // Need to get this state _before_ the reducer processes the action - let originalState: StateType | typeof INTERNAL_NIL_TOKEN = api.getState() + if (removeListener.match(action)) { + return stopListening(action.payload) + } - // `getOriginalState` can only be called synchronously. - // @see https://github.com/reduxjs/redux-toolkit/discussions/1648#discussioncomment-1932820 - const getOriginalState = (): StateType => { - if (originalState === INTERNAL_NIL_TOKEN) { - throw new Error( - `${alm}: getOriginalState can only be called synchronously` - ) - } + // Need to get this state _before_ the reducer processes the action + let originalState: StateType | typeof INTERNAL_NIL_TOKEN = api.getState() - return originalState as StateType + // `getOriginalState` can only be called synchronously. + // @see https://github.com/reduxjs/redux-toolkit/discussions/1648#discussioncomment-1932820 + const getOriginalState = (): StateType => { + if (originalState === INTERNAL_NIL_TOKEN) { + throw new Error( + `${alm}: getOriginalState can only be called synchronously`, + ) } - let result: unknown - - try { - // Actually forward the action to the reducer before we handle listeners - result = next(action) - - if (listenerMap.size > 0) { - const currentState = api.getState() - // Work around ESBuild+TS transpilation issue - const listenerEntries = Array.from(listenerMap.values()) - for (const entry of listenerEntries) { - let runListener = false - - try { - runListener = entry.predicate(action, currentState, originalState) - } catch (predicateError) { - runListener = false + return originalState as StateType + } - safelyNotifyError(onError, predicateError, { - raisedBy: 'predicate', - }) - } + let result: unknown - if (!runListener) { - continue - } + try { + // Actually forward the action to the reducer before we handle listeners + result = next(action) + + if (listenerMap.size > 0) { + const currentState = api.getState() + // Work around ESBuild+TS transpilation issue + const listenerEntries = Array.from(listenerMap.values()) + for (const entry of listenerEntries) { + let runListener = false + + try { + runListener = entry.predicate(action, currentState, originalState) + } catch (predicateError) { + runListener = false + + safelyNotifyError(onError, predicateError, { + raisedBy: 'predicate', + }) + } - notifyListener(entry, action, api, getOriginalState) + if (!runListener) { + continue } + + notifyListener(entry, action, api, getOriginalState) } - } finally { - // Remove `originalState` store from this scope. - originalState = INTERNAL_NIL_TOKEN } - - return result + } finally { + // Remove `originalState` store from this scope. + originalState = INTERNAL_NIL_TOKEN } + return result + } + return { middleware, startListening, diff --git a/packages/toolkit/src/listenerMiddleware/task.ts b/packages/toolkit/src/listenerMiddleware/task.ts index 01f20a72c2..a2fffce0d9 100644 --- a/packages/toolkit/src/listenerMiddleware/task.ts +++ b/packages/toolkit/src/listenerMiddleware/task.ts @@ -22,7 +22,7 @@ export const validateActive = (signal: AbortSignal): void => { */ export function raceWithSignal( signal: AbortSignalWithReason, - promise: Promise + promise: Promise, ): Promise { let cleanup = noop return new Promise((resolve, reject) => { @@ -50,7 +50,7 @@ export function raceWithSignal( */ export const runTask = async ( task: () => Promise, - cleanUp?: () => void + cleanUp?: () => void, ): Promise> => { try { await Promise.resolve() @@ -82,7 +82,7 @@ export const createPause = (signal: AbortSignal) => { raceWithSignal(signal, promise).then((output) => { validateActive(signal) return output - }) + }), ) } } diff --git a/packages/toolkit/src/listenerMiddleware/tests/fork.test.ts b/packages/toolkit/src/listenerMiddleware/tests/fork.test.ts index 41a5df123f..98e0c68461 100644 --- a/packages/toolkit/src/listenerMiddleware/tests/fork.test.ts +++ b/packages/toolkit/src/listenerMiddleware/tests/fork.test.ts @@ -123,7 +123,7 @@ describe('fork', () => { }) .result.then( deferredForkedTaskError.resolve, - deferredForkedTaskError.resolve + deferredForkedTaskError.resolve, ) }, }) @@ -132,7 +132,7 @@ describe('fork', () => { store.dispatch(increment()) expect(await deferredForkedTaskError).toEqual( - new TaskAbortError(listenerCancelled) + new TaskAbortError(listenerCancelled), ) }) @@ -346,7 +346,7 @@ describe('fork', () => { store.dispatch(increment()) expect(await deferredResult).toEqual( - new TaskAbortError(listenerCancelled) + new TaskAbortError(listenerCancelled), ) }) @@ -383,13 +383,13 @@ describe('fork', () => { async (forkApi) => { forkApi.signal.addEventListener('abort', () => { deferredResult.resolve( - (forkApi.signal as AbortSignalWithReason).reason + (forkApi.signal as AbortSignalWithReason).reason, ) }) await forkApi.delay(10) }, - { autoJoin } + { autoJoin }, ) }, }) @@ -402,7 +402,7 @@ describe('fork', () => { if (cancelListener) unsubscribe({ cancelActive: true }) expect(await deferredResult).toBe(expectedAbortReason) - } + }, ) test('fork.delay does not trigger unhandledRejections for completed or cancelled tasks', async () => { @@ -418,7 +418,7 @@ describe('fork', () => { forkApi.signal.addEventListener( 'abort', deferredCompletedEvt.resolve, - { once: true } + { once: true }, ) forkApi.delay(100) // missing await @@ -433,7 +433,7 @@ describe('fork', () => { forkApi.signal.addEventListener( 'abort', deferredCompletedEvt.resolve, - { once: true } + { once: true }, ) forkApi.delay(1_000) // missing await await forkApi.pause(godotPauseTrigger) diff --git a/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.test-d.ts b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.test-d.ts new file mode 100644 index 0000000000..8ac4c11549 --- /dev/null +++ b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.test-d.ts @@ -0,0 +1,540 @@ +import { createListenerEntry } from '@internal/listenerMiddleware' +import type { + Action, + PayloadAction, + TypedAddListener, + TypedStartListening, + UnknownAction, + UnsubscribeListener, +} from '@reduxjs/toolkit' +import { + addListener, + configureStore, + createAction, + createListenerMiddleware, + createSlice, + isFluxStandardAction, +} from '@reduxjs/toolkit' + +const listenerMiddleware = createListenerMiddleware() +const { startListening } = listenerMiddleware + +const addTypedListenerAction = addListener as TypedAddListener + +interface CounterState { + value: number +} + +const testAction1 = createAction('testAction1') +const testAction2 = createAction('testAction2') + +const counterSlice = createSlice({ + name: 'counter', + initialState: { value: 0 } as CounterState, + reducers: { + increment(state) { + state.value += 1 + }, + decrement(state) { + state.value -= 1 + }, + // Use the PayloadAction type to declare the contents of `action.payload` + incrementByAmount: (state, action: PayloadAction) => { + state.value += action.payload + }, + }, +}) + +const { increment, decrement, incrementByAmount } = counterSlice.actions + +describe('type tests', () => { + const store = configureStore({ + reducer: () => 42, + middleware: (gDM) => gDM().prepend(createListenerMiddleware().middleware), + }) + + test('Allows passing an extra argument on middleware creation', () => { + const originalExtra = 42 + const listenerMiddleware = createListenerMiddleware({ + extra: originalExtra, + }) + const store = configureStore({ + reducer: counterSlice.reducer, + middleware: (gDM) => gDM().prepend(listenerMiddleware.middleware), + }) + + let foundExtra: number | null = null + + const typedAddListener = + listenerMiddleware.startListening as TypedStartListening< + CounterState, + typeof store.dispatch, + typeof originalExtra + > + + typedAddListener({ + matcher: (action): action is Action => true, + effect: (action, listenerApi) => { + foundExtra = listenerApi.extra + + expectTypeOf(listenerApi.extra).toMatchTypeOf(originalExtra) + }, + }) + + store.dispatch(testAction1('a')) + expect(foundExtra).toBe(originalExtra) + }) + + test('unsubscribing via callback from dispatch', () => { + const unsubscribe = store.dispatch( + addListener({ + actionCreator: testAction1, + effect: () => {}, + }), + ) + + expectTypeOf(unsubscribe).toEqualTypeOf() + + store.dispatch(testAction1('a')) + + unsubscribe() + store.dispatch(testAction2('b')) + store.dispatch(testAction1('c')) + }) + + test('take resolves to `[A, CurrentState, PreviousState] | null` if a possibly undefined timeout parameter is provided', () => { + type ExpectedTakeResultType = + | readonly [ReturnType, CounterState, CounterState] + | null + + let timeout: number | undefined = undefined + let done = false + + const startAppListening = + startListening as TypedStartListening + startAppListening({ + predicate: incrementByAmount.match, + effect: async (_, listenerApi) => { + let takeResult = await listenerApi.take(increment.match, timeout) + + timeout = 1 + takeResult = await listenerApi.take(increment.match, timeout) + expect(takeResult).toBeNull() + + expectTypeOf(takeResult).toMatchTypeOf() + + done = true + }, + }) + + expect(done).toBe(true) + }) + + test('State args default to unknown', () => { + createListenerEntry({ + predicate: ( + action, + currentState, + previousState, + ): action is UnknownAction => { + expectTypeOf(currentState).toBeUnknown() + + expectTypeOf(previousState).toBeUnknown() + + return true + }, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toBeUnknown() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = getState() + + expectTypeOf(thunkState).toBeUnknown() + }) + }, + }) + + startListening({ + predicate: ( + action, + currentState, + previousState, + ): action is UnknownAction => { + expectTypeOf(currentState).toBeUnknown() + + expectTypeOf(previousState).toBeUnknown() + + return true + }, + effect: (action, listenerApi) => {}, + }) + + startListening({ + matcher: increment.match, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toBeUnknown() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = getState() + + expectTypeOf(thunkState).toBeUnknown() + }) + }, + }) + + store.dispatch( + addListener({ + predicate: ( + action, + currentState, + previousState, + ): action is UnknownAction => { + expectTypeOf(currentState).toBeUnknown() + + expectTypeOf(previousState).toBeUnknown() + + return true + }, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toBeUnknown() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = getState() + + expectTypeOf(thunkState).toBeUnknown() + }) + }, + }), + ) + + store.dispatch( + addListener({ + matcher: increment.match, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toBeUnknown() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = getState() + + expectTypeOf(thunkState).toBeUnknown() + }) + }, + }), + ) + }) + + test('Action type is inferred from args', () => { + startListening({ + type: 'abcd', + effect: (action, listenerApi) => { + expectTypeOf(action).toEqualTypeOf<{ type: 'abcd' }>() + }, + }) + + startListening({ + actionCreator: incrementByAmount, + effect: (action, listenerApi) => { + expectTypeOf(action).toMatchTypeOf>() + }, + }) + + startListening({ + matcher: incrementByAmount.match, + effect: (action, listenerApi) => { + expectTypeOf(action).toMatchTypeOf>() + }, + }) + + startListening({ + predicate: ( + action, + currentState, + previousState, + ): action is PayloadAction => { + return ( + isFluxStandardAction(action) && typeof action.payload === 'boolean' + ) + }, + effect: (action, listenerApi) => { + expectTypeOf(action).toEqualTypeOf>() + }, + }) + + startListening({ + predicate: (action, currentState) => { + return ( + isFluxStandardAction(action) && typeof action.payload === 'number' + ) + }, + effect: (action, listenerApi) => { + expectTypeOf(action).toEqualTypeOf() + }, + }) + + store.dispatch( + addListener({ + type: 'abcd', + effect: (action, listenerApi) => { + expectTypeOf(action).toEqualTypeOf<{ type: 'abcd' }>() + }, + }), + ) + + store.dispatch( + addListener({ + actionCreator: incrementByAmount, + effect: (action, listenerApi) => { + expectTypeOf(action).toMatchTypeOf>() + }, + }), + ) + + store.dispatch( + addListener({ + matcher: incrementByAmount.match, + effect: (action, listenerApi) => { + expectTypeOf(action).toMatchTypeOf>() + }, + }), + ) + }) + + test('Can create a pre-typed middleware', () => { + const typedMiddleware = createListenerMiddleware() + + typedMiddleware.startListening({ + predicate: ( + action, + currentState, + previousState, + ): action is UnknownAction => { + expectTypeOf(currentState).not.toBeAny() + + expectTypeOf(previousState).not.toBeAny() + + expectTypeOf(currentState).toEqualTypeOf() + + expectTypeOf(previousState).toEqualTypeOf() + + return true + }, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toEqualTypeOf() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = listenerApi.getState() + + expectTypeOf(thunkState).toEqualTypeOf() + }) + }, + }) + + // Can pass a predicate function with fewer args + typedMiddleware.startListening({ + predicate: (action, currentState): action is PayloadAction => { + expectTypeOf(currentState).not.toBeAny() + + expectTypeOf(currentState).toEqualTypeOf() + + return true + }, + effect: (action, listenerApi) => { + expectTypeOf(action).toEqualTypeOf>() + + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toEqualTypeOf() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = listenerApi.getState() + + expectTypeOf(thunkState).toEqualTypeOf() + }) + }, + }) + + typedMiddleware.startListening({ + actionCreator: incrementByAmount, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toEqualTypeOf() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = listenerApi.getState() + + expectTypeOf(thunkState).toEqualTypeOf() + }) + }, + }) + + store.dispatch( + addTypedListenerAction({ + predicate: ( + action, + currentState, + previousState, + ): action is ReturnType => { + expectTypeOf(currentState).not.toBeAny() + + expectTypeOf(previousState).not.toBeAny() + + expectTypeOf(currentState).toEqualTypeOf() + + expectTypeOf(previousState).toEqualTypeOf() + + return true + }, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toEqualTypeOf() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = listenerApi.getState() + + expectTypeOf(thunkState).toEqualTypeOf() + }) + }, + }), + ) + + store.dispatch( + addTypedListenerAction({ + predicate: ( + action, + currentState, + previousState, + ): action is UnknownAction => { + expectTypeOf(currentState).not.toBeAny() + + expectTypeOf(previousState).not.toBeAny() + + expectTypeOf(currentState).toEqualTypeOf() + + expectTypeOf(previousState).toEqualTypeOf() + + return true + }, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toEqualTypeOf() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = listenerApi.getState() + + expectTypeOf(thunkState).toEqualTypeOf() + }) + }, + }), + ) + }) + + test('Can create pre-typed versions of startListening and addListener', () => { + const typedAddListener = startListening as TypedStartListening + const typedAddListenerAction = addListener as TypedAddListener + + typedAddListener({ + predicate: ( + action, + currentState, + previousState, + ): action is UnknownAction => { + expectTypeOf(currentState).not.toBeAny() + + expectTypeOf(previousState).not.toBeAny() + + expectTypeOf(currentState).toEqualTypeOf() + + expectTypeOf(previousState).toEqualTypeOf() + + return true + }, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toEqualTypeOf() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = listenerApi.getState() + + expectTypeOf(thunkState).toEqualTypeOf() + }) + }, + }) + + typedAddListener({ + matcher: incrementByAmount.match, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toEqualTypeOf() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = listenerApi.getState() + + expectTypeOf(thunkState).toEqualTypeOf() + }) + }, + }) + + store.dispatch( + typedAddListenerAction({ + predicate: ( + action, + currentState, + previousState, + ): action is UnknownAction => { + expectTypeOf(currentState).not.toBeAny() + + expectTypeOf(previousState).not.toBeAny() + + expectTypeOf(currentState).toEqualTypeOf() + + expectTypeOf(previousState).toEqualTypeOf() + + return true + }, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toEqualTypeOf() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = listenerApi.getState() + + expectTypeOf(thunkState).toEqualTypeOf() + }) + }, + }), + ) + + store.dispatch( + typedAddListenerAction({ + matcher: incrementByAmount.match, + effect: (action, listenerApi) => { + const listenerState = listenerApi.getState() + + expectTypeOf(listenerState).toEqualTypeOf() + + listenerApi.dispatch((dispatch, getState) => { + const thunkState = listenerApi.getState() + + expectTypeOf(thunkState).toEqualTypeOf() + }) + }, + }), + ) + }) +}) diff --git a/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.test.ts b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.test.ts index c6af789516..56939af639 100644 --- a/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.test.ts +++ b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.test.ts @@ -1,38 +1,37 @@ import { + TaskAbortError, + addListener, + clearAllListeners, configureStore, createAction, + createListenerMiddleware, createSlice, isAnyOf, - isFluxStandardAction, + removeListener, } from '@reduxjs/toolkit' import type { Mock } from 'vitest' import { vi } from 'vitest' -import type { Action, UnknownAction, PayloadAction } from '@reduxjs/toolkit' - -import { - createListenerMiddleware, - createListenerEntry, - addListener, - removeListener, - TaskAbortError, - clearAllListeners, -} from '../index' - import type { + Action, ListenerEffect, ListenerEffectAPI, + PayloadAction, TypedAddListener, + TypedRemoveListener, TypedStartListening, - UnsubscribeListener, - ListenerMiddleware, -} from '../index' + UnknownAction, +} from '@reduxjs/toolkit' + +import { + listenerCancelled, + listenerCompleted, +} from '@internal/listenerMiddleware/exceptions' + import type { AbortSignalWithReason, AddListenerOverloads, - TypedRemoveListener, -} from '../types' -import { listenerCancelled, listenerCompleted } from '../exceptions' +} from '@internal/listenerMiddleware/types' const middlewareApi = { getState: expect.any(Function), @@ -76,44 +75,6 @@ export function deferred(): Deferred { return Object.assign(promise, methods) as Deferred } -export declare type IsAny = true | false extends ( - T extends never ? true : false -) - ? True - : False - -export declare type IsUnknown = unknown extends T - ? IsAny - : False - -export function expectType(t: T): T { - return t -} - -type Equals = IsAny< - T, - never, - IsAny -> -export function expectExactType(t: T) { - return >(u: U) => {} -} - -type EnsureUnknown = IsUnknown -export function expectUnknown>(t: T) { - return t -} - -type EnsureAny = IsAny -export function expectExactAny>(t: T) { - return t -} - -type IsNotAny = IsAny -export function expectNotAny>(t: T): T { - return t -} - describe('createListenerMiddleware', () => { let store = configureStore({ reducer: () => 42, @@ -150,16 +111,13 @@ describe('createListenerMiddleware', () => { let listenerMiddleware = createListenerMiddleware() let { middleware, startListening, stopListening, clearListeners } = listenerMiddleware - let addTypedListenerAction = addListener as TypedAddListener - let removeTypedListenerAction = + const removeTypedListenerAction = removeListener as TypedRemoveListener const testAction1 = createAction('testAction1') type TestAction1 = ReturnType const testAction2 = createAction('testAction2') - type TestAction2 = ReturnType const testAction3 = createAction('testAction3') - type TestAction3 = ReturnType beforeAll(() => { vi.spyOn(console, 'error').mockImplementation(noop) @@ -202,7 +160,6 @@ describe('createListenerMiddleware', () => { matcher: (action): action is Action => true, effect: (action, listenerApi) => { foundExtra = listenerApi.extra - expectType(listenerApi.extra) }, }) @@ -223,7 +180,7 @@ describe('createListenerMiddleware', () => { startListening({ actionCreator: testAction1, - effect: effect, + effect, }) store.dispatch(testAction1('a')) @@ -261,16 +218,16 @@ describe('createListenerMiddleware', () => { removeTypedListenerAction({ actionCreator: testAction2, effect, - }) - ) + }), + ), ).toBe(false) expect( store.dispatch( removeTypedListenerAction({ actionCreator: testAction1, effect, - }) - ) + }), + ), ).toBe(true) }) @@ -281,7 +238,7 @@ describe('createListenerMiddleware', () => { addListener({ type: testAction2.type, effect, - }) + }), ) store.dispatch(testAction2('b')) @@ -300,7 +257,7 @@ describe('createListenerMiddleware', () => { const unsubscribe = startListening({ matcher: isAction1Or2, - effect: effect, + effect, }) store.dispatch(testAction1('a')) @@ -426,7 +383,7 @@ describe('createListenerMiddleware', () => { addListener({ actionCreator: testAction1, effect, - }) + }), ) store.dispatch(testAction1('a')) @@ -446,11 +403,9 @@ describe('createListenerMiddleware', () => { addListener({ actionCreator: testAction1, effect, - }) + }), ) - expectType(unsubscribe) - store.dispatch(testAction1('a')) unsubscribe() @@ -549,7 +504,7 @@ describe('createListenerMiddleware', () => { actionCreator: testAction1, effect, cancelActive: true, - }) + }), ) expect(wasCancelled).toBe(false) await delay(10) @@ -565,7 +520,7 @@ describe('createListenerMiddleware', () => { typeof store.dispatch >, 'effect' | 'withTypes' - > + >, ][] = [ ['predicate', { predicate: () => true }], ['actionCreator', { actionCreator: testAction1 }], @@ -591,7 +546,7 @@ describe('createListenerMiddleware', () => { store.dispatch(testAction1('b')) expect(effect).toBeCalledTimes(1) - } + }, ) const unforwardedActions: [string, UnknownAction][] = [ @@ -617,7 +572,7 @@ describe('createListenerMiddleware', () => { [{}, testAction1('a')], [{}, testAction2('b')], ]) - } + }, ) test('listenerApi.signal has correct reason when listener is cancelled or completes', async () => { @@ -631,7 +586,7 @@ describe('createListenerMiddleware', () => { () => { payload.resolve((signal as AbortSignalWithReason).reason) }, - { once: true } + { once: true }, ) cancelActiveListeners() @@ -640,10 +595,10 @@ describe('createListenerMiddleware', () => { }) const deferredCancelledSignalReason = store.dispatch( - notifyDeferred(deferred()) + notifyDeferred(deferred()), ).payload const deferredCompletedSignalReason = store.dispatch( - notifyDeferred(deferred()) + notifyDeferred(deferred()), ).payload expect(await deferredCancelledSignalReason).toBe(listenerCancelled) @@ -661,7 +616,7 @@ describe('createListenerMiddleware', () => { () => { payload.resolve((signal as AbortSignalWithReason).reason) }, - { once: true } + { once: true }, ) cancel() @@ -669,7 +624,7 @@ describe('createListenerMiddleware', () => { }) const deferredCancelledSignalReason = store.dispatch( - notifyDeferred(deferred()) + notifyDeferred(deferred()), ).payload expect(await deferredCancelledSignalReason).toBe(listenerCancelled) @@ -717,7 +672,7 @@ describe('createListenerMiddleware', () => { expect(listenerCompleted).toBe(false) expect(listenerCancelled).toBe(true) expect((error as any)?.message).toBe( - 'task cancelled (reason: listener-cancelled)' + 'task cancelled (reason: listener-cancelled)', ) }) @@ -727,7 +682,7 @@ describe('createListenerMiddleware', () => { if (action.payload === 'b') { api.unsubscribe() } - } + }, ) startListening({ @@ -790,7 +745,7 @@ describe('createListenerMiddleware', () => { listenerApi.signal.addEventListener( 'abort', () => listener1Test.resolve(listener1Calls), - { once: true } + { once: true }, ) await listenerApi.condition(() => true) listener1Test.reject(new Error('unreachable: listener1Test')) @@ -833,7 +788,7 @@ describe('createListenerMiddleware', () => { listenerApi.signal.addEventListener( 'abort', () => listener1Test.resolve(listener1Calls), - { once: true } + { once: true }, ) await listenerApi.condition(() => true) listener1Test.reject(new Error('unreachable: listener1Test')) @@ -940,8 +895,8 @@ describe('createListenerMiddleware', () => { const runIncrementBy = () => { listenerApi.dispatch( counterSlice.actions.incrementByAmount( - listenerApi.getOriginalState().value + 2 - ) + listenerApi.getOriginalState().value + 2, + ), ) } @@ -963,9 +918,9 @@ describe('createListenerMiddleware', () => { expect(onError).toBeCalledWith( new Error( - 'listenerMiddleware: getOriginalState can only be called synchronously' + 'listenerMiddleware: getOriginalState can only be called synchronously', ), - { raisedBy: 'effect' } + { raisedBy: 'effect' }, ) expect(store.getState()).toEqual({ value: 3 }) }) @@ -986,8 +941,8 @@ describe('createListenerMiddleware', () => { }) test('listenerApi.delay does not trigger unhandledRejections for completed or cancelled listners', async () => { - let deferredCompletedEvt = deferred() - let deferredCancelledEvt = deferred() + const deferredCompletedEvt = deferred() + const deferredCancelledEvt = deferred() const godotPauseTrigger = deferred() // Unfortunately we cannot test declaratively unhandleRejections in jest: https://github.com/facebook/jest/issues/5620 @@ -999,7 +954,7 @@ describe('createListenerMiddleware', () => { listenerApi.signal.addEventListener( 'abort', deferredCompletedEvt.resolve, - { once: true } + { once: true }, ) listenerApi.delay(100) // missing await }, @@ -1012,7 +967,7 @@ describe('createListenerMiddleware', () => { listenerApi.signal.addEventListener( 'abort', deferredCancelledEvt.resolve, - { once: true } + { once: true }, ) listenerApi.delay(100) // missing await listenerApi.pause(godotPauseTrigger) @@ -1209,10 +1164,6 @@ describe('createListenerMiddleware', () => { middleware: (gDM) => gDM().prepend(middleware), }) - type ExpectedTakeResultType = - | readonly [ReturnType, CounterState, CounterState] - | null - let timeout: number | undefined = undefined let done = false @@ -1231,8 +1182,6 @@ describe('createListenerMiddleware', () => { takeResult = await listenerApi.take(increment.match, timeout) expect(takeResult).toBeNull() - expectType(takeResult) - done = true }, }) @@ -1323,8 +1272,8 @@ describe('createListenerMiddleware', () => { }) test('take does not trigger unhandledRejections for completed or cancelled tasks', async () => { - let deferredCompletedEvt = deferred() - let deferredCancelledEvt = deferred() + const deferredCompletedEvt = deferred() + const deferredCancelledEvt = deferred() const store = configureStore({ reducer: counterSlice.reducer, middleware: (gDM) => gDM().prepend(middleware), @@ -1337,7 +1286,7 @@ describe('createListenerMiddleware', () => { listenerApi.unsubscribe() // run once listenerApi.signal.addEventListener( 'abort', - deferredCompletedEvt.resolve + deferredCompletedEvt.resolve, ) listenerApi.take(() => true) // missing await }, @@ -1349,7 +1298,7 @@ describe('createListenerMiddleware', () => { listenerApi.cancelActiveListeners() listenerApi.signal.addEventListener( 'abort', - deferredCancelledEvt.resolve + deferredCancelledEvt.resolve, ) listenerApi.take(() => true) // missing await await listenerApi.pause(godotPauseTrigger) @@ -1400,364 +1349,4 @@ describe('createListenerMiddleware', () => { expect(jobsCanceled).toBe(2) }) }) - - describe('Type tests', () => { - const listenerMiddleware = createListenerMiddleware() - const { middleware, startListening } = listenerMiddleware - const store = configureStore({ - reducer: counterSlice.reducer, - middleware: (gDM) => gDM().prepend(middleware), - }) - - test('State args default to unknown', () => { - createListenerEntry({ - predicate: ( - action, - currentState, - previousState - ): action is UnknownAction => { - expectUnknown(currentState) - expectUnknown(previousState) - return true - }, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectUnknown(listenerState) - listenerApi.dispatch((dispatch, getState) => { - const thunkState = getState() - expectUnknown(thunkState) - }) - }, - }) - - startListening({ - predicate: ( - action, - currentState, - previousState - ): action is UnknownAction => { - expectUnknown(currentState) - expectUnknown(previousState) - return true - }, - effect: (action, listenerApi) => {}, - }) - - startListening({ - matcher: increment.match, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectUnknown(listenerState) - listenerApi.dispatch((dispatch, getState) => { - const thunkState = getState() - expectUnknown(thunkState) - }) - }, - }) - - store.dispatch( - addListener({ - predicate: ( - action, - currentState, - previousState - ): action is UnknownAction => { - expectUnknown(currentState) - expectUnknown(previousState) - return true - }, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectUnknown(listenerState) - listenerApi.dispatch((dispatch, getState) => { - const thunkState = getState() - expectUnknown(thunkState) - }) - }, - }) - ) - - store.dispatch( - addListener({ - matcher: increment.match, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectUnknown(listenerState) - // TODO Can't get the thunk dispatch types to carry through - listenerApi.dispatch((dispatch, getState) => { - const thunkState = getState() - expectUnknown(thunkState) - }) - }, - }) - ) - }) - - test('Action type is inferred from args', () => { - startListening({ - type: 'abcd', - effect: (action, listenerApi) => { - expectType<{ type: 'abcd' }>(action) - }, - }) - - startListening({ - actionCreator: incrementByAmount, - effect: (action, listenerApi) => { - expectType>(action) - }, - }) - - startListening({ - matcher: incrementByAmount.match, - effect: (action, listenerApi) => { - expectType>(action) - }, - }) - - startListening({ - predicate: ( - action, - currentState, - previousState - ): action is PayloadAction => { - return ( - isFluxStandardAction(action) && typeof action.payload === 'boolean' - ) - }, - effect: (action, listenerApi) => { - expectExactType>(action) - }, - }) - - startListening({ - predicate: (action, currentState) => { - return ( - isFluxStandardAction(action) && typeof action.payload === 'number' - ) - }, - effect: (action, listenerApi) => { - expectExactType(action) - }, - }) - - store.dispatch( - addListener({ - type: 'abcd', - effect: (action, listenerApi) => { - expectType<{ type: 'abcd' }>(action) - }, - }) - ) - - store.dispatch( - addListener({ - actionCreator: incrementByAmount, - effect: (action, listenerApi) => { - expectType>(action) - }, - }) - ) - - store.dispatch( - addListener({ - matcher: incrementByAmount.match, - effect: (action, listenerApi) => { - expectType>(action) - }, - }) - ) - }) - - test('Can create a pre-typed middleware', () => { - const typedMiddleware = createListenerMiddleware() - - typedMiddleware.startListening({ - predicate: ( - action, - currentState, - previousState - ): action is UnknownAction => { - expectNotAny(currentState) - expectNotAny(previousState) - expectExactType(currentState) - expectExactType(previousState) - return true - }, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectExactType(listenerState) - listenerApi.dispatch((dispatch, getState) => { - const thunkState = listenerApi.getState() - expectExactType(thunkState) - }) - }, - }) - - // Can pass a predicate function with fewer args - typedMiddleware.startListening({ - // TODO Why won't this infer the listener's `action` with implicit argument types? - predicate: ( - action: UnknownAction, - currentState: CounterState - ): action is PayloadAction => { - expectNotAny(currentState) - expectExactType(currentState) - return true - }, - effect: (action, listenerApi) => { - expectType>(action) - - const listenerState = listenerApi.getState() - expectExactType(listenerState) - listenerApi.dispatch((dispatch, getState) => { - const thunkState = listenerApi.getState() - expectExactType(thunkState) - }) - }, - }) - - typedMiddleware.startListening({ - actionCreator: incrementByAmount, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectExactType(listenerState) - listenerApi.dispatch((dispatch, getState) => { - const thunkState = listenerApi.getState() - expectExactType(thunkState) - }) - }, - }) - - store.dispatch( - addTypedListenerAction({ - predicate: ( - action, - currentState, - previousState - ): action is ReturnType => { - expectNotAny(currentState) - expectNotAny(previousState) - expectExactType(currentState) - expectExactType(previousState) - return true - }, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectExactType(listenerState) - listenerApi.dispatch((dispatch, getState) => { - const thunkState = listenerApi.getState() - expectExactType(thunkState) - }) - }, - }) - ) - - store.dispatch( - addTypedListenerAction({ - predicate: ( - action, - currentState, - previousState - ): action is UnknownAction => { - expectNotAny(currentState) - expectNotAny(previousState) - expectExactType(currentState) - expectExactType(previousState) - return true - }, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectExactType(listenerState) - listenerApi.dispatch((dispatch, getState) => { - const thunkState = listenerApi.getState() - expectExactType(thunkState) - }) - }, - }) - ) - }) - - test('Can create pre-typed versions of startListening and addListener', () => { - const typedAddListener = - startListening as TypedStartListening - const typedAddListenerAction = - addListener as TypedAddListener - - typedAddListener({ - predicate: ( - action, - currentState, - previousState - ): action is UnknownAction => { - expectNotAny(currentState) - expectNotAny(previousState) - expectExactType(currentState) - expectExactType(previousState) - return true - }, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectExactType(listenerState) - // TODO Can't get the thunk dispatch types to carry through - listenerApi.dispatch((dispatch, getState) => { - const thunkState = listenerApi.getState() - expectExactType(thunkState) - }) - }, - }) - - typedAddListener({ - matcher: incrementByAmount.match, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectExactType(listenerState) - // TODO Can't get the thunk dispatch types to carry through - listenerApi.dispatch((dispatch, getState) => { - const thunkState = listenerApi.getState() - expectExactType(thunkState) - }) - }, - }) - - store.dispatch( - typedAddListenerAction({ - predicate: ( - action, - currentState, - previousState - ): action is UnknownAction => { - expectNotAny(currentState) - expectNotAny(previousState) - expectExactType(currentState) - expectExactType(previousState) - return true - }, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectExactType(listenerState) - listenerApi.dispatch((dispatch, getState) => { - const thunkState = listenerApi.getState() - expectExactType(thunkState) - }) - }, - }) - ) - - store.dispatch( - typedAddListenerAction({ - matcher: incrementByAmount.match, - effect: (action, listenerApi) => { - const listenerState = listenerApi.getState() - expectExactType(listenerState) - listenerApi.dispatch((dispatch, getState) => { - const thunkState = listenerApi.getState() - expectExactType(thunkState) - }) - }, - }) - ) - }) - }) }) - diff --git a/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test-d.ts b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test-d.ts index 3d6a3d1775..6756144579 100644 --- a/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test-d.ts +++ b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test-d.ts @@ -36,7 +36,7 @@ export const counterSlice = createSlice({ export function fetchCount(amount = 1) { return new Promise<{ data: number }>((resolve) => - setTimeout(() => resolve({ data: amount }), 500) + setTimeout(() => resolve({ data: amount }), 500), ) } @@ -46,7 +46,7 @@ export const incrementAsync = createAsyncThunk( const response = await fetchCount(amount) // The value we return becomes the `fulfilled` action payload return response.data - } + }, ) const { increment } = counterSlice.actions @@ -127,7 +127,7 @@ describe('listenerMiddleware.withTypes()', () => { expectTypeOf(listenerApi.dispatch).toEqualTypeOf() }, - }) + }), ) }) diff --git a/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test.ts b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test.ts index c962aa0274..84bcf1ff2c 100644 --- a/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test.ts +++ b/packages/toolkit/src/listenerMiddleware/tests/listenerMiddleware.withTypes.test.ts @@ -26,7 +26,7 @@ export const counterSlice = createSlice({ export function fetchCount(amount = 1) { return new Promise<{ data: number }>((resolve) => - setTimeout(() => resolve({ data: amount }), 500) + setTimeout(() => resolve({ data: amount }), 500), ) } @@ -36,7 +36,7 @@ export const incrementAsync = createAsyncThunk( const response = await fetchCount(amount) // The value we return becomes the `fulfilled` action payload return response.data - } + }, ) const { increment } = counterSlice.actions @@ -76,7 +76,7 @@ describe('startAppListening.withTypes', () => { expect(startAppListening.withTypes).toEqual(expect.any(Function)) expect(startAppListening.withTypes().withTypes).toEqual( - expect.any(Function) + expect.any(Function), ) expect(startAppListening).toBe(listenerMiddleware.startListening) @@ -108,7 +108,7 @@ describe('removeAppListener.withTypes', () => { expect(removeAppListener.withTypes).toEqual(expect.any(Function)) expect(removeAppListener.withTypes().withTypes).toEqual( - expect.any(Function) + expect.any(Function), ) expect(removeAppListener).toBe(removeListener) diff --git a/packages/toolkit/src/listenerMiddleware/tests/useCases.test.ts b/packages/toolkit/src/listenerMiddleware/tests/useCases.test.ts index 0bd4a13a7d..7517f9071d 100644 --- a/packages/toolkit/src/listenerMiddleware/tests/useCases.test.ts +++ b/packages/toolkit/src/listenerMiddleware/tests/useCases.test.ts @@ -87,7 +87,7 @@ describe('Saga-style Effects Scenarios', () => { ;(this.events[event] = this.events[event] || []).push(cb) return () => (this.events[event] = (this.events[event] || []).filter( - (l: any) => l !== cb + (l: any) => l !== cb, )) }, }) diff --git a/packages/toolkit/src/listenerMiddleware/types.ts b/packages/toolkit/src/listenerMiddleware/types.ts index fc6a304224..73a7ef1c0e 100644 --- a/packages/toolkit/src/listenerMiddleware/types.ts +++ b/packages/toolkit/src/listenerMiddleware/types.ts @@ -30,14 +30,14 @@ export interface TypedActionCreator { export type AnyListenerPredicate = ( action: UnknownAction, currentState: State, - originalState: State + originalState: State, ) => boolean /** @public */ export type ListenerPredicate = ( action: UnknownAction, currentState: State, - originalState: State + originalState: State, ) => action is Action /** @public */ @@ -144,7 +144,7 @@ export interface ForkOptions { export interface ListenerEffectAPI< State, Dispatch extends ReduxDispatch, - ExtraArgument = unknown + ExtraArgument = unknown, > extends MiddlewareAPI { /** * Returns the store state as it existed when the action was originally dispatched, _before_ the reducers ran. @@ -272,10 +272,10 @@ export type ListenerEffect< Action extends ReduxAction, State, Dispatch extends ReduxDispatch, - ExtraArgument = unknown + ExtraArgument = unknown, > = ( action: Action, - api: ListenerEffectAPI + api: ListenerEffectAPI, ) => void | Promise /** @@ -316,7 +316,7 @@ export type ListenerMiddleware< unknown, UnknownAction >, - ExtraArgument = unknown + ExtraArgument = unknown, > = Middleware< { (action: ReduxAction<'listenerMiddleware/add'>): UnsubscribeListener @@ -333,7 +333,7 @@ export interface ListenerMiddlewareInstance< unknown, ReduxAction > = ThunkDispatch, - ExtraArgument = unknown + ExtraArgument = unknown, > { middleware: ListenerMiddleware @@ -361,31 +361,33 @@ export interface ListenerMiddlewareInstance< /** @public */ export type TakePatternOutputWithoutTimeout< State, - Predicate extends AnyListenerPredicate -> = Predicate extends MatchFunction - ? Promise<[Action, State, State]> - : Promise<[UnknownAction, State, State]> + Predicate extends AnyListenerPredicate, +> = + Predicate extends MatchFunction + ? Promise<[Action, State, State]> + : Promise<[UnknownAction, State, State]> /** @public */ export type TakePatternOutputWithTimeout< State, - Predicate extends AnyListenerPredicate -> = Predicate extends MatchFunction - ? Promise<[Action, State, State] | null> - : Promise<[UnknownAction, State, State] | null> + Predicate extends AnyListenerPredicate, +> = + Predicate extends MatchFunction + ? Promise<[Action, State, State] | null> + : Promise<[UnknownAction, State, State] | null> /** @public */ export interface TakePattern { >( - predicate: Predicate + predicate: Predicate, ): TakePatternOutputWithoutTimeout >( predicate: Predicate, - timeout: number + timeout: number, ): TakePatternOutputWithTimeout >( predicate: Predicate, - timeout?: number | undefined + timeout?: number | undefined, ): TakePatternOutputWithTimeout } @@ -396,7 +398,7 @@ export interface UnsubscribeListenerOptions { /** @public */ export type UnsubscribeListener = ( - unsubscribeOptions?: UnsubscribeListenerOptions + unsubscribeOptions?: UnsubscribeListenerOptions, ) => void /** @@ -412,7 +414,7 @@ export interface AddListenerOverloads< UnknownAction >, ExtraArgument = unknown, - AdditionalOptions = unknown + AdditionalOptions = unknown, > { /** Accepts a "listener predicate" that is also a TS type predicate for the action*/ < @@ -420,7 +422,7 @@ export interface AddListenerOverloads< ListenerPredicateType extends ListenerPredicate< MiddlewareActionType, StateType - > + >, >( options: { actionCreator?: never @@ -433,7 +435,7 @@ export interface AddListenerOverloads< DispatchType, ExtraArgument > - } & AdditionalOptions + } & AdditionalOptions, ): Return /** Accepts an RTK action creator, like `incrementByAmount` */ @@ -449,7 +451,7 @@ export interface AddListenerOverloads< DispatchType, ExtraArgument > - } & AdditionalOptions + } & AdditionalOptions, ): Return /** Accepts a specific action type string */ @@ -465,7 +467,7 @@ export interface AddListenerOverloads< DispatchType, ExtraArgument > - } & AdditionalOptions + } & AdditionalOptions, ): Return /** Accepts an RTK matcher function, such as `incrementByAmount.match` */ @@ -481,7 +483,7 @@ export interface AddListenerOverloads< DispatchType, ExtraArgument > - } & AdditionalOptions + } & AdditionalOptions, ): Return /** Accepts a "listener predicate" that just returns a boolean, no type assertion */ @@ -497,7 +499,7 @@ export interface AddListenerOverloads< DispatchType, ExtraArgument > - } & AdditionalOptions + } & AdditionalOptions, ): Return } @@ -508,7 +510,7 @@ export type RemoveListenerOverloads< StateType, unknown, UnknownAction - > + >, > = AddListenerOverloads< boolean, StateType, @@ -521,7 +523,7 @@ export type RemoveListenerOverloads< export interface RemoveListenerAction< Action extends UnknownAction, State, - Dispatch extends ReduxDispatch + Dispatch extends ReduxDispatch, > { type: 'listenerMiddleware/remove' payload: { @@ -544,7 +546,7 @@ export type TypedAddListener< >, ExtraArgument = unknown, Payload = ListenerEntry, - T extends string = 'listenerMiddleware/add' + T extends string = 'listenerMiddleware/add', > = BaseActionCreator & AddListenerOverloads< PayloadAction, @@ -579,7 +581,7 @@ export type TypedAddListener< OverrideStateType, unknown, UnknownAction - > + >, >() => TypedAddListener } @@ -596,7 +598,7 @@ export type TypedRemoveListener< UnknownAction >, Payload = ListenerEntry, - T extends string = 'listenerMiddleware/remove' + T extends string = 'listenerMiddleware/remove', > = BaseActionCreator & AddListenerOverloads< PayloadAction, @@ -632,7 +634,7 @@ export type TypedRemoveListener< OverrideStateType, unknown, UnknownAction - > + >, >() => TypedRemoveListener } @@ -648,7 +650,7 @@ export type TypedStartListening< unknown, UnknownAction >, - ExtraArgument = unknown + ExtraArgument = unknown, > = AddListenerOverloads< UnsubscribeListener, StateType, @@ -689,7 +691,7 @@ export type TypedStartListening< OverrideStateType, unknown, UnknownAction - > + >, >() => TypedStartListening } @@ -704,7 +706,7 @@ export type TypedStopListening< StateType, unknown, UnknownAction - > + >, > = RemoveListenerOverloads & { /** * Creates a "pre-typed" version of @@ -740,7 +742,7 @@ export type TypedStopListening< OverrideStateType, unknown, UnknownAction - > + >, >() => TypedStopListening } @@ -755,7 +757,7 @@ export type TypedCreateListenerEntry< StateType, unknown, UnknownAction - > + >, > = AddListenerOverloads< ListenerEntry, StateType, @@ -791,7 +793,7 @@ export type TypedCreateListenerEntry< OverrideStateType, unknown, UnknownAction - > + >, >() => TypedStopListening } @@ -802,7 +804,7 @@ export type TypedCreateListenerEntry< /** @internal An single listener entry */ export type ListenerEntry< State = unknown, - Dispatch extends ReduxDispatch = ReduxDispatch + Dispatch extends ReduxDispatch = ReduxDispatch, > = { id: string effect: ListenerEffect @@ -833,9 +835,5 @@ export type GuardedType = T extends (x: any, ...args: any[]) => x is infer T : never /** @public */ -export type ListenerPredicateGuardedActionType = T extends ListenerPredicate< - infer Action, - any -> - ? Action - : never +export type ListenerPredicateGuardedActionType = + T extends ListenerPredicate ? Action : never diff --git a/packages/toolkit/src/listenerMiddleware/utils.ts b/packages/toolkit/src/listenerMiddleware/utils.ts index f52e49b154..dd9480eb1f 100644 --- a/packages/toolkit/src/listenerMiddleware/utils.ts +++ b/packages/toolkit/src/listenerMiddleware/utils.ts @@ -2,10 +2,10 @@ import type { AbortSignalWithReason } from './types' export const assertFunction: ( func: unknown, - expected: string + expected: string, ) => asserts func is (...args: unknown[]) => unknown = ( func: unknown, - expected: string + expected: string, ) => { if (typeof func !== 'function') { throw new TypeError(`${expected} is not a function`) @@ -16,7 +16,7 @@ export const noop = () => {} export const catchRejection = ( promise: Promise, - onError = noop + onError = noop, ): Promise => { promise.catch(onError) @@ -25,7 +25,7 @@ export const catchRejection = ( export const addAbortSignalListener = ( abortSignal: AbortSignal, - callback: (evt: Event) => void + callback: (evt: Event) => void, ) => { abortSignal.addEventListener('abort', callback, { once: true }) return () => abortSignal.removeEventListener('abort', callback) @@ -43,7 +43,7 @@ export const addAbortSignalListener = ( */ export const abortControllerWithReason = ( abortController: AbortController, - reason: T + reason: T, ): void => { type Consumer = (val: T) => void diff --git a/packages/toolkit/src/mapBuilders.ts b/packages/toolkit/src/mapBuilders.ts index 5c6ac60010..560d640888 100644 --- a/packages/toolkit/src/mapBuilders.ts +++ b/packages/toolkit/src/mapBuilders.ts @@ -26,7 +26,7 @@ export interface ActionReducerMapBuilder { */ addCase>( actionCreator: ActionCreator, - reducer: CaseReducer> + reducer: CaseReducer>, ): ActionReducerMapBuilder /** * Adds a case reducer to handle a single exact action type. @@ -37,7 +37,7 @@ export interface ActionReducerMapBuilder { */ addCase>( type: Type, - reducer: CaseReducer + reducer: CaseReducer, ): ActionReducerMapBuilder /** @@ -98,7 +98,7 @@ const reducer = createReducer(initialState, (builder) => { */ addMatcher( matcher: TypeGuard | ((action: any) => boolean), - reducer: CaseReducer + reducer: CaseReducer, ): Omit, 'addCase'> /** @@ -124,11 +124,11 @@ const reducer = createReducer(initialState, builder => { } export function executeReducerBuilderCallback( - builderCallback: (builder: ActionReducerMapBuilder) => void + builderCallback: (builder: ActionReducerMapBuilder) => void, ): [ CaseReducers, ActionMatcherDescriptionCollection, - CaseReducer | undefined + CaseReducer | undefined, ] { const actionsMap: CaseReducers = {} const actionMatchers: ActionMatcherDescriptionCollection = [] @@ -136,7 +136,7 @@ export function executeReducerBuilderCallback( const builder = { addCase( typeOrActionCreator: string | TypedActionCreator, - reducer: CaseReducer + reducer: CaseReducer, ) { if (process.env.NODE_ENV !== 'production') { /* @@ -146,12 +146,12 @@ export function executeReducerBuilderCallback( */ if (actionMatchers.length > 0) { throw new Error( - '`builder.addCase` should only be called before calling `builder.addMatcher`' + '`builder.addCase` should only be called before calling `builder.addMatcher`', ) } if (defaultCaseReducer) { throw new Error( - '`builder.addCase` should only be called before calling `builder.addDefaultCase`' + '`builder.addCase` should only be called before calling `builder.addDefaultCase`', ) } } @@ -161,13 +161,13 @@ export function executeReducerBuilderCallback( : typeOrActionCreator.type if (!type) { throw new Error( - '`builder.addCase` cannot be called with an empty action type' + '`builder.addCase` cannot be called with an empty action type', ) } if (type in actionsMap) { throw new Error( '`builder.addCase` cannot be called with two reducers for the same action type ' + - `'${type}'` + `'${type}'`, ) } actionsMap[type] = reducer @@ -175,12 +175,12 @@ export function executeReducerBuilderCallback( }, addMatcher( matcher: TypeGuard, - reducer: CaseReducer + reducer: CaseReducer, ) { if (process.env.NODE_ENV !== 'production') { if (defaultCaseReducer) { throw new Error( - '`builder.addMatcher` should only be called before calling `builder.addDefaultCase`' + '`builder.addMatcher` should only be called before calling `builder.addDefaultCase`', ) } } diff --git a/packages/toolkit/src/matchers.ts b/packages/toolkit/src/matchers.ts index e8ca651077..6a5ccea09f 100644 --- a/packages/toolkit/src/matchers.ts +++ b/packages/toolkit/src/matchers.ts @@ -69,7 +69,7 @@ export function isAllOf[]]>( */ export function hasExpectedRequestMetadata( action: any, - validStatus: readonly string[] + validStatus: readonly string[], ) { if (!action || !action.meta) return false @@ -104,7 +104,7 @@ export type PendingActionFromAsyncThunk = * @public */ export function isPending(): ( - action: any + action: any, ) => action is UnknownAsyncThunkPendingAction /** * A higher-order function that returns a function that may be used to check @@ -116,7 +116,7 @@ export function isPending(): ( * @public */ export function isPending< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >( ...asyncThunks: AsyncThunks ): (action: any) => action is PendingActionFromAsyncThunk @@ -126,7 +126,7 @@ export function isPending< */ export function isPending(action: any): action is UnknownAsyncThunkPendingAction export function isPending< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >(...asyncThunks: AsyncThunks | [any]) { if (asyncThunks.length === 0) { return (action: any) => hasExpectedRequestMetadata(action, ['pending']) @@ -137,11 +137,11 @@ export function isPending< } return ( - action: any + action: any, ): action is PendingActionFromAsyncThunk => { // note: this type will be correct because we have at least 1 asyncThunk const matchers: [Matcher, ...Matcher[]] = asyncThunks.map( - (asyncThunk) => asyncThunk.pending + (asyncThunk) => asyncThunk.pending, ) as any const combinedMatcher = isAnyOf(...matchers) @@ -165,7 +165,7 @@ export type RejectedActionFromAsyncThunk = * @public */ export function isRejected(): ( - action: any + action: any, ) => action is UnknownAsyncThunkRejectedAction /** * A higher-order function that returns a function that may be used to check @@ -177,7 +177,7 @@ export function isRejected(): ( * @public */ export function isRejected< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >( ...asyncThunks: AsyncThunks ): (action: any) => action is RejectedActionFromAsyncThunk @@ -186,10 +186,10 @@ export function isRejected< * @public */ export function isRejected( - action: any + action: any, ): action is UnknownAsyncThunkRejectedAction export function isRejected< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >(...asyncThunks: AsyncThunks | [any]) { if (asyncThunks.length === 0) { return (action: any) => hasExpectedRequestMetadata(action, ['rejected']) @@ -200,11 +200,11 @@ export function isRejected< } return ( - action: any + action: any, ): action is RejectedActionFromAsyncThunk => { // note: this type will be correct because we have at least 1 asyncThunk const matchers: [Matcher, ...Matcher[]] = asyncThunks.map( - (asyncThunk) => asyncThunk.rejected + (asyncThunk) => asyncThunk.rejected, ) as any const combinedMatcher = isAnyOf(...matchers) @@ -231,7 +231,7 @@ export type RejectedWithValueActionFromAsyncThunk = * @public */ export function isRejectedWithValue(): ( - action: any + action: any, ) => action is UnknownAsyncThunkRejectedAction /** * A higher-order function that returns a function that may be used to check @@ -243,21 +243,21 @@ export function isRejectedWithValue(): ( * @public */ export function isRejectedWithValue< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >( ...asyncThunks: AsyncThunks ): ( - action: any + action: any, ) => action is RejectedWithValueActionFromAsyncThunk /** * Tests if `action` is a rejected thunk action with value * @public */ export function isRejectedWithValue( - action: any + action: any, ): action is UnknownAsyncThunkRejectedAction export function isRejectedWithValue< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >(...asyncThunks: AsyncThunks | [any]) { const hasFlag = (action: any): action is any => { return action && action.meta && action.meta.rejectedWithValue @@ -276,7 +276,7 @@ export function isRejectedWithValue< } return ( - action: any + action: any, ): action is RejectedActionFromAsyncThunk => { const combinedMatcher = isAllOf(isRejected(...asyncThunks), hasFlag) @@ -299,7 +299,7 @@ export type FulfilledActionFromAsyncThunk = * @public */ export function isFulfilled(): ( - action: any + action: any, ) => action is UnknownAsyncThunkFulfilledAction /** * A higher-order function that returns a function that may be used to check @@ -311,7 +311,7 @@ export function isFulfilled(): ( * @public */ export function isFulfilled< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >( ...asyncThunks: AsyncThunks ): (action: any) => action is FulfilledActionFromAsyncThunk @@ -320,10 +320,10 @@ export function isFulfilled< * @public */ export function isFulfilled( - action: any + action: any, ): action is UnknownAsyncThunkFulfilledAction export function isFulfilled< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >(...asyncThunks: AsyncThunks | [any]) { if (asyncThunks.length === 0) { return (action: any) => hasExpectedRequestMetadata(action, ['fulfilled']) @@ -334,11 +334,11 @@ export function isFulfilled< } return ( - action: any + action: any, ): action is FulfilledActionFromAsyncThunk => { // note: this type will be correct because we have at least 1 asyncThunk const matchers: [Matcher, ...Matcher[]] = asyncThunks.map( - (asyncThunk) => asyncThunk.fulfilled + (asyncThunk) => asyncThunk.fulfilled, ) as any const combinedMatcher = isAnyOf(...matchers) @@ -370,7 +370,7 @@ export type ActionsFromAsyncThunk = * @public */ export function isAsyncThunkAction(): ( - action: any + action: any, ) => action is UnknownAsyncThunkAction /** * A higher-order function that returns a function that may be used to check @@ -381,7 +381,7 @@ export function isAsyncThunkAction(): ( * @public */ export function isAsyncThunkAction< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >( ...asyncThunks: AsyncThunks ): (action: any) => action is ActionsFromAsyncThunk @@ -390,10 +390,10 @@ export function isAsyncThunkAction< * @public */ export function isAsyncThunkAction( - action: any + action: any, ): action is UnknownAsyncThunkAction export function isAsyncThunkAction< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >(...asyncThunks: AsyncThunks | [any]) { if (asyncThunks.length === 0) { return (action: any) => @@ -405,7 +405,7 @@ export function isAsyncThunkAction< } return ( - action: any + action: any, ): action is ActionsFromAsyncThunk => { // note: this type will be correct because we have at least 1 asyncThunk const matchers: [Matcher, ...Matcher[]] = [] as any @@ -414,7 +414,7 @@ export function isAsyncThunkAction< matchers.push( asyncThunk.pending, asyncThunk.rejected, - asyncThunk.fulfilled + asyncThunk.fulfilled, ) } diff --git a/packages/toolkit/src/query/HandledError.ts b/packages/toolkit/src/query/HandledError.ts index dcbf936b3b..c95791bd1d 100644 --- a/packages/toolkit/src/query/HandledError.ts +++ b/packages/toolkit/src/query/HandledError.ts @@ -1,6 +1,6 @@ export class HandledError { constructor( public readonly value: any, - public readonly meta: any = undefined + public readonly meta: any = undefined, ) {} } diff --git a/packages/toolkit/src/query/apiTypes.ts b/packages/toolkit/src/query/apiTypes.ts index 2aa7992999..e7d2332119 100644 --- a/packages/toolkit/src/query/apiTypes.ts +++ b/packages/toolkit/src/query/apiTypes.ts @@ -23,7 +23,7 @@ export interface ApiModules< // eslint-disable-next-line @typescript-eslint/no-unused-vars ReducerPath extends string, // eslint-disable-next-line @typescript-eslint/no-unused-vars - TagTypes extends string + TagTypes extends string, > {} export type ModuleName = keyof ApiModules @@ -34,7 +34,7 @@ export type Module = { BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, - TagTypes extends string + TagTypes extends string, >( api: Api, options: WithRequiredProp< @@ -48,11 +48,11 @@ export type Module = { | 'invalidationBehavior' | 'tagTypes' >, - context: ApiContext + context: ApiContext, ): { injectEndpoint( endpointName: string, - definition: EndpointDefinition + definition: EndpointDefinition, ): void } } @@ -62,7 +62,7 @@ export interface ApiContext { endpointDefinitions: Definitions batch(cb: () => void): void extractRehydrationInfo: ( - action: UnknownAction + action: UnknownAction, ) => CombinedState | undefined hasRehydrationInfo: (action: UnknownAction) => boolean } @@ -72,7 +72,7 @@ export type Api< Definitions extends EndpointDefinitions, ReducerPath extends string, TagTypes extends string, - Enhancers extends ModuleName = CoreModule + Enhancers extends ModuleName = CoreModule, > = UnionToIntersection< ApiModules[Enhancers] > & { @@ -81,7 +81,7 @@ export type Api< */ injectEndpoints(_: { endpoints: ( - build: EndpointBuilder + build: EndpointBuilder, ) => NewDefinitions overrideExisting?: boolean }): Api< @@ -96,7 +96,7 @@ export type Api< */ enhanceEndpoints< NewTagTypes extends string = never, - NewDefinitions extends EndpointDefinitions = never + NewDefinitions extends EndpointDefinitions = never, >(_: { addTagTypes?: readonly NewTagTypes[] endpoints?: UpdateDefinitions< diff --git a/packages/toolkit/src/query/baseQueryTypes.ts b/packages/toolkit/src/query/baseQueryTypes.ts index ed6a693c10..9af22a3f7e 100644 --- a/packages/toolkit/src/query/baseQueryTypes.ts +++ b/packages/toolkit/src/query/baseQueryTypes.ts @@ -37,20 +37,20 @@ export type BaseQueryFn< Result = unknown, Error = unknown, DefinitionExtraOptions = {}, - Meta = {} + Meta = {}, > = ( args: Args, api: BaseQueryApi, - extraOptions: DefinitionExtraOptions + extraOptions: DefinitionExtraOptions, ) => MaybePromise> export type BaseQueryEnhancer< AdditionalArgs = unknown, AdditionalDefinitionExtraOptions = unknown, - Config = void + Config = void, > = ( baseQuery: BaseQuery, - config: Config + config: Config, ) => BaseQueryFn< BaseQueryArg & AdditionalArgs, BaseQueryResult, @@ -59,13 +59,12 @@ export type BaseQueryEnhancer< NonNullable> > -export type BaseQueryResult = UnwrapPromise< - ReturnType -> extends infer Unwrapped - ? Unwrapped extends { data: any } - ? Unwrapped['data'] +export type BaseQueryResult = + UnwrapPromise> extends infer Unwrapped + ? Unwrapped extends { data: any } + ? Unwrapped['data'] + : never : never - : never export type BaseQueryMeta = UnwrapPromise< ReturnType diff --git a/packages/toolkit/src/query/core/apiState.ts b/packages/toolkit/src/query/core/apiState.ts index 3b1d6624c9..cdf6831d2b 100644 --- a/packages/toolkit/src/query/core/apiState.ts +++ b/packages/toolkit/src/query/core/apiState.ts @@ -83,6 +83,14 @@ export type SubscriptionOptions = { * How frequently to automatically re-fetch data (in milliseconds). Defaults to `0` (off). */ pollingInterval?: number + /** + * Defaults to 'false'. This setting allows you to control whether RTK Query will continue polling if the window is not focused. + * + * If pollingInterval is not set or set to 0, this **will not be evaluated** until pollingInterval is greater than 0. + * + * Note: requires [`setupListeners`](./setupListeners) to have been called. + */ + skipPollingIfUnfocused?: boolean /** * Defaults to `false`. This setting allows you to control whether RTK Query will try to refetch all subscribed queries after regaining a network connection. * @@ -221,7 +229,7 @@ export type MutationSubState> = export type CombinedState< D extends EndpointDefinitions, E extends string, - ReducerPath extends string + ReducerPath extends string, > = { queries: QueryState mutations: MutationState @@ -264,7 +272,7 @@ export type MutationState = { export type RootState< Definitions extends EndpointDefinitions, TagTypes extends string, - ReducerPath extends string + ReducerPath extends string, > = { [P in ReducerPath]: CombinedState } diff --git a/packages/toolkit/src/query/core/buildInitiate.ts b/packages/toolkit/src/query/core/buildInitiate.ts index 1b3a1e0aa1..384d10c50e 100644 --- a/packages/toolkit/src/query/core/buildInitiate.ts +++ b/packages/toolkit/src/query/core/buildInitiate.ts @@ -21,12 +21,14 @@ import type { QueryResultSelectorResult } from './buildSelectors' import type { Dispatch } from 'redux' import { isNotNullish } from '../utils/isNotNullish' import { countObjectKeys } from '../utils/countObjectKeys' +import type { SafePromise } from '../../tsHelpers' +import { asSafePromise } from '../../tsHelpers' declare module './module' { export interface ApiEndpointQuery< Definition extends QueryDefinition, // eslint-disable-next-line @typescript-eslint/no-unused-vars - Definitions extends EndpointDefinitions + Definitions extends EndpointDefinitions, > { initiate: StartQueryActionCreator } @@ -34,7 +36,7 @@ declare module './module' { export interface ApiEndpointMutation< Definition extends MutationDefinition, // eslint-disable-next-line @typescript-eslint/no-unused-vars - Definitions extends EndpointDefinitions + Definitions extends EndpointDefinitions, > { initiate: StartMutationActionCreator } @@ -52,15 +54,15 @@ export interface StartQueryActionCreatorOptions { } type StartQueryActionCreator< - D extends QueryDefinition + D extends QueryDefinition, > = ( arg: QueryArgFrom, - options?: StartQueryActionCreatorOptions + options?: StartQueryActionCreatorOptions, ) => ThunkAction, any, any, UnknownAction> export type QueryActionCreatorResult< - D extends QueryDefinition -> = Promise> & { + D extends QueryDefinition, +> = SafePromise> & { arg: QueryArgFrom requestId: string subscriptionOptions: SubscriptionOptions | undefined @@ -73,7 +75,7 @@ export type QueryActionCreatorResult< } type StartMutationActionCreator< - D extends MutationDefinition + D extends MutationDefinition, > = ( arg: QueryArgFrom, options?: { @@ -85,12 +87,12 @@ type StartMutationActionCreator< */ track?: boolean fixedCacheKey?: string - } + }, ) => ThunkAction, any, any, UnknownAction> export type MutationActionCreatorResult< - D extends MutationDefinition -> = Promise< + D extends MutationDefinition, +> = SafePromise< | { data: ResultTypeFrom } | { error: @@ -244,7 +246,7 @@ export function buildInitiate({ * we could use it to validate the result, but it's probably not necessary */ _endpointName: string, - fixedCacheKeyOrRequestId: string + fixedCacheKeyOrRequestId: string, ) { return (dispatch: Dispatch) => { return runningMutations.get(dispatch)?.[fixedCacheKeyOrRequestId] as @@ -267,7 +269,7 @@ export function buildInitiate({ if (process.env.NODE_ENV !== 'production') { if ((middlewareWarning as any).triggered) return const returnedValue = dispatch( - api.internalActions.internal_getRTKQSubscriptions() + api.internalActions.internal_getRTKQSubscriptions(), ) ;(middlewareWarning as any).triggered = true @@ -281,7 +283,7 @@ export function buildInitiate({ // Otherwise, must not have been added throw new Error( `Warning: Middleware for RTK-Query API at reducerPath "${api.reducerPath}" has not been added to the store. -You must add the middleware for RTK-Query to function correctly!` +You must add the middleware for RTK-Query to function correctly!`, ) } } @@ -289,7 +291,7 @@ You must add the middleware for RTK-Query to function correctly!` function buildInitiateQuery( endpointName: string, - endpointDefinition: QueryDefinition + endpointDefinition: QueryDefinition, ) { const queryAction: StartQueryActionCreator = ( @@ -299,7 +301,7 @@ You must add the middleware for RTK-Query to function correctly!` forceRefetch, subscriptionOptions, [forceQueryFnSymbol]: forceQueryFn, - } = {} + } = {}, ) => (dispatch, getState) => { const queryCacheKey = serializeQueryArgs({ @@ -335,17 +337,19 @@ You must add the middleware for RTK-Query to function correctly!` const selectFromState = () => selector(getState()) const statePromise: QueryActionCreatorResult = Object.assign( - forceQueryFn + (forceQueryFn ? // a query has been forced (upsertQueryData) // -> we want to resolve it once data has been written with the data that will be written thunkResult.then(selectFromState) : skippedSynchronously && !runningQuery - ? // a query has been skipped due to a condition and we do not have any currently running query - // -> we want to resolve it immediately with the current data - Promise.resolve(stateAfter) - : // query just started or one is already in flight - // -> wait for the running query, then resolve with data from after that - Promise.all([runningQuery, thunkResult]).then(selectFromState), + ? // a query has been skipped due to a condition and we do not have any currently running query + // -> we want to resolve it immediately with the current data + Promise.resolve(stateAfter) + : // query just started or one is already in flight + // -> wait for the running query, then resolve with data from after that + Promise.all([runningQuery, thunkResult]).then( + selectFromState, + )) as SafePromise, { arg, requestId, @@ -363,7 +367,7 @@ You must add the middleware for RTK-Query to function correctly!` }, refetch: () => dispatch( - queryAction(arg, { subscribe: false, forceRefetch: true }) + queryAction(arg, { subscribe: false, forceRefetch: true }), ), unsubscribe() { if (subscribe) @@ -371,7 +375,7 @@ You must add the middleware for RTK-Query to function correctly!` unsubscribeQueryResult({ queryCacheKey, requestId, - }) + }), ) }, updateSubscriptionOptions(options: SubscriptionOptions) { @@ -382,10 +386,10 @@ You must add the middleware for RTK-Query to function correctly!` requestId, queryCacheKey, options, - }) + }), ) }, - } + }, ) if (!runningQuery && !skippedSynchronously && !forceQueryFn) { @@ -407,7 +411,7 @@ You must add the middleware for RTK-Query to function correctly!` } function buildInitiateMutation( - endpointName: string + endpointName: string, ): StartMutationActionCreator { return (arg, { track = true, fixedCacheKey } = {}) => (dispatch, getState) => { @@ -421,10 +425,10 @@ You must add the middleware for RTK-Query to function correctly!` const thunkResult = dispatch(thunk) middlewareWarning(dispatch) const { requestId, abort, unwrap } = thunkResult - const returnValuePromise = thunkResult - .unwrap() - .then((data) => ({ data })) - .catch((error) => ({ error })) + const returnValuePromise = asSafePromise( + thunkResult.unwrap().then((data) => ({ data })), + (error) => ({ error }), + ) const reset = () => { dispatch(removeMutationResult({ requestId, fixedCacheKey })) diff --git a/packages/toolkit/src/query/core/buildMiddleware/batchActions.ts b/packages/toolkit/src/query/core/buildMiddleware/batchActions.ts index f941bcd544..b847dee01a 100644 --- a/packages/toolkit/src/query/core/buildMiddleware/batchActions.ts +++ b/packages/toolkit/src/query/core/buildMiddleware/batchActions.ts @@ -21,7 +21,7 @@ export const buildBatchedActionsHandler: InternalHandlerBuilder< // This is done to speed up perf when loading many components const actuallyMutateSubscriptions = ( mutableState: SubscriptionState, - action: Action + action: Action, ) => { if (updateSubscriptionOptions.match(action)) { const { queryCacheKey, requestId, options } = action.payload @@ -99,15 +99,15 @@ export const buildBatchedActionsHandler: InternalHandlerBuilder< return ( action, - mwApi + mwApi, ): [ actionShouldContinue: boolean, - result: SubscriptionSelectors | boolean + result: SubscriptionSelectors | boolean, ] => { if (!previousSubscriptions) { // Initialize it the first time this handler runs previousSubscriptions = JSON.parse( - JSON.stringify(internalState.currentSubscriptions) + JSON.stringify(internalState.currentSubscriptions), ) } @@ -128,7 +128,7 @@ export const buildBatchedActionsHandler: InternalHandlerBuilder< // Update subscription data based on this action const didMutate = actuallyMutateSubscriptions( internalState.currentSubscriptions, - action + action, ) let actionShouldContinue = true @@ -143,12 +143,12 @@ export const buildBatchedActionsHandler: InternalHandlerBuilder< updateSyncTimer = setTimeout(() => { // Deep clone the current subscription data const newSubscriptions: SubscriptionState = JSON.parse( - JSON.stringify(internalState.currentSubscriptions) + JSON.stringify(internalState.currentSubscriptions), ) // Figure out a smaller diff between original and current const [, patches] = produceWithPatches( previousSubscriptions, - () => newSubscriptions + () => newSubscriptions, ) // Sync the store state for visibility diff --git a/packages/toolkit/src/query/core/buildMiddleware/cacheCollection.ts b/packages/toolkit/src/query/core/buildMiddleware/cacheCollection.ts index becf6b8d1f..2d2ffeccf3 100644 --- a/packages/toolkit/src/query/core/buildMiddleware/cacheCollection.ts +++ b/packages/toolkit/src/query/core/buildMiddleware/cacheCollection.ts @@ -28,7 +28,7 @@ declare module '../../endpointDefinitions' { ResultType, QueryArg, BaseQuery extends BaseQueryFn, - ReducerPath extends string = string + ReducerPath extends string = string, > { /** * Overrides the api-wide definition of `keepUnusedDataFor` for this endpoint only. _(This value is in seconds.)_ @@ -64,7 +64,7 @@ export const buildCacheCollectionHandler: InternalHandlerBuilder = ({ const handler: ApiMiddlewareInternalHandler = ( action, mwApi, - internalState + internalState, ) => { if (unsubscribeQueryResult.match(action)) { const state = mwApi.getState()[reducerPath] @@ -74,7 +74,7 @@ export const buildCacheCollectionHandler: InternalHandlerBuilder = ({ queryCacheKey, state.queries[queryCacheKey]?.endpointName, mwApi, - state.config + state.config, ) } @@ -96,7 +96,7 @@ export const buildCacheCollectionHandler: InternalHandlerBuilder = ({ queryCacheKey as QueryCacheKey, queryState?.endpointName, mwApi, - state.config + state.config, ) } } @@ -106,7 +106,7 @@ export const buildCacheCollectionHandler: InternalHandlerBuilder = ({ queryCacheKey: QueryCacheKey, endpointName: string | undefined, api: SubMiddlewareApi, - config: ConfigState + config: ConfigState, ) { const endpointDefinition = context.endpointDefinitions[ endpointName! @@ -124,7 +124,7 @@ export const buildCacheCollectionHandler: InternalHandlerBuilder = ({ // Also avoid negative values too. const finalKeepUnusedDataFor = Math.max( 0, - Math.min(keepUnusedDataFor, THIRTY_TWO_BIT_MAX_TIMER_SECONDS) + Math.min(keepUnusedDataFor, THIRTY_TWO_BIT_MAX_TIMER_SECONDS), ) if (!anySubscriptionsRemainingForKey(queryCacheKey)) { diff --git a/packages/toolkit/src/query/core/buildMiddleware/cacheLifecycle.ts b/packages/toolkit/src/query/core/buildMiddleware/cacheLifecycle.ts index 247bd7434c..0a41e0174f 100644 --- a/packages/toolkit/src/query/core/buildMiddleware/cacheLifecycle.ts +++ b/packages/toolkit/src/query/core/buildMiddleware/cacheLifecycle.ts @@ -24,7 +24,7 @@ declare module '../../endpointDefinitions' { QueryArg, BaseQuery extends BaseQueryFn, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > extends LifecycleApi { /** * Gets the current value of this cache entry. @@ -47,7 +47,7 @@ declare module '../../endpointDefinitions' { QueryArg, BaseQuery extends BaseQueryFn, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > extends LifecycleApi { /** * Gets the current value of this cache entry. @@ -82,7 +82,7 @@ declare module '../../endpointDefinitions' { export interface CacheLifecyclePromises< ResultType = unknown, - MetaType = unknown + MetaType = unknown, > { /** * Promise that will resolve with the first value for this cache key. @@ -122,7 +122,7 @@ declare module '../../endpointDefinitions' { QueryArg, BaseQuery extends BaseQueryFn, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > extends QueryBaseLifecycleApi, CacheLifecyclePromises> {} @@ -130,7 +130,7 @@ declare module '../../endpointDefinitions' { QueryArg, BaseQuery extends BaseQueryFn, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > extends MutationBaseLifecycleApi< QueryArg, BaseQuery, @@ -144,11 +144,11 @@ declare module '../../endpointDefinitions' { ResultType, QueryArg, BaseQuery extends BaseQueryFn, - ReducerPath extends string = string + ReducerPath extends string = string, > { onCacheEntryAdded?( arg: QueryArg, - api: QueryCacheLifecycleApi + api: QueryCacheLifecycleApi, ): Promise | void } @@ -157,7 +157,7 @@ declare module '../../endpointDefinitions' { ResultType, QueryArg, BaseQuery extends BaseQueryFn, - ReducerPath extends string = string + ReducerPath extends string = string, > { onCacheEntryAdded?( arg: QueryArg, @@ -166,13 +166,13 @@ declare module '../../endpointDefinitions' { BaseQuery, ResultType, ReducerPath - > + >, ): Promise | void } } const neverResolvedError = new Error( - 'Promise never resolved before cacheEntryRemoved.' + 'Promise never resolved before cacheEntryRemoved.', ) as Error & { message: 'Promise never resolved before cacheEntryRemoved.' } @@ -198,7 +198,7 @@ export const buildCacheLifecycleHandler: InternalHandlerBuilder = ({ const handler: ApiMiddlewareInternalHandler = ( action, mwApi, - stateBefore + stateBefore, ) => { const cacheKey = getCacheKey(action) @@ -211,7 +211,7 @@ export const buildCacheLifecycleHandler: InternalHandlerBuilder = ({ action.meta.arg.originalArgs, cacheKey, mwApi, - action.meta.requestId + action.meta.requestId, ) } } else if (mutationThunk.pending.match(action)) { @@ -222,7 +222,7 @@ export const buildCacheLifecycleHandler: InternalHandlerBuilder = ({ action.meta.arg.originalArgs, cacheKey, mwApi, - action.meta.requestId + action.meta.requestId, ) } } else if (isFulfilledThunk(action)) { @@ -253,7 +253,9 @@ export const buildCacheLifecycleHandler: InternalHandlerBuilder = ({ function getCacheKey(action: any) { if (isQueryThunk(action)) return action.meta.arg.queryCacheKey - if (isMutationThunk(action)) return action.meta.requestId + if (isMutationThunk(action)) { + return action.meta.arg.fixedCacheKey ?? action.meta.requestId + } if (api.internalActions.removeQueryResult.match(action)) return action.payload.queryCacheKey if (api.internalActions.removeMutationResult.match(action)) @@ -266,7 +268,7 @@ export const buildCacheLifecycleHandler: InternalHandlerBuilder = ({ originalArgs: any, queryCacheKey: string, mwApi: SubMiddlewareApi, - requestId: string + requestId: string, ) { const endpointDefinition = context.endpointDefinitions[endpointName] const onCacheEntryAdded = endpointDefinition?.onCacheEntryAdded @@ -295,7 +297,7 @@ export const buildCacheLifecycleHandler: InternalHandlerBuilder = ({ const selector = (api.endpoints[endpointName] as any).select( endpointDefinition.type === DefinitionType.query ? originalArgs - : queryCacheKey + : queryCacheKey, ) const extra = mwApi.dispatch((_, __, extra) => extra) @@ -310,8 +312,8 @@ export const buildCacheLifecycleHandler: InternalHandlerBuilder = ({ api.util.updateQueryData( endpointName as never, originalArgs, - updateRecipe - ) + updateRecipe, + ), ) : undefined) as any, diff --git a/packages/toolkit/src/query/core/buildMiddleware/index.ts b/packages/toolkit/src/query/core/buildMiddleware/index.ts index eecd189e84..4c44107368 100644 --- a/packages/toolkit/src/query/core/buildMiddleware/index.ts +++ b/packages/toolkit/src/query/core/buildMiddleware/index.ts @@ -29,7 +29,7 @@ import { buildBatchedActionsHandler } from './batchActions' export function buildMiddleware< Definitions extends EndpointDefinitions, ReducerPath extends string, - TagTypes extends string + TagTypes extends string, >(input: BuildMiddlewareInput) { const { reducerPath, queryThunk, api, context } = input const { apiUid } = context @@ -136,7 +136,7 @@ export function buildMiddleware< { status: QueryStatus.uninitialized } >, queryCacheKey: string, - override: Partial = {} + override: Partial = {}, ) { return queryThunk({ type: 'query', diff --git a/packages/toolkit/src/query/core/buildMiddleware/invalidationByTags.ts b/packages/toolkit/src/query/core/buildMiddleware/invalidationByTags.ts index 4334d4f813..150406a863 100644 --- a/packages/toolkit/src/query/core/buildMiddleware/invalidationByTags.ts +++ b/packages/toolkit/src/query/core/buildMiddleware/invalidationByTags.ts @@ -35,12 +35,12 @@ export const buildInvalidationByTagsHandler: InternalHandlerBuilder = ({ const { removeQueryResult } = api.internalActions const isThunkActionWithTags = isAnyOf( isFulfilled(mutationThunk), - isRejectedWithValue(mutationThunk) + isRejectedWithValue(mutationThunk), ) const isQueryEnd = isAnyOf( isFulfilled(mutationThunk, queryThunk), - isRejected(mutationThunk, queryThunk) + isRejected(mutationThunk, queryThunk), ) let pendingTagInvalidations: FullTagDescription[] = [] @@ -52,9 +52,9 @@ export const buildInvalidationByTagsHandler: InternalHandlerBuilder = ({ action, 'invalidatesTags', endpointDefinitions, - assertTagType + assertTagType, ), - mwApi + mwApi, ) } else if (isQueryEnd(action)) { invalidateTags([], mwApi) @@ -66,33 +66,38 @@ export const buildInvalidationByTagsHandler: InternalHandlerBuilder = ({ undefined, undefined, undefined, - assertTagType + assertTagType, ), - mwApi + mwApi, ) } } - function hasPendingRequests(state: CombinedState) { + function hasPendingRequests( + state: CombinedState, + ) { for (const key in state.queries) { - if (state.queries[key]?.status === QueryStatus.pending) return true; + if (state.queries[key]?.status === QueryStatus.pending) return true } for (const key in state.mutations) { - if (state.mutations[key]?.status === QueryStatus.pending) return true; + if (state.mutations[key]?.status === QueryStatus.pending) return true } - return false; + return false } function invalidateTags( newTags: readonly FullTagDescription[], - mwApi: SubMiddlewareApi + mwApi: SubMiddlewareApi, ) { const rootState = mwApi.getState() const state = rootState[reducerPath] pendingTagInvalidations.push(...newTags) - if (state.config.invalidationBehavior === 'delayed' && hasPendingRequests(state)) { + if ( + state.config.invalidationBehavior === 'delayed' && + hasPendingRequests(state) + ) { return } @@ -114,7 +119,7 @@ export const buildInvalidationByTagsHandler: InternalHandlerBuilder = ({ mwApi.dispatch( removeQueryResult({ queryCacheKey: queryCacheKey as QueryCacheKey, - }) + }), ) } else if (querySubState.status !== QueryStatus.uninitialized) { mwApi.dispatch(refetchQuery(querySubState, queryCacheKey)) diff --git a/packages/toolkit/src/query/core/buildMiddleware/polling.ts b/packages/toolkit/src/query/core/buildMiddleware/polling.ts index 839a3a5243..6bee83fae4 100644 --- a/packages/toolkit/src/query/core/buildMiddleware/polling.ts +++ b/packages/toolkit/src/query/core/buildMiddleware/polling.ts @@ -51,7 +51,7 @@ export const buildPollingHandler: InternalHandlerBuilder = ({ function startNextPoll( { queryCacheKey }: QuerySubstateIdentifier, - api: SubMiddlewareApi + api: SubMiddlewareApi, ) { const state = api.getState()[reducerPath] const querySubState = state.queries[queryCacheKey] @@ -60,7 +60,8 @@ export const buildPollingHandler: InternalHandlerBuilder = ({ if (!querySubState || querySubState.status === QueryStatus.uninitialized) return - const lowestPollingInterval = findLowestPollingInterval(subscriptions) + const { lowestPollingInterval, skipPollingIfUnfocused } = + findLowestPollingInterval(subscriptions) if (!Number.isFinite(lowestPollingInterval)) return const currentPoll = currentPolls[queryCacheKey] @@ -72,21 +73,21 @@ export const buildPollingHandler: InternalHandlerBuilder = ({ const nextPollTimestamp = Date.now() + lowestPollingInterval - const currentInterval: typeof currentPolls[number] = (currentPolls[ - queryCacheKey - ] = { + currentPolls[queryCacheKey] = { nextPollTimestamp, pollingInterval: lowestPollingInterval, timeout: setTimeout(() => { - currentInterval!.timeout = undefined - api.dispatch(refetchQuery(querySubState, queryCacheKey)) + if (state.config.focused || !skipPollingIfUnfocused) { + api.dispatch(refetchQuery(querySubState, queryCacheKey)) + } + startNextPoll({ queryCacheKey }, api) }, lowestPollingInterval), - }) + } } function updatePollingInterval( { queryCacheKey }: QuerySubstateIdentifier, - api: SubMiddlewareApi + api: SubMiddlewareApi, ) { const state = api.getState()[reducerPath] const querySubState = state.queries[queryCacheKey] @@ -96,7 +97,7 @@ export const buildPollingHandler: InternalHandlerBuilder = ({ return } - const lowestPollingInterval = findLowestPollingInterval(subscriptions) + const { lowestPollingInterval } = findLowestPollingInterval(subscriptions) if (!Number.isFinite(lowestPollingInterval)) { cleanupPollForKey(queryCacheKey) @@ -126,17 +127,24 @@ export const buildPollingHandler: InternalHandlerBuilder = ({ } function findLowestPollingInterval(subscribers: Subscribers = {}) { + let skipPollingIfUnfocused: boolean | undefined = false let lowestPollingInterval = Number.POSITIVE_INFINITY for (let key in subscribers) { if (!!subscribers[key].pollingInterval) { lowestPollingInterval = Math.min( subscribers[key].pollingInterval!, - lowestPollingInterval + lowestPollingInterval, ) + skipPollingIfUnfocused = + subscribers[key].skipPollingIfUnfocused || skipPollingIfUnfocused } } - return lowestPollingInterval + return { + lowestPollingInterval, + skipPollingIfUnfocused, + } } + return handler } diff --git a/packages/toolkit/src/query/core/buildMiddleware/queryLifecycle.ts b/packages/toolkit/src/query/core/buildMiddleware/queryLifecycle.ts index 580581238c..ebb47b771c 100644 --- a/packages/toolkit/src/query/core/buildMiddleware/queryLifecycle.ts +++ b/packages/toolkit/src/query/core/buildMiddleware/queryLifecycle.ts @@ -19,7 +19,7 @@ export type ReferenceQueryLifecycle = never declare module '../../endpointDefinitions' { export interface QueryLifecyclePromises< ResultType, - BaseQuery extends BaseQueryFn + BaseQuery extends BaseQueryFn, > { /** * Promise that will resolve with the (transformed) query result. @@ -72,7 +72,7 @@ declare module '../../endpointDefinitions' { ResultType, QueryArg, BaseQuery extends BaseQueryFn, - ReducerPath extends string = string + ReducerPath extends string = string, > { /** * A function that is called when the individual query is started. The function is called with a lifecycle api object containing properties such as `queryFulfilled`, allowing code to be run when a query is started, when it succeeds, and when it fails (i.e. throughout the lifecycle of an individual query/mutation call). @@ -114,7 +114,7 @@ declare module '../../endpointDefinitions' { */ onQueryStarted?( arg: QueryArg, - api: QueryLifecycleApi + api: QueryLifecycleApi, ): Promise | void } @@ -123,7 +123,7 @@ declare module '../../endpointDefinitions' { ResultType, QueryArg, BaseQuery extends BaseQueryFn, - ReducerPath extends string = string + ReducerPath extends string = string, > { /** * A function that is called when the individual mutation is started. The function is called with a lifecycle api object containing properties such as `queryFulfilled`, allowing code to be run when a query is started, when it succeeds, and when it fails (i.e. throughout the lifecycle of an individual query/mutation call). @@ -175,7 +175,7 @@ declare module '../../endpointDefinitions' { */ onQueryStarted?( arg: QueryArg, - api: MutationLifecycleApi + api: MutationLifecycleApi, ): Promise | void } @@ -183,7 +183,7 @@ declare module '../../endpointDefinitions' { QueryArg, BaseQuery extends BaseQueryFn, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > extends QueryBaseLifecycleApi, QueryLifecyclePromises {} @@ -191,7 +191,7 @@ declare module '../../endpointDefinitions' { QueryArg, BaseQuery extends BaseQueryFn, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > extends MutationBaseLifecycleApi< QueryArg, BaseQuery, @@ -242,7 +242,7 @@ export const buildQueryLifecycleHandler: InternalHandlerBuilder = ({ const selector = (api.endpoints[endpointName] as any).select( endpointDefinition.type === DefinitionType.query ? originalArgs - : requestId + : requestId, ) const extra = mwApi.dispatch((_, __, extra) => extra) @@ -257,8 +257,8 @@ export const buildQueryLifecycleHandler: InternalHandlerBuilder = ({ api.util.updateQueryData( endpointName as never, originalArgs, - updateRecipe - ) + updateRecipe, + ), ) : undefined) as any, queryFulfilled, diff --git a/packages/toolkit/src/query/core/buildMiddleware/types.ts b/packages/toolkit/src/query/core/buildMiddleware/types.ts index 2e41e095f7..e2ab377b6c 100644 --- a/packages/toolkit/src/query/core/buildMiddleware/types.ts +++ b/packages/toolkit/src/query/core/buildMiddleware/types.ts @@ -41,7 +41,7 @@ export interface SubscriptionSelectors { export interface BuildMiddlewareInput< Definitions extends EndpointDefinitions, ReducerPath extends string, - TagTypes extends string + TagTypes extends string, > { reducerPath: ReducerPath context: ApiContext @@ -65,13 +65,13 @@ export interface BuildSubMiddlewareInput { status: QueryStatus.uninitialized } >, queryCacheKey: string, - override?: Partial + override?: Partial, ): AsyncThunkAction isThisApiSliceAction: (action: Action) => boolean } export type SubMiddlewareBuilder = ( - input: BuildSubMiddlewareInput + input: BuildSubMiddlewareInput, ) => Middleware< {}, RootState, @@ -83,11 +83,11 @@ type MwNext = Parameters>[0] export type ApiMiddlewareInternalHandler = ( action: Action, mwApi: SubMiddlewareApi & { next: MwNext }, - prevState: RootState + prevState: RootState, ) => Return export type InternalHandlerBuilder = ( - input: BuildSubMiddlewareInput + input: BuildSubMiddlewareInput, ) => ApiMiddlewareInternalHandler export interface PromiseConstructorWithKnownReason { @@ -100,8 +100,8 @@ export interface PromiseConstructorWithKnownReason { new ( executor: ( resolve: (value: T | PromiseLike) => void, - reject: (reason?: R) => void - ) => void + reject: (reason?: R) => void, + ) => void, ): PromiseWithKnownReason } @@ -121,7 +121,7 @@ export interface PromiseWithKnownReason onrejected?: | ((reason: R) => TResult2 | PromiseLike) | undefined - | null + | null, ): Promise /** @@ -133,6 +133,6 @@ export interface PromiseWithKnownReason onrejected?: | ((reason: R) => TResult | PromiseLike) | undefined - | null + | null, ): Promise } diff --git a/packages/toolkit/src/query/core/buildMiddleware/windowEventHandling.ts b/packages/toolkit/src/query/core/buildMiddleware/windowEventHandling.ts index 409bc56e08..d59df2eaa5 100644 --- a/packages/toolkit/src/query/core/buildMiddleware/windowEventHandling.ts +++ b/packages/toolkit/src/query/core/buildMiddleware/windowEventHandling.ts @@ -28,7 +28,7 @@ export const buildWindowEventHandler: InternalHandlerBuilder = ({ function refetchValidQueries( api: SubMiddlewareApi, - type: 'refetchOnFocus' | 'refetchOnReconnect' + type: 'refetchOnFocus' | 'refetchOnReconnect', ) { const state = api.getState()[reducerPath] const queries = state.queries @@ -43,10 +43,10 @@ export const buildWindowEventHandler: InternalHandlerBuilder = ({ const shouldRefetch = Object.values(subscriptionSubState).some( - (sub) => sub[type] === true + (sub) => sub[type] === true, ) || (Object.values(subscriptionSubState).every( - (sub) => sub[type] === undefined + (sub) => sub[type] === undefined, ) && state.config[type]) @@ -55,7 +55,7 @@ export const buildWindowEventHandler: InternalHandlerBuilder = ({ api.dispatch( removeQueryResult({ queryCacheKey: queryCacheKey as QueryCacheKey, - }) + }), ) } else if (querySubState.status !== QueryStatus.uninitialized) { api.dispatch(refetchQuery(querySubState, queryCacheKey)) diff --git a/packages/toolkit/src/query/core/buildSelectors.ts b/packages/toolkit/src/query/core/buildSelectors.ts index efd48b8170..4ca49fc3e4 100644 --- a/packages/toolkit/src/query/core/buildSelectors.ts +++ b/packages/toolkit/src/query/core/buildSelectors.ts @@ -1,4 +1,5 @@ -import { createNextState, createSelector } from './rtkImports' +import type { createSelector as _createSelector } from './rtkImports' +import { createNextState } from './rtkImports' import type { MutationSubState, QuerySubState, @@ -51,7 +52,7 @@ export const skipToken = /* @__PURE__ */ Symbol.for('RTKQ/skipToken') declare module './module' { export interface ApiEndpointQuery< Definition extends QueryDefinition, - Definitions extends EndpointDefinitions + Definitions extends EndpointDefinitions, > { select: QueryResultSelectorFactory< Definition, @@ -65,7 +66,7 @@ declare module './module' { export interface ApiEndpointMutation< Definition extends MutationDefinition, - Definitions extends EndpointDefinitions + Definitions extends EndpointDefinitions, > { select: MutationResultSelectorFactory< Definition, @@ -80,27 +81,27 @@ declare module './module' { type QueryResultSelectorFactory< Definition extends QueryDefinition, - RootState + RootState, > = ( - queryArg: QueryArgFrom | SkipToken + queryArg: QueryArgFrom | SkipToken, ) => (state: RootState) => QueryResultSelectorResult export type QueryResultSelectorResult< - Definition extends QueryDefinition + Definition extends QueryDefinition, > = QuerySubState & RequestStatusFlags type MutationResultSelectorFactory< Definition extends MutationDefinition, - RootState + RootState, > = ( requestId: | string | { requestId: string | undefined; fixedCacheKey: string | undefined } - | SkipToken + | SkipToken, ) => (state: RootState) => MutationResultSelectorResult export type MutationResultSelectorResult< - Definition extends MutationDefinition + Definition extends MutationDefinition, > = MutationSubState & RequestStatusFlags const initialSubState: QuerySubState = { @@ -110,22 +111,24 @@ const initialSubState: QuerySubState = { // abuse immer to freeze default states const defaultQuerySubState = /* @__PURE__ */ createNextState( initialSubState, - () => {} + () => {}, ) const defaultMutationSubState = /* @__PURE__ */ createNextState( initialSubState as MutationSubState, - () => {} + () => {}, ) export function buildSelectors< Definitions extends EndpointDefinitions, - ReducerPath extends string + ReducerPath extends string, >({ serializeQueryArgs, reducerPath, + createSelector, }: { serializeQueryArgs: InternalSerializeQueryArgs reducerPath: ReducerPath + createSelector: typeof _createSelector }) { type RootState = _RootState @@ -140,7 +143,7 @@ export function buildSelectors< } function withRequestFlags( - substate: T + substate: T, ): T & RequestStatusFlags { return { ...substate, @@ -155,7 +158,7 @@ export function buildSelectors< if ((selectInternalState as any).triggered) return state ;(selectInternalState as any).triggered = true console.error( - `Error: No data found at \`state.${reducerPath}\`. Did you forget to add the reducer to the store?` + `Error: No data found at \`state.${reducerPath}\`. Did you forget to add the reducer to the store?`, ) } } @@ -164,7 +167,7 @@ export function buildSelectors< function buildQuerySelector( endpointName: string, - endpointDefinition: QueryDefinition + endpointDefinition: QueryDefinition, ) { return ((queryArgs: any) => { const serializedArgs = serializeQueryArgs({ @@ -204,7 +207,7 @@ export function buildSelectors< function selectInvalidatedBy( state: RootState, - tags: ReadonlyArray> + tags: ReadonlyArray>, ): Array<{ endpointName: string originalArgs: any @@ -242,24 +245,24 @@ export function buildSelectors< }, ] : [] - }) + }), ) } function selectCachedArgsForQuery>( state: RootState, - queryName: QueryName + queryName: QueryName, ): Array> { return Object.values(state[reducerPath].queries as QueryState) .filter( ( - entry + entry, ): entry is Exclude< QuerySubState, { status: QueryStatus.uninitialized } > => entry?.endpointName === queryName && - entry.status !== QueryStatus.uninitialized + entry.status !== QueryStatus.uninitialized, ) .map((entry) => entry.originalArgs) } diff --git a/packages/toolkit/src/query/core/buildSlice.ts b/packages/toolkit/src/query/core/buildSlice.ts index bb712281a9..f609e3a989 100644 --- a/packages/toolkit/src/query/core/buildSlice.ts +++ b/packages/toolkit/src/query/core/buildSlice.ts @@ -46,7 +46,7 @@ import { isUpsertQuery } from './buildInitiate' function updateQuerySubstateIfExists( state: QueryState, queryCacheKey: QueryCacheKey, - update: (substate: QuerySubState) => void + update: (substate: QuerySubState) => void, ) { const substate = state[queryCacheKey] if (substate) { @@ -57,7 +57,7 @@ function updateQuerySubstateIfExists( export function getMutationCacheKey( id: | MutationSubstateIdentifier - | { requestId: string; arg: { fixedCacheKey?: string | undefined } } + | { requestId: string; arg: { fixedCacheKey?: string | undefined } }, ): string export function getMutationCacheKey(id: { fixedCacheKey?: string @@ -68,7 +68,7 @@ export function getMutationCacheKey( id: | { fixedCacheKey?: string; requestId?: string } | MutationSubstateIdentifier - | { requestId: string; arg: { fixedCacheKey?: string | undefined } } + | { requestId: string; arg: { fixedCacheKey?: string | undefined } }, ): string | undefined { return ('arg' in id ? id.arg.fixedCacheKey : id.fixedCacheKey) ?? id.requestId } @@ -78,7 +78,7 @@ function updateMutationSubstateIfExists( id: | MutationSubstateIdentifier | { requestId: string; arg: { fixedCacheKey?: string | undefined } }, - update: (substate: MutationSubState) => void + update: (substate: MutationSubState) => void, ) { const substate = state[getMutationCacheKey(id)] if (substate) { @@ -119,7 +119,9 @@ export function buildSlice({ removeQueryResult: { reducer( draft, - { payload: { queryCacheKey } }: PayloadAction + { + payload: { queryCacheKey }, + }: PayloadAction, ) { delete draft[queryCacheKey] }, @@ -132,7 +134,7 @@ export function buildSlice({ payload: { queryCacheKey, patches }, }: PayloadAction< QuerySubstateIdentifier & { patches: readonly Patch[] } - > + >, ) { updateQuerySubstateIfExists(draft, queryCacheKey, (substate) => { substate.data = applyPatches(substate.data as any, patches.concat()) @@ -200,7 +202,7 @@ export function buildSlice({ fulfilledTimeStamp, requestId, }) - } + }, ) substate.data = newData } else { @@ -215,14 +217,14 @@ export function buildSlice({ isDraft(substate.data) ? original(substate.data) : substate.data, - payload + payload, ) : payload } delete substate.error substate.fulfilledTimeStamp = meta.fulfilledTimeStamp - } + }, ) }) .addCase( @@ -240,9 +242,9 @@ export function buildSlice({ substate.status = QueryStatus.rejected substate.error = (payload ?? error) as any } - } + }, ) - } + }, ) .addMatcher(hasRehydrationInfo, (draft, action) => { const { queries } = extractRehydrationInfo(action)! @@ -285,7 +287,7 @@ export function buildSlice({ endpointName: arg.endpointName, startedTimeStamp, } - } + }, ) .addCase(mutationThunk.fulfilled, (draft, { payload, meta }) => { if (!meta.arg.track) return @@ -334,7 +336,7 @@ export function buildSlice({ action: PayloadAction<{ queryCacheKey: QueryCacheKey providedTags: readonly FullTagDescription[] - }> + }>, ) { const { queryCacheKey, providedTags } = action.payload @@ -370,7 +372,7 @@ export function buildSlice({ (draft, { payload: { queryCacheKey } }) => { for (const tagTypeSubscriptions of Object.values(draft)) { for (const idSubscriptions of Object.values( - tagTypeSubscriptions + tagTypeSubscriptions, )) { const foundAt = idSubscriptions.indexOf(queryCacheKey) if (foundAt !== -1) { @@ -378,7 +380,7 @@ export function buildSlice({ } } } - } + }, ) .addMatcher(hasRehydrationInfo, (draft, action) => { const { provided } = extractRehydrationInfo(action)! @@ -404,7 +406,7 @@ export function buildSlice({ action, 'providesTags', definitions, - assertTagType + assertTagType, ) const { queryCacheKey } = action.meta.arg @@ -413,9 +415,9 @@ export function buildSlice({ invalidationSlice.actions.updateProvidedBy({ queryCacheKey, providedTags, - }) + }), ) - } + }, ) }, }) @@ -433,13 +435,13 @@ export function buildSlice({ requestId: string options: Subscribers[number] } & QuerySubstateIdentifier - > + >, ) { // Dummy }, unsubscribeQueryResult( d, - a: PayloadAction<{ requestId: string } & QuerySubstateIdentifier> + a: PayloadAction<{ requestId: string } & QuerySubstateIdentifier>, ) { // Dummy }, diff --git a/packages/toolkit/src/query/core/buildThunks.ts b/packages/toolkit/src/query/core/buildThunks.ts index 70627228c4..2fe616bb7d 100644 --- a/packages/toolkit/src/query/core/buildThunks.ts +++ b/packages/toolkit/src/query/core/buildThunks.ts @@ -51,54 +51,55 @@ declare module './module' { export interface ApiEndpointQuery< Definition extends QueryDefinition, // eslint-disable-next-line @typescript-eslint/no-unused-vars - Definitions extends EndpointDefinitions + Definitions extends EndpointDefinitions, > extends Matchers {} export interface ApiEndpointMutation< Definition extends MutationDefinition, // eslint-disable-next-line @typescript-eslint/no-unused-vars - Definitions extends EndpointDefinitions + Definitions extends EndpointDefinitions, > extends Matchers {} } type EndpointThunk< Thunk extends QueryThunk | MutationThunk, - Definition extends EndpointDefinition -> = Definition extends EndpointDefinition< - infer QueryArg, - infer BaseQueryFn, - any, - infer ResultType -> - ? Thunk extends AsyncThunk - ? AsyncThunk< - ResultType, - ATArg & { originalArgs: QueryArg }, - ATConfig & { rejectValue: BaseQueryError } - > + Definition extends EndpointDefinition, +> = + Definition extends EndpointDefinition< + infer QueryArg, + infer BaseQueryFn, + any, + infer ResultType + > + ? Thunk extends AsyncThunk + ? AsyncThunk< + ResultType, + ATArg & { originalArgs: QueryArg }, + ATConfig & { rejectValue: BaseQueryError } + > + : never : never - : never export type PendingAction< Thunk extends QueryThunk | MutationThunk, - Definition extends EndpointDefinition + Definition extends EndpointDefinition, > = ReturnType['pending']> export type FulfilledAction< Thunk extends QueryThunk | MutationThunk, - Definition extends EndpointDefinition + Definition extends EndpointDefinition, > = ReturnType['fulfilled']> export type RejectedAction< Thunk extends QueryThunk | MutationThunk, - Definition extends EndpointDefinition + Definition extends EndpointDefinition, > = ReturnType['rejected']> export type Matcher = (value: any) => value is M export interface Matchers< Thunk extends QueryThunk | MutationThunk, - Definition extends EndpointDefinition + Definition extends EndpointDefinition, > { matchPending: Matcher> matchFulfilled: Matcher> @@ -156,36 +157,36 @@ function defaultTransformResponse(baseQueryReturnValue: unknown) { export type MaybeDrafted = T | Draft export type Recipe = (data: MaybeDrafted) => void | MaybeDrafted export type UpsertRecipe = ( - data: MaybeDrafted | undefined + data: MaybeDrafted | undefined, ) => void | MaybeDrafted export type PatchQueryDataThunk< Definitions extends EndpointDefinitions, - PartialState + PartialState, > = >( endpointName: EndpointName, args: QueryArgFrom, patches: readonly Patch[], - updateProvided?: boolean + updateProvided?: boolean, ) => ThunkAction export type UpdateQueryDataThunk< Definitions extends EndpointDefinitions, - PartialState + PartialState, > = >( endpointName: EndpointName, args: QueryArgFrom, updateRecipe: Recipe>, - updateProvided?: boolean + updateProvided?: boolean, ) => ThunkAction export type UpsertQueryDataThunk< Definitions extends EndpointDefinitions, - PartialState + PartialState, > = >( endpointName: EndpointName, args: QueryArgFrom, - value: ResultTypeFrom + value: ResultTypeFrom, ) => ThunkAction< QueryActionCreatorResult< Definitions[EndpointName] extends QueryDefinition @@ -218,7 +219,7 @@ export type PatchCollection = { export function buildThunks< BaseQuery extends BaseQueryFn, ReducerPath extends string, - Definitions extends EndpointDefinitions + Definitions extends EndpointDefinitions, >({ reducerPath, baseQuery, @@ -247,7 +248,7 @@ export function buildThunks< }) dispatch( - api.internalActions.queryResultPatched({ queryCacheKey, patches }) + api.internalActions.queryResultPatched({ queryCacheKey, patches }), ) if (!updateProvided) { @@ -256,7 +257,7 @@ export function buildThunks< const newValue = api.endpoints[endpointName].select(args)( // Work around TS 4.1 mismatch - getState() as RootState + getState() as RootState, ) const providedTags = calculateProvidedBy( @@ -265,11 +266,11 @@ export function buildThunks< undefined, args, {}, - assertTagType + assertTagType, ) dispatch( - api.internalActions.updateProvidedBy({ queryCacheKey, providedTags }) + api.internalActions.updateProvidedBy({ queryCacheKey, providedTags }), ) } @@ -280,7 +281,7 @@ export function buildThunks< const currentState = endpointDefinition.select(args)( // Work around TS 4.1 mismatch - getState() as RootState + getState() as RootState, ) let ret: PatchCollection = { @@ -292,8 +293,8 @@ export function buildThunks< endpointName, args, ret.inversePatches, - updateProvided - ) + updateProvided, + ), ), } if (currentState.status === QueryStatus.uninitialized) { @@ -304,7 +305,7 @@ export function buildThunks< if (isDraftable(currentState.data)) { const [value, patches, inversePatches] = produceWithPatches( currentState.data, - updateRecipe + updateRecipe, ) ret.patches.push(...patches) ret.inversePatches.push(...inversePatches) @@ -321,7 +322,12 @@ export function buildThunks< } dispatch( - api.util.patchQueryData(endpointName, args, ret.patches, updateProvided) + api.util.patchQueryData( + endpointName, + args, + ret.patches, + updateProvided, + ), ) return ret @@ -341,7 +347,7 @@ export function buildThunks< [forceQueryFnSymbol]: () => ({ data: value, }), - }) + }), ) } @@ -359,7 +365,7 @@ export function buildThunks< dispatch, getState, extra, - } + }, ) => { const endpointDefinition = endpointDefinitions[arg.endpointName] @@ -367,7 +373,7 @@ export function buildThunks< let transformResponse: ( baseQueryReturnValue: any, meta: any, - arg: any + arg: any, ) => any = defaultTransformResponse let result: QueryReturnValue const baseQueryApi = { @@ -390,7 +396,7 @@ export function buildThunks< result = await baseQuery( endpointDefinition.query(arg.originalArgs), baseQueryApi, - endpointDefinition.extraOptions as any + endpointDefinition.extraOptions as any, ) if (endpointDefinition.transformResponse) { @@ -402,7 +408,11 @@ export function buildThunks< baseQueryApi, endpointDefinition.extraOptions as any, (arg) => - baseQuery(arg, baseQueryApi, endpointDefinition.extraOptions as any) + baseQuery( + arg, + baseQueryApi, + endpointDefinition.extraOptions as any, + ), ) } if ( @@ -433,7 +443,7 @@ export function buildThunks< ${err} It needs to return an object with either the shape \`{ data: }\` or \`{ error: }\` that may contain an optional \`meta\` property. Object returned was:`, - result + result, ) } } @@ -446,7 +456,7 @@ export function buildThunks< fulfilledTimeStamp: Date.now(), baseQueryMeta: result.meta, [SHOULD_AUTOBATCH]: true, - } + }, ) } catch (error) { let catchedError = error @@ -454,7 +464,7 @@ export function buildThunks< let transformErrorResponse: ( baseQueryReturnValue: any, meta: any, - arg: any + arg: any, ) => any = defaultTransformResponse if ( @@ -468,9 +478,9 @@ export function buildThunks< await transformErrorResponse( catchedError.value, catchedError.meta, - arg.originalArgs + arg.originalArgs, ), - { baseQueryMeta: catchedError.meta, [SHOULD_AUTOBATCH]: true } + { baseQueryMeta: catchedError.meta, [SHOULD_AUTOBATCH]: true }, ) } catch (e) { catchedError = e @@ -483,7 +493,7 @@ export function buildThunks< console.error( `An unhandled error occurred processing a request for the endpoint "${arg.endpointName}". In the case of an unhandled error, no tags will be "provided" or "invalidated".`, - catchedError + catchedError, ) } else { console.error(catchedError) @@ -494,7 +504,7 @@ In the case of an unhandled error, no tags will be "provided" or "invalidated".` function isForcedQuery( arg: QueryThunkArg, - state: RootState + state: RootState, ) { const requestState = state[reducerPath]?.queries?.[arg.queryCacheKey] const baseFetchOnMountOrArgChange = @@ -586,14 +596,14 @@ In the case of an unhandled error, no tags will be "provided" or "invalidated".` const hasTheForce = (options: any): options is { force: boolean } => 'force' in options const hasMaxAge = ( - options: any + options: any, ): options is { ifOlderThan: false | number } => 'ifOlderThan' in options const prefetch = >( endpointName: EndpointName, arg: any, - options: PrefetchOptions + options: PrefetchOptions, ): ThunkAction => (dispatch: ThunkDispatch, getState: () => any) => { const force = hasTheForce(options) && options.force @@ -602,7 +612,7 @@ In the case of an unhandled error, no tags will be "provided" or "invalidated".` const queryAction = (force: boolean = true) => (api.endpoints[endpointName] as ApiEndpointQuery).initiate( arg, - { forceRefetch: force } + { forceRefetch: force }, ) const latestStateValue = ( api.endpoints[endpointName] as ApiEndpointQuery @@ -636,13 +646,13 @@ In the case of an unhandled error, no tags will be "provided" or "invalidated".` function buildMatchThunkActions< Thunk extends | AsyncThunk - | AsyncThunk + | AsyncThunk, >(thunk: Thunk, endpointName: string) { return { matchPending: isAllOf(isPending(thunk), matchesEndpoint(endpointName)), matchFulfilled: isAllOf( isFulfilled(thunk), - matchesEndpoint(endpointName) + matchesEndpoint(endpointName), ), matchRejected: isAllOf(isRejected(thunk), matchesEndpoint(endpointName)), } as Matchers @@ -665,7 +675,7 @@ export function calculateProvidedByThunk( >, type: 'providesTags' | 'invalidatesTags', endpointDefinitions: EndpointDefinitions, - assertTagType: AssertTagTypes + assertTagType: AssertTagTypes, ) { return calculateProvidedBy( endpointDefinitions[action.meta.arg.endpointName][type], @@ -673,6 +683,6 @@ export function calculateProvidedByThunk( isRejectedWithValue(action) ? action.payload : undefined, action.meta.arg.originalArgs, 'baseQueryMeta' in action.meta ? action.meta.baseQueryMeta : undefined, - assertTagType + assertTagType, ) } diff --git a/packages/toolkit/src/query/core/module.ts b/packages/toolkit/src/query/core/module.ts index bc95e8df4e..c237c7b298 100644 --- a/packages/toolkit/src/query/core/module.ts +++ b/packages/toolkit/src/query/core/module.ts @@ -49,6 +49,7 @@ import type { ReferenceCacheLifecycle } from './buildMiddleware/cacheLifecycle' import type { ReferenceQueryLifecycle } from './buildMiddleware/queryLifecycle' import type { ReferenceCacheCollection } from './buildMiddleware/cacheCollection' import { enablePatches } from 'immer' +import { createSelector as _createSelector } from './rtkImports' /** * `ifOlderThan` - (default: `false` | `number`) - _number is value in seconds_ @@ -80,7 +81,7 @@ declare module '../apiTypes' { BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string, - TagTypes extends string + TagTypes extends string, > { [coreModuleName]: { /** @@ -152,7 +153,7 @@ declare module '../apiTypes' { */ getRunningQueryThunk>( endpointName: EndpointName, - args: QueryArgFrom + args: QueryArgFrom, ): ThunkWithReturnValue< | QueryActionCreatorResult< Definitions[EndpointName] & { type: 'query' } @@ -172,7 +173,7 @@ declare module '../apiTypes' { */ getRunningMutationThunk>( endpointName: EndpointName, - fixedCacheKeyOrRequestId: string + fixedCacheKeyOrRequestId: string, ): ThunkWithReturnValue< | MutationActionCreatorResult< Definitions[EndpointName] & { type: 'mutation' } @@ -220,7 +221,7 @@ declare module '../apiTypes' { prefetch>( endpointName: EndpointName, arg: QueryArgFrom, - options: PrefetchOptions + options: PrefetchOptions, ): ThunkAction /** * A Redux thunk action creator that, when dispatched, creates and applies a set of JSON diff/patch objects to the current state. This immediately updates the Redux state with those changes. @@ -350,7 +351,7 @@ declare module '../apiTypes' { */ selectInvalidatedBy: ( state: RootState, - tags: ReadonlyArray> + tags: ReadonlyArray>, ) => Array<{ endpointName: string originalArgs: any @@ -364,7 +365,7 @@ declare module '../apiTypes' { */ selectCachedArgsForQuery: >( state: RootState, - queryName: QueryName + queryName: QueryName, ) => Array> } /** @@ -380,8 +381,8 @@ declare module '../apiTypes' { > ? ApiEndpointQuery : Definitions[K] extends MutationDefinition - ? ApiEndpointMutation - : never + ? ApiEndpointMutation + : never } } } @@ -391,7 +392,7 @@ export interface ApiEndpointQuery< // eslint-disable-next-line @typescript-eslint/no-unused-vars Definition extends QueryDefinition, // eslint-disable-next-line @typescript-eslint/no-unused-vars - Definitions extends EndpointDefinitions + Definitions extends EndpointDefinitions, > { name: string /** @@ -405,7 +406,7 @@ export interface ApiEndpointMutation< // eslint-disable-next-line @typescript-eslint/no-unused-vars Definition extends MutationDefinition, // eslint-disable-next-line @typescript-eslint/no-unused-vars - Definitions extends EndpointDefinitions + Definitions extends EndpointDefinitions, > { name: string /** @@ -431,6 +432,13 @@ export type ListenerActions = { export type InternalActions = SliceActions & ListenerActions +export interface CoreModuleOptions { + /** + * A selector creator (usually from `reselect`, or matching the same signature) + */ + createSelector?: typeof _createSelector +} + /** * Creates a module containing the basic redux logic for use with `buildCreateApi`. * @@ -439,7 +447,9 @@ export type InternalActions = SliceActions & ListenerActions * const createBaseApi = buildCreateApi(coreModule()); * ``` */ -export const coreModule = (): Module => ({ +export const coreModule = ({ + createSelector = _createSelector, +}: CoreModuleOptions = {}): Module => ({ name: coreModuleName, init( api, @@ -454,7 +464,7 @@ export const coreModule = (): Module => ({ refetchOnReconnect, invalidationBehavior, }, - context + context, ) { enablePatches() @@ -467,7 +477,7 @@ export const coreModule = (): Module => ({ ) { if (!tagTypes.includes(tag.type as any)) { console.error( - `Tag type '${tag.type}' was used, but not specified in \`tagTypes\`!` + `Tag type '${tag.type}' was used, but not specified in \`tagTypes\`!`, ) } } @@ -548,6 +558,7 @@ export const coreModule = (): Module => ({ } = buildSelectors({ serializeQueryArgs: serializeQueryArgs as any, reducerPath, + createSelector, }) safeAssign(api.util, { selectInvalidatedBy, selectCachedArgsForQuery }) @@ -593,7 +604,7 @@ export const coreModule = (): Module => ({ select: buildQuerySelector(endpointName, definition), initiate: buildInitiateQuery(endpointName, definition), }, - buildMatchThunkActions(queryThunk, endpointName) + buildMatchThunkActions(queryThunk, endpointName), ) } else if (isMutationDefinition(definition)) { safeAssign( @@ -603,7 +614,7 @@ export const coreModule = (): Module => ({ select: buildMutationSelector(), initiate: buildInitiateMutation(endpointName), }, - buildMatchThunkActions(mutationThunk, endpointName) + buildMatchThunkActions(mutationThunk, endpointName), ) } }, diff --git a/packages/toolkit/src/query/core/setupListeners.ts b/packages/toolkit/src/query/core/setupListeners.ts index 01df593906..1c52042738 100644 --- a/packages/toolkit/src/query/core/setupListeners.ts +++ b/packages/toolkit/src/query/core/setupListeners.ts @@ -36,8 +36,8 @@ export function setupListeners( onFocusLost: typeof onFocusLost onOnline: typeof onOnline onOffline: typeof onOffline - } - ) => () => void + }, + ) => () => void, ) { function defaultHandler() { const handleFocus = () => dispatch(onFocus()) @@ -58,7 +58,7 @@ export function setupListeners( window.addEventListener( 'visibilitychange', handleVisibilityChange, - false + false, ) window.addEventListener('focus', handleFocus, false) diff --git a/packages/toolkit/src/query/createApi.ts b/packages/toolkit/src/query/createApi.ts index ed22f4ec9e..2a9eb4e9a2 100644 --- a/packages/toolkit/src/query/createApi.ts +++ b/packages/toolkit/src/query/createApi.ts @@ -17,7 +17,7 @@ export interface CreateApiOptions< BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', - TagTypes extends string = never + TagTypes extends string = never, > { /** * The base query used by each endpoint if no `queryFn` option is specified. RTK Query exports a utility called [fetchBaseQuery](./fetchBaseQuery) as a lightweight wrapper around `fetch` for common use-cases. See [Customizing Queries](../../rtk-query/usage/customizing-queries) if `fetchBaseQuery` does not handle your requirements. @@ -97,7 +97,7 @@ export interface CreateApiOptions< * Endpoints are just a set of operations that you want to perform against your server. You define them as an object using the builder syntax. There are two basic endpoint types: [`query`](../../rtk-query/usage/queries) and [`mutation`](../../rtk-query/usage/mutations). */ endpoints( - build: EndpointBuilder + build: EndpointBuilder, ): Definitions /** * Defaults to `60` _(this value is in seconds)_. This is how long RTK Query will keep your data cached for **after** the last component unsubscribes. For example, if you query an endpoint, then unmount the component, then mount another component that makes the same request within the given time frame, the most recent value will be served from the cache. @@ -200,7 +200,7 @@ export interface CreateApiOptions< reducerPath, }: { reducerPath: ReducerPath - } + }, ) => | undefined | CombinedState< @@ -220,9 +220,9 @@ export type CreateApi = { BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', - TagTypes extends string = never + TagTypes extends string = never, >( - options: CreateApiOptions + options: CreateApiOptions, ): Api } @@ -256,7 +256,7 @@ export function buildCreateApi, ...Module[]]>( const extractRehydrationInfo = weakMapMemoize((action: UnknownAction) => options.extractRehydrationInfo?.(action, { reducerPath: (options.reducerPath ?? 'api') as any, - }) + }), ) const optionsWithDefaults: CreateApiOptions = { @@ -305,7 +305,7 @@ export function buildCreateApi, ...Module[]]>( apiUid: nanoid(), extractRehydrationInfo, hasRehydrationInfo: weakMapMemoize( - (action) => extractRehydrationInfo(action) != null + (action) => extractRehydrationInfo(action) != null, ), } @@ -321,14 +321,14 @@ export function buildCreateApi, ...Module[]]>( } if (endpoints) { for (const [endpointName, partialDefinition] of Object.entries( - endpoints + endpoints, )) { if (typeof partialDefinition === 'function') { partialDefinition(context.endpointDefinitions[endpointName]) } else { Object.assign( context.endpointDefinitions[endpointName] || {}, - partialDefinition + partialDefinition, ) } } @@ -338,19 +338,19 @@ export function buildCreateApi, ...Module[]]>( } as Api const initializedModules = modules.map((m) => - m.init(api as any, optionsWithDefaults as any, context) + m.init(api as any, optionsWithDefaults as any, context), ) function injectEndpoints( - inject: Parameters[0] + inject: Parameters[0], ) { const evaluatedEndpoints = inject.endpoints({ - query: (x) => ({ ...x, type: DefinitionType.query } as any), - mutation: (x) => ({ ...x, type: DefinitionType.mutation } as any), + query: (x) => ({ ...x, type: DefinitionType.query }) as any, + mutation: (x) => ({ ...x, type: DefinitionType.mutation }) as any, }) for (const [endpointName, definition] of Object.entries( - evaluatedEndpoints + evaluatedEndpoints, )) { if ( !inject.overrideExisting && @@ -361,7 +361,7 @@ export function buildCreateApi, ...Module[]]>( process.env.NODE_ENV === 'development' ) { console.error( - `called \`injectEndpoints\` to override already-existing endpointName ${endpointName} without specifying \`overrideExisting: true\`` + `called \`injectEndpoints\` to override already-existing endpointName ${endpointName} without specifying \`overrideExisting: true\``, ) } diff --git a/packages/toolkit/src/query/defaultSerializeQueryArgs.ts b/packages/toolkit/src/query/defaultSerializeQueryArgs.ts index e3fe011b44..fcfd63aeb9 100644 --- a/packages/toolkit/src/query/defaultSerializeQueryArgs.ts +++ b/packages/toolkit/src/query/defaultSerializeQueryArgs.ts @@ -25,7 +25,7 @@ export const defaultSerializeQueryArgs: SerializeQueryArgs = ({ acc[key] = (value as any)[key] return acc }, {}) - : value + : value, ) if (isPlainObject(queryArgs)) { cache?.set(queryArgs, stringified) diff --git a/packages/toolkit/src/query/endpointDefinitions.ts b/packages/toolkit/src/query/endpointDefinitions.ts index c5262184cd..1a552fae94 100644 --- a/packages/toolkit/src/query/endpointDefinitions.ts +++ b/packages/toolkit/src/query/endpointDefinitions.ts @@ -27,7 +27,7 @@ const baseQuery = /* @__PURE__ */ Symbol() interface EndpointDefinitionWithQuery< QueryArg, BaseQuery extends BaseQueryFn, - ResultType + ResultType, > { /** * `query` can be a function that returns either a `string` or an `object` which is passed to your `baseQuery`. If you are using [fetchBaseQuery](./fetchBaseQuery), this can return either a `string` or an `object` of properties in `FetchArgs`. If you use your own custom [`baseQuery`](../../rtk-query/usage/customizing-queries), you can customize this behavior to your liking. @@ -75,7 +75,7 @@ interface EndpointDefinitionWithQuery< transformResponse?( baseQueryReturnValue: BaseQueryResult, meta: BaseQueryMeta, - arg: QueryArg + arg: QueryArg, ): ResultType | Promise /** * A function to manipulate the data returned by a failed query or mutation. @@ -83,7 +83,7 @@ interface EndpointDefinitionWithQuery< transformErrorResponse?( baseQueryReturnValue: BaseQueryError, meta: BaseQueryMeta, - arg: QueryArg + arg: QueryArg, ): unknown /** * Defaults to `true`. @@ -103,7 +103,7 @@ interface EndpointDefinitionWithQuery< interface EndpointDefinitionWithQueryFn< QueryArg, BaseQuery extends BaseQueryFn, - ResultType + ResultType, > { /** * Can be used in place of `query` as an inline function that bypasses `baseQuery` completely for the endpoint. @@ -147,8 +147,14 @@ interface EndpointDefinitionWithQueryFn< arg: QueryArg, api: BaseQueryApi, extraOptions: BaseQueryExtraOptions, - baseQuery: (arg: Parameters[0]) => ReturnType - ): MaybePromise>> + baseQuery: (arg: Parameters[0]) => ReturnType, + ): MaybePromise< + QueryReturnValue< + ResultType, + BaseQueryError, + BaseQueryMeta + > + > query?: never transformResponse?: never transformErrorResponse?: never @@ -170,7 +176,7 @@ interface EndpointDefinitionWithQueryFn< export interface BaseEndpointTypes< QueryArg, BaseQuery extends BaseQueryFn, - ResultType + ResultType, > { QueryArg: QueryArg BaseQuery: BaseQuery @@ -180,7 +186,7 @@ export interface BaseEndpointTypes< export type BaseEndpointDefinition< QueryArg, BaseQuery extends BaseQueryFn, - ResultType + ResultType, > = ( | ([CastAny, {}>] extends [NEVER] ? never @@ -207,12 +213,12 @@ export type GetResultDescriptionFn< ResultType, QueryArg, ErrorType, - MetaType + MetaType, > = ( result: ResultType | undefined, error: ErrorType | undefined, arg: QueryArg, - meta: MetaType + meta: MetaType, ) => ReadonlyArray> export type FullTagDescription = { @@ -225,7 +231,7 @@ export type ResultDescription< ResultType, QueryArg, ErrorType, - MetaType + MetaType, > = | ReadonlyArray> | GetResultDescriptionFn @@ -235,7 +241,7 @@ export interface QueryTypes< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > extends BaseEndpointTypes { /** * The endpoint definition type. To be used with some internal generic types. @@ -260,7 +266,7 @@ export interface QueryExtraOptions< ResultType, QueryArg, BaseQuery extends BaseQueryFn, - ReducerPath extends string = string + ReducerPath extends string = string, > { type: DefinitionType.query /** @@ -439,7 +445,7 @@ export interface QueryExtraOptions< baseQueryMeta: BaseQueryMeta requestId: string fulfilledTimeStamp: number - } + }, ): ResultType | void /** @@ -500,7 +506,7 @@ export type QueryDefinition< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > = BaseEndpointDefinition & QueryExtraOptions @@ -509,7 +515,7 @@ export interface MutationTypes< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > extends BaseEndpointTypes { /** * The endpoint definition type. To be used with some internal generic types. @@ -534,7 +540,7 @@ export interface MutationExtraOptions< ResultType, QueryArg, BaseQuery extends BaseQueryFn, - ReducerPath extends string = string + ReducerPath extends string = string, > { type: DefinitionType.mutation /** @@ -605,7 +611,7 @@ export type MutationDefinition< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > = BaseEndpointDefinition & MutationExtraOptions @@ -614,7 +620,7 @@ export type EndpointDefinition< BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, - ReducerPath extends string = string + ReducerPath extends string = string, > = | QueryDefinition | MutationDefinition @@ -625,13 +631,13 @@ export type EndpointDefinitions = Record< > export function isQueryDefinition( - e: EndpointDefinition + e: EndpointDefinition, ): e is QueryDefinition { return e.type === DefinitionType.query } export function isMutationDefinition( - e: EndpointDefinition + e: EndpointDefinition, ): e is MutationDefinition { return e.type === DefinitionType.mutation } @@ -639,7 +645,7 @@ export function isMutationDefinition( export type EndpointBuilder< BaseQuery extends BaseQueryFn, TagTypes extends string, - ReducerPath extends string + ReducerPath extends string, > = { /** * An endpoint definition that retrieves data, and may provide tags to the cache. @@ -671,7 +677,7 @@ export type EndpointBuilder< definition: OmitFromUnion< QueryDefinition, 'type' - > + >, ): QueryDefinition /** * An endpoint definition that alters data on the server or will possibly invalidate the cache. @@ -709,7 +715,7 @@ export type EndpointBuilder< ReducerPath >, 'type' - > + >, ): MutationDefinition } @@ -723,14 +729,14 @@ export function calculateProvidedBy( error: ErrorType | undefined, queryArg: QueryArg, meta: MetaType | undefined, - assertTagTypes: AssertTagTypes + assertTagTypes: AssertTagTypes, ): readonly FullTagDescription[] { if (isFunction(description)) { return description( result as ResultType, error as undefined, queryArg, - meta as MetaType + meta as MetaType, ) .map(expandTagDescription) .map(assertTagTypes) @@ -746,7 +752,7 @@ function isFunction(t: T): t is Extract { } export function expandTagDescription( - description: TagDescription + description: TagDescription, ): FullTagDescription { return typeof description === 'string' ? { type: description } : description } @@ -757,29 +763,22 @@ export type ResultTypeFrom> = D extends BaseEndpointDefinition ? RT : unknown export type ReducerPathFrom< - D extends EndpointDefinition + D extends EndpointDefinition, > = D extends EndpointDefinition ? RP : unknown export type TagTypesFrom> = D extends EndpointDefinition ? RP : unknown -export type TagTypesFromApi = T extends Api - ? TagTypes - : never +export type TagTypesFromApi = + T extends Api ? TagTypes : never -export type DefinitionsFromApi = T extends Api< - any, - infer Definitions, - any, - any -> - ? Definitions - : never +export type DefinitionsFromApi = + T extends Api ? Definitions : never export type TransformedResponse< NewDefinitions extends EndpointDefinitions, K, - ResultType + ResultType, > = K extends keyof NewDefinitions ? NewDefinitions[K]['transformResponse'] extends undefined ? ResultType @@ -798,25 +797,25 @@ export type OverrideResultType = > ? QueryDefinition : Definition extends MutationDefinition< - infer QueryArg, - infer BaseQuery, - infer TagTypes, - any, - infer ReducerPath - > - ? MutationDefinition< - QueryArg, - BaseQuery, - TagTypes, - NewResultType, - ReducerPath - > - : never + infer QueryArg, + infer BaseQuery, + infer TagTypes, + any, + infer ReducerPath + > + ? MutationDefinition< + QueryArg, + BaseQuery, + TagTypes, + NewResultType, + ReducerPath + > + : never export type UpdateDefinitions< Definitions extends EndpointDefinitions, NewTagTypes extends string, - NewDefinitions extends EndpointDefinitions + NewDefinitions extends EndpointDefinitions, > = { [K in keyof Definitions]: Definitions[K] extends QueryDefinition< infer QueryArg, @@ -833,18 +832,18 @@ export type UpdateDefinitions< ReducerPath > : Definitions[K] extends MutationDefinition< - infer QueryArg, - infer BaseQuery, - any, - infer ResultType, - infer ReducerPath - > - ? MutationDefinition< - QueryArg, - BaseQuery, - NewTagTypes, - TransformedResponse, - ReducerPath - > - : never + infer QueryArg, + infer BaseQuery, + any, + infer ResultType, + infer ReducerPath + > + ? MutationDefinition< + QueryArg, + BaseQuery, + NewTagTypes, + TransformedResponse, + ReducerPath + > + : never } diff --git a/packages/toolkit/src/query/fakeBaseQuery.ts b/packages/toolkit/src/query/fakeBaseQuery.ts index 54def42b33..4e1c4f2270 100644 --- a/packages/toolkit/src/query/fakeBaseQuery.ts +++ b/packages/toolkit/src/query/fakeBaseQuery.ts @@ -15,7 +15,7 @@ export function fakeBaseQuery(): BaseQueryFn< > { return function () { throw new Error( - 'When using `fakeBaseQuery`, all queries & mutations must use the `queryFn` definition syntax.' + 'When using `fakeBaseQuery`, all queries & mutations must use the `queryFn` definition syntax.', ) } } diff --git a/packages/toolkit/src/query/fetchBaseQuery.ts b/packages/toolkit/src/query/fetchBaseQuery.ts index 055bf6f47b..00cf6e54ab 100644 --- a/packages/toolkit/src/query/fetchBaseQuery.ts +++ b/packages/toolkit/src/query/fetchBaseQuery.ts @@ -112,11 +112,11 @@ export type FetchBaseQueryArgs = { api: Pick< BaseQueryApi, 'getState' | 'extra' | 'endpoint' | 'type' | 'forced' - > + >, ) => MaybePromise fetchFn?: ( input: RequestInfo, - init?: RequestInit | undefined + init?: RequestInit | undefined, ) => Promise paramsSerializer?: (params: Record) => string /** @@ -209,7 +209,7 @@ export function fetchBaseQuery({ > { if (typeof fetch === 'undefined' && fetchFn === defaultFetchFn) { console.warn( - 'Warning: `fetch` is not available. Please supply a custom `fetchFn` property to use `fetchBaseQuery` on SSR environments.' + 'Warning: `fetch` is not available. Please supply a custom `fetchFn` property to use `fetchBaseQuery` on SSR environments.', ) } return async (arg, api) => { @@ -301,13 +301,13 @@ export function fetchBaseQuery({ await Promise.all([ handleResponse(response, responseHandler).then( (r) => (resultData = r), - (e) => (handleResponseError = e) + (e) => (handleResponseError = e), ), // see https://github.com/node-fetch/node-fetch/issues/665#issuecomment-538995182 // we *have* to "use up" both streams at the same time or they will stop running in node-fetch scenarios responseClone.text().then( (r) => (responseText = r), - () => {} + () => {}, ), ]) if (handleResponseError) throw handleResponseError @@ -339,7 +339,7 @@ export function fetchBaseQuery({ async function handleResponse( response: Response, - responseHandler: ResponseHandler + responseHandler: ResponseHandler, ) { if (typeof responseHandler === 'function') { return responseHandler(response) diff --git a/packages/toolkit/src/query/index.ts b/packages/toolkit/src/query/index.ts index b509bac8f0..2c4f11e0a9 100644 --- a/packages/toolkit/src/query/index.ts +++ b/packages/toolkit/src/query/index.ts @@ -28,6 +28,9 @@ export type { QueryArgFrom, ResultTypeFrom, DefinitionType, + DefinitionsFromApi, + OverrideResultType, + TagTypesFromApi, } from './endpointDefinitions' export { fetchBaseQuery } from './fetchBaseQuery' export type { diff --git a/packages/toolkit/src/query/react/ApiProvider.tsx b/packages/toolkit/src/query/react/ApiProvider.tsx index 4c9f7acf23..a2d56f3ae2 100644 --- a/packages/toolkit/src/query/react/ApiProvider.tsx +++ b/packages/toolkit/src/query/react/ApiProvider.tsx @@ -42,7 +42,7 @@ export function ApiProvider>(props: { const existingContext = useContext(context) if (existingContext) { throw new Error( - 'Existing Redux context detected. If you already have a store set up, please use the traditional Redux setup.' + 'Existing Redux context detected. If you already have a store set up, please use the traditional Redux setup.', ) } const [store] = React.useState(() => @@ -51,7 +51,7 @@ export function ApiProvider>(props: { [props.api.reducerPath]: props.api.reducer, }, middleware: (gDM) => gDM().concat(props.api.middleware), - }) + }), ) // Adds the event listeners for online/offline/focus/etc useEffect( @@ -59,7 +59,7 @@ export function ApiProvider>(props: { props.setupListeners === false ? undefined : setupListeners(store.dispatch, props.setupListeners), - [props.setupListeners, store.dispatch] + [props.setupListeners, store.dispatch], ) return ( diff --git a/packages/toolkit/src/query/react/buildHooks.ts b/packages/toolkit/src/query/react/buildHooks.ts index cd69763b65..b6d611b778 100644 --- a/packages/toolkit/src/query/react/buildHooks.ts +++ b/packages/toolkit/src/query/react/buildHooks.ts @@ -1,62 +1,56 @@ import type { - UnknownAction, Selector, ThunkAction, ThunkDispatch, + UnknownAction, } from '@reduxjs/toolkit' -import { createSelector } from '@reduxjs/toolkit' -import type { DependencyList } from 'react' -import { - useCallback, - useDebugValue, - useEffect, - useLayoutEffect, - useMemo, - useRef, - useState, -} from 'react' -import { QueryStatus, skipToken } from '@reduxjs/toolkit/query' -import type { - QuerySubState, - SubscriptionOptions, - QueryKeys, - RootState, -} from '@reduxjs/toolkit/query' import type { + Api, + ApiContext, + ApiEndpointMutation, + ApiEndpointQuery, + CoreModule, EndpointDefinitions, + MutationActionCreatorResult, MutationDefinition, - QueryDefinition, - QueryArgFrom, - ResultTypeFrom, - QueryResultSelectorResult, MutationResultSelectorResult, - SkipToken, + PrefetchOptions, QueryActionCreatorResult, - MutationActionCreatorResult, + QueryArgFrom, + QueryDefinition, + QueryKeys, + QueryResultSelectorResult, + QuerySubState, + ResultTypeFrom, + RootState, SerializeQueryArgs, - Api, - ApiContext, + SkipToken, + SubscriptionOptions, TSHelpersId, TSHelpersNoInfer, TSHelpersOverride, - ApiEndpointMutation, - ApiEndpointQuery, - CoreModule, - PrefetchOptions, } from '@reduxjs/toolkit/query' +import { QueryStatus, skipToken } from '@reduxjs/toolkit/query' +import type { DependencyList } from 'react' +import { + useCallback, + useDebugValue, + useEffect, + useLayoutEffect, + useMemo, + useRef, + useState, +} from 'react' import { shallowEqual } from 'react-redux' -import type { ReactHooksModuleOptions } from './module' -import { useStableQueryArgs } from './useSerializedStableValue' +import type { BaseQueryFn } from '../baseQueryTypes' +import type { SubscriptionSelectors } from '../core/buildMiddleware/types' +import { defaultSerializeQueryArgs } from '../defaultSerializeQueryArgs' import type { UninitializedValue } from './constants' import { UNINITIALIZED_VALUE } from './constants' +import type { ReactHooksModuleOptions } from './module' +import { useStableQueryArgs } from './useSerializedStableValue' import { useShallowStableValue } from './useShallowStableValue' -import type { BaseQueryFn } from '../baseQueryTypes' -import { defaultSerializeQueryArgs } from '../defaultSerializeQueryArgs' -import { - InternalMiddlewareState, - SubscriptionSelectors, -} from '../core/buildMiddleware/types' // Copy-pasted from React-Redux export const useIsomorphicLayoutEffect = @@ -67,7 +61,7 @@ export const useIsomorphicLayoutEffect = : useEffect export interface QueryHooks< - Definition extends QueryDefinition + Definition extends QueryDefinition, > { useQuery: UseQuery useLazyQuery: UseLazyQuery @@ -77,7 +71,7 @@ export interface QueryHooks< } export interface MutationHooks< - Definition extends MutationDefinition + Definition extends MutationDefinition, > { useMutation: UseMutation } @@ -98,15 +92,15 @@ export interface MutationHooks< * - Re-renders as the request status changes and data becomes available */ export type UseQuery> = < - R extends Record = UseQueryStateDefaultResult + R extends Record = UseQueryStateDefaultResult, >( arg: QueryArgFrom | SkipToken, - options?: UseQuerySubscriptionOptions & UseQueryStateOptions + options?: UseQuerySubscriptionOptions & UseQueryStateOptions, ) => UseQueryHookResult export type UseQueryHookResult< D extends QueryDefinition, - R = UseQueryStateDefaultResult + R = UseQueryStateDefaultResult, > = UseQueryStateResult & UseQuerySubscriptionResult /** @@ -119,7 +113,7 @@ export type TypedUseQueryHookResult< BaseQuery extends BaseQueryFn, R = UseQueryStateDefaultResult< QueryDefinition - > + >, > = TypedUseQueryStateResult & TypedUseQuerySubscriptionResult @@ -182,14 +176,14 @@ interface UseQuerySubscriptionOptions extends SubscriptionOptions { * - Accepts polling/re-fetching options to trigger automatic re-fetches when the corresponding criteria is met */ export type UseQuerySubscription< - D extends QueryDefinition + D extends QueryDefinition, > = ( arg: QueryArgFrom | SkipToken, - options?: UseQuerySubscriptionOptions + options?: UseQuerySubscriptionOptions, ) => UseQuerySubscriptionResult export type UseQuerySubscriptionResult< - D extends QueryDefinition + D extends QueryDefinition, > = Pick, 'refetch'> /** @@ -199,13 +193,13 @@ export type UseQuerySubscriptionResult< export type TypedUseQuerySubscriptionResult< ResultType, QueryArg, - BaseQuery extends BaseQueryFn + BaseQuery extends BaseQueryFn, > = UseQuerySubscriptionResult< QueryDefinition > export type UseLazyQueryLastPromiseInfo< - D extends QueryDefinition + D extends QueryDefinition, > = { lastArg: QueryArgFrom } @@ -228,13 +222,13 @@ export type UseLazyQueryLastPromiseInfo< * When the trigger function returned from a LazyQuery is called, it always initiates a new request to the server even if there is cached data. Set `preferCacheValue`(the second argument to the function) as `true` if you want it to immediately return a cached value if one exists. */ export type UseLazyQuery> = < - R extends Record = UseQueryStateDefaultResult + R extends Record = UseQueryStateDefaultResult, >( - options?: SubscriptionOptions & Omit, 'skip'> + options?: SubscriptionOptions & Omit, 'skip'>, ) => [ LazyQueryTrigger, UseQueryStateResult, - UseLazyQueryLastPromiseInfo + UseLazyQueryLastPromiseInfo, ] export type LazyQueryTrigger> = { @@ -260,7 +254,7 @@ export type LazyQueryTrigger> = { */ ( arg: QueryArgFrom, - preferCacheValue?: boolean + preferCacheValue?: boolean, ): QueryActionCreatorResult } @@ -276,14 +270,14 @@ export type LazyQueryTrigger> = { * - Accepts polling/re-fetching options to trigger automatic re-fetches when the corresponding criteria is met and the fetch has been manually called at least once */ export type UseLazyQuerySubscription< - D extends QueryDefinition + D extends QueryDefinition, > = ( - options?: SubscriptionOptions + options?: SubscriptionOptions, ) => readonly [LazyQueryTrigger, QueryArgFrom | UninitializedValue] export type QueryStateSelector< R extends Record, - D extends QueryDefinition + D extends QueryDefinition, > = (state: UseQueryStateDefaultResult) => R /** @@ -297,15 +291,15 @@ export type QueryStateSelector< * - Re-renders as the request status changes and data becomes available */ export type UseQueryState> = < - R extends Record = UseQueryStateDefaultResult + R extends Record = UseQueryStateDefaultResult, >( arg: QueryArgFrom | SkipToken, - options?: UseQueryStateOptions + options?: UseQueryStateOptions, ) => UseQueryStateResult export type UseQueryStateOptions< D extends QueryDefinition, - R extends Record + R extends Record, > = { /** * Prevents a query from automatically running. @@ -375,7 +369,7 @@ export type UseQueryStateOptions< export type UseQueryStateResult< _ extends QueryDefinition, - R + R, > = TSHelpersNoInfer /** @@ -388,7 +382,7 @@ export type TypedUseQueryStateResult< BaseQuery extends BaseQueryFn, R = UseQueryStateDefaultResult< QueryDefinition - > + >, > = TSHelpersNoInfer type UseQueryStateBaseResult> = @@ -465,12 +459,12 @@ type UseQueryStateDefaultResult> = export type MutationStateSelector< R extends Record, - D extends MutationDefinition + D extends MutationDefinition, > = (state: MutationResultSelectorResult) => R export type UseMutationStateOptions< D extends MutationDefinition, - R extends Record + R extends Record, > = { selectFromResult?: MutationStateSelector fixedCacheKey?: string @@ -478,7 +472,7 @@ export type UseMutationStateOptions< export type UseMutationStateResult< D extends MutationDefinition, - R + R, > = TSHelpersNoInfer & { originalArgs?: QueryArgFrom /** @@ -498,7 +492,7 @@ export type TypedUseMutationResult< BaseQuery extends BaseQueryFn, R = MutationResultSelectorResult< MutationDefinition - > + >, > = UseMutationStateResult< MutationDefinition, R @@ -515,9 +509,9 @@ export type TypedUseMutationResult< * - Re-renders as the request status changes and data becomes available */ export type UseMutation> = < - R extends Record = MutationResultSelectorResult + R extends Record = MutationResultSelectorResult, >( - options?: UseMutationStateOptions + options?: UseMutationStateOptions, ) => readonly [MutationTrigger, UseMutationStateResult] export type MutationTrigger> = @@ -548,7 +542,7 @@ export type MutationTrigger> = * to prevent that the library user has to do an additional check for `isUninitialized`/ */ const noPendingQueryStateSelector: QueryStateSelector = ( - selected + selected, ) => { if (selected.isUninitialized) { return { @@ -565,7 +559,7 @@ const noPendingQueryStateSelector: QueryStateSelector = ( type GenericPrefetchThunk = ( endpointName: any, arg: any, - options: PrefetchOptions + options: PrefetchOptions, ) => ThunkAction /** @@ -582,6 +576,7 @@ export function buildHooks({ batch, hooks: { useDispatch, useSelector, useStore }, unstable__sideEffectsInRender, + createSelector, }, serializeQueryArgs, context, @@ -593,7 +588,7 @@ export function buildHooks({ }) { const usePossiblyImmediateEffect: ( effect: () => void | undefined, - deps?: DependencyList + deps?: DependencyList, ) => void = unstable__sideEffectsInRender ? (cb) => cb() : useEffect return { buildQueryHooks, buildMutationHook, usePrefetch } @@ -601,7 +596,7 @@ export function buildHooks({ function queryStatePreSelector( currentState: QueryResultSelectorResult, lastResult: UseQueryStateDefaultResult | undefined, - queryArgs: any + queryArgs: any, ): UseQueryStateDefaultResult { // if we had a last result and the current result is uninitialized, // we might have called `api.util.resetApiState` @@ -649,7 +644,7 @@ export function buildHooks({ function usePrefetch>( endpointName: EndpointName, - defaultOptions?: PrefetchOptions + defaultOptions?: PrefetchOptions, ) { const dispatch = useDispatch>() const stableDefaultOptions = useShallowStableValue(defaultOptions) @@ -660,9 +655,9 @@ export function buildHooks({ (api.util.prefetch as GenericPrefetchThunk)(endpointName, arg, { ...stableDefaultOptions, ...options, - }) + }), ), - [endpointName, dispatch, stableDefaultOptions] + [endpointName, dispatch, stableDefaultOptions], ) } @@ -675,7 +670,8 @@ export function buildHooks({ refetchOnMountOrArgChange, skip = false, pollingInterval = 0, - } = {} + skipPollingIfUnfocused = false, + } = {}, ) => { const { initiate } = api.endpoints[name] as ApiEndpointQuery< QueryDefinition, @@ -685,7 +681,7 @@ export function buildHooks({ const subscriptionSelectorsRef = useRef() if (!subscriptionSelectorsRef.current) { const returnedValue = dispatch( - api.internalActions.internal_getRTKQSubscriptions() + api.internalActions.internal_getRTKQSubscriptions(), ) if (process.env.NODE_ENV !== 'production') { @@ -695,7 +691,7 @@ export function buildHooks({ ) { throw new Error( `Warning: Middleware for RTK-Query API at reducerPath "${api.reducerPath}" has not been added to the store. - You must add the middleware for RTK-Query to function correctly!` + You must add the middleware for RTK-Query to function correctly!`, ) } } @@ -712,12 +708,13 @@ export function buildHooks({ // and then we never try to initiate a refetch. defaultSerializeQueryArgs, context.endpointDefinitions[name], - name + name, ) const stableSubscriptionOptions = useShallowStableValue({ refetchOnReconnect, refetchOnFocus, pollingInterval, + skipPollingIfUnfocused, }) const lastRenderHadSubscription = useRef(false) @@ -733,7 +730,7 @@ export function buildHooks({ currentRenderHasSubscription = subscriptionSelectorsRef.current.isRequestSubscribed( queryCacheKey, - requestId + requestId, ) } @@ -774,7 +771,7 @@ export function buildHooks({ initiate(stableArg, { subscriptionOptions: stableSubscriptionOptions, forceRefetch: refetchOnMountOrArgChange, - }) + }), ) promiseRef.current = promise @@ -805,12 +802,12 @@ export function buildHooks({ refetch: () => { if (!promiseRef.current) throw new Error( - 'Cannot refetch a query that has not been started yet.' + 'Cannot refetch a query that has not been started yet.', ) return promiseRef.current?.refetch() }, }), - [] + [], ) } @@ -818,6 +815,7 @@ export function buildHooks({ refetchOnReconnect, refetchOnFocus, pollingInterval = 0, + skipPollingIfUnfocused = false, } = {}) => { const { initiate } = api.endpoints[name] as ApiEndpointQuery< QueryDefinition, @@ -832,6 +830,7 @@ export function buildHooks({ refetchOnReconnect, refetchOnFocus, pollingInterval, + skipPollingIfUnfocused, }) usePossiblyImmediateEffect(() => { @@ -839,7 +838,7 @@ export function buildHooks({ if (stableSubscriptionOptions !== lastSubscriptionOptions) { promiseRef.current?.updateSubscriptionOptions( - stableSubscriptionOptions + stableSubscriptionOptions, ) } }, [stableSubscriptionOptions]) @@ -860,7 +859,7 @@ export function buildHooks({ initiate(arg, { subscriptionOptions: subscriptionOptionsRef.current, forceRefetch: !preferCacheValue, - }) + }), ) setArg(arg) @@ -868,7 +867,7 @@ export function buildHooks({ return promise! }, - [dispatch, initiate] + [dispatch, initiate], ) /* cleanup on unmount */ @@ -890,7 +889,7 @@ export function buildHooks({ const useQueryState: UseQueryState = ( arg: any, - { skip = false, selectFromResult } = {} + { skip = false, selectFromResult } = {}, ) => { const { select } = api.endpoints[name] as ApiEndpointQuery< QueryDefinition, @@ -900,7 +899,7 @@ export function buildHooks({ skip ? skipToken : arg, serializeQueryArgs, context.endpointDefinitions[name], - name + name, ) type ApiRootState = Parameters>[0] @@ -920,9 +919,9 @@ export function buildHooks({ memoizeOptions: { resultEqualityCheck: shallowEqual, }, - } + }, ), - [select, stableArg] + [select, stableArg], ) const querySelector: Selector = useMemo( @@ -932,19 +931,19 @@ export function buildHooks({ devModeChecks: { identityFunctionCheck: 'never' }, }) : selectDefaultResult, - [selectDefaultResult, selectFromResult] + [selectDefaultResult, selectFromResult], ) const currentState = useSelector( (state: RootState) => querySelector(state, lastValue.current), - shallowEqual + shallowEqual, ) const store = useStore>() const newLastValue = selectDefaultResult( store.getState(), - lastValue.current + lastValue.current, ) useIsomorphicLayoutEffect(() => { lastValue.current = newLastValue @@ -967,7 +966,7 @@ export function buildHooks({ const info = useMemo(() => ({ lastArg: arg }), [arg]) return useMemo( () => [trigger, queryStateResults, info], - [trigger, queryStateResults, info] + [trigger, queryStateResults, info], ) }, useQuery(arg, options) { @@ -986,7 +985,7 @@ export function buildHooks({ return useMemo( () => ({ ...queryStateResults, ...querySubscriptionResults }), - [queryStateResults, querySubscriptionResults] + [queryStateResults, querySubscriptionResults], ) }, } @@ -1007,7 +1006,7 @@ export function buildHooks({ promise?.reset() } }, - [promise] + [promise], ) const triggerMutation = useCallback( @@ -1016,20 +1015,20 @@ export function buildHooks({ setPromise(promise) return promise }, - [dispatch, initiate, fixedCacheKey] + [dispatch, initiate, fixedCacheKey], ) const { requestId } = promise || {} const selectDefaultResult = useMemo( () => select({ fixedCacheKey, requestId: promise?.requestId }), - [fixedCacheKey, promise, select] + [fixedCacheKey, promise, select], ) const mutationSelector = useMemo( - () => + (): Selector, any> => selectFromResult ? createSelector([selectDefaultResult], selectFromResult) : selectDefaultResult, - [selectFromResult, selectDefaultResult] + [selectFromResult, selectDefaultResult], ) const currentState = useSelector(mutationSelector, shallowEqual) @@ -1045,7 +1044,7 @@ export function buildHooks({ api.internalActions.removeMutationResult({ requestId, fixedCacheKey, - }) + }), ) } }) @@ -1072,12 +1071,12 @@ export function buildHooks({ const finalState = useMemo( () => ({ ...currentState, originalArgs, reset }), - [currentState, originalArgs, reset] + [currentState, originalArgs, reset], ) return useMemo( () => [triggerMutation, finalState] as const, - [triggerMutation, finalState] + [triggerMutation, finalState], ) } } diff --git a/packages/toolkit/src/query/react/index.ts b/packages/toolkit/src/query/react/index.ts index 5a9b5a6cdf..b9acba6b6b 100644 --- a/packages/toolkit/src/query/react/index.ts +++ b/packages/toolkit/src/query/react/index.ts @@ -2,7 +2,7 @@ // does not have to import this into each source file it rewrites. import { formatProdErrorMessage } from '@reduxjs/toolkit' -import { coreModule, buildCreateApi } from '@reduxjs/toolkit/query' +import { buildCreateApi, coreModule } from '@reduxjs/toolkit/query' import { reactHooksModule, reactHooksModuleName } from './module' export * from '@reduxjs/toolkit/query' @@ -10,13 +10,13 @@ export { ApiProvider } from './ApiProvider' const createApi = /* @__PURE__ */ buildCreateApi( coreModule(), - reactHooksModule() + reactHooksModule(), ) export type { + TypedUseMutationResult, TypedUseQueryHookResult, TypedUseQueryStateResult, TypedUseQuerySubscriptionResult, - TypedUseMutationResult, } from './buildHooks' export { createApi, reactHooksModule, reactHooksModuleName } diff --git a/packages/toolkit/src/query/react/module.ts b/packages/toolkit/src/query/react/module.ts index 3ff9a02166..fed0b3d7a9 100644 --- a/packages/toolkit/src/query/react/module.ts +++ b/packages/toolkit/src/query/react/module.ts @@ -1,25 +1,27 @@ -import type { MutationHooks, QueryHooks } from './buildHooks' -import { buildHooks } from './buildHooks' -import { isQueryDefinition, isMutationDefinition } from '../endpointDefinitions' import type { + Api, + BaseQueryFn, EndpointDefinitions, - QueryDefinition, + Module, MutationDefinition, QueryArgFrom, + QueryDefinition, } from '@reduxjs/toolkit/query' -import type { Api, Module } from '../apiTypes' -import { capitalize } from '../utils' +import { isMutationDefinition, isQueryDefinition } from '../endpointDefinitions' import { safeAssign } from '../tsHelpers' -import type { BaseQueryFn } from '@reduxjs/toolkit/query' +import { capitalize } from '../utils' +import type { MutationHooks, QueryHooks } from './buildHooks' +import { buildHooks } from './buildHooks' import type { HooksWithUniqueNames } from './namedHooks' import { + batch as rrBatch, useDispatch as rrUseDispatch, useSelector as rrUseSelector, useStore as rrUseStore, - batch as rrBatch, } from 'react-redux' +import { createSelector as _createSelector } from 'reselect' import type { QueryKeys } from '../core/apiState' import type { PrefetchOptions } from '../core/module' import { countObjectKeys } from '../utils/countObjectKeys' @@ -35,7 +37,7 @@ declare module '@reduxjs/toolkit/query' { // eslint-disable-next-line @typescript-eslint/no-unused-vars ReducerPath extends string, // eslint-disable-next-line @typescript-eslint/no-unused-vars - TagTypes extends string + TagTypes extends string, > { [reactHooksModuleName]: { /** @@ -51,18 +53,18 @@ declare module '@reduxjs/toolkit/query' { > ? QueryHooks : Definitions[K] extends MutationDefinition - ? MutationHooks - : never + ? MutationHooks + : never } /** * A hook that accepts a string endpoint name, and provides a callback that when called, pre-fetches the data for that endpoint. */ usePrefetch>( endpointName: EndpointName, - options?: PrefetchOptions + options?: PrefetchOptions, ): ( arg: QueryArgFrom, - options?: PrefetchOptions + options?: PrefetchOptions, ) => void } & HooksWithUniqueNames } @@ -111,6 +113,10 @@ export interface ReactHooksModuleOptions { * ``` */ unstable__sideEffectsInRender?: boolean + /** + * A selector creator (usually from `reselect`, or matching the same signature) + */ + createSelector?: typeof _createSelector } /** @@ -140,6 +146,7 @@ export const reactHooksModule = ({ useSelector: rrUseSelector, useStore: rrUseStore, }, + createSelector = _createSelector, unstable__sideEffectsInRender = false, ...rest }: ReactHooksModuleOptions = {}): Module => { @@ -153,7 +160,7 @@ export const reactHooksModule = ({ if (!warned) { console.warn( 'As of RTK 2.0, the hooks now need to be specified as one object, provided under a `hooks` key:' + - '\n`reactHooksModule({ hooks: { useDispatch, useSelector, useStore } })`' + '\n`reactHooksModule({ hooks: { useDispatch, useSelector, useStore } })`', ) warned = true } @@ -168,8 +175,8 @@ export const reactHooksModule = ({ `When using custom hooks for context, all ${ hookNames.length } hooks need to be provided: ${hookNames.join( - ', ' - )}.\nHook ${hookName} was either not provided or not a function.` + ', ', + )}.\nHook ${hookName} was either not provided or not a function.`, ) } } @@ -181,8 +188,8 @@ export const reactHooksModule = ({ const anyApi = api as any as Api< any, Record, - string, - string, + any, + any, ReactHooksModule > const { buildQueryHooks, buildMutationHook, usePrefetch } = buildHooks({ @@ -191,6 +198,7 @@ export const reactHooksModule = ({ batch, hooks, unstable__sideEffectsInRender, + createSelector, }, serializeQueryArgs, context, diff --git a/packages/toolkit/src/query/react/useSerializedStableValue.ts b/packages/toolkit/src/query/react/useSerializedStableValue.ts index 52f87d7158..95bc62af78 100644 --- a/packages/toolkit/src/query/react/useSerializedStableValue.ts +++ b/packages/toolkit/src/query/react/useSerializedStableValue.ts @@ -6,7 +6,7 @@ export function useStableQueryArgs( queryArgs: T, serialize: SerializeQueryArgs, endpointDefinition: EndpointDefinition, - endpointName: string + endpointName: string, ) { const incoming = useMemo( () => ({ @@ -16,7 +16,7 @@ export function useStableQueryArgs( ? serialize({ queryArgs, endpointDefinition, endpointName }) : queryArgs, }), - [queryArgs, serialize, endpointDefinition, endpointName] + [queryArgs, serialize, endpointDefinition, endpointName], ) const cache = useRef(incoming) useEffect(() => { diff --git a/packages/toolkit/src/query/retry.ts b/packages/toolkit/src/query/retry.ts index 7bd960c699..3e5015d858 100644 --- a/packages/toolkit/src/query/retry.ts +++ b/packages/toolkit/src/query/retry.ts @@ -26,7 +26,7 @@ async function defaultBackoff(attempt: number = 0, maxRetries: number = 5) { const timeout = ~~((Math.random() + 0.4) * (300 << attempts)) // Force a positive int in the case we make this an option await new Promise((resolve) => - setTimeout((res: any) => resolve(res), timeout) + setTimeout((res: any) => resolve(res), timeout), ) } @@ -37,7 +37,7 @@ type RetryConditionFunction = ( attempt: number baseQueryApi: BaseQueryApi extraOptions: BaseQueryExtraOptions & RetryOptions - } + }, ) => boolean export type RetryOptions = { diff --git a/packages/toolkit/src/query/tests/apiProvider.test.tsx b/packages/toolkit/src/query/tests/apiProvider.test.tsx index b153a36b7f..80101a8386 100644 --- a/packages/toolkit/src/query/tests/apiProvider.test.tsx +++ b/packages/toolkit/src/query/tests/apiProvider.test.tsx @@ -1,13 +1,13 @@ -import * as React from 'react' -import { createApi, ApiProvider } from '@reduxjs/toolkit/query/react' +import { configureStore } from '@reduxjs/toolkit' +import { ApiProvider, createApi } from '@reduxjs/toolkit/query/react' import { fireEvent, render, waitFor } from '@testing-library/react' -import { waitMs } from './helpers' +import { delay } from 'msw' +import * as React from 'react' import { Provider } from 'react-redux' -import { configureStore } from '@reduxjs/toolkit' const api = createApi({ baseQuery: async (arg: any) => { - await waitMs() + await delay(150) return { data: arg?.body ? arg.body : null } }, endpoints: (build) => ({ @@ -42,18 +42,18 @@ describe('ApiProvider', () => { const { getByText, getByTestId } = render( - + , ) await waitFor(() => - expect(getByTestId('isFetching').textContent).toBe('false') + expect(getByTestId('isFetching').textContent).toBe('false'), ) fireEvent.click(getByText('Increment value')) await waitFor(() => - expect(getByTestId('isFetching').textContent).toBe('true') + expect(getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(getByTestId('isFetching').textContent).toBe('false') + expect(getByTestId('isFetching').textContent).toBe('false'), ) fireEvent.click(getByText('Increment value')) // Being that nothing has changed in the args, this should never fire. @@ -64,10 +64,10 @@ describe('ApiProvider', () => { render( null })}> child - - ) + , + ), ).toThrowErrorMatchingInlineSnapshot( - `[Error: Existing Redux context detected. If you already have a store set up, please use the traditional Redux setup.]` + `[Error: Existing Redux context detected. If you already have a store set up, please use the traditional Redux setup.]`, ) }) }) diff --git a/packages/toolkit/src/query/tests/baseQueryTypes.test-d.ts b/packages/toolkit/src/query/tests/baseQueryTypes.test-d.ts new file mode 100644 index 0000000000..1ffa324b8b --- /dev/null +++ b/packages/toolkit/src/query/tests/baseQueryTypes.test-d.ts @@ -0,0 +1,32 @@ +import { createApi, fetchBaseQuery, retry } from '@reduxjs/toolkit/query' + +describe('type tests', () => { + test('BaseQuery meta types propagate to endpoint callbacks', () => { + createApi({ + baseQuery: fetchBaseQuery(), + endpoints: (build) => ({ + getDummy: build.query({ + query: () => 'dummy', + onCacheEntryAdded: async (arg, { cacheDataLoaded }) => { + const { meta } = await cacheDataLoaded + const { request, response } = meta! // Expect request and response to be there + }, + }), + }), + }) + + const baseQuery = retry(fetchBaseQuery()) // Even when wrapped with retry + createApi({ + baseQuery, + endpoints: (build) => ({ + getDummy: build.query({ + query: () => 'dummy', + onCacheEntryAdded: async (arg, { cacheDataLoaded }) => { + const { meta } = await cacheDataLoaded + const { request, response } = meta! // Expect request and response to be there + }, + }), + }), + }) + }) +}) diff --git a/packages/toolkit/src/query/tests/baseQueryTypes.typetest.ts b/packages/toolkit/src/query/tests/baseQueryTypes.typetest.ts deleted file mode 100644 index f321ced60c..0000000000 --- a/packages/toolkit/src/query/tests/baseQueryTypes.typetest.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { createApi, fetchBaseQuery, retry } from '@reduxjs/toolkit/query' - -/** - * Test: BaseQuery meta types propagate to endpoint callbacks - */ -{ - createApi({ - baseQuery: fetchBaseQuery(), - endpoints: (build) => ({ - getDummy: build.query({ - query: () => 'dummy', - onCacheEntryAdded: async (arg, { cacheDataLoaded }) => { - const { meta } = await cacheDataLoaded - const { request, response } = meta! // Expect request and response to be there - }, - }), - }), - }) - - const baseQuery = retry(fetchBaseQuery()) // Even when wrapped with retry - createApi({ - baseQuery, - endpoints: (build) => ({ - getDummy: build.query({ - query: () => 'dummy', - onCacheEntryAdded: async (arg, { cacheDataLoaded }) => { - const { meta } = await cacheDataLoaded - const { request, response } = meta! // Expect request and response to be there - }, - }), - }), - }) -} diff --git a/packages/toolkit/src/query/tests/buildCreateApi.test.tsx b/packages/toolkit/src/query/tests/buildCreateApi.test.tsx index 8d8956f559..9a443c9350 100644 --- a/packages/toolkit/src/query/tests/buildCreateApi.test.tsx +++ b/packages/toolkit/src/query/tests/buildCreateApi.test.tsx @@ -1,42 +1,20 @@ +import { createSelectorCreator, lruMemoize } from '@reduxjs/toolkit' +import { + buildCreateApi, + coreModule, + reactHooksModule, +} from '@reduxjs/toolkit/query/react' +import { render, screen, waitFor } from '@testing-library/react' +import { delay } from 'msw' import * as React from 'react' import type { ReactReduxContextValue } from 'react-redux' import { + Provider, createDispatchHook, createSelectorHook, createStoreHook, - Provider, } from 'react-redux' -import { - buildCreateApi, - coreModule, - reactHooksModule, -} from '@reduxjs/toolkit/query/react' -import { - act, - fireEvent, - render, - screen, - waitFor, - renderHook, -} from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import { rest } from 'msw' -import { - actionsReducer, - ANY, - expectExactType, - expectType, - setupApiStore, - withProvider, - useRenderCounter, - waitMs, -} from './helpers' -import { server } from './mocks/server' -import type { UnknownAction } from 'redux' -import type { SubscriptionOptions } from '@reduxjs/toolkit/dist/query/core/apiState' -import type { SerializedError } from '@reduxjs/toolkit' -import { createListenerMiddleware, configureStore } from '@reduxjs/toolkit' -import { delay } from '../../utils' +import { setupApiStore, useRenderCounter } from '../../tests/utils/helpers' const MyContext = React.createContext(null as any) @@ -50,12 +28,12 @@ describe('buildCreateApi', () => { useSelector: createSelectorHook(MyContext), useStore: createStoreHook(MyContext), }, - }) + }), ) const api = customCreateApi({ baseQuery: async (arg: any) => { - await waitMs() + await delay(150) return { data: arg?.body ? { ...arg.body } : {}, @@ -100,7 +78,7 @@ describe('buildCreateApi', () => { expect(getRenderCount()).toBe(2) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) expect(getRenderCount()).toBe(3) }) @@ -115,7 +93,7 @@ describe('buildCreateApi', () => { useDispatch: createDispatchHook(MyContext), useSelector: createSelectorHook(MyContext), }, - }) + }), ) } @@ -123,7 +101,68 @@ describe('buildCreateApi', () => { ` [Error: When using custom hooks for context, all 3 hooks need to be provided: useDispatch, useSelector, useStore. Hook useStore was either not provided or not a function.] - ` + `, + ) + }) + test('allows passing createSelector instance', async () => { + const memoize = vi.fn(lruMemoize) + const createSelector = createSelectorCreator(memoize) + const createApi = buildCreateApi( + coreModule({ createSelector }), + reactHooksModule({ createSelector }), ) + const api = createApi({ + baseQuery: async (arg: any) => { + await delay(150) + + return { + data: arg?.body ? { ...arg.body } : {}, + } + }, + endpoints: (build) => ({ + getUser: build.query<{ name: string }, number>({ + query: () => ({ + body: { name: 'Timmy' }, + }), + }), + }), + }) + + const storeRef = setupApiStore(api, {}, { withoutTestLifecycles: true }) + + await storeRef.store.dispatch(api.endpoints.getUser.initiate(1)) + + const selectUser = api.endpoints.getUser.select(1) + + expect(selectUser(storeRef.store.getState()).data).toEqual({ + name: 'Timmy', + }) + + expect(memoize).toHaveBeenCalledTimes(4) + + memoize.mockClear() + + function User() { + const { isFetching } = api.endpoints.getUser.useQuery(1) + + return ( +

+ ) + } + + function Wrapper({ children }: any) { + return {children} + } + + render(, { wrapper: Wrapper }) + + await waitFor(() => + expect(screen.getByTestId('isFetching').textContent).toBe('false'), + ) + + // select() + selectFromResult + expect(memoize).toHaveBeenCalledTimes(8) }) }) diff --git a/packages/toolkit/src/query/tests/buildHooks.test-d.tsx b/packages/toolkit/src/query/tests/buildHooks.test-d.tsx new file mode 100644 index 0000000000..9e15bf68ee --- /dev/null +++ b/packages/toolkit/src/query/tests/buildHooks.test-d.tsx @@ -0,0 +1,263 @@ +import type { UseMutation, UseQuery } from '@internal/query/react/buildHooks' +import { ANY } from '@internal/tests/utils/helpers' +import type { SerializedError } from '@reduxjs/toolkit' +import type { SubscriptionOptions } from '@reduxjs/toolkit/query/react' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' +import { useState } from 'react' + +let amount = 0 +let nextItemId = 0 + +interface Item { + id: number +} + +const api = createApi({ + baseQuery: (arg: any) => { + if (arg?.body && 'amount' in arg.body) { + amount += 1 + } + + if (arg?.body && 'forceError' in arg.body) { + return { + error: { + status: 500, + data: null, + }, + } + } + + if (arg?.body && 'listItems' in arg.body) { + const items: Item[] = [] + for (let i = 0; i < 3; i++) { + const item = { id: nextItemId++ } + items.push(item) + } + return { data: items } + } + + return { + data: arg?.body ? { ...arg.body, ...(amount ? { amount } : {}) } : {}, + } + }, + endpoints: (build) => ({ + getUser: build.query<{ name: string }, number>({ + query: () => ({ + body: { name: 'Timmy' }, + }), + }), + getUserAndForceError: build.query<{ name: string }, number>({ + query: () => ({ + body: { + forceError: true, + }, + }), + }), + getIncrementedAmount: build.query<{ amount: number }, void>({ + query: () => ({ + url: '', + body: { + amount, + }, + }), + }), + updateUser: build.mutation<{ name: string }, { name: string }>({ + query: (update) => ({ body: update }), + }), + getError: build.query({ + query: () => '/error', + }), + listItems: build.query({ + serializeQueryArgs: ({ endpointName }) => { + return endpointName + }, + query: ({ pageNumber }) => ({ + url: `items?limit=1&offset=${pageNumber}`, + body: { + listItems: true, + }, + }), + merge: (currentCache, newItems) => { + currentCache.push(...newItems) + }, + forceRefetch: () => { + return true + }, + }), + }), +}) + +describe('type tests', () => { + test('useLazyQuery hook callback returns various properties to handle the result', () => { + function User() { + const [getUser] = api.endpoints.getUser.useLazyQuery() + const [{ successMsg, errMsg, isAborted }, setValues] = useState({ + successMsg: '', + errMsg: '', + isAborted: false, + }) + + const handleClick = (abort: boolean) => async () => { + const res = getUser(1) + + // no-op simply for clearer type assertions + res.then((result) => { + if (result.isSuccess) { + expectTypeOf(result).toMatchTypeOf<{ + data: { + name: string + } + }>() + } + + if (result.isError) { + expectTypeOf(result).toMatchTypeOf<{ + error: { status: number; data: unknown } | SerializedError + }>() + } + }) + + expectTypeOf(res.arg).toBeNumber() + + expectTypeOf(res.requestId).toBeString() + + expectTypeOf(res.abort).toEqualTypeOf<() => void>() + + expectTypeOf(res.unsubscribe).toEqualTypeOf<() => void>() + + expectTypeOf(res.updateSubscriptionOptions).toEqualTypeOf< + (options: SubscriptionOptions) => void + >() + + expectTypeOf(res.refetch).toMatchTypeOf<() => void>() + + expectTypeOf(res.unwrap()).resolves.toEqualTypeOf<{ name: string }>() + } + + return ( +
+ + +
{successMsg}
+
{errMsg}
+
{isAborted ? 'Request was aborted' : ''}
+
+ ) + } + }) + + test('useMutation hook callback returns various properties to handle the result', async () => { + function User() { + const [updateUser] = api.endpoints.updateUser.useMutation() + const [successMsg, setSuccessMsg] = useState('') + const [errMsg, setErrMsg] = useState('') + const [isAborted, setIsAborted] = useState(false) + + const handleClick = async () => { + const res = updateUser({ name: 'Banana' }) + + expectTypeOf(res).resolves.toMatchTypeOf< + | { + error: { status: number; data: unknown } | SerializedError + } + | { + data: { + name: string + } + } + >() + + expectTypeOf(res.arg).toMatchTypeOf<{ + endpointName: string + originalArgs: { name: string } + track?: boolean + }>() + + expectTypeOf(res.requestId).toBeString() + + expectTypeOf(res.abort).toEqualTypeOf<() => void>() + + expectTypeOf(res.unwrap()).resolves.toEqualTypeOf<{ name: string }>() + + expectTypeOf(res.reset).toEqualTypeOf<() => void>() + } + + return ( +
+ +
{successMsg}
+
{errMsg}
+
{isAborted ? 'Request was aborted' : ''}
+
+ ) + } + }) + + test('selectFromResult (query) behaviors', () => { + interface Post { + id: number + name: string + fetched_at: string + } + + type PostsResponse = Post[] + + const api = createApi({ + baseQuery: fetchBaseQuery({ baseUrl: 'https://example.com/' }), + tagTypes: ['Posts'], + endpoints: (build) => ({ + getPosts: build.query({ + query: () => ({ url: 'posts' }), + providesTags: (result) => + result ? result.map(({ id }) => ({ type: 'Posts', id })) : [], + }), + updatePost: build.mutation>({ + query: ({ id, ...body }) => ({ + url: `post/${id}`, + method: 'PUT', + body, + }), + invalidatesTags: (result, error, { id }) => [{ type: 'Posts', id }], + }), + addPost: build.mutation>({ + query: (body) => ({ + url: `post`, + method: 'POST', + body, + }), + invalidatesTags: ['Posts'], + }), + }), + }) + + expectTypeOf(api.useGetPostsQuery).toEqualTypeOf( + api.endpoints.getPosts.useQuery, + ) + + expectTypeOf(api.useUpdatePostMutation).toEqualTypeOf( + api.endpoints.updatePost.useMutation, + ) + + expectTypeOf(api.useAddPostMutation).toEqualTypeOf( + api.endpoints.addPost.useMutation, + ) + }) + + test('UseQuery type can be used to recreate the hook type', () => { + const fakeQuery = ANY as UseQuery< + typeof api.endpoints.getUser.Types.QueryDefinition + > + + expectTypeOf(fakeQuery).toEqualTypeOf(api.endpoints.getUser.useQuery) + }) + + test('UseMutation type can be used to recreate the hook type', () => { + const fakeMutation = ANY as UseMutation< + typeof api.endpoints.updateUser.Types.MutationDefinition + > + + expectTypeOf(fakeMutation).toEqualTypeOf( + api.endpoints.updateUser.useMutation, + ) + }) +}) diff --git a/packages/toolkit/src/query/tests/buildHooks.test.tsx b/packages/toolkit/src/query/tests/buildHooks.test.tsx index e9f1f1ac90..868cd6647a 100644 --- a/packages/toolkit/src/query/tests/buildHooks.test.tsx +++ b/packages/toolkit/src/query/tests/buildHooks.test.tsx @@ -1,44 +1,38 @@ -import * as React from 'react' -import type { SpyInstance } from 'vitest' -import { vi } from 'vitest' -import type { - UseMutation, - UseQuery, -} from '@reduxjs/toolkit/dist/query/react/buildHooks' +import type { SubscriptionOptions } from '@internal/query/core/apiState' +import type { SubscriptionSelectors } from '@internal/query/core/buildMiddleware/types' +import { server } from '@internal/query/tests/mocks/server' +import { countObjectKeys } from '@internal/query/utils/countObjectKeys' import { + actionsReducer, + setupApiStore, + useRenderCounter, + waitMs, + withProvider, +} from '@internal/tests/utils/helpers' +import type { UnknownAction } from '@reduxjs/toolkit' +import { + configureStore, + createListenerMiddleware, + createSlice, +} from '@reduxjs/toolkit' +import { + QueryStatus, createApi, fetchBaseQuery, - QueryStatus, skipToken, } from '@reduxjs/toolkit/query/react' import { act, fireEvent, render, + renderHook, screen, waitFor, - renderHook, } from '@testing-library/react' import userEvent from '@testing-library/user-event' -import { rest } from 'msw' -import { - actionsReducer, - ANY, - expectExactType, - expectType, - setupApiStore, - withProvider, - useRenderCounter, - waitMs, -} from './helpers' -import { server } from './mocks/server' -import type { UnknownAction } from 'redux' -import type { SubscriptionOptions } from '@reduxjs/toolkit/dist/query/core/apiState' -import type { SerializedError } from '@reduxjs/toolkit' -import { createListenerMiddleware, configureStore, createSlice } from '@reduxjs/toolkit' -import { delay } from '../../utils' -import type { SubscriptionSelectors } from '../core/buildMiddleware/types' -import { countObjectKeys } from '../utils/countObjectKeys' +import { HttpResponse, http } from 'msw' +import { useEffect, useState } from 'react' +import type { MockInstance } from 'vitest' // Just setup a temporary in-memory counter for tests that `getIncrementedAmount`. // This can be used to test how many renders happen due to data changes or @@ -52,7 +46,7 @@ interface Item { const api = createApi({ baseQuery: async (arg: any) => { - await waitMs() + await waitMs(150) if (arg?.body && 'amount' in arg.body) { amount += 1 } @@ -104,7 +98,7 @@ const api = createApi({ query: (update) => ({ body: update }), }), getError: build.query({ - query: (query) => '/error', + query: () => '/error', }), listItems: build.query({ serializeQueryArgs: ({ endpointName }) => { @@ -119,7 +113,7 @@ const api = createApi({ merge: (currentCache, newItems) => { currentCache.push(...newItems) }, - forceRefetch: ({ currentArg, previousArg }) => { + forceRefetch: () => { return true }, }), @@ -137,7 +131,7 @@ const storeRef = setupApiStore( middleware: { prepend: [listenerMiddleware.middleware], }, - } + }, ) let getSubscriptions: SubscriptionSelectors['getSubscriptions'] @@ -152,7 +146,7 @@ beforeEach(() => { }, }) ;({ getSubscriptions, getSubscriptionCount } = storeRef.store.dispatch( - api.internalActions.internal_getRTKQSubscriptions() + api.internalActions.internal_getRTKQSubscriptions(), ) as unknown as SubscriptionSelectors) }) @@ -183,14 +177,14 @@ describe('hooks tests', () => { expect(getRenderCount()).toBe(2) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) expect(getRenderCount()).toBe(3) }) test('useQuery hook sets isFetching=true whenever a request is in flight', async () => { function User() { - const [value, setValue] = React.useState(0) + const [value, setValue] = useState(0) const { isFetching } = api.endpoints.getUser.useQuery(1, { skip: value < 1, @@ -211,14 +205,14 @@ describe('hooks tests', () => { expect(getRenderCount()).toBe(1) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) fireEvent.click(screen.getByText('Increment value')) // setState = 1, perform request = 2 await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) expect(getRenderCount()).toBe(4) @@ -231,13 +225,13 @@ describe('hooks tests', () => { test('useQuery hook sets isLoading=true only on initial request', async () => { let refetch: any, isLoading: boolean, isFetching: boolean function User() { - const [value, setValue] = React.useState(0) + const [value, setValue] = useState(0) ;({ isLoading, isFetching, refetch } = api.endpoints.getUser.useQuery( 2, { skip: value < 1, - } + }, )) return (
@@ -254,25 +248,25 @@ describe('hooks tests', () => { // Being that we skipped the initial request on mount, this should be false await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) fireEvent.click(screen.getByText('Increment value')) // Condition is met, should load await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) // Make sure the original loading has completed. fireEvent.click(screen.getByText('Increment value')) // Being that we already have data, isLoading should be false await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) // We call a refetch, should still be `false` act(() => void refetch()) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) expect(screen.getByTestId('isLoading').textContent).toBe('false') }) @@ -280,7 +274,7 @@ describe('hooks tests', () => { test('useQuery hook sets isLoading and isFetching to the correct states', async () => { let refetchMe: () => void = () => {} function User() { - const [value, setValue] = React.useState(0) + const [value, setValue] = useState(0) getRenderCount = useRenderCounter() const { isLoading, isFetching, refetch } = @@ -346,10 +340,10 @@ describe('hooks tests', () => { const { isLoading, isFetching, status } = api.endpoints.getUser.useQuery(id) - React.useEffect(() => { + useEffect(() => { loadingHist.push(isLoading) }, [isLoading]) - React.useEffect(() => { + useEffect(() => { fetchingHist.push(isFetching) }, [isFetching]) return ( @@ -362,12 +356,12 @@ describe('hooks tests', () => { let { rerender } = render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('status').textContent).toBe('1') + expect(screen.getByTestId('status').textContent).toBe('1'), ) rerender() await waitFor(() => - expect(screen.getByTestId('status').textContent).toBe('2') + expect(screen.getByTestId('status').textContent).toBe('2'), ) expect(loadingHist).toEqual([true, false]) @@ -393,14 +387,14 @@ describe('hooks tests', () => { const { unmount } = render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) unmount() @@ -409,14 +403,14 @@ describe('hooks tests', () => { // Let's make sure we actually fetch, and we increment expect(screen.getByTestId('isLoading').textContent).toBe('false') await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('2') + expect(screen.getByTestId('amount').textContent).toBe('2'), ) }) @@ -439,14 +433,14 @@ describe('hooks tests', () => { const { unmount } = render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) unmount() @@ -456,7 +450,7 @@ describe('hooks tests', () => { // and the condition is set to 10 seconds expect(screen.getByTestId('isFetching').textContent).toBe('false') await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) }) @@ -479,14 +473,14 @@ describe('hooks tests', () => { const { unmount } = render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) unmount() @@ -497,21 +491,21 @@ describe('hooks tests', () => { render(, { wrapper: storeRef.wrapper }) // Let's make sure we actually fetch, and we increment await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('2') + expect(screen.getByTestId('amount').textContent).toBe('2'), ) }) test('refetchOnMountOrArgChange works as expected when changing skip from false->true', async () => { let data, isLoading, isFetching function User() { - const [skip, setSkip] = React.useState(true) + const [skip, setSkip] = useState(true) ;({ data, isLoading, isFetching } = api.endpoints.getIncrementedAmount.useQuery(undefined, { refetchOnMountOrArgChange: 0.5, @@ -539,14 +533,14 @@ describe('hooks tests', () => { fireEvent.click(screen.getByText('change skip')) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) }) @@ -557,7 +551,7 @@ describe('hooks tests', () => { let data, isLoading, isFetching function User() { - const [skip, setSkip] = React.useState(true) + const [skip, setSkip] = useState(true) ;({ data, isLoading, isFetching } = api.endpoints.getIncrementedAmount.useQuery(undefined, { skip, @@ -585,7 +579,7 @@ describe('hooks tests', () => { fireEvent.click(screen.getByText('change skip')) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => { @@ -622,20 +616,20 @@ describe('hooks tests', () => { fireEvent.click(screen.getByText('change skip')) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('2') + expect(screen.getByTestId('amount').textContent).toBe('2'), ) }) test(`useQuery refetches when query args object changes even if serialized args don't change`, async () => { function ItemList() { - const [pageNumber, setPageNumber] = React.useState(0) + const [pageNumber, setPageNumber] = useState(0) const { data = [] } = api.useListItemsQuery({ pageNumber }) const renderedItems = data.map((item) => ( @@ -681,7 +675,7 @@ describe('hooks tests', () => { isUninitialized: false, refetch: expect.any(Function), status: 'pending', - }) + }), ) }) test('with `selectFromResult`', async () => { @@ -690,7 +684,7 @@ describe('hooks tests', () => { () => api.endpoints.getUser.useQuery(5, { selectFromResult }), { wrapper: storeRef.wrapper, - } + }, ) await waitFor(() => expect(result.current.isSuccess).toBe(true)) @@ -713,7 +707,7 @@ describe('hooks tests', () => { () => api.endpoints.getIncrementedAmount.useQuery(), { wrapper: storeRef.wrapper, - } + }, ) await waitFor(() => expect(result.current.isSuccess).toBe(true)) @@ -757,18 +751,18 @@ describe('hooks tests', () => { } // 1) Initial state: an active subscription - const { result, rerender, unmount } = renderHook( + const { rerender, unmount } = renderHook( ([arg, options]: Parameters< typeof pokemonApi.useGetPokemonByNameQuery >) => pokemonApi.useGetPokemonByNameQuery(arg, options), { wrapper: storeRef.wrapper, initialProps: ['a'], - } + }, ) await act(async () => { - await delay(1) + await waitMs(1) }) // 2) Set the current subscription to `{skip: true} @@ -797,13 +791,13 @@ describe('hooks tests', () => { checkNumSubscriptions('b', 1) await act(async () => { - await delay(1) + await waitMs(1) }) unmount() await act(async () => { - await delay(1) + await waitMs(1) }) // There should be no subscription entries left over after changing @@ -812,13 +806,13 @@ describe('hooks tests', () => { const finalSubscriptions = getSubscriptions() - for (let cacheKeyEntry of Object.values(finalSubscriptions)) { + for (const cacheKeyEntry of Object.values(finalSubscriptions)) { expect(Object.values(cacheKeyEntry!).length).toBe(0) } }) describe('Hook middleware requirements', () => { - let mock: SpyInstance + let mock: MockInstance beforeEach(() => { mock = vi.spyOn(console, 'error').mockImplementation(() => {}) @@ -840,12 +834,12 @@ describe('hooks tests', () => { () => api.endpoints.getIncrementedAmount.useQuery(), { wrapper: withProvider(store), - } + }, ) } expect(doRender).toThrowError( - /Warning: Middleware for RTK-Query API at reducerPath "api" has not been added to the store/ + /Warning: Middleware for RTK-Query API at reducerPath "api" has not been added to the store/, ) }) }) @@ -882,7 +876,7 @@ describe('hooks tests', () => { expect(getRenderCount()).toBe(1) await waitFor(() => - expect(screen.getByTestId('isUninitialized').textContent).toBe('true') + expect(screen.getByTestId('isUninitialized').textContent).toBe('true'), ) await waitFor(() => expect(data).toBeUndefined()) @@ -890,19 +884,19 @@ describe('hooks tests', () => { expect(getRenderCount()).toBe(2) await waitFor(() => - expect(screen.getByTestId('isUninitialized').textContent).toBe('false') + expect(screen.getByTestId('isUninitialized').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) expect(getRenderCount()).toBe(3) fireEvent.click(screen.getByTestId('fetchButton')) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) expect(getRenderCount()).toBe(5) }) @@ -910,7 +904,7 @@ describe('hooks tests', () => { test('useLazyQuery accepts updated subscription options and only dispatches updateSubscriptionOptions when values are updated', async () => { let interval = 1000 function User() { - const [options, setOptions] = React.useState() + const [options, setOptions] = useState() const [fetchUser, { data: hookData, isFetching, isUninitialized }] = api.endpoints.getUser.useLazyQuery(options) getRenderCount = useRenderCounter() @@ -943,7 +937,7 @@ describe('hooks tests', () => { expect(getRenderCount()).toBe(1) // hook mount await waitFor(() => - expect(screen.getByTestId('isUninitialized').textContent).toBe('true') + expect(screen.getByTestId('isUninitialized').textContent).toBe('true'), ) await waitFor(() => expect(data).toBeUndefined()) @@ -951,10 +945,10 @@ describe('hooks tests', () => { expect(getRenderCount()).toBe(2) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) expect(getRenderCount()).toBe(3) @@ -963,10 +957,10 @@ describe('hooks tests', () => { fireEvent.click(screen.getByTestId('fetchButton')) // perform new request = 2 await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) expect(getRenderCount()).toBe(6) @@ -977,15 +971,15 @@ describe('hooks tests', () => { fireEvent.click(screen.getByTestId('fetchButton')) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) expect(getRenderCount()).toBe(9) expect( - actions.filter(api.internalActions.updateSubscriptionOptions.match) + actions.filter(api.internalActions.updateSubscriptionOptions.match), ).toHaveLength(1) }) @@ -1014,61 +1008,61 @@ describe('hooks tests', () => { const { unmount } = render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isUninitialized').textContent).toBe('true') + expect(screen.getByTestId('isUninitialized').textContent).toBe('true'), ) await waitFor(() => expect(data).toBeUndefined()) fireEvent.click(screen.getByTestId('fetchUser1')) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) // Being that there is only the initial query, no unsubscribe should be dispatched expect( - actions.filter(api.internalActions.unsubscribeQueryResult.match) + actions.filter(api.internalActions.unsubscribeQueryResult.match), ).toHaveLength(0) fireEvent.click(screen.getByTestId('fetchUser2')) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) expect( - actions.filter(api.internalActions.unsubscribeQueryResult.match) + actions.filter(api.internalActions.unsubscribeQueryResult.match), ).toHaveLength(1) fireEvent.click(screen.getByTestId('fetchUser1')) expect( - actions.filter(api.internalActions.unsubscribeQueryResult.match) + actions.filter(api.internalActions.unsubscribeQueryResult.match), ).toHaveLength(2) // we always unsubscribe the original promise and create a new one fireEvent.click(screen.getByTestId('fetchUser1')) expect( - actions.filter(api.internalActions.unsubscribeQueryResult.match) + actions.filter(api.internalActions.unsubscribeQueryResult.match), ).toHaveLength(3) unmount() // We unsubscribe after the component unmounts expect( - actions.filter(api.internalActions.unsubscribeQueryResult.match) + actions.filter(api.internalActions.unsubscribeQueryResult.match), ).toHaveLength(4) }) test('useLazyQuery hook callback returns various properties to handle the result', async () => { function User() { const [getUser] = api.endpoints.getUser.useLazyQuery() - const [{ successMsg, errMsg, isAborted }, setValues] = React.useState({ + const [{ successMsg, errMsg, isAborted }, setValues] = useState({ successMsg: '', errMsg: '', isAborted: false, @@ -1077,38 +1071,11 @@ describe('hooks tests', () => { const handleClick = (abort: boolean) => async () => { const res = getUser(1) - // no-op simply for clearer type assertions - res.then((result) => { - if (result.isSuccess) { - expectType<{ - data: { - name: string - } - }>(result) - } - if (result.isError) { - expectType<{ - error: { status: number; data: unknown } | SerializedError - }>(result) - } - }) - - expectType(res.arg) - expectType(res.requestId) - expectType<() => void>(res.abort) - expectType<() => Promise<{ name: string }>>(res.unwrap) - expectType<() => void>(res.unsubscribe) - expectType<(options: SubscriptionOptions) => void>( - res.updateSubscriptionOptions - ) - expectType<() => void>(res.refetch) - // abort the query immediately to force an error if (abort) res.abort() res .unwrap() .then((result) => { - expectType<{ name: string }>(result) setValues({ successMsg: `Successfully fetched user ${result.name}`, errMsg: '', @@ -1143,14 +1110,14 @@ describe('hooks tests', () => { expect(screen.queryByText('Request was aborted')).toBeNull() fireEvent.click( - screen.getByRole('button', { name: 'Fetch User and abort' }) + screen.getByRole('button', { name: 'Fetch User and abort' }), ) await screen.findByText('An error has occurred fetching userId: 1') expect(screen.queryByText(/Successfully fetched user/i)).toBeNull() screen.getByText('Request was aborted') fireEvent.click( - screen.getByRole('button', { name: 'Fetch User successfully' }) + screen.getByRole('button', { name: 'Fetch User successfully' }), ) await screen.findByText('Successfully fetched user Timmy') expect(screen.queryByText(/An error has occurred/i)).toBeNull() @@ -1162,7 +1129,7 @@ describe('hooks tests', () => { const [getUser, { data, error }] = api.endpoints.getUserAndForceError.useLazyQuery() - const [unwrappedError, setUnwrappedError] = React.useState() + const [unwrappedError, setUnwrappedError] = useState() const handleClick = async () => { const res = getUser(1) @@ -1203,7 +1170,7 @@ describe('hooks tests', () => { data: null, }) expect(JSON.parse(unwrappedErrorResult)).toMatchObject( - JSON.parse(errorResult) + JSON.parse(errorResult), ) } }) @@ -1215,7 +1182,7 @@ describe('hooks tests', () => { function User() { const [getUser, { data, error }] = api.endpoints.getUser.useLazyQuery() - const [unwrappedResult, setUnwrappedResult] = React.useState< + const [unwrappedResult, setUnwrappedResult] = useState< undefined | { name: string } >() @@ -1254,7 +1221,7 @@ describe('hooks tests', () => { name: 'Timmy', }) expect(JSON.parse(unwrappedDataResult)).toMatchObject( - JSON.parse(dataResult) + JSON.parse(dataResult), ) } }) @@ -1282,14 +1249,14 @@ describe('hooks tests', () => { render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) fireEvent.click(screen.getByText('Update User')) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) }) @@ -1314,56 +1281,31 @@ describe('hooks tests', () => { fireEvent.click(screen.getByText('Update User')) await waitFor(() => expect(screen.getByTestId('result').textContent).toBe( - JSON.stringify(result) - ) + JSON.stringify(result), + ), ) }) test('useMutation hook callback returns various properties to handle the result', async () => { function User() { const [updateUser] = api.endpoints.updateUser.useMutation() - const [successMsg, setSuccessMsg] = React.useState('') - const [errMsg, setErrMsg] = React.useState('') - const [isAborted, setIsAborted] = React.useState(false) + const [successMsg, setSuccessMsg] = useState('') + const [errMsg, setErrMsg] = useState('') + const [isAborted, setIsAborted] = useState(false) const handleClick = async () => { const res = updateUser({ name: 'Banana' }) - // no-op simply for clearer type assertions - res.then((result) => { - expectType< - | { - error: { status: number; data: unknown } | SerializedError - } - | { - data: { - name: string - } - } - >(result) - }) - - expectType<{ - endpointName: string - originalArgs: { name: string } - track?: boolean - }>(res.arg) - expectType(res.requestId) - expectType<() => void>(res.abort) - expectType<() => Promise<{ name: string }>>(res.unwrap) - expectType<() => void>(res.reset) - // abort the mutation immediately to force an error res.abort() res .unwrap() .then((result) => { - expectType<{ name: string }>(result) setSuccessMsg(`Successfully updated user ${result.name}`) }) .catch((err) => { setErrMsg( - `An error has occurred updating user ${res.arg.originalArgs.name}` + `An error has occurred updating user ${res.arg.originalArgs.name}`, ) if (err.name === 'AbortError') { setIsAborted(true) @@ -1387,7 +1329,7 @@ describe('hooks tests', () => { expect(screen.queryByText('Request was aborted')).toBeNull() fireEvent.click( - screen.getByRole('button', { name: 'Update User and abort' }) + screen.getByRole('button', { name: 'Update User and abort' }), ) await screen.findByText('An error has occurred updating user Banana') expect(screen.queryByText(/Successfully updated user/i)).toBeNull() @@ -1399,7 +1341,7 @@ describe('hooks tests', () => { () => api.endpoints.updateUser.useMutation(), { wrapper: storeRef.wrapper, - } + }, ) const arg = { name: 'Foo' } @@ -1420,8 +1362,8 @@ describe('hooks tests', () => { {result.isUninitialized ? 'isUninitialized' : result.isSuccess - ? 'isSuccess' - : 'other'} + ? 'isSuccess' + : 'other'} {result.originalArgs?.name} @@ -1474,12 +1416,12 @@ describe('hooks tests', () => { // Resolve initial query await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) userEvent.hover(screen.getByTestId('highPriority')) expect( - api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any) + api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any), ).toEqual({ data: { name: 'Timmy' }, endpointName: 'getUser', @@ -1496,11 +1438,11 @@ describe('hooks tests', () => { }) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) expect( - api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any) + api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any), ).toEqual({ data: { name: 'Timmy' }, endpointName: 'getUser', @@ -1542,13 +1484,13 @@ describe('hooks tests', () => { // Let the initial query resolve await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) // Try to prefetch what we just loaded userEvent.hover(screen.getByTestId('lowPriority')) expect( - api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any) + api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any), ).toEqual({ data: { name: 'Timmy' }, endpointName: 'getUser', @@ -1566,7 +1508,7 @@ describe('hooks tests', () => { await waitMs() expect( - api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any) + api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any), ).toEqual({ data: { name: 'Timmy' }, endpointName: 'getUser', @@ -1607,7 +1549,7 @@ describe('hooks tests', () => { render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) // Wait 400ms, making it respect ifOlderThan @@ -1616,7 +1558,7 @@ describe('hooks tests', () => { // This should run the query being that we're past the threshold userEvent.hover(screen.getByTestId('lowPriority')) expect( - api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any) + api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any), ).toEqual({ data: { name: 'Timmy' }, endpointName: 'getUser', @@ -1632,11 +1574,11 @@ describe('hooks tests', () => { }) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) expect( - api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any) + api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any), ).toEqual({ data: { name: 'Timmy' }, endpointName: 'getUser', @@ -1677,19 +1619,19 @@ describe('hooks tests', () => { render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) await waitMs() // Get a snapshot of the last result const latestQueryData = api.endpoints.getUser.select(USER_ID)( - storeRef.store.getState() as any + storeRef.store.getState() as any, ) userEvent.hover(screen.getByTestId('lowPriority')) // Serve up the result from the cache being that the condition wasn't met expect( - api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any) + api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any), ).toEqual(latestQueryData) }) @@ -1717,7 +1659,7 @@ describe('hooks tests', () => { userEvent.hover(screen.getByTestId('lowPriority')) expect( - api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any) + api.endpoints.getUser.select(USER_ID)(storeRef.store.getState() as any), ).toEqual({ endpointName: 'getUser', isError: false, @@ -1752,15 +1694,19 @@ describe('hooks tests', () => { test('initially failed useQueries that provide an tag will refetch after a mutation invalidates it', async () => { const checkSessionData = { name: 'matt' } server.use( - rest.get('https://example.com/me', (req, res, ctx) => { - return res.once(ctx.status(500)) + http.get( + 'https://example.com/me', + () => { + return HttpResponse.json(null, { status: 500 }) + }, + { once: true }, + ), + http.get('https://example.com/me', () => { + return HttpResponse.json(checkSessionData) }), - rest.get('https://example.com/me', (req, res, ctx) => { - return res(ctx.json(checkSessionData)) + http.post('https://example.com/login', () => { + return HttpResponse.json(null, { status: 200 }) }), - rest.post('https://example.com/login', (req, res, ctx) => { - return res(ctx.status(200)) - }) ) let data, isLoading, isError function User() { @@ -1781,34 +1727,34 @@ describe('hooks tests', () => { render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('isError').textContent).toBe('true') + expect(screen.getByTestId('isError').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('user').textContent).toBe('') + expect(screen.getByTestId('user').textContent).toBe(''), ) fireEvent.click(screen.getByRole('button', { name: /Login/i })) await waitFor(() => - expect(screen.getByTestId('loginLoading').textContent).toBe('true') + expect(screen.getByTestId('loginLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('loginLoading').textContent).toBe('false') + expect(screen.getByTestId('loginLoading').textContent).toBe('false'), ) // login mutation will cause the original errored out query to refire, clearing the error and setting the user await waitFor(() => - expect(screen.getByTestId('isError').textContent).toBe('false') + expect(screen.getByTestId('isError').textContent).toBe('false'), ) await waitFor(() => expect(screen.getByTestId('user').textContent).toBe( - JSON.stringify(checkSessionData) - ) + JSON.stringify(checkSessionData), + ), ) const { checkSession, login } = api.endpoints @@ -1819,7 +1765,7 @@ describe('hooks tests', () => { login.matchPending, login.matchFulfilled, checkSession.matchPending, - checkSession.matchFulfilled + checkSession.matchFulfilled, ) }) }) @@ -1869,14 +1815,14 @@ describe('hooks with createApi defaults set', () => { const { unmount } = render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) unmount() @@ -1897,14 +1843,14 @@ describe('hooks with createApi defaults set', () => { render(, { wrapper: storeRef.wrapper }) // Let's make sure we actually fetch, and we increment await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('2') + expect(screen.getByTestId('amount').textContent).toBe('2'), ) }) @@ -1925,14 +1871,14 @@ describe('hooks with createApi defaults set', () => { let { unmount } = render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) unmount() @@ -1953,10 +1899,10 @@ describe('hooks with createApi defaults set', () => { render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) }) @@ -1977,40 +1923,45 @@ describe('hooks with createApi defaults set', () => { posts = [...initialPosts] const handlers = [ - rest.get('https://example.com/posts', (req, res, ctx) => { - return res(ctx.json(posts)) + http.get('https://example.com/posts', () => { + return HttpResponse.json(posts) }), - rest.put>( + http.put<{ id: string }, Partial>( 'https://example.com/post/:id', - (req, res, ctx) => { - const id = Number(req.params.id) + async ({ request, params }) => { + const body = await request.json() + const id = Number(params.id) const idx = posts.findIndex((post) => post.id === id) const newPosts = posts.map((post, index) => index !== idx ? post : { - ...req.body, + ...body, id, - name: req.body.name || post.name, + name: body?.name || post.name, fetched_at: new Date().toUTCString(), - } + }, ) posts = [...newPosts] - return res(ctx.json(posts)) - } + return HttpResponse.json(posts) + }, + ), + http.post>( + 'https://example.com/post', + async ({ request }) => { + const body = await request.json() + const post = body + startingId += 1 + posts.concat({ + ...post, + fetched_at: new Date().toISOString(), + id: startingId, + }) + return HttpResponse.json(posts) + }, ), - rest.post('https://example.com/post', (req, res, ctx) => { - let post = req.body as Omit - startingId += 1 - posts.concat({ - ...post, - fetched_at: new Date().toISOString(), - id: startingId, - }) - return res(ctx.json(posts)) - }), ] server.use(...handlers) @@ -2053,25 +2004,19 @@ describe('hooks with createApi defaults set', () => { }) const counterSlice = createSlice({ - name: "counter", + name: 'counter', initialState: { count: 0 }, reducers: { increment(state) { state.count++ - } - } + }, + }, }) const storeRef = setupApiStore(api, { counter: counterSlice.reducer, }) - expectExactType(api.useGetPostsQuery)(api.endpoints.getPosts.useQuery) - expectExactType(api.useUpdatePostMutation)( - api.endpoints.updatePost.useMutation - ) - expectExactType(api.useAddPostMutation)(api.endpoints.addPost.useMutation) - test('useQueryState serves a deeply memoized value and does not rerender unnecessarily', async () => { function Posts() { const { data: posts } = api.endpoints.getPosts.useQuery() @@ -2113,7 +2058,7 @@ describe('hooks with createApi defaults set', () => {
, - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) expect(getRenderCount()).toBe(1) @@ -2187,7 +2132,7 @@ describe('hooks with createApi defaults set', () => {

( - type: T + type: T, ): PayloadActionCreator // @public export function createAction< PA extends PrepareAction, - T extends string = string + T extends string = string, >( type: T, - prepareAction: PA + prepareAction: PA, ): PayloadActionCreator['payload'], T, PA> // @public (undocumented) export function createAsyncThunk( typePrefix: string, payloadCreator: AsyncThunkPayloadCreator, - options?: AsyncThunkOptions + options?: AsyncThunkOptions, ): AsyncThunk // @public (undocumented) export function createAsyncThunk< Returned, ThunkArg, - ThunkApiConfig extends AsyncThunkConfig + ThunkApiConfig extends AsyncThunkConfig, >( typePrefix: string, payloadCreator: AsyncThunkPayloadCreator, - options?: AsyncThunkOptions + options?: AsyncThunkOptions, ): AsyncThunk // @public @@ -287,7 +287,7 @@ export function createEntityAdapter(options?: { // @public export function createImmutableStateInvariantMiddleware( - options?: ImmutableStateInvariantMiddlewareOptions + options?: ImmutableStateInvariantMiddlewareOptions, ): Middleware export { createNextState } @@ -295,41 +295,41 @@ export { createNextState } // @public export function createReducer>( initialState: S | (() => S), - builderCallback: (builder: ActionReducerMapBuilder) => void + builderCallback: (builder: ActionReducerMapBuilder) => void, ): ReducerWithInitialState // @public export function createReducer< S extends NotFunction, - CR extends CaseReducers = CaseReducers + CR extends CaseReducers = CaseReducers, >( initialState: S | (() => S), actionsMap: CR, actionMatchers?: ActionMatcherDescriptionCollection, - defaultCaseReducer?: CaseReducer + defaultCaseReducer?: CaseReducer, ): ReducerWithInitialState export { createSelector } // @public export function createSerializableStateInvariantMiddleware( - options?: SerializableStateInvariantMiddlewareOptions + options?: SerializableStateInvariantMiddlewareOptions, ): Middleware // @public export function createSlice< State, CaseReducers extends SliceCaseReducers, - Name extends string = string + Name extends string = string, >( - options: CreateSliceOptions + options: CreateSliceOptions, ): Slice // @public export interface CreateSliceOptions< State = any, CR extends SliceCaseReducers = SliceCaseReducers, - Name extends string = string + Name extends string = string, > { extraReducers?: | CaseReducers, any> @@ -353,7 +353,7 @@ export { Draft } export interface EnhancedStore< S = any, A extends Action = UnknownAction, - M extends Middlewares = Middlewares + M extends Middlewares = Middlewares, > extends Store { dispatch: Dispatch & DispatchForMiddlewares } @@ -368,7 +368,7 @@ export interface EntityAdapter extends EntityStateAdapter { getSelectors(): EntitySelectors> // (undocumented) getSelectors( - selectState: (state: V) => EntityState + selectState: (state: V) => EntityState, ): EntitySelectors // (undocumented) selectId: IdSelector @@ -406,102 +406,102 @@ export interface EntityStateAdapter { // (undocumented) addMany>( state: PreventAny, - entities: readonly T[] | Record + entities: readonly T[] | Record, ): S // (undocumented) addMany>( state: PreventAny, - entities: PayloadAction> + entities: PayloadAction>, ): S // (undocumented) addOne>(state: PreventAny, entity: T): S // (undocumented) addOne>( state: PreventAny, - action: PayloadAction + action: PayloadAction, ): S // (undocumented) removeAll>(state: PreventAny): S // (undocumented) removeMany>( state: PreventAny, - keys: readonly EntityId[] + keys: readonly EntityId[], ): S // (undocumented) removeMany>( state: PreventAny, - keys: PayloadAction + keys: PayloadAction, ): S // (undocumented) removeOne>(state: PreventAny, key: EntityId): S // (undocumented) removeOne>( state: PreventAny, - key: PayloadAction + key: PayloadAction, ): S // (undocumented) setAll>( state: PreventAny, - entities: readonly T[] | Record + entities: readonly T[] | Record, ): S // (undocumented) setAll>( state: PreventAny, - entities: PayloadAction> + entities: PayloadAction>, ): S // (undocumented) setMany>( state: PreventAny, - entities: readonly T[] | Record + entities: readonly T[] | Record, ): S // (undocumented) setMany>( state: PreventAny, - entities: PayloadAction> + entities: PayloadAction>, ): S // (undocumented) setOne>(state: PreventAny, entity: T): S // (undocumented) setOne>( state: PreventAny, - action: PayloadAction + action: PayloadAction, ): S // (undocumented) updateMany>( state: PreventAny, - updates: ReadonlyArray> + updates: ReadonlyArray>, ): S // (undocumented) updateMany>( state: PreventAny, - updates: PayloadAction>> + updates: PayloadAction>>, ): S // (undocumented) updateOne>( state: PreventAny, - update: Update + update: Update, ): S // (undocumented) updateOne>( state: PreventAny, - update: PayloadAction> + update: PayloadAction>, ): S // (undocumented) upsertMany>( state: PreventAny, - entities: readonly T[] | Record + entities: readonly T[] | Record, ): S // (undocumented) upsertMany>( state: PreventAny, - entities: PayloadAction> + entities: PayloadAction>, ): S // (undocumented) upsertOne>(state: PreventAny, entity: T): S // (undocumented) upsertOne>( state: PreventAny, - entity: PayloadAction + entity: PayloadAction, ): S } @@ -511,7 +511,7 @@ export function findNonSerializableValue( path?: string, isSerializable?: (value: unknown) => boolean, getEntries?: (value: unknown) => [string, any][], - ignoredPaths?: readonly (string | RegExp)[] + ignoredPaths?: readonly (string | RegExp)[], ): NonSerializableValue | false export { freeze } @@ -523,12 +523,12 @@ export function getDefaultMiddleware< thunk: true immutableCheck: true serializableCheck: true - } + }, >(options?: O): MiddlewareArray | ThunkMiddlewareFor> // @public export function getType( - actionCreator: PayloadActionCreator + actionCreator: PayloadActionCreator, ): T // @public (undocumented) @@ -547,7 +547,7 @@ export interface ImmutableStateInvariantMiddlewareOptions { export function isAllOf, ...Matcher[]]>( ...matchers: Matchers ): ( - action: any + action: any, ) => action is UnionToIntersection> // @public @@ -557,38 +557,38 @@ export function isAnyOf, ...Matcher[]]>( // @public export function isAsyncThunkAction(): ( - action: any + action: any, ) => action is UnknownAsyncThunkAction // @public export function isAsyncThunkAction< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >( ...asyncThunks: AsyncThunks ): (action: any) => action is ActionsFromAsyncThunk // @public export function isAsyncThunkAction( - action: any + action: any, ): action is UnknownAsyncThunkAction export { isDraft } // @public export function isFulfilled(): ( - action: any + action: any, ) => action is UnknownAsyncThunkFulfilledAction // @public export function isFulfilled< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >( ...asyncThunks: AsyncThunks ): (action: any) => action is FulfilledActionFromAsyncThunk // @public export function isFulfilled( - action: any + action: any, ): action is UnknownAsyncThunkFulfilledAction // @public @@ -596,12 +596,12 @@ export function isImmutableDefault(value: unknown): boolean // @public export function isPending(): ( - action: any + action: any, ) => action is UnknownAsyncThunkPendingAction // @public export function isPending< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >( ...asyncThunks: AsyncThunks ): (action: any) => action is PendingActionFromAsyncThunk @@ -617,43 +617,43 @@ export function isPlainObject(value: unknown): value is object // @public export function isRejected(): ( - action: any + action: any, ) => action is UnknownAsyncThunkRejectedAction // @public export function isRejected< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >( ...asyncThunks: AsyncThunks ): (action: any) => action is RejectedActionFromAsyncThunk // @public export function isRejected( - action: any + action: any, ): action is UnknownAsyncThunkRejectedAction // @public export function isRejectedWithValue(): ( - action: any + action: any, ) => action is UnknownAsyncThunkRejectedAction // @public export function isRejectedWithValue< - AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]] + AsyncThunks extends [AnyAsyncThunk, ...AnyAsyncThunk[]], >( ...asyncThunks: AsyncThunks ): ( - action: any + action: any, ) => action is RejectedWithValueActionFromAsyncThunk // @public export function isRejectedWithValue( - action: any + action: any, ): action is UnknownAsyncThunkRejectedAction // @public (undocumented) export class MiddlewareArray< - Middlewares extends Middleware + Middlewares extends Middleware, > extends Array { // (undocumented) static get [Symbol.species](): any @@ -661,7 +661,7 @@ export class MiddlewareArray< constructor(...items: Middlewares[]) // (undocumented) concat>>( - items: AdditionalMiddlewares + items: AdditionalMiddlewares, ): MiddlewareArray // (undocumented) concat>>( @@ -669,7 +669,7 @@ export class MiddlewareArray< ): MiddlewareArray // (undocumented) prepend>>( - items: AdditionalMiddlewares + items: AdditionalMiddlewares, ): MiddlewareArray // (undocumented) prepend>>( @@ -696,7 +696,7 @@ export type PayloadAction< P = void, T extends string = string, M = never, - E = never + E = never, > = { payload: P type: T @@ -715,7 +715,7 @@ export type PayloadAction< export type PayloadActionCreator< P = void, T extends string = string, - PA extends PrepareAction

, - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) expect(getRenderCount()).toBe(2) @@ -2239,7 +2184,7 @@ describe('hooks with createApi defaults set', () => {
, - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) expect(getRenderCount()).toBe(1) @@ -2292,7 +2237,7 @@ describe('hooks with createApi defaults set', () => { }) getRenderCount = useRenderCounter() - React.useEffect(() => { + useEffect(() => { expectablePost = post }, [post]) @@ -2308,7 +2253,7 @@ describe('hooks with createApi defaults set', () => {
, - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) expect(getRenderCount()).toBe(1) @@ -2342,9 +2287,7 @@ describe('hooks with createApi defaults set', () => { return (
- {posts?.map((post) => ( -
{post.name}
- ))} + {posts?.map((post) =>
{post.name}
)}
) } @@ -2353,7 +2296,9 @@ describe('hooks with createApi defaults set', () => { return (
storeRef.store.dispatch(counterSlice.actions.increment())} + onClick={() => + storeRef.store.dispatch(counterSlice.actions.increment()) + } > Increment Count
@@ -2365,7 +2310,7 @@ describe('hooks with createApi defaults set', () => { , - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) await waitFor(() => expect(getRenderCount()).toBe(2)) @@ -2377,12 +2322,6 @@ describe('hooks with createApi defaults set', () => { test('useQuery with selectFromResult option has a type error if the result is not an object', async () => { function SelectedPost() { - const _res1 = api.endpoints.getPosts.useQuery(undefined, { - // selectFromResult must always return an object - // @ts-expect-error - selectFromResult: ({ data }) => data?.length ?? 0, - }) - const res2 = api.endpoints.getPosts.useQuery(undefined, { // selectFromResult must always return an object selectFromResult: ({ data }) => ({ size: data?.length ?? 0 }), @@ -2399,7 +2338,7 @@ describe('hooks with createApi defaults set', () => {
, - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) expect(screen.getByTestId('size2').textContent).toBe('0') @@ -2473,7 +2412,7 @@ describe('hooks with createApi defaults set', () => { increment.matchFulfilled, increment.matchPending, api.internalActions.removeMutationResult.match, - increment.matchFulfilled + increment.matchFulfilled, ) }) @@ -2502,16 +2441,16 @@ describe('hooks with createApi defaults set', () => { fireEvent.click(screen.getByTestId('incrementButton')) await waitFor(() => expect(screen.getByTestId('data').textContent).toBe( - JSON.stringify({ amount: 1 }) - ) + JSON.stringify({ amount: 1 }), + ), ) expect(getRenderCount()).toBe(3) fireEvent.click(screen.getByTestId('incrementButton')) await waitFor(() => expect(screen.getByTestId('data').textContent).toBe( - JSON.stringify({ amount: 2 }) - ) + JSON.stringify({ amount: 2 }), + ), ) expect(getRenderCount()).toBe(5) }) @@ -2540,19 +2479,19 @@ describe('hooks with createApi defaults set', () => { expect(getRenderCount()).toBe(2) // will be pending, isLoading: true, await waitFor(() => - expect(screen.getByTestId('status').textContent).toBe('pending') + expect(screen.getByTestId('status').textContent).toBe('pending'), ) await waitFor(() => - expect(screen.getByTestId('status').textContent).toBe('fulfilled') + expect(screen.getByTestId('status').textContent).toBe('fulfilled'), ) expect(getRenderCount()).toBe(3) fireEvent.click(screen.getByTestId('incrementButton')) await waitFor(() => - expect(screen.getByTestId('status').textContent).toBe('pending') + expect(screen.getByTestId('status').textContent).toBe('pending'), ) await waitFor(() => - expect(screen.getByTestId('status').textContent).toBe('fulfilled') + expect(screen.getByTestId('status').textContent).toBe('fulfilled'), ) expect(getRenderCount()).toBe(5) }) @@ -2599,18 +2538,18 @@ describe('skip behaviour', () => { { wrapper: storeRef.wrapper, initialProps: [1, { skip: true }], - } + }, ) expect(result.current).toEqual(uninitialized) - await delay(1) + await waitMs(1) expect(getSubscriptionCount('getUser(1)')).toBe(0) await act(async () => { rerender([1]) }) expect(result.current).toMatchObject({ status: QueryStatus.fulfilled }) - await delay(1) + await waitMs(1) expect(getSubscriptionCount('getUser(1)')).toBe(1) await act(async () => { @@ -2621,7 +2560,7 @@ describe('skip behaviour', () => { currentData: undefined, data: { name: 'Timmy' }, }) - await delay(1) + await waitMs(1) expect(getSubscriptionCount('getUser(1)')).toBe(0) }) @@ -2632,11 +2571,11 @@ describe('skip behaviour', () => { { wrapper: storeRef.wrapper, initialProps: [skipToken], - } + }, ) expect(result.current).toEqual(uninitialized) - await delay(1) + await waitMs(1) expect(getSubscriptionCount('getUser(1)')).toBe(0) // also no subscription on `getUser(skipToken)` or similar: @@ -2646,7 +2585,7 @@ describe('skip behaviour', () => { rerender([1]) }) expect(result.current).toMatchObject({ status: QueryStatus.fulfilled }) - await delay(1) + await waitMs(1) expect(getSubscriptionCount('getUser(1)')).toBe(1) expect(getSubscriptions()).not.toEqual({}) @@ -2658,7 +2597,7 @@ describe('skip behaviour', () => { currentData: undefined, data: { name: 'Timmy' }, }) - await delay(1) + await waitMs(1) expect(getSubscriptionCount('getUser(1)')).toBe(0) }) @@ -2669,11 +2608,11 @@ describe('skip behaviour', () => { { wrapper: storeRef.wrapper, initialProps: [1], - } + }, ) await act(async () => { - await delay(1) + await waitMs(1) }) // Normal fulfilled result, with both `data` and `currentData` @@ -2686,7 +2625,7 @@ describe('skip behaviour', () => { await act(async () => { rerender([1, { skip: true }]) - await delay(1) + await waitMs(1) }) // After skipping, the query is "uninitialized", but still retains the last fetched `data` @@ -2699,20 +2638,3 @@ describe('skip behaviour', () => { }) }) }) - -// type tests: -{ - const ANY = {} as any - - // UseQuery type can be used to recreate the hook type - const fakeQuery = ANY as UseQuery< - typeof api.endpoints.getUser.Types.QueryDefinition - > - expectExactType(fakeQuery)(api.endpoints.getUser.useQuery) - - // UseMutation type can be used to recreate the hook type - const fakeMutation = ANY as UseMutation< - typeof api.endpoints.updateUser.Types.MutationDefinition - > - expectExactType(fakeMutation)(api.endpoints.updateUser.useMutation) -} diff --git a/packages/toolkit/src/query/tests/buildInitiate.test.tsx b/packages/toolkit/src/query/tests/buildInitiate.test.tsx index 27925d14b2..f7022acf30 100644 --- a/packages/toolkit/src/query/tests/buildInitiate.test.tsx +++ b/packages/toolkit/src/query/tests/buildInitiate.test.tsx @@ -1,7 +1,7 @@ +import { setupApiStore } from '../../tests/utils/helpers' import { createApi } from '../core' import type { SubscriptionSelectors } from '../core/buildMiddleware/types' import { fakeBaseQuery } from '../fakeBaseQuery' -import { setupApiStore } from './helpers' let calls = 0 const api = createApi({ @@ -30,7 +30,7 @@ let isRequestSubscribed: SubscriptionSelectors['isRequestSubscribed'] beforeEach(() => { ;({ getSubscriptions, isRequestSubscribed } = storeRef.store.dispatch( - api.internalActions.internal_getRTKQSubscriptions() + api.internalActions.internal_getRTKQSubscriptions(), ) as unknown as SubscriptionSelectors) }) @@ -45,7 +45,7 @@ test('multiple synchonrous initiate calls with pre-existing cache entry', async const secondValuePromise = store.dispatch(api.endpoints.increment.initiate()) // and one with a forced refresh const thirdValuePromise = store.dispatch( - api.endpoints.increment.initiate(undefined, { forceRefetch: true }) + api.endpoints.increment.initiate(undefined, { forceRefetch: true }), ) // and another increment const fourthValuePromise = store.dispatch(api.endpoints.increment.initiate()) @@ -74,16 +74,16 @@ describe('calling initiate without a cache entry, with subscribe: false still re const { store, api } = storeRef calls = 0 const promise = store.dispatch( - api.endpoints.increment.initiate(undefined, { subscribe: false }) + api.endpoints.increment.initiate(undefined, { subscribe: false }), ) expect(isRequestSubscribed('increment(undefined)', promise.requestId)).toBe( - false + false, ) expect( isRequestSubscribed( 'increment(undefined)', - `${promise.requestId}_running` - ) + `${promise.requestId}_running`, + ), ).toBe(true) await expect(promise).resolves.toMatchObject({ @@ -93,8 +93,8 @@ describe('calling initiate without a cache entry, with subscribe: false still re expect( isRequestSubscribed( 'increment(undefined)', - `${promise.requestId}_running` - ) + `${promise.requestId}_running`, + ), ).toBe(false) }) @@ -102,20 +102,20 @@ describe('calling initiate without a cache entry, with subscribe: false still re const { store, api } = storeRef calls = 0 const promise = store.dispatch( - api.endpoints.failing.initiate(undefined, { subscribe: false }) + api.endpoints.failing.initiate(undefined, { subscribe: false }), ) expect(isRequestSubscribed('failing(undefined)', promise.requestId)).toBe( - false + false, ) expect( - isRequestSubscribed('failing(undefined)', `${promise.requestId}_running`) + isRequestSubscribed('failing(undefined)', `${promise.requestId}_running`), ).toBe(true) await expect(promise).resolves.toMatchObject({ status: 'rejected', }) expect( - isRequestSubscribed('failing(undefined)', `${promise.requestId}_running`) + isRequestSubscribed('failing(undefined)', `${promise.requestId}_running`), ).toBe(false) }) }) diff --git a/packages/toolkit/src/query/tests/buildMiddleware.test-d.ts b/packages/toolkit/src/query/tests/buildMiddleware.test-d.ts new file mode 100644 index 0000000000..b7382f4077 --- /dev/null +++ b/packages/toolkit/src/query/tests/buildMiddleware.test-d.ts @@ -0,0 +1,83 @@ +import { createApi } from '@reduxjs/toolkit/query' + +const baseQuery = (args?: any) => ({ data: args }) + +const api = createApi({ + baseQuery, + tagTypes: ['Banana', 'Bread'], + endpoints: (build) => ({ + getBanana: build.query({ + query(id) { + return { url: `banana/${id}` } + }, + providesTags: ['Banana'], + }), + getBananas: build.query({ + query() { + return { url: 'bananas' } + }, + providesTags: ['Banana'], + }), + getBread: build.query({ + query(id) { + return { url: `bread/${id}` } + }, + providesTags: ['Bread'], + }), + }), +}) + +describe('type tests', () => { + it('should allow for an array of string TagTypes', () => { + api.util.invalidateTags(['Banana', 'Bread']) + }) + + it('should allow for an array of full TagTypes descriptions', () => { + api.util.invalidateTags([{ type: 'Banana' }, { type: 'Bread', id: 1 }]) + }) + + it('should allow for a mix of full descriptions as well as plain strings', () => { + api.util.invalidateTags(['Banana', { type: 'Bread', id: 1 }]) + }) + + it('should error when using non-existing TagTypes', () => { + // @ts-expect-error + api.util.invalidateTags(['Missing Tag']) + }) + + it('should error when using non-existing TagTypes in the full format', () => { + // @ts-expect-error + api.util.invalidateTags([{ type: 'Missing' }]) + }) + + it('should allow pre-fetching for an endpoint that takes an arg', () => { + api.util.prefetch('getBanana', 5, { force: true }) + api.util.prefetch('getBanana', 5, { force: false }) + api.util.prefetch('getBanana', 5, { ifOlderThan: false }) + api.util.prefetch('getBanana', 5, { ifOlderThan: 30 }) + api.util.prefetch('getBanana', 5, {}) + }) + + it('should error when pre-fetching with the incorrect arg type', () => { + // @ts-expect-error arg should be number, not string + api.util.prefetch('getBanana', '5', { force: true }) + }) + + it('should allow pre-fetching for an endpoint with a void arg', () => { + api.util.prefetch('getBananas', undefined, { force: true }) + api.util.prefetch('getBananas', undefined, { force: false }) + api.util.prefetch('getBananas', undefined, { ifOlderThan: false }) + api.util.prefetch('getBananas', undefined, { ifOlderThan: 30 }) + api.util.prefetch('getBananas', undefined, {}) + }) + + it('should error when pre-fetching with a defined arg when expecting void', () => { + // @ts-expect-error arg should be void, not number + api.util.prefetch('getBananas', 5, { force: true }) + }) + + it('should error when pre-fetching for an incorrect endpoint name', () => { + // @ts-expect-error endpoint name does not exist + api.util.prefetch('getPomegranates', undefined, { force: true }) + }) +}) diff --git a/packages/toolkit/src/query/tests/buildMiddleware.test.tsx b/packages/toolkit/src/query/tests/buildMiddleware.test.tsx index f6154ea848..0e52cb0cd1 100644 --- a/packages/toolkit/src/query/tests/buildMiddleware.test.tsx +++ b/packages/toolkit/src/query/tests/buildMiddleware.test.tsx @@ -1,5 +1,6 @@ import { createApi } from '@reduxjs/toolkit/query' -import { actionsReducer, setupApiStore, waitMs } from './helpers' +import { actionsReducer, setupApiStore } from '../../tests/utils/helpers' +import { delay } from 'msw' const baseQuery = (args?: any) => ({ data: args }) const api = createApi({ @@ -37,13 +38,13 @@ it('invalidates the specified tags', async () => { expect(storeRef.store.getState().actions).toMatchSequence( api.internalActions.middlewareRegistered.match, getBanana.matchPending, - getBanana.matchFulfilled + getBanana.matchFulfilled, ) await storeRef.store.dispatch(api.util.invalidateTags(['Banana', 'Bread'])) // Slight pause to let the middleware run and such - await waitMs(20) + await delay(20) const firstSequence = [ api.internalActions.middlewareRegistered.match, @@ -58,7 +59,7 @@ it('invalidates the specified tags', async () => { await storeRef.store.dispatch(getBread.initiate(1)) await storeRef.store.dispatch(api.util.invalidateTags([{ type: 'Bread' }])) - await waitMs(20) + await delay(20) expect(storeRef.store.getState().actions).toMatchSequence( ...firstSequence, @@ -66,53 +67,6 @@ it('invalidates the specified tags', async () => { getBread.matchFulfilled, api.util.invalidateTags.match, getBread.matchPending, - getBread.matchFulfilled + getBread.matchFulfilled, ) }) - -describe.skip('TS only tests', () => { - it('should allow for an array of string TagTypes', () => { - api.util.invalidateTags(['Banana', 'Bread']) - }) - it('should allow for an array of full TagTypes descriptions', () => { - api.util.invalidateTags([{ type: 'Banana' }, { type: 'Bread', id: 1 }]) - }) - - it('should allow for a mix of full descriptions as well as plain strings', () => { - api.util.invalidateTags(['Banana', { type: 'Bread', id: 1 }]) - }) - it('should error when using non-existing TagTypes', () => { - // @ts-expect-error - api.util.invalidateTags(['Missing Tag']) - }) - it('should error when using non-existing TagTypes in the full format', () => { - // @ts-expect-error - api.util.invalidateTags([{ type: 'Missing' }]) - }) - it('should allow pre-fetching for an endpoint that takes an arg', () => { - api.util.prefetch('getBanana', 5, { force: true }) - api.util.prefetch('getBanana', 5, { force: false }) - api.util.prefetch('getBanana', 5, { ifOlderThan: false }) - api.util.prefetch('getBanana', 5, { ifOlderThan: 30 }) - api.util.prefetch('getBanana', 5, {}) - }) - it('should error when pre-fetching with the incorrect arg type', () => { - // @ts-expect-error arg should be number, not string - api.util.prefetch('getBanana', '5', { force: true }) - }) - it('should allow pre-fetching for an endpoint with a void arg', () => { - api.util.prefetch('getBananas', undefined, { force: true }) - api.util.prefetch('getBananas', undefined, { force: false }) - api.util.prefetch('getBananas', undefined, { ifOlderThan: false }) - api.util.prefetch('getBananas', undefined, { ifOlderThan: 30 }) - api.util.prefetch('getBananas', undefined, {}) - }) - it('should error when pre-fetching with a defined arg when expecting void', () => { - // @ts-expect-error arg should be void, not number - api.util.prefetch('getBananas', 5, { force: true }) - }) - it('should error when pre-fetching for an incorrect endpoint name', () => { - // @ts-expect-error endpoint name does not exist - api.util.prefetch('getPomegranates', undefined, { force: true }) - }) -}) diff --git a/packages/toolkit/src/query/tests/buildSelector.test.ts b/packages/toolkit/src/query/tests/buildSelector.test-d.ts similarity index 83% rename from packages/toolkit/src/query/tests/buildSelector.test.ts rename to packages/toolkit/src/query/tests/buildSelector.test-d.ts index 5a62a1320d..15bf0c6be2 100644 --- a/packages/toolkit/src/query/tests/buildSelector.test.ts +++ b/packages/toolkit/src/query/tests/buildSelector.test-d.ts @@ -1,10 +1,9 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' -import { createSelector, configureStore } from '@reduxjs/toolkit' -import { expectExactType } from './helpers' +import { configureStore, createSelector } from '@reduxjs/toolkit' -describe('buildSelector', () => { - test.skip('buildSelector typetest', () => { +describe('type tests', () => { + test('buildSelector type test', () => { interface Todo { userId: number id: number @@ -32,11 +31,12 @@ describe('buildSelector', () => { [exampleQuerySelector], (queryState) => { return queryState?.data?.[0] ?? ({} as Todo) - } + }, ) + const firstTodoTitleSelector = createSelector( [todosSelector], - (todo) => todo?.title + (todo) => todo?.title, ) const store = configureStore({ @@ -50,9 +50,11 @@ describe('buildSelector', () => { // This only compiles if we carried the types through const upperTitle = todoTitle.toUpperCase() - expectExactType(upperTitle) + + expectTypeOf(upperTitle).toBeString() }) - test.skip('selectCachedArgsForQuery typetest', () => { + + test('selectCachedArgsForQuery type test', () => { interface Todo { userId: number id: number @@ -81,8 +83,8 @@ describe('buildSelector', () => { }, }) - expectExactType( - exampleApi.util.selectCachedArgsForQuery(store.getState(), 'getTodos') - ) + expectTypeOf( + exampleApi.util.selectCachedArgsForQuery(store.getState(), 'getTodos'), + ).toEqualTypeOf() }) }) diff --git a/packages/toolkit/src/query/tests/buildSlice.test.ts b/packages/toolkit/src/query/tests/buildSlice.test.ts index 1a075beb6e..72ac45b7a2 100644 --- a/packages/toolkit/src/query/tests/buildSlice.test.ts +++ b/packages/toolkit/src/query/tests/buildSlice.test.ts @@ -1,7 +1,7 @@ import { createSlice } from '@reduxjs/toolkit' import { createApi } from '@reduxjs/toolkit/query' -import { setupApiStore } from './helpers' -import { delay } from '../../utils' +import { delay } from 'msw' +import { setupApiStore } from '../../tests/utils/helpers' let shouldApiResponseSuccess = true @@ -44,7 +44,7 @@ describe('buildSlice', () => { const initialState = storeRef.store.getState() await storeRef.store.dispatch( - getUser.initiate(1, { subscriptionOptions: { pollingInterval: 10 } }) + getUser.initiate(1, { subscriptionOptions: { pollingInterval: 10 } }), ) const initialQueryState = { @@ -95,10 +95,10 @@ describe('buildSlice', () => { await storeRef.store.dispatch(getUser.initiate(1)) expect( - api.util.selectInvalidatedBy(storeRef.store.getState(), ['SUCCEED']) + api.util.selectInvalidatedBy(storeRef.store.getState(), ['SUCCEED']), ).toHaveLength(1) expect( - api.util.selectInvalidatedBy(storeRef.store.getState(), ['FAILED']) + api.util.selectInvalidatedBy(storeRef.store.getState(), ['FAILED']), ).toHaveLength(0) shouldApiResponseSuccess = false @@ -108,10 +108,10 @@ describe('buildSlice', () => { await delay(10) expect( - api.util.selectInvalidatedBy(storeRef.store.getState(), ['SUCCEED']) + api.util.selectInvalidatedBy(storeRef.store.getState(), ['SUCCEED']), ).toHaveLength(0) expect( - api.util.selectInvalidatedBy(storeRef.store.getState(), ['FAILED']) + api.util.selectInvalidatedBy(storeRef.store.getState(), ['FAILED']), ).toHaveLength(1) }) }) diff --git a/packages/toolkit/src/query/tests/buildThunks.test.tsx b/packages/toolkit/src/query/tests/buildThunks.test.tsx index ed40bd9342..d68a0e9800 100644 --- a/packages/toolkit/src/query/tests/buildThunks.test.tsx +++ b/packages/toolkit/src/query/tests/buildThunks.test.tsx @@ -1,9 +1,8 @@ import { configureStore } from '@reduxjs/toolkit' -import { vi } from 'vitest' import { createApi } from '@reduxjs/toolkit/query/react' import { renderHook, waitFor } from '@testing-library/react' +import { withProvider } from '../../tests/utils/helpers' import type { BaseQueryApi } from '../baseQueryTypes' -import { withProvider } from './helpers' test('handles a non-async baseQuery without error', async () => { const baseQuery = (args?: any) => ({ data: args }) @@ -96,7 +95,7 @@ describe('re-triggering behavior on arg change', () => { { wrapper: withProvider(store), initialProps: 5, - } + }, ) await waitFor(() => { @@ -128,7 +127,7 @@ describe('re-triggering behavior on arg change', () => { { wrapper: withProvider(store), initialProps: { name: 'Bob', likes: 'iceCream' }, - } + }, ) await waitFor(() => { @@ -161,7 +160,7 @@ describe('re-triggering behavior on arg change', () => { { wrapper: withProvider(store), initialProps: { person: { name } }, - } + }, ) await waitFor(() => { @@ -184,7 +183,7 @@ describe('re-triggering behavior on arg change', () => { { wrapper: withProvider(store), initialProps: { name: 'Tim', likes: 'Bananas' }, - } + }, ) await waitFor(() => { diff --git a/packages/toolkit/src/query/tests/cacheCollection.test.ts b/packages/toolkit/src/query/tests/cacheCollection.test.ts index 28e090a4b4..936ae82044 100644 --- a/packages/toolkit/src/query/tests/cacheCollection.test.ts +++ b/packages/toolkit/src/query/tests/cacheCollection.test.ts @@ -27,7 +27,7 @@ test(`query: await cleanup, defaults`, async () => { query: () => '/success', }), }), - }) + }), ) const promise = store.dispatch(api.endpoints.query.initiate('arg')) @@ -49,7 +49,7 @@ test(`query: await cleanup, keepUnusedDataFor set`, async () => { }), }), keepUnusedDataFor: 29, - }) + }), ) const promise = store.dispatch(api.endpoints.query.initiate('arg')) @@ -71,7 +71,7 @@ test(`query: handles large keepUnuseDataFor values over 32-bit ms`, async () => }), }), keepUnusedDataFor: THIRTY_TWO_BIT_MAX_TIMER_SECONDS - 10, - }) + }), ) const promise = store.dispatch(api.endpoints.query.initiate('arg')) @@ -113,7 +113,7 @@ describe(`query: await cleanup, keepUnusedDataFor set`, () => { }), }), keepUnusedDataFor: 29, - }) + }), ) test('global keepUnusedDataFor', async () => { @@ -162,13 +162,13 @@ function storeForApi< reducer: Reducer middleware: Middleware util: { resetApiState(): any } - } + }, >(api: A) { const store = configureStore({ reducer: { api: api.reducer }, middleware: (gdm) => gdm({ serializableCheck: false, immutableCheck: false }).concat( - api.middleware + api.middleware, ), enhancers: (gde) => gde({ diff --git a/packages/toolkit/src/query/tests/cacheLifecycle.test-d.ts b/packages/toolkit/src/query/tests/cacheLifecycle.test-d.ts new file mode 100644 index 0000000000..3133bbc879 --- /dev/null +++ b/packages/toolkit/src/query/tests/cacheLifecycle.test-d.ts @@ -0,0 +1,31 @@ +import type { FetchBaseQueryMeta } from '@reduxjs/toolkit/query' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' + +const api = createApi({ + baseQuery: fetchBaseQuery({ baseUrl: 'https://example.com' }), + endpoints: () => ({}), +}) + +describe('type tests', () => { + test(`mutation: await cacheDataLoaded, await cacheEntryRemoved (success)`, () => { + const extended = api.injectEndpoints({ + overrideExisting: true, + endpoints: (build) => ({ + injected: build.mutation({ + query: () => '/success', + async onCacheEntryAdded( + arg, + { dispatch, getState, cacheEntryRemoved, cacheDataLoaded }, + ) { + const firstValue = await cacheDataLoaded + + expectTypeOf(firstValue).toMatchTypeOf<{ + data: number + meta?: FetchBaseQueryMeta + }>() + }, + }), + }), + }) + }) +}) diff --git a/packages/toolkit/src/query/tests/cacheLifecycle.test.ts b/packages/toolkit/src/query/tests/cacheLifecycle.test.ts index fa505f895d..7876777857 100644 --- a/packages/toolkit/src/query/tests/cacheLifecycle.test.ts +++ b/packages/toolkit/src/query/tests/cacheLifecycle.test.ts @@ -1,14 +1,10 @@ -import { createApi } from '@reduxjs/toolkit/query' -import type { FetchBaseQueryMeta } from '@reduxjs/toolkit/query' -import { vi } from 'vitest' -import { fetchBaseQuery } from '@reduxjs/toolkit/query' import { - expectType, + DEFAULT_DELAY_MS, fakeTimerWaitFor, setupApiStore, - DEFAULT_DELAY_MS, -} from './helpers' -import { QueryActionCreatorResult } from '../core/buildInitiate' +} from '@internal/tests/utils/helpers' +import type { QueryActionCreatorResult } from '@reduxjs/toolkit/query' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' beforeAll(() => { vi.useFakeTimers() @@ -60,7 +56,7 @@ describe.each([['query'], ['mutation']] as const)( query: () => '/success', async onCacheEntryAdded( arg, - { dispatch, getState, cacheEntryRemoved } + { dispatch, getState, cacheEntryRemoved }, ) { onNewCacheEntry(arg) await cacheEntryRemoved @@ -70,7 +66,7 @@ describe.each([['query'], ['mutation']] as const)( }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) expect(onNewCacheEntry).toHaveBeenCalledWith('arg') @@ -100,13 +96,10 @@ describe.each([['query'], ['mutation']] as const)( query: () => '/success', async onCacheEntryAdded( arg, - { dispatch, getState, cacheEntryRemoved, cacheDataLoaded } + { dispatch, getState, cacheEntryRemoved, cacheDataLoaded }, ) { onNewCacheEntry(arg) const firstValue = await cacheDataLoaded - expectType<{ data: number; meta?: FetchBaseQueryMeta }>( - firstValue - ) gotFirstValue(firstValue) await cacheEntryRemoved onCleanup() @@ -115,7 +108,7 @@ describe.each([['query'], ['mutation']] as const)( }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) expect(onNewCacheEntry).toHaveBeenCalledWith('arg') @@ -158,7 +151,7 @@ describe.each([['query'], ['mutation']] as const)( query: () => '/error', // we will initiate only once and that one time will be an error -> cacheDataLoaded will never resolve async onCacheEntryAdded( arg, - { dispatch, getState, cacheEntryRemoved, cacheDataLoaded } + { dispatch, getState, cacheEntryRemoved, cacheDataLoaded }, ) { onNewCacheEntry(arg) // this will wait until cacheEntryRemoved, then reject => nothing past that line will execute @@ -173,7 +166,7 @@ describe.each([['query'], ['mutation']] as const)( }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) expect(onNewCacheEntry).toHaveBeenCalledWith('arg') @@ -198,7 +191,7 @@ describe.each([['query'], ['mutation']] as const)( query: () => '/error', // we will initiate only once and that one time will be an error -> cacheDataLoaded will never resolve async onCacheEntryAdded( arg, - { dispatch, getState, cacheEntryRemoved, cacheDataLoaded } + { dispatch, getState, cacheEntryRemoved, cacheDataLoaded }, ) { onNewCacheEntry(arg) @@ -216,7 +209,7 @@ describe.each([['query'], ['mutation']] as const)( }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) expect(onNewCacheEntry).toHaveBeenCalledWith('arg') @@ -249,7 +242,7 @@ describe.each([['query'], ['mutation']] as const)( query: () => '/error', // we will initiate only once and that one time will be an error -> cacheDataLoaded will never resolve async onCacheEntryAdded( arg, - { dispatch, getState, cacheEntryRemoved, cacheDataLoaded } + { dispatch, getState, cacheEntryRemoved, cacheDataLoaded }, ) { onNewCacheEntry(arg) @@ -268,7 +261,7 @@ describe.each([['query'], ['mutation']] as const)( }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) expect(onNewCacheEntry).toHaveBeenCalledWith('arg') @@ -300,7 +293,7 @@ describe.each([['query'], ['mutation']] as const)( query: () => '/error', // we will initiate only once and that one time will be an error -> cacheDataLoaded will never resolve async onCacheEntryAdded( arg, - { dispatch, getState, cacheEntryRemoved, cacheDataLoaded } + { dispatch, getState, cacheEntryRemoved, cacheDataLoaded }, ) { onNewCacheEntry(arg) @@ -319,7 +312,7 @@ describe.each([['query'], ['mutation']] as const)( }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) expect(onNewCacheEntry).toHaveBeenCalledWith('arg') @@ -342,7 +335,7 @@ describe.each([['query'], ['mutation']] as const)( message: 'Promise never resolved before cacheEntryRemoved.', }) }) - } + }, ) test(`query: getCacheEntry`, async () => { @@ -360,7 +353,7 @@ test(`query: getCacheEntry`, async () => { getCacheEntry, cacheEntryRemoved, cacheDataLoaded, - } + }, ) { snapshot(getCacheEntry()) gotFirstValue(await cacheDataLoaded) @@ -372,7 +365,7 @@ test(`query: getCacheEntry`, async () => { }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) await promise promise.unsubscribe() @@ -434,7 +427,7 @@ test(`mutation: getCacheEntry`, async () => { getCacheEntry, cacheEntryRemoved, cacheDataLoaded, - } + }, ) { snapshot(getCacheEntry()) gotFirstValue(await cacheDataLoaded) @@ -446,7 +439,7 @@ test(`mutation: getCacheEntry`, async () => { }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) await fakeTimerWaitFor(() => { expect(gotFirstValue).toHaveBeenCalled() @@ -504,7 +497,7 @@ test('updateCachedData', async () => { updateCachedData, cacheEntryRemoved, cacheDataLoaded, - } + }, ) { expect(getCacheEntry().data).toEqual(undefined) // calling `updateCachedData` when there is no data yet should not do anything @@ -542,7 +535,7 @@ test('updateCachedData', async () => { }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) await promise promise.unsubscribe() @@ -577,7 +570,7 @@ test('dispatching further actions does not trigger another lifecycle', async () expect(onNewCacheEntry).toHaveBeenCalledTimes(1) await storeRef.store.dispatch( - extended.endpoints.injected.initiate(undefined, { forceRefetch: true }) + extended.endpoints.injected.initiate(undefined, { forceRefetch: true }), ) expect(onNewCacheEntry).toHaveBeenCalledTimes(1) }) @@ -595,7 +588,7 @@ test('dispatching a query initializer with `subscribe: false` does also start a }), }) await storeRef.store.dispatch( - extended.endpoints.injected.initiate(undefined, { subscribe: false }) + extended.endpoints.injected.initiate(undefined, { subscribe: false }), ) expect(onNewCacheEntry).toHaveBeenCalledTimes(1) @@ -617,7 +610,7 @@ test('dispatching a mutation initializer with `track: false` does not start a li }), }) await storeRef.store.dispatch( - extended.endpoints.injected.initiate(undefined, { track: false }) + extended.endpoints.injected.initiate(undefined, { track: false }), ) expect(onNewCacheEntry).toHaveBeenCalledTimes(0) diff --git a/packages/toolkit/src/query/tests/cleanup.test.tsx b/packages/toolkit/src/query/tests/cleanup.test.tsx index cb1ff750fa..dc3d8fcbe1 100644 --- a/packages/toolkit/src/query/tests/cleanup.test.tsx +++ b/packages/toolkit/src/query/tests/cleanup.test.tsx @@ -1,12 +1,11 @@ // tests for "cleanup-after-unsubscribe" behaviour -import { vi } from 'vitest' import React from 'react' import { createListenerMiddleware } from '@reduxjs/toolkit' import { createApi, QueryStatus } from '@reduxjs/toolkit/query/react' -import { render, waitFor, act, screen } from '@testing-library/react' -import { setupApiStore } from './helpers' -import { SubscriptionSelectors } from '../core/buildMiddleware/types' +import { act, render, screen, waitFor } from '@testing-library/react' +import { setupApiStore } from '../../tests/utils/helpers' +import type { SubscriptionSelectors } from '../core/buildMiddleware/types' const tick = () => new Promise((res) => setImmediate(res)) @@ -21,8 +20,8 @@ const api = createApi({ }) const storeRef = setupApiStore(api) -let getSubStateA = () => storeRef.store.getState().api.queries['a(undefined)'] -let getSubStateB = () => storeRef.store.getState().api.queries['b(undefined)'] +const getSubStateA = () => storeRef.store.getState().api.queries['a(undefined)'] +const getSubStateB = () => storeRef.store.getState().api.queries['b(undefined)'] function UsingA() { const { data } = api.endpoints.a.useQuery() @@ -52,10 +51,10 @@ test('data stays in store when component stays rendered', async () => { render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(getSubStateA()?.status).toBe(QueryStatus.fulfilled) + expect(getSubStateA()?.status).toBe(QueryStatus.fulfilled), ) - vi.advanceTimersByTime(120000) + vi.advanceTimersByTime(120_000) expect(getSubStateA()?.status).toBe(QueryStatus.fulfilled) }) @@ -65,12 +64,12 @@ test('data is removed from store after 60 seconds', async () => { const { unmount } = render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(getSubStateA()?.status).toBe(QueryStatus.fulfilled) + expect(getSubStateA()?.status).toBe(QueryStatus.fulfilled), ) unmount() - vi.advanceTimersByTime(59000) + vi.advanceTimersByTime(59_000) expect(getSubStateA()?.status).toBe(QueryStatus.fulfilled) @@ -88,7 +87,7 @@ test('data stays in store when component stays rendered while data for another c , - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) await waitFor(() => { expect(getSubStateA()?.status).toBe(QueryStatus.fulfilled) @@ -98,16 +97,12 @@ test('data stays in store when component stays rendered while data for another c const statusA = getSubStateA() await act(async () => { - rerender( - <> - - - ) + rerender() vi.advanceTimersByTime(10) }) - vi.advanceTimersByTime(120000) + vi.advanceTimersByTime(120_000) expect(getSubStateA()).toEqual(statusA) expect(getSubStateB()).toBeUndefined() @@ -122,7 +117,7 @@ test('data stays in store when one component requiring the data stays in the sto , - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) await waitFor(() => { expect(getSubStateA()?.status).toBe(QueryStatus.fulfilled) @@ -133,11 +128,7 @@ test('data stays in store when one component requiring the data stays in the sto const statusB = getSubStateB() await act(async () => { - rerender( - <> - - - ) + rerender() vi.advanceTimersByTime(10) vi.runAllTimers() }) @@ -160,7 +151,7 @@ test('Minimizes the number of subscription dispatches when multiple components a withoutTestLifecycles: true, }) - let actionTypes: unknown[] = [] + const actionTypes: unknown[] = [] listenerMiddleware.startListening({ predicate: () => true, @@ -177,7 +168,7 @@ test('Minimizes the number of subscription dispatches when multiple components a }) const { getSubscriptionCount } = storeRef.store.dispatch( - api.internalActions.internal_getRTKQSubscriptions() + api.internalActions.internal_getRTKQSubscriptions(), ) as unknown as SubscriptionSelectors const NUM_LIST_ITEMS = 1000 @@ -210,4 +201,4 @@ test('Minimizes the number of subscription dispatches when multiple components a 'api/executeQuery/pending', 'api/executeQuery/fulfilled', ]) -}, 25000) +}, 25_000) diff --git a/packages/toolkit/src/query/tests/createApi.test-d.ts b/packages/toolkit/src/query/tests/createApi.test-d.ts new file mode 100644 index 0000000000..b33ced1f6e --- /dev/null +++ b/packages/toolkit/src/query/tests/createApi.test-d.ts @@ -0,0 +1,377 @@ +import { setupApiStore } from '@internal/tests/utils/helpers' +import type { SerializedError } from '@reduxjs/toolkit' +import { configureStore } from '@reduxjs/toolkit' +import type { + DefinitionsFromApi, + FetchBaseQueryError, + MutationDefinition, + OverrideResultType, + QueryDefinition, + TagDescription, + TagTypesFromApi, +} from '@reduxjs/toolkit/query' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' + +describe('type tests', () => { + test('sensible defaults', () => { + const api = createApi({ + baseQuery: fetchBaseQuery(), + endpoints: (build) => ({ + getUser: build.query({ + query(id) { + return { url: `user/${id}` } + }, + }), + updateUser: build.mutation({ + query: () => '', + }), + }), + }) + + configureStore({ + reducer: { + [api.reducerPath]: api.reducer, + }, + middleware: (gDM) => gDM().concat(api.middleware), + }) + + expectTypeOf(api.reducerPath).toEqualTypeOf<'api'>() + + expectTypeOf(api.util.invalidateTags) + .parameter(0) + .toEqualTypeOf[]>() + }) + + describe('endpoint definition typings', () => { + const api = createApi({ + baseQuery: (from: 'From'): { data: 'To' } | Promise<{ data: 'To' }> => ({ + data: 'To', + }), + endpoints: () => ({}), + tagTypes: ['typeA', 'typeB'], + }) + + test('query: query & transformResponse types', () => { + api.injectEndpoints({ + endpoints: (build) => ({ + query: build.query<'RetVal', 'Arg'>({ + query: (x: 'Arg') => 'From' as const, + transformResponse(r: 'To') { + return 'RetVal' as const + }, + }), + query1: build.query<'RetVal', 'Arg'>({ + // @ts-expect-error + query: (x: 'Error') => 'From' as const, + transformResponse(r: 'To') { + return 'RetVal' as const + }, + }), + query2: build.query<'RetVal', 'Arg'>({ + // @ts-expect-error + query: (x: 'Arg') => 'Error' as const, + transformResponse(r: 'To') { + return 'RetVal' as const + }, + }), + query3: build.query<'RetVal', 'Arg'>({ + query: (x: 'Arg') => 'From' as const, + // @ts-expect-error + transformResponse(r: 'Error') { + return 'RetVal' as const + }, + }), + query4: build.query<'RetVal', 'Arg'>({ + query: (x: 'Arg') => 'From' as const, + // @ts-expect-error + transformResponse(r: 'To') { + return 'Error' as const + }, + }), + queryInference1: build.query<'RetVal', 'Arg'>({ + query: (x) => { + expectTypeOf(x).toEqualTypeOf<'Arg'>() + + return 'From' + }, + transformResponse(r) { + expectTypeOf(r).toEqualTypeOf<'To'>() + + return 'RetVal' + }, + }), + queryInference2: (() => { + const query = build.query({ + query: (x: 'Arg') => 'From' as const, + transformResponse(r: 'To') { + return 'RetVal' as const + }, + }) + + expectTypeOf(query).toMatchTypeOf< + QueryDefinition<'Arg', any, any, 'RetVal'> + >() + + return query + })(), + }), + }) + }) + + test('mutation: query & transformResponse types', () => { + api.injectEndpoints({ + endpoints: (build) => ({ + query: build.mutation<'RetVal', 'Arg'>({ + query: (x: 'Arg') => 'From' as const, + transformResponse(r: 'To') { + return 'RetVal' as const + }, + }), + query1: build.mutation<'RetVal', 'Arg'>({ + // @ts-expect-error + query: (x: 'Error') => 'From' as const, + transformResponse(r: 'To') { + return 'RetVal' as const + }, + }), + query2: build.mutation<'RetVal', 'Arg'>({ + // @ts-expect-error + query: (x: 'Arg') => 'Error' as const, + transformResponse(r: 'To') { + return 'RetVal' as const + }, + }), + query3: build.mutation<'RetVal', 'Arg'>({ + query: (x: 'Arg') => 'From' as const, + // @ts-expect-error + transformResponse(r: 'Error') { + return 'RetVal' as const + }, + }), + query4: build.mutation<'RetVal', 'Arg'>({ + query: (x: 'Arg') => 'From' as const, + // @ts-expect-error + transformResponse(r: 'To') { + return 'Error' as const + }, + }), + mutationInference1: build.mutation<'RetVal', 'Arg'>({ + query: (x) => { + expectTypeOf(x).toEqualTypeOf<'Arg'>() + + return 'From' + }, + transformResponse(r) { + expectTypeOf(r).toEqualTypeOf<'To'>() + + return 'RetVal' + }, + }), + mutationInference2: (() => { + const query = build.mutation({ + query: (x: 'Arg') => 'From' as const, + transformResponse(r: 'To') { + return 'RetVal' as const + }, + }) + + expectTypeOf(query).toMatchTypeOf< + MutationDefinition<'Arg', any, any, 'RetVal'> + >() + + return query + })(), + }), + }) + }) + + describe('enhancing endpoint definitions', () => { + const baseQuery = (x: string) => ({ data: 'success' }) + + function getNewApi() { + return createApi({ + baseQuery, + tagTypes: ['old'], + endpoints: (build) => ({ + query1: build.query<'out1', 'in1'>({ query: (id) => `${id}` }), + query2: build.query<'out2', 'in2'>({ query: (id) => `${id}` }), + mutation1: build.mutation<'out1', 'in1'>({ + query: (id) => `${id}`, + }), + mutation2: build.mutation<'out2', 'in2'>({ + query: (id) => `${id}`, + }), + }), + }) + } + + const api1 = getNewApi() + + test('warn on wrong tagType', () => { + const storeRef = setupApiStore(api1, undefined, { + withoutTestLifecycles: true, + }) + + api1.enhanceEndpoints({ + endpoints: { + query1: { + // @ts-expect-error + providesTags: ['new'], + }, + query2: { + // @ts-expect-error + providesTags: ['missing'], + }, + }, + }) + + const enhanced = api1.enhanceEndpoints({ + addTagTypes: ['new'], + endpoints: { + query1: { + providesTags: ['new'], + }, + query2: { + // @ts-expect-error + providesTags: ['missing'], + }, + }, + }) + + storeRef.store.dispatch(api1.endpoints.query1.initiate('in1')) + + storeRef.store.dispatch(api1.endpoints.query2.initiate('in2')) + + enhanced.enhanceEndpoints({ + endpoints: { + query1: { + // returned `enhanced` api contains "new" entityType + providesTags: ['new'], + }, + query2: { + // @ts-expect-error + providesTags: ['missing'], + }, + }, + }) + }) + + test('modify', () => { + const storeRef = setupApiStore(api1, undefined, { + withoutTestLifecycles: true, + }) + + api1.enhanceEndpoints({ + endpoints: { + query1: { + query: (x) => { + expectTypeOf(x).toEqualTypeOf<'in1'>() + + return 'modified1' + }, + }, + query2(definition) { + definition.query = (x) => { + expectTypeOf(x).toEqualTypeOf<'in2'>() + + return 'modified2' + } + }, + mutation1: { + query: (x) => { + expectTypeOf(x).toEqualTypeOf<'in1'>() + + return 'modified1' + }, + }, + mutation2(definition) { + definition.query = (x) => { + expectTypeOf(x).toEqualTypeOf<'in2'>() + + return 'modified2' + } + }, + // @ts-expect-error + nonExisting: {}, + }, + }) + + storeRef.store.dispatch(api1.endpoints.query1.initiate('in1')) + storeRef.store.dispatch(api1.endpoints.query2.initiate('in2')) + storeRef.store.dispatch(api1.endpoints.mutation1.initiate('in1')) + storeRef.store.dispatch(api1.endpoints.mutation2.initiate('in2')) + }) + + test('updated transform response types', async () => { + const baseApi = createApi({ + baseQuery: fetchBaseQuery({ baseUrl: 'https://example.com' }), + tagTypes: ['old'], + endpoints: (build) => ({ + query1: build.query<'out1', void>({ query: () => 'success' }), + mutation1: build.mutation<'out1', void>({ query: () => 'success' }), + }), + }) + + type Transformed = { value: string } + + type Definitions = DefinitionsFromApi + + type TagTypes = TagTypesFromApi + + type Q1Definition = OverrideResultType< + Definitions['query1'], + Transformed + > + + type M1Definition = OverrideResultType< + Definitions['mutation1'], + Transformed + > + + type UpdatedDefinitions = Omit & { + query1: Q1Definition + mutation1: M1Definition + } + + const enhancedApi = baseApi.enhanceEndpoints< + TagTypes, + UpdatedDefinitions + >({ + endpoints: { + query1: { + transformResponse: (a, b, c) => ({ + value: 'transformed', + }), + }, + mutation1: { + transformResponse: (a, b, c) => ({ + value: 'transformed', + }), + }, + }, + }) + + const storeRef = setupApiStore(enhancedApi, undefined, { + withoutTestLifecycles: true, + }) + + const queryResponse = await storeRef.store.dispatch( + enhancedApi.endpoints.query1.initiate(), + ) + + expectTypeOf(queryResponse.data).toMatchTypeOf< + Transformed | undefined + >() + + const mutationResponse = await storeRef.store.dispatch( + enhancedApi.endpoints.mutation1.initiate(), + ) + + expectTypeOf(mutationResponse).toMatchTypeOf< + | { data: Transformed } + | { error: FetchBaseQueryError | SerializedError } + >() + }) + }) + }) +}) diff --git a/packages/toolkit/src/query/tests/createApi.test.ts b/packages/toolkit/src/query/tests/createApi.test.ts index cdeb22c952..e1c3fad253 100644 --- a/packages/toolkit/src/query/tests/createApi.test.ts +++ b/packages/toolkit/src/query/tests/createApi.test.ts @@ -1,41 +1,29 @@ -import type { SerializedError } from '@reduxjs/toolkit' -import { configureStore, createAction, createReducer } from '@reduxjs/toolkit' -import type { SpyInstance } from 'vitest' -import { vi } from 'vitest' -import type { - Api, - MutationDefinition, - QueryDefinition, -} from '@reduxjs/toolkit/query' -import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' -import type { - FetchBaseQueryError, - FetchBaseQueryMeta, -} from '@reduxjs/toolkit/dist/query/fetchBaseQuery' - +import { server } from '@internal/query/tests/mocks/server' import { - ANY, - expectType, - expectExactType, - setupApiStore, - waitMs, getSerializedHeaders, -} from './helpers' -import { server } from './mocks/server' -import { rest } from 'msw' -import type { SerializeQueryArgs } from '../defaultSerializeQueryArgs' -import { string } from 'yargs' + setupApiStore, +} from '@internal/tests/utils/helpers' +import { configureStore, createAction, createReducer } from '@reduxjs/toolkit' import type { DefinitionsFromApi, + FetchBaseQueryMeta, OverrideResultType, + SerializeQueryArgs, TagTypesFromApi, -} from '@reduxjs/toolkit/dist/query/endpointDefinitions' +} from '@reduxjs/toolkit/query' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' +import { HttpResponse, delay, http } from 'msw' +import nodeFetch from 'node-fetch' +import type { MockInstance } from 'vitest' -const originalEnv = process.env.NODE_ENV -beforeAll(() => void ((process.env as any).NODE_ENV = 'development')) -afterAll(() => void ((process.env as any).NODE_ENV = originalEnv)) +beforeAll(() => { + vi.stubEnv('NODE_ENV', 'development') + + return vi.unstubAllEnvs +}) + +let spy: MockInstance -let spy: SpyInstance beforeAll(() => { spy = vi.spyOn(console, 'error').mockImplementation(() => {}) }) @@ -73,14 +61,6 @@ test('sensible defaults', () => { }) expect(api.reducerPath).toBe('api') - expectType<'api'>(api.reducerPath) - type TagTypes = typeof api extends Api - ? E - : 'no match' - expectType(ANY as never) - // @ts-expect-error - expectType(0) - expect(api.endpoints.getUser.name).toBe('getUser') expect(api.endpoints.updateUser.name).toBe('updateUser') }) @@ -185,14 +165,14 @@ describe('wrong tagTypes log errors', () => { store.dispatch(api.endpoints[endpoint].initiate()) let result: { status: string } do { - await waitMs(5) + await delay(5) // @ts-ignore result = api.endpoints[endpoint].select()(store.getState()) } while (result.status === 'pending') if (shouldError) { expect(spy).toHaveBeenCalledWith( - "Tag type 'Users' was used, but not specified in `tagTypes`!" + "Tag type 'Users' was used, but not specified in `tagTypes`!", ) } else { expect(spy).not.toHaveBeenCalled() @@ -247,11 +227,9 @@ describe('endpoint definition typings', () => { }), queryInference1: build.query<'RetVal', 'Arg'>({ query: (x) => { - expectType<'Arg'>(x) return 'From' }, transformResponse(r) { - expectType<'To'>(r) return 'RetVal' }, }), @@ -262,7 +240,6 @@ describe('endpoint definition typings', () => { return 'RetVal' as const }, }) - expectType>(query) return query })(), }), @@ -307,11 +284,9 @@ describe('endpoint definition typings', () => { }), mutationInference1: build.mutation<'RetVal', 'Arg'>({ query: (x) => { - expectType<'Arg'>(x) return 'From' }, transformResponse(r) { - expectType<'To'>(r) return 'RetVal' }, }), @@ -322,7 +297,6 @@ describe('endpoint definition typings', () => { return 'RetVal' as const }, }) - expectType>(query) return query })(), }), @@ -460,13 +434,13 @@ describe('endpoint definition typings', () => { }) storeRef.store.dispatch(api.endpoints.query1.initiate('in1')) - await waitMs(1) + await delay(1) expect(spy).not.toHaveBeenCalled() storeRef.store.dispatch(api.endpoints.query2.initiate('in2')) - await waitMs(1) + await delay(1) expect(spy).toHaveBeenCalledWith( - "Tag type 'missing' was used, but not specified in `tagTypes`!" + "Tag type 'missing' was used, but not specified in `tagTypes`!", ) // only type-test this part @@ -494,25 +468,21 @@ describe('endpoint definition typings', () => { endpoints: { query1: { query: (x) => { - expectExactType('in1' as const)(x) return 'modified1' }, }, query2(definition) { definition.query = (x) => { - expectExactType('in2' as const)(x) return 'modified2' } }, mutation1: { query: (x) => { - expectExactType('in1' as const)(x) return 'modified1' }, }, mutation2(definition) { definition.query = (x) => { - expectExactType('in2' as const)(x) return 'modified2' } }, @@ -580,17 +550,13 @@ describe('endpoint definition typings', () => { }) const queryResponse = await storeRef.store.dispatch( - enhancedApi.endpoints.query1.initiate() + enhancedApi.endpoints.query1.initiate(), ) expect(queryResponse.data).toEqual({ value: 'transformed' }) - expectType(queryResponse.data) const mutationResponse = await storeRef.store.dispatch( - enhancedApi.endpoints.mutation1.initiate() + enhancedApi.endpoints.mutation1.initiate(), ) - expectType< - { data: Transformed } | { error: FetchBaseQueryError | SerializedError } - >(mutationResponse) expect('data' in mutationResponse && mutationResponse.data).toEqual({ value: 'transformed', }) @@ -635,7 +601,7 @@ describe('additional transformResponse behaviors', () => { }), transformResponse: ( response: { body: { nested: EchoResponseData } }, - meta + meta, ) => { return { ...response.body.nested, @@ -651,11 +617,12 @@ describe('additional transformResponse behaviors', () => { query: build.query({ query: () => '/success', transformResponse: async (response: SuccessResponse) => { - const res = await fetch('https://example.com/echo', { + const res: any = await nodeFetch('https://example.com/echo', { method: 'POST', body: JSON.stringify({ banana: 'bread' }), }).then((res) => res.json()) - const additionalData = JSON.parse(res.body) as EchoResponseData + + const additionalData = res.body as EchoResponseData return { ...response, ...additionalData } }, }), @@ -686,7 +653,7 @@ describe('additional transformResponse behaviors', () => { test('transformResponse transforms a response from a mutation', async () => { const result = await storeRef.store.dispatch( - api.endpoints.mutation.initiate({}) + api.endpoints.mutation.initiate({}), ) expect('data' in result && result.data).toEqual({ banana: 'bread' }) @@ -694,7 +661,7 @@ describe('additional transformResponse behaviors', () => { test('transformResponse transforms a response from a mutation with an error', async () => { const result = await storeRef.store.dispatch( - api.endpoints.mutationWithError.initiate({}) + api.endpoints.mutationWithError.initiate({}), ) expect('error' in result && result.error).toEqual('error') @@ -702,7 +669,7 @@ describe('additional transformResponse behaviors', () => { test('transformResponse can inject baseQuery meta into the end result from a mutation', async () => { const result = await storeRef.store.dispatch( - api.endpoints.mutationWithMeta.initiate({}) + api.endpoints.mutationWithMeta.initiate({}), ) expect('data' in result && result.data).toEqual({ @@ -716,7 +683,6 @@ describe('additional transformResponse behaviors', () => { response: { headers: { 'content-type': 'application/json', - 'x-powered-by': 'msw', }, }, }, @@ -725,7 +691,7 @@ describe('additional transformResponse behaviors', () => { test('transformResponse can inject baseQuery meta into the end result from a query', async () => { const result = await storeRef.store.dispatch( - api.endpoints.queryWithMeta.initiate() + api.endpoints.queryWithMeta.initiate(), ) expect(result.data).toEqual({ @@ -737,7 +703,6 @@ describe('additional transformResponse behaviors', () => { response: { headers: { 'content-type': 'application/json', - 'x-powered-by': 'msw', }, }, }, @@ -795,45 +760,49 @@ describe('query endpoint lifecycles - onStart, onSuccess, onError', () => { test('query lifecycle events fire properly', async () => { // We intentionally fail the first request so we can test all lifecycles server.use( - rest.get('https://example.com/success', (_, res, ctx) => - res.once(ctx.status(500), ctx.json({ value: 'failed' })) - ) + http.get( + 'https://example.com/success', + () => HttpResponse.json({ value: 'failed' }, { status: 500 }), + { once: true }, + ), ) expect(storeRef.store.getState().testReducer.count).toBe(null) const failAttempt = storeRef.store.dispatch(api.endpoints.query.initiate()) expect(storeRef.store.getState().testReducer.count).toBe(0) await failAttempt - await waitMs(10) + await delay(10) expect(storeRef.store.getState().testReducer.count).toBe(-1) const successAttempt = storeRef.store.dispatch( - api.endpoints.query.initiate() + api.endpoints.query.initiate(), ) expect(storeRef.store.getState().testReducer.count).toBe(0) await successAttempt - await waitMs(10) + await delay(10) expect(storeRef.store.getState().testReducer.count).toBe(1) }) test('mutation lifecycle events fire properly', async () => { // We intentionally fail the first request so we can test all lifecycles server.use( - rest.post('https://example.com/success', (_, res, ctx) => - res.once(ctx.status(500), ctx.json({ value: 'failed' })) - ) + http.post( + 'https://example.com/success', + () => HttpResponse.json({ value: 'failed' }, { status: 500 }), + { once: true }, + ), ) expect(storeRef.store.getState().testReducer.count).toBe(null) const failAttempt = storeRef.store.dispatch( - api.endpoints.mutation.initiate() + api.endpoints.mutation.initiate(), ) expect(storeRef.store.getState().testReducer.count).toBe(0) await failAttempt expect(storeRef.store.getState().testReducer.count).toBe(-1) const successAttempt = storeRef.store.dispatch( - api.endpoints.mutation.initiate() + api.endpoints.mutation.initiate(), ) expect(storeRef.store.getState().testReducer.count).toBe(0) await successAttempt @@ -905,7 +874,7 @@ describe('structuralSharing flag behaviors', () => { const firstRef = api.endpoints.enabled.select()(storeRef.store.getState()) await storeRef.store.dispatch( - api.endpoints.enabled.initiate(undefined, { forceRefetch: true }) + api.endpoints.enabled.initiate(undefined, { forceRefetch: true }), ) const secondRef = api.endpoints.enabled.select()(storeRef.store.getState()) @@ -919,7 +888,7 @@ describe('structuralSharing flag behaviors', () => { const firstRef = api.endpoints.disabled.select()(storeRef.store.getState()) await storeRef.store.dispatch( - api.endpoints.disabled.initiate(undefined, { forceRefetch: true }) + api.endpoints.disabled.initiate(undefined, { forceRefetch: true }), ) const secondRef = api.endpoints.disabled.select()(storeRef.store.getState()) @@ -944,7 +913,7 @@ describe('custom serializeQueryArgs per endpoint', () => { } const dummyClient: MyApiClient = { - async fetchPost(id) { + async fetchPost() { return { value: 'success' } }, } @@ -1024,23 +993,23 @@ describe('custom serializeQueryArgs per endpoint', () => { it('Works via createApi', async () => { await storeRef.store.dispatch( - api.endpoints.queryWithNoSerializer.initiate(99) + api.endpoints.queryWithNoSerializer.initiate(99), ) expect(serializer1).toHaveBeenCalledTimes(0) await storeRef.store.dispatch( - api.endpoints.queryWithCustomSerializer.initiate(42) + api.endpoints.queryWithCustomSerializer.initiate(42), ) expect(serializer1).toHaveBeenCalled() expect( - storeRef.store.getState().api.queries['base-queryWithNoSerializer-99'] + storeRef.store.getState().api.queries['base-queryWithNoSerializer-99'], ).toBeTruthy() expect( - storeRef.store.getState().api.queries['queryWithCustomSerializer-42'] + storeRef.store.getState().api.queries['queryWithCustomSerializer-42'], ).toBeTruthy() }) @@ -1059,14 +1028,14 @@ describe('custom serializeQueryArgs per endpoint', () => { expect(serializer2).toHaveBeenCalledTimes(0) await storeRef.store.dispatch( - injectedApi.endpoints.injectedQueryWithCustomSerializer.initiate(5) + injectedApi.endpoints.injectedQueryWithCustomSerializer.initiate(5), ) expect(serializer2).toHaveBeenCalled() expect( storeRef.store.getState().api.queries[ 'injectedQueryWithCustomSerializer-5' - ] + ], ).toBeTruthy() }) @@ -1075,13 +1044,13 @@ describe('custom serializeQueryArgs per endpoint', () => { api.endpoints.queryWithCustomObjectSerializer.initiate({ id: 42, client: dummyClient, - }) + }), ) expect( storeRef.store.getState().api.queries[ 'queryWithCustomObjectSerializer({"id":42})' - ] + ], ).toBeTruthy() }) @@ -1090,13 +1059,13 @@ describe('custom serializeQueryArgs per endpoint', () => { api.endpoints.queryWithCustomNumberSerializer.initiate({ id: 42, client: dummyClient, - }) + }), ) expect( storeRef.store.getState().api.queries[ 'queryWithCustomNumberSerializer(42)' - ] + ], ).toBeTruthy() }) @@ -1105,13 +1074,14 @@ describe('custom serializeQueryArgs per endpoint', () => { const PAGE_SIZE = 3 server.use( - rest.get('https://example.com/listItems', (req, res, ctx) => { - const pageString = req.url.searchParams.get('page') + http.get('https://example.com/listItems', ({ request }) => { + const url = new URL(request.url) + const pageString = url.searchParams.get('page') const pageNum = parseInt(pageString || '0') const results = paginate(allItems, PAGE_SIZE, pageNum) - return res(ctx.json(results)) - }) + return HttpResponse.json(results) + }), ) // Page number shouldn't matter here, because the cache key ignores that. @@ -1133,13 +1103,14 @@ describe('custom serializeQueryArgs per endpoint', () => { const PAGE_SIZE = 3 server.use( - rest.get('https://example.com/listItems2', (req, res, ctx) => { - const pageString = req.url.searchParams.get('page') + http.get('https://example.com/listItems2', ({ request }) => { + const url = new URL(request.url) + const pageString = url.searchParams.get('page') const pageNum = parseInt(pageString || '0') const results = paginate(allItems, PAGE_SIZE, pageNum) - return res(ctx.json(results)) - }) + return HttpResponse.json(results) + }), ) const selectListItems = api.endpoints.listItems2.select(0) diff --git a/packages/toolkit/src/query/tests/defaultSerializeQueryArgs.test.ts b/packages/toolkit/src/query/tests/defaultSerializeQueryArgs.test.ts index 45bd57cbb8..fa9ad3b72b 100644 --- a/packages/toolkit/src/query/tests/defaultSerializeQueryArgs.test.ts +++ b/packages/toolkit/src/query/tests/defaultSerializeQueryArgs.test.ts @@ -9,7 +9,7 @@ test('string arg', () => { endpointDefinition, endpointName, queryArgs: 'arg', - }) + }), ).toMatchInlineSnapshot(`"test("arg")"`) }) @@ -19,7 +19,7 @@ test('number arg', () => { endpointDefinition, endpointName, queryArgs: 5, - }) + }), ).toMatchInlineSnapshot(`"test(5)"`) }) @@ -29,7 +29,7 @@ test('simple object arg is sorted', () => { endpointDefinition, endpointName, queryArgs: { name: 'arg', age: 5 }, - }) + }), ).toMatchInlineSnapshot(`"test({"age":5,"name":"arg"})"`) }) @@ -39,9 +39,9 @@ test('nested object arg is sorted recursively', () => { endpointDefinition, endpointName, queryArgs: { name: { last: 'Split', first: 'Banana' }, age: 5 }, - }) + }), ).toMatchInlineSnapshot( - `"test({"age":5,"name":{"first":"Banana","last":"Split"}})"` + `"test({"age":5,"name":{"first":"Banana","last":"Split"}})"`, ) }) @@ -70,7 +70,7 @@ test('Fully serializes a deeply nested object', () => { queryArgs: nestedObj, }) expect(res).toMatchInlineSnapshot( - `"test({"a":{"a1":{"a11":{"a111":1}}},"b":{"b1":{"b11":2},"b2":{"b21":3}}})"` + `"test({"a":{"a1":{"a11":{"a111":1}}},"b":{"b1":{"b11":2},"b2":{"b21":3}}})"`, ) }) diff --git a/packages/toolkit/src/query/tests/devWarnings.test.tsx b/packages/toolkit/src/query/tests/devWarnings.test.tsx index d87968f9f1..f0b61d3518 100644 --- a/packages/toolkit/src/query/tests/devWarnings.test.tsx +++ b/packages/toolkit/src/query/tests/devWarnings.test.tsx @@ -110,7 +110,7 @@ describe('missing middleware', () => { } expect(doDispatch1).toThrowError(reMatchMissingMiddlewareError) expect(doDispatch2).toThrowError( - /Warning: Middleware for RTK-Query API at reducerPath "api2" has not been added to the store/ + /Warning: Middleware for RTK-Query API at reducerPath "api2" has not been added to the store/, ) }) }) @@ -141,7 +141,7 @@ describe('missing reducer', () => { expect(getLog().log).toBe( shouldWarn ? 'Error: No data found at `state.api`. Did you forget to add the reducer to the store?' - : '' + : '', ) }) }) @@ -166,7 +166,7 @@ describe('missing reducer', () => { // @ts-expect-error api1.endpoints.q1.select(undefined)(store.getState()) expect(getLog().log).toBe( - 'Error: No data found at `state.api`. Did you forget to add the reducer to the store?' + 'Error: No data found at `state.api`. Did you forget to add the reducer to the store?', ) }) @@ -181,7 +181,7 @@ describe('missing reducer', () => { // @ts-expect-error api2.endpoints.q1.select(undefined)(store.getState()) expect(getLog().log).toBe( - 'Error: No data found at `state.api`. Did you forget to add the reducer to the store?\nError: No data found at `state.api2`. Did you forget to add the reducer to the store?' + 'Error: No data found at `state.api`. Did you forget to add the reducer to the store?\nError: No data found at `state.api2`. Did you forget to add the reducer to the store?', ) }) }) @@ -197,7 +197,7 @@ test('warns for reducer and also throws error if everything is missing', async ( } expect(doDispatch).toThrowError(reMatchMissingMiddlewareError) expect(getLog().log).toBe( - 'Error: No data found at `state.api`. Did you forget to add the reducer to the store?' + 'Error: No data found at `state.api`. Did you forget to add the reducer to the store?', ) }) @@ -218,7 +218,7 @@ describe('warns on multiple apis using the same `reducerPath`', () => { expect(getLog().log).toBe( `There is a mismatch between slice and middleware for the reducerPath "api". You can only have one api per reducer path, this will lead to crashes in various situations! -If you have multiple apis, you *have* to specify the reducerPath option when using createApi!` +If you have multiple apis, you *have* to specify the reducerPath option when using createApi!`, ) }) @@ -240,7 +240,7 @@ You can only have one api per reducer path, this will lead to crashes in various If you have multiple apis, you *have* to specify the reducerPath option when using createApi! There is a mismatch between slice and middleware for the reducerPath "api". You can only have one api per reducer path, this will lead to crashes in various situations! -If you have multiple apis, you *have* to specify the reducerPath option when using createApi!` +If you have multiple apis, you *have* to specify the reducerPath option when using createApi!`, ) }) @@ -259,7 +259,7 @@ If you have multiple apis, you *have* to specify the reducerPath option when usi expect(getLog().log).toBe( `There is a mismatch between slice and middleware for the reducerPath "api". You can only have one api per reducer path, this will lead to crashes in various situations! -If you have multiple apis, you *have* to specify the reducerPath option when using createApi!` +If you have multiple apis, you *have* to specify the reducerPath option when using createApi!`, ) }) @@ -270,7 +270,7 @@ If you have multiple apis, you *have* to specify the reducerPath option when usi * It would be great to support this case as well, but for now: * "It is what it is." */ - test.skip('common: two apis, only second middleware', async () => { + test.todo('common: two apis, only second middleware', async () => { const store = configureStore({ reducer: { // @ts-ignore @@ -285,7 +285,7 @@ If you have multiple apis, you *have* to specify the reducerPath option when usi expect(getLog().log).toBe( `There is a mismatch between slice and middleware for the reducerPath "api". You can only have one api per reducer path, this will lead to crashes in various situations! -If you have multiple apis, you *have* to specify the reducerPath option when using createApi!` +If you have multiple apis, you *have* to specify the reducerPath option when using createApi!`, ) }) }) diff --git a/packages/toolkit/src/query/tests/errorHandling.test-d.tsx b/packages/toolkit/src/query/tests/errorHandling.test-d.tsx new file mode 100644 index 0000000000..544b12a25f --- /dev/null +++ b/packages/toolkit/src/query/tests/errorHandling.test-d.tsx @@ -0,0 +1,52 @@ +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' +import { useState } from 'react' + +const mockSuccessResponse = { value: 'success' } + +const api = createApi({ + baseQuery: fetchBaseQuery({ baseUrl: 'https://example.com' }), + endpoints: (build) => ({ + update: build.mutation({ + query: () => ({ url: 'success' }), + }), + failedUpdate: build.mutation({ + query: () => ({ url: 'error' }), + }), + }), +}) + +describe('type tests', () => { + test('a mutation is unwrappable and has the correct types', () => { + function User() { + const [manualError, setManualError] = useState() + + const [update, { isLoading, data, error }] = + api.endpoints.update.useMutation() + + return ( +
+
{String(isLoading)}
+
{JSON.stringify(data)}
+
{JSON.stringify(error)}
+
+ {JSON.stringify(manualError)} +
+ +
+ ) + } + }) +}) diff --git a/packages/toolkit/src/query/tests/errorHandling.test.tsx b/packages/toolkit/src/query/tests/errorHandling.test.tsx index 96a3e0cc63..83338ec722 100644 --- a/packages/toolkit/src/query/tests/errorHandling.test.tsx +++ b/packages/toolkit/src/query/tests/errorHandling.test.tsx @@ -1,22 +1,21 @@ -import * as React from 'react' -import type { BaseQueryFn } from '@reduxjs/toolkit/query/react' +import type { ThunkDispatch, UnknownAction } from '@reduxjs/toolkit' +import type { BaseQueryFn, BaseQueryApi } from '@reduxjs/toolkit/query/react' import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' -import { rest } from 'msw' -import type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios' -import axios from 'axios' -import { expectExactType, hookWaitFor, setupApiStore } from './helpers' -import { server } from './mocks/server' import { + act, fireEvent, render, - waitFor, - screen, - act, renderHook, + screen, + waitFor, } from '@testing-library/react' +import type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios' +import axios from 'axios' +import { HttpResponse, http } from 'msw' +import * as React from 'react' import { useDispatch } from 'react-redux' -import type { UnknownAction, ThunkDispatch } from '@reduxjs/toolkit' -import type { BaseQueryApi } from '../baseQueryTypes' +import { hookWaitFor, setupApiStore } from '@internal/tests/utils/helpers' +import { server } from '@internal/query/tests/mocks/server' const baseQuery = fetchBaseQuery({ baseUrl: 'https://example.com' }) @@ -34,8 +33,10 @@ const api = createApi({ const storeRef = setupApiStore(api) -const failQueryOnce = rest.get('/query', (_, req, ctx) => - req.once(ctx.status(500), ctx.json({ value: 'failed' })) +const failQueryOnce = http.get( + '/query', + () => HttpResponse.json({ value: 'failed' }, { status: 500 }), + { once: true }, ) describe('fetchBaseQuery', () => { @@ -56,7 +57,7 @@ describe('fetchBaseQuery', () => { }) test('success', async () => { await expect( - baseQuery('/success', commonBaseQueryApiArgs, {}) + baseQuery('/success', commonBaseQueryApiArgs, {}), ).resolves.toEqual({ data: { value: 'success' }, meta: { @@ -68,7 +69,7 @@ describe('fetchBaseQuery', () => { test('error', async () => { server.use(failQueryOnce) await expect( - baseQuery('/error', commonBaseQueryApiArgs, {}) + baseQuery('/error', commonBaseQueryApiArgs, {}), ).resolves.toEqual({ error: { data: { value: 'error' }, @@ -85,9 +86,9 @@ describe('fetchBaseQuery', () => { describe('query error handling', () => { test('success', async () => { server.use( - rest.get('https://example.com/query', (_, res, ctx) => - res(ctx.json({ value: 'success' })) - ) + http.get('https://example.com/query', () => + HttpResponse.json({ value: 'success' }), + ), ) const { result } = renderHook(() => api.endpoints.query.useQuery({}), { wrapper: storeRef.wrapper, @@ -100,15 +101,15 @@ describe('query error handling', () => { isError: false, isSuccess: true, data: { value: 'success' }, - }) + }), ) }) test('error', async () => { server.use( - rest.get('https://example.com/query', (_, res, ctx) => - res(ctx.status(500), ctx.json({ value: 'error' })) - ) + http.get('https://example.com/query', () => + HttpResponse.json({ value: 'error' }, { status: 500 }), + ), ) const { result } = renderHook(() => api.endpoints.query.useQuery({}), { wrapper: storeRef.wrapper, @@ -124,15 +125,15 @@ describe('query error handling', () => { status: 500, data: { value: 'error' }, }, - }) + }), ) }) test('success -> error', async () => { server.use( - rest.get('https://example.com/query', (_, res, ctx) => - res(ctx.json({ value: 'success' })) - ) + http.get('https://example.com/query', () => + HttpResponse.json({ value: 'success' }), + ), ) const { result } = renderHook(() => api.endpoints.query.useQuery({}), { wrapper: storeRef.wrapper, @@ -145,13 +146,15 @@ describe('query error handling', () => { isError: false, isSuccess: true, data: { value: 'success' }, - }) + }), ) server.use( - rest.get('https://example.com/query', (_, res, ctx) => - res.once(ctx.status(500), ctx.json({ value: 'error' })) - ) + http.get( + 'https://example.com/query', + () => HttpResponse.json({ value: 'error' }, { status: 500 }), + { once: true }, + ), ) act(() => void result.current.refetch()) @@ -168,20 +171,22 @@ describe('query error handling', () => { }, // last data will stay available data: { value: 'success' }, - }) + }), ) }) test('error -> success', async () => { server.use( - rest.get('https://example.com/query', (_, res, ctx) => - res(ctx.json({ value: 'success' })) - ) + http.get('https://example.com/query', () => + HttpResponse.json({ value: 'success' }), + ), ) server.use( - rest.get('https://example.com/query', (_, res, ctx) => - res.once(ctx.status(500), ctx.json({ value: 'error' })) - ) + http.get( + 'https://example.com/query', + () => HttpResponse.json({ value: 'error' }, { status: 500 }), + { once: true }, + ), ) const { result } = renderHook(() => api.endpoints.query.useQuery({}), { wrapper: storeRef.wrapper, @@ -197,7 +202,7 @@ describe('query error handling', () => { status: 500, data: { value: 'error' }, }, - }) + }), ) act(() => void result.current.refetch()) @@ -209,7 +214,7 @@ describe('query error handling', () => { isError: false, isSuccess: true, data: { value: 'success' }, - }) + }), ) }) }) @@ -217,9 +222,9 @@ describe('query error handling', () => { describe('mutation error handling', () => { test('success', async () => { server.use( - rest.post('https://example.com/mutation', (_, res, ctx) => - res(ctx.json({ value: 'success' })) - ) + http.post('https://example.com/mutation', () => + HttpResponse.json({ value: 'success' }), + ), ) const { result } = renderHook(() => api.endpoints.mutation.useMutation(), { wrapper: storeRef.wrapper, @@ -236,15 +241,15 @@ describe('mutation error handling', () => { isError: false, isSuccess: true, data: { value: 'success' }, - }) + }), ) }) test('error', async () => { server.use( - rest.post('https://example.com/mutation', (_, res, ctx) => - res(ctx.status(500), ctx.json({ value: 'error' })) - ) + http.post('https://example.com/mutation', () => + HttpResponse.json({ value: 'error' }, { status: 500 }), + ), ) const { result } = renderHook(() => api.endpoints.mutation.useMutation(), { wrapper: storeRef.wrapper, @@ -264,15 +269,15 @@ describe('mutation error handling', () => { status: 500, data: { value: 'error' }, }, - }) + }), ) }) test('success -> error', async () => { server.use( - rest.post('https://example.com/mutation', (_, res, ctx) => - res(ctx.json({ value: 'success' })) - ) + http.post('https://example.com/mutation', () => + HttpResponse.json({ value: 'success' }), + ), ) const { result } = renderHook(() => api.endpoints.mutation.useMutation(), { wrapper: storeRef.wrapper, @@ -290,14 +295,16 @@ describe('mutation error handling', () => { isError: false, isSuccess: true, data: { value: 'success' }, - }) + }), ) } server.use( - rest.post('https://example.com/mutation', (_, res, ctx) => - res.once(ctx.status(500), ctx.json({ value: 'error' })) - ) + http.post( + 'https://example.com/mutation', + () => HttpResponse.json({ value: 'error' }, { status: 500 }), + { once: true }, + ), ) { @@ -315,7 +322,7 @@ describe('mutation error handling', () => { status: 500, data: { value: 'error' }, }, - }) + }), ) expect(result.current[1].data).toBeUndefined() } @@ -323,14 +330,16 @@ describe('mutation error handling', () => { test('error -> success', async () => { server.use( - rest.post('https://example.com/mutation', (_, res, ctx) => - res(ctx.json({ value: 'success' })) - ) + http.post('https://example.com/mutation', () => + HttpResponse.json({ value: 'success' }), + ), ) server.use( - rest.post('https://example.com/mutation', (_, res, ctx) => - res.once(ctx.status(500), ctx.json({ value: 'error' })) - ) + http.post( + 'https://example.com/mutation', + () => HttpResponse.json({ value: 'error' }, { status: 500 }), + { once: true }, + ), ) const { result } = renderHook(() => api.endpoints.mutation.useMutation(), { @@ -352,7 +361,7 @@ describe('mutation error handling', () => { status: 500, data: { value: 'error' }, }, - }) + }), ) } @@ -367,7 +376,7 @@ describe('mutation error handling', () => { isLoading: false, isError: false, isSuccess: true, - }) + }), ) expect(result.current[1].error).toBeUndefined() } @@ -377,7 +386,7 @@ describe('mutation error handling', () => { describe('custom axios baseQuery', () => { const axiosBaseQuery = ( - { baseUrl }: { baseUrl: string } = { baseUrl: '' } + { baseUrl }: { baseUrl: string } = { baseUrl: '' }, ): BaseQueryFn< { url: string @@ -398,7 +407,7 @@ describe('custom axios baseQuery', () => { meta: { request: config, response: result }, } } catch (axiosError) { - let err = axiosError as AxiosError + const err = axiosError as AxiosError return { error: { status: err.response?.status, @@ -442,9 +451,9 @@ describe('custom axios baseQuery', () => { test('axios errors behave as expected', async () => { server.use( - rest.get('https://example.com/success', (_, res, ctx) => - res(ctx.status(500), ctx.json({ value: 'error' })) - ) + http.get('https://example.com/success', () => + HttpResponse.json({ value: 'error' }, { status: 500 }), + ), ) const { result } = renderHook(() => api.endpoints.query.useQuery(), { wrapper: storeRef.wrapper, @@ -457,7 +466,7 @@ describe('custom axios baseQuery', () => { isError: true, isSuccess: false, error: { status: 500, data: { value: 'error' } }, - }) + }), ) }) }) @@ -481,9 +490,11 @@ describe('error handling in a component', () => { test('a mutation is unwrappable and has the correct types', async () => { server.use( - rest.get('https://example.com/success', (_, res, ctx) => - res.once(ctx.status(500), ctx.json(mockErrorResponse)) - ) + http.get( + 'https://example.com/success', + () => HttpResponse.json(mockErrorResponse, { status: 500 }), + { once: true }, + ), ) function User() { @@ -504,7 +515,6 @@ describe('error handling in a component', () => { update({ name: 'hello' }) .unwrap() .then((result) => { - expectExactType(mockSuccessResponse)(result) setManualError(undefined) }) .catch((error) => act(() => setManualError(error))) @@ -519,36 +529,36 @@ describe('error handling in a component', () => { render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) fireEvent.click(screen.getByText('Update User')) expect(screen.getByTestId('isLoading').textContent).toBe('true') await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) // Make sure the hook and the unwrapped action return the same things in an error state await waitFor(() => expect(screen.getByTestId('error').textContent).toEqual( - screen.getByTestId('manuallySetError').textContent - ) + screen.getByTestId('manuallySetError').textContent, + ), ) fireEvent.click(screen.getByText('Update User')) expect(screen.getByTestId('isLoading').textContent).toBe('true') await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('error').textContent).toBeFalsy() + expect(screen.getByTestId('error').textContent).toBeFalsy(), ) await waitFor(() => - expect(screen.getByTestId('manuallySetError').textContent).toBeFalsy() + expect(screen.getByTestId('manuallySetError').textContent).toBeFalsy(), ) await waitFor(() => expect(screen.getByTestId('data').textContent).toEqual( - JSON.stringify(mockSuccessResponse) - ) + JSON.stringify(mockSuccessResponse), + ), ) }) @@ -566,7 +576,7 @@ describe('error handling in a component', () => { > act(() => { mutationqueryFulfilled = dispatch( - api.endpoints.update.initiate({}, { track }) + api.endpoints.update.initiate({}, { track }), ) }) const result = await mutationqueryFulfilled! @@ -588,7 +598,7 @@ describe('error handling in a component', () => { > act(() => { mutationqueryFulfilled = dispatch( - api.endpoints.failedUpdate.initiate({}, { track }) + api.endpoints.failedUpdate.initiate({}, { track }), ) }) const result = await mutationqueryFulfilled! @@ -612,7 +622,7 @@ describe('error handling in a component', () => { > act(() => { mutationqueryFulfilled = dispatch( - api.endpoints.update.initiate({}, { track }) + api.endpoints.update.initiate({}, { track }), ) }) const result = await mutationqueryFulfilled!.unwrap() @@ -634,7 +644,7 @@ describe('error handling in a component', () => { > act(() => { mutationqueryFulfilled = dispatch( - api.endpoints.failedUpdate.initiate({}, { track }) + api.endpoints.failedUpdate.initiate({}, { track }), ) }) const unwrappedPromise = mutationqueryFulfilled!.unwrap() diff --git a/packages/toolkit/src/query/tests/fakeBaseQuery.test.tsx b/packages/toolkit/src/query/tests/fakeBaseQuery.test.tsx index c2f7b4c997..cddf0c051f 100644 --- a/packages/toolkit/src/query/tests/fakeBaseQuery.test.tsx +++ b/packages/toolkit/src/query/tests/fakeBaseQuery.test.tsx @@ -1,6 +1,6 @@ import { configureStore } from '@reduxjs/toolkit' import { createApi, fakeBaseQuery } from '@reduxjs/toolkit/query' -import './helpers' +import '../../tests/utils/helpers' type CustomErrorType = { type: 'Custom' } @@ -128,7 +128,7 @@ test('fakeBaseQuery throws when invoking query', async () => { result = await store.dispatch(thunk) }).toHaveConsoleOutput( `An unhandled error occurred processing a request for the endpoint "withQuery". - In the case of an unhandled error, no tags will be "provided" or "invalidated". [Error: When using \`fakeBaseQuery\`, all queries & mutations must use the \`queryFn\` definition syntax.]` + In the case of an unhandled error, no tags will be "provided" or "invalidated". [Error: When using \`fakeBaseQuery\`, all queries & mutations must use the \`queryFn\` definition syntax.]`, ) expect(result!.error).toEqual({ diff --git a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx index 6ab089f2be..07bda8f612 100644 --- a/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx +++ b/packages/toolkit/src/query/tests/fetchBaseQuery.test.tsx @@ -1,14 +1,13 @@ -import { vi } from 'vitest' import { createSlice } from '@reduxjs/toolkit' import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' -import { setupApiStore, waitMs } from './helpers' -import { server } from './mocks/server' -// @ts-ignore +import { headersToObject } from 'headers-polyfill' +import { HttpResponse, delay, http } from 'msw' import nodeFetch from 'node-fetch' - -import { rest } from 'msw' import queryString from 'query-string' +import { vi } from 'vitest' +import { setupApiStore } from '../../tests/utils/helpers' import type { BaseQueryApi } from '../baseQueryTypes' +import { server } from './mocks/server' const defaultHeaders: Record = { fake: 'header', @@ -19,13 +18,13 @@ const defaultHeaders: Record = { const baseUrl = 'https://example.com' // @ts-ignore -const fetchFn = vi.fn, any[]>(global.fetch) +const fetchFn = vi.fn, any[]>(nodeFetch) const baseQuery = fetchBaseQuery({ baseUrl, fetchFn: fetchFn as any, prepareHeaders: (headers, { getState }) => { - const token = (getState() as RootState).auth.token + const { token } = (getState() as RootState).auth // If we have a token set in state, let's assume that we should be passing it. if (token) { @@ -108,6 +107,7 @@ describe('fetchBaseQuery', () => { expect(res).toBeInstanceOf(Object) expect(res.meta?.request).toBeInstanceOf(Request) expect(res.meta?.response).toBeInstanceOf(Object) + expect(res.data).toBeNull() }) @@ -143,15 +143,17 @@ describe('fetchBaseQuery', () => { describe('non-JSON-body', () => { it('success: should return data ("text" responseHandler)', async () => { server.use( - rest.get('https://example.com/success', (_, res, ctx) => - res.once(ctx.text(`this is not json!`)) - ) + http.get( + 'https://example.com/success', + () => HttpResponse.text(`this is not json!`), + { once: true }, + ), ) const req = baseQuery( { url: '/success', responseHandler: 'text' }, commonBaseQueryApi, - {} + {}, ) expect(req).toBeInstanceOf(Promise) const res = await req @@ -163,9 +165,11 @@ describe('fetchBaseQuery', () => { it('success: should fail gracefully (default="json" responseHandler)', async () => { server.use( - rest.get('https://example.com/success', (_, res, ctx) => - res.once(ctx.text(`this is not json!`)) - ) + http.get( + 'https://example.com/success', + () => HttpResponse.text(`this is not json!`), + { once: true }, + ), ) const req = baseQuery('/success', commonBaseQueryApi, {}) @@ -184,12 +188,11 @@ describe('fetchBaseQuery', () => { it('success: parse text without error ("content-type" responseHandler)', async () => { server.use( - rest.get('https://example.com/success', (_, res, ctx) => - res.once( - ctx.text(`this is not json!`) - // NOTE: MSW sets content-type header as text automatically - ) - ) + http.get( + 'https://example.com/success', + () => HttpResponse.text(`this is not json!`), + { once: true }, + ), ) const req = baseQuery( @@ -198,13 +201,13 @@ describe('fetchBaseQuery', () => { responseHandler: 'content-type', }, commonBaseQueryApi, - {} + {}, ) expect(req).toBeInstanceOf(Promise) const res = await req expect(res).toBeInstanceOf(Object) expect(res.meta?.response?.headers.get('content-type')).toEqual( - 'text/plain' + 'text/plain', ) expect(res.meta?.request).toBeInstanceOf(Request) expect(res.meta?.response).toBeInstanceOf(Object) @@ -213,12 +216,11 @@ describe('fetchBaseQuery', () => { it('success: parse json without error ("content-type" responseHandler)', async () => { server.use( - rest.get('https://example.com/success', (_, res, ctx) => - res.once( - ctx.json(`this will become json!`) - // NOTE: MSW sets content-type header as json automatically - ) - ) + http.get( + 'https://example.com/success', + () => HttpResponse.json(`this will become json!`), + { once: true }, + ), ) const req = baseQuery( @@ -227,13 +229,13 @@ describe('fetchBaseQuery', () => { responseHandler: 'content-type', }, commonBaseQueryApi, - {} + {}, ) expect(req).toBeInstanceOf(Promise) const res = await req expect(res).toBeInstanceOf(Object) expect(res.meta?.response?.headers.get('content-type')).toEqual( - 'application/json' + 'application/json', ) expect(res.meta?.request).toBeInstanceOf(Request) expect(res.meta?.response).toBeInstanceOf(Object) @@ -242,15 +244,15 @@ describe('fetchBaseQuery', () => { it('server error: should fail normally with a 500 status ("text" responseHandler)', async () => { server.use( - rest.get('https://example.com/error', (_, res, ctx) => - res(ctx.status(500), ctx.text(`this is not json!`)) - ) + http.get('https://example.com/error', () => + HttpResponse.text(`this is not json!`, { status: 500 }), + ), ) const req = baseQuery( { url: '/error', responseHandler: 'text' }, commonBaseQueryApi, - {} + {}, ) expect(req).toBeInstanceOf(Promise) const res = await req @@ -266,15 +268,15 @@ describe('fetchBaseQuery', () => { it('server error: should fail normally with a 500 status as text ("content-type" responseHandler)', async () => { const serverResponse = 'Internal Server Error' server.use( - rest.get('https://example.com/error', (_, res, ctx) => - res(ctx.status(500), ctx.text(serverResponse)) - ) + http.get('https://example.com/error', () => + HttpResponse.text(serverResponse, { status: 500 }), + ), ) const req = baseQuery( { url: '/error', responseHandler: 'content-type' }, commonBaseQueryApi, - {} + {}, ) expect(req).toBeInstanceOf(Promise) const res = await req @@ -282,7 +284,7 @@ describe('fetchBaseQuery', () => { expect(res.meta?.request).toBeInstanceOf(Request) expect(res.meta?.response).toBeInstanceOf(Object) expect(res.meta?.response?.headers.get('content-type')).toEqual( - 'text/plain' + 'text/plain', ) expect(res.error).toEqual({ status: 500, @@ -295,15 +297,15 @@ describe('fetchBaseQuery', () => { errors: { field1: "Password cannot be 'password'" }, } server.use( - rest.get('https://example.com/error', (_, res, ctx) => - res(ctx.status(500), ctx.json(serverResponse)) - ) + http.get('https://example.com/error', () => + HttpResponse.json(serverResponse, { status: 500 }), + ), ) const req = baseQuery( { url: '/error', responseHandler: 'content-type' }, commonBaseQueryApi, - {} + {}, ) expect(req).toBeInstanceOf(Promise) const res = await req @@ -311,7 +313,7 @@ describe('fetchBaseQuery', () => { expect(res.meta?.request).toBeInstanceOf(Request) expect(res.meta?.response).toBeInstanceOf(Object) expect(res.meta?.response?.headers.get('content-type')).toEqual( - 'application/json' + 'application/json', ) expect(res.error).toEqual({ status: 500, @@ -321,9 +323,9 @@ describe('fetchBaseQuery', () => { it('server error: should fail gracefully (default="json" responseHandler)', async () => { server.use( - rest.get('https://example.com/error', (_, res, ctx) => - res(ctx.status(500), ctx.text(`this is not json!`)) - ) + http.get('https://example.com/error', () => + HttpResponse.text(`this is not json!`, { status: 500 }), + ), ) const req = baseQuery('/error', commonBaseQueryApi, {}) @@ -351,7 +353,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo', body: data, method: 'POST' }, { ...commonBaseQueryApi, type: 'mutation' }, - {} + {}, )) expect(request.headers['content-type']).toBe('application/json') @@ -365,7 +367,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo', body: data, method: 'POST' }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['content-type']).toBe('application/json') @@ -386,7 +388,7 @@ describe('fetchBaseQuery', () => { headers: { 'content-type': 'text/html' }, }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['content-type']).toBe('text/html') @@ -405,7 +407,7 @@ describe('fetchBaseQuery', () => { headers: { 'content-type': 'text/html' }, }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['content-type']).toBe('text/html') @@ -427,7 +429,7 @@ describe('fetchBaseQuery', () => { method: 'POST', }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['content-type']).toBe('application/vnd.api+json') @@ -446,7 +448,7 @@ describe('fetchBaseQuery', () => { method: 'POST', }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['content-type']).toBe('application/json') @@ -467,7 +469,7 @@ describe('fetchBaseQuery', () => { method: 'POST', }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['content-type']).toBe('application/json') @@ -481,7 +483,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo' }, commonBaseQueryApi, - {} + {}, )) expect(request.url).toEqual(`${baseUrl}/echo`) @@ -494,7 +496,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo', params }, commonBaseQueryApi, - {} + {}, )) expect(request.url).toEqual(`${baseUrl}/echo?a=1&b=true`) @@ -507,7 +509,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo?banana=pudding', params }, commonBaseQueryApi, - {} + {}, )) expect(request.url).toEqual(`${baseUrl}/echo?banana=pudding&a=1&b=true`) @@ -520,7 +522,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo', params }, commonBaseQueryApi, - {} + {}, )) expect(request.url).toEqual(`${baseUrl}/echo?apple=fruit`) @@ -533,7 +535,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo', params }, commonBaseQueryApi, - {} + {}, )) expect(request.url).toEqual(`${baseUrl}/echo?apple=fruit&randy=null`) @@ -573,11 +575,11 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo', params }, commonBaseQueryApi, - {} + {}, )) expect(request.url).toEqual( - `${baseUrl}/echo?someArray[]=a&someArray[]=b&someArray[]=c` + `${baseUrl}/echo?someArray[]=a&someArray[]=b&someArray[]=c`, ) }) @@ -605,7 +607,7 @@ describe('fetchBaseQuery', () => { headers: { 'content-type': 'application/vnd.hal+json' }, }, commonBaseQueryApi, - {} + {}, )) expect(request.body).toMatchObject(testBody) @@ -622,7 +624,7 @@ describe('fetchBaseQuery', () => { response.status === 200 && body.success === false ? false : true, }, commonBaseQueryApi, - {} + {}, ) expect(res.error).toEqual({ @@ -641,7 +643,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo' }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['fake']).toBe(defaultHeaders['fake']) @@ -654,7 +656,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo', headers: { authorization: 'Bearer banana' } }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['authorization']).toBe('Bearer banana') @@ -674,7 +676,7 @@ describe('fetchBaseQuery', () => { }, }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['authorization']).toBe('Bearer banana') @@ -691,7 +693,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo', headers: { fake, delete: '', delete2: '' } }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['fake']).toBe(fake) @@ -780,7 +782,7 @@ describe('fetchBaseQuery', () => { type: 'query', endpoint: '', }, - {} + {}, ) } @@ -804,7 +806,7 @@ describe('fetchBaseQuery', () => { fetchFn: fetchFn as any, prepareHeaders: ( headers, - { getState, extra, endpoint, type, forced } + { getState, extra, endpoint, type, forced }, ) => { _getState = getState _endpoint = endpoint @@ -836,7 +838,7 @@ describe('fetchBaseQuery', () => { forced: true, endpoint: 'someEndpointName', }, - {} + {}, ) } @@ -873,7 +875,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo', headers: undefined }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['fake']).toBe(defaultHeaders['fake']) @@ -887,7 +889,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo', headers: { banana } }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['banana']).toBe('1') @@ -902,7 +904,7 @@ describe('fetchBaseQuery', () => { ;({ data: request } = await baseQuery( { url: '/echo', headers: { banana } }, commonBaseQueryApi, - {} + {}, )) expect(request.headers['banana']).toBeUndefined() @@ -914,9 +916,11 @@ describe('fetchBaseQuery', () => { describe('Accepts global arguments', () => { test('Global responseHandler', async () => { server.use( - rest.get('https://example.com/success', (_, res, ctx) => - res.once(ctx.text(`this is not json!`)) - ) + http.get( + 'https://example.com/success', + () => HttpResponse.text(`this is not json!`), + { once: true }, + ), ) const globalizedBaseQuery = fetchBaseQuery({ @@ -928,7 +932,7 @@ describe('fetchBaseQuery', () => { const req = globalizedBaseQuery( { url: '/success' }, commonBaseQueryApi, - {} + {}, ) expect(req).toBeInstanceOf(Promise) const res = await req @@ -953,7 +957,7 @@ describe('fetchBaseQuery', () => { url: '/nonstandard-error', }, commonBaseQueryApi, - {} + {}, ) expect(res.error).toEqual({ @@ -966,16 +970,25 @@ describe('fetchBaseQuery', () => { }) test('Global timeout', async () => { - let reject: () => void - const donePromise = new Promise((resolve, _reject) => { - reject = _reject - }) server.use( - rest.get('https://example.com/empty1', async (req, res, ctx) => { - await Promise.race([waitMs(3000), donePromise]) - return res.once(ctx.json({ ...req, headers: req.headers.all() })) - }) + http.get( + 'https://example.com/empty1', + async ({ request, cookies, params, requestId }) => { + await delay(300) + + return HttpResponse.json({ + ...request, + cookies, + params, + requestId, + url: new URL(request.url), + headers: headersToObject(request.headers), + }) + }, + { once: true }, + ), ) + const globalizedBaseQuery = fetchBaseQuery({ baseUrl, fetchFn: fetchFn as any, @@ -985,13 +998,13 @@ describe('fetchBaseQuery', () => { const result = await globalizedBaseQuery( { url: '/empty1' }, commonBaseQueryApi, - {} + {}, ) + expect(result?.error).toEqual({ status: 'TIMEOUT_ERROR', - error: 'AbortError: The user aborted a request.', + error: 'AbortError: The operation was aborted.', }) - reject!() }) }) }) @@ -1009,7 +1022,7 @@ describe('fetchFn', () => { ;({ data: request } = await baseQuery( { url: '/echo', params }, commonBaseQueryApi, - {} + {}, )) expect(request.url).toEqual(`${baseUrl}/echo?apple=fruit`) @@ -1039,20 +1052,24 @@ describe('fetchFn', () => { describe('FormData', () => { test('sets the right headers when sending FormData', async () => { const body = new FormData() + body.append('username', 'test') + body.append( 'file', new Blob([JSON.stringify({ hello: 'there' }, null, 2)], { type: 'application/json', - }) + }), ) const res = await baseQuery( { url: '/echo', method: 'POST', body }, commonBaseQueryApi, - {} + {}, ) + const request: any = res.data + expect(request.headers['content-type']).not.toContain('application/json') }) }) @@ -1068,7 +1085,7 @@ describe('still throws on completely unexpected errors', () => { }, }, commonBaseQueryApi, - {} + {}, ) expect(req).toBeInstanceOf(Promise) await expect(req).rejects.toBe(error) @@ -1077,26 +1094,34 @@ describe('still throws on completely unexpected errors', () => { describe('timeout', () => { test('throws a timeout error when a request takes longer than specified timeout duration', async () => { - let reject: () => void - const donePromise = new Promise((resolve, _reject) => { - reject = _reject - }) - server.use( - rest.get('https://example.com/empty2', async (req, res, ctx) => { - await Promise.race([waitMs(3000), donePromise]) - return res.once(ctx.json({ ...req, headers: req.headers.all() })) - }) + http.get( + 'https://example.com/empty2', + async ({ request, cookies, params, requestId }) => { + await delay(300) + + return HttpResponse.json({ + ...request, + url: new URL(request.url), + cookies, + params, + requestId, + headers: headersToObject(request.headers), + }) + }, + { once: true }, + ), ) + const result = await baseQuery( { url: '/empty2', timeout: 200 }, commonBaseQueryApi, - {} + {}, ) + expect(result?.error).toEqual({ status: 'TIMEOUT_ERROR', - error: 'AbortError: The user aborted a request.', + error: 'AbortError: The operation was aborted.', }) - reject!() }) }) diff --git a/packages/toolkit/src/query/tests/invalidation.test.tsx b/packages/toolkit/src/query/tests/invalidation.test.tsx index a4081a3d63..773b7cc0a6 100644 --- a/packages/toolkit/src/query/tests/invalidation.test.tsx +++ b/packages/toolkit/src/query/tests/invalidation.test.tsx @@ -1,7 +1,8 @@ +import type { TagDescription } from '@reduxjs/toolkit/query' import { createApi, fakeBaseQuery } from '@reduxjs/toolkit/query' -import { setupApiStore, waitMs } from './helpers' -import type { TagDescription } from '@reduxjs/toolkit/dist/query/endpointDefinitions' import { waitFor } from '@testing-library/react' +import { delay } from 'msw' +import { setupApiStore } from '../../tests/utils/helpers' const tagTypes = [ 'apple', @@ -12,7 +13,7 @@ const tagTypes = [ 'dog', 'giraffe', ] as const -type TagTypes = typeof tagTypes[number] +type TagTypes = (typeof tagTypes)[number] type Tags = TagDescription[] /** providesTags, invalidatesTags, shouldInvalidate */ @@ -102,7 +103,7 @@ test.each(caseMatrix)( }), }), undefined, - { withoutTestLifecycles: true } + { withoutTestLifecycles: true }, ) store.dispatch(providing.initiate()) @@ -110,15 +111,15 @@ test.each(caseMatrix)( expect(queryCount).toBe(1) await waitFor(() => { expect(api.endpoints.providing.select()(store.getState()).status).toBe( - 'fulfilled' + 'fulfilled', ) expect(api.endpoints.unrelated.select()(store.getState()).status).toBe( - 'fulfilled' + 'fulfilled', ) }) const toInvalidate = api.util.selectInvalidatedBy( store.getState(), - invalidatesTags + invalidatesTags, ) if (shouldInvalidate) { @@ -135,7 +136,7 @@ test.each(caseMatrix)( store.dispatch(invalidating.initiate()) expect(queryCount).toBe(1) - await waitMs(2) + await delay(2) expect(queryCount).toBe(shouldInvalidate ? 2 : 1) - } + }, ) diff --git a/packages/toolkit/src/query/tests/matchers.test-d.tsx b/packages/toolkit/src/query/tests/matchers.test-d.tsx new file mode 100644 index 0000000000..2d73df12d0 --- /dev/null +++ b/packages/toolkit/src/query/tests/matchers.test-d.tsx @@ -0,0 +1,80 @@ +import type { SerializedError } from '@reduxjs/toolkit' +import { createSlice } from '@reduxjs/toolkit' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' + +interface ResultType { + result: 'complex' +} + +interface ArgType { + foo: 'bar' + count: 3 +} + +const baseQuery = fetchBaseQuery({ baseUrl: 'https://example.com' }) +const api = createApi({ + baseQuery, + endpoints(build) { + return { + querySuccess: build.query({ + query: () => '/success', + }), + querySuccess2: build.query({ query: () => '/success' }), + queryFail: build.query({ query: () => '/error' }), + mutationSuccess: build.mutation({ + query: () => ({ url: '/success', method: 'POST' }), + }), + mutationSuccess2: build.mutation({ + query: () => ({ url: '/success', method: 'POST' }), + }), + mutationFail: build.mutation({ + query: () => ({ url: '/error', method: 'POST' }), + }), + } + }, +}) + +describe('type tests', () => { + test('inferred types', () => { + createSlice({ + name: 'auth', + initialState: {}, + reducers: {}, + extraReducers: (builder) => { + builder + .addMatcher( + api.endpoints.querySuccess.matchPending, + (state, action) => { + expectTypeOf(action.payload).toBeUndefined() + + expectTypeOf( + action.meta.arg.originalArgs, + ).toEqualTypeOf() + }, + ) + .addMatcher( + api.endpoints.querySuccess.matchFulfilled, + (state, action) => { + expectTypeOf(action.payload).toEqualTypeOf() + + expectTypeOf(action.meta.fulfilledTimeStamp).toBeNumber() + + expectTypeOf( + action.meta.arg.originalArgs, + ).toEqualTypeOf() + }, + ) + .addMatcher( + api.endpoints.querySuccess.matchRejected, + (state, action) => { + expectTypeOf(action.error).toEqualTypeOf() + + expectTypeOf( + action.meta.arg.originalArgs, + ).toEqualTypeOf() + }, + ) + }, + }) + }) +}) diff --git a/packages/toolkit/src/query/tests/matchers.test.tsx b/packages/toolkit/src/query/tests/matchers.test.tsx index 37c1dfe58b..5b26740e98 100644 --- a/packages/toolkit/src/query/tests/matchers.test.tsx +++ b/packages/toolkit/src/query/tests/matchers.test.tsx @@ -1,13 +1,11 @@ -import type { SerializedError } from '@reduxjs/toolkit' -import { createSlice } from '@reduxjs/toolkit' -import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' -import { renderHook, act } from '@testing-library/react' import { actionsReducer, - expectExactType, hookWaitFor, setupApiStore, -} from './helpers' +} from '@internal/tests/utils/helpers' +import { createSlice } from '@reduxjs/toolkit' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' +import { act, renderHook } from '@testing-library/react' interface ResultType { result: 'complex' @@ -65,23 +63,23 @@ test('matches query pending & fulfilled actions for the given endpoint', async ( expect(storeRef.store.getState().actions).toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchFulfilled + endpoint.matchFulfilled, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, otherEndpoint.matchPending, - otherEndpoint.matchFulfilled + otherEndpoint.matchFulfilled, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchFulfilled, api.endpoints.mutationSuccess.matchFulfilled, - endpoint.matchRejected + endpoint.matchRejected, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchRejected + endpoint.matchRejected, ) }) test('matches query pending & rejected actions for the given endpoint', async () => { @@ -93,17 +91,17 @@ test('matches query pending & rejected actions for the given endpoint', async () expect(storeRef.store.getState().actions).toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchRejected + endpoint.matchRejected, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchFulfilled, - endpoint.matchRejected + endpoint.matchRejected, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchFulfilled + endpoint.matchFulfilled, ) }) @@ -118,18 +116,18 @@ test('matches lazy query pending & fulfilled actions for given endpoint', async expect(storeRef.store.getState().actions).toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchFulfilled + endpoint.matchFulfilled, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchFulfilled, - endpoint.matchRejected + endpoint.matchRejected, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchRejected + endpoint.matchRejected, ) }) @@ -144,17 +142,17 @@ test('matches lazy query pending & rejected actions for given endpoint', async ( expect(storeRef.store.getState().actions).toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchRejected + endpoint.matchRejected, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchFulfilled, - endpoint.matchRejected + endpoint.matchRejected, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchFulfilled + endpoint.matchFulfilled, ) }) @@ -170,22 +168,22 @@ test('matches mutation pending & fulfilled actions for the given endpoint', asyn expect(storeRef.store.getState().actions).toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchFulfilled + endpoint.matchFulfilled, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, otherEndpoint.matchPending, - otherEndpoint.matchFulfilled + otherEndpoint.matchFulfilled, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchFulfilled, - endpoint.matchRejected + endpoint.matchRejected, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchRejected + endpoint.matchRejected, ) }) test('matches mutation pending & rejected actions for the given endpoint', async () => { @@ -199,17 +197,17 @@ test('matches mutation pending & rejected actions for the given endpoint', async expect(storeRef.store.getState().actions).toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchRejected + endpoint.matchRejected, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchFulfilled, - endpoint.matchRejected + endpoint.matchRejected, ) expect(storeRef.store.getState().actions).not.toMatchSequence( api.internalActions.middlewareRegistered.match, endpoint.matchPending, - endpoint.matchFulfilled + endpoint.matchFulfilled, ) }) @@ -223,28 +221,20 @@ test('inferred types', () => { .addMatcher( api.endpoints.querySuccess.matchPending, (state, action) => { - expectExactType(undefined)(action.payload) // @ts-expect-error console.log(action.error) - expectExactType({} as ArgType)(action.meta.arg.originalArgs) - } + }, ) .addMatcher( api.endpoints.querySuccess.matchFulfilled, (state, action) => { - expectExactType({} as ResultType)(action.payload) - expectExactType(0 as number)(action.meta.fulfilledTimeStamp) // @ts-expect-error console.log(action.error) - expectExactType({} as ArgType)(action.meta.arg.originalArgs) - } + }, ) .addMatcher( api.endpoints.querySuccess.matchRejected, - (state, action) => { - expectExactType({} as SerializedError)(action.error) - expectExactType({} as ArgType)(action.meta.arg.originalArgs) - } + (state, action) => {}, ) }, }) diff --git a/packages/toolkit/src/query/tests/mocks/handlers.ts b/packages/toolkit/src/query/tests/mocks/handlers.ts new file mode 100644 index 0000000000..3fe044fdf0 --- /dev/null +++ b/packages/toolkit/src/query/tests/mocks/handlers.ts @@ -0,0 +1,101 @@ +import { headersToObject } from 'headers-polyfill' +import { HttpResponse, http } from 'msw' + +export type Post = { + id: number + title: string + body: string +} + +export const posts: Record = { + 1: { id: 1, title: 'hello', body: 'extra body!' }, +} + +export const handlers = [ + http.get( + 'https://example.com/echo', + async ({ request, params, cookies, requestId }) => { + return HttpResponse.json({ + ...request, + params, + cookies, + requestId, + url: new URL(request.url), + headers: headersToObject(request.headers), + }) + }, + ), + + http.post( + 'https://example.com/echo', + async ({ request, cookies, params, requestId }) => { + let body + + try { + body = + headersToObject(request.headers)['content-type'] === 'text/html' + ? await request.text() + : await request.json() + } catch (err) { + body = request.body + } + + return HttpResponse.json({ + ...request, + cookies, + params, + requestId, + body, + url: new URL(request.url), + headers: headersToObject(request.headers), + }) + }, + ), + + http.get('https://example.com/success', () => + HttpResponse.json({ value: 'success' }), + ), + + http.post('https://example.com/success', () => + HttpResponse.json({ value: 'success' }), + ), + + http.get('https://example.com/empty', () => new HttpResponse('')), + + http.get('https://example.com/error', () => + HttpResponse.json({ value: 'error' }, { status: 500 }), + ), + + http.post('https://example.com/error', () => + HttpResponse.json({ value: 'error' }, { status: 500 }), + ), + + http.get('https://example.com/nonstandard-error', () => + HttpResponse.json( + { + success: false, + message: 'This returns a 200 but is really an error', + }, + { status: 200 }, + ), + ), + + http.get('https://example.com/mirror', ({ params }) => + HttpResponse.json(params), + ), + + http.post('https://example.com/mirror', ({ params }) => + HttpResponse.json(params), + ), + + http.get('https://example.com/posts/random', () => { + // just simulate an api that returned a random ID + const { id } = posts[1] + return HttpResponse.json({ id }) + }), + + http.get<{ id: string }, any, Pick>( + 'https://example.com/post/:id', + ({ params }) => HttpResponse.json(posts[params.id]), + ), +] diff --git a/packages/toolkit/src/query/tests/mocks/server.ts b/packages/toolkit/src/query/tests/mocks/server.ts index 62d1c350f5..5dc2fb1467 100644 --- a/packages/toolkit/src/query/tests/mocks/server.ts +++ b/packages/toolkit/src/query/tests/mocks/server.ts @@ -1,62 +1,5 @@ import { setupServer } from 'msw/node' -import { rest } from 'msw' +import { handlers } from './handlers' // This configures a request mocking server with the given request handlers. - -export type Post = { - id: number - title: string - body: string -} - -export const posts: Record = { - 1: { id: 1, title: 'hello', body: 'extra body!' }, -} - -export const server = setupServer( - rest.get('https://example.com/echo', (req, res, ctx) => - res(ctx.json({ ...req, headers: req.headers.all() })) - ), - rest.post('https://example.com/echo', (req, res, ctx) => - res(ctx.json({ ...req, headers: req.headers.all() })) - ), - rest.get('https://example.com/success', (_, res, ctx) => - res(ctx.json({ value: 'success' })) - ), - rest.post('https://example.com/success', (_, res, ctx) => - res(ctx.json({ value: 'success' })) - ), - rest.get('https://example.com/empty', (_, res, ctx) => res(ctx.body(''))), - rest.get('https://example.com/error', (_, res, ctx) => - res(ctx.status(500), ctx.json({ value: 'error' })) - ), - rest.post('https://example.com/error', (_, res, ctx) => - res(ctx.status(500), ctx.json({ value: 'error' })) - ), - rest.get('https://example.com/nonstandard-error', (_, res, ctx) => - res( - ctx.status(200), - ctx.json({ - success: false, - message: 'This returns a 200 but is really an error', - }) - ) - ), - rest.get('https://example.com/mirror', (req, res, ctx) => - res(ctx.json(req.params)) - ), - rest.post('https://example.com/mirror', (req, res, ctx) => - res(ctx.json(req.params)) - ), - rest.get('https://example.com/posts/random', (req, res, ctx) => { - // just simulate an api that returned a random ID - const { id, ..._post } = posts[1] - return res(ctx.json({ id })) - }), - rest.get( - 'https://example.com/post/:id', - (req, res, ctx) => { - return res(ctx.json(posts[req.params.id])) - } - ) -) +export const server = setupServer(...handlers) diff --git a/packages/toolkit/src/query/tests/optimisticUpdates.test.tsx b/packages/toolkit/src/query/tests/optimisticUpdates.test.tsx index f96e2b4162..eb9893a3be 100644 --- a/packages/toolkit/src/query/tests/optimisticUpdates.test.tsx +++ b/packages/toolkit/src/query/tests/optimisticUpdates.test.tsx @@ -1,7 +1,11 @@ -import { vi } from 'vitest' import { createApi } from '@reduxjs/toolkit/query/react' -import { actionsReducer, hookWaitFor, setupApiStore, waitMs } from './helpers' -import { renderHook, act } from '@testing-library/react' +import { act, renderHook } from '@testing-library/react' +import { delay } from 'msw' +import { + actionsReducer, + hookWaitFor, + setupApiStore, +} from '../../tests/utils/helpers' import type { InvalidationState } from '../core/apiState' interface Post { @@ -11,7 +15,9 @@ interface Post { } const baseQuery = vi.fn() -beforeEach(() => baseQuery.mockReset()) +beforeEach(() => { + baseQuery.mockReset() +}) const api = createApi({ baseQuery: (...args: any[]) => { @@ -45,7 +51,7 @@ const api = createApi({ const { undo } = dispatch( api.util.updateQueryData('post', id, (draft) => { Object.assign(draft, patch) - }) + }), ) queryFulfilled.catch(undo) }, @@ -92,7 +98,7 @@ describe('basic lifecycle', () => { () => extendedApi.endpoints.test.useMutation(), { wrapper: storeRef.wrapper, - } + }, ) baseQuery.mockResolvedValue('success') @@ -105,7 +111,7 @@ describe('basic lifecycle', () => { expect(onError).not.toHaveBeenCalled() expect(onSuccess).not.toHaveBeenCalled() - await act(() => waitMs(5)) + await act(() => delay(5)) expect(onError).not.toHaveBeenCalled() expect(onSuccess).toHaveBeenCalledWith({ data: 'success', meta: 'meta' }) }) @@ -115,7 +121,7 @@ describe('basic lifecycle', () => { () => extendedApi.endpoints.test.useMutation(), { wrapper: storeRef.wrapper, - } + }, ) baseQuery.mockRejectedValueOnce('error') @@ -127,7 +133,7 @@ describe('basic lifecycle', () => { expect(baseQuery).toHaveBeenCalledWith('arg', expect.any(Object), undefined) expect(onError).not.toHaveBeenCalled() expect(onSuccess).not.toHaveBeenCalled() - await act(() => waitMs(5)) + await act(() => delay(5)) expect(onError).toHaveBeenCalledWith({ error: 'error', isUnhandledError: false, @@ -166,7 +172,7 @@ describe('updateQueryData', () => { returnValue = storeRef.store.dispatch( api.util.updateQueryData('post', '3', (draft) => { draft.contents = 'I love cheese!' - }) + }), ) }) @@ -185,7 +191,7 @@ describe('updateQueryData', () => { act(() => { storeRef.store.dispatch( - api.util.patchQueryData('post', '3', returnValue.inversePatches) + api.util.patchQueryData('post', '3', returnValue.inversePatches), ) }) @@ -212,7 +218,7 @@ describe('updateQueryData', () => { provided = storeRef.store.getState().api.provided }) - const provided3 = provided['Post']['3'] + const provided3 = provided.Post['3'] let returnValue!: ReturnType> act(() => { @@ -227,8 +233,8 @@ describe('updateQueryData', () => { contents: 'TODO', }) }, - true - ) + true, + ), ) }) @@ -236,7 +242,7 @@ describe('updateQueryData', () => { provided = storeRef.store.getState().api.provided }) - const provided4 = provided['Post']['4'] + const provided4 = provided.Post['4'] expect(provided4).toEqual(provided3) @@ -248,12 +254,12 @@ describe('updateQueryData', () => { provided = storeRef.store.getState().api.provided }) - const provided4Next = provided['Post']['4'] + const provided4Next = provided.Post['4'] expect(provided4Next).toEqual([]) }) - test('updates (list) cache values excluding provided tags, undos that', async () => { + test('updates (list) cache values excluding provided tags, undoes that', async () => { baseQuery .mockResolvedValueOnce([ { @@ -286,8 +292,8 @@ describe('updateQueryData', () => { contents: 'TODO', }) }, - false - ) + false, + ), ) }) @@ -295,7 +301,7 @@ describe('updateQueryData', () => { provided = storeRef.store.getState().api.provided }) - const provided4 = provided['Post']['4'] + const provided4 = provided.Post['4'] expect(provided4).toEqual(undefined) @@ -307,7 +313,7 @@ describe('updateQueryData', () => { provided = storeRef.store.getState().api.provided }) - const provided4Next = provided['Post']['4'] + const provided4Next = provided.Post['4'] expect(provided4Next).toEqual(undefined) }) @@ -338,7 +344,7 @@ describe('updateQueryData', () => { returnValue = storeRef.store.dispatch( api.util.updateQueryData('post', '4', (draft) => { draft.contents = 'I love cheese!' - }) + }), ) }) @@ -378,7 +384,7 @@ describe('full integration', () => { }), { wrapper: storeRef.wrapper, - } + }, ) await hookWaitFor(() => expect(result.current.query.isSuccess).toBeTruthy()) @@ -403,7 +409,7 @@ describe('full integration', () => { id: '3', title: 'Meanwhile, this changed server-side.', contents: 'Delicious cheese!', - }) + }), ) }) @@ -429,7 +435,7 @@ describe('full integration', () => { }), { wrapper: storeRef.wrapper, - } + }, ) await hookWaitFor(() => expect(result.current.query.isSuccess).toBeTruthy()) @@ -456,7 +462,7 @@ describe('full integration', () => { id: '3', title: 'All about cheese.', contents: 'TODO', - }) + }), ) // mutation failed - will not invalidate query and not refetch data from the server @@ -468,8 +474,8 @@ describe('full integration', () => { title: 'Meanwhile, this changed server-side.', contents: 'TODO', }), - 50 - ) + 50, + ), ).rejects.toBeTruthy() act(() => void result.current.query.refetch()) @@ -482,7 +488,7 @@ describe('full integration', () => { title: 'Meanwhile, this changed server-side.', contents: 'TODO', }), - 50 + 50, ) }) }) diff --git a/packages/toolkit/src/query/tests/optimisticUpserts.test.tsx b/packages/toolkit/src/query/tests/optimisticUpserts.test.tsx index 1d67f0f1a0..2902b84ccb 100644 --- a/packages/toolkit/src/query/tests/optimisticUpserts.test.tsx +++ b/packages/toolkit/src/query/tests/optimisticUpserts.test.tsx @@ -1,9 +1,11 @@ -import { vi } from 'vitest' import { createApi } from '@reduxjs/toolkit/query/react' -import { actionsReducer, hookWaitFor, setupApiStore, waitMs } from './helpers' -import { skipToken } from '../core/buildSelectors' +import { + actionsReducer, + hookWaitFor, + setupApiStore, +} from '../../tests/utils/helpers' import { renderHook, act, waitFor } from '@testing-library/react' -import { delay } from '../../utils' +import { delay } from 'msw' interface Post { id: string @@ -42,7 +44,7 @@ const api = createApi({ api.util.upsertQueryData('post', arg.id, { ...currentItem.data, ...arg, - }) + }), ) } }, @@ -103,7 +105,7 @@ describe('basic lifecycle', () => { title: 'Inserted title', } const insertPromise = storeRef.store.dispatch( - api.util.upsertQueryData('post', newPost.id, newPost) + api.util.upsertQueryData('post', newPost.id, newPost), ) await insertPromise @@ -120,7 +122,7 @@ describe('basic lifecycle', () => { } const updatePromise = storeRef.store.dispatch( - api.util.upsertQueryData('post', updatedPost.id, updatedPost) + api.util.upsertQueryData('post', updatedPost.id, updatedPost), ) await updatePromise @@ -136,7 +138,7 @@ describe('basic lifecycle', () => { () => extendedApi.endpoints.test.useMutation(), { wrapper: storeRef.wrapper, - } + }, ) baseQuery.mockResolvedValue('success') @@ -149,7 +151,7 @@ describe('basic lifecycle', () => { expect(onError).not.toHaveBeenCalled() expect(onSuccess).not.toHaveBeenCalled() - await act(() => waitMs(5)) + await act(() => delay(5)) expect(onError).not.toHaveBeenCalled() expect(onSuccess).toHaveBeenCalledWith({ data: 'success', meta: 'meta' }) }) @@ -159,7 +161,7 @@ describe('basic lifecycle', () => { () => extendedApi.endpoints.test.useMutation(), { wrapper: storeRef.wrapper, - } + }, ) baseQuery.mockRejectedValueOnce('error') @@ -172,7 +174,7 @@ describe('basic lifecycle', () => { expect(onError).not.toHaveBeenCalled() expect(onSuccess).not.toHaveBeenCalled() - await act(() => waitMs(5)) + await act(() => delay(5)) expect(onError).toHaveBeenCalledWith({ error: 'error', isUnhandledError: false, @@ -212,7 +214,7 @@ describe('upsertQueryData', () => { id: '3', title: 'All about cheese.', contents: 'I love cheese!', - }) + }), ) }) @@ -240,7 +242,7 @@ describe('upsertQueryData', () => { () => api.endpoints.post.useQuery('4'), { wrapper: storeRef.wrapper, - } + }, ) await hookWaitFor(() => expect(result.current.isError).toBeTruthy()) @@ -251,7 +253,7 @@ describe('upsertQueryData', () => { id: '4', title: 'All about cheese', contents: 'I love cheese!', - }) + }), ) }) @@ -284,7 +286,7 @@ describe('upsertQueryData', () => { const selector = api.endpoints.post.select('3') const fetchRes = storeRef.store.dispatch(api.endpoints.post.initiate('3')) const upsertRes = storeRef.store.dispatch( - api.util.upsertQueryData('post', '3', upsertedData) + api.util.upsertQueryData('post', '3', upsertedData), ) await upsertRes @@ -310,7 +312,7 @@ describe('upsertQueryData', () => { const selector = api.endpoints.post.select('3') const fetchRes = storeRef.store.dispatch(api.endpoints.post.initiate('3')) const upsertRes = storeRef.store.dispatch( - api.util.upsertQueryData('post', '3', upsertedData) + api.util.upsertQueryData('post', '3', upsertedData), ) await upsertRes @@ -351,7 +353,7 @@ describe('full integration', () => { }), { wrapper: storeRef.wrapper, - } + }, ) await hookWaitFor(() => expect(result.current.query.isSuccess).toBeTruthy()) @@ -379,7 +381,7 @@ describe('full integration', () => { id: '3', title: 'Meanwhile, this changed server-side.', contents: 'Delicious cheese!', - }) + }), ) }) @@ -405,7 +407,7 @@ describe('full integration', () => { }), { wrapper: storeRef.wrapper, - } + }, ) await hookWaitFor(() => expect(result.current.query.isSuccess).toBeTruthy()) @@ -438,8 +440,8 @@ describe('full integration', () => { title: 'Meanwhile, this changed server-side.', contents: 'TODO', }), - 50 - ) + 50, + ), ).rejects.toBeTruthy() act(() => void result.current.query.refetch()) @@ -452,14 +454,14 @@ describe('full integration', () => { title: 'Meanwhile, this changed server-side.', contents: 'TODO', }), - 50 + 50, ) }) test('Interop with in-flight requests', async () => { await act(async () => { const fetchRes = storeRef.store.dispatch( - api.endpoints.post2.initiate('3') + api.endpoints.post2.initiate('3'), ) const upsertRes = storeRef.store.dispatch( @@ -467,7 +469,7 @@ describe('full integration', () => { id: '3', title: 'Upserted title', contents: 'Upserted contents', - }) + }), ) const selectEntry = api.endpoints.post2.select('3') @@ -480,7 +482,7 @@ describe('full integration', () => { contents: 'Upserted contents', }) }, - { interval: 1, timeout: 15 } + { interval: 1, timeout: 15 }, ) await waitFor( () => { @@ -491,7 +493,7 @@ describe('full integration', () => { contents: 'TODO', }) }, - { interval: 1 } + { interval: 1 }, ) }) }) diff --git a/packages/toolkit/src/query/tests/polling.test.tsx b/packages/toolkit/src/query/tests/polling.test.tsx index d5d3cd20f8..431b9ff1bb 100644 --- a/packages/toolkit/src/query/tests/polling.test.tsx +++ b/packages/toolkit/src/query/tests/polling.test.tsx @@ -1,7 +1,6 @@ -import { vi } from 'vitest' import { createApi } from '@reduxjs/toolkit/query' -import { setupApiStore, waitMs } from './helpers' -import { delay } from '../../utils' +import { delay } from 'msw' +import { setupApiStore } from '../../tests/utils/helpers' import type { SubscriptionSelectors } from '../core/buildMiddleware/types' const mockBaseQuery = vi @@ -28,7 +27,7 @@ let getSubscriptions: SubscriptionSelectors['getSubscriptions'] beforeEach(() => { ;({ getSubscriptions } = storeRef.store.dispatch( - api.internalActions.internal_getRTKQSubscriptions() + api.internalActions.internal_getRTKQSubscriptions(), ) as unknown as SubscriptionSelectors) }) @@ -43,14 +42,14 @@ describe('polling tests', () => { getPosts.initiate(1, { subscriptionOptions: { pollingInterval: 10 }, subscribe: true, - }) + }), ) expect(mockBaseQuery).toHaveBeenCalledTimes(1) storeRef.store.dispatch(api.util.resetApiState()) - await waitMs(30) + await delay(30) expect(mockBaseQuery).toHaveBeenCalledTimes(1) }) @@ -61,7 +60,7 @@ describe('polling tests', () => { getPosts.initiate(1, { subscriptionOptions: { pollingInterval: 10 }, subscribe: true, - }) + }), ) const getSubs = createSubscriptionGetter(queryCacheKey) @@ -82,14 +81,14 @@ describe('polling tests', () => { getPosts.initiate(1, { subscriptionOptions: { pollingInterval: 10 }, subscribe: true, - }) + }), ) storeRef.store.dispatch( getPosts.initiate(1, { subscriptionOptions: { pollingInterval: 10 }, subscribe: true, - }) + }), ) await delay(10) @@ -109,18 +108,126 @@ describe('polling tests', () => { getPosts.initiate(1, { subscriptionOptions: { pollingInterval: 30000 }, subscribe: true, - }) + }), ) storeRef.store.dispatch( getPosts.initiate(1, { subscriptionOptions: { pollingInterval: 10 }, subscribe: true, - }) + }), ) - await waitMs(20) + await delay(20) expect(mockBaseQuery.mock.calls.length).toBeGreaterThanOrEqual(2) }) + + it('respects skipPollingIfUnfocused', async () => { + mockBaseQuery.mockClear() + storeRef.store.dispatch( + getPosts.initiate(2, { + subscriptionOptions: { + pollingInterval: 10, + skipPollingIfUnfocused: true, + }, + subscribe: true, + }), + ) + storeRef.store.dispatch(api.internalActions?.onFocusLost()) + + await delay(50) + const callsWithSkip = mockBaseQuery.mock.calls.length + + storeRef.store.dispatch( + getPosts.initiate(2, { + subscriptionOptions: { + pollingInterval: 10, + skipPollingIfUnfocused: false, + }, + subscribe: true, + }), + ) + + storeRef.store.dispatch(api.internalActions?.onFocus()) + + await delay(50) + const callsWithoutSkip = mockBaseQuery.mock.calls.length + + expect(callsWithSkip).toBe(1) + expect(callsWithoutSkip).toBeGreaterThan(2) + + storeRef.store.dispatch(api.util.resetApiState()) + }) + + it('respects skipPollingIfUnfocused if at least one subscription has it', async () => { + storeRef.store.dispatch( + getPosts.initiate(3, { + subscriptionOptions: { + pollingInterval: 10, + skipPollingIfUnfocused: false, + }, + subscribe: true, + }), + ) + + await delay(50) + const callsWithoutSkip = mockBaseQuery.mock.calls.length + + storeRef.store.dispatch( + getPosts.initiate(3, { + subscriptionOptions: { + pollingInterval: 15, + skipPollingIfUnfocused: true, + }, + subscribe: true, + }), + ) + + storeRef.store.dispatch( + getPosts.initiate(3, { + subscriptionOptions: { + pollingInterval: 20, + skipPollingIfUnfocused: false, + }, + subscribe: true, + }), + ) + + storeRef.store.dispatch(api.internalActions?.onFocusLost()) + + await delay(50) + const callsWithSkip = mockBaseQuery.mock.calls.length + + expect(callsWithoutSkip).toBeGreaterThan(2) + expect(callsWithSkip).toBe(callsWithoutSkip + 1) + }) + + it('replaces skipPollingIfUnfocused when the subscription options are updated', async () => { + const { requestId, queryCacheKey, ...subscription } = + storeRef.store.dispatch( + getPosts.initiate(1, { + subscriptionOptions: { + pollingInterval: 10, + skipPollingIfUnfocused: false, + }, + subscribe: true, + }), + ) + + const getSubs = createSubscriptionGetter(queryCacheKey) + + await delay(1) + expect(Object.keys(getSubs())).toHaveLength(1) + expect(getSubs()[requestId].skipPollingIfUnfocused).toBe(false) + + subscription.updateSubscriptionOptions({ + pollingInterval: 20, + skipPollingIfUnfocused: true, + }) + + await delay(1) + expect(Object.keys(getSubs())).toHaveLength(1) + expect(getSubs()[requestId].skipPollingIfUnfocused).toBe(true) + }) }) diff --git a/packages/toolkit/src/query/tests/queryFn.test.tsx b/packages/toolkit/src/query/tests/queryFn.test.tsx index daf751c6a3..4b292f9983 100644 --- a/packages/toolkit/src/query/tests/queryFn.test.tsx +++ b/packages/toolkit/src/query/tests/queryFn.test.tsx @@ -1,19 +1,18 @@ -import { vi } from 'vitest' +import type { QuerySubState } from '@internal/query/core/apiState' +import type { Post } from '@internal/query/tests/mocks/handlers' +import { posts } from '@internal/query/tests/mocks/handlers' +import { actionsReducer, setupApiStore } from '@internal/tests/utils/helpers' import type { SerializedError } from '@reduxjs/toolkit' import { configureStore } from '@reduxjs/toolkit' import type { BaseQueryFn, FetchBaseQueryError } from '@reduxjs/toolkit/query' import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' -import type { Post } from './mocks/server' -import { posts } from './mocks/server' -import { actionsReducer, setupApiStore } from './helpers' -import type { QuerySubState } from '@reduxjs/toolkit/dist/query/core/apiState' describe('queryFn base implementation tests', () => { const baseQuery: BaseQueryFn = vi.fn((arg: string) => arg.includes('withErrorQuery') ? { error: `cut${arg}` } - : { data: { wrappedByBaseQuery: arg } } + : { data: { wrappedByBaseQuery: arg } }, ) const api = createApi({ @@ -194,19 +193,19 @@ describe('queryFn base implementation tests', () => { endpointName.includes('Throw') ? `An unhandled error occurred processing a request for the endpoint "${endpointName}". In the case of an unhandled error, no tags will be "provided" or "invalidated". [Error: resultFrom(${endpointName})]` - : '' + : '', ) if (expectedResult === 'data') { expect(result).toEqual( expect.objectContaining({ data: `resultFrom(${endpointName})`, - }) + }), ) } else if (expectedResult === 'error') { expect(result).toEqual( expect.objectContaining({ error: `resultFrom(${endpointName})`, - }) + }), ) } else { expect(result).toEqual( @@ -214,7 +213,7 @@ describe('queryFn base implementation tests', () => { error: expect.objectContaining({ message: `resultFrom(${endpointName})`, }), - }) + }), ) } }) @@ -242,20 +241,20 @@ describe('queryFn base implementation tests', () => { endpointName.includes('Throw') ? `An unhandled error occurred processing a request for the endpoint "${endpointName}". In the case of an unhandled error, no tags will be "provided" or "invalidated". [Error: resultFrom(${endpointName})]` - : '' + : '', ) if (expectedResult === 'data') { expect(result).toEqual( expect.objectContaining({ data: `resultFrom(${endpointName})`, - }) + }), ) } else if (expectedResult === 'error') { expect(result).toEqual( expect.objectContaining({ error: `resultFrom(${endpointName})`, - }) + }), ) } else { expect(result).toEqual( @@ -263,7 +262,7 @@ describe('queryFn base implementation tests', () => { error: expect.objectContaining({ message: `resultFrom(${endpointName})`, }), - }) + }), ) } }) @@ -276,12 +275,12 @@ describe('queryFn base implementation tests', () => { result = await store.dispatch(thunk) }).toHaveConsoleOutput( `An unhandled error occurred processing a request for the endpoint "withNeither". - In the case of an unhandled error, no tags will be "provided" or "invalidated". [TypeError: endpointDefinition.queryFn is not a function]` + In the case of an unhandled error, no tags will be "provided" or "invalidated". [TypeError: endpointDefinition.queryFn is not a function]`, ) expect(result!.error).toEqual( expect.objectContaining({ message: 'endpointDefinition.queryFn is not a function', - }) + }), ) } { @@ -294,12 +293,12 @@ describe('queryFn base implementation tests', () => { result = await store.dispatch(thunk) }).toHaveConsoleOutput( `An unhandled error occurred processing a request for the endpoint "mutationWithNeither". - In the case of an unhandled error, no tags will be "provided" or "invalidated". [TypeError: endpointDefinition.queryFn is not a function]` + In the case of an unhandled error, no tags will be "provided" or "invalidated". [TypeError: endpointDefinition.queryFn is not a function]`, ) expect((result as any).error).toEqual( expect.objectContaining({ message: 'endpointDefinition.queryFn is not a function', - }) + }), ) } }) @@ -373,14 +372,14 @@ describe('usage scenario tests', () => { it('can chain multiple queries together', async () => { const result = await storeRef.store.dispatch( - api.endpoints.getRandomUser.initiate() + api.endpoints.getRandomUser.initiate(), ) expect(result.data).toEqual(posts[1]) }) it('can wrap a service like Firebase', async () => { const result = await storeRef.store.dispatch( - api.endpoints.getFirebaseUser.initiate(1) + api.endpoints.getFirebaseUser.initiate(1), ) expect(result.data).toEqual(mockData) }) @@ -389,7 +388,7 @@ describe('usage scenario tests', () => { let result: QuerySubState await expect(async () => { result = await storeRef.store.dispatch( - api.endpoints.getMissingFirebaseUser.initiate(1) + api.endpoints.getMissingFirebaseUser.initiate(1), ) }) .toHaveConsoleOutput(`An unhandled error occurred processing a request for the endpoint "getMissingFirebaseUser". @@ -400,7 +399,7 @@ describe('usage scenario tests', () => { expect.objectContaining({ message: 'Missing user', name: 'Error', - }) + }), ) }) }) diff --git a/packages/toolkit/src/query/tests/queryLifecycle.test-d.tsx b/packages/toolkit/src/query/tests/queryLifecycle.test-d.tsx new file mode 100644 index 0000000000..983de884f4 --- /dev/null +++ b/packages/toolkit/src/query/tests/queryLifecycle.test-d.tsx @@ -0,0 +1,151 @@ +import type { + FetchBaseQueryError, + FetchBaseQueryMeta, +} from '@reduxjs/toolkit/query' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' + +const api = createApi({ + baseQuery: fetchBaseQuery({ baseUrl: 'https://example.com' }), + endpoints: () => ({}), +}) + +describe('type tests', () => { + test(`mutation: onStart and onSuccess`, async () => { + const extended = api.injectEndpoints({ + overrideExisting: true, + endpoints: (build) => ({ + injected: build.mutation({ + query: () => '/success', + async onQueryStarted(arg, { queryFulfilled }) { + // awaiting without catching like this would result in an `unhandledRejection` exception if there was an error + // unfortunately we cannot test for that in jest. + const result = await queryFulfilled + + expectTypeOf(result).toMatchTypeOf<{ + data: number + meta?: FetchBaseQueryMeta + }>() + }, + }), + }), + }) + }) + + test('query types', () => { + const extended = api.injectEndpoints({ + overrideExisting: true, + endpoints: (build) => ({ + injected: build.query({ + query: () => '/success', + async onQueryStarted(arg, { queryFulfilled }) { + queryFulfilled.then( + (result) => { + expectTypeOf(result).toMatchTypeOf<{ + data: number + meta?: FetchBaseQueryMeta + }>() + }, + (reason) => { + if (reason.isUnhandledError) { + expectTypeOf(reason).toEqualTypeOf<{ + error: unknown + meta?: undefined + isUnhandledError: true + }>() + } else { + expectTypeOf(reason).toEqualTypeOf<{ + error: FetchBaseQueryError + isUnhandledError: false + meta: FetchBaseQueryMeta | undefined + }>() + } + }, + ) + + queryFulfilled.catch((reason) => { + if (reason.isUnhandledError) { + expectTypeOf(reason).toEqualTypeOf<{ + error: unknown + meta?: undefined + isUnhandledError: true + }>() + } else { + expectTypeOf(reason).toEqualTypeOf<{ + error: FetchBaseQueryError + isUnhandledError: false + meta: FetchBaseQueryMeta | undefined + }>() + } + }) + + const result = await queryFulfilled + + expectTypeOf(result).toMatchTypeOf<{ + data: number + meta?: FetchBaseQueryMeta + }>() + }, + }), + }), + }) + }) + + test('mutation types', () => { + const extended = api.injectEndpoints({ + overrideExisting: true, + endpoints: (build) => ({ + injected: build.query({ + query: () => '/success', + async onQueryStarted(arg, { queryFulfilled }) { + queryFulfilled.then( + (result) => { + expectTypeOf(result).toMatchTypeOf<{ + data: number + meta?: FetchBaseQueryMeta + }>() + }, + (reason) => { + if (reason.isUnhandledError) { + expectTypeOf(reason).toEqualTypeOf<{ + error: unknown + meta?: undefined + isUnhandledError: true + }>() + } else { + expectTypeOf(reason).toEqualTypeOf<{ + error: FetchBaseQueryError + isUnhandledError: false + meta: FetchBaseQueryMeta | undefined + }>() + } + }, + ) + + queryFulfilled.catch((reason) => { + if (reason.isUnhandledError) { + expectTypeOf(reason).toEqualTypeOf<{ + error: unknown + meta?: undefined + isUnhandledError: true + }>() + } else { + expectTypeOf(reason).toEqualTypeOf<{ + error: FetchBaseQueryError + isUnhandledError: false + meta: FetchBaseQueryMeta | undefined + }>() + } + }) + + const result = await queryFulfilled + + expectTypeOf(result).toMatchTypeOf<{ + data: number + meta?: FetchBaseQueryMeta + }>() + }, + }), + }), + }) + }) +}) diff --git a/packages/toolkit/src/query/tests/queryLifecycle.test.tsx b/packages/toolkit/src/query/tests/queryLifecycle.test.tsx index d3099799b8..b0396e9b0c 100644 --- a/packages/toolkit/src/query/tests/queryLifecycle.test.tsx +++ b/packages/toolkit/src/query/tests/queryLifecycle.test.tsx @@ -1,14 +1,9 @@ -import { vi } from 'vitest' -import { createApi } from '@reduxjs/toolkit/query' +import { server } from '@internal/query/tests/mocks/server' +import { setupApiStore } from '@internal/tests/utils/helpers' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' import { waitFor } from '@testing-library/react' -import type { - FetchBaseQueryMeta, - FetchBaseQueryError, -} from '@reduxjs/toolkit/query' -import { fetchBaseQuery } from '@reduxjs/toolkit/query' -import { expectType, setupApiStore } from './helpers' -import { server } from './mocks/server' -import { rest } from 'msw' +import { HttpResponse, http } from 'msw' +import { vi } from 'vitest' const api = createApi({ baseQuery: fetchBaseQuery({ baseUrl: 'https://example.com' }), @@ -56,7 +51,6 @@ describe.each([['query'], ['mutation']] as const)( // awaiting without catching like this would result in an `unhandledRejection` exception if there was an error // unfortunately we cannot test for that in jest. const result = await queryFulfilled - expectType<{ data: number; meta?: FetchBaseQueryMeta }>(result) onSuccess(result) }, }), @@ -110,7 +104,7 @@ describe.each([['query'], ['mutation']] as const)( }) expect(onSuccess).not.toHaveBeenCalled() }) - } + }, ) test('query: getCacheEntry (success)', async () => { @@ -122,7 +116,7 @@ test('query: getCacheEntry (success)', async () => { query: () => '/success', async onQueryStarted( arg, - { dispatch, getState, getCacheEntry, queryFulfilled } + { dispatch, getState, getCacheEntry, queryFulfilled }, ) { try { snapshot(getCacheEntry()) @@ -138,7 +132,7 @@ test('query: getCacheEntry (success)', async () => { }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) await waitFor(() => { @@ -183,7 +177,7 @@ test('query: getCacheEntry (error)', async () => { query: () => '/error', async onQueryStarted( arg, - { dispatch, getState, getCacheEntry, queryFulfilled } + { dispatch, getState, getCacheEntry, queryFulfilled }, ) { try { snapshot(getCacheEntry()) @@ -199,7 +193,7 @@ test('query: getCacheEntry (error)', async () => { }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) await waitFor(() => { @@ -243,7 +237,7 @@ test('mutation: getCacheEntry (success)', async () => { query: () => '/success', async onQueryStarted( arg, - { dispatch, getState, getCacheEntry, queryFulfilled } + { dispatch, getState, getCacheEntry, queryFulfilled }, ) { try { snapshot(getCacheEntry()) @@ -259,7 +253,7 @@ test('mutation: getCacheEntry (success)', async () => { }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) await waitFor(() => { @@ -300,7 +294,7 @@ test('mutation: getCacheEntry (error)', async () => { query: () => '/error', async onQueryStarted( arg, - { dispatch, getState, getCacheEntry, queryFulfilled } + { dispatch, getState, getCacheEntry, queryFulfilled }, ) { try { snapshot(getCacheEntry()) @@ -316,7 +310,7 @@ test('mutation: getCacheEntry (error)', async () => { }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) await waitFor(() => { @@ -363,7 +357,7 @@ test('query: updateCachedData', async () => { getCacheEntry, updateCachedData, queryFulfilled, - } + }, ) { // calling `updateCachedData` when there is no data yet should not do anything // but if there is a cache value it will be updated & overwritten by the next succesful result @@ -398,12 +392,16 @@ test('query: updateCachedData', async () => { // request 2: error expect(onError).not.toHaveBeenCalled() server.use( - rest.get('https://example.com/success', (_, req, ctx) => - req.once(ctx.status(500), ctx.json({ value: 'failed' })) - ) + http.get( + 'https://example.com/success', + () => { + return HttpResponse.json({ value: 'failed' }, { status: 500 }) + }, + { once: true }, + ), ) storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg', { forceRefetch: true }) + extended.endpoints.injected.initiate('arg', { forceRefetch: true }), ) await waitFor(() => { @@ -415,7 +413,7 @@ test('query: updateCachedData', async () => { expect(onSuccess).not.toHaveBeenCalled() storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg', { forceRefetch: true }) + extended.endpoints.injected.initiate('arg', { forceRefetch: true }), ) await waitFor(() => { @@ -438,122 +436,14 @@ test('query: will only start lifecycle if query is not skipped due to `condition }), }) const promise = storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg') + extended.endpoints.injected.initiate('arg'), ) expect(onStart).toHaveBeenCalledTimes(1) storeRef.store.dispatch(extended.endpoints.injected.initiate('arg')) expect(onStart).toHaveBeenCalledTimes(1) await promise storeRef.store.dispatch( - extended.endpoints.injected.initiate('arg', { forceRefetch: true }) + extended.endpoints.injected.initiate('arg', { forceRefetch: true }), ) expect(onStart).toHaveBeenCalledTimes(2) }) - -test('query types', () => { - const extended = api.injectEndpoints({ - overrideExisting: true, - endpoints: (build) => ({ - injected: build['query']({ - query: () => '/success', - async onQueryStarted(arg, { queryFulfilled }) { - onStart(arg) - - queryFulfilled.then( - (result) => { - expectType<{ data: number; meta?: FetchBaseQueryMeta }>(result) - }, - (reason) => { - if (reason.isUnhandledError) { - expectType<{ - error: unknown - meta?: undefined - isUnhandledError: true - }>(reason) - } else { - expectType<{ - error: FetchBaseQueryError - isUnhandledError: false - meta: FetchBaseQueryMeta | undefined - }>(reason) - } - } - ) - - queryFulfilled.catch((reason) => { - if (reason.isUnhandledError) { - expectType<{ - error: unknown - meta?: undefined - isUnhandledError: true - }>(reason) - } else { - expectType<{ - error: FetchBaseQueryError - isUnhandledError: false - meta: FetchBaseQueryMeta | undefined - }>(reason) - } - }) - - const result = await queryFulfilled - expectType<{ data: number; meta?: FetchBaseQueryMeta }>(result) - }, - }), - }), - }) -}) - -test('mutation types', () => { - const extended = api.injectEndpoints({ - overrideExisting: true, - endpoints: (build) => ({ - injected: build['query']({ - query: () => '/success', - async onQueryStarted(arg, { queryFulfilled }) { - onStart(arg) - - queryFulfilled.then( - (result) => { - expectType<{ data: number; meta?: FetchBaseQueryMeta }>(result) - }, - (reason) => { - if (reason.isUnhandledError) { - expectType<{ - error: unknown - meta?: undefined - isUnhandledError: true - }>(reason) - } else { - expectType<{ - error: FetchBaseQueryError - isUnhandledError: false - meta: FetchBaseQueryMeta | undefined - }>(reason) - } - } - ) - - queryFulfilled.catch((reason) => { - if (reason.isUnhandledError) { - expectType<{ - error: unknown - meta?: undefined - isUnhandledError: true - }>(reason) - } else { - expectType<{ - error: FetchBaseQueryError - isUnhandledError: false - meta: FetchBaseQueryMeta | undefined - }>(reason) - } - }) - - const result = await queryFulfilled - expectType<{ data: number; meta?: FetchBaseQueryMeta }>(result) - }, - }), - }), - }) -}) diff --git a/packages/toolkit/src/query/tests/raceConditions.test.ts b/packages/toolkit/src/query/tests/raceConditions.test.ts index 0ec49da2fb..3178f42666 100644 --- a/packages/toolkit/src/query/tests/raceConditions.test.ts +++ b/packages/toolkit/src/query/tests/raceConditions.test.ts @@ -1,6 +1,6 @@ import { createApi, QueryStatus } from '@reduxjs/toolkit/query' -import { getLog } from 'console-testing-library' -import { actionsReducer, setupApiStore, waitMs } from './helpers' +import { delay } from 'msw' +import { actionsReducer, setupApiStore } from '../../tests/utils/helpers' // We need to be able to control when which query resolves to simulate race // conditions properly, that's the purpose of this factory. @@ -59,7 +59,7 @@ it('invalidates a query after a corresponding mutation', async () => { const getQueryState = () => storeRef.store.getState().api.queries[query.queryCacheKey] getEatenBananaPromises.resolveOldest() - await waitMs(2) + await delay(2) expect(getQueryState()?.data).toBe(0) expect(getQueryState()?.status).toBe(QueryStatus.fulfilled) @@ -68,14 +68,14 @@ it('invalidates a query after a corresponding mutation', async () => { const getMutationState = () => storeRef.store.getState().api.mutations[mutation.requestId] eatBananaPromises.resolveOldest() - await waitMs(2) + await delay(2) expect(getMutationState()?.status).toBe(QueryStatus.fulfilled) expect(getQueryState()?.data).toBe(0) expect(getQueryState()?.status).toBe(QueryStatus.pending) getEatenBananaPromises.resolveOldest() - await waitMs(2) + await delay(2) expect(getQueryState()?.data).toBe(1) expect(getQueryState()?.status).toBe(QueryStatus.fulfilled) @@ -92,17 +92,17 @@ it('invalidates a query whose corresponding mutation finished while the query wa const getMutationState = () => storeRef.store.getState().api.mutations[mutation.requestId] eatBananaPromises.resolveOldest() - await waitMs(2) + await delay(2) expect(getMutationState()?.status).toBe(QueryStatus.fulfilled) getEatenBananaPromises.resolveOldest() - await waitMs(2) + await delay(2) expect(getQueryState()?.data).toBe(0) expect(getQueryState()?.status).toBe(QueryStatus.pending) // should already be refetching getEatenBananaPromises.resolveOldest() - await waitMs(2) + await delay(2) expect(getQueryState()?.status).toBe(QueryStatus.fulfilled) expect(getQueryState()?.data).toBe(1) diff --git a/packages/toolkit/src/query/tests/refetchingBehaviors.test.tsx b/packages/toolkit/src/query/tests/refetchingBehaviors.test.tsx index f2703e5b56..be27d08d9f 100644 --- a/packages/toolkit/src/query/tests/refetchingBehaviors.test.tsx +++ b/packages/toolkit/src/query/tests/refetchingBehaviors.test.tsx @@ -1,9 +1,7 @@ -import { vi } from 'vitest' -import * as React from 'react' import { createApi, setupListeners } from '@reduxjs/toolkit/query/react' -import { act, fireEvent, render, waitFor, screen } from '@testing-library/react' -import { setupApiStore, waitMs } from './helpers' -import { delay } from '../../utils' +import { act, fireEvent, render, screen, waitFor } from '@testing-library/react' +import { delay } from 'msw' +import { setupApiStore } from '../../tests/utils/helpers' // Just setup a temporary in-memory counter for tests that `getIncrementedAmount`. // This can be used to test how many renders happen due to data changes or @@ -12,7 +10,7 @@ let amount = 0 const defaultApi = createApi({ baseQuery: async (arg: any) => { - await waitMs() + await delay(150) if ('amount' in arg?.body) { amount += 1 } @@ -38,7 +36,7 @@ const defaultApi = createApi({ const storeRef = setupApiStore(defaultApi) -let getIncrementedAmountState = () => +const getIncrementedAmountState = () => storeRef.store.getState().api.queries['getIncrementedAmount(undefined)'] afterEach(() => { @@ -64,23 +62,23 @@ describe('refetchOnFocus tests', () => { render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) await act(async () => { fireEvent.focus(window) }) - await waitMs() + await delay(150) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('2') + expect(screen.getByTestId('amount').textContent).toBe('2'), ) }) @@ -104,23 +102,23 @@ describe('refetchOnFocus tests', () => { render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) act(() => { fireEvent.focus(window) }) - await waitMs() + await delay(150) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) }) @@ -154,17 +152,17 @@ describe('refetchOnFocus tests', () => { , - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) act(() => { @@ -172,13 +170,13 @@ describe('refetchOnFocus tests', () => { }) expect(screen.getByTestId('isLoading').textContent).toBe('false') await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('2') + expect(screen.getByTestId('amount').textContent).toBe('2'), ) }) @@ -202,13 +200,13 @@ describe('refetchOnFocus tests', () => { const { unmount } = render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) unmount() @@ -243,13 +241,13 @@ describe('refetchOnReconnect tests', () => { render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) act(() => { @@ -258,13 +256,13 @@ describe('refetchOnReconnect tests', () => { }) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('2') + expect(screen.getByTestId('amount').textContent).toBe('2'), ) }) @@ -288,13 +286,13 @@ describe('refetchOnReconnect tests', () => { render(, { wrapper: storeRef.wrapper }) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) act(() => { @@ -303,7 +301,7 @@ describe('refetchOnReconnect tests', () => { }) expect(screen.getByTestId('isFetching').textContent).toBe('false') await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) }) @@ -337,17 +335,17 @@ describe('refetchOnReconnect tests', () => { , - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) act(() => { @@ -356,13 +354,13 @@ describe('refetchOnReconnect tests', () => { }) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('2') + expect(screen.getByTestId('amount').textContent).toBe('2'), ) }) }) @@ -391,10 +389,10 @@ describe('customListenersHandler', () => { window.removeEventListener('online', handleOnline) console.log('cleanup!') } - } + }, ) - await waitMs() + await delay(150) let data, isLoading, isFetching @@ -417,13 +415,13 @@ describe('customListenersHandler', () => { expect(consoleSpy).toHaveBeenCalledWith('setup!') await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('true') + expect(screen.getByTestId('isLoading').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isLoading').textContent).toBe('false') + expect(screen.getByTestId('isLoading').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('1') + expect(screen.getByTestId('amount').textContent).toBe('1'), ) act(() => { @@ -441,18 +439,18 @@ describe('customListenersHandler', () => { expect( defaultApi.internalActions.onOnline.match( - mockCallsWithoutInternals[1][0] as any - ) + mockCallsWithoutInternals[1][0] as any, + ), ).toBe(true) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('true') + expect(screen.getByTestId('isFetching').textContent).toBe('true'), ) await waitFor(() => - expect(screen.getByTestId('isFetching').textContent).toBe('false') + expect(screen.getByTestId('isFetching').textContent).toBe('false'), ) await waitFor(() => - expect(screen.getByTestId('amount').textContent).toBe('2') + expect(screen.getByTestId('amount').textContent).toBe('2'), ) unsubscribe() diff --git a/packages/toolkit/src/query/tests/retry.test-d.ts b/packages/toolkit/src/query/tests/retry.test-d.ts new file mode 100644 index 0000000000..26a9eb210f --- /dev/null +++ b/packages/toolkit/src/query/tests/retry.test-d.ts @@ -0,0 +1,19 @@ +import type { RetryOptions } from '@internal/query/retry' + +describe('type tests', () => { + test('RetryOptions only accepts one of maxRetries or retryCondition', () => { + // Should not complain if only `maxRetries` exists + expectTypeOf({ maxRetries: 5 }).toMatchTypeOf() + + // Should not complain if only `retryCondition` exists + expectTypeOf({ retryCondition: () => false }).toMatchTypeOf() + + // Should complain if both `maxRetries` and `retryCondition` exist at once + expectTypeOf({ + maxRetries: 5, + retryCondition: () => false, + }).not.toMatchTypeOf() + }) +}) + +export {} diff --git a/packages/toolkit/src/query/tests/retry.test.ts b/packages/toolkit/src/query/tests/retry.test.ts index 2bb35e89ae..dcc3ac8415 100644 --- a/packages/toolkit/src/query/tests/retry.test.ts +++ b/packages/toolkit/src/query/tests/retry.test.ts @@ -1,8 +1,6 @@ -import { vi } from 'vitest' import type { BaseQueryFn } from '@reduxjs/toolkit/query' import { createApi, retry } from '@reduxjs/toolkit/query' -import { setupApiStore, waitMs } from './helpers' -import type { RetryOptions } from '../retry' +import { setupApiStore } from '../../tests/utils/helpers' beforeEach(() => { vi.useFakeTimers() @@ -12,13 +10,11 @@ const loopTimers = async (max: number = 12) => { let count = 0 while (count < max) { await vi.advanceTimersByTimeAsync(1) - vi.advanceTimersByTime(120000) + vi.advanceTimersByTime(120_000) count++ } } -vi.fn() - describe('configuration', () => { test('retrying without any config options', async () => { const baseBaseQuery = vi.fn< @@ -321,7 +317,7 @@ describe('configuration', () => { const attempts = Math.min(attempt, maxRetries) const timeout = attempts * 300 // Scale up by 300ms per request, ex: 300ms, 600ms, 900ms, 1200ms... await new Promise((resolve) => - setTimeout((res: any) => resolve(res), timeout) + setTimeout((res: any) => resolve(res), timeout), ) }, }) @@ -468,12 +464,4 @@ describe('configuration', () => { expect(baseBaseQuery).toHaveBeenCalledTimes(1) }) - - test.skip('RetryOptions only accepts one of maxRetries or retryCondition', () => { - // @ts-expect-error Should complain if both exist at once - const ro: RetryOptions = { - maxRetries: 5, - retryCondition: () => false, - } - }) }) diff --git a/packages/toolkit/src/query/tests/tsconfig.json b/packages/toolkit/src/query/tests/tsconfig.json deleted file mode 100644 index 105334e225..0000000000 --- a/packages/toolkit/src/query/tests/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../../../tsconfig.test.json" -} diff --git a/packages/toolkit/src/query/tests/tsconfig.typetests.json b/packages/toolkit/src/query/tests/tsconfig.typetests.json deleted file mode 100644 index 6616cca002..0000000000 --- a/packages/toolkit/src/query/tests/tsconfig.typetests.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "../../../tsconfig.test.json", - "compilerOptions": { - "skipLibCheck": true - } -} diff --git a/packages/toolkit/src/query/tests/unionTypes.test-d.ts b/packages/toolkit/src/query/tests/unionTypes.test-d.ts new file mode 100644 index 0000000000..d47cdae41b --- /dev/null +++ b/packages/toolkit/src/query/tests/unionTypes.test-d.ts @@ -0,0 +1,778 @@ +import type { SerializedError } from '@reduxjs/toolkit' +import type { + FetchBaseQueryError, + TypedUseMutationResult, + TypedUseQueryHookResult, + TypedUseQueryStateResult, + TypedUseQuerySubscriptionResult, +} from '@reduxjs/toolkit/query/react' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' + +const baseQuery = fetchBaseQuery() + +const api = createApi({ + baseQuery, + endpoints: (build) => ({ + getTest: build.query({ query: () => '' }), + mutation: build.mutation({ query: () => '' }), + }), +}) + +describe('union types', () => { + test('query selector union', () => { + const result = api.endpoints.getTest.select()({} as any) + + if (result.isUninitialized) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + } + + if (result.isLoading) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError | undefined + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + } + + if (result.isError) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + } + + if (result.isSuccess) { + expectTypeOf(result.data).toBeString() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + } + + expectTypeOf(result).not.toBeNever() + + // is always one of those four + if ( + !result.isUninitialized && + !result.isLoading && + !result.isError && + !result.isSuccess + ) { + expectTypeOf(result).toBeNever() + } + }) + + test('useQuery union', () => { + const result = api.endpoints.getTest.useQuery() + + if (result.isUninitialized) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toEqualTypeOf() + } + + if (result.isLoading) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError | undefined + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toBeBoolean() + } + + if (result.isError) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toEqualTypeOf() + } + + if (result.isSuccess) { + expectTypeOf(result.data).toBeString() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isFetching).toBeBoolean() + } + + if (result.isFetching) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError | undefined + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toBeBoolean() + + expectTypeOf(result.isSuccess).toBeBoolean() + + expectTypeOf(result.isError).toEqualTypeOf() + } + + expectTypeOf(result.currentData).toEqualTypeOf() + + if (result.isSuccess) { + if (!result.isFetching) { + expectTypeOf(result.currentData).toBeString() + } else { + expectTypeOf(result.currentData).toEqualTypeOf() + } + } + + expectTypeOf(result).not.toBeNever() + + // is always one of those four + if ( + !result.isUninitialized && + !result.isLoading && + !result.isError && + !result.isSuccess + ) { + expectTypeOf(result).toBeNever() + } + }) + test('useQuery TS4.1 union', () => { + const result = api.useGetTestQuery() + + if (result.isUninitialized) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toEqualTypeOf() + } + + if (result.isLoading) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError | undefined + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toBeBoolean() + } + + if (result.isError) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toEqualTypeOf() + } + + if (result.isSuccess) { + expectTypeOf(result.data).toBeString() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isFetching).toBeBoolean() + } + + if (result.isFetching) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError | undefined + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toBeBoolean() + + expectTypeOf(result.isSuccess).toBeBoolean() + + expectTypeOf(result.isError).toEqualTypeOf() + } + + expectTypeOf(result).not.toBeNever() + + // is always one of those four + if ( + !result.isUninitialized && + !result.isLoading && + !result.isError && + !result.isSuccess + ) { + expectTypeOf(result).toBeNever() + } + }) + + test('useLazyQuery union', () => { + const [_trigger, result] = api.endpoints.getTest.useLazyQuery() + + if (result.isUninitialized) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toEqualTypeOf() + } + + if (result.isLoading) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError | undefined + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toBeBoolean() + } + + if (result.isError) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toEqualTypeOf() + } + + if (result.isSuccess) { + expectTypeOf(result.data).toBeString() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isFetching).toBeBoolean() + } + + if (result.isFetching) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError | undefined + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toBeBoolean() + + expectTypeOf(result.isSuccess).toBeBoolean() + + expectTypeOf(result.isError).toEqualTypeOf() + } + + expectTypeOf(result).not.toBeNever() + + // is always one of those four + if ( + !result.isUninitialized && + !result.isLoading && + !result.isError && + !result.isSuccess + ) { + expectTypeOf(result).toBeNever() + } + }) + + test('useLazyQuery TS4.1 union', () => { + const [_trigger, result] = api.useLazyGetTestQuery() + + if (result.isUninitialized) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toEqualTypeOf() + } + + if (result.isLoading) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError | undefined + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toBeBoolean() + } + + if (result.isError) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + + expectTypeOf(result.isFetching).toEqualTypeOf() + } + + if (result.isSuccess) { + expectTypeOf(result.data).toBeString() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isFetching).toBeBoolean() + } + + if (result.isFetching) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError | undefined + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toBeBoolean() + + expectTypeOf(result.isSuccess).toBeBoolean() + + expectTypeOf(result.isError).toEqualTypeOf() + } + + expectTypeOf(result).not.toBeNever() + + // is always one of those four + if ( + !result.isUninitialized && + !result.isLoading && + !result.isError && + !result.isSuccess + ) { + expectTypeOf(result).toBeNever() + } + }) + + test('queryHookResult (without selector) union', async () => { + const useQueryStateResult = api.endpoints.getTest.useQueryState() + + const useQueryResult = api.endpoints.getTest.useQuery() + + const useQueryStateWithSelectFromResult = + api.endpoints.getTest.useQueryState(undefined, { + selectFromResult: () => ({ x: true }), + }) + + const { refetch, ...useQueryResultWithoutMethods } = useQueryResult + + assertType(useQueryStateResult) + + expectTypeOf(useQueryStateResult).toMatchTypeOf( + useQueryResultWithoutMethods, + ) + + expectTypeOf(useQueryStateWithSelectFromResult) + .parameter(0) + .not.toMatchTypeOf(useQueryResultWithoutMethods) + + expectTypeOf(api.endpoints.getTest.select).returns.returns.toEqualTypeOf< + Awaited> + >() + }) + + test('useQueryState (with selectFromResult)', () => { + const result = api.endpoints.getTest.useQueryState(undefined, { + selectFromResult({ + data, + isLoading, + isFetching, + isError, + isSuccess, + isUninitialized, + }) { + return { + data: data ?? 1, + isLoading, + isFetching, + isError, + isSuccess, + isUninitialized, + } + }, + }) + + expectTypeOf({ + data: '' as string | number, + isUninitialized: false, + isLoading: true, + isFetching: true, + isSuccess: false, + isError: false, + }).toEqualTypeOf(result) + }) + + test('useQuery (with selectFromResult)', async () => { + const { refetch, ...result } = api.endpoints.getTest.useQuery(undefined, { + selectFromResult({ + data, + isLoading, + isFetching, + isError, + isSuccess, + isUninitialized, + }) { + return { + data: data ?? 1, + isLoading, + isFetching, + isError, + isSuccess, + isUninitialized, + } + }, + }) + + expectTypeOf({ + data: '' as string | number, + isUninitialized: false, + isLoading: true, + isFetching: true, + isSuccess: false, + isError: false, + }).toEqualTypeOf(result) + + expectTypeOf(api.endpoints.getTest.select).returns.returns.toEqualTypeOf< + Awaited> + >() + }) + + test('useMutation union', () => { + const [_trigger, result] = api.endpoints.mutation.useMutation() + + if (result.isUninitialized) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + } + + if (result.isLoading) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError | undefined + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + } + + if (result.isError) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + } + + if (result.isSuccess) { + expectTypeOf(result.data).toBeString() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + } + + expectTypeOf(result).not.toBeNever() + + // is always one of those four + if ( + !result.isUninitialized && + !result.isLoading && + !result.isError && + !result.isSuccess + ) { + expectTypeOf(result).toBeNever() + } + }) + + test('useMutation (with selectFromResult)', () => { + const [_trigger, result] = api.endpoints.mutation.useMutation({ + selectFromResult({ + data, + isLoading, + isError, + isSuccess, + isUninitialized, + }) { + return { + data: data ?? 'hi', + isLoading, + isError, + isSuccess, + isUninitialized, + } + }, + }) + + expectTypeOf({ + data: '' as string, + isUninitialized: false, + isLoading: true, + isSuccess: false, + isError: false, + reset: () => {}, + }).toMatchTypeOf(result) + }) + + test('useMutation TS4.1 union', () => { + const [_trigger, result] = api.useMutationMutation() + + if (result.isUninitialized) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + } + + if (result.isLoading) { + expectTypeOf(result.data).toBeUndefined() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError | undefined + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + } + + if (result.isError) { + expectTypeOf(result.data).toEqualTypeOf() + + expectTypeOf(result.error).toEqualTypeOf< + SerializedError | FetchBaseQueryError + >() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isSuccess).toEqualTypeOf() + } + + if (result.isSuccess) { + expectTypeOf(result.data).toBeString() + + expectTypeOf(result.error).toBeUndefined() + + expectTypeOf(result.isUninitialized).toEqualTypeOf() + + expectTypeOf(result.isLoading).toEqualTypeOf() + + expectTypeOf(result.isError).toEqualTypeOf() + } + + expectTypeOf(result).not.toBeNever() + + // is always one of those four + if ( + !result.isUninitialized && + !result.isLoading && + !result.isError && + !result.isSuccess + ) { + expectTypeOf(result).toBeNever() + } + }) +}) + +describe('"Typed" helper types', () => { + test('useQuery', () => { + const result = api.endpoints.getTest.useQuery() + + expectTypeOf< + TypedUseQueryHookResult + >().toEqualTypeOf(result) + }) + + test('useQuery with selectFromResult', () => { + const result = api.endpoints.getTest.useQuery(undefined, { + selectFromResult: () => ({ x: true }), + }) + + expectTypeOf< + TypedUseQueryHookResult + >().toEqualTypeOf(result) + }) + + test('useQueryState', () => { + const result = api.endpoints.getTest.useQueryState() + + expectTypeOf< + TypedUseQueryStateResult + >().toEqualTypeOf(result) + }) + + test('useQueryState with selectFromResult', () => { + const result = api.endpoints.getTest.useQueryState(undefined, { + selectFromResult: () => ({ x: true }), + }) + + expectTypeOf< + TypedUseQueryStateResult + >().toEqualTypeOf(result) + }) + + test('useQuerySubscription', () => { + const result = api.endpoints.getTest.useQuerySubscription() + + expectTypeOf< + TypedUseQuerySubscriptionResult + >().toEqualTypeOf(result) + }) + + test('useMutation', () => { + const [trigger, result] = api.endpoints.mutation.useMutation() + + expectTypeOf< + TypedUseMutationResult + >().toMatchTypeOf(result) + }) +}) diff --git a/packages/toolkit/src/query/tests/unionTypes.test.ts b/packages/toolkit/src/query/tests/unionTypes.test.ts deleted file mode 100644 index eaceba0b68..0000000000 --- a/packages/toolkit/src/query/tests/unionTypes.test.ts +++ /dev/null @@ -1,611 +0,0 @@ -import type { SerializedError } from '@reduxjs/toolkit' -import type { - FetchBaseQueryError, - TypedUseQueryHookResult, - TypedUseQueryStateResult, - TypedUseQuerySubscriptionResult, - TypedUseMutationResult, -} from '@reduxjs/toolkit/query/react' -import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' -import { expectExactType, expectType } from './helpers' - -const baseQuery = fetchBaseQuery() -const api = createApi({ - baseQuery, - endpoints: (build) => ({ - test: build.query({ query: () => '' }), - mutation: build.mutation({ query: () => '' }), - }), -}) - -describe.skip('TS only tests', () => { - test('query selector union', () => { - const result = api.endpoints.test.select()({} as any) - - if (result.isUninitialized) { - expectExactType(undefined)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - } - if (result.isLoading) { - expectExactType('' as string | undefined)(result.data) - expectExactType( - undefined as SerializedError | FetchBaseQueryError | undefined - )(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - } - if (result.isError) { - expectExactType('' as string | undefined)(result.data) - expectExactType({} as SerializedError | FetchBaseQueryError)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isSuccess) - } - if (result.isSuccess) { - expectExactType('' as string)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - } - - // @ts-expect-error - expectType(result) - // is always one of those four - if ( - !result.isUninitialized && - !result.isLoading && - !result.isError && - !result.isSuccess - ) { - expectType(result) - } - }) - test('useQuery union', () => { - const result = api.endpoints.test.useQuery() - - if (result.isUninitialized) { - expectExactType(undefined)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as false)(result.isFetching) - } - if (result.isLoading) { - expectExactType(undefined)(result.data) - expectExactType( - undefined as SerializedError | FetchBaseQueryError | undefined - )(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as boolean)(result.isFetching) - } - if (result.isError) { - expectExactType('' as string | undefined)(result.data) - expectExactType({} as SerializedError | FetchBaseQueryError)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as false)(result.isFetching) - } - if (result.isSuccess) { - expectExactType('' as string)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - expectExactType(false as boolean)(result.isFetching) - } - if (result.isFetching) { - expectExactType('' as string | undefined)(result.data) - expectExactType( - undefined as SerializedError | FetchBaseQueryError | undefined - )(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as boolean)(result.isLoading) - expectExactType(false as boolean)(result.isSuccess) - expectExactType(false as false)(result.isError) - } - - expectExactType('' as string | undefined)(result.currentData) - // @ts-expect-error - expectExactType('' as string)(result.currentData) - - if (result.isSuccess) { - if (!result.isFetching) { - expectExactType('' as string)(result.currentData) - } else { - expectExactType('' as string | undefined)(result.currentData) - // @ts-expect-error - expectExactType('' as string)(result.currentData) - } - } - - // @ts-expect-error - expectType(result) - // is always one of those four - if ( - !result.isUninitialized && - !result.isLoading && - !result.isError && - !result.isSuccess - ) { - expectType(result) - } - }) - test('useQuery TS4.1 union', () => { - const result = api.useTestQuery() - - if (result.isUninitialized) { - expectExactType(undefined)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as false)(result.isFetching) - } - if (result.isLoading) { - expectExactType(undefined)(result.data) - expectExactType( - undefined as SerializedError | FetchBaseQueryError | undefined - )(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as boolean)(result.isFetching) - } - if (result.isError) { - expectExactType('' as string | undefined)(result.data) - expectExactType({} as SerializedError | FetchBaseQueryError)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as false)(result.isFetching) - } - if (result.isSuccess) { - expectExactType('' as string)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - expectExactType(false as boolean)(result.isFetching) - } - if (result.isFetching) { - expectExactType('' as string | undefined)(result.data) - expectExactType( - undefined as SerializedError | FetchBaseQueryError | undefined - )(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as boolean)(result.isLoading) - expectExactType(false as boolean)(result.isSuccess) - expectExactType(false as false)(result.isError) - } - - // @ts-expect-error - expectType(result) - // is always one of those four - if ( - !result.isUninitialized && - !result.isLoading && - !result.isError && - !result.isSuccess - ) { - expectType(result) - } - }) - - test('useLazyQuery union', () => { - const [_trigger, result] = api.endpoints.test.useLazyQuery() - - if (result.isUninitialized) { - expectExactType(undefined)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as false)(result.isFetching) - } - if (result.isLoading) { - expectExactType(undefined)(result.data) - expectExactType( - undefined as SerializedError | FetchBaseQueryError | undefined - )(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as boolean)(result.isFetching) - } - if (result.isError) { - expectExactType('' as string | undefined)(result.data) - expectExactType({} as SerializedError | FetchBaseQueryError)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as false)(result.isFetching) - } - if (result.isSuccess) { - expectExactType('' as string)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - expectExactType(false as boolean)(result.isFetching) - } - if (result.isFetching) { - expectExactType('' as string | undefined)(result.data) - expectExactType( - undefined as SerializedError | FetchBaseQueryError | undefined - )(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as boolean)(result.isLoading) - expectExactType(false as boolean)(result.isSuccess) - expectExactType(false as false)(result.isError) - } - - // @ts-expect-error - expectType(result) - // is always one of those four - if ( - !result.isUninitialized && - !result.isLoading && - !result.isError && - !result.isSuccess - ) { - expectType(result) - } - }) - - test('useLazyQuery TS4.1 union', () => { - const [_trigger, result] = api.useLazyTestQuery() - - if (result.isUninitialized) { - expectExactType(undefined)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as false)(result.isFetching) - } - if (result.isLoading) { - expectExactType(undefined)(result.data) - expectExactType( - undefined as SerializedError | FetchBaseQueryError | undefined - )(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as boolean)(result.isFetching) - } - if (result.isError) { - expectExactType('' as string | undefined)(result.data) - expectExactType({} as SerializedError | FetchBaseQueryError)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isSuccess) - expectExactType(false as false)(result.isFetching) - } - if (result.isSuccess) { - expectExactType('' as string)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - expectExactType(false as boolean)(result.isFetching) - } - if (result.isFetching) { - expectExactType('' as string | undefined)(result.data) - expectExactType( - undefined as SerializedError | FetchBaseQueryError | undefined - )(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as boolean)(result.isLoading) - expectExactType(false as boolean)(result.isSuccess) - expectExactType(false as false)(result.isError) - } - - // @ts-expect-error - expectType(result) - // is always one of those four - if ( - !result.isUninitialized && - !result.isLoading && - !result.isError && - !result.isSuccess - ) { - expectType(result) - } - }) - - test('queryHookResult (without selector) union', async () => { - const useQueryStateResult = api.endpoints.test.useQueryState() - const useQueryResult = api.endpoints.test.useQuery() - const useQueryStateWithSelectFromResult = api.endpoints.test.useQueryState( - undefined, - { - selectFromResult: () => ({ x: true }), - } - ) - - const { refetch, ...useQueryResultWithoutMethods } = useQueryResult - expectExactType(useQueryStateResult)(useQueryResultWithoutMethods) - expectExactType(useQueryStateWithSelectFromResult)( - // @ts-expect-error - useQueryResultWithoutMethods - ) - expectType>>( - await refetch() - ) - }) - - test('useQueryState (with selectFromResult)', () => { - const result = api.endpoints.test.useQueryState(undefined, { - selectFromResult({ - data, - isLoading, - isFetching, - isError, - isSuccess, - isUninitialized, - }) { - return { - data: data ?? 1, - isLoading, - isFetching, - isError, - isSuccess, - isUninitialized, - } - }, - }) - expectExactType({ - data: '' as string | number, - isUninitialized: false, - isLoading: true, - isFetching: true, - isSuccess: false, - isError: false, - })(result) - }) - - test('useQuery (with selectFromResult)', async () => { - const { refetch, ...result } = api.endpoints.test.useQuery(undefined, { - selectFromResult({ - data, - isLoading, - isFetching, - isError, - isSuccess, - isUninitialized, - }) { - return { - data: data ?? 1, - isLoading, - isFetching, - isError, - isSuccess, - isUninitialized, - } - }, - }) - expectExactType({ - data: '' as string | number, - isUninitialized: false, - isLoading: true, - isFetching: true, - isSuccess: false, - isError: false, - })(result) - - expectType>>( - await refetch() - ) - }) - - test('useMutation union', () => { - const [_trigger, result] = api.endpoints.mutation.useMutation() - - if (result.isUninitialized) { - expectExactType(undefined)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - } - if (result.isLoading) { - expectExactType(undefined as undefined)(result.data) - expectExactType( - undefined as SerializedError | FetchBaseQueryError | undefined - )(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - } - if (result.isError) { - expectExactType('' as string | undefined)(result.data) - expectExactType({} as SerializedError | FetchBaseQueryError)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isSuccess) - } - if (result.isSuccess) { - expectExactType('' as string)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - } - - // @ts-expect-error - expectType(result) - // is always one of those four - if ( - !result.isUninitialized && - !result.isLoading && - !result.isError && - !result.isSuccess - ) { - expectType(result) - } - }) - - test('useMutation (with selectFromResult)', () => { - const [_trigger, result] = api.endpoints.mutation.useMutation({ - selectFromResult({ - data, - isLoading, - isError, - isSuccess, - isUninitialized, - }) { - return { - data: data ?? 'hi', - isLoading, - isError, - isSuccess, - isUninitialized, - } - }, - }) - expectExactType({ - data: '' as string, - isUninitialized: false, - isLoading: true, - isSuccess: false, - isError: false, - reset: () => {}, - })(result) - }) - - test('useMutation TS4.1 union', () => { - const [_trigger, result] = api.useMutationMutation() - - if (result.isUninitialized) { - expectExactType(undefined)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - } - if (result.isLoading) { - expectExactType(undefined as undefined)(result.data) - expectExactType( - undefined as SerializedError | FetchBaseQueryError | undefined - )(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isError) - expectExactType(false as false)(result.isSuccess) - } - if (result.isError) { - expectExactType('' as string | undefined)(result.data) - expectExactType({} as SerializedError | FetchBaseQueryError)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isSuccess) - } - if (result.isSuccess) { - expectExactType('' as string)(result.data) - expectExactType(undefined)(result.error) - - expectExactType(false as false)(result.isUninitialized) - expectExactType(false as false)(result.isLoading) - expectExactType(false as false)(result.isError) - } - - // @ts-expect-error - expectType(result) - // is always one of those four - if ( - !result.isUninitialized && - !result.isLoading && - !result.isError && - !result.isSuccess - ) { - expectType(result) - } - }) - - test('"Typed" helper types', () => { - // useQuery - { - const result = api.endpoints.test.useQuery() - expectType>( - result - ) - } - // useQuery with selectFromResult - { - const result = api.endpoints.test.useQuery(undefined, { - selectFromResult: () => ({ x: true }), - }) - expectType< - TypedUseQueryHookResult - >(result) - } - // useQueryState - { - const result = api.endpoints.test.useQueryState() - expectType>( - result - ) - } - // useQueryState with selectFromResult - { - const result = api.endpoints.test.useQueryState(undefined, { - selectFromResult: () => ({ x: true }), - }) - expectType< - TypedUseQueryStateResult - >(result) - } - // useQuerySubscription - { - const result = api.endpoints.test.useQuerySubscription() - expectType< - TypedUseQuerySubscriptionResult - >(result) - } - - // useMutation - { - const [trigger, result] = api.endpoints.mutation.useMutation() - expectType>(result) - } - }) -}) diff --git a/packages/toolkit/src/query/tests/useMutation-fixedCacheKey.test.tsx b/packages/toolkit/src/query/tests/useMutation-fixedCacheKey.test.tsx index ded2e71b4e..5ab0d8f215 100644 --- a/packages/toolkit/src/query/tests/useMutation-fixedCacheKey.test.tsx +++ b/packages/toolkit/src/query/tests/useMutation-fixedCacheKey.test.tsx @@ -1,15 +1,18 @@ import { createApi } from '@reduxjs/toolkit/query/react' -import { setupApiStore, waitMs } from './helpers' -import React from 'react' import { + act, + getByTestId, render, screen, - getByTestId, waitFor, - act, } from '@testing-library/react' +import { delay } from 'msw' +import { vi } from 'vitest' +import { setupApiStore } from '../../tests/utils/helpers' describe('fixedCacheKey', () => { + const onNewCacheEntry = vi.fn() + const api = createApi({ async baseQuery(arg: string | Promise) { return { data: await arg } @@ -54,7 +57,7 @@ describe('fixedCacheKey', () => { , - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) const c1 = screen.getByTestId('C1') const c2 = screen.getByTestId('C2') @@ -66,7 +69,7 @@ describe('fixedCacheKey', () => { }) await waitFor(() => - expect(getByTestId(c1, 'status').textContent).toBe('fulfilled') + expect(getByTestId(c1, 'status').textContent).toBe('fulfilled'), ) expect(getByTestId(c1, 'data').textContent).toBe('C1') expect(getByTestId(c2, 'status').textContent).toBe('uninitialized') @@ -78,7 +81,7 @@ describe('fixedCacheKey', () => { , - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) const c1 = screen.getByTestId('C1') const c2 = screen.getByTestId('C2') @@ -116,7 +119,7 @@ describe('fixedCacheKey', () => { , - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) const c1 = screen.getByTestId('C1') const c2 = screen.getByTestId('C2') @@ -134,7 +137,7 @@ describe('fixedCacheKey', () => { }) await waitFor(() => - expect(getByTestId(c1, 'status').textContent).toBe('fulfilled') + expect(getByTestId(c1, 'status').textContent).toBe('fulfilled'), ) // the components with the first cache key should be affected @@ -156,7 +159,7 @@ describe('fixedCacheKey', () => { }) await waitFor(() => - expect(getByTestId(c3, 'status').textContent).toBe('fulfilled') + expect(getByTestId(c3, 'status').textContent).toBe('fulfilled'), ) // the components with the first cache key should be unaffected @@ -200,7 +203,7 @@ describe('fixedCacheKey', () => { , - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) const c1 = screen.getByTestId('C1') const c2 = screen.getByTestId('C2') @@ -212,7 +215,7 @@ describe('fixedCacheKey', () => { }) await waitFor(() => - expect(getByTestId(c1, 'status').textContent).toBe('fulfilled') + expect(getByTestId(c1, 'status').textContent).toBe('fulfilled'), ) expect(getByTestId(c1, 'data').textContent).toBe('C1') expect(getByTestId(c2, 'status').textContent).toBe('uninitialized') @@ -230,7 +233,7 @@ describe('fixedCacheKey', () => { }) await waitFor(() => - expect(getByTestId(c1, 'status').textContent).toBe('fulfilled') + expect(getByTestId(c1, 'status').textContent).toBe('fulfilled'), ) expect(getByTestId(c1, 'data').textContent).toBe('C1') @@ -249,7 +252,7 @@ describe('fixedCacheKey', () => { , - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) const c1 = screen.getByTestId('C1') const c2 = screen.getByTestId('C2') @@ -261,7 +264,7 @@ describe('fixedCacheKey', () => { }) await waitFor(() => - expect(getByTestId(c1, 'status').textContent).toBe('fulfilled') + expect(getByTestId(c1, 'status').textContent).toBe('fulfilled'), ) expect(getByTestId(c1, 'data').textContent).toBe('C1') expect(getByTestId(c2, 'status').textContent).toBe('fulfilled') @@ -312,7 +315,7 @@ describe('fixedCacheKey', () => { , - { wrapper: storeRef.wrapper } + { wrapper: storeRef.wrapper }, ) const c1 = screen.getByTestId('C1') const c2 = screen.getByTestId('C2') @@ -339,7 +342,7 @@ describe('fixedCacheKey', () => { await Promise.resolve() }) - await waitMs() + await delay(150) expect(getByTestId(c1, 'status').textContent).toBe('pending') expect(getByTestId(c1, 'data').textContent).toBe('') @@ -349,9 +352,43 @@ describe('fixedCacheKey', () => { await Promise.resolve() }) - await waitMs() + await delay(150) expect(getByTestId(c1, 'status').textContent).toBe('fulfilled') expect(getByTestId(c1, 'data').textContent).toBe('this should be visible') }) + + test('using fixedCacheKey should create a new cache entry', async () => { + api.enhanceEndpoints({ + endpoints: { + send: { + onCacheEntryAdded: (arg) => onNewCacheEntry(arg), + }, + }, + }) + + render(, { + wrapper: storeRef.wrapper, + }) + + let c1 = screen.getByTestId('C1') + + expect(getByTestId(c1, 'status').textContent).toBe('uninitialized') + expect(getByTestId(c1, 'originalArgs').textContent).toBe('undefined') + + await act(async () => { + getByTestId(c1, 'trigger').click() + await Promise.resolve() + }) + + expect(onNewCacheEntry).toHaveBeenCalledWith('C1') + + api.enhanceEndpoints({ + endpoints: { + send: { + onCacheEntryAdded: undefined, + }, + }, + }) + }) }) diff --git a/packages/toolkit/src/query/tests/utils.test.ts b/packages/toolkit/src/query/tests/utils.test.ts index 1124f0294b..859865c6d7 100644 --- a/packages/toolkit/src/query/tests/utils.test.ts +++ b/packages/toolkit/src/query/tests/utils.test.ts @@ -13,7 +13,7 @@ afterAll(() => { describe('isOnline', () => { test('Assumes online=true in a node env', () => { vi.spyOn(window, 'navigator', 'get').mockImplementation( - () => undefined as any + () => undefined as any, ) expect(navigator).toBeUndefined() @@ -22,14 +22,14 @@ describe('isOnline', () => { test('Returns false if navigator isOnline=false', () => { vi.spyOn(window, 'navigator', 'get').mockImplementation( - () => ({ onLine: false } as any) + () => ({ onLine: false }) as any, ) expect(isOnline()).toBe(false) }) test('Returns true if navigator isOnline=true', () => { vi.spyOn(window, 'navigator', 'get').mockImplementation( - () => ({ onLine: true } as any) + () => ({ onLine: true }) as any, ) expect(isOnline()).toBe(true) }) @@ -38,7 +38,7 @@ describe('isOnline', () => { describe('isDocumentVisible', () => { test('Assumes true when in a non-browser env', () => { vi.spyOn(window, 'document', 'get').mockImplementation( - () => undefined as any + () => undefined as any, ) expect(window.document).toBeUndefined() expect(isDocumentVisible()).toBe(true) @@ -46,28 +46,28 @@ describe('isDocumentVisible', () => { test('Returns false when hidden=true', () => { vi.spyOn(window, 'document', 'get').mockImplementation( - () => ({ visibilityState: 'hidden' } as any) + () => ({ visibilityState: 'hidden' }) as any, ) expect(isDocumentVisible()).toBe(false) }) test('Returns true when visibilityState=prerender', () => { vi.spyOn(window, 'document', 'get').mockImplementation( - () => ({ visibilityState: 'prerender' } as any) + () => ({ visibilityState: 'prerender' }) as any, ) expect(document.visibilityState).toBe('prerender') expect(isDocumentVisible()).toBe(true) }) test('Returns true when visibilityState=visible', () => { vi.spyOn(window, 'document', 'get').mockImplementation( - () => ({ visibilityState: 'visible' } as any) + () => ({ visibilityState: 'visible' }) as any, ) expect(document.visibilityState).toBe('visible') expect(isDocumentVisible()).toBe(true) }) test('Returns true when visibilityState=undefined', () => { vi.spyOn(window, 'document', 'get').mockImplementation( - () => ({ visibilityState: undefined } as any) + () => ({ visibilityState: undefined }) as any, ) expect(document.visibilityState).toBeUndefined() expect(isDocumentVisible()).toBe(true) diff --git a/packages/toolkit/src/query/tsHelpers.ts b/packages/toolkit/src/query/tsHelpers.ts index 7c2734b448..f663e9965b 100644 --- a/packages/toolkit/src/query/tsHelpers.ts +++ b/packages/toolkit/src/query/tsHelpers.ts @@ -24,9 +24,8 @@ export type NonOptionalKeys = { [K in keyof T]-?: undefined extends T[K] ? never : K }[keyof T] -export type HasRequiredProps = NonOptionalKeys extends never - ? False - : True +export type HasRequiredProps = + NonOptionalKeys extends never ? False : True export type OptionalIfAllPropsOptional = HasRequiredProps diff --git a/packages/toolkit/src/query/utils/isOnline.ts b/packages/toolkit/src/query/utils/isOnline.ts index af34850c9b..0dcb65b97a 100644 --- a/packages/toolkit/src/query/utils/isOnline.ts +++ b/packages/toolkit/src/query/utils/isOnline.ts @@ -7,6 +7,6 @@ export function isOnline() { return typeof navigator === 'undefined' ? true : navigator.onLine === undefined - ? true - : navigator.onLine + ? true + : navigator.onLine } diff --git a/packages/toolkit/src/query/utils/joinUrls.ts b/packages/toolkit/src/query/utils/joinUrls.ts index afcf1ad2e1..31e5e24953 100644 --- a/packages/toolkit/src/query/utils/joinUrls.ts +++ b/packages/toolkit/src/query/utils/joinUrls.ts @@ -5,7 +5,7 @@ const withoutLeadingSlash = (url: string) => url.replace(/^\//, '') export function joinUrls( base: string | undefined, - url: string | undefined + url: string | undefined, ): string { if (!base) { return url! diff --git a/packages/toolkit/src/serializableStateInvariantMiddleware.ts b/packages/toolkit/src/serializableStateInvariantMiddleware.ts index 118d3f50ec..a4dba23562 100644 --- a/packages/toolkit/src/serializableStateInvariantMiddleware.ts +++ b/packages/toolkit/src/serializableStateInvariantMiddleware.ts @@ -39,7 +39,7 @@ export function findNonSerializableValue( isSerializable: (value: unknown) => boolean = isPlain, getEntries?: (value: unknown) => [string, any][], ignoredPaths: IgnorePaths = [], - cache?: WeakSet + cache?: WeakSet, ): NonSerializableValue | false { let foundNestedSerializable: NonSerializableValue | false @@ -89,7 +89,7 @@ export function findNonSerializableValue( isSerializable, getEntries, ignoredPaths, - cache + cache, ) if (foundNestedSerializable) { @@ -186,7 +186,7 @@ export interface SerializableStateInvariantMiddlewareOptions { * @public */ export function createSerializableStateInvariantMiddleware( - options: SerializableStateInvariantMiddlewareOptions = {} + options: SerializableStateInvariantMiddlewareOptions = {}, ): Middleware { if (process.env.NODE_ENV === 'production') { return () => (next) => (action) => next(action) @@ -215,7 +215,7 @@ export function createSerializableStateInvariantMiddleware( const measureUtils = getTimeMeasureUtils( warnAfter, - 'SerializableStateInvariantMiddleware' + 'SerializableStateInvariantMiddleware', ) if ( @@ -232,7 +232,7 @@ export function createSerializableStateInvariantMiddleware( isSerializable, getEntries, ignoredActionPaths, - cache + cache, ) if (foundActionNonSerializableValue) { @@ -244,7 +244,7 @@ export function createSerializableStateInvariantMiddleware( '\nTake a look at the logic that dispatched this action: ', action, '\n(See https://redux.js.org/faq/actions#why-should-type-be-a-string-or-at-least-serializable-why-should-my-action-types-be-constants)', - '\n(To allow non-serializable values see: https://redux-toolkit.js.org/usage/usage-guide#working-with-non-serializable-data)' + '\n(To allow non-serializable values see: https://redux-toolkit.js.org/usage/usage-guide#working-with-non-serializable-data)', ) } }) @@ -260,7 +260,7 @@ export function createSerializableStateInvariantMiddleware( isSerializable, getEntries, ignoredPaths, - cache + cache, ) if (foundStateNonSerializableValue) { @@ -271,7 +271,7 @@ export function createSerializableStateInvariantMiddleware( value, ` Take a look at the reducer(s) handling this action type: ${action.type}. -(See https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state)` +(See https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state)`, ) } }) diff --git a/packages/toolkit/src/tests/Tuple.test-d.ts b/packages/toolkit/src/tests/Tuple.test-d.ts new file mode 100644 index 0000000000..9433634323 --- /dev/null +++ b/packages/toolkit/src/tests/Tuple.test-d.ts @@ -0,0 +1,83 @@ +import { Tuple } from '@reduxjs/toolkit' + +describe('type tests', () => { + test('compatibility is checked between described types', () => { + const stringTuple = new Tuple('') + + expectTypeOf(stringTuple).toEqualTypeOf>() + + expectTypeOf(stringTuple).toMatchTypeOf>() + + expectTypeOf(stringTuple).not.toMatchTypeOf>() + + const numberTuple = new Tuple(0, 1) + + expectTypeOf(numberTuple).not.toMatchTypeOf>() + }) + + test('concat is inferred properly', () => { + const singleString = new Tuple('') + + expectTypeOf(singleString).toEqualTypeOf>() + + expectTypeOf(singleString.concat('')).toEqualTypeOf< + Tuple<[string, string]> + >() + + expectTypeOf(singleString.concat([''] as const)).toMatchTypeOf< + Tuple<[string, string]> + >() + }) + + test('prepend is inferred properly', () => { + const singleString = new Tuple('') + + expectTypeOf(singleString).toEqualTypeOf>() + + expectTypeOf(singleString.prepend('')).toEqualTypeOf< + Tuple<[string, string]> + >() + + expectTypeOf(singleString.prepend([''] as const)).toMatchTypeOf< + Tuple<[string, string]> + >() + }) + + test('push must match existing items', () => { + const stringTuple = new Tuple('') + + expectTypeOf(stringTuple.push).toBeCallableWith('') + + expectTypeOf(stringTuple.push).parameter(0).not.toBeNumber() + }) + + test('Tuples can be combined', () => { + const stringTuple = new Tuple('') + + const numberTuple = new Tuple(0, 1) + + expectTypeOf(stringTuple.concat(numberTuple)).toEqualTypeOf< + Tuple<[string, number, number]> + >() + + expectTypeOf(stringTuple.prepend(numberTuple)).toEqualTypeOf< + Tuple<[number, number, string]> + >() + + expectTypeOf(numberTuple.concat(stringTuple)).toEqualTypeOf< + Tuple<[number, number, string]> + >() + + expectTypeOf(numberTuple.prepend(stringTuple)).toEqualTypeOf< + Tuple<[string, number, number]> + >() + + expectTypeOf(stringTuple.prepend(numberTuple)).not.toMatchTypeOf< + Tuple<[string, number, number]> + >() + + expectTypeOf(stringTuple.concat(numberTuple)).not.toMatchTypeOf< + Tuple<[number, number, string]> + >() + }) +}) diff --git a/packages/toolkit/src/tests/Tuple.typetest.ts b/packages/toolkit/src/tests/Tuple.typetest.ts deleted file mode 100644 index 4beaf28fae..0000000000 --- a/packages/toolkit/src/tests/Tuple.typetest.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Tuple } from '@reduxjs/toolkit' -import { expectType } from './helpers' - -/** - * Test: compatibility is checked between described types - */ -{ - const stringTuple = new Tuple('') - - expectType>(stringTuple) - - expectType>(stringTuple) - - // @ts-expect-error - expectType>(stringTuple) - - const numberTuple = new Tuple(0, 1) - // @ts-expect-error - expectType>(numberTuple) -} - -/** - * Test: concat is inferred properly - */ -{ - const singleString = new Tuple('') - - expectType>(singleString) - - expectType>(singleString.concat('')) - - expectType>(singleString.concat([''])) -} - -/** - * Test: prepend is inferred properly - */ -{ - const singleString = new Tuple('') - - expectType>(singleString) - - expectType>(singleString.prepend('')) - - expectType>(singleString.prepend([''])) -} - -/** - * Test: push must match existing items - */ -{ - const stringTuple = new Tuple('') - - stringTuple.push('') - - // @ts-expect-error - stringTuple.push(0) -} - -/** - * Test: Tuples can be combined - */ -{ - const stringTuple = new Tuple('') - - const numberTuple = new Tuple(0, 1) - - expectType>(stringTuple.concat(numberTuple)) - - expectType>(stringTuple.prepend(numberTuple)) - - expectType>(numberTuple.concat(stringTuple)) - - expectType>(numberTuple.prepend(stringTuple)) - - // @ts-expect-error - expectType>(stringTuple.prepend(numberTuple)) - - // @ts-expect-error - expectType>(stringTuple.concat(numberTuple)) -} diff --git a/packages/toolkit/src/tests/actionCreatorInvariantMiddleware.test.ts b/packages/toolkit/src/tests/actionCreatorInvariantMiddleware.test.ts index 65f83ee063..25d5df9568 100644 --- a/packages/toolkit/src/tests/actionCreatorInvariantMiddleware.test.ts +++ b/packages/toolkit/src/tests/actionCreatorInvariantMiddleware.test.ts @@ -19,7 +19,7 @@ describe('createActionCreatorInvariantMiddleware', () => { it('sends the action through the middleware chain', () => { const next = vi.fn() const dispatch = createActionCreatorInvariantMiddleware()( - {} as MiddlewareAPI + {} as MiddlewareAPI, )(next) dispatch({ type: 'SOME_ACTION' }) @@ -29,10 +29,10 @@ describe('createActionCreatorInvariantMiddleware', () => { }) const makeActionTester = ( - options?: ActionCreatorInvariantMiddlewareOptions + options?: ActionCreatorInvariantMiddlewareOptions, ) => createActionCreatorInvariantMiddleware(options)({} as MiddlewareAPI)( - (action) => action + (action) => action, ) it('logs a warning to console if an action creator is mistakenly dispatched', () => { diff --git a/packages/toolkit/src/tests/combineSlices.test-d.ts b/packages/toolkit/src/tests/combineSlices.test-d.ts new file mode 100644 index 0000000000..6b773a5d54 --- /dev/null +++ b/packages/toolkit/src/tests/combineSlices.test-d.ts @@ -0,0 +1,189 @@ +import type { Reducer, Slice, WithSlice } from '@reduxjs/toolkit' +import { combineSlices } from '@reduxjs/toolkit' +import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' + +declare const stringSlice: Slice + +declare const numberSlice: Slice + +declare const booleanReducer: Reducer + +const exampleApi = createApi({ + baseQuery: fetchBaseQuery(), + endpoints: (build) => ({ + getThing: build.query({ + query: () => '', + }), + }), +}) + +type ExampleApiState = ReturnType + +describe('type tests', () => { + test('combineSlices correctly combines static state', () => { + const rootReducer = combineSlices(stringSlice, numberSlice, exampleApi, { + boolean: booleanReducer, + }) + + expectTypeOf(rootReducer(undefined, { type: '' })).toEqualTypeOf<{ + string: string + number: number + boolean: boolean + api: ExampleApiState + }>() + }) + + test('withLazyLoadedSlices adds partial to state', () => { + const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices< + WithSlice & WithSlice + >() + + expectTypeOf(rootReducer(undefined, { type: '' }).number).toEqualTypeOf< + number | undefined + >() + + expectTypeOf(rootReducer(undefined, { type: '' }).api).toEqualTypeOf< + ExampleApiState | undefined + >() + }) + + test('inject marks injected keys as required', () => { + const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices< + WithSlice & + WithSlice & { boolean: boolean } + >() + + expectTypeOf(rootReducer(undefined, { type: '' }).number).toEqualTypeOf< + number | undefined + >() + + expectTypeOf(rootReducer(undefined, { type: '' }).boolean).toEqualTypeOf< + boolean | undefined + >() + + expectTypeOf(rootReducer(undefined, { type: '' }).api).toEqualTypeOf< + ExampleApiState | undefined + >() + + const withNumber = rootReducer.inject(numberSlice) + + expectTypeOf(withNumber(undefined, { type: '' }).number).toBeNumber() + + const withBool = rootReducer.inject({ + reducerPath: 'boolean' as const, + reducer: booleanReducer, + }) + + expectTypeOf(withBool(undefined, { type: '' }).boolean).toBeBoolean() + + const withApi = rootReducer.inject(exampleApi) + + expectTypeOf( + withApi(undefined, { type: '' }).api, + ).toEqualTypeOf() + }) + + test('selector() allows defining selectors with injected reducers defined', () => { + const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices< + WithSlice & { boolean: boolean } + >() + + type RootState = ReturnType + + const withoutInjection = rootReducer.selector( + (state: RootState) => state.number, + ) + + expectTypeOf( + withoutInjection(rootReducer(undefined, { type: '' })), + ).toEqualTypeOf() + + const withInjection = rootReducer + .inject(numberSlice) + .selector((state) => state.number) + + expectTypeOf( + withInjection(rootReducer(undefined, { type: '' })), + ).toBeNumber() + }) + + test('selector() passes arguments through', () => { + const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices< + WithSlice & { boolean: boolean } + >() + + const selector = rootReducer + .inject(numberSlice) + .selector((state, num: number) => state.number) + + const state = rootReducer(undefined, { type: '' }) + + expectTypeOf(selector).toBeCallableWith(state, 0) + + // required argument + expectTypeOf(selector).parameters.not.toMatchTypeOf([state]) + + // number not string + expectTypeOf(selector).parameters.not.toMatchTypeOf([state, '']) + }) + + test('nested calls inferred correctly', () => { + const innerReducer = + combineSlices(stringSlice).withLazyLoadedSlices< + WithSlice + >() + + const innerSelector = innerReducer.inject(numberSlice).selector( + (state) => state.number, + (rootState: RootState) => rootState.inner, + ) + + const outerReducer = combineSlices({ inner: innerReducer }) + + type RootState = ReturnType + + expectTypeOf(outerReducer(undefined, { type: '' })).toMatchTypeOf<{ + inner: { string: string } + }>() + + expectTypeOf( + innerSelector(outerReducer(undefined, { type: '' })), + ).toBeNumber() + }) + + test('selector errors if selectorFn and selectState are mismatched', () => { + const combinedReducer = + combineSlices(stringSlice).withLazyLoadedSlices< + WithSlice + >() + + const outerReducer = combineSlices({ inner: combinedReducer }) + + type RootState = ReturnType + + combinedReducer.selector( + (state) => state.number, + // @ts-expect-error wrong state returned + (rootState: RootState) => rootState.inner.number, + ) + + combinedReducer.selector( + (state, num: number) => state.number, + // @ts-expect-error wrong arguments + (rootState: RootState, str: string) => rootState.inner, + ) + + combinedReducer.selector( + (state, num: number) => state.number, + (rootState: RootState) => rootState.inner, + ) + + // TODO: see if there's a way of making this work + // probably a rare case so not the end of the world if not + combinedReducer.selector( + (state) => state.number, + // @ts-ignore + (rootState: RootState, num: number) => rootState.inner, + ) + }) +}) diff --git a/packages/toolkit/src/tests/combineSlices.test.ts b/packages/toolkit/src/tests/combineSlices.test.ts index 4e3439fd0f..a74b675c68 100644 --- a/packages/toolkit/src/tests/combineSlices.test.ts +++ b/packages/toolkit/src/tests/combineSlices.test.ts @@ -1,10 +1,10 @@ -import { createReducer } from '../createReducer' -import { createAction } from '../createAction' -import { createSlice } from '../createSlice' -import type { WithSlice } from '../combineSlices' -import { combineSlices } from '../combineSlices' -import { expectType } from './helpers' -import type { CombinedState } from '../query/core/apiState' +import type { WithSlice } from '@reduxjs/toolkit' +import { + combineSlices, + createAction, + createReducer, + createSlice, +} from '@reduxjs/toolkit' const dummyAction = createAction('dummy') @@ -26,7 +26,7 @@ const booleanReducer = createReducer(false, () => {}) const api = { reducerPath: 'api' as const, reducer: createReducer( - expectType>({ + { queries: {}, mutations: {}, provided: {}, @@ -42,8 +42,8 @@ const api = { refetchOnReconnect: false, refetchOnFocus: false, }, - }), - () => {} + }, + () => {}, ), } @@ -55,7 +55,7 @@ describe('combineSlices', () => { num: numberSlice.reducer, boolean: booleanReducer, }, - api + api, ) expect(combinedReducer(undefined, dummyAction())).toEqual({ string: stringSlice.getInitialState(), @@ -65,6 +65,12 @@ describe('combineSlices', () => { }) }) describe('injects', () => { + beforeEach(() => { + vi.stubEnv('NODE_ENV', 'development') + + return vi.unstubAllEnvs + }) + it('injects slice', () => { const combinedReducer = combineSlices(stringSlice).withLazyLoadedSlices< @@ -76,13 +82,14 @@ describe('combineSlices', () => { const injectedReducer = combinedReducer.inject(numberSlice) expect(injectedReducer(undefined, dummyAction()).number).toBe( - numberSlice.getInitialState() + numberSlice.getInitialState(), ) }) it('logs error when same name is used for different reducers', () => { const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {}) - const combinedReducer = - combineSlices(stringSlice).withLazyLoadedSlices<{ boolean: boolean }>() + const combinedReducer = combineSlices(stringSlice).withLazyLoadedSlices<{ + boolean: boolean + }>() combinedReducer.inject({ reducerPath: 'boolean' as const, @@ -103,7 +110,7 @@ describe('combineSlices', () => { }) expect(consoleSpy).toHaveBeenCalledWith( - `called \`inject\` to override already-existing reducer boolean without specifying \`overrideExisting: true\`` + `called \`inject\` to override already-existing reducer boolean without specifying \`overrideExisting: true\``, ) consoleSpy.mockRestore() }) @@ -118,15 +125,16 @@ describe('combineSlices', () => { combinedReducer.inject( { reducerPath: 'number' as const, reducer: () => 0 }, - { overrideExisting: true } + { overrideExisting: true }, ) expect(consoleSpy).not.toHaveBeenCalled() }) }) describe('selector', () => { - const combinedReducer = - combineSlices(stringSlice).withLazyLoadedSlices<{ boolean: boolean }>() + const combinedReducer = combineSlices(stringSlice).withLazyLoadedSlices<{ + boolean: boolean + }>() const uninjectedState = combinedReducer(undefined, dummyAction()) @@ -141,18 +149,18 @@ describe('combineSlices', () => { const selectBoolean = injectedReducer.selector((state) => state.boolean) expect(selectBoolean(uninjectedState)).toBe( - booleanReducer.getInitialState() + booleanReducer.getInitialState(), ) }) it('exposes original to allow for logging', () => { const selectBoolean = injectedReducer.selector( - (state) => injectedReducer.selector.original(state).boolean + (state) => injectedReducer.selector.original(state).boolean, ) expect(selectBoolean(uninjectedState)).toBe(undefined) }) it('throws if original is called on something other than state proxy', () => { expect(() => injectedReducer.selector.original({} as any)).toThrow( - 'original must be used on state Proxy' + 'original must be used on state Proxy', ) }) it('allows passing a selectState selector, to handle nested state', () => { @@ -164,11 +172,11 @@ describe('combineSlices', () => { const selector = injectedReducer.selector( (state) => state.boolean, - (rootState: RootState) => rootState.inner + (rootState: RootState) => rootState.inner, ) expect(selector(wrappedReducer(undefined, dummyAction()))).toBe( - booleanReducer.getInitialState() + booleanReducer.getInitialState(), ) }) }) diff --git a/packages/toolkit/src/tests/combineSlices.typetest.ts b/packages/toolkit/src/tests/combineSlices.typetest.ts deleted file mode 100644 index 8ab744f335..0000000000 --- a/packages/toolkit/src/tests/combineSlices.typetest.ts +++ /dev/null @@ -1,210 +0,0 @@ -/* eslint-disable no-lone-blocks */ -import type { Reducer, Slice, WithSlice } from '@reduxjs/toolkit' -import { combineSlices } from '@reduxjs/toolkit' -import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query' -import { expectExactType, expectType } from './helpers' - -declare const stringSlice: Slice - -declare const numberSlice: Slice - -declare const booleanReducer: Reducer - -const exampleApi = createApi({ - baseQuery: fetchBaseQuery(), - endpoints: (build) => ({ - getThing: build.query({ - query: () => '', - }), - }), -}) - -type ExampleApiState = ReturnType - -/** - * Test: combineSlices correctly combines static state - */ -{ - const rootReducer = combineSlices(stringSlice, numberSlice, exampleApi, { - boolean: booleanReducer, - }) - expectType<{ - string: string - number: number - boolean: boolean - api: ExampleApiState - }>(rootReducer(undefined, { type: '' })) -} - -/** - * Test: withLazyLoadedSlices adds partial to state - */ -{ - const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices< - WithSlice & WithSlice - >() - expectExactType(0)( - rootReducer(undefined, { type: '' }).number - ) - expectExactType(undefined)( - rootReducer(undefined, { type: '' }).api - ) -} - -/** - * Test: inject marks injected keys as required - */ -{ - const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices< - WithSlice & - WithSlice & { boolean: boolean } - >() - - expectExactType(0)( - rootReducer(undefined, { type: '' }).number - ) - expectExactType(true)( - rootReducer(undefined, { type: '' }).boolean - ) - expectExactType(undefined)( - rootReducer(undefined, { type: '' }).api - ) - - const withNumber = rootReducer.inject(numberSlice) - expectExactType(0)(withNumber(undefined, { type: '' }).number) - - const withBool = rootReducer.inject({ - reducerPath: 'boolean' as const, - reducer: booleanReducer, - }) - expectExactType(true)(withBool(undefined, { type: '' }).boolean) - - const withApi = rootReducer.inject(exampleApi) - expectExactType({} as ExampleApiState)( - withApi(undefined, { type: '' }).api - ) -} - -declare const wrongNumberSlice: Slice - -declare const wrongBooleanReducer: Reducer - -const wrongApi = createApi({ - baseQuery: fetchBaseQuery(), - endpoints: (build) => ({ - getThing2: build.query({ - query: () => '', - }), - }), -}) - -/** - * Test: selector() allows defining selectors with injected reducers defined - */ -{ - const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices< - WithSlice & { boolean: boolean } - >() - - type RootState = ReturnType - - const withoutInjection = rootReducer.selector( - (state: RootState) => state.number - ) - - expectExactType(0)( - withoutInjection(rootReducer(undefined, { type: '' })) - ) - - const withInjection = rootReducer - .inject(numberSlice) - .selector((state) => state.number) - - expectExactType(0)( - withInjection(rootReducer(undefined, { type: '' })) - ) -} - -/** - * Test: selector() passes arguments through - */ -{ - const rootReducer = combineSlices(stringSlice).withLazyLoadedSlices< - WithSlice & { boolean: boolean } - >() - - const selector = rootReducer - .inject(numberSlice) - .selector((state, num: number) => state.number) - - const state = rootReducer(undefined, { type: '' }) - // @ts-expect-error required argument - selector(state) - // @ts-expect-error number not string - selector(state, '') - selector(state, 0) -} - -/** - * Test: nested calls inferred correctly - */ -{ - const innerReducer = - combineSlices(stringSlice).withLazyLoadedSlices< - WithSlice - >() - - const innerSelector = innerReducer.inject(numberSlice).selector( - (state) => state.number, - (rootState: RootState) => rootState.inner - ) - - const outerReducer = combineSlices({ inner: innerReducer }) - - type RootState = ReturnType - - expectType<{ inner: { string: string } }>( - outerReducer(undefined, { type: '' }) - ) - - expectType(innerSelector(outerReducer(undefined, { type: '' }))) -} - -/** - * Test: selector errors if selectorFn and selectState are mismatched - */ - -{ - const combinedReducer = - combineSlices(stringSlice).withLazyLoadedSlices< - WithSlice - >() - - const outerReducer = combineSlices({ inner: combinedReducer }) - - type RootState = ReturnType - - combinedReducer.selector( - (state) => state.number, - // @ts-expect-error wrong state returned - (rootState: RootState) => rootState.inner.number - ) - combinedReducer.selector( - (state, num: number) => state.number, - // @ts-expect-error wrong arguments - (rootState: RootState, str: string) => rootState.inner - ) - - combinedReducer.selector( - (state, num: number) => state.number, - (rootState: RootState) => rootState.inner - ) - - // TODO: see if there's a way of making this work - // probably a rare case so not the end of the world if not - combinedReducer.selector( - (state) => state.number, - // @ts-ignore - (rootState: RootState, num: number) => rootState.inner - ) -} diff --git a/packages/toolkit/src/tests/combinedTest.test.ts b/packages/toolkit/src/tests/combinedTest.test.ts index 7f906d8182..a130df7a1d 100644 --- a/packages/toolkit/src/tests/combinedTest.test.ts +++ b/packages/toolkit/src/tests/combinedTest.test.ts @@ -48,7 +48,7 @@ describe('Combined entity slice', () => { async (arg, { getState, dispatch, extra, requestId, signal }) => { const state = getState() return fakeBooks - } + }, ) const booksSlice = createSlice({ diff --git a/packages/toolkit/src/tests/configureStore.test-d.ts b/packages/toolkit/src/tests/configureStore.test-d.ts new file mode 100644 index 0000000000..2bf27f4bdc --- /dev/null +++ b/packages/toolkit/src/tests/configureStore.test-d.ts @@ -0,0 +1,805 @@ +import type { + Action, + ConfigureStoreOptions, + Dispatch, + Middleware, + PayloadAction, + Reducer, + Store, + StoreEnhancer, + ThunkAction, + ThunkDispatch, + ThunkMiddleware, + UnknownAction, +} from '@reduxjs/toolkit' +import { + Tuple, + applyMiddleware, + combineReducers, + configureStore, + createSlice, +} from '@reduxjs/toolkit' +import { thunk } from 'redux-thunk' + +const _anyMiddleware: any = () => () => () => {} + +describe('type tests', () => { + test('configureStore() requires a valid reducer or reducer map.', () => { + configureStore({ + reducer: (state, action) => 0, + }) + + configureStore({ + reducer: { + counter1: () => 0, + counter2: () => 1, + }, + }) + + // @ts-expect-error + configureStore({ reducer: 'not a reducer' }) + + // @ts-expect-error + configureStore({ reducer: { a: 'not a reducer' } }) + + // @ts-expect-error + configureStore({}) + }) + + test('configureStore() infers the store state type.', () => { + const reducer: Reducer = () => 0 + + const store = configureStore({ reducer }) + + expectTypeOf(store).toMatchTypeOf>() + + expectTypeOf(store).not.toMatchTypeOf>() + }) + + test('configureStore() infers the store action type.', () => { + const reducer: Reducer> = () => 0 + + const store = configureStore({ reducer }) + + expectTypeOf(store).toMatchTypeOf>>() + + expectTypeOf(store).not.toMatchTypeOf< + Store> + >() + }) + + test('configureStore() accepts Tuple for middleware, but not plain array.', () => { + const middleware: Middleware = (store) => (next) => next + + configureStore({ + reducer: () => 0, + middleware: () => new Tuple(middleware), + }) + + configureStore({ + reducer: () => 0, + // @ts-expect-error + middleware: () => [middleware], + }) + + configureStore({ + reducer: () => 0, + // @ts-expect-error + middleware: () => new Tuple('not middleware'), + }) + }) + + test('configureStore() accepts devTools flag.', () => { + configureStore({ + reducer: () => 0, + devTools: true, + }) + + configureStore({ + reducer: () => 0, + // @ts-expect-error + devTools: 'true', + }) + }) + + test('configureStore() accepts devTools EnhancerOptions.', () => { + configureStore({ + reducer: () => 0, + devTools: { name: 'myApp' }, + }) + + configureStore({ + reducer: () => 0, + // @ts-expect-error + devTools: { appName: 'myApp' }, + }) + }) + + test('configureStore() accepts preloadedState.', () => { + configureStore({ + reducer: () => 0, + preloadedState: 0, + }) + + configureStore({ + // @ts-expect-error + reducer: (_: number) => 0, + preloadedState: 'non-matching state type', + }) + }) + + test('nullable state is preserved', () => { + const store = configureStore({ + reducer: (): string | null => null, + }) + + expectTypeOf(store.getState()).toEqualTypeOf() + }) + + test('configureStore() accepts store Tuple for enhancers, but not plain array', () => { + const enhancer = applyMiddleware(() => (next) => next) + + const store = configureStore({ + reducer: () => 0, + enhancers: () => new Tuple(enhancer), + }) + + const store2 = configureStore({ + reducer: () => 0, + // @ts-expect-error + enhancers: () => [enhancer], + }) + + expectTypeOf(store.dispatch).toMatchTypeOf< + Dispatch & ThunkDispatch + >() + + configureStore({ + reducer: () => 0, + // @ts-expect-error + enhancers: () => new Tuple('not a store enhancer'), + }) + + const somePropertyStoreEnhancer: StoreEnhancer<{ + someProperty: string + }> = (next) => { + return (reducer, preloadedState) => { + return { + ...next(reducer, preloadedState), + someProperty: 'some value', + } + } + } + + const anotherPropertyStoreEnhancer: StoreEnhancer<{ + anotherProperty: number + }> = (next) => { + return (reducer, preloadedState) => { + return { + ...next(reducer, preloadedState), + anotherProperty: 123, + } + } + } + + const store3 = configureStore({ + reducer: () => 0, + enhancers: () => + new Tuple(somePropertyStoreEnhancer, anotherPropertyStoreEnhancer), + }) + + expectTypeOf(store3.dispatch).toEqualTypeOf() + + expectTypeOf(store3.someProperty).toBeString() + + expectTypeOf(store3.anotherProperty).toBeNumber() + + const storeWithCallback = configureStore({ + reducer: () => 0, + enhancers: (getDefaultEnhancers) => + getDefaultEnhancers() + .prepend(anotherPropertyStoreEnhancer) + .concat(somePropertyStoreEnhancer), + }) + + expectTypeOf(store3.dispatch).toMatchTypeOf< + Dispatch & ThunkDispatch + >() + + expectTypeOf(store3.someProperty).toBeString() + + expectTypeOf(store3.anotherProperty).toBeNumber() + + const someStateExtendingEnhancer: StoreEnhancer< + {}, + { someProperty: string } + > = + (next) => + (...args) => { + const store = next(...args) + const getState = () => ({ + ...store.getState(), + someProperty: 'some value', + }) + return { + ...store, + getState, + } as any + } + + const anotherStateExtendingEnhancer: StoreEnhancer< + {}, + { anotherProperty: number } + > = + (next) => + (...args) => { + const store = next(...args) + const getState = () => ({ + ...store.getState(), + anotherProperty: 123, + }) + return { + ...store, + getState, + } as any + } + + const store4 = configureStore({ + reducer: () => ({ aProperty: 0 }), + enhancers: () => + new Tuple(someStateExtendingEnhancer, anotherStateExtendingEnhancer), + }) + + const state = store4.getState() + + expectTypeOf(state.aProperty).toBeNumber() + + expectTypeOf(state.someProperty).toBeString() + + expectTypeOf(state.anotherProperty).toBeNumber() + + const storeWithCallback2 = configureStore({ + reducer: () => ({ aProperty: 0 }), + enhancers: (gDE) => + gDE().concat(someStateExtendingEnhancer, anotherStateExtendingEnhancer), + }) + + const stateWithCallback = storeWithCallback2.getState() + + expectTypeOf(stateWithCallback.aProperty).toBeNumber() + + expectTypeOf(stateWithCallback.someProperty).toBeString() + + expectTypeOf(stateWithCallback.anotherProperty).toBeNumber() + }) + + test('Preloaded state typings', () => { + const counterReducer1: Reducer = () => 0 + const counterReducer2: Reducer = () => 0 + + test('partial preloaded state', () => { + const store = configureStore({ + reducer: { + counter1: counterReducer1, + counter2: counterReducer2, + }, + preloadedState: { + counter1: 0, + }, + }) + + expectTypeOf(store.getState().counter1).toBeNumber() + + expectTypeOf(store.getState().counter2).toBeNumber() + }) + + test('empty preloaded state', () => { + const store = configureStore({ + reducer: { + counter1: counterReducer1, + counter2: counterReducer2, + }, + preloadedState: {}, + }) + + expectTypeOf(store.getState().counter1).toBeNumber() + + expectTypeOf(store.getState().counter2).toBeNumber() + }) + + test('excess properties in preloaded state', () => { + const store = configureStore({ + reducer: { + // @ts-expect-error + counter1: counterReducer1, + counter2: counterReducer2, + }, + preloadedState: { + counter1: 0, + counter3: 5, + }, + }) + + expectTypeOf(store.getState().counter1).toBeNumber() + + expectTypeOf(store.getState().counter2).toBeNumber() + }) + + test('mismatching properties in preloaded state', () => { + const store = configureStore({ + reducer: { + // @ts-expect-error + counter1: counterReducer1, + counter2: counterReducer2, + }, + preloadedState: { + counter3: 5, + }, + }) + + expectTypeOf(store.getState().counter1).toBeNumber() + + expectTypeOf(store.getState().counter2).toBeNumber() + }) + + test('string preloaded state when expecting object', () => { + const store = configureStore({ + reducer: { + // @ts-expect-error + counter1: counterReducer1, + counter2: counterReducer2, + }, + preloadedState: 'test', + }) + + expectTypeOf(store.getState().counter1).toBeNumber() + + expectTypeOf(store.getState().counter2).toBeNumber() + }) + + test('nested combineReducers allows partial', () => { + const store = configureStore({ + reducer: { + group1: combineReducers({ + counter1: counterReducer1, + counter2: counterReducer2, + }), + group2: combineReducers({ + counter1: counterReducer1, + counter2: counterReducer2, + }), + }, + preloadedState: { + group1: { + counter1: 5, + }, + }, + }) + + expectTypeOf(store.getState().group1.counter1).toBeNumber() + + expectTypeOf(store.getState().group1.counter2).toBeNumber() + + expectTypeOf(store.getState().group2.counter1).toBeNumber() + + expectTypeOf(store.getState().group2.counter2).toBeNumber() + }) + + test('non-nested combineReducers does not allow partial', () => { + interface GroupState { + counter1: number + counter2: number + } + + const initialState = { counter1: 0, counter2: 0 } + + const group1Reducer: Reducer = (state = initialState) => state + const group2Reducer: Reducer = (state = initialState) => state + + const store = configureStore({ + reducer: { + // @ts-expect-error + group1: group1Reducer, + group2: group2Reducer, + }, + preloadedState: { + group1: { + counter1: 5, + }, + }, + }) + + expectTypeOf(store.getState().group1.counter1).toBeNumber() + + expectTypeOf(store.getState().group1.counter2).toBeNumber() + + expectTypeOf(store.getState().group2.counter1).toBeNumber() + + expectTypeOf(store.getState().group2.counter2).toBeNumber() + }) + }) + + test('Dispatch typings', () => { + type StateA = number + const reducerA = () => 0 + const thunkA = () => { + return (() => {}) as any as ThunkAction, StateA, any, any> + } + + type StateB = string + const thunkB = () => { + return (dispatch: Dispatch, getState: () => StateB) => {} + } + + test('by default, dispatching Thunks is possible', () => { + const store = configureStore({ + reducer: reducerA, + }) + + store.dispatch(thunkA()) + // @ts-expect-error + store.dispatch(thunkB()) + + const res = store.dispatch((dispatch, getState) => { + return 42 + }) + + const action = store.dispatch({ type: 'foo' }) + }) + + test('return type of thunks and actions is inferred correctly', () => { + const slice = createSlice({ + name: 'counter', + initialState: { + value: 0, + }, + reducers: { + incrementByAmount: (state, action: PayloadAction) => { + state.value += action.payload + }, + }, + }) + + const store = configureStore({ + reducer: { + counter: slice.reducer, + }, + }) + + const action = slice.actions.incrementByAmount(2) + + const dispatchResult = store.dispatch(action) + + expectTypeOf(dispatchResult).toMatchTypeOf<{ + type: string + payload: number + }>() + + const promiseResult = store.dispatch(async (dispatch) => { + return 42 + }) + + expectTypeOf(promiseResult).toEqualTypeOf>() + + const store2 = configureStore({ + reducer: { + counter: slice.reducer, + }, + middleware: (gDM) => + gDM({ + thunk: { + extraArgument: 42, + }, + }), + }) + + const dispatchResult2 = store2.dispatch(action) + + expectTypeOf(dispatchResult2).toMatchTypeOf<{ + type: string + payload: number + }>() + }) + + test('removing the Thunk Middleware', () => { + const store = configureStore({ + reducer: reducerA, + middleware: () => new Tuple(), + }) + + expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkA()) + + expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB()) + }) + + test('adding the thunk middleware by hand', () => { + const store = configureStore({ + reducer: reducerA, + middleware: () => new Tuple(thunk as ThunkMiddleware), + }) + + store.dispatch(thunkA()) + // @ts-expect-error + store.dispatch(thunkB()) + }) + + test('custom middleware', () => { + const store = configureStore({ + reducer: reducerA, + middleware: () => + new Tuple(0 as unknown as Middleware<(a: StateA) => boolean, StateA>), + }) + + expectTypeOf(store.dispatch(5)).toBeBoolean() + + expectTypeOf(store.dispatch(5)).not.toBeString() + }) + + test('multiple custom middleware', () => { + const middleware = [] as any as Tuple< + [ + Middleware<(a: 'a') => 'A', StateA>, + Middleware<(b: 'b') => 'B', StateA>, + ThunkMiddleware, + ] + > + + const store = configureStore({ + reducer: reducerA, + middleware: () => middleware, + }) + + expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>() + + expectTypeOf(store.dispatch('b')).toEqualTypeOf<'B'>() + + expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf>() + }) + + test('Accepts thunk with `unknown`, `undefined` or `null` ThunkAction extraArgument per default', () => { + const store = configureStore({ reducer: {} }) + // undefined is the default value for the ThunkMiddleware extraArgument + store.dispatch(function () {} as ThunkAction< + void, + {}, + undefined, + UnknownAction + >) + // `null` for the `extra` generic was previously documented in the RTK "Advanced Tutorial", but + // is a bad pattern and users should use `unknown` instead + // @ts-expect-error + store.dispatch(function () {} as ThunkAction< + void, + {}, + null, + UnknownAction + >) + // unknown is the best way to type a ThunkAction if you do not care + // about the value of the extraArgument, as it will always work with every + // ThunkMiddleware, no matter the actual extraArgument type + store.dispatch(function () {} as ThunkAction< + void, + {}, + unknown, + UnknownAction + >) + // @ts-expect-error + store.dispatch(function () {} as ThunkAction< + void, + {}, + boolean, + UnknownAction + >) + }) + + test('custom middleware and getDefaultMiddleware', () => { + const store = configureStore({ + reducer: reducerA, + middleware: (gDM) => + gDM().prepend((() => {}) as any as Middleware< + (a: 'a') => 'A', + StateA + >), + }) + + expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>() + + expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf>() + + expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB()) + }) + + test('custom middleware and getDefaultMiddleware, using prepend', () => { + const otherMiddleware: Middleware<(a: 'a') => 'A', StateA> = + _anyMiddleware + + const store = configureStore({ + reducer: reducerA, + middleware: (gDM) => { + const concatenated = gDM().prepend(otherMiddleware) + + expectTypeOf(concatenated).toMatchTypeOf< + ReadonlyArray< + typeof otherMiddleware | ThunkMiddleware | Middleware<{}> + > + >() + + return concatenated + }, + }) + + expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>() + + expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf>() + + expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB()) + }) + + test('custom middleware and getDefaultMiddleware, using concat', () => { + const otherMiddleware: Middleware<(a: 'a') => 'A', StateA> = + _anyMiddleware + + const store = configureStore({ + reducer: reducerA, + middleware: (gDM) => { + const concatenated = gDM().concat(otherMiddleware) + + expectTypeOf(concatenated).toMatchTypeOf< + ReadonlyArray< + typeof otherMiddleware | ThunkMiddleware | Middleware<{}> + > + >() + + return concatenated + }, + }) + + expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>() + + expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf>() + + expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB()) + }) + + test('middlewareBuilder notation, getDefaultMiddleware (unconfigured)', () => { + const store = configureStore({ + reducer: reducerA, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware().prepend((() => {}) as any as Middleware< + (a: 'a') => 'A', + StateA + >), + }) + + expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>() + + expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf>() + + expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB()) + }) + + test('middlewareBuilder notation, getDefaultMiddleware, concat & prepend', () => { + const otherMiddleware: Middleware<(a: 'a') => 'A', StateA> = + _anyMiddleware + + const otherMiddleware2: Middleware<(a: 'b') => 'B', StateA> = + _anyMiddleware + + const store = configureStore({ + reducer: reducerA, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware() + .concat(otherMiddleware) + .prepend(otherMiddleware2), + }) + + expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>() + + expectTypeOf(store.dispatch(thunkA())).toEqualTypeOf>() + + expectTypeOf(store.dispatch('b')).toEqualTypeOf<'B'>() + + expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkB()) + }) + + test('middlewareBuilder notation, getDefaultMiddleware (thunk: false)', () => { + const store = configureStore({ + reducer: reducerA, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ thunk: false }).prepend( + (() => {}) as any as Middleware<(a: 'a') => 'A', StateA>, + ), + }) + + expectTypeOf(store.dispatch('a')).toEqualTypeOf<'A'>() + + expectTypeOf(store.dispatch).parameter(0).not.toMatchTypeOf(thunkA()) + }) + + test("badly typed middleware won't make `dispatch` `any`", () => { + const store = configureStore({ + reducer: reducerA, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware().concat(_anyMiddleware as Middleware), + }) + + expectTypeOf(store.dispatch).not.toBeAny() + }) + + test("decorated `configureStore` won't make `dispatch` `never`", () => { + const someSlice = createSlice({ + name: 'something', + initialState: null as any, + reducers: { + set(state) { + return state + }, + }, + }) + + function configureMyStore( + options: Omit, 'reducer'>, + ) { + return configureStore({ + ...options, + reducer: someSlice.reducer, + }) + } + + const store = configureMyStore({}) + + expectTypeOf(store.dispatch).toBeFunction() + }) + + interface CounterState { + value: number + } + + const counterSlice = createSlice({ + name: 'counter', + initialState: { value: 0 } as CounterState, + reducers: { + increment(state) { + state.value += 1 + }, + decrement(state) { + state.value -= 1 + }, + // Use the PayloadAction type to declare the contents of `action.payload` + incrementByAmount: (state, action: PayloadAction) => { + state.value += action.payload + }, + }, + }) + + type Unsubscribe = () => void + + // A fake middleware that tells TS that an unsubscribe callback is being returned for a given action + // This is the same signature that the "listener" middleware uses + const dummyMiddleware: Middleware< + { + (action: Action<'actionListenerMiddleware/add'>): Unsubscribe + }, + CounterState + > = (storeApi) => (next) => (action) => {} + + const store = configureStore({ + reducer: counterSlice.reducer, + middleware: (gDM) => gDM().prepend(dummyMiddleware), + }) + + // Order matters here! We need the listener type to come first, otherwise + // the thunk middleware type kicks in and TS thinks a plain action is being returned + expectTypeOf(store.dispatch).toEqualTypeOf< + ((action: Action<'actionListenerMiddleware/add'>) => Unsubscribe) & + ThunkDispatch & + Dispatch + >() + + const unsubscribe = store.dispatch({ + type: 'actionListenerMiddleware/add', + } as const) + + expectTypeOf(unsubscribe).toEqualTypeOf() + }) +}) diff --git a/packages/toolkit/src/tests/configureStore.test.ts b/packages/toolkit/src/tests/configureStore.test.ts index d122395fd8..3d78068919 100644 --- a/packages/toolkit/src/tests/configureStore.test.ts +++ b/packages/toolkit/src/tests/configureStore.test.ts @@ -1,11 +1,11 @@ -import { vi } from 'vitest' +import * as DevTools from '@internal/devtoolsExtension' import type { StoreEnhancer } from '@reduxjs/toolkit' import { Tuple } from '@reduxjs/toolkit' import type * as Redux from 'redux' -import type * as DevTools from '@internal/devtoolsExtension' +import { vi } from 'vitest' -vi.doMock('redux', async () => { - const redux: any = await vi.importActual('redux') +vi.doMock('redux', async (importOriginal) => { + const redux = await importOriginal() vi.spyOn(redux, 'applyMiddleware') vi.spyOn(redux, 'combineReducers') @@ -15,45 +15,8 @@ vi.doMock('redux', async () => { return redux }) -vi.doMock('@internal/devtoolsExtension', async () => { - const devtools: typeof DevTools = await vi.importActual( - '@internal/devtoolsExtension' - ) - vi.spyOn(devtools, 'composeWithDevTools') // @remap-prod-remove-line - return devtools -}) - -function originalReduxCompose(...funcs: Function[]) { - if (funcs.length === 0) { - // infer the argument type so it is usable in inference down the line - return (arg: T) => arg - } - - if (funcs.length === 1) { - return funcs[0] - } - - return funcs.reduce( - (a, b) => - (...args: any) => - a(b(...args)) - ) -} - -function originalComposeWithDevtools() { - if (arguments.length === 0) return undefined - if (typeof arguments[0] === 'object') return originalReduxCompose - return originalReduxCompose.apply(null, arguments as any as Function[]) -} - describe('configureStore', async () => { - // RTK's internal `composeWithDevtools` function isn't publicly exported, - // so we can't mock it. However, it _does_ try to access the global extension method - // attached to `window`. So, if we mock _that_, we'll know if the enhancer ran. - const mockDevtoolsCompose = vi - .fn() - .mockImplementation(originalComposeWithDevtools) - ;(window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ = mockDevtoolsCompose + const composeWithDevToolsSpy = vi.spyOn(DevTools, 'composeWithDevTools') const redux = await import('redux') @@ -73,10 +36,10 @@ describe('configureStore', async () => { expect(redux.createStore).toHaveBeenCalledWith( reducer, undefined, - expect.any(Function) + expect.any(Function), ) expect(redux.applyMiddleware).toHaveBeenCalled() - expect(mockDevtoolsCompose).toHaveBeenCalled() // @remap-prod-remove-line + expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line }) }) @@ -90,11 +53,11 @@ describe('configureStore', async () => { expect(configureStore({ reducer })).toBeInstanceOf(Object) expect(redux.combineReducers).toHaveBeenCalledWith(reducer) expect(redux.applyMiddleware).toHaveBeenCalled() - expect(mockDevtoolsCompose).toHaveBeenCalled() // @remap-prod-remove-line-line + expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line expect(redux.createStore).toHaveBeenCalledWith( expect.any(Function), undefined, - expect.any(Function) + expect.any(Function), ) }) }) @@ -102,7 +65,7 @@ describe('configureStore', async () => { describe('given no reducer', () => { it('throws', () => { expect(configureStore).toThrow( - '`reducer` is a required argument, and must be a function or an object of functions that can be passed to combineReducers' + '`reducer` is a required argument, and must be a function or an object of functions that can be passed to combineReducers', ) }) }) @@ -110,14 +73,14 @@ describe('configureStore', async () => { describe('given no middleware', () => { it('calls createStore without any middleware', () => { expect( - configureStore({ middleware: () => new Tuple(), reducer }) + configureStore({ middleware: () => new Tuple(), reducer }), ).toBeInstanceOf(Object) expect(redux.applyMiddleware).toHaveBeenCalledWith() - expect(mockDevtoolsCompose).toHaveBeenCalled() // @remap-prod-remove-line-line + expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line expect(redux.createStore).toHaveBeenCalledWith( reducer, undefined, - expect.any(Function) + expect.any(Function), ) }) }) @@ -126,7 +89,7 @@ describe('configureStore', async () => { it('throws an error requiring a callback', () => { // @ts-expect-error expect(() => configureStore({ middleware: [], reducer })).toThrow( - '`middleware` field must be a callback' + '`middleware` field must be a callback', ) }) }) @@ -134,19 +97,19 @@ describe('configureStore', async () => { describe('given undefined middleware', () => { it('calls createStore with default middleware', () => { expect(configureStore({ middleware: undefined, reducer })).toBeInstanceOf( - Object + Object, ) expect(redux.applyMiddleware).toHaveBeenCalledWith( expect.any(Function), // immutableCheck expect.any(Function), // thunk expect.any(Function), // serializableCheck - expect.any(Function) // actionCreatorCheck + expect.any(Function), // actionCreatorCheck ) - expect(mockDevtoolsCompose).toHaveBeenCalled() // @remap-prod-remove-line-line + expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line expect(redux.createStore).toHaveBeenCalledWith( reducer, undefined, - expect.any(Function) + expect.any(Function), ) }) }) @@ -155,9 +118,9 @@ describe('configureStore', async () => { it('throws an error', () => { const invalidBuilder = vi.fn((getDefaultMiddleware) => undefined as any) expect(() => - configureStore({ middleware: invalidBuilder, reducer }) + configureStore({ middleware: invalidBuilder, reducer }), ).toThrow( - 'when using a middleware builder function, an array of middleware must be returned' + 'when using a middleware builder function, an array of middleware must be returned', ) }) }) @@ -166,7 +129,7 @@ describe('configureStore', async () => { it('throws an error', () => { const invalidBuilder = vi.fn((getDefaultMiddleware) => [true] as any) expect(() => - configureStore({ middleware: invalidBuilder, reducer }) + configureStore({ middleware: invalidBuilder, reducer }), ).toThrow('each middleware provided to configureStore must be a function') }) }) @@ -176,14 +139,14 @@ describe('configureStore', async () => { const thank: Redux.Middleware = (_store) => (next) => (action) => next(action) expect( - configureStore({ middleware: () => new Tuple(thank), reducer }) + configureStore({ middleware: () => new Tuple(thank), reducer }), ).toBeInstanceOf(Object) expect(redux.applyMiddleware).toHaveBeenCalledWith(thank) - expect(mockDevtoolsCompose).toHaveBeenCalled() // @remap-prod-remove-line-line + expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line expect(redux.createStore).toHaveBeenCalledWith( reducer, undefined, - expect.any(Function) + expect.any(Function), ) }) }) @@ -191,7 +154,7 @@ describe('configureStore', async () => { describe('middleware builder notation', () => { it('calls builder, passes getDefaultMiddleware and uses returned middlewares', () => { const thank = vi.fn( - ((_store) => (next) => (action) => 'foobar') as Redux.Middleware + ((_store) => (next) => (action) => 'foobar') as Redux.Middleware, ) const builder = vi.fn((getDefaultMiddleware) => { @@ -212,14 +175,14 @@ describe('configureStore', async () => { describe('with devTools disabled', () => { it('calls createStore without devTools enhancer', () => { expect(configureStore({ devTools: false, reducer })).toBeInstanceOf( - Object + Object, ) expect(redux.applyMiddleware).toHaveBeenCalled() expect(redux.compose).toHaveBeenCalled() expect(redux.createStore).toHaveBeenCalledWith( reducer, undefined, - expect.any(Function) + expect.any(Function), ) }) }) @@ -231,14 +194,14 @@ describe('configureStore', async () => { trace: true, } expect(configureStore({ devTools: options, reducer })).toBeInstanceOf( - Object + Object, ) expect(redux.applyMiddleware).toHaveBeenCalled() - expect(mockDevtoolsCompose).toHaveBeenCalledWith(options) // @remap-prod-remove-line + expect(composeWithDevToolsSpy).toHaveBeenCalledWith(options) // @remap-prod-remove-line expect(redux.createStore).toHaveBeenCalledWith( reducer, undefined, - expect.any(Function) + expect.any(Function), ) }) }) @@ -247,11 +210,11 @@ describe('configureStore', async () => { it('calls createStore with preloadedState', () => { expect(configureStore({ reducer })).toBeInstanceOf(Object) expect(redux.applyMiddleware).toHaveBeenCalled() - expect(mockDevtoolsCompose).toHaveBeenCalled() // @remap-prod-remove-line + expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line expect(redux.createStore).toHaveBeenCalledWith( reducer, undefined, - expect.any(Function) + expect.any(Function), ) }) }) @@ -275,14 +238,14 @@ describe('configureStore', async () => { configureStore({ enhancers: (gDE) => gDE().concat(dummyEnhancer), reducer, - }) + }), ).toBeInstanceOf(Object) expect(redux.applyMiddleware).toHaveBeenCalled() - expect(mockDevtoolsCompose).toHaveBeenCalled() // @remap-prod-remove-line + expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line expect(redux.createStore).toHaveBeenCalledWith( reducer, undefined, - expect.any(Function) + expect.any(Function), ) expect(dummyEnhancerCalled).toBe(true) @@ -291,19 +254,19 @@ describe('configureStore', async () => { describe('invalid arguments', () => { test('enhancers is not a callback', () => { expect(() => configureStore({ reducer, enhancers: [] as any })).toThrow( - '`enhancers` field must be a callback' + '`enhancers` field must be a callback', ) }) test('callback fails to return array', () => { expect(() => - configureStore({ reducer, enhancers: (() => {}) as any }) + configureStore({ reducer, enhancers: (() => {}) as any }), ).toThrow('`enhancers` callback must return an array') }) test('array contains non-function', () => { expect(() => - configureStore({ reducer, enhancers: (() => ['']) as any }) + configureStore({ reducer, enhancers: (() => ['']) as any }), ).toThrow('each enhancer provided to configureStore must be a function') }) }) @@ -325,7 +288,7 @@ describe('configureStore', async () => { expect(dummyEnhancerCalled).toBe(true) expect(consoleSpy).toHaveBeenCalledWith( - 'middlewares were provided, but middleware enhancer was not included in final enhancers - make sure to call `getDefaultEnhancers`' + 'middlewares were provided, but middleware enhancer was not included in final enhancers - make sure to call `getDefaultEnhancers`', ) }) it("doesn't warn when middleware enhancer is excluded if no middlewares provided", () => { diff --git a/packages/toolkit/src/tests/configureStore.typetest.ts b/packages/toolkit/src/tests/configureStore.typetest.ts deleted file mode 100644 index 041f1141a9..0000000000 --- a/packages/toolkit/src/tests/configureStore.typetest.ts +++ /dev/null @@ -1,833 +0,0 @@ -/* eslint-disable no-lone-blocks */ -import type { - Dispatch, - UnknownAction, - Middleware, - Reducer, - Store, - Action, - StoreEnhancer, -} from 'redux' -import { applyMiddleware, combineReducers } from 'redux' -import type { PayloadAction, ConfigureStoreOptions } from '@reduxjs/toolkit' -import { configureStore, createSlice, Tuple } from '@reduxjs/toolkit' -import type { ThunkMiddleware, ThunkAction, ThunkDispatch } from 'redux-thunk' -import { thunk } from 'redux-thunk' -import { expectExactType, expectNotAny, expectType } from './helpers' - -const _anyMiddleware: any = () => () => () => {} - -/* - * Test: configureStore() requires a valid reducer or reducer map. - */ -{ - configureStore({ - reducer: (state, action) => 0, - }) - - configureStore({ - reducer: { - counter1: () => 0, - counter2: () => 1, - }, - }) - - // @ts-expect-error - configureStore({ reducer: 'not a reducer' }) - - // @ts-expect-error - configureStore({ reducer: { a: 'not a reducer' } }) - - // @ts-expect-error - configureStore({}) -} - -/* - * Test: configureStore() infers the store state type. - */ -{ - const reducer: Reducer = () => 0 - const store = configureStore({ reducer }) - const numberStore: Store = store - - // @ts-expect-error - const stringStore: Store = store -} - -/* - * Test: configureStore() infers the store action type. - */ -{ - const reducer: Reducer> = () => 0 - const store = configureStore({ reducer }) - const numberStore: Store> = store - - // @ts-expect-error - const stringStore: Store> = store -} - -/* - * Test: configureStore() accepts Tuple, but not plain array. - */ -{ - const middleware: Middleware = (store) => (next) => next - - configureStore({ - reducer: () => 0, - middleware: () => new Tuple(middleware), - }) - - configureStore({ - reducer: () => 0, - // @ts-expect-error - middleware: () => [middleware], - }) - - configureStore({ - reducer: () => 0, - // @ts-expect-error - middleware: () => new Tuple('not middleware'), - }) -} - -/* - * Test: configureStore() accepts devTools flag. - */ -{ - configureStore({ - reducer: () => 0, - devTools: true, - }) - - configureStore({ - reducer: () => 0, - // @ts-expect-error - devTools: 'true', - }) -} - -/* - * Test: configureStore() accepts devTools EnhancerOptions. - */ -{ - configureStore({ - reducer: () => 0, - devTools: { name: 'myApp' }, - }) - - configureStore({ - reducer: () => 0, - // @ts-expect-error - devTools: { appname: 'myApp' }, - }) -} - -/* - * Test: configureStore() accepts preloadedState. - */ -{ - configureStore({ - reducer: () => 0, - preloadedState: 0, - }) - - configureStore({ - // @ts-expect-error - reducer: (_: number) => 0, - preloadedState: 'non-matching state type', - }) -} - -/** - * Test: nullable state is preserved - */ - -{ - const store = configureStore({ - reducer: (): string | null => null, - }) - expectExactType(null)(store.getState()) -} - -/* - * Test: configureStore() accepts store Tuple, but not plain array - */ -{ - { - const enhancer = applyMiddleware(() => (next) => next) - - const store = configureStore({ - reducer: () => 0, - enhancers: () => new Tuple(enhancer), - }) - - const store2 = configureStore({ - reducer: () => 0, - // @ts-expect-error - enhancers: () => [enhancer], - }) - - expectType>( - store.dispatch - ) - } - - configureStore({ - reducer: () => 0, - // @ts-expect-error - enhancers: () => new Tuple('not a store enhancer'), - }) - - { - const somePropertyStoreEnhancer: StoreEnhancer<{ someProperty: string }> = ( - next - ) => { - return (reducer, preloadedState) => { - return { - ...next(reducer, preloadedState), - someProperty: 'some value', - } - } - } - - const anotherPropertyStoreEnhancer: StoreEnhancer<{ - anotherProperty: number - }> = (next) => { - return (reducer, preloadedState) => { - return { - ...next(reducer, preloadedState), - anotherProperty: 123, - } - } - } - - const store = configureStore({ - reducer: () => 0, - enhancers: () => - new Tuple(somePropertyStoreEnhancer, anotherPropertyStoreEnhancer), - }) - - expectType(store.dispatch) - expectType(store.someProperty) - expectType(store.anotherProperty) - - const storeWithCallback = configureStore({ - reducer: () => 0, - enhancers: (getDefaultEnhancers) => - getDefaultEnhancers() - .prepend(anotherPropertyStoreEnhancer) - .concat(somePropertyStoreEnhancer), - }) - - expectType>( - store.dispatch - ) - expectType(storeWithCallback.someProperty) - expectType(storeWithCallback.anotherProperty) - } - - { - const someStateExtendingEnhancer: StoreEnhancer< - {}, - { someProperty: string } - > = - (next) => - (...args) => { - const store = next(...args) - const getState = () => ({ - ...store.getState(), - someProperty: 'some value', - }) - return { - ...store, - getState, - } as any - } - - const anotherStateExtendingEnhancer: StoreEnhancer< - {}, - { anotherProperty: number } - > = - (next) => - (...args) => { - const store = next(...args) - const getState = () => ({ - ...store.getState(), - anotherProperty: 123, - }) - return { - ...store, - getState, - } as any - } - - const store = configureStore({ - reducer: () => ({ aProperty: 0 }), - enhancers: () => - new Tuple(someStateExtendingEnhancer, anotherStateExtendingEnhancer), - }) - - const state = store.getState() - expectType(state.aProperty) - expectType(state.someProperty) - expectType(state.anotherProperty) - - const storeWithCallback = configureStore({ - reducer: () => ({ aProperty: 0 }), - enhancers: (gDE) => - gDE().concat(someStateExtendingEnhancer, anotherStateExtendingEnhancer), - }) - - const stateWithCallback = storeWithCallback.getState() - - expectType(stateWithCallback.aProperty) - expectType(stateWithCallback.someProperty) - expectType(stateWithCallback.anotherProperty) - } -} - -/** - * Test: Preloaded state typings - */ -{ - let counterReducer1: Reducer = () => 0 - let counterReducer2: Reducer = () => 0 - - /** - * Test: partial preloaded state - */ - { - const store = configureStore({ - reducer: { - counter1: counterReducer1, - counter2: counterReducer2, - }, - preloadedState: { - counter1: 0, - }, - }) - - const counter1: number = store.getState().counter1 - const counter2: number = store.getState().counter2 - } - - /** - * Test: empty preloaded state - */ - { - const store = configureStore({ - reducer: { - counter1: counterReducer1, - counter2: counterReducer2, - }, - preloadedState: {}, - }) - - const counter1: number = store.getState().counter1 - const counter2: number = store.getState().counter2 - } - - /** - * Test: excess properties in preloaded state - */ - { - const store = configureStore({ - reducer: { - // @ts-expect-error - counter1: counterReducer1, - counter2: counterReducer2, - }, - preloadedState: { - counter1: 0, - counter3: 5, - }, - }) - - const counter1: number = store.getState().counter1 - const counter2: number = store.getState().counter2 - } - - /** - * Test: mismatching properties in preloaded state - */ - { - const store = configureStore({ - reducer: { - // @ts-expect-error - counter1: counterReducer1, - counter2: counterReducer2, - }, - preloadedState: { - counter3: 5, - }, - }) - - const counter1: number = store.getState().counter1 - const counter2: number = store.getState().counter2 - } - - /** - * Test: string preloaded state when expecting object - */ - { - const store = configureStore({ - reducer: { - // @ts-expect-error - counter1: counterReducer1, - counter2: counterReducer2, - }, - preloadedState: 'test', - }) - - const counter1: number = store.getState().counter1 - const counter2: number = store.getState().counter2 - } - - /** - * Test: nested combineReducers allows partial - */ - { - const store = configureStore({ - reducer: { - group1: combineReducers({ - counter1: counterReducer1, - counter2: counterReducer2, - }), - group2: combineReducers({ - counter1: counterReducer1, - counter2: counterReducer2, - }), - }, - preloadedState: { - group1: { - counter1: 5, - }, - }, - }) - - const group1counter1: number = store.getState().group1.counter1 - const group1counter2: number = store.getState().group1.counter2 - const group2counter1: number = store.getState().group2.counter1 - const group2counter2: number = store.getState().group2.counter2 - } - - /** - * Test: non-nested combineReducers does not allow partial - */ - { - interface GroupState { - counter1: number - counter2: number - } - - const initialState = { counter1: 0, counter2: 0 } - - const group1Reducer: Reducer = (state = initialState) => state - const group2Reducer: Reducer = (state = initialState) => state - - const store = configureStore({ - reducer: { - // @ts-expect-error - group1: group1Reducer, - group2: group2Reducer, - }, - preloadedState: { - group1: { - counter1: 5, - }, - }, - }) - - const group1counter1: number = store.getState().group1.counter1 - const group1counter2: number = store.getState().group1.counter2 - const group2counter1: number = store.getState().group2.counter1 - const group2counter2: number = store.getState().group2.counter2 - } -} - -/** - * Test: Dispatch typings - */ -{ - type StateA = number - const reducerA = () => 0 - function thunkA() { - return (() => {}) as any as ThunkAction, StateA, any, any> - } - - type StateB = string - function thunkB() { - return (dispatch: Dispatch, getState: () => StateB) => {} - } - /** - * Test: by default, dispatching Thunks is possible - */ - { - const store = configureStore({ - reducer: reducerA, - }) - - store.dispatch(thunkA()) - // @ts-expect-error - store.dispatch(thunkB()) - - const res = store.dispatch((dispatch, getState) => { - return 42 - }) - - const action = store.dispatch({ type: 'foo' }) - } - /** - * Test: return type of thunks and actions is inferred correctly - */ - { - const slice = createSlice({ - name: 'counter', - initialState: { - value: 0, - }, - reducers: { - incrementByAmount: (state, action: PayloadAction) => { - state.value += action.payload - }, - }, - }) - - const store = configureStore({ - reducer: { - counter: slice.reducer, - }, - }) - - const action = slice.actions.incrementByAmount(2) - - const dispatchResult = store.dispatch(action) - expectType<{ type: string; payload: number }>(dispatchResult) - - const promiseResult = store.dispatch(async (dispatch) => { - return 42 - }) - - expectType>(promiseResult) - - const store2 = configureStore({ - reducer: { - counter: slice.reducer, - }, - middleware: (gDM) => - gDM({ - thunk: { - extraArgument: 42, - }, - }), - }) - - const dispatchResult2 = store2.dispatch(action) - expectType<{ type: string; payload: number }>(dispatchResult2) - } - /** - * Test: removing the Thunk Middleware - */ - { - const store = configureStore({ - reducer: reducerA, - middleware: () => new Tuple(), - }) - // @ts-expect-error - store.dispatch(thunkA()) - // @ts-expect-error - store.dispatch(thunkB()) - } - /** - * Test: adding the thunk middleware by hand - */ - { - const store = configureStore({ - reducer: reducerA, - middleware: () => new Tuple(thunk as ThunkMiddleware), - }) - store.dispatch(thunkA()) - // @ts-expect-error - store.dispatch(thunkB()) - } - /** - * Test: custom middleware - */ - { - const store = configureStore({ - reducer: reducerA, - middleware: () => - new Tuple(0 as unknown as Middleware<(a: StateA) => boolean, StateA>), - }) - const result: boolean = store.dispatch(5) - // @ts-expect-error - const result2: string = store.dispatch(5) - } - /** - * Test: multiple custom middleware - */ - { - const middleware = [] as any as Tuple< - [ - Middleware<(a: 'a') => 'A', StateA>, - Middleware<(b: 'b') => 'B', StateA>, - ThunkMiddleware - ] - > - const store = configureStore({ - reducer: reducerA, - middleware: () => middleware, - }) - - const result: 'A' = store.dispatch('a') - const result2: 'B' = store.dispatch('b') - const result3: Promise<'A'> = store.dispatch(thunkA()) - } - /** - * Accepts thunk with `unknown`, `undefined` or `null` ThunkAction extraArgument per default - */ - { - const store = configureStore({ reducer: {} }) - // undefined is the default value for the ThunkMiddleware extraArgument - store.dispatch(function () {} as ThunkAction< - void, - {}, - undefined, - UnknownAction - >) - // `null` for the `extra` generic was previously documented in the RTK "Advanced Tutorial", but - // is a bad pattern and users should use `unknown` instead - // @ts-expect-error - store.dispatch(function () {} as ThunkAction) - // unknown is the best way to type a ThunkAction if you do not care - // about the value of the extraArgument, as it will always work with every - // ThunkMiddleware, no matter the actual extraArgument type - store.dispatch(function () {} as ThunkAction< - void, - {}, - unknown, - UnknownAction - >) - // @ts-expect-error - store.dispatch(function () {} as ThunkAction< - void, - {}, - boolean, - UnknownAction - >) - } - - /** - * Test: custom middleware and getDefaultMiddleware - */ - { - const store = configureStore({ - reducer: reducerA, - middleware: (gDM) => - gDM().prepend((() => {}) as any as Middleware<(a: 'a') => 'A', StateA>), - }) - - const result1: 'A' = store.dispatch('a') - const result2: Promise<'A'> = store.dispatch(thunkA()) - // @ts-expect-error - store.dispatch(thunkB()) - } - - /** - * Test: custom middleware and getDefaultMiddleware, using prepend - */ - { - const otherMiddleware: Middleware<(a: 'a') => 'A', StateA> = _anyMiddleware - - const store = configureStore({ - reducer: reducerA, - middleware: (gDM) => { - const concatenated = gDM().prepend(otherMiddleware) - expectType< - ReadonlyArray< - typeof otherMiddleware | ThunkMiddleware | Middleware<{}> - > - >(concatenated) - - return concatenated - }, - }) - const result1: 'A' = store.dispatch('a') - const result2: Promise<'A'> = store.dispatch(thunkA()) - // @ts-expect-error - store.dispatch(thunkB()) - } - - /** - * Test: custom middleware and getDefaultMiddleware, using concat - */ - { - const otherMiddleware: Middleware<(a: 'a') => 'A', StateA> = _anyMiddleware - - const store = configureStore({ - reducer: reducerA, - middleware: (gDM) => { - const concatenated = gDM().concat(otherMiddleware) - - expectType< - ReadonlyArray< - typeof otherMiddleware | ThunkMiddleware | Middleware<{}> - > - >(concatenated) - return concatenated - }, - }) - const result1: 'A' = store.dispatch('a') - const result2: Promise<'A'> = store.dispatch(thunkA()) - // @ts-expect-error - store.dispatch(thunkB()) - } - - /** - * Test: middlewareBuilder notation, getDefaultMiddleware (unconfigured) - */ - { - const store = configureStore({ - reducer: reducerA, - middleware: (getDefaultMiddleware) => - getDefaultMiddleware().prepend((() => {}) as any as Middleware< - (a: 'a') => 'A', - StateA - >), - }) - const result1: 'A' = store.dispatch('a') - const result2: Promise<'A'> = store.dispatch(thunkA()) - // @ts-expect-error - store.dispatch(thunkB()) - } - - /** - * Test: middlewareBuilder notation, getDefaultMiddleware, concat & prepend - */ - { - const otherMiddleware: Middleware<(a: 'a') => 'A', StateA> = _anyMiddleware - const otherMiddleware2: Middleware<(a: 'b') => 'B', StateA> = _anyMiddleware - const store = configureStore({ - reducer: reducerA, - middleware: (getDefaultMiddleware) => - getDefaultMiddleware() - .concat(otherMiddleware) - .prepend(otherMiddleware2), - }) - const result1: 'A' = store.dispatch('a') - const result2: Promise<'A'> = store.dispatch(thunkA()) - const result3: 'B' = store.dispatch('b') - // @ts-expect-error - store.dispatch(thunkB()) - } - - /** - * Test: middlewareBuilder notation, getDefaultMiddleware (thunk: false) - */ - { - const store = configureStore({ - reducer: reducerA, - middleware: (getDefaultMiddleware) => - getDefaultMiddleware({ thunk: false }).prepend( - (() => {}) as any as Middleware<(a: 'a') => 'A', StateA> - ), - }) - const result1: 'A' = store.dispatch('a') - // @ts-expect-error - store.dispatch(thunkA()) - } - - /** - * Test: badly typed middleware won't make `dispatch` `any` - */ - { - const store = configureStore({ - reducer: reducerA, - middleware: (getDefaultMiddleware) => - getDefaultMiddleware().concat(_anyMiddleware as Middleware), - }) - - expectNotAny(store.dispatch) - } - - /** - * Test: decorated `configureStore` won't make `dispatch` `never` - */ - { - const someSlice = createSlice({ - name: 'something', - initialState: null as any, - reducers: { - set(state) { - return state - }, - }, - }) - - function configureMyStore( - options: Omit, 'reducer'> - ) { - return configureStore({ - ...options, - reducer: someSlice.reducer, - }) - } - - const store = configureMyStore({}) - - expectType(store.dispatch) - } - - { - interface CounterState { - value: number - } - - const counterSlice = createSlice({ - name: 'counter', - initialState: { value: 0 } as CounterState, - reducers: { - increment(state) { - state.value += 1 - }, - decrement(state) { - state.value -= 1 - }, - // Use the PayloadAction type to declare the contents of `action.payload` - incrementByAmount: (state, action: PayloadAction) => { - state.value += action.payload - }, - }, - }) - - type Unsubscribe = () => void - - // A fake middleware that tells TS that an unsubscribe callback is being returned for a given action - // This is the same signature that the "listener" middleware uses - const dummyMiddleware: Middleware< - { - (action: Action<'actionListenerMiddleware/add'>): Unsubscribe - }, - CounterState - > = (storeApi) => (next) => (action) => {} - - const store = configureStore({ - reducer: counterSlice.reducer, - middleware: (gDM) => gDM().prepend(dummyMiddleware), - }) - - // Order matters here! We need the listener type to come first, otherwise - // the thunk middleware type kicks in and TS thinks a plain action is being returned - expectType< - ((action: Action<'actionListenerMiddleware/add'>) => Unsubscribe) & - ThunkDispatch & - Dispatch - >(store.dispatch) - - const unsubscribe = store.dispatch({ - type: 'actionListenerMiddleware/add', - } as const) - - expectType(unsubscribe) - } -} diff --git a/packages/toolkit/src/tests/createAction.test-d.tsx b/packages/toolkit/src/tests/createAction.test-d.tsx new file mode 100644 index 0000000000..c7af7ffab2 --- /dev/null +++ b/packages/toolkit/src/tests/createAction.test-d.tsx @@ -0,0 +1,326 @@ +import type { + Action, + ActionCreator, + ActionCreatorWithNonInferrablePayload, + ActionCreatorWithOptionalPayload, + ActionCreatorWithPayload, + ActionCreatorWithPreparedPayload, + ActionCreatorWithoutPayload, + PayloadAction, + PayloadActionCreator, + UnknownAction, +} from '@reduxjs/toolkit' +import { createAction } from '@reduxjs/toolkit' + +describe('type tests', () => { + describe('PayloadAction', () => { + test('PayloadAction has type parameter for the payload.', () => { + const action: PayloadAction = { type: '', payload: 5 } + + expectTypeOf(action.payload).toBeNumber() + + expectTypeOf(action.payload).not.toBeString() + }) + + test('PayloadAction type parameter is required.', () => { + expectTypeOf({ type: '', payload: 5 }).not.toMatchTypeOf() + }) + + test('PayloadAction has a string type tag.', () => { + expectTypeOf({ type: '', payload: 5 }).toEqualTypeOf< + PayloadAction + >() + + expectTypeOf({ type: 1, payload: 5 }).not.toMatchTypeOf() + }) + + test('PayloadAction is compatible with Action', () => { + const action: PayloadAction = { type: '', payload: 5 } + + expectTypeOf(action).toMatchTypeOf>() + }) + }) + + describe('PayloadActionCreator', () => { + test('PayloadActionCreator returns correctly typed PayloadAction depending on whether a payload is passed.', () => { + const actionCreator = Object.assign( + (payload?: number) => ({ + type: 'action', + payload, + }), + { type: 'action' }, + ) as PayloadActionCreator + + expectTypeOf(actionCreator(1)).toEqualTypeOf< + PayloadAction + >() + + expectTypeOf(actionCreator()).toEqualTypeOf< + PayloadAction + >() + + expectTypeOf(actionCreator(undefined)).toEqualTypeOf< + PayloadAction + >() + + expectTypeOf(actionCreator()).not.toMatchTypeOf>() + + expectTypeOf(actionCreator(1)).not.toMatchTypeOf< + PayloadAction + >() + }) + + test('PayloadActionCreator is compatible with ActionCreator.', () => { + const payloadActionCreator = Object.assign( + (payload?: number) => ({ + type: 'action', + payload, + }), + { type: 'action' }, + ) as PayloadActionCreator + + expectTypeOf(payloadActionCreator).toMatchTypeOf< + ActionCreator + >() + + const payloadActionCreator2 = Object.assign( + (payload?: number) => ({ + type: 'action', + payload: payload || 1, + }), + { type: 'action' }, + ) as PayloadActionCreator + + expectTypeOf(payloadActionCreator2).toMatchTypeOf< + ActionCreator> + >() + }) + }) + + test('createAction() has type parameter for the action payload.', () => { + const increment = createAction('increment') + + expectTypeOf(increment).parameter(0).toBeNumber() + + expectTypeOf(increment).parameter(0).not.toBeString() + }) + + test('createAction() type parameter is required, not inferred (defaults to `void`).', () => { + const increment = createAction('increment') + + expectTypeOf(increment).parameter(0).not.toBeNumber() + + expectTypeOf(increment().payload).not.toBeNumber() + }) + + test('createAction().type is a string literal.', () => { + const increment = createAction('increment') + + expectTypeOf(increment(1).type).toBeString() + + expectTypeOf(increment(1).type).toEqualTypeOf<'increment'>() + + expectTypeOf(increment(1).type).not.toMatchTypeOf<'other'>() + + expectTypeOf(increment(1).type).not.toBeNumber() + }) + + test('type still present when using prepareAction', () => { + const strLenAction = createAction('strLen', (payload: string) => ({ + payload: payload.length, + })) + + expectTypeOf(strLenAction('test').type).toBeString() + }) + + test('changing payload type with prepareAction', () => { + const strLenAction = createAction('strLen', (payload: string) => ({ + payload: payload.length, + })) + + expectTypeOf(strLenAction('test').payload).toBeNumber() + + expectTypeOf(strLenAction('test').payload).not.toBeString() + + expectTypeOf(strLenAction('test')).not.toHaveProperty('error') + }) + + test('adding metadata with prepareAction', () => { + const strLenMetaAction = createAction('strLenMeta', (payload: string) => ({ + payload, + meta: payload.length, + })) + + expectTypeOf(strLenMetaAction('test').meta).toBeNumber() + + expectTypeOf(strLenMetaAction('test').meta).not.toBeString() + + expectTypeOf(strLenMetaAction('test')).not.toHaveProperty('error') + }) + + test('adding boolean error with prepareAction', () => { + const boolErrorAction = createAction('boolError', (payload: string) => ({ + payload, + error: true, + })) + + expectTypeOf(boolErrorAction('test').error).toBeBoolean() + + expectTypeOf(boolErrorAction('test').error).not.toBeString() + }) + + test('adding string error with prepareAction', () => { + const strErrorAction = createAction('strError', (payload: string) => ({ + payload, + error: 'this is an error', + })) + + expectTypeOf(strErrorAction('test').error).toBeString() + + expectTypeOf(strErrorAction('test').error).not.toBeBoolean() + }) + + test('regression test for https://github.com/reduxjs/redux-toolkit/issues/214', () => { + const action = createAction<{ input?: string }>('ACTION') + + expectTypeOf(action({ input: '' }).payload.input).toEqualTypeOf< + string | undefined + >() + + expectTypeOf(action({ input: '' }).payload.input).not.toBeNumber() + + expectTypeOf(action).parameter(0).not.toMatchTypeOf({ input: 3 }) + }) + + test('regression test for https://github.com/reduxjs/redux-toolkit/issues/224', () => { + const oops = createAction('oops', (x: any) => ({ + payload: x, + error: x, + meta: x, + })) + + expectTypeOf(oops('').payload).toBeAny() + + expectTypeOf(oops('').error).toBeAny() + + expectTypeOf(oops('').meta).toBeAny() + }) + + describe('createAction.match()', () => { + test('simple use case', () => { + const actionCreator = createAction('test') + + const x: Action = {} as any + + if (actionCreator.match(x)) { + expectTypeOf(x.type).toEqualTypeOf<'test'>() + + expectTypeOf(x.payload).toBeString() + } else { + expectTypeOf(x.type).not.toMatchTypeOf<'test'>() + + expectTypeOf(x).not.toHaveProperty('payload') + } + }) + + test('special case: optional argument', () => { + const actionCreator = createAction('test') + + const x: Action = {} as any + + if (actionCreator.match(x)) { + expectTypeOf(x.type).toEqualTypeOf<'test'>() + + expectTypeOf(x.payload).toEqualTypeOf() + } + }) + + test('special case: without argument', () => { + const actionCreator = createAction('test') + + const x: Action = {} as any + + if (actionCreator.match(x)) { + expectTypeOf(x.type).toEqualTypeOf<'test'>() + + expectTypeOf(x.payload).not.toMatchTypeOf<{}>() + } + }) + + test('special case: with prepareAction', () => { + const actionCreator = createAction('test', () => ({ + payload: '', + meta: '', + error: false, + })) + + const x: Action = {} as any + + if (actionCreator.match(x)) { + expectTypeOf(x.type).toEqualTypeOf<'test'>() + + expectTypeOf(x.payload).toBeString() + + expectTypeOf(x.meta).toBeString() + + expectTypeOf(x.error).toBeBoolean() + + expectTypeOf(x.payload).not.toBeNumber() + + expectTypeOf(x.meta).not.toBeNumber() + + expectTypeOf(x.error).not.toBeNumber() + } + }) + test('potential use: as array filter', () => { + const actionCreator = createAction('test') + + const x: Action[] = [] + + expectTypeOf(x.filter(actionCreator.match)).toEqualTypeOf< + PayloadAction[] + >() + }) + }) + + test('ActionCreatorWithOptionalPayload', () => { + expectTypeOf(createAction('')).toEqualTypeOf< + ActionCreatorWithOptionalPayload + >() + + expectTypeOf( + createAction(''), + ).toEqualTypeOf() + + assertType(createAction('')) + + expectTypeOf(createAction('')).toEqualTypeOf< + ActionCreatorWithPayload + >() + + expectTypeOf( + createAction('', (_: 0) => ({ + payload: 1 as 1, + error: 2 as 2, + meta: 3 as 3, + })), + ).toEqualTypeOf>() + + const anyCreator = createAction('') + + expectTypeOf(anyCreator).toEqualTypeOf>() + + expectTypeOf(anyCreator({}).payload).toBeAny() + }) + + test("Verify action creators should not be passed directly as arguments to React event handlers if there shouldn't be a payload", () => { + const emptyAction = createAction('empty/action') + + function TestComponent() { + // This typically leads to an error like: + // // A non-serializable value was detected in an action, in the path: `payload`. + // @ts-expect-error Should error because `void` and `MouseEvent` aren't compatible + return + } + }) +}) diff --git a/packages/toolkit/src/tests/createAction.test.ts b/packages/toolkit/src/tests/createAction.test.ts index 2c4a80e13d..74e02e17cd 100644 --- a/packages/toolkit/src/tests/createAction.test.ts +++ b/packages/toolkit/src/tests/createAction.test.ts @@ -98,7 +98,7 @@ describe('createAction', () => { 'A_TYPE', (a: string, b: string, c: string) => ({ payload: a + b + c, - }) + }), ) expect(actionCreator('1', '2', '3').payload).toBe('123') }) diff --git a/packages/toolkit/src/tests/createAction.typetest.tsx b/packages/toolkit/src/tests/createAction.typetest.tsx deleted file mode 100644 index 991d8c0f63..0000000000 --- a/packages/toolkit/src/tests/createAction.typetest.tsx +++ /dev/null @@ -1,359 +0,0 @@ -import React from 'react' -import type { Action, UnknownAction, ActionCreator } from 'redux' -import type { - PayloadAction, - PayloadActionCreator, - ActionCreatorWithoutPayload, - ActionCreatorWithOptionalPayload, - ActionCreatorWithPayload, - ActionCreatorWithNonInferrablePayload, - ActionCreatorWithPreparedPayload, -} from '@reduxjs/toolkit' -import { createAction } from '@reduxjs/toolkit' -import type { IsAny } from '@internal/tsHelpers' -import { expectType } from './helpers' - -/* PayloadAction */ - -/* - * Test: PayloadAction has type parameter for the payload. - */ -{ - const action: PayloadAction = { type: '', payload: 5 } - const numberPayload: number = action.payload - - // @ts-expect-error - const stringPayload: string = action.payload -} - -/* - * Test: PayloadAction type parameter is required. - */ -{ - // @ts-expect-error - const action: PayloadAction = { type: '', payload: 5 } - // @ts-expect-error - const numberPayload: number = action.payload - // @ts-expect-error - const stringPayload: string = action.payload -} - -/* - * Test: PayloadAction has a string type tag. - */ -{ - const action: PayloadAction = { type: '', payload: 5 } - - // @ts-expect-error - const action2: PayloadAction = { type: 1, payload: 5 } -} - -/* - * Test: PayloadAction is compatible with Action - */ -{ - const action: PayloadAction = { type: '', payload: 5 } - const stringAction: Action = action -} - -/* PayloadActionCreator */ - -/* - * Test: PayloadActionCreator returns correctly typed PayloadAction depending - * on whether a payload is passed. - */ -{ - const actionCreator = Object.assign( - (payload?: number) => ({ - type: 'action', - payload, - }), - { type: 'action' } - ) as PayloadActionCreator - - expectType>(actionCreator(1)) - expectType>(actionCreator()) - expectType>(actionCreator(undefined)) - - // @ts-expect-error - expectType>(actionCreator()) - // @ts-expect-error - expectType>(actionCreator(1)) -} - -/* - * Test: PayloadActionCreator is compatible with ActionCreator. - */ -{ - const payloadActionCreator = Object.assign( - (payload?: number) => ({ - type: 'action', - payload, - }), - { type: 'action' } - ) as PayloadActionCreator - const actionCreator: ActionCreator = payloadActionCreator - - const payloadActionCreator2 = Object.assign( - (payload?: number) => ({ - type: 'action', - payload: payload || 1, - }), - { type: 'action' } - ) as PayloadActionCreator - - const actionCreator2: ActionCreator> = - payloadActionCreator2 -} - -/* createAction() */ - -/* - * Test: createAction() has type parameter for the action payload. - */ -{ - const increment = createAction('increment') - const n: number = increment(1).payload - - // @ts-expect-error - increment('').payload -} - -/* - * Test: createAction() type parameter is required, not inferred (defaults to `void`). - */ -{ - const increment = createAction('increment') - // @ts-expect-error - const n: number = increment(1).payload -} -/* - * Test: createAction().type is a string literal. - */ -{ - const increment = createAction('increment') - const n: string = increment(1).type - const s: 'increment' = increment(1).type - - // @ts-expect-error - const r: 'other' = increment(1).type - // @ts-expect-error - const q: number = increment(1).type -} - -/* - * Test: type still present when using prepareAction - */ -{ - const strLenAction = createAction('strLen', (payload: string) => ({ - payload: payload.length, - })) - - expectType(strLenAction('test').type) -} - -/* - * Test: changing payload type with prepareAction - */ -{ - const strLenAction = createAction('strLen', (payload: string) => ({ - payload: payload.length, - })) - expectType(strLenAction('test').payload) - - // @ts-expect-error - expectType(strLenAction('test').payload) - // @ts-expect-error - const error: any = strLenAction('test').error -} - -/* - * Test: adding metadata with prepareAction - */ -{ - const strLenMetaAction = createAction('strLenMeta', (payload: string) => ({ - payload, - meta: payload.length, - })) - - expectType(strLenMetaAction('test').meta) - - // @ts-expect-error - expectType(strLenMetaAction('test').meta) - // @ts-expect-error - const error: any = strLenMetaAction('test').error -} - -/* - * Test: adding boolean error with prepareAction - */ -{ - const boolErrorAction = createAction('boolError', (payload: string) => ({ - payload, - error: true, - })) - - expectType(boolErrorAction('test').error) - - // @ts-expect-error - expectType(boolErrorAction('test').error) -} - -/* - * Test: adding string error with prepareAction - */ -{ - const strErrorAction = createAction('strError', (payload: string) => ({ - payload, - error: 'this is an error', - })) - - expectType(strErrorAction('test').error) - - // @ts-expect-error - expectType(strErrorAction('test').error) -} - -/* - * regression test for https://github.com/reduxjs/redux-toolkit/issues/214 - */ -{ - const action = createAction<{ input?: string }>('ACTION') - const t: string | undefined = action({ input: '' }).payload.input - - // @ts-expect-error - const u: number = action({ input: '' }).payload.input - // @ts-expect-error - const v: number = action({ input: 3 }).payload.input -} - -/* - * regression test for https://github.com/reduxjs/redux-toolkit/issues/224 - */ -{ - const oops = createAction('oops', (x: any) => ({ - payload: x, - error: x, - meta: x, - })) - - type Ret = ReturnType - - const payload: IsAny = true - const error: IsAny = true - const meta: IsAny = true - - // @ts-expect-error - const payloadNotAny: IsAny = false - // @ts-expect-error - const errorNotAny: IsAny = false - // @ts-expect-error - const metaNotAny: IsAny = false -} - -/** - * Test: createAction.match() - */ -{ - // simple use case - { - const actionCreator = createAction('test') - const x: Action = {} as any - if (actionCreator.match(x)) { - expectType<'test'>(x.type) - expectType(x.payload) - } else { - // @ts-expect-error - expectType<'test'>(x.type) - // @ts-expect-error - expectType(x.payload) - } - } - - // special case: optional argument - { - const actionCreator = createAction('test') - const x: Action = {} as any - if (actionCreator.match(x)) { - expectType<'test'>(x.type) - expectType(x.payload) - } - } - - // special case: without argument - { - const actionCreator = createAction('test') - const x: Action = {} as any - if (actionCreator.match(x)) { - expectType<'test'>(x.type) - // @ts-expect-error - expectType<{}>(x.payload) - } - } - - // special case: with prepareAction - { - const actionCreator = createAction('test', () => ({ - payload: '', - meta: '', - error: false, - })) - const x: Action = {} as any - if (actionCreator.match(x)) { - expectType<'test'>(x.type) - expectType(x.payload) - expectType(x.meta) - expectType(x.error) - // @ts-expect-error - expectType(x.payload) - // @ts-expect-error - expectType(x.meta) - // @ts-expect-error - expectType(x.error) - } - } - // potential use: as array filter - { - const actionCreator = createAction('test') - const x: Array> = [] - expectType>>( - x.filter(actionCreator.match) - ) - - expectType>>( - // @ts-expect-error - x.filter(actionCreator.match) - ) - } -} -{ - expectType>( - createAction('') - ) - expectType(createAction('')) - expectType(createAction('')) - expectType>(createAction('')) - expectType>( - createAction('', (_: 0) => ({ - payload: 1 as 1, - error: 2 as 2, - meta: 3 as 3, - })) - ) - const anyCreator = createAction('') - expectType>(anyCreator) - type AnyPayload = ReturnType['payload'] - expectType>(true) -} - -// Verify action creators should not be passed directly as arguments -// to React event handlers if there shouldn't be a payload -{ - const emptyAction = createAction('empty/action') - function TestComponent() { - // This typically leads to an error like: - // // A non-serializable value was detected in an action, in the path: `payload`. - // @ts-expect-error Should error because `void` and `MouseEvent` aren't compatible - return - } -} diff --git a/packages/toolkit/src/tests/createAsyncThunk.test-d.ts b/packages/toolkit/src/tests/createAsyncThunk.test-d.ts new file mode 100644 index 0000000000..7f961666e9 --- /dev/null +++ b/packages/toolkit/src/tests/createAsyncThunk.test-d.ts @@ -0,0 +1,891 @@ +import type { + AsyncThunk, + SerializedError, + ThunkDispatch, + UnknownAction, +} from '@reduxjs/toolkit' +import { + configureStore, + createAsyncThunk, + createReducer, + createSlice, + unwrapResult, +} from '@reduxjs/toolkit' + +import type { TSVersion } from '@phryneas/ts-version' +import type { AxiosError } from 'axios' +import apiRequest from 'axios' + +const defaultDispatch = (() => {}) as ThunkDispatch<{}, any, UnknownAction> +const unknownAction = { type: 'foo' } as UnknownAction + +describe('type tests', () => { + test('basic usage', async () => { + const asyncThunk = createAsyncThunk('test', (id: number) => + Promise.resolve(id * 2), + ) + + const reducer = createReducer({}, (builder) => + builder + .addCase(asyncThunk.pending, (_, action) => { + expectTypeOf(action).toEqualTypeOf< + ReturnType<(typeof asyncThunk)['pending']> + >() + }) + + .addCase(asyncThunk.fulfilled, (_, action) => { + expectTypeOf(action).toEqualTypeOf< + ReturnType<(typeof asyncThunk)['fulfilled']> + >() + + expectTypeOf(action.payload).toBeNumber() + }) + + .addCase(asyncThunk.rejected, (_, action) => { + expectTypeOf(action).toEqualTypeOf< + ReturnType<(typeof asyncThunk)['rejected']> + >() + + expectTypeOf(action.error).toMatchTypeOf | undefined>() + }), + ) + + const promise = defaultDispatch(asyncThunk(3)) + + expectTypeOf(promise.requestId).toBeString() + + expectTypeOf(promise.arg).toBeNumber() + + expectTypeOf(promise.abort).toEqualTypeOf<(reason?: string) => void>() + + const result = await promise + + if (asyncThunk.fulfilled.match(result)) { + expectTypeOf(result).toEqualTypeOf< + ReturnType<(typeof asyncThunk)['fulfilled']> + >() + } else { + expectTypeOf(result).toEqualTypeOf< + ReturnType<(typeof asyncThunk)['rejected']> + >() + } + + promise + .then(unwrapResult) + .then((result) => { + expectTypeOf(result).toBeNumber() + + expectTypeOf(result).not.toMatchTypeOf() + }) + .catch((error) => { + // catch is always any-typed, nothing we can do here + expectTypeOf(error).toBeAny() + }) + }) + + test('More complex usage of thunk args', () => { + interface BookModel { + id: string + title: string + } + + type BooksState = BookModel[] + + const fakeBooks: BookModel[] = [ + { id: 'b', title: 'Second' }, + { id: 'a', title: 'First' }, + ] + + const correctDispatch = (() => {}) as ThunkDispatch< + BookModel[], + { userAPI: Function }, + UnknownAction + > + + // Verify that the the first type args to createAsyncThunk line up right + const fetchBooksTAC = createAsyncThunk< + BookModel[], + number, + { + state: BooksState + extra: { userAPI: Function } + } + >( + 'books/fetch', + async (arg, { getState, dispatch, extra, requestId, signal }) => { + const state = getState() + + expectTypeOf(arg).toBeNumber() + + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(extra).toEqualTypeOf<{ userAPI: Function }>() + + return fakeBooks + }, + ) + + correctDispatch(fetchBooksTAC(1)) + // @ts-expect-error + defaultDispatch(fetchBooksTAC(1)) + }) + + test('returning a rejected action from the promise creator is possible', async () => { + type ReturnValue = { data: 'success' } + type RejectValue = { data: 'error' } + + const fetchBooksTAC = createAsyncThunk< + ReturnValue, + number, + { + rejectValue: RejectValue + } + >('books/fetch', async (arg, { rejectWithValue }) => { + return rejectWithValue({ data: 'error' }) + }) + + const returned = await defaultDispatch(fetchBooksTAC(1)) + if (fetchBooksTAC.rejected.match(returned)) { + expectTypeOf(returned.payload).toEqualTypeOf() + + expectTypeOf(returned.payload).toBeNullable() + } else { + expectTypeOf(returned.payload).toEqualTypeOf() + } + + expectTypeOf(unwrapResult(returned)).toEqualTypeOf() + + expectTypeOf(unwrapResult(returned)).not.toMatchTypeOf() + }) + + test('regression #1156: union return values fall back to allowing only single member', () => { + const fn = createAsyncThunk('session/isAdmin', async () => { + const response: boolean = false + return response + }) + }) + + test('Should handle reject with value within a try catch block. Note: this is a sample code taken from #1605', () => { + type ResultType = { + text: string + } + const demoPromise = async (): Promise => + new Promise((resolve, _) => resolve({ text: '' })) + const thunk = createAsyncThunk('thunk', async (args, thunkAPI) => { + try { + const result = await demoPromise() + return result + } catch (error) { + return thunkAPI.rejectWithValue(error) + } + }) + createReducer({}, (builder) => + builder.addCase(thunk.fulfilled, (s, action) => { + expectTypeOf(action.payload).toEqualTypeOf() + }), + ) + }) + + test('reject with value', () => { + interface Item { + name: string + } + + interface ErrorFromServer { + error: string + } + + interface CallsResponse { + data: Item[] + } + + const fetchLiveCallsError = createAsyncThunk< + Item[], + string, + { + rejectValue: ErrorFromServer + } + >('calls/fetchLiveCalls', async (organizationId, { rejectWithValue }) => { + try { + const result = await apiRequest.get( + `organizations/${organizationId}/calls/live/iwill404`, + ) + return result.data.data + } catch (err) { + const error: AxiosError = err as any // cast for access to AxiosError properties + if (!error.response) { + // let it be handled as any other unknown error + throw err + } + return rejectWithValue(error.response && error.response.data) + } + }) + + defaultDispatch(fetchLiveCallsError('asd')).then((result) => { + if (fetchLiveCallsError.fulfilled.match(result)) { + //success + expectTypeOf(result).toEqualTypeOf< + ReturnType<(typeof fetchLiveCallsError)['fulfilled']> + >() + + expectTypeOf(result.payload).toEqualTypeOf() + } else { + expectTypeOf(result).toEqualTypeOf< + ReturnType<(typeof fetchLiveCallsError)['rejected']> + >() + + if (result.payload) { + // rejected with value + expectTypeOf(result.payload).toEqualTypeOf() + } else { + // rejected by throw + expectTypeOf(result.payload).toBeUndefined() + + expectTypeOf(result.error).toEqualTypeOf() + + expectTypeOf(result.error).not.toBeAny() + } + } + defaultDispatch(fetchLiveCallsError('asd')) + .then((result) => { + expectTypeOf(result.payload).toEqualTypeOf< + Item[] | ErrorFromServer | undefined + >() + + return result + }) + .then(unwrapResult) + .then((unwrapped) => { + expectTypeOf(unwrapped).toEqualTypeOf() + + expectTypeOf(unwrapResult).parameter(0).not.toMatchTypeOf(unwrapped) + }) + }) + }) + + describe('payloadCreator first argument type has impact on asyncThunk argument', () => { + test('asyncThunk has no argument', () => { + const asyncThunk = createAsyncThunk('test', () => 0) + + expectTypeOf(asyncThunk).toMatchTypeOf<() => any>() + + expectTypeOf(asyncThunk).parameters.toEqualTypeOf<[]>() + + expectTypeOf(asyncThunk).returns.toBeFunction() + }) + + test('one argument, specified as undefined: asyncThunk has no argument', () => { + const asyncThunk = createAsyncThunk('test', (arg: undefined) => 0) + + expectTypeOf(asyncThunk).toMatchTypeOf<() => any>() + + expectTypeOf(asyncThunk).parameters.toEqualTypeOf<[]>() + }) + + test('one argument, specified as void: asyncThunk has no argument', () => { + const asyncThunk = createAsyncThunk('test', (arg: void) => 0) + + expectTypeOf(asyncThunk).toMatchTypeOf<() => any>() + }) + + test('one argument, specified as optional number: asyncThunk has optional number argument', () => { + // this test will fail with strictNullChecks: false, that is to be expected + // in that case, we have to forbid this behaviour or it will make arguments optional everywhere + const asyncThunk = createAsyncThunk('test', (arg?: number) => 0) + + // Per https://github.com/reduxjs/redux-toolkit/issues/3758#issuecomment-1742152774 , this is a bug in + // TS 5.1 and 5.2, that is fixed in 5.3. Conditionally run the TS assertion here. + type IsTS51Or52 = TSVersion.Major extends 5 + ? TSVersion.Minor extends 1 | 2 + ? true + : false + : false + + type expectedType = IsTS51Or52 extends true + ? (arg: number) => any + : (arg?: number) => any + + expectTypeOf(asyncThunk).toMatchTypeOf() + + // We _should_ be able to call this with no arguments, but we run into that error in 5.1 and 5.2. + // Disabling this for now. + // asyncThunk() + expectTypeOf(asyncThunk).toBeCallableWith(5) + + expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[string]>() + }) + + test('one argument, specified as number|undefined: asyncThunk has optional number argument', () => { + // this test will fail with strictNullChecks: false, that is to be expected + // in that case, we have to forbid this behaviour or it will make arguments optional everywhere + const asyncThunk = createAsyncThunk( + 'test', + (arg: number | undefined) => 0, + ) + + expectTypeOf(asyncThunk).toMatchTypeOf<(arg?: number) => any>() + + expectTypeOf(asyncThunk).toBeCallableWith() + + expectTypeOf(asyncThunk).toBeCallableWith(undefined) + + expectTypeOf(asyncThunk).toBeCallableWith(5) + + expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[string]>() + }) + + test('one argument, specified as number|void: asyncThunk has optional number argument', () => { + const asyncThunk = createAsyncThunk('test', (arg: number | void) => 0) + + expectTypeOf(asyncThunk).toMatchTypeOf<(arg?: number) => any>() + + expectTypeOf(asyncThunk).toBeCallableWith() + + expectTypeOf(asyncThunk).toBeCallableWith(undefined) + + expectTypeOf(asyncThunk).toBeCallableWith(5) + + expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[string]>() + }) + + test('one argument, specified as any: asyncThunk has required any argument', () => { + const asyncThunk = createAsyncThunk('test', (arg: any) => 0) + + expectTypeOf(asyncThunk).parameter(0).toBeAny() + + expectTypeOf(asyncThunk).toBeCallableWith(5) + + expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>() + }) + + test('one argument, specified as unknown: asyncThunk has required unknown argument', () => { + const asyncThunk = createAsyncThunk('test', (arg: unknown) => 0) + + expectTypeOf(asyncThunk).parameter(0).toBeUnknown() + + expectTypeOf(asyncThunk).toBeCallableWith(5) + + expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>() + }) + + test('one argument, specified as number: asyncThunk has required number argument', () => { + const asyncThunk = createAsyncThunk('test', (arg: number) => 0) + + expectTypeOf(asyncThunk).toMatchTypeOf<(arg: number) => any>() + + expectTypeOf(asyncThunk).toBeCallableWith(5) + + expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>() + }) + + test('two arguments, first specified as undefined: asyncThunk has no argument', () => { + const asyncThunk = createAsyncThunk( + 'test', + (arg: undefined, thunkApi) => 0, + ) + + expectTypeOf(asyncThunk).toMatchTypeOf<() => any>() + + expectTypeOf(asyncThunk).toBeCallableWith() + + // @ts-expect-error cannot be called with an argument, even if the argument is `undefined` + expectTypeOf(asyncThunk).toBeCallableWith(undefined) + + // cannot be called with an argument + expectTypeOf(asyncThunk).parameter(0).not.toBeAny() + + expectTypeOf(asyncThunk).parameters.toEqualTypeOf<[]>() + }) + + test('two arguments, first specified as void: asyncThunk has no argument', () => { + const asyncThunk = createAsyncThunk('test', (arg: void, thunkApi) => 0) + + expectTypeOf(asyncThunk).toMatchTypeOf<() => any>() + + expectTypeOf(asyncThunk).toBeCallableWith() + + expectTypeOf(asyncThunk).parameter(0).toBeVoid() + + // cannot be called with an argument + expectTypeOf(asyncThunk).parameter(0).not.toBeAny() + + expectTypeOf(asyncThunk).parameters.toEqualTypeOf<[]>() + }) + + test('two arguments, first specified as number|undefined: asyncThunk has optional number argument', () => { + // this test will fail with strictNullChecks: false, that is to be expected + // in that case, we have to forbid this behaviour or it will make arguments optional everywhere + const asyncThunk = createAsyncThunk( + 'test', + (arg: number | undefined, thunkApi) => 0, + ) + + expectTypeOf(asyncThunk).toMatchTypeOf<(arg?: number) => any>() + + expectTypeOf(asyncThunk).toBeCallableWith() + + expectTypeOf(asyncThunk).toBeCallableWith(undefined) + + expectTypeOf(asyncThunk).toBeCallableWith(5) + + expectTypeOf(asyncThunk).parameter(0).not.toBeString() + }) + + test('two arguments, first specified as number|void: asyncThunk has optional number argument', () => { + const asyncThunk = createAsyncThunk( + 'test', + (arg: number | void, thunkApi) => 0, + ) + + expectTypeOf(asyncThunk).toMatchTypeOf<(arg?: number) => any>() + + expectTypeOf(asyncThunk).toBeCallableWith() + + expectTypeOf(asyncThunk).toBeCallableWith(undefined) + + expectTypeOf(asyncThunk).toBeCallableWith(5) + + expectTypeOf(asyncThunk).parameter(0).not.toBeString() + }) + + test('two arguments, first specified as any: asyncThunk has required any argument', () => { + const asyncThunk = createAsyncThunk('test', (arg: any, thunkApi) => 0) + + expectTypeOf(asyncThunk).parameter(0).toBeAny() + + expectTypeOf(asyncThunk).toBeCallableWith(5) + + expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>() + }) + + test('two arguments, first specified as unknown: asyncThunk has required unknown argument', () => { + const asyncThunk = createAsyncThunk('test', (arg: unknown, thunkApi) => 0) + + expectTypeOf(asyncThunk).parameter(0).toBeUnknown() + + expectTypeOf(asyncThunk).toBeCallableWith(5) + + expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>() + }) + + test('two arguments, first specified as number: asyncThunk has required number argument', () => { + const asyncThunk = createAsyncThunk('test', (arg: number, thunkApi) => 0) + + expectTypeOf(asyncThunk).toMatchTypeOf<(arg: number) => any>() + + expectTypeOf(asyncThunk).parameter(0).toBeNumber() + + expectTypeOf(asyncThunk).toBeCallableWith(5) + + expectTypeOf(asyncThunk).parameters.not.toMatchTypeOf<[]>() + }) + }) + + test('createAsyncThunk without generics', () => { + const thunk = createAsyncThunk('test', () => { + return 'ret' as const + }) + + expectTypeOf(thunk).toEqualTypeOf>() + }) + + test('createAsyncThunk without generics, accessing `api` does not break return type', () => { + const thunk = createAsyncThunk('test', (_: void, api) => { + return 'ret' as const + }) + + expectTypeOf(thunk).toEqualTypeOf>() + }) + + test('createAsyncThunk rejectWithValue without generics: Expect correct return type', () => { + const asyncThunk = createAsyncThunk( + 'test', + (_: void, { rejectWithValue }) => { + try { + return Promise.resolve(true) + } catch (e) { + return rejectWithValue(e) + } + }, + ) + + defaultDispatch(asyncThunk()) + .then((result) => { + if (asyncThunk.fulfilled.match(result)) { + expectTypeOf(result).toEqualTypeOf< + ReturnType<(typeof asyncThunk)['fulfilled']> + >() + + expectTypeOf(result.payload).toBeBoolean() + + expectTypeOf(result).not.toHaveProperty('error') + } else { + expectTypeOf(result).toEqualTypeOf< + ReturnType<(typeof asyncThunk)['rejected']> + >() + + expectTypeOf(result.error).toEqualTypeOf() + + expectTypeOf(result.payload).toBeUnknown() + } + + return result + }) + .then(unwrapResult) + .then((unwrapped) => { + expectTypeOf(unwrapped).toBeBoolean() + }) + }) + + test('createAsyncThunk with generics', () => { + type Funky = { somethingElse: 'Funky!' } + function funkySerializeError(err: any): Funky { + return { somethingElse: 'Funky!' } + } + + // has to stay on one line or type tests fail in older TS versions + // prettier-ignore + // @ts-expect-error + const shouldFail = createAsyncThunk('without generics', () => {}, { serializeError: funkySerializeError }) + + const shouldWork = createAsyncThunk< + any, + void, + { serializedErrorType: Funky } + >('with generics', () => {}, { + serializeError: funkySerializeError, + }) + + if (shouldWork.rejected.match(unknownAction)) { + expectTypeOf(unknownAction.error).toEqualTypeOf() + } + }) + + test('`idGenerator` option takes no arguments, and returns a string', () => { + const returnsNumWithArgs = (foo: any) => 100 + // has to stay on one line or type tests fail in older TS versions + // prettier-ignore + // @ts-expect-error + const shouldFailNumWithArgs = createAsyncThunk('foo', () => {}, { idGenerator: returnsNumWithArgs }) + + const returnsNumWithoutArgs = () => 100 + // prettier-ignore + // @ts-expect-error + const shouldFailNumWithoutArgs = createAsyncThunk('foo', () => {}, { idGenerator: returnsNumWithoutArgs }) + + const returnsStrWithNumberArg = (foo: number) => 'foo' + // prettier-ignore + // @ts-expect-error + const shouldFailWrongArgs = createAsyncThunk('foo', (arg: string) => {}, { idGenerator: returnsStrWithNumberArg }) + + const returnsStrWithStringArg = (foo: string) => 'foo' + const shoulducceedCorrectArgs = createAsyncThunk( + 'foo', + (arg: string) => {}, + { + idGenerator: returnsStrWithStringArg, + }, + ) + + const returnsStrWithoutArgs = () => 'foo' + const shouldSucceed = createAsyncThunk('foo', () => {}, { + idGenerator: returnsStrWithoutArgs, + }) + }) + + test('fulfillWithValue should infer return value', () => { + // https://github.com/reduxjs/redux-toolkit/issues/2886 + + const initialState = { + loading: false, + obj: { magic: '' }, + } + + const getObj = createAsyncThunk( + 'slice/getObj', + async (_: any, { fulfillWithValue, rejectWithValue }) => { + try { + return fulfillWithValue({ magic: 'object' }) + } catch (rejected: any) { + return rejectWithValue(rejected?.response?.error || rejected) + } + }, + ) + + createSlice({ + name: 'slice', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(getObj.fulfilled, (state, action) => { + expectTypeOf(action.payload).toEqualTypeOf<{ magic: string }>() + }) + }, + }) + }) + + test('meta return values', () => { + // return values + createAsyncThunk<'ret', void, {}>('test', (_, api) => 'ret' as const) + createAsyncThunk<'ret', void, {}>('test', async (_, api) => 'ret' as const) + createAsyncThunk<'ret', void, { fulfilledMeta: string }>('test', (_, api) => + api.fulfillWithValue('ret' as const, ''), + ) + createAsyncThunk<'ret', void, { fulfilledMeta: string }>( + 'test', + async (_, api) => api.fulfillWithValue('ret' as const, ''), + ) + createAsyncThunk<'ret', void, { fulfilledMeta: string }>( + 'test', + // @ts-expect-error has to be a fulfilledWithValue call + (_, api) => 'ret' as const, + ) + createAsyncThunk<'ret', void, { fulfilledMeta: string }>( + 'test', + // @ts-expect-error has to be a fulfilledWithValue call + async (_, api) => 'ret' as const, + ) + createAsyncThunk<'ret', void, { fulfilledMeta: string }>( + 'test', // @ts-expect-error should only allow returning with 'test' + (_, api) => api.fulfillWithValue(5, ''), + ) + createAsyncThunk<'ret', void, { fulfilledMeta: string }>( + 'test', // @ts-expect-error should only allow returning with 'test' + async (_, api) => api.fulfillWithValue(5, ''), + ) + + // reject values + createAsyncThunk<'ret', void, { rejectValue: string }>('test', (_, api) => + api.rejectWithValue('ret'), + ) + createAsyncThunk<'ret', void, { rejectValue: string }>( + 'test', + async (_, api) => api.rejectWithValue('ret'), + ) + createAsyncThunk< + 'ret', + void, + { rejectValue: string; rejectedMeta: number } + >('test', (_, api) => api.rejectWithValue('ret', 5)) + createAsyncThunk< + 'ret', + void, + { rejectValue: string; rejectedMeta: number } + >('test', async (_, api) => api.rejectWithValue('ret', 5)) + createAsyncThunk< + 'ret', + void, + { rejectValue: string; rejectedMeta: number } + >('test', (_, api) => api.rejectWithValue('ret', 5)) + createAsyncThunk< + 'ret', + void, + { rejectValue: string; rejectedMeta: number } + >( + 'test', + // @ts-expect-error wrong rejectedMeta type + (_, api) => api.rejectWithValue('ret', ''), + ) + createAsyncThunk< + 'ret', + void, + { rejectValue: string; rejectedMeta: number } + >( + 'test', + // @ts-expect-error wrong rejectedMeta type + async (_, api) => api.rejectWithValue('ret', ''), + ) + createAsyncThunk< + 'ret', + void, + { rejectValue: string; rejectedMeta: number } + >( + 'test', + // @ts-expect-error wrong rejectValue type + (_, api) => api.rejectWithValue(5, ''), + ) + createAsyncThunk< + 'ret', + void, + { rejectValue: string; rejectedMeta: number } + >( + 'test', + // @ts-expect-error wrong rejectValue type + async (_, api) => api.rejectWithValue(5, ''), + ) + }) + + test('usage with config override generic', () => { + const typedCAT = createAsyncThunk.withTypes<{ + state: RootState + dispatch: AppDispatch + rejectValue: string + extra: { s: string; n: number } + }>() + + // inferred usage + const thunk = typedCAT('foo', (arg: number, api) => { + // correct getState Type + const test1: number = api.getState().foo.value + // correct dispatch type + const test2: number = api.dispatch((dispatch, getState) => { + expectTypeOf(dispatch).toEqualTypeOf< + ThunkDispatch<{ foo: { value: number } }, undefined, UnknownAction> + >() + + expectTypeOf(getState).toEqualTypeOf<() => { foo: { value: number } }>() + + return getState().foo.value + }) + + // correct extra type + const { s, n } = api.extra + + expectTypeOf(s).toBeString() + + expectTypeOf(n).toBeNumber() + + if (1 < 2) + // @ts-expect-error + return api.rejectWithValue(5) + if (1 < 2) return api.rejectWithValue('test') + return test1 + test2 + }) + + // usage with two generics + const thunk2 = typedCAT('foo', (arg, api) => { + expectTypeOf(arg).toBeString() + + // correct getState Type + const test1: number = api.getState().foo.value + // correct dispatch type + const test2: number = api.dispatch((dispatch, getState) => { + expectTypeOf(dispatch).toEqualTypeOf< + ThunkDispatch<{ foo: { value: number } }, undefined, UnknownAction> + >() + + expectTypeOf(getState).toEqualTypeOf<() => { foo: { value: number } }>() + + return getState().foo.value + }) + // correct extra type + const { s, n } = api.extra + + expectTypeOf(s).toBeString() + + expectTypeOf(n).toBeNumber() + + if (1 < 2) expectTypeOf(api.rejectWithValue).toBeCallableWith('test') + + expectTypeOf(api.rejectWithValue).parameter(0).not.toBeNumber() + + expectTypeOf(api.rejectWithValue).parameters.toEqualTypeOf<[string]>() + + return api.rejectWithValue('test') + }) + + // usage with config override generic + const thunk3 = typedCAT( + 'foo', + (arg, api) => { + expectTypeOf(arg).toBeString() + + // correct getState Type + const test1: number = api.getState().foo.value + // correct dispatch type + const test2: number = api.dispatch((dispatch, getState) => { + expectTypeOf(dispatch).toEqualTypeOf< + ThunkDispatch<{ foo: { value: number } }, undefined, UnknownAction> + >() + + expectTypeOf(getState).toEqualTypeOf< + () => { foo: { value: number } } + >() + + return getState().foo.value + }) + // correct extra type + const { s, n } = api.extra + + expectTypeOf(s).toBeString() + + expectTypeOf(n).toBeNumber() + + if (1 < 2) return api.rejectWithValue(5) + if (1 < 2) expectTypeOf(api.rejectWithValue).toBeCallableWith(5) + + expectTypeOf(api.rejectWithValue).parameter(0).not.toBeString() + + expectTypeOf(api.rejectWithValue).parameters.toEqualTypeOf<[number]>() + + return api.rejectWithValue(5) + }, + ) + + const slice = createSlice({ + name: 'foo', + initialState: { value: 0 }, + reducers: {}, + extraReducers(builder) { + builder + .addCase(thunk.fulfilled, (state, action) => { + state.value += action.payload + }) + .addCase(thunk.rejected, (state, action) => { + expectTypeOf(action.payload).toEqualTypeOf() + }) + .addCase(thunk2.fulfilled, (state, action) => { + state.value += action.payload + }) + .addCase(thunk2.rejected, (state, action) => { + expectTypeOf(action.payload).toEqualTypeOf() + }) + .addCase(thunk3.fulfilled, (state, action) => { + state.value += action.payload + }) + .addCase(thunk3.rejected, (state, action) => { + expectTypeOf(action.payload).toEqualTypeOf() + }) + }, + }) + + const store = configureStore({ + reducer: { + foo: slice.reducer, + }, + }) + + type RootState = ReturnType + type AppDispatch = typeof store.dispatch + }) + + test('rejectedMeta', async () => { + const getNewStore = () => + configureStore({ + reducer(actions = [], action) { + return [...actions, action] + }, + }) + + const store = getNewStore() + + const fulfilledThunk = createAsyncThunk< + string, + string, + { rejectedMeta: { extraProp: string } } + >('test', (arg: string, { rejectWithValue }) => { + return rejectWithValue('damn!', { extraProp: 'baz' }) + }) + + const promise = store.dispatch(fulfilledThunk('testArg')) + + const ret = await promise + + if (ret.meta.requestStatus === 'rejected' && ret.meta.rejectedWithValue) { + expectTypeOf(ret.meta.extraProp).toBeString() + } else { + // could be caused by a `throw`, `abort()` or `condition` - no `rejectedMeta` in that case + expectTypeOf(ret.meta).not.toHaveProperty('extraProp') + } + }) +}) diff --git a/packages/toolkit/src/tests/createAsyncThunk.test.ts b/packages/toolkit/src/tests/createAsyncThunk.test.ts index f57b4fe45c..ef6ae71838 100644 --- a/packages/toolkit/src/tests/createAsyncThunk.test.ts +++ b/packages/toolkit/src/tests/createAsyncThunk.test.ts @@ -1,20 +1,19 @@ -import { vi } from 'vitest' import type { UnknownAction } from '@reduxjs/toolkit' import { - createAsyncThunk, - unwrapResult, configureStore, + createAsyncThunk, createReducer, + unwrapResult, + miniSerializeError, } from '@reduxjs/toolkit' -import { miniSerializeError } from '@internal/createAsyncThunk' +import { vi } from 'vitest' import { - mockConsole, createConsole, getLog, + mockConsole, } from 'console-testing-library/pure' -import { expectType } from './helpers' -import { delay } from '../utils' +import { delay } from '@internal/utils' declare global { interface Window { @@ -41,13 +40,13 @@ describe('createAsyncThunk', () => { const thunkActionCreator = createAsyncThunk('testType', async () => 42) expect(thunkActionCreator.settled).toEqual(expect.any(Function)) expect(thunkActionCreator.settled(thunkActionCreator.pending(''))).toBe( - false + false, ) expect( - thunkActionCreator.settled(thunkActionCreator.rejected(null, '')) + thunkActionCreator.settled(thunkActionCreator.rejected(null, '')), ).toBe(true) expect( - thunkActionCreator.settled(thunkActionCreator.fulfilled(42, '')) + thunkActionCreator.settled(thunkActionCreator.fulfilled(42, '')), ).toBe(true) }) @@ -87,7 +86,7 @@ describe('createAsyncThunk', () => { passedArg = arg generatedRequestId = requestId return result - } + }, ) const thunkFunction = thunkActionCreator(args) @@ -103,12 +102,12 @@ describe('createAsyncThunk', () => { expect(dispatch).toHaveBeenNthCalledWith( 1, - thunkActionCreator.pending(generatedRequestId, args) + thunkActionCreator.pending(generatedRequestId, args), ) expect(dispatch).toHaveBeenNthCalledWith( 2, - thunkActionCreator.fulfilled(result, generatedRequestId, args) + thunkActionCreator.fulfilled(result, generatedRequestId, args), ) }) @@ -125,7 +124,7 @@ describe('createAsyncThunk', () => { async (args: number, { requestId }) => { generatedRequestId = requestId throw error - } + }, ) const thunkFunction = thunkActionCreator(args) @@ -136,7 +135,7 @@ describe('createAsyncThunk', () => { expect(dispatch).toHaveBeenNthCalledWith( 1, - thunkActionCreator.pending(generatedRequestId, args) + thunkActionCreator.pending(generatedRequestId, args), ) expect(dispatch).toHaveBeenCalledTimes(2) @@ -161,7 +160,7 @@ describe('createAsyncThunk', () => { async (args: number, { requestId }) => { generatedRequestId = requestId throw errorObject - } + }, ) const thunkFunction = thunkActionCreator(args) @@ -172,7 +171,7 @@ describe('createAsyncThunk', () => { expect(dispatch).toHaveBeenNthCalledWith( 1, - thunkActionCreator.pending(generatedRequestId, args) + thunkActionCreator.pending(generatedRequestId, args), ) expect(dispatch).toHaveBeenCalledTimes(2) @@ -200,7 +199,7 @@ describe('createAsyncThunk', () => { async (args: number, { requestId }) => { generatedRequestId = requestId throw errorObject - } + }, ) const thunkFunction = thunkActionCreator(args) @@ -211,7 +210,7 @@ describe('createAsyncThunk', () => { expect(dispatch).toHaveBeenNthCalledWith( 1, - thunkActionCreator.pending(generatedRequestId, args) + thunkActionCreator.pending(generatedRequestId, args), ) expect(dispatch).toHaveBeenCalledTimes(2) @@ -245,7 +244,7 @@ describe('createAsyncThunk', () => { generatedRequestId = requestId return rejectWithValue(errorPayload) - } + }, ) const thunkFunction = thunkActionCreator(args) @@ -256,7 +255,7 @@ describe('createAsyncThunk', () => { expect(dispatch).toHaveBeenNthCalledWith( 1, - thunkActionCreator.pending(generatedRequestId, args) + thunkActionCreator.pending(generatedRequestId, args), ) expect(dispatch).toHaveBeenCalledTimes(2) @@ -290,7 +289,7 @@ describe('createAsyncThunk', () => { generatedRequestId = requestId throw rejectWithValue(errorPayload) - } + }, ) const thunkFunction = thunkActionCreator(args) @@ -301,7 +300,7 @@ describe('createAsyncThunk', () => { expect(dispatch).toHaveBeenNthCalledWith( 1, - thunkActionCreator.pending(generatedRequestId, args) + thunkActionCreator.pending(generatedRequestId, args), ) expect(dispatch).toHaveBeenCalledTimes(2) @@ -344,7 +343,7 @@ describe('createAsyncThunk', () => { } return rejectWithValue(errorPayload) } - } + }, ) const thunkFunction = thunkActionCreator(args) @@ -355,7 +354,7 @@ describe('createAsyncThunk', () => { expect(dispatch).toHaveBeenNthCalledWith( 1, - thunkActionCreator.pending(generatedRequestId, args) + thunkActionCreator.pending(generatedRequestId, args), ) expect(dispatch).toHaveBeenCalledTimes(2) @@ -378,8 +377,8 @@ describe('createAsyncThunk with abortController', () => { reject( new DOMException( 'This should never be reached as it should already be handled.', - 'AbortError' - ) + 'AbortError', + ), ) } signal.addEventListener('abort', () => { @@ -387,7 +386,7 @@ describe('createAsyncThunk with abortController', () => { }) setTimeout(resolve, 100) }) - } + }, ) let store = configureStore({ @@ -438,7 +437,7 @@ describe('createAsyncThunk with abortController', () => { // calling unwrapResult on the returned object re-throws the error from the abortablePayloadCreator expect(() => unwrapResult(result)).toThrowError( - expect.objectContaining(expectedAbortedAction.error) + expect.objectContaining(expectedAbortedAction.error), ) }) @@ -472,7 +471,7 @@ describe('createAsyncThunk with abortController', () => { // calling unwrapResult on the returned object re-throws the error from the abortablePayloadCreator expect(() => unwrapResult(result)).toThrowError( - expect.objectContaining(expectedAbortedAction.error) + expect.objectContaining(expectedAbortedAction.error), ) }) @@ -497,7 +496,7 @@ describe('createAsyncThunk with abortController', () => { }) describe('behaviour with missing AbortController', () => { - let keepAbortController: typeof window['AbortController'] + let keepAbortController: (typeof window)['AbortController'] let freshlyLoadedModule: typeof import('../createAsyncThunk') let restore: () => void = () => {} let nodeEnv: string @@ -524,7 +523,7 @@ describe('createAsyncThunk with abortController', () => { 'longRunning', async () => { await new Promise((resolve) => setTimeout(resolve, 30000)) - } + }, ) expect(longRunningAsyncThunk()).toThrow('AbortController is not defined') @@ -600,7 +599,7 @@ describe('conditional skipping of asyncThunks', () => { expect(condition).toHaveBeenCalledTimes(1) expect(condition).toHaveBeenLastCalledWith( arg, - expect.objectContaining({ getState, extra }) + expect.objectContaining({ getState, extra }), ) }) @@ -626,7 +625,7 @@ describe('conditional skipping of asyncThunks', () => { await asyncThunk(arg)(dispatch, getState, extra) expect(dispatch).toHaveBeenCalledTimes(1) expect(dispatch).toHaveBeenLastCalledWith( - expect.objectContaining({ type: 'test/rejected' }) + expect.objectContaining({ type: 'test/rejected' }), ) }) @@ -663,7 +662,7 @@ describe('conditional skipping of asyncThunks', () => { }) const promise = asyncThunk(arg)(dispatch, getState, extra) promise.abort( - `If the promise was 1. somehow canceled, 2. in a 'started' state and 3. we attempted to abort, this would crash the tests` + `If the promise was 1. somehow canceled, 2. in a 'started' state and 3. we attempted to abort, this would crash the tests`, ) }) @@ -683,7 +682,7 @@ describe('conditional skipping of asyncThunks', () => { }, meta: { aborted: false, - arg: arg, + arg, rejectedWithValue: false, condition: true, requestId: expect.stringContaining(''), @@ -691,7 +690,7 @@ describe('conditional skipping of asyncThunks', () => { }, payload: undefined, type: 'test/rejected', - }) + }), ) }) }) @@ -737,7 +736,7 @@ describe('unwrapResult', () => { }) const unwrapPromise = asyncThunk()(dispatch, getState, extra).then( - unwrapResult + unwrapResult, ) await expect(unwrapPromise).resolves.toBe('fulfilled!') @@ -753,14 +752,14 @@ describe('unwrapResult', () => { }) const unwrapPromise = asyncThunk()(dispatch, getState, extra).then( - unwrapResult + unwrapResult, ) await expect(unwrapPromise).rejects.toEqual(miniSerializeError(error)) const unwrapPromise2 = asyncThunk()(dispatch, getState, extra) await expect(unwrapPromise2.unwrap()).rejects.toEqual( - miniSerializeError(error) + miniSerializeError(error), ) }) test('rejectWithValue case', async () => { @@ -769,7 +768,7 @@ describe('unwrapResult', () => { }) const unwrapPromise = asyncThunk()(dispatch, getState, extra).then( - unwrapResult + unwrapResult, ) await expect(unwrapPromise).rejects.toBe('rejectWithValue!') @@ -801,7 +800,7 @@ describe('idGenerator option', () => { async (args: void, { requestId }) => { generatedRequestId = requestId }, - { idGenerator } + { idGenerator }, ) // dispatching the thunks should be using the custom id generator @@ -825,7 +824,7 @@ describe('idGenerator option', () => { 'test', async (args: void, { requestId }) => { generatedRequestId = requestId - } + }, ) // dispatching the default options thunk should still generate an id, // but not using the custom id generator @@ -833,10 +832,10 @@ describe('idGenerator option', () => { expect(generatedRequestId).toEqual(promise3.requestId) expect(promise3.requestId).not.toEqual('') expect(promise3.requestId).not.toEqual( - expect.stringContaining('fake-random-id') + expect.stringContaining('fake-random-id'), ) expect((await promise3).meta.requestId).not.toEqual( - expect.stringContaining('fake-fandom-id') + expect.stringContaining('fake-fandom-id'), ) }) @@ -848,7 +847,7 @@ describe('idGenerator option', () => { async (args: any, { requestId }) => { generatedRequestId = requestId }, - { idGenerator: customIdGenerator } + { idGenerator: customIdGenerator }, ) const thunkArg = 1 @@ -896,7 +895,7 @@ describe('meta', () => { return [...actions, action] }, }) - let store = getNewStore() + const store = getNewStore() beforeEach(() => { const store = getNewStore() @@ -970,7 +969,6 @@ describe('meta', () => { }) if (ret.meta.requestStatus === 'rejected' && ret.meta.rejectedWithValue) { - expectType(ret.meta.extraProp) } else { // could be caused by a `throw`, `abort()` or `condition` - no `rejectedMeta` in that case // @ts-expect-error diff --git a/packages/toolkit/src/tests/createAsyncThunk.typetest.ts b/packages/toolkit/src/tests/createAsyncThunk.typetest.ts deleted file mode 100644 index 05cf4fd604..0000000000 --- a/packages/toolkit/src/tests/createAsyncThunk.typetest.ts +++ /dev/null @@ -1,772 +0,0 @@ -/* eslint-disable no-lone-blocks */ -import type { - UnknownAction, - SerializedError, - AsyncThunk, -} from '@reduxjs/toolkit' -import { - createAsyncThunk, - createReducer, - unwrapResult, - createSlice, - configureStore, -} from '@reduxjs/toolkit' -import type { ThunkDispatch } from 'redux-thunk' - -import type { AxiosError } from 'axios' -import apiRequest from 'axios' -import type { IsAny, IsUnknown } from '@internal/tsHelpers' -import { expectExactType, expectType } from './helpers' -import type { - AsyncThunkFulfilledActionCreator, - AsyncThunkRejectedActionCreator, -} from '@internal/createAsyncThunk' -import type { TSVersion } from '@phryneas/ts-version' - -const ANY = {} as any -const defaultDispatch = (() => {}) as ThunkDispatch<{}, any, UnknownAction> -const unknownAction = { type: 'foo' } as UnknownAction - -// basic usage -;(async function () { - const async = createAsyncThunk('test', (id: number) => - Promise.resolve(id * 2) - ) - - const reducer = createReducer({}, (builder) => - builder - .addCase(async.pending, (_, action) => { - expectType>(action) - }) - .addCase(async.fulfilled, (_, action) => { - expectType>(action) - expectType(action.payload) - }) - .addCase(async.rejected, (_, action) => { - expectType>(action) - expectType | undefined>(action.error) - }) - ) - - const promise = defaultDispatch(async(3)) - - expectType(promise.requestId) - expectType(promise.arg) - expectType<(reason?: string) => void>(promise.abort) - - const result = await promise - - if (async.fulfilled.match(result)) { - expectType>(result) - // @ts-expect-error - expectType>(result) - } else { - expectType>(result) - // @ts-expect-error - expectType>(result) - } - - promise - .then(unwrapResult) - .then((result) => { - expectType(result) - // @ts-expect-error - expectType(result) - }) - .catch((error) => { - // catch is always any-typed, nothing we can do here - }) -})() - -// More complex usage of thunk args -;(async function () { - interface BookModel { - id: string - title: string - } - - type BooksState = BookModel[] - - const fakeBooks: BookModel[] = [ - { id: 'b', title: 'Second' }, - { id: 'a', title: 'First' }, - ] - - const correctDispatch = (() => {}) as ThunkDispatch< - BookModel[], - { userAPI: Function }, - UnknownAction - > - - // Verify that the the first type args to createAsyncThunk line up right - const fetchBooksTAC = createAsyncThunk< - BookModel[], - number, - { - state: BooksState - extra: { userAPI: Function } - } - >( - 'books/fetch', - async (arg, { getState, dispatch, extra, requestId, signal }) => { - const state = getState() - - expectType(arg) - expectType(state) - expectType<{ userAPI: Function }>(extra) - return fakeBooks - } - ) - - correctDispatch(fetchBooksTAC(1)) - // @ts-expect-error - defaultDispatch(fetchBooksTAC(1)) -})() -/** - * returning a rejected action from the promise creator is possible - */ -;(async () => { - type ReturnValue = { data: 'success' } - type RejectValue = { data: 'error' } - - const fetchBooksTAC = createAsyncThunk< - ReturnValue, - number, - { - rejectValue: RejectValue - } - >('books/fetch', async (arg, { rejectWithValue }) => { - return rejectWithValue({ data: 'error' }) - }) - - const returned = await defaultDispatch(fetchBooksTAC(1)) - if (fetchBooksTAC.rejected.match(returned)) { - expectType(returned.payload) - expectType(returned.payload!) - } else { - expectType(returned.payload) - } - - expectType(unwrapResult(returned)) - // @ts-expect-error - expectType(unwrapResult(returned)) -})() - -/** - * regression #1156: union return values fall back to allowing only single member - */ -;(async () => { - const fn = createAsyncThunk('session/isAdmin', async () => { - const response: boolean = false - return response - }) -})() - -/** - * Should handle reject withvalue within a try catch block - * - * Note: - * this is a sample code taken from #1605 - * - */ -;(async () => { - type ResultType = { - text: string - } - const demoPromise = async (): Promise => - new Promise((resolve, _) => resolve({ text: '' })) - const thunk = createAsyncThunk('thunk', async (args, thunkAPI) => { - try { - const result = await demoPromise() - return result - } catch (error) { - return thunkAPI.rejectWithValue(error) - } - }) - createReducer({}, (builder) => - builder.addCase(thunk.fulfilled, (s, action) => { - expectType(action.payload) - }) - ) -})() - -{ - interface Item { - name: string - } - - interface ErrorFromServer { - error: string - } - - interface CallsResponse { - data: Item[] - } - - const fetchLiveCallsError = createAsyncThunk< - Item[], - string, - { - rejectValue: ErrorFromServer - } - >('calls/fetchLiveCalls', async (organizationId, { rejectWithValue }) => { - try { - const result = await apiRequest.get( - `organizations/${organizationId}/calls/live/iwill404` - ) - return result.data.data - } catch (err) { - let error: AxiosError = err as any // cast for access to AxiosError properties - if (!error.response) { - // let it be handled as any other unknown error - throw err - } - return rejectWithValue(error.response && error.response.data) - } - }) - - defaultDispatch(fetchLiveCallsError('asd')).then((result) => { - if (fetchLiveCallsError.fulfilled.match(result)) { - //success - expectType>(result) - expectType(result.payload) - } else { - expectType>(result) - if (result.payload) { - // rejected with value - expectType(result.payload) - } else { - // rejected by throw - expectType(result.payload) - expectType(result.error) - // @ts-expect-error - expectType>(true) - } - } - defaultDispatch(fetchLiveCallsError('asd')) - .then((result) => { - expectType(result.payload) - // @ts-expect-error - expectType(unwrapped) - return result - }) - .then(unwrapResult) - .then((unwrapped) => { - expectType(unwrapped) - // @ts-expect-error - expectType(unwrapResult(unwrapped)) - }) - }) -} - -/** - * payloadCreator first argument type has impact on asyncThunk argument - */ -{ - // no argument: asyncThunk has no argument - { - const asyncThunk = createAsyncThunk('test', () => 0) - expectType<() => any>(asyncThunk) - // @ts-expect-error cannot be called with an argument - asyncThunk(0 as any) - } - - // one argument, specified as undefined: asyncThunk has no argument - { - const asyncThunk = createAsyncThunk('test', (arg: undefined) => 0) - expectType<() => any>(asyncThunk) - // @ts-expect-error cannot be called with an argument - asyncThunk(0 as any) - } - - // one argument, specified as void: asyncThunk has no argument - { - const asyncThunk = createAsyncThunk('test', (arg: void) => 0) - expectType<() => any>(asyncThunk) - // @ts-expect-error cannot be called with an argument - asyncThunk(0 as any) - } - - // one argument, specified as optional number: asyncThunk has optional number argument - // this test will fail with strictNullChecks: false, that is to be expected - // in that case, we have to forbid this behaviour or it will make arguments optional everywhere - { - const asyncThunk = createAsyncThunk('test', (arg?: number) => 0) - - // Per https://github.com/reduxjs/redux-toolkit/issues/3758#issuecomment-1742152774 , this is a bug in - // TS 5.1 and 5.2, that is fixed in 5.3. Conditionally run the TS assertion here. - type IsTS51Or52 = TSVersion.Major extends 5 - ? TSVersion.Minor extends 1 | 2 - ? true - : false - : false - - type expectedType = IsTS51Or52 extends true - ? (arg: number) => any - : (arg?: number) => any - expectType(asyncThunk) - // We _should_ be able to call this with no arguments, but we run into that error in 5.1 and 5.2. - // Disabling this for now. - // asyncThunk() - asyncThunk(5) - // @ts-expect-error - asyncThunk('string') - } - - // one argument, specified as number|undefined: asyncThunk has optional number argument - // this test will fail with strictNullChecks: false, that is to be expected - // in that case, we have to forbid this behaviour or it will make arguments optional everywhere - { - const asyncThunk = createAsyncThunk('test', (arg: number | undefined) => 0) - expectType<(arg?: number) => any>(asyncThunk) - asyncThunk() - asyncThunk(5) - // @ts-expect-error - asyncThunk('string') - } - - // one argument, specified as number|void: asyncThunk has optional number argument - { - const asyncThunk = createAsyncThunk('test', (arg: number | void) => 0) - expectType<(arg?: number) => any>(asyncThunk) - asyncThunk() - asyncThunk(5) - // @ts-expect-error - asyncThunk('string') - } - - // one argument, specified as any: asyncThunk has required any argument - { - const asyncThunk = createAsyncThunk('test', (arg: any) => 0) - expectType[0], true, false>>(true) - asyncThunk(5) - // @ts-expect-error - asyncThunk() - } - - // one argument, specified as unknown: asyncThunk has required unknown argument - { - const asyncThunk = createAsyncThunk('test', (arg: unknown) => 0) - expectType[0], true, false>>(true) - asyncThunk(5) - // @ts-expect-error - asyncThunk() - } - - // one argument, specified as number: asyncThunk has required number argument - { - const asyncThunk = createAsyncThunk('test', (arg: number) => 0) - expectType<(arg: number) => any>(asyncThunk) - asyncThunk(5) - // @ts-expect-error - asyncThunk() - } - - // two arguments, first specified as undefined: asyncThunk has no argument - { - const asyncThunk = createAsyncThunk('test', (arg: undefined, thunkApi) => 0) - expectType<() => any>(asyncThunk) - // @ts-expect-error cannot be called with an argument - asyncThunk(0 as any) - } - - // two arguments, first specified as void: asyncThunk has no argument - { - const asyncThunk = createAsyncThunk('test', (arg: void, thunkApi) => 0) - expectType<() => any>(asyncThunk) - // @ts-expect-error cannot be called with an argument - asyncThunk(0 as any) - } - - // two arguments, first specified as number|undefined: asyncThunk has optional number argument - // this test will fail with strictNullChecks: false, that is to be expected - // in that case, we have to forbid this behaviour or it will make arguments optional everywhere - { - const asyncThunk = createAsyncThunk( - 'test', - (arg: number | undefined, thunkApi) => 0 - ) - expectType<(arg?: number) => any>(asyncThunk) - asyncThunk() - asyncThunk(5) - // @ts-expect-error - asyncThunk('string') - } - - // two arguments, first specified as number|void: asyncThunk has optional number argument - { - const asyncThunk = createAsyncThunk( - 'test', - (arg: number | void, thunkApi) => 0 - ) - expectType<(arg?: number) => any>(asyncThunk) - asyncThunk() - asyncThunk(5) - // @ts-expect-error - asyncThunk('string') - } - - // two arguments, first specified as any: asyncThunk has required any argument - { - const asyncThunk = createAsyncThunk('test', (arg: any, thunkApi) => 0) - expectType[0], true, false>>(true) - asyncThunk(5) - // @ts-expect-error - asyncThunk() - } - - // two arguments, first specified as unknown: asyncThunk has required unknown argument - { - const asyncThunk = createAsyncThunk('test', (arg: unknown, thunkApi) => 0) - expectType[0], true, false>>(true) - asyncThunk(5) - // @ts-expect-error - asyncThunk() - } - - // two arguments, first specified as number: asyncThunk has required number argument - { - const asyncThunk = createAsyncThunk('test', (arg: number, thunkApi) => 0) - expectType<(arg: number) => any>(asyncThunk) - asyncThunk(5) - // @ts-expect-error - asyncThunk() - } -} - -{ - // createAsyncThunk without generics - const thunk = createAsyncThunk('test', () => { - return 'ret' as const - }) - expectType>(thunk) -} - -{ - // createAsyncThunk without generics, accessing `api` does not break return type - const thunk = createAsyncThunk('test', (_: void, api) => { - console.log(api) - return 'ret' as const - }) - expectType>(thunk) -} - -// createAsyncThunk rejectWithValue without generics: Expect correct return type -{ - const asyncThunk = createAsyncThunk( - 'test', - (_: void, { rejectWithValue }) => { - try { - return Promise.resolve(true) - } catch (e) { - return rejectWithValue(e) - } - } - ) - - defaultDispatch(asyncThunk()) - .then((result) => { - if (asyncThunk.fulfilled.match(result)) { - expectType>>( - result - ) - expectType(result.payload) - // @ts-expect-error - expectType(result.error) - } else { - expectType>>( - result - ) - expectType(result.error) - expectType(result.payload) - } - - return result - }) - .then(unwrapResult) - .then((unwrapped) => { - expectType(unwrapped) - }) -} - -{ - type Funky = { somethingElse: 'Funky!' } - function funkySerializeError(err: any): Funky { - return { somethingElse: 'Funky!' } - } - - // has to stay on one line or type tests fail in older TS versions - // prettier-ignore - // @ts-expect-error - const shouldFail = createAsyncThunk('without generics', () => {}, { serializeError: funkySerializeError }) - - const shouldWork = createAsyncThunk< - any, - void, - { serializedErrorType: Funky } - >('with generics', () => {}, { - serializeError: funkySerializeError, - }) - - if (shouldWork.rejected.match(unknownAction)) { - expectType(unknownAction.error) - } -} - -/** - * `idGenerator` option takes no arguments, and returns a string - */ -{ - const returnsNumWithArgs = (foo: any) => 100 - // has to stay on one line or type tests fail in older TS versions - // prettier-ignore - // @ts-expect-error - const shouldFailNumWithArgs = createAsyncThunk('foo', () => {}, { idGenerator: returnsNumWithArgs }) - - const returnsNumWithoutArgs = () => 100 - // prettier-ignore - // @ts-expect-error - const shouldFailNumWithoutArgs = createAsyncThunk('foo', () => {}, { idGenerator: returnsNumWithoutArgs }) - - const returnsStrWithNumberArg = (foo: number) => 'foo' - // prettier-ignore - // @ts-expect-error - const shouldFailWrongArgs = createAsyncThunk('foo', (arg: string) => {}, { idGenerator: returnsStrWithNumberArg }) - - const returnsStrWithStringArg = (foo: string) => 'foo' - const shoulducceedCorrectArgs = createAsyncThunk('foo', (arg: string) => {}, { - idGenerator: returnsStrWithStringArg, - }) - - const returnsStrWithoutArgs = () => 'foo' - const shouldSucceed = createAsyncThunk('foo', () => {}, { - idGenerator: returnsStrWithoutArgs, - }) -} - -{ - // https://github.com/reduxjs/redux-toolkit/issues/2886 - // fulfillWithValue should infer return value - - const initialState = { - loading: false, - obj: { magic: '' }, - } - - const getObj = createAsyncThunk( - 'slice/getObj', - async (_: any, { fulfillWithValue, rejectWithValue }) => { - try { - return fulfillWithValue({ magic: 'object' }) - } catch (rejected: any) { - return rejectWithValue(rejected?.response?.error || rejected) - } - } - ) - - createSlice({ - name: 'slice', - initialState, - reducers: {}, - extraReducers: (builder) => { - builder.addCase(getObj.fulfilled, (state, action) => { - expectExactType<{ magic: string }>(ANY)(action.payload) - }) - }, - }) -} - -// meta return values -{ - // return values - createAsyncThunk<'ret', void, {}>('test', (_, api) => 'ret' as const) - createAsyncThunk<'ret', void, {}>('test', async (_, api) => 'ret' as const) - createAsyncThunk<'ret', void, { fulfilledMeta: string }>('test', (_, api) => - api.fulfillWithValue('ret' as const, '') - ) - createAsyncThunk<'ret', void, { fulfilledMeta: string }>( - 'test', - async (_, api) => api.fulfillWithValue('ret' as const, '') - ) - createAsyncThunk<'ret', void, { fulfilledMeta: string }>( - 'test', - // @ts-expect-error has to be a fulfilledWithValue call - (_, api) => 'ret' as const - ) - createAsyncThunk<'ret', void, { fulfilledMeta: string }>( - 'test', - // @ts-expect-error has to be a fulfilledWithValue call - async (_, api) => 'ret' as const - ) - createAsyncThunk<'ret', void, { fulfilledMeta: string }>( - 'test', // @ts-expect-error should only allow returning with 'test' - (_, api) => api.fulfillWithValue(5, '') - ) - createAsyncThunk<'ret', void, { fulfilledMeta: string }>( - 'test', // @ts-expect-error should only allow returning with 'test' - async (_, api) => api.fulfillWithValue(5, '') - ) - - // reject values - createAsyncThunk<'ret', void, { rejectValue: string }>('test', (_, api) => - api.rejectWithValue('ret') - ) - createAsyncThunk<'ret', void, { rejectValue: string }>( - 'test', - async (_, api) => api.rejectWithValue('ret') - ) - createAsyncThunk<'ret', void, { rejectValue: string; rejectedMeta: number }>( - 'test', - (_, api) => api.rejectWithValue('ret', 5) - ) - createAsyncThunk<'ret', void, { rejectValue: string; rejectedMeta: number }>( - 'test', - async (_, api) => api.rejectWithValue('ret', 5) - ) - createAsyncThunk<'ret', void, { rejectValue: string; rejectedMeta: number }>( - 'test', - (_, api) => api.rejectWithValue('ret', 5) - ) - createAsyncThunk<'ret', void, { rejectValue: string; rejectedMeta: number }>( - 'test', - // @ts-expect-error wrong rejectedMeta type - (_, api) => api.rejectWithValue('ret', '') - ) - createAsyncThunk<'ret', void, { rejectValue: string; rejectedMeta: number }>( - 'test', - // @ts-expect-error wrong rejectedMeta type - async (_, api) => api.rejectWithValue('ret', '') - ) - createAsyncThunk<'ret', void, { rejectValue: string; rejectedMeta: number }>( - 'test', - // @ts-expect-error wrong rejectValue type - (_, api) => api.rejectWithValue(5, '') - ) - createAsyncThunk<'ret', void, { rejectValue: string; rejectedMeta: number }>( - 'test', - // @ts-expect-error wrong rejectValue type - async (_, api) => api.rejectWithValue(5, '') - ) -} - -{ - const typedCAT = createAsyncThunk.withTypes<{ - state: RootState - dispatch: AppDispatch - rejectValue: string - extra: { s: string; n: number } - }>() - - // inferred usage - const thunk = typedCAT('foo', (arg: number, api) => { - // correct getState Type - const test1: number = api.getState().foo.value - // correct dispatch type - const test2: number = api.dispatch((dispatch, getState) => { - expectExactType< - ThunkDispatch<{ foo: { value: number } }, undefined, UnknownAction> - >(ANY)(dispatch) - expectExactType<() => { foo: { value: number } }>(ANY)(getState) - return getState().foo.value - }) - - // correct extra type - const { s, n } = api.extra - expectExactType(ANY)(s) - expectExactType(ANY)(n) - - if (1 < 2) - // @ts-expect-error - return api.rejectWithValue(5) - if (1 < 2) return api.rejectWithValue('test') - return test1 + test2 - }) - - // usage with two generics - const thunk2 = typedCAT('foo', (arg, api) => { - expectExactType('' as string)(arg) - // correct getState Type - const test1: number = api.getState().foo.value - // correct dispatch type - const test2: number = api.dispatch((dispatch, getState) => { - expectExactType< - ThunkDispatch<{ foo: { value: number } }, undefined, UnknownAction> - >(ANY)(dispatch) - expectExactType<() => { foo: { value: number } }>(ANY)(getState) - return getState().foo.value - }) - // correct extra type - const { s, n } = api.extra - expectExactType(ANY)(s) - expectExactType(ANY)(n) - - if (1 < 2) - // @ts-expect-error - return api.rejectWithValue(5) - if (1 < 2) return api.rejectWithValue('test') - return test1 + test2 - }) - - // usage with config override generic - const thunk3 = typedCAT( - 'foo', - (arg, api) => { - expectExactType('' as string)(arg) - // correct getState Type - const test1: number = api.getState().foo.value - // correct dispatch type - const test2: number = api.dispatch((dispatch, getState) => { - expectExactType< - ThunkDispatch<{ foo: { value: number } }, undefined, UnknownAction> - >(ANY)(dispatch) - expectExactType<() => { foo: { value: number } }>(ANY)(getState) - return getState().foo.value - }) - // correct extra type - const { s, n } = api.extra - expectExactType(ANY)(s) - expectExactType(ANY)(n) - if (1 < 2) return api.rejectWithValue(5) - if (1 < 2) - // @ts-expect-error - return api.rejectWithValue('test') - return 5 - } - ) - - const slice = createSlice({ - name: 'foo', - initialState: { value: 0 }, - reducers: {}, - extraReducers(builder) { - builder - .addCase(thunk.fulfilled, (state, action) => { - state.value += action.payload - }) - .addCase(thunk.rejected, (state, action) => { - expectExactType('' as string | undefined)(action.payload) - }) - .addCase(thunk2.fulfilled, (state, action) => { - state.value += action.payload - }) - .addCase(thunk2.rejected, (state, action) => { - expectExactType('' as string | undefined)(action.payload) - }) - .addCase(thunk3.fulfilled, (state, action) => { - state.value += action.payload - }) - .addCase(thunk3.rejected, (state, action) => { - expectExactType(0 as number | undefined)(action.payload) - }) - }, - }) - - const store = configureStore({ - reducer: { - foo: slice.reducer, - }, - }) - - type RootState = ReturnType - type AppDispatch = typeof store.dispatch -} diff --git a/packages/toolkit/src/tests/createDraftSafeSelector.test.ts b/packages/toolkit/src/tests/createDraftSafeSelector.test.ts index ab95fc48d8..e25ac95d5e 100644 --- a/packages/toolkit/src/tests/createDraftSafeSelector.test.ts +++ b/packages/toolkit/src/tests/createDraftSafeSelector.test.ts @@ -28,7 +28,7 @@ test('handles drafts correctly', () => { const unsafeSelector = createSelector(selectSelf, (state) => state.value) const draftSafeSelector = createDraftSafeSelector( selectSelf, - (state) => state.value + (state) => state.value, ) produce({ value: 1 }, (state) => { diff --git a/packages/toolkit/src/tests/createDraftSafeSelector.withTypes.test.ts b/packages/toolkit/src/tests/createDraftSafeSelector.withTypes.test.ts new file mode 100644 index 0000000000..cc7ec2f1d8 --- /dev/null +++ b/packages/toolkit/src/tests/createDraftSafeSelector.withTypes.test.ts @@ -0,0 +1,49 @@ +import { createDraftSafeSelector } from '@reduxjs/toolkit' + +interface Todo { + id: number + completed: boolean +} + +interface Alert { + id: number + read: boolean +} + +interface RootState { + todos: Todo[] + alerts: Alert[] +} + +const rootState: RootState = { + todos: [ + { id: 0, completed: false }, + { id: 1, completed: false }, + ], + alerts: [ + { id: 0, read: false }, + { id: 1, read: false }, + ], +} + +describe(createDraftSafeSelector.withTypes, () => { + const createTypedDraftSafeSelector = + createDraftSafeSelector.withTypes() + + test('should return createDraftSafeSelector', () => { + expect(createTypedDraftSafeSelector.withTypes).toEqual(expect.any(Function)) + + expect(createTypedDraftSafeSelector.withTypes().withTypes).toEqual( + expect.any(Function), + ) + + expect(createTypedDraftSafeSelector).toBe(createDraftSafeSelector) + + const selectTodoIds = createTypedDraftSafeSelector( + [(state) => state.todos], + (todos) => todos.map(({ id }) => id), + ) + + expect(selectTodoIds(rootState)).to.be.an('array').that.is.not.empty + }) +}) diff --git a/packages/toolkit/src/tests/createEntityAdapter.test-d.ts b/packages/toolkit/src/tests/createEntityAdapter.test-d.ts new file mode 100644 index 0000000000..0e8a4c54f4 --- /dev/null +++ b/packages/toolkit/src/tests/createEntityAdapter.test-d.ts @@ -0,0 +1,161 @@ +import type { + ActionCreatorWithPayload, + ActionCreatorWithoutPayload, + EntityAdapter, + EntityId, + EntityStateAdapter, + Update, +} from '@reduxjs/toolkit' +import { createEntityAdapter, createSlice } from '@reduxjs/toolkit' + +function extractReducers( + adapter: EntityAdapter, +): EntityStateAdapter { + const { selectId, sortComparer, getInitialState, getSelectors, ...rest } = + adapter + return rest +} + +describe('type tests', () => { + test('should be usable in a slice, with all the "reducer-like" functions', () => { + type Id = string & { readonly __tag: unique symbol } + type Entity = { + id: Id + } + const adapter = createEntityAdapter() + const slice = createSlice({ + name: 'test', + initialState: adapter.getInitialState(), + reducers: { + ...extractReducers(adapter), + }, + }) + + expectTypeOf(slice.actions.addOne).toMatchTypeOf< + ActionCreatorWithPayload + >() + + expectTypeOf(slice.actions.addMany).toMatchTypeOf< + ActionCreatorWithPayload | Record> + >() + + expectTypeOf(slice.actions.setAll).toMatchTypeOf< + ActionCreatorWithPayload | Record> + >() + + expectTypeOf(slice.actions.removeOne).toMatchTypeOf< + ActionCreatorWithPayload + >() + + expectTypeOf(slice.actions.addMany).not.toMatchTypeOf< + ActionCreatorWithPayload> + >() + + expectTypeOf(slice.actions.setAll).not.toMatchTypeOf< + ActionCreatorWithPayload> + >() + + expectTypeOf(slice.actions.removeOne).toMatchTypeOf< + ActionCreatorWithPayload + >() + + expectTypeOf(slice.actions.removeMany).toMatchTypeOf< + ActionCreatorWithPayload> + >() + + expectTypeOf(slice.actions.removeMany).not.toMatchTypeOf< + ActionCreatorWithPayload + >() + + expectTypeOf( + slice.actions.removeAll, + ).toMatchTypeOf() + + expectTypeOf(slice.actions.updateOne).toMatchTypeOf< + ActionCreatorWithPayload> + >() + + expectTypeOf(slice.actions.updateMany).not.toMatchTypeOf< + ActionCreatorWithPayload[]> + >() + + expectTypeOf(slice.actions.upsertOne).toMatchTypeOf< + ActionCreatorWithPayload + >() + + expectTypeOf(slice.actions.updateMany).toMatchTypeOf< + ActionCreatorWithPayload>> + >() + + expectTypeOf(slice.actions.upsertOne).toMatchTypeOf< + ActionCreatorWithPayload + >() + + expectTypeOf(slice.actions.upsertMany).toMatchTypeOf< + ActionCreatorWithPayload | Record> + >() + + expectTypeOf(slice.actions.upsertMany).not.toMatchTypeOf< + ActionCreatorWithPayload> + >() + }) + + test('should not be able to mix with a different EntityAdapter', () => { + type Entity = { + id: EntityId + value: string + } + type Entity2 = { + id: EntityId + value2: string + } + const adapter = createEntityAdapter() + const adapter2 = createEntityAdapter() + createSlice({ + name: 'test', + initialState: adapter.getInitialState(), + reducers: { + addOne: adapter.addOne, + // @ts-expect-error + addOne2: adapter2.addOne, + }, + }) + }) + + test('should be usable in a slice with extra properties', () => { + type Entity = { id: EntityId; value: string } + const adapter = createEntityAdapter() + createSlice({ + name: 'test', + initialState: adapter.getInitialState({ extraData: 'test' }), + reducers: { + addOne: adapter.addOne, + }, + }) + }) + + test('should not be usable in a slice with an unfitting state', () => { + type Entity = { id: EntityId; value: string } + const adapter = createEntityAdapter() + createSlice({ + name: 'test', + initialState: { somethingElse: '' }, + reducers: { + // @ts-expect-error + addOne: adapter.addOne, + }, + }) + }) + + test('should not be able to create an adapter unless the type has an Id or an idSelector is provided', () => { + type Entity = { + value: string + } + // @ts-expect-error + const adapter = createEntityAdapter() + const adapter2: EntityAdapter = + createEntityAdapter({ + selectId: (e: Entity) => e.value, + }) + }) +}) diff --git a/packages/toolkit/src/tests/createEntityAdapter.typetest.ts b/packages/toolkit/src/tests/createEntityAdapter.typetest.ts deleted file mode 100644 index 30a64395c1..0000000000 --- a/packages/toolkit/src/tests/createEntityAdapter.typetest.ts +++ /dev/null @@ -1,148 +0,0 @@ -import type { - EntityAdapter, - ActionCreatorWithPayload, - ActionCreatorWithoutPayload, - EntityStateAdapter, - EntityId, - Update, -} from '@reduxjs/toolkit' -import { createSlice, createEntityAdapter } from '@reduxjs/toolkit' -import { expectType } from './helpers' - -function extractReducers( - adapter: EntityAdapter -): Omit, 'map'> { - const { selectId, sortComparer, getInitialState, getSelectors, ...rest } = - adapter - return rest -} - -/** - * should be usable in a slice, with all the "reducer-like" functions - */ -{ - type Id = string & { readonly __tag: unique symbol } - type Entity = { - id: Id - } - const adapter = createEntityAdapter() - const slice = createSlice({ - name: 'test', - initialState: adapter.getInitialState(), - reducers: { - ...extractReducers(adapter), - }, - }) - - expectType>(slice.actions.addOne) - expectType< - ActionCreatorWithPayload | Record> - >(slice.actions.addMany) - expectType< - ActionCreatorWithPayload | Record> - >(slice.actions.setAll) - expectType>>( - // @ts-expect-error - slice.actions.addMany - ) - expectType>>( - // @ts-expect-error - slice.actions.setAll - ) - expectType>(slice.actions.removeOne) - expectType>>( - slice.actions.removeMany - ) - // @ts-expect-error - expectType>(slice.actions.removeMany) - expectType(slice.actions.removeAll) - expectType>>( - slice.actions.updateOne - ) - expectType[]>>( - // @ts-expect-error - slice.actions.updateMany - ) - expectType>>>( - slice.actions.updateMany - ) - expectType>(slice.actions.upsertOne) - expectType< - ActionCreatorWithPayload | Record> - >(slice.actions.upsertMany) - expectType>>( - // @ts-expect-error - slice.actions.upsertMany - ) -} - -/** - * should not be able to mix with a different EntityAdapter - */ -{ - type Entity = { - id: EntityId - value: string - } - type Entity2 = { - id: EntityId - value2: string - } - const adapter = createEntityAdapter() - const adapter2 = createEntityAdapter() - createSlice({ - name: 'test', - initialState: adapter.getInitialState(), - reducers: { - addOne: adapter.addOne, - // @ts-expect-error - addOne2: adapter2.addOne, - }, - }) -} - -/** - * should be usable in a slice with extra properties - */ -{ - type Entity = { id: EntityId; value: string } - const adapter = createEntityAdapter() - createSlice({ - name: 'test', - initialState: adapter.getInitialState({ extraData: 'test' }), - reducers: { - addOne: adapter.addOne, - }, - }) -} - -/** - * should not be usable in a slice with an unfitting state - */ -{ - type Entity = { id: EntityId; value: string } - const adapter = createEntityAdapter() - createSlice({ - name: 'test', - initialState: { somethingElse: '' }, - reducers: { - // @ts-expect-error - addOne: adapter.addOne, - }, - }) -} - -/** - * should not be able to create an adapter unless the type has an Id - * or an idSelector is provided - */ -{ - type Entity = { - value: string - } - // @ts-expect-error - const adapter = createEntityAdapter() - const adapter2: EntityAdapter = createEntityAdapter({ - selectId: (e: Entity) => e.value, - }) -} diff --git a/packages/toolkit/src/tests/createReducer.test-d.ts b/packages/toolkit/src/tests/createReducer.test-d.ts new file mode 100644 index 0000000000..535710a256 --- /dev/null +++ b/packages/toolkit/src/tests/createReducer.test-d.ts @@ -0,0 +1,74 @@ +import type { ActionReducerMapBuilder, Reducer } from '@reduxjs/toolkit' +import { createAction, createReducer } from '@reduxjs/toolkit' + +describe('type tests', () => { + test('createReducer() infers type of returned reducer.', () => { + const incrementHandler = ( + state: number, + action: { type: 'increment'; payload: number }, + ) => state + 1 + + const decrementHandler = ( + state: number, + action: { type: 'decrement'; payload: number }, + ) => state - 1 + + const reducer = createReducer(0 as number, (builder) => { + builder + .addCase('increment', incrementHandler) + .addCase('decrement', decrementHandler) + }) + + expectTypeOf(reducer).toMatchTypeOf>() + + expectTypeOf(reducer).not.toMatchTypeOf>() + }) + + test('createReducer() state type can be specified explicitly.', () => { + const incrementHandler = ( + state: number, + action: { type: 'increment'; payload: number }, + ) => state + action.payload + + const decrementHandler = ( + state: number, + action: { type: 'decrement'; payload: number }, + ) => state - action.payload + + createReducer(0 as number, (builder) => { + builder + .addCase('increment', incrementHandler) + .addCase('decrement', decrementHandler) + }) + + // @ts-expect-error + createReducer(0 as number, (builder) => { + // @ts-expect-error + builder + .addCase('increment', incrementHandler) + .addCase('decrement', decrementHandler) + }) + }) + + test('createReducer() ensures state type is mutable within a case reducer.', () => { + const initialState: { readonly counter: number } = { counter: 0 } + + createReducer(initialState, (builder) => { + builder.addCase('increment', (state) => { + state.counter += 1 + }) + }) + }) + + test('builder callback for actionMap', () => { + const increment = createAction('increment') + + const reducer = createReducer(0, (builder) => + expectTypeOf(builder).toEqualTypeOf>(), + ) + + expectTypeOf(reducer(0, increment(5))).toBeNumber() + + expectTypeOf(reducer(0, increment(5))).not.toBeString() + }) +}) diff --git a/packages/toolkit/src/tests/createReducer.test.ts b/packages/toolkit/src/tests/createReducer.test.ts index 5d794c78b7..e5ea7365a3 100644 --- a/packages/toolkit/src/tests/createReducer.test.ts +++ b/packages/toolkit/src/tests/createReducer.test.ts @@ -89,11 +89,11 @@ describe('createReducer', () => { } expect(wrapper).toThrowError( - /The object notation for `createReducer` has been removed/ + /The object notation for `createReducer` has been removed/, ) expect(wrapper).toThrowError( - /The object notation for `createReducer` has been removed/ + /The object notation for `createReducer` has been removed/, ) }) @@ -145,7 +145,7 @@ describe('createReducer', () => { const mutateStateOutsideReducer = () => (result[0].text = 'edited') expect(mutateStateOutsideReducer).toThrowError( - 'Cannot add property text, object is not extensible' + 'Cannot add property text, object is not extensible', ) }) @@ -157,12 +157,12 @@ describe('createReducer', () => { const mutateStateOutsideReducer = () => (frozenInitialState[0].text = 'edited') expect(mutateStateOutsideReducer).toThrowError( - /Cannot assign to read only property/ + /Cannot assign to read only property/, ) }) test('does not throw error if initial state is not draftable', () => { expect(() => - createReducer(new URLSearchParams(), () => {}) + createReducer(new URLSearchParams(), () => {}), ).not.toThrowError() }) }) @@ -263,7 +263,7 @@ describe('createReducer', () => { const reducer = createReducer(0, (builder) => builder .addCase(increment, (state, action) => state + action.payload) - .addCase(decrement, (state, action) => state - action.payload) + .addCase(decrement, (state, action) => state - action.payload), ) expect(reducer(0, increment(5))).toBe(5) expect(reducer(5, decrement(5))).toBe(0) @@ -274,13 +274,13 @@ describe('createReducer', () => { .addCase( 'increment', (state, action: { type: 'increment'; payload: number }) => - state + action.payload + state + action.payload, ) .addCase( 'decrement', (state, action: { type: 'decrement'; payload: number }) => - state - action.payload - ) + state - action.payload, + ), ) expect(reducer(0, increment(5))).toBe(5) expect(reducer(5, decrement(5))).toBe(0) @@ -292,8 +292,8 @@ describe('createReducer', () => { .addCase( 'decrement', (state, action: { type: 'decrement'; payload: number }) => - state - action.payload - ) + state - action.payload, + ), ) expect(reducer(0, increment(5))).toBe(5) expect(reducer(5, decrement(5))).toBe(0) @@ -302,11 +302,11 @@ describe('createReducer', () => { const reducer = createReducer(0, (builder) => builder.addCase( 'decrement', - (state, action: { type: 'decrement'; payload: number }) => {} - ) + (state, action: { type: 'decrement'; payload: number }) => {}, + ), ) expect(() => reducer(5, decrement(5))).toThrowErrorMatchingInlineSnapshot( - `[Error: A case reducer on a non-draftable value must not return undefined]` + `[Error: A case reducer on a non-draftable value must not return undefined]`, ) }) test('allows you to return undefined if the state was null, thus skipping an update', () => { @@ -318,8 +318,8 @@ describe('createReducer', () => { return state - action.payload } return undefined - } - ) + }, + ), ) expect(reducer(0, decrement(5))).toBe(-5) expect(reducer(null, decrement(5))).toBe(null) @@ -330,8 +330,8 @@ describe('createReducer', () => { 'decrement', (state, action: { type: 'decrement'; payload: number }) => { return null - } - ) + }, + ), ) expect(reducer(5, decrement(5))).toBe(null) }) @@ -340,8 +340,8 @@ describe('createReducer', () => { builder.addCase( 'decrement', (state, action: { type: 'decrement'; payload: number }) => - state - action.payload - ) + state - action.payload, + ), ) expect(reducer(5, decrement(5))).toBe(0) }) @@ -351,20 +351,20 @@ describe('createReducer', () => { builder .addCase(increment, (state, action) => state + action.payload) .addCase(increment, (state, action) => state + action.payload) - .addCase(decrement, (state, action) => state - action.payload) - ) + .addCase(decrement, (state, action) => state - action.payload), + ), ).toThrowErrorMatchingInlineSnapshot( - `[Error: \`builder.addCase\` cannot be called with two reducers for the same action type 'increment']` + `[Error: \`builder.addCase\` cannot be called with two reducers for the same action type 'increment']`, ) expect(() => createReducer(0, (builder) => builder .addCase(increment, (state, action) => state + action.payload) .addCase('increment', (state) => state + 1) - .addCase(decrement, (state, action) => state - action.payload) - ) + .addCase(decrement, (state, action) => state - action.payload), + ), ).toThrowErrorMatchingInlineSnapshot( - `[Error: \`builder.addCase\` cannot be called with two reducers for the same action type 'increment']` + `[Error: \`builder.addCase\` cannot be called with two reducers for the same action type 'increment']`, ) }) @@ -373,16 +373,16 @@ describe('createReducer', () => { type: 'custom_action', payload, }) - customActionCreator.type = "" + customActionCreator.type = '' expect(() => createReducer(0, (builder) => builder.addCase( customActionCreator, - (state, action) => state + action.payload - ) - ) + (state, action) => state + action.payload, + ), + ), ).toThrowErrorMatchingInlineSnapshot( - `[Error: \`builder.addCase\` cannot be called with an empty action type]` + `[Error: \`builder.addCase\` cannot be called with an empty action type]`, ) }) }) @@ -398,14 +398,14 @@ describe('createReducer', () => { }) const numberActionMatcher = ( - a: UnknownAction + a: UnknownAction, ): a is PayloadAction => isPlainObject(a.meta) && 'type' in a.meta && (a.meta as Record<'type', unknown>).type === 'number_action' const stringActionMatcher = ( - a: UnknownAction + a: UnknownAction, ): a is PayloadAction => isPlainObject(a.meta) && 'type' in a.meta && @@ -425,7 +425,7 @@ describe('createReducer', () => { }) .addMatcher(stringActionMatcher, (state) => { state.stringActions += 1 - }) + }), ) expect(reducer(undefined, incrementBy(1))).toEqual({ numberActions: 1, @@ -452,7 +452,7 @@ describe('createReducer', () => { .addDefaultCase((state) => { state.numberActions = -1 state.stringActions = -1 - }) + }), ) expect(reducer(undefined, { type: 'somethingElse' })).toEqual({ numberActions: -1, @@ -473,7 +473,7 @@ describe('createReducer', () => { }) .addMatcher(numberActionMatcher, (state) => { state.numberActions = state.numberActions * 10 + 3 - }) + }), ) expect(reducer(undefined, incrementBy(1))).toEqual({ numberActions: 123, @@ -492,7 +492,7 @@ describe('createReducer', () => { const reducer = createReducer(initialState, (builder) => builder.addMatcher(incrementBy.match, (state) => { state.numberActions += 100 - }) + }), ) expect(reducer(undefined, incrementBy(1))).toEqual({ numberActions: 100, @@ -504,33 +504,33 @@ describe('createReducer', () => { createReducer(initialState, (builder: any) => builder .addMatcher(numberActionMatcher, () => {}) - .addCase(incrementBy, () => {}) - ) + .addCase(incrementBy, () => {}), + ), ).toThrowErrorMatchingInlineSnapshot( - `[Error: \`builder.addCase\` should only be called before calling \`builder.addMatcher\`]` + `[Error: \`builder.addCase\` should only be called before calling \`builder.addMatcher\`]`, ) expect(() => createReducer(initialState, (builder: any) => - builder.addDefaultCase(() => {}).addCase(incrementBy, () => {}) - ) + builder.addDefaultCase(() => {}).addCase(incrementBy, () => {}), + ), ).toThrowErrorMatchingInlineSnapshot( - `[Error: \`builder.addCase\` should only be called before calling \`builder.addDefaultCase\`]` + `[Error: \`builder.addCase\` should only be called before calling \`builder.addDefaultCase\`]`, ) expect(() => createReducer(initialState, (builder: any) => builder .addDefaultCase(() => {}) - .addMatcher(numberActionMatcher, () => {}) - ) + .addMatcher(numberActionMatcher, () => {}), + ), ).toThrowErrorMatchingInlineSnapshot( - `[Error: \`builder.addMatcher\` should only be called before calling \`builder.addDefaultCase\`]` + `[Error: \`builder.addMatcher\` should only be called before calling \`builder.addDefaultCase\`]`, ) expect(() => createReducer(initialState, (builder: any) => - builder.addDefaultCase(() => {}).addDefaultCase(() => {}) - ) + builder.addDefaultCase(() => {}).addDefaultCase(() => {}), + ), ).toThrowErrorMatchingInlineSnapshot( - `[Error: \`builder.addDefaultCase\` can only be called once]` + `[Error: \`builder.addDefaultCase\` can only be called once]`, ) }) }) @@ -547,7 +547,7 @@ function behavesLikeReducer(todosReducer: TodosReducer) { todosReducer([], { type: 'ADD_TODO', payload: { newTodo: { text: 'Run the tests' } }, - }) + }), ).toEqual([ { text: 'Run the tests', @@ -566,8 +566,8 @@ function behavesLikeReducer(todosReducer: TodosReducer) { { type: 'ADD_TODO', payload: { newTodo: { text: 'Use Redux' } }, - } - ) + }, + ), ).toEqual([ { text: 'Run the tests', @@ -594,8 +594,8 @@ function behavesLikeReducer(todosReducer: TodosReducer) { { type: 'ADD_TODO', payload: { newTodo: { text: 'Fix the tests' } }, - } - ) + }, + ), ).toEqual([ { text: 'Run the tests', @@ -628,8 +628,8 @@ function behavesLikeReducer(todosReducer: TodosReducer) { { type: 'TOGGLE_TODO', payload: { index: 0 }, - } - ) + }, + ), ).toEqual([ { text: 'Run the tests', diff --git a/packages/toolkit/src/tests/createReducer.typetest.ts b/packages/toolkit/src/tests/createReducer.typetest.ts deleted file mode 100644 index 4fe5c2a62f..0000000000 --- a/packages/toolkit/src/tests/createReducer.typetest.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { Reducer } from 'redux' -import type { ActionReducerMapBuilder } from '@reduxjs/toolkit' -import { createReducer, createAction } from '@reduxjs/toolkit' -import { expectType } from './helpers' - -/* - * Test: createReducer() infers type of returned reducer. - */ -{ - const incrementHandler = ( - state: number, - action: { type: 'increment'; payload: number } - ) => state + 1 - const decrementHandler = ( - state: number, - action: { type: 'decrement'; payload: number } - ) => state - 1 - - const reducer = createReducer(0 as number, (builder) => { - builder - .addCase('increment', incrementHandler) - .addCase('decrement', decrementHandler) - }) - - const numberReducer: Reducer = reducer - - // @ts-expect-error - const stringReducer: Reducer = reducer -} - -/** - * Test: createReducer() state type can be specified expliclity. - */ -{ - const incrementHandler = ( - state: number, - action: { type: 'increment'; payload: number } - ) => state + action.payload - - const decrementHandler = ( - state: number, - action: { type: 'decrement'; payload: number } - ) => state - action.payload - - createReducer(0 as number, (builder) => { - builder - .addCase('increment', incrementHandler) - .addCase('decrement', decrementHandler) - }) - - // @ts-expect-error - createReducer(0 as number, (builder) => { - // @ts-expect-error - builder - .addCase('increment', incrementHandler) - .addCase('decrement', decrementHandler) - }) -} - -/* - * Test: createReducer() ensures state type is mutable within a case reducer. - */ -{ - const initialState: { readonly counter: number } = { counter: 0 } - - createReducer(initialState, (builder) => { - builder.addCase('increment', (state) => { - state.counter += 1 - }) - }) -} - -/** Test: builder callback for actionMap */ -{ - const increment = createAction('increment') - - const reducer = createReducer(0, (builder) => - expectType>(builder) - ) - - expectType(reducer(0, increment(5))) - // @ts-expect-error - expectType(reducer(0, increment(5))) -} diff --git a/packages/toolkit/src/tests/createSlice.test-d.ts b/packages/toolkit/src/tests/createSlice.test-d.ts new file mode 100644 index 0000000000..d76d8fa5ee --- /dev/null +++ b/packages/toolkit/src/tests/createSlice.test-d.ts @@ -0,0 +1,957 @@ +import type { + Action, + ActionCreatorWithNonInferrablePayload, + ActionCreatorWithOptionalPayload, + ActionCreatorWithPayload, + ActionCreatorWithPreparedPayload, + ActionCreatorWithoutPayload, + ActionReducerMapBuilder, + AsyncThunk, + CaseReducer, + PayloadAction, + PayloadActionCreator, + Reducer, + ReducerCreators, + SerializedError, + SliceCaseReducers, + ThunkDispatch, + UnknownAction, + ValidateSliceCaseReducers, +} from '@reduxjs/toolkit' +import { + asyncThunkCreator, + buildCreateSlice, + configureStore, + createAction, + createAsyncThunk, + createSlice, + isRejected, +} from '@reduxjs/toolkit' +import { castDraft } from 'immer' + +describe('type tests', () => { + const counterSlice = createSlice({ + name: 'counter', + initialState: 0, + reducers: { + increment: (state: number, action) => state + action.payload, + decrement: (state: number, action) => state - action.payload, + }, + }) + + test('Slice name is strongly typed.', () => { + const uiSlice = createSlice({ + name: 'ui', + initialState: 0, + reducers: { + goToNext: (state: number, action) => state + action.payload, + goToPrevious: (state: number, action) => state - action.payload, + }, + }) + + const actionCreators = { + [counterSlice.name]: { ...counterSlice.actions }, + [uiSlice.name]: { ...uiSlice.actions }, + } + + expectTypeOf(counterSlice.actions).toEqualTypeOf(actionCreators.counter) + + expectTypeOf(uiSlice.actions).toEqualTypeOf(actionCreators.ui) + + expectTypeOf(actionCreators).not.toHaveProperty('anyKey') + }) + + test("createSlice() infers the returned slice's type.", () => { + const firstAction = createAction<{ count: number }>('FIRST_ACTION') + + const slice = createSlice({ + name: 'counter', + initialState: 0, + reducers: { + increment: (state: number, action) => state + action.payload, + decrement: (state: number, action) => state - action.payload, + }, + extraReducers: (builder) => { + builder.addCase( + firstAction, + (state, action) => state + action.payload.count, + ) + }, + }) + + test('Reducer', () => { + expectTypeOf(slice.reducer).toMatchTypeOf< + Reducer + >() + + expectTypeOf(slice.reducer).not.toMatchTypeOf< + Reducer + >() + }) + + test('Actions', () => { + slice.actions.increment(1) + slice.actions.decrement(1) + + expectTypeOf(slice.actions).not.toHaveProperty('other') + }) + }) + + test('Slice action creator types are inferred.', () => { + const counter = createSlice({ + name: 'counter', + initialState: 0, + reducers: { + increment: (state) => state + 1, + decrement: ( + state, + { payload = 1 }: PayloadAction, + ) => state - payload, + multiply: (state, { payload }: PayloadAction) => + Array.isArray(payload) + ? payload.reduce((acc, val) => acc * val, state) + : state * payload, + addTwo: { + reducer: (s, { payload }: PayloadAction) => s + payload, + prepare: (a: number, b: number) => ({ + payload: a + b, + }), + }, + }, + }) + + expectTypeOf( + counter.actions.increment, + ).toMatchTypeOf() + + counter.actions.increment() + + expectTypeOf(counter.actions.decrement).toMatchTypeOf< + ActionCreatorWithOptionalPayload + >() + + counter.actions.decrement() + counter.actions.decrement(2) + + expectTypeOf(counter.actions.multiply).toMatchTypeOf< + ActionCreatorWithPayload + >() + + counter.actions.multiply(2) + counter.actions.multiply([2, 3, 4]) + + expectTypeOf(counter.actions.addTwo).toMatchTypeOf< + ActionCreatorWithPreparedPayload<[number, number], number> + >() + + counter.actions.addTwo(1, 2) + + expectTypeOf(counter.actions.multiply).parameters.not.toMatchTypeOf<[]>() + + expectTypeOf(counter.actions.multiply).parameter(0).not.toBeString() + + expectTypeOf(counter.actions.addTwo).parameters.not.toMatchTypeOf< + [number] + >() + + expectTypeOf(counter.actions.addTwo).parameters.toEqualTypeOf< + [number, number] + >() + }) + + test('Slice action creator types properties are strongly typed', () => { + const counter = createSlice({ + name: 'counter', + initialState: 0, + reducers: { + increment: (state) => state + 1, + decrement: (state) => state - 1, + multiply: (state, { payload }: PayloadAction) => + Array.isArray(payload) + ? payload.reduce((acc, val) => acc * val, state) + : state * payload, + }, + }) + + expectTypeOf( + counter.actions.increment.type, + ).toEqualTypeOf<'counter/increment'>() + + expectTypeOf( + counter.actions.increment().type, + ).toEqualTypeOf<'counter/increment'>() + + expectTypeOf( + counter.actions.decrement.type, + ).toEqualTypeOf<'counter/decrement'>() + + expectTypeOf( + counter.actions.decrement().type, + ).toEqualTypeOf<'counter/decrement'>() + + expectTypeOf( + counter.actions.multiply.type, + ).toEqualTypeOf<'counter/multiply'>() + + expectTypeOf( + counter.actions.multiply(1).type, + ).toEqualTypeOf<'counter/multiply'>() + + expectTypeOf( + counter.actions.increment.type, + ).not.toMatchTypeOf<'increment'>() + }) + + test('Slice action creator types are inferred for enhanced reducers.', () => { + const counter = createSlice({ + name: 'test', + initialState: { counter: 0, concat: '' }, + reducers: { + incrementByStrLen: { + reducer: (state, action: PayloadAction) => { + state.counter += action.payload + }, + prepare: (payload: string) => ({ + payload: payload.length, + }), + }, + concatMetaStrLen: { + reducer: (state, action: PayloadAction) => { + state.concat += action.payload + }, + prepare: (payload: string) => ({ + payload, + meta: payload.length, + }), + }, + }, + }) + + expectTypeOf( + counter.actions.incrementByStrLen('test').type, + ).toEqualTypeOf<'test/incrementByStrLen'>() + + expectTypeOf(counter.actions.incrementByStrLen('test').payload).toBeNumber() + + expectTypeOf(counter.actions.concatMetaStrLen('test').payload).toBeString() + + expectTypeOf(counter.actions.concatMetaStrLen('test').meta).toBeNumber() + + expectTypeOf( + counter.actions.incrementByStrLen('test').payload, + ).not.toBeString() + + expectTypeOf(counter.actions.concatMetaStrLen('test').meta).not.toBeString() + }) + + test('access meta and error from reducer', () => { + const counter = createSlice({ + name: 'test', + initialState: { counter: 0, concat: '' }, + reducers: { + // case: meta and error not used in reducer + testDefaultMetaAndError: { + reducer(_, action: PayloadAction) {}, + prepare: (payload: number) => ({ + payload, + meta: 'meta' as 'meta', + error: 'error' as 'error', + }), + }, + // case: meta and error marked as "unknown" in reducer + testUnknownMetaAndError: { + reducer( + _, + action: PayloadAction, + ) {}, + prepare: (payload: number) => ({ + payload, + meta: 'meta' as 'meta', + error: 'error' as 'error', + }), + }, + // case: meta and error are typed in the reducer as returned by prepare + testMetaAndError: { + reducer(_, action: PayloadAction) {}, + prepare: (payload: number) => ({ + payload, + meta: 'meta' as 'meta', + error: 'error' as 'error', + }), + }, + // case: meta is typed differently in the reducer than returned from prepare + testErroneousMeta: { + reducer(_, action: PayloadAction) {}, + // @ts-expect-error + prepare: (payload: number) => ({ + payload, + meta: 1, + error: 'error' as 'error', + }), + }, + // case: error is typed differently in the reducer than returned from prepare + testErroneousError: { + reducer(_, action: PayloadAction) {}, + // @ts-expect-error + prepare: (payload: number) => ({ + payload, + meta: 'meta' as 'meta', + error: 1, + }), + }, + }, + }) + }) + + test('returned case reducer has the correct type', () => { + const counter = createSlice({ + name: 'counter', + initialState: 0, + reducers: { + increment(state, action: PayloadAction) { + return state + action.payload + }, + decrement: { + reducer(state, action: PayloadAction) { + return state - action.payload + }, + prepare(amount: number) { + return { payload: amount } + }, + }, + }, + }) + + test('Should match positively', () => { + expectTypeOf(counter.caseReducers.increment).toMatchTypeOf< + (state: number, action: PayloadAction) => number | void + >() + }) + + test('Should match positively for reducers with prepare callback', () => { + expectTypeOf(counter.caseReducers.decrement).toMatchTypeOf< + (state: number, action: PayloadAction) => number | void + >() + }) + + test("Should not mismatch the payload if it's a simple reducer", () => { + expectTypeOf(counter.caseReducers.increment).not.toMatchTypeOf< + (state: number, action: PayloadAction) => number | void + >() + }) + + test("Should not mismatch the payload if it's a reducer with a prepare callback", () => { + expectTypeOf(counter.caseReducers.decrement).not.toMatchTypeOf< + (state: number, action: PayloadAction) => number | void + >() + }) + + test("Should not include entries that don't exist", () => { + expectTypeOf(counter.caseReducers).not.toHaveProperty( + 'someThingNonExistent', + ) + }) + }) + + test('prepared payload does not match action payload - should cause an error.', () => { + const counter = createSlice({ + name: 'counter', + initialState: { counter: 0 }, + reducers: { + increment: { + reducer(state, action: PayloadAction) { + state.counter += action.payload.length + }, + // @ts-expect-error + prepare(x: string) { + return { + payload: 6, + } + }, + }, + }, + }) + }) + + test('if no Payload Type is specified, accept any payload', () => { + // see https://github.com/reduxjs/redux-toolkit/issues/165 + + const initialState = { + name: null, + } + + const mySlice = createSlice({ + name: 'name', + initialState, + reducers: { + setName: (state, action) => { + state.name = action.payload + }, + }, + }) + + expectTypeOf( + mySlice.actions.setName, + ).toMatchTypeOf() + + const x = mySlice.actions.setName + + mySlice.actions.setName(null) + mySlice.actions.setName('asd') + mySlice.actions.setName(5) + }) + + test('actions.x.match()', () => { + const mySlice = createSlice({ + name: 'name', + initialState: { name: 'test' }, + reducers: { + setName: (state, action: PayloadAction) => { + state.name = action.payload + }, + }, + }) + + const x: Action = {} as any + if (mySlice.actions.setName.match(x)) { + expectTypeOf(x.type).toEqualTypeOf<'name/setName'>() + + expectTypeOf(x.payload).toBeString() + } else { + expectTypeOf(x.type).not.toMatchTypeOf<'name/setName'>() + + expectTypeOf(x).not.toHaveProperty('payload') + } + }) + + test('builder callback for extraReducers', () => { + createSlice({ + name: 'test', + initialState: 0, + reducers: {}, + extraReducers: (builder) => { + expectTypeOf(builder).toEqualTypeOf>() + }, + }) + }) + + test('wrapping createSlice should be possible', () => { + interface GenericState { + data?: T + status: 'loading' | 'finished' | 'error' + } + + const createGenericSlice = < + T, + Reducers extends SliceCaseReducers>, + >({ + name = '', + initialState, + reducers, + }: { + name: string + initialState: GenericState + reducers: ValidateSliceCaseReducers, Reducers> + }) => { + return createSlice({ + name, + initialState, + reducers: { + start(state) { + state.status = 'loading' + }, + success(state: GenericState, action: PayloadAction) { + state.data = action.payload + state.status = 'finished' + }, + ...reducers, + }, + }) + } + + const wrappedSlice = createGenericSlice({ + name: 'test', + initialState: { status: 'loading' } as GenericState, + reducers: { + magic(state) { + expectTypeOf(state).toEqualTypeOf>() + + expectTypeOf(state).not.toMatchTypeOf>() + + state.status = 'finished' + state.data = 'hocus pocus' + }, + }, + }) + + expectTypeOf(wrappedSlice.actions.success).toMatchTypeOf< + ActionCreatorWithPayload + >() + + expectTypeOf(wrappedSlice.actions.magic).toMatchTypeOf< + ActionCreatorWithoutPayload + >() + }) + + test('extraReducers', () => { + interface GenericState { + data: T | null + } + + function createDataSlice< + T, + Reducers extends SliceCaseReducers>, + >( + name: string, + reducers: ValidateSliceCaseReducers, Reducers>, + initialState: GenericState, + ) { + const doNothing = createAction('doNothing') + const setData = createAction('setData') + + const slice = createSlice({ + name, + initialState, + reducers, + extraReducers: (builder) => { + builder.addCase(doNothing, (state) => { + return { ...state } + }) + builder.addCase(setData, (state, { payload }) => { + return { + ...state, + data: payload, + } + }) + }, + }) + return { doNothing, setData, slice } + } + }) + + test('slice selectors', () => { + const sliceWithoutSelectors = createSlice({ + name: '', + initialState: '', + reducers: {}, + }) + + expectTypeOf(sliceWithoutSelectors.selectors).not.toHaveProperty('foo') + + const sliceWithSelectors = createSlice({ + name: 'counter', + initialState: { value: 0 }, + reducers: { + increment: (state) => { + state.value += 1 + }, + }, + selectors: { + selectValue: (state) => state.value, + selectMultiply: (state, multiplier: number) => state.value * multiplier, + selectToFixed: Object.assign( + (state: { value: number }) => state.value.toFixed(2), + { static: true }, + ), + }, + }) + + const rootState = { + [sliceWithSelectors.reducerPath]: sliceWithSelectors.getInitialState(), + } + + const { selectValue, selectMultiply, selectToFixed } = + sliceWithSelectors.selectors + + expectTypeOf(selectValue(rootState)).toBeNumber() + + expectTypeOf(selectMultiply(rootState, 2)).toBeNumber() + + expectTypeOf(selectToFixed(rootState)).toBeString() + + expectTypeOf(selectToFixed.unwrapped.static).toBeBoolean() + + const nestedState = { + nested: rootState, + } + + const nestedSelectors = sliceWithSelectors.getSelectors( + (rootState: typeof nestedState) => rootState.nested.counter, + ) + + expectTypeOf(nestedSelectors.selectValue(nestedState)).toBeNumber() + + expectTypeOf(nestedSelectors.selectMultiply(nestedState, 2)).toBeNumber() + + expectTypeOf(nestedSelectors.selectToFixed(nestedState)).toBeString() + }) + + test('reducer callback', () => { + interface TestState { + foo: string + } + + interface TestArg { + test: string + } + + interface TestReturned { + payload: string + } + + interface TestReject { + cause: string + } + + const slice = createSlice({ + name: 'test', + initialState: {} as TestState, + reducers: (create) => { + const preTypedAsyncThunk = create.asyncThunk.withTypes<{ + rejectValue: TestReject + }>() + + // @ts-expect-error + create.asyncThunk(() => {}) + + // @ts-expect-error + create.asyncThunk.withTypes<{ + rejectValue: string + dispatch: StoreDispatch + }>() + + return { + normalReducer: create.reducer((state, action) => { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.payload).toBeString() + }), + optionalReducer: create.reducer( + (state, action) => { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.payload).toEqualTypeOf() + }, + ), + noActionReducer: create.reducer((state) => { + expectTypeOf(state).toEqualTypeOf() + }), + preparedReducer: create.preparedReducer( + (payload: string) => ({ + payload, + meta: 'meta' as const, + error: 'error' as const, + }), + (state, action) => { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.payload).toBeString() + + expectTypeOf(action.meta).toEqualTypeOf<'meta'>() + + expectTypeOf(action.error).toEqualTypeOf<'error'>() + }, + ), + testInfer: create.asyncThunk( + function payloadCreator(arg: TestArg, api) { + return Promise.resolve({ payload: 'foo' }) + }, + { + pending(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + }, + fulfilled(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + + expectTypeOf(action.payload).toEqualTypeOf() + }, + rejected(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + + expectTypeOf(action.error).toEqualTypeOf() + }, + settled(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + + if (isRejected(action)) { + expectTypeOf(action.error).toEqualTypeOf() + } else { + expectTypeOf(action.payload).toEqualTypeOf() + } + }, + }, + ), + testExplicitType: create.asyncThunk< + TestReturned, + TestArg, + { + rejectValue: TestReject + } + >( + function payloadCreator(arg, api) { + // here would be a circular reference + expectTypeOf(api.getState()).toBeUnknown() + // here would be a circular reference + expectTypeOf(api.dispatch).toMatchTypeOf< + ThunkDispatch + >() + + // so you need to cast inside instead + const getState = api.getState as () => StoreState + const dispatch = api.dispatch as StoreDispatch + + expectTypeOf(arg).toEqualTypeOf() + + expectTypeOf(api.rejectWithValue).toMatchTypeOf< + (value: TestReject) => any + >() + + return Promise.resolve({ payload: 'foo' }) + }, + { + pending(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + }, + fulfilled(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + + expectTypeOf(action.payload).toEqualTypeOf() + }, + rejected(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + + expectTypeOf(action.error).toEqualTypeOf() + + expectTypeOf(action.payload).toEqualTypeOf< + TestReject | undefined + >() + }, + settled(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + + if (isRejected(action)) { + expectTypeOf(action.error).toEqualTypeOf() + + expectTypeOf(action.payload).toEqualTypeOf< + TestReject | undefined + >() + } else { + expectTypeOf(action.payload).toEqualTypeOf() + } + }, + }, + ), + testPreTyped: preTypedAsyncThunk( + function payloadCreator(arg: TestArg, api) { + expectTypeOf(api.rejectWithValue).toMatchTypeOf< + (value: TestReject) => any + >() + + return Promise.resolve({ payload: 'foo' }) + }, + { + pending(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + }, + fulfilled(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + + expectTypeOf(action.payload).toEqualTypeOf() + }, + rejected(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + + expectTypeOf(action.error).toEqualTypeOf() + + expectTypeOf(action.payload).toEqualTypeOf< + TestReject | undefined + >() + }, + settled(state, action) { + expectTypeOf(state).toEqualTypeOf() + + expectTypeOf(action.meta.arg).toEqualTypeOf() + + if (isRejected(action)) { + expectTypeOf(action.error).toEqualTypeOf() + + expectTypeOf(action.payload).toEqualTypeOf< + TestReject | undefined + >() + } else { + expectTypeOf(action.payload).toEqualTypeOf() + } + }, + }, + ), + } + }, + }) + + const store = configureStore({ reducer: { test: slice.reducer } }) + + type StoreState = ReturnType + + type StoreDispatch = typeof store.dispatch + + expectTypeOf(slice.actions.normalReducer).toMatchTypeOf< + PayloadActionCreator + >() + + expectTypeOf(slice.actions.normalReducer).toBeCallableWith('') + + expectTypeOf(slice.actions.normalReducer).parameters.not.toMatchTypeOf<[]>() + + expectTypeOf(slice.actions.normalReducer).parameters.not.toMatchTypeOf< + [number] + >() + + expectTypeOf(slice.actions.optionalReducer).toMatchTypeOf< + ActionCreatorWithOptionalPayload + >() + + expectTypeOf(slice.actions.optionalReducer).toBeCallableWith() + + expectTypeOf(slice.actions.optionalReducer).toBeCallableWith('') + + expectTypeOf(slice.actions.optionalReducer).parameter(0).not.toBeNumber() + + expectTypeOf( + slice.actions.noActionReducer, + ).toMatchTypeOf() + + expectTypeOf(slice.actions.noActionReducer).toBeCallableWith() + + expectTypeOf(slice.actions.noActionReducer).parameter(0).not.toBeString() + + expectTypeOf(slice.actions.preparedReducer).toEqualTypeOf< + ActionCreatorWithPreparedPayload< + [string], + string, + 'test/preparedReducer', + 'error', + 'meta' + > + >() + + expectTypeOf(slice.actions.testInfer).toEqualTypeOf< + AsyncThunk + >() + + expectTypeOf(slice.actions.testExplicitType).toEqualTypeOf< + AsyncThunk + >() + + type TestInferThunk = AsyncThunk + + expectTypeOf(slice.caseReducers.testInfer.pending).toEqualTypeOf< + CaseReducer> + >() + + expectTypeOf(slice.caseReducers.testInfer.fulfilled).toEqualTypeOf< + CaseReducer> + >() + + expectTypeOf(slice.caseReducers.testInfer.rejected).toEqualTypeOf< + CaseReducer> + >() + }) + + test('wrapping createSlice should be possible, with callback', () => { + interface GenericState { + data?: T + status: 'loading' | 'finished' | 'error' + } + + const createGenericSlice = < + T, + Reducers extends SliceCaseReducers>, + >({ + name = '', + initialState, + reducers, + }: { + name: string + initialState: GenericState + reducers: (create: ReducerCreators>) => Reducers + }) => { + return createSlice({ + name, + initialState, + reducers: (create) => ({ + start: create.reducer((state) => { + state.status = 'loading' + }), + success: create.reducer((state, action) => { + state.data = castDraft(action.payload) + state.status = 'finished' + }), + ...reducers(create), + }), + }) + } + + const wrappedSlice = createGenericSlice({ + name: 'test', + initialState: { status: 'loading' } as GenericState, + reducers: (create) => ({ + magic: create.reducer((state) => { + expectTypeOf(state).toEqualTypeOf>() + + expectTypeOf(state).not.toMatchTypeOf>() + + state.status = 'finished' + state.data = 'hocus pocus' + }), + }), + }) + + expectTypeOf(wrappedSlice.actions.success).toMatchTypeOf< + ActionCreatorWithPayload + >() + + expectTypeOf(wrappedSlice.actions.magic).toMatchTypeOf< + ActionCreatorWithoutPayload + >() + }) + + test('selectSlice', () => { + expectTypeOf(counterSlice.selectSlice({ counter: 0 })).toBeNumber() + + // We use `not.toEqualTypeOf` instead of `not.toMatchTypeOf` + // because `toMatchTypeOf` allows missing properties + expectTypeOf(counterSlice.selectSlice).parameter(0).not.toEqualTypeOf<{}>() + }) + + test('buildCreateSlice', () => { + expectTypeOf(buildCreateSlice()).toEqualTypeOf(createSlice) + + buildCreateSlice({ + // @ts-expect-error not possible to recreate shape because symbol is not exported + creators: { asyncThunk: { [Symbol()]: createAsyncThunk } }, + }) + buildCreateSlice({ creators: { asyncThunk: asyncThunkCreator } }) + }) +}) diff --git a/packages/toolkit/src/tests/createSlice.test.ts b/packages/toolkit/src/tests/createSlice.test.ts index 4856582c1e..3f6bdc5d90 100644 --- a/packages/toolkit/src/tests/createSlice.test.ts +++ b/packages/toolkit/src/tests/createSlice.test.ts @@ -1,17 +1,16 @@ -import { vi } from 'vitest' import type { PayloadAction, WithSlice } from '@reduxjs/toolkit' import { asyncThunkCreator, buildCreateSlice, - configureStore, combineSlices, - createSlice, + configureStore, createAction, + createSlice, } from '@reduxjs/toolkit' import { - mockConsole, createConsole, getLog, + mockConsole, } from 'console-testing-library/pure' type CreateSlice = typeof createSlice @@ -34,7 +33,7 @@ describe('createSlice', () => { state * action.payload, }, initialState: 0, - }) + }), ).toThrowError() }) }) @@ -50,12 +49,18 @@ describe('createSlice', () => { state * action.payload, }, initialState: 0, - }) + }), ).toThrowError() }) }) describe('when initial state is undefined', () => { + beforeEach(() => { + vi.stubEnv('NODE_ENV', 'development') + + return vi.unstubAllEnvs + }) + it('should throw an error', () => { createSlice({ name: 'test', @@ -64,7 +69,7 @@ describe('createSlice', () => { }) expect(getLog().log).toBe( - 'You must provide an `initialState` value that is not `undefined`. You may have misspelled `initialState`' + 'You must provide an `initialState` value that is not `undefined`. You may have misspelled `initialState`', ) }) }) @@ -116,7 +121,7 @@ describe('createSlice', () => { name: 'params', initialState: new URLSearchParams(), reducers: {}, - }) + }), ).not.toThrowError() }) }) @@ -157,7 +162,7 @@ describe('createSlice', () => { name: 'params', initialState: () => new URLSearchParams(), reducers: {}, - }) + }), ).not.toThrowError() }) }) @@ -194,7 +199,7 @@ describe('createSlice', () => { extraReducers: (builder) => { builder.addCase( addMore, - (state, action) => state + action.payload.amount + (state, action) => state + action.payload.amount, ) }, @@ -218,7 +223,7 @@ describe('createSlice', () => { extraReducers: (builder) => builder.addCase( increment, - (state, action) => state + action.payload + (state, action) => state + action.payload, ), }) expect(slice.reducer(0, increment(5))).toBe(5) @@ -233,7 +238,7 @@ describe('createSlice', () => { builder.addCase( 'increment', (state, action: { type: 'increment'; payload: number }) => - state + action.payload + state + action.payload, ), }) expect(slice.reducer(0, increment(5))).toBe(5) @@ -252,7 +257,7 @@ describe('createSlice', () => { }) slice.reducer(undefined, { type: 'unrelated' }) }).toThrowErrorMatchingInlineSnapshot( - `[Error: \`builder.addCase\` cannot be called with two reducers for the same action type 'increment']` + `[Error: \`builder.addCase\` cannot be called with two reducers for the same action type 'increment']`, ) }) @@ -265,7 +270,7 @@ describe('createSlice', () => { builder.addMatcher( increment.match, (state, action: { type: 'increment'; payload: number }) => - state + action.payload + state + action.payload, ), }) expect(slice.reducer(0, increment(5))).toBe(5) @@ -279,7 +284,7 @@ describe('createSlice', () => { extraReducers: (builder) => builder.addDefaultCase( (state, action) => - state + (action as PayloadAction).payload + state + (action as PayloadAction).payload, ), }) expect(slice.reducer(0, increment(5))).toBe(5) @@ -328,7 +333,7 @@ describe('createSlice', () => { testSlice.reducer(0, testSlice.actions.testReducer('testPayload')) expect(reducer).toHaveBeenCalledWith( 0, - expect.objectContaining({ payload: 'testPayload' }) + expect.objectContaining({ payload: 'testPayload' }), ) }) }) @@ -366,23 +371,23 @@ describe('createSlice', () => { }) expect(first.reducer(undefined, { type: 'unrelated' })).toBe( - 'firstInitial' + 'firstInitial', ) expect(first.reducer(undefined, first.actions.something())).toBe( - 'firstSomething' + 'firstSomething', ) expect(first.reducer(undefined, second.actions.other())).toBe( - 'firstOther' + 'firstOther', ) expect(second.reducer(undefined, { type: 'unrelated' })).toBe( - 'secondInitial' + 'secondInitial', ) expect(second.reducer(undefined, first.actions.something())).toBe( - 'secondSomething' + 'secondSomething', ) expect(second.reducer(undefined, second.actions.other())).toBe( - 'secondOther' + 'secondOther', ) }) }) @@ -420,7 +425,7 @@ describe('createSlice', () => { } expect(wrapper).toThrowError( - /The object notation for `createSlice.extraReducers` has been removed/ + /The object notation for `createSlice.extraReducers` has been removed/, ) dummySlice = (createSlice as CreateSlice)({ @@ -433,16 +438,17 @@ describe('createSlice', () => { }, }) expect(wrapper).toThrowError( - /The object notation for `createSlice.extraReducers` has been removed/ + /The object notation for `createSlice.extraReducers` has been removed/, ) }) // TODO Determine final production behavior here - it.skip('Crashes in production', () => { - process.env.NODE_ENV = 'production' + it.todo('Crashes in production', () => { + vi.stubEnv('NODE_ENV', 'production') + const { createSlice } = require('../createSlice') - let dummySlice = (createSlice as CreateSlice)({ + const dummySlice = (createSlice as CreateSlice)({ name: 'dummy', initialState: [], reducers: {}, @@ -450,13 +456,15 @@ describe('createSlice', () => { extraReducers: {}, }) const wrapper = () => { - let reducer = dummySlice.reducer + const { reducer } = dummySlice reducer(undefined, { type: 'dummy' }) } expect(wrapper).toThrowError( - /The object notation for `createSlice.extraReducers` has been removed/ + /The object notation for `createSlice.extraReducers` has been removed/, ) + + vi.unstubAllEnvs() }) }) describe('slice selectors', () => { @@ -468,7 +476,7 @@ describe('createSlice', () => { selectSlice: (state) => state, selectMultiple: Object.assign( (state: number, multiplier: number) => state * multiplier, - { test: 0 } + { test: 0 }, ), }, }) @@ -485,7 +493,7 @@ describe('createSlice', () => { number: slice.getInitialState(), } const { selectSlice, selectMultiple } = slice.getSelectors( - (state: typeof customState) => state.number + (state: typeof customState) => state.number, ) expect(selectSlice(customState)).toBe(slice.getInitialState()) expect(selectMultiple(customState, 2)).toBe(slice.getInitialState() * 2) @@ -493,6 +501,16 @@ describe('createSlice', () => { it('allows accessing properties on the selector', () => { expect(slice.selectors.selectMultiple.unwrapped.test).toBe(0) }) + it('has selectSlice attached to slice, which can go without this', () => { + const slice = createSlice({ + name: 'counter', + initialState: 42, + reducers: {}, + }) + const { selectSlice } = slice + expect(() => selectSlice({ counter: 42 })).not.toThrow() + expect(selectSlice({ counter: 42 })).toBe(42) + }) }) describe('slice injections', () => { it('uses injectInto to inject slice into combined reducer', () => { @@ -521,13 +539,22 @@ describe('createSlice', () => { // selector returns initial state if undefined in real state expect(injectedSlice.selectSlice(uninjectedState)).toBe( - slice.getInitialState() + slice.getInitialState(), + ) + expect(injectedSlice.selectors.selectMultiple({}, 1)).toBe( + slice.getInitialState(), + ) + expect(injectedSlice.getSelectors().selectMultiple(undefined, 1)).toBe( + slice.getInitialState(), ) const injectedState = combinedReducer(undefined, increment()) expect(injectedSlice.selectSlice(injectedState)).toBe( - slice.getInitialState() + 1 + slice.getInitialState() + 1, + ) + expect(injectedSlice.selectors.selectMultiple(injectedState, 1)).toBe( + slice.getInitialState() + 1, ) }) it('allows providing a custom name to inject under', () => { @@ -558,10 +585,10 @@ describe('createSlice', () => { const injectedState = combinedReducer(undefined, increment()) expect(injected.selectSlice(injectedState)).toBe( - slice.getInitialState() + 1 + slice.getInitialState() + 1, ) expect(injected.selectors.selectMultiple(injectedState, 2)).toBe( - (slice.getInitialState() + 1) * 2 + (slice.getInitialState() + 1) * 2, ) const injected2 = slice.injectInto(combinedReducer, { @@ -571,11 +598,50 @@ describe('createSlice', () => { const injected2State = combinedReducer(undefined, increment()) expect(injected2.selectSlice(injected2State)).toBe( - slice.getInitialState() + 1 + slice.getInitialState() + 1, ) expect(injected2.selectors.selectMultiple(injected2State, 2)).toBe( - (slice.getInitialState() + 1) * 2 + (slice.getInitialState() + 1) * 2, + ) + }) + it('avoids incorrectly caching selectors', () => { + const slice = createSlice({ + name: 'counter', + reducerPath: 'injected', + initialState: 42, + reducers: { + increment: (state) => ++state, + }, + selectors: { + selectMultiple: (state, multiplier: number) => state * multiplier, + }, + }) + expect(slice.getSelectors()).toBe(slice.getSelectors()) + const combinedReducer = combineSlices({ + static: slice.reducer, + }).withLazyLoadedSlices>() + + const injected = slice.injectInto(combinedReducer) + + expect(injected.getSelectors()).not.toBe(slice.getSelectors()) + + expect(injected.getSelectors().selectMultiple(undefined, 1)).toBe(42) + + expect(() => + // @ts-expect-error + slice.getSelectors().selectMultiple(undefined, 1), + ).toThrowErrorMatchingInlineSnapshot( + `[Error: selectState returned undefined for an uninjected slice reducer]`, ) + + const injected2 = slice.injectInto(combinedReducer, { + reducerPath: 'other', + }) + + // can use same cache for localised selectors + expect(injected.getSelectors()).toBe(injected2.getSelectors()) + // these should be different + expect(injected.selectors).not.toBe(injected2.selectors) }) }) describe('reducers definition with asyncThunks', () => { @@ -585,9 +651,9 @@ describe('createSlice', () => { name: 'test', initialState: [] as any[], reducers: (create) => ({ thunk: create.asyncThunk(() => {}) }), - }) + }), ).toThrowErrorMatchingInlineSnapshot( - `[Error: Cannot use \`create.asyncThunk\` in the built-in \`createSlice\`. Use \`buildCreateSlice({ creators: { asyncThunk: asyncThunkCreator } })\` to create a customised version of \`createSlice\`.]` + `[Error: Cannot use \`create.asyncThunk\` in the built-in \`createSlice\`. Use \`buildCreateSlice({ creators: { asyncThunk: asyncThunkCreator } })\` to create a customised version of \`createSlice\`.]`, ) }) const createAppSlice = buildCreateSlice({ @@ -615,7 +681,7 @@ describe('createSlice', () => { function payloadCreator(arg, api) { return Promise.resolve('resolved payload') }, - { pending, fulfilled, rejected, settled } + { pending, fulfilled, rejected, settled }, ), }), }) @@ -659,7 +725,7 @@ describe('createSlice', () => { function payloadCreator(arg, api): any { throw new Error('') }, - { pending, fulfilled, rejected, settled } + { pending, fulfilled, rejected, settled }, ), }), }) @@ -713,7 +779,7 @@ describe('createSlice', () => { fulfilled, rejected, settled, - } + }, ), }), }) @@ -751,7 +817,7 @@ describe('createSlice', () => { function payloadCreator(arg, api) { return Promise.resolve('resolved payload') }, - { pending, fulfilled, settled } + { pending, fulfilled, settled }, ), }), }) @@ -767,9 +833,9 @@ describe('createSlice', () => { slice.actions.thunkReducers.rejected( new Error('test'), 'fakeRequestId', - {} - ) - ) + {}, + ), + ), ).not.toThrow() }) @@ -786,13 +852,16 @@ describe('createSlice', () => { }), (state, action) => { state.push(action) - } + }, ), }), }) expect( - slice.reducer([], slice.actions.prepared('test', 1, { message: 'err' })) + slice.reducer( + [], + slice.actions.prepared('test', 1, { message: 'err' }), + ), ).toMatchInlineSnapshot(` [ { @@ -824,9 +893,9 @@ describe('createSlice', () => { }, }, }), - }) + }), ).toThrowErrorMatchingInlineSnapshot( - `[Error: Please use the \`create.preparedReducer\` notation for prepared action creators with the \`create\` notation.]` + `[Error: Please use the \`create.preparedReducer\` notation for prepared action creators with the \`create\` notation.]`, ) }) }) diff --git a/packages/toolkit/src/tests/createSlice.typetest.ts b/packages/toolkit/src/tests/createSlice.typetest.ts deleted file mode 100644 index 24c450f6ae..0000000000 --- a/packages/toolkit/src/tests/createSlice.typetest.ts +++ /dev/null @@ -1,875 +0,0 @@ -import type { Action, UnknownAction, Reducer } from 'redux' -import type { - ActionCreatorWithNonInferrablePayload, - ActionCreatorWithOptionalPayload, - ActionCreatorWithoutPayload, - ActionCreatorWithPayload, - ActionCreatorWithPreparedPayload, - ActionReducerMapBuilder, - AsyncThunk, - CaseReducer, - PayloadAction, - PayloadActionCreator, - ReducerCreators, - SerializedError, - SliceCaseReducers, - ThunkDispatch, - ValidateSliceCaseReducers, -} from '@reduxjs/toolkit' -import { - configureStore, - isRejected, - createAction, - createSlice, - buildCreateSlice, - asyncThunkCreator, - createAsyncThunk, -} from '@reduxjs/toolkit' -import { expectExactType, expectType, expectUnknown } from './helpers' -import { castDraft } from 'immer' - -/* - * Test: Slice name is strongly typed. - */ - -const counterSlice = createSlice({ - name: 'counter', - initialState: 0, - reducers: { - increment: (state: number, action) => state + action.payload, - decrement: (state: number, action) => state - action.payload, - }, -}) - -const uiSlice = createSlice({ - name: 'ui', - initialState: 0, - reducers: { - goToNext: (state: number, action) => state + action.payload, - goToPrevious: (state: number, action) => state - action.payload, - }, -}) - -const actionCreators = { - [counterSlice.name]: { ...counterSlice.actions }, - [uiSlice.name]: { ...uiSlice.actions }, -} - -expectType(actionCreators.counter) -expectType(actionCreators.ui) - -// @ts-expect-error -const value = actionCreators.anyKey - -/* - * Test: createSlice() infers the returned slice's type. - */ -{ - const firstAction = createAction<{ count: number }>('FIRST_ACTION') - - const slice = createSlice({ - name: 'counter', - initialState: 0, - reducers: { - increment: (state: number, action) => state + action.payload, - decrement: (state: number, action) => state - action.payload, - }, - extraReducers: (builder) => { - builder.addCase( - firstAction, - (state, action) => state + action.payload.count - ) - }, - }) - - /* Reducer */ - - expectType>(slice.reducer) - - // @ts-expect-error - expectType>(slice.reducer) - // @ts-expect-error - expectType>(slice.reducer) - /* Actions */ - - slice.actions.increment(1) - slice.actions.decrement(1) - - // @ts-expect-error - slice.actions.other(1) -} - -/* - * Test: Slice action creator types are inferred. - */ -{ - const counter = createSlice({ - name: 'counter', - initialState: 0, - reducers: { - increment: (state) => state + 1, - decrement: (state, { payload = 1 }: PayloadAction) => - state - payload, - multiply: (state, { payload }: PayloadAction) => - Array.isArray(payload) - ? payload.reduce((acc, val) => acc * val, state) - : state * payload, - addTwo: { - reducer: (s, { payload }: PayloadAction) => s + payload, - prepare: (a: number, b: number) => ({ - payload: a + b, - }), - }, - }, - }) - - expectType(counter.actions.increment) - counter.actions.increment() - - expectType>( - counter.actions.decrement - ) - counter.actions.decrement() - counter.actions.decrement(2) - - expectType>( - counter.actions.multiply - ) - counter.actions.multiply(2) - counter.actions.multiply([2, 3, 4]) - - expectType>( - counter.actions.addTwo - ) - counter.actions.addTwo(1, 2) - - // @ts-expect-error - counter.actions.multiply() - - // @ts-expect-error - counter.actions.multiply('2') - - // @ts-expect-error - counter.actions.addTwo(1) -} - -/* - * Test: Slice action creator types properties are "string" - */ -{ - const counter = createSlice({ - name: 'counter', - initialState: 0, - reducers: { - increment: (state) => state + 1, - decrement: (state) => state - 1, - multiply: (state, { payload }: PayloadAction) => - Array.isArray(payload) - ? payload.reduce((acc, val) => acc * val, state) - : state * payload, - }, - }) - - const s: 'counter/increment' = counter.actions.increment.type - const sa: 'counter/increment' = counter.actions.increment().type - const t: 'counter/decrement' = counter.actions.decrement.type - const ta: 'counter/decrement' = counter.actions.decrement().type - const u: 'counter/multiply' = counter.actions.multiply.type - const ua: 'counter/multiply' = counter.actions.multiply(1).type - - // @ts-expect-error - const y: 'increment' = counter.actions.increment.type -} - -/* - * Test: Slice action creator types are inferred for enhanced reducers. - */ -{ - const counter = createSlice({ - name: 'test', - initialState: { counter: 0, concat: '' }, - reducers: { - incrementByStrLen: { - reducer: (state, action: PayloadAction) => { - state.counter += action.payload - }, - prepare: (payload: string) => ({ - payload: payload.length, - }), - }, - concatMetaStrLen: { - reducer: (state, action: PayloadAction) => { - state.concat += action.payload - }, - prepare: (payload: string) => ({ - payload, - meta: payload.length, - }), - }, - }, - }) - - expectType<'test/incrementByStrLen'>( - counter.actions.incrementByStrLen('test').type - ) - expectType(counter.actions.incrementByStrLen('test').payload) - expectType(counter.actions.concatMetaStrLen('test').payload) - expectType(counter.actions.concatMetaStrLen('test').meta) - - // @ts-expect-error - expectType(counter.actions.incrementByStrLen('test').payload) - - // @ts-expect-error - expectType(counter.actions.concatMetaStrLen('test').meta) -} - -/** - * Test: access meta and error from reducer - */ -{ - const counter = createSlice({ - name: 'test', - initialState: { counter: 0, concat: '' }, - reducers: { - // case: meta and error not used in reducer - testDefaultMetaAndError: { - reducer(_, action: PayloadAction) {}, - prepare: (payload: number) => ({ - payload, - meta: 'meta' as 'meta', - error: 'error' as 'error', - }), - }, - // case: meta and error marked as "unknown" in reducer - testUnknownMetaAndError: { - reducer(_, action: PayloadAction) {}, - prepare: (payload: number) => ({ - payload, - meta: 'meta' as 'meta', - error: 'error' as 'error', - }), - }, - // case: meta and error are typed in the reducer as returned by prepare - testMetaAndError: { - reducer(_, action: PayloadAction) {}, - prepare: (payload: number) => ({ - payload, - meta: 'meta' as 'meta', - error: 'error' as 'error', - }), - }, - // case: meta is typed differently in the reducer than returned from prepare - testErroneousMeta: { - reducer(_, action: PayloadAction) {}, - // @ts-expect-error - prepare: (payload: number) => ({ - payload, - meta: 1, - error: 'error' as 'error', - }), - }, - // case: error is typed differently in the reducer than returned from prepare - testErroneousError: { - reducer(_, action: PayloadAction) {}, - // @ts-expect-error - prepare: (payload: number) => ({ - payload, - meta: 'meta' as 'meta', - error: 1, - }), - }, - }, - }) -} - -/* - * Test: returned case reducer has the correct type - */ -{ - const counter = createSlice({ - name: 'counter', - initialState: 0, - reducers: { - increment(state, action: PayloadAction) { - return state + action.payload - }, - decrement: { - reducer(state, action: PayloadAction) { - return state - action.payload - }, - prepare(amount: number) { - return { payload: amount } - }, - }, - }, - }) - - // Should match positively - expectType<(state: number, action: PayloadAction) => number | void>( - counter.caseReducers.increment - ) - - // Should match positively for reducers with prepare callback - expectType<(state: number, action: PayloadAction) => number | void>( - counter.caseReducers.decrement - ) - - // Should not mismatch the payload if it's a simple reducer - - expectType<(state: number, action: PayloadAction) => number | void>( - // @ts-expect-error - counter.caseReducers.increment - ) - - // Should not mismatch the payload if it's a reducer with a prepare callback - - expectType<(state: number, action: PayloadAction) => number | void>( - // @ts-expect-error - counter.caseReducers.decrement - ) - - // Should not include entries that don't exist - - expectType<(state: number, action: PayloadAction) => number | void>( - // @ts-expect-error - counter.caseReducers.someThingNonExistant - ) -} - -/* - * Test: prepared payload does not match action payload - should cause an error. - */ -{ - const counter = createSlice({ - name: 'counter', - initialState: { counter: 0 }, - reducers: { - increment: { - reducer(state, action: PayloadAction) { - state.counter += action.payload.length - }, - // @ts-expect-error - prepare(x: string) { - return { - payload: 6, - } - }, - }, - }, - }) -} - -/* - * Test: if no Payload Type is specified, accept any payload - * see https://github.com/reduxjs/redux-toolkit/issues/165 - */ -{ - const initialState = { - name: null, - } - - const mySlice = createSlice({ - name: 'name', - initialState, - reducers: { - setName: (state, action) => { - state.name = action.payload - }, - }, - }) - - expectType(mySlice.actions.setName) - - const x = mySlice.actions.setName - - mySlice.actions.setName(null) - mySlice.actions.setName('asd') - mySlice.actions.setName(5) -} - -/** - * Test: actions.x.match() - */ -{ - const mySlice = createSlice({ - name: 'name', - initialState: { name: 'test' }, - reducers: { - setName: (state, action: PayloadAction) => { - state.name = action.payload - }, - }, - }) - - const x: Action = {} as any - if (mySlice.actions.setName.match(x)) { - expectType<'name/setName'>(x.type) - expectType(x.payload) - } else { - // @ts-expect-error - expectType<'name/setName'>(x.type) - // @ts-expect-error - expectType(x.payload) - } -} - -/** Test: builder callback for extraReducers */ -{ - createSlice({ - name: 'test', - initialState: 0, - reducers: {}, - extraReducers: (builder) => { - expectType>(builder) - }, - }) -} - -/** Test: wrapping createSlice should be possible */ -{ - interface GenericState { - data?: T - status: 'loading' | 'finished' | 'error' - } - - const createGenericSlice = < - T, - Reducers extends SliceCaseReducers> - >({ - name = '', - initialState, - reducers, - }: { - name: string - initialState: GenericState - reducers: ValidateSliceCaseReducers, Reducers> - }) => { - return createSlice({ - name, - initialState, - reducers: { - start(state) { - state.status = 'loading' - }, - success(state: GenericState, action: PayloadAction) { - state.data = action.payload - state.status = 'finished' - }, - ...reducers, - }, - }) - } - - const wrappedSlice = createGenericSlice({ - name: 'test', - initialState: { status: 'loading' } as GenericState, - reducers: { - magic(state) { - expectType>(state) - // @ts-expect-error - expectType>(state) - - state.status = 'finished' - state.data = 'hocus pocus' - }, - }, - }) - - expectType>(wrappedSlice.actions.success) - expectType>(wrappedSlice.actions.magic) -} - -{ - interface GenericState { - data: T | null - } - - function createDataSlice< - T, - Reducers extends SliceCaseReducers> - >( - name: string, - reducers: ValidateSliceCaseReducers, Reducers>, - initialState: GenericState - ) { - const doNothing = createAction('doNothing') - const setData = createAction('setData') - - const slice = createSlice({ - name, - initialState, - reducers, - extraReducers: (builder) => { - builder.addCase(doNothing, (state) => { - return { ...state } - }) - builder.addCase(setData, (state, { payload }) => { - return { - ...state, - data: payload, - } - }) - }, - }) - return { doNothing, setData, slice } - } -} - -/** - * Test: slice selectors - */ - -{ - const sliceWithoutSelectors = createSlice({ - name: '', - initialState: '', - reducers: {}, - }) - - // @ts-expect-error - sliceWithoutSelectors.selectors.foo - - const sliceWithSelectors = createSlice({ - name: 'counter', - initialState: { value: 0 }, - reducers: { - increment: (state) => { - state.value += 1 - }, - }, - selectors: { - selectValue: (state) => state.value, - selectMultiply: (state, multiplier: number) => state.value * multiplier, - selectToFixed: Object.assign( - (state: { value: number }) => state.value.toFixed(2), - { static: true } - ), - }, - }) - - const rootState = { - [sliceWithSelectors.reducerPath]: sliceWithSelectors.getInitialState(), - } - - const { selectValue, selectMultiply, selectToFixed } = - sliceWithSelectors.selectors - - expectType(selectValue(rootState)) - expectType(selectMultiply(rootState, 2)) - expectType(selectToFixed(rootState)) - - expectType(selectToFixed.unwrapped.static) - - const nestedState = { - nested: rootState, - } - - const nestedSelectors = sliceWithSelectors.getSelectors( - (rootState: typeof nestedState) => rootState.nested.counter - ) - - expectType(nestedSelectors.selectValue(nestedState)) - expectType(nestedSelectors.selectMultiply(nestedState, 2)) - expectType(nestedSelectors.selectToFixed(nestedState)) -} - -/** - * Test: reducer callback - */ - -{ - interface TestState { - foo: string - } - - interface TestArg { - test: string - } - - interface TestReturned { - payload: string - } - - interface TestReject { - cause: string - } - - const slice = createSlice({ - name: 'test', - initialState: {} as TestState, - reducers: (create) => { - const pretypedAsyncThunk = - create.asyncThunk.withTypes<{ rejectValue: TestReject }>() - - // @ts-expect-error - create.asyncThunk(() => {}) - - // @ts-expect-error - create.asyncThunk.withTypes<{ - rejectValue: string - dispatch: StoreDispatch - }>() - - return { - normalReducer: create.reducer((state, action) => { - expectType(state) - expectType(action.payload) - }), - optionalReducer: create.reducer((state, action) => { - expectType(state) - expectType(action.payload) - }), - noActionReducer: create.reducer((state) => { - expectType(state) - }), - preparedReducer: create.preparedReducer( - (payload: string) => ({ - payload, - meta: 'meta' as const, - error: 'error' as const, - }), - (state, action) => { - expectType(state) - expectType(action.payload) - expectExactType('meta' as const)(action.meta) - expectExactType('error' as const)(action.error) - } - ), - testInfer: create.asyncThunk( - function payloadCreator(arg: TestArg, api) { - return Promise.resolve({ payload: 'foo' }) - }, - { - pending(state, action) { - expectType(state) - expectType(action.meta.arg) - }, - fulfilled(state, action) { - expectType(state) - expectType(action.meta.arg) - expectType(action.payload) - }, - rejected(state, action) { - expectType(state) - expectType(action.meta.arg) - expectType(action.error) - }, - settled(state, action) { - expectType(state) - expectType(action.meta.arg) - if (isRejected(action)) { - expectType(action.error) - } else { - expectType(action.payload) - } - }, - } - ), - testExplicitType: create.asyncThunk< - TestReturned, - TestArg, - { - rejectValue: TestReject - } - >( - function payloadCreator(arg, api) { - // here would be a circular reference - expectUnknown(api.getState()) - // here would be a circular reference - expectType>(api.dispatch) - // so you need to cast inside instead - const getState = api.getState as () => StoreState - const dispatch = api.dispatch as StoreDispatch - expectType(arg) - expectType<(value: TestReject) => any>(api.rejectWithValue) - return Promise.resolve({ payload: 'foo' }) - }, - { - pending(state, action) { - expectType(state) - expectType(action.meta.arg) - }, - fulfilled(state, action) { - expectType(state) - expectType(action.meta.arg) - expectType(action.payload) - }, - rejected(state, action) { - expectType(state) - expectType(action.meta.arg) - expectType(action.error) - expectType(action.payload) - }, - settled(state, action) { - expectType(state) - expectType(action.meta.arg) - if (isRejected(action)) { - expectType(action.error) - expectType(action.payload) - } else { - expectType(action.payload) - } - }, - } - ), - testPretyped: pretypedAsyncThunk( - function payloadCreator(arg: TestArg, api) { - expectType<(value: TestReject) => any>(api.rejectWithValue) - return Promise.resolve({ payload: 'foo' }) - }, - { - pending(state, action) { - expectType(state) - expectType(action.meta.arg) - }, - fulfilled(state, action) { - expectType(state) - expectType(action.meta.arg) - expectType(action.payload) - }, - rejected(state, action) { - expectType(state) - expectType(action.meta.arg) - expectType(action.error) - expectType(action.payload) - }, - settled(state, action) { - expectType(state) - expectType(action.meta.arg) - if (isRejected(action)) { - expectType(action.error) - expectType(action.payload) - } else { - expectType(action.payload) - } - }, - } - ), - } - }, - }) - - const store = configureStore({ reducer: { test: slice.reducer } }) - - type StoreState = ReturnType - type StoreDispatch = typeof store.dispatch - - expectType>(slice.actions.normalReducer) - slice.actions.normalReducer('') - // @ts-expect-error - slice.actions.normalReducer() - // @ts-expect-error - slice.actions.normalReducer(0) - expectType>( - slice.actions.optionalReducer - ) - slice.actions.optionalReducer() - slice.actions.optionalReducer('') - // @ts-expect-error - slice.actions.optionalReducer(0) - - expectType(slice.actions.noActionReducer) - slice.actions.noActionReducer() - // @ts-expect-error - slice.actions.noActionReducer('') - expectType< - ActionCreatorWithPreparedPayload< - [string], - string, - 'test/preparedReducer', - 'error', - 'meta' - > - >(slice.actions.preparedReducer) - expectType>(slice.actions.testInfer) - expectType>( - slice.actions.testExplicitType - ) - { - type TestInferThunk = AsyncThunk - expectType>>( - slice.caseReducers.testInfer.pending - ) - expectType>>( - slice.caseReducers.testInfer.fulfilled - ) - expectType>>( - slice.caseReducers.testInfer.rejected - ) - } -} - -/** Test: wrapping createSlice should be possible, with callback */ -{ - interface GenericState { - data?: T - status: 'loading' | 'finished' | 'error' - } - - const createGenericSlice = < - T, - Reducers extends SliceCaseReducers> - >({ - name = '', - initialState, - reducers, - }: { - name: string - initialState: GenericState - reducers: (create: ReducerCreators>) => Reducers - }) => { - return createSlice({ - name, - initialState, - reducers: (create) => ({ - start: create.reducer((state) => { - state.status = 'loading' - }), - success: create.reducer((state, action) => { - state.data = castDraft(action.payload) - state.status = 'finished' - }), - ...reducers(create), - }), - }) - } - - const wrappedSlice = createGenericSlice({ - name: 'test', - initialState: { status: 'loading' } as GenericState, - reducers: (create) => ({ - magic: create.reducer((state) => { - expectType>(state) - // @ts-expect-error - expectType>(state) - - state.status = 'finished' - state.data = 'hocus pocus' - }), - }), - }) - - expectType>(wrappedSlice.actions.success) - expectType>(wrappedSlice.actions.magic) -} - -/** - * Test: selectSlice - */ -{ - expectType(counterSlice.selectSlice({ counter: 0 })) - // @ts-expect-error - counterSlice.selectSlice({}) -} - -/** - * Test: buildCreateSlice - */ -{ - expectExactType(createSlice)(buildCreateSlice()) - buildCreateSlice({ - // @ts-expect-error not possible to recreate shape because symbol is not exported - creators: { asyncThunk: { [Symbol()]: createAsyncThunk } }, - }) - buildCreateSlice({ creators: { asyncThunk: asyncThunkCreator } }) -} diff --git a/packages/toolkit/src/tests/getDefaultEnhancers.test-d.ts b/packages/toolkit/src/tests/getDefaultEnhancers.test-d.ts new file mode 100644 index 0000000000..67d42e99e6 --- /dev/null +++ b/packages/toolkit/src/tests/getDefaultEnhancers.test-d.ts @@ -0,0 +1,143 @@ +import type { StoreEnhancer } from '@reduxjs/toolkit' +import { configureStore } from '@reduxjs/toolkit' + +declare const enhancer1: StoreEnhancer< + { + has1: true + }, + { stateHas1: true } +> + +declare const enhancer2: StoreEnhancer< + { + has2: true + }, + { stateHas2: true } +> + +describe('type tests', () => { + test('prepend single element', () => { + const store = configureStore({ + reducer: () => 0, + enhancers: (gDE) => gDE().prepend(enhancer1), + }) + + expectTypeOf(store.has1).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas1).toEqualTypeOf() + + expectTypeOf(store).not.toHaveProperty('has2') + + expectTypeOf(store.getState()).not.toHaveProperty('stateHas2') + }) + + test('prepend multiple (rest)', () => { + const store = configureStore({ + reducer: () => 0, + enhancers: (gDE) => gDE().prepend(enhancer1, enhancer2), + }) + + expectTypeOf(store.has1).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas1).toEqualTypeOf() + + expectTypeOf(store.has2).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas2).toEqualTypeOf() + + expectTypeOf(store).not.toHaveProperty('has3') + + expectTypeOf(store.getState()).not.toHaveProperty('stateHas3') + }) + + test('prepend multiple (array notation)', () => { + const store = configureStore({ + reducer: () => 0, + enhancers: (gDE) => gDE().prepend([enhancer1, enhancer2] as const), + }) + + expectTypeOf(store.has1).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas1).toEqualTypeOf() + + expectTypeOf(store.has2).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas2).toEqualTypeOf() + + expectTypeOf(store).not.toHaveProperty('has3') + + expectTypeOf(store.getState()).not.toHaveProperty('stateHas3') + }) + + test('concat single element', () => { + const store = configureStore({ + reducer: () => 0, + enhancers: (gDE) => gDE().concat(enhancer1), + }) + + expectTypeOf(store.has1).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas1).toEqualTypeOf() + + expectTypeOf(store).not.toHaveProperty('has2') + + expectTypeOf(store.getState()).not.toHaveProperty('stateHas2') + }) + + test('prepend multiple (rest)', () => { + const store = configureStore({ + reducer: () => 0, + enhancers: (gDE) => gDE().concat(enhancer1, enhancer2), + }) + + expectTypeOf(store.has1).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas1).toEqualTypeOf() + + expectTypeOf(store.has2).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas2).toEqualTypeOf() + + expectTypeOf(store).not.toHaveProperty('has3') + + expectTypeOf(store.getState()).not.toHaveProperty('stateHas3') + }) + + test('concat multiple (array notation)', () => { + const store = configureStore({ + reducer: () => 0, + enhancers: (gDE) => gDE().concat([enhancer1, enhancer2] as const), + }) + + expectTypeOf(store.has1).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas1).toEqualTypeOf() + + expectTypeOf(store.has2).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas2).toEqualTypeOf() + + expectTypeOf(store).not.toHaveProperty('has3') + + expectTypeOf(store.getState()).not.toHaveProperty('stateHas3') + }) + + test('concat and prepend', () => { + const store = configureStore({ + reducer: () => 0, + enhancers: (gDE) => gDE().concat(enhancer1).prepend(enhancer2), + }) + + expectTypeOf(store.has1).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas1).toEqualTypeOf() + + expectTypeOf(store.has2).toEqualTypeOf() + + expectTypeOf(store.getState().stateHas2).toEqualTypeOf() + + expectTypeOf(store).not.toHaveProperty('has3') + + expectTypeOf(store.getState()).not.toHaveProperty('stateHas3') + }) +}) diff --git a/packages/toolkit/src/tests/getDefaultEnhancers.typetest.ts b/packages/toolkit/src/tests/getDefaultEnhancers.typetest.ts deleted file mode 100644 index 7ea38237cc..0000000000 --- a/packages/toolkit/src/tests/getDefaultEnhancers.typetest.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { configureStore } from '@reduxjs/toolkit' -import type { StoreEnhancer } from 'redux' - -declare const expectType: (t: T) => T - -declare const enhancer1: StoreEnhancer< - { - has1: true - }, - { stateHas1: true } -> - -declare const enhancer2: StoreEnhancer< - { - has2: true - }, - { stateHas2: true } -> - -{ - // prepend single element - { - const store = configureStore({ - reducer: () => 0, - enhancers: (gDE) => gDE().prepend(enhancer1), - }) - expectType(store.has1) - expectType(store.getState().stateHas1) - - // @ts-expect-error - expectType(store.has2) - // @ts-expect-error - expectType(store.getState().stateHas2) - } - - // prepend multiple (rest) - { - const store = configureStore({ - reducer: () => 0, - enhancers: (gDE) => gDE().prepend(enhancer1, enhancer2), - }) - expectType(store.has1) - expectType(store.getState().stateHas1) - expectType(store.has2) - expectType(store.getState().stateHas2) - - // @ts-expect-error - expectType(store.has3) - // @ts-expect-error - expectType(store.getState().stateHas3) - } - - // prepend multiple (array notation) - { - const store = configureStore({ - reducer: () => 0, - enhancers: (gDE) => gDE().prepend([enhancer1, enhancer2] as const), - }) - expectType(store.has1) - expectType(store.getState().stateHas1) - expectType(store.has2) - expectType(store.getState().stateHas2) - - // @ts-expect-error - expectType(store.has3) - // @ts-expect-error - expectType(store.getState().stateHas3) - } - - // concat single element - { - const store = configureStore({ - reducer: () => 0, - enhancers: (gDE) => gDE().concat(enhancer1), - }) - expectType(store.has1) - expectType(store.getState().stateHas1) - - // @ts-expect-error - expectType(store.has2) - // @ts-expect-error - expectType(store.getState().stateHas2) - } - - // prepend multiple (rest) - { - const store = configureStore({ - reducer: () => 0, - enhancers: (gDE) => gDE().concat(enhancer1, enhancer2), - }) - expectType(store.has1) - expectType(store.getState().stateHas1) - expectType(store.has2) - expectType(store.getState().stateHas2) - - // @ts-expect-error - expectType(store.has3) - // @ts-expect-error - expectType(store.getState().stateHas3) - } - - // concat multiple (array notation) - { - const store = configureStore({ - reducer: () => 0, - enhancers: (gDE) => gDE().concat([enhancer1, enhancer2] as const), - }) - expectType(store.has1) - expectType(store.getState().stateHas1) - expectType(store.has2) - expectType(store.getState().stateHas2) - - // @ts-expect-error - expectType(store.has3) - // @ts-expect-error - expectType(store.getState().stateHas3) - } - - // concat and prepend - { - const store = configureStore({ - reducer: () => 0, - enhancers: (gDE) => gDE().concat(enhancer1).prepend(enhancer2), - }) - expectType(store.has1) - expectType(store.getState().stateHas1) - expectType(store.has2) - expectType(store.getState().stateHas2) - - // @ts-expect-error - expectType(store.has3) - // @ts-expect-error - expectType(store.getState().stateHas3) - } -} diff --git a/packages/toolkit/src/tests/getDefaultMiddleware.test-d.ts b/packages/toolkit/src/tests/getDefaultMiddleware.test-d.ts new file mode 100644 index 0000000000..50680a09ce --- /dev/null +++ b/packages/toolkit/src/tests/getDefaultMiddleware.test-d.ts @@ -0,0 +1,199 @@ +import { buildGetDefaultMiddleware } from '@internal/getDefaultMiddleware' +import type { + Action, + Dispatch, + Middleware, + ThunkAction, + ThunkDispatch, + ThunkMiddleware, + Tuple, + UnknownAction, +} from '@reduxjs/toolkit' +import { configureStore } from '@reduxjs/toolkit' + +declare const middleware1: Middleware<{ + (_: string): number +}> + +declare const middleware2: Middleware<{ + (_: number): string +}> + +type ThunkReturn = Promise<'thunk'> +declare const thunkCreator: () => () => ThunkReturn + +const getDefaultMiddleware = buildGetDefaultMiddleware() + +describe('type tests', () => { + test('prepend single element', () => { + const store = configureStore({ + reducer: () => 0, + middleware: (gDM) => gDM().prepend(middleware1), + }) + + expectTypeOf(store.dispatch('foo')).toBeNumber() + + expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf() + + expectTypeOf(store.dispatch('foo')).not.toBeString() + }) + + test('prepend multiple (rest)', () => { + const store = configureStore({ + reducer: () => 0, + middleware: (gDM) => gDM().prepend(middleware1, middleware2), + }) + + expectTypeOf(store.dispatch('foo')).toBeNumber() + + expectTypeOf(store.dispatch(5)).toBeString() + + expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf() + + expectTypeOf(store.dispatch('foo')).not.toBeString() + }) + + test('prepend multiple (array notation)', () => { + const store = configureStore({ + reducer: () => 0, + middleware: (gDM) => gDM().prepend([middleware1, middleware2] as const), + }) + + expectTypeOf(store.dispatch('foo')).toBeNumber() + + expectTypeOf(store.dispatch(5)).toBeString() + + expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf() + + expectTypeOf(store.dispatch('foo')).not.toBeString() + }) + + test('concat single element', () => { + const store = configureStore({ + reducer: () => 0, + middleware: (gDM) => gDM().concat(middleware1), + }) + + expectTypeOf(store.dispatch('foo')).toBeNumber() + + expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf() + + expectTypeOf(store.dispatch('foo')).not.toBeString() + }) + + test('prepend multiple (rest)', () => { + const store = configureStore({ + reducer: () => 0, + middleware: (gDM) => gDM().concat(middleware1, middleware2), + }) + + expectTypeOf(store.dispatch('foo')).toBeNumber() + + expectTypeOf(store.dispatch(5)).toBeString() + + expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf() + + expectTypeOf(store.dispatch('foo')).not.toBeString() + }) + + test('concat multiple (array notation)', () => { + const store = configureStore({ + reducer: () => 0, + middleware: (gDM) => gDM().concat([middleware1, middleware2] as const), + }) + + expectTypeOf(store.dispatch('foo')).toBeNumber() + + expectTypeOf(store.dispatch(5)).toBeString() + + expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf() + + expectTypeOf(store.dispatch('foo')).not.toBeString() + }) + + test('concat and prepend', () => { + const store = configureStore({ + reducer: () => 0, + middleware: (gDM) => gDM().concat(middleware1).prepend(middleware2), + }) + + expectTypeOf(store.dispatch('foo')).toBeNumber() + + expectTypeOf(store.dispatch(5)).toBeString() + + expectTypeOf(store.dispatch(thunkCreator())).toEqualTypeOf() + + expectTypeOf(store.dispatch('foo')).not.toBeString() + }) + + test('allows passing options to thunk', () => { + const extraArgument = 42 as const + + const m2 = getDefaultMiddleware({ + thunk: false, + }) + + expectTypeOf(m2).toMatchTypeOf>() + + const dummyMiddleware: Middleware< + { + (action: Action<'actionListenerMiddleware/add'>): () => void + }, + { counter: number } + > = (storeApi) => (next) => (action) => { + return next(action) + } + + const dummyMiddleware2: Middleware<{}, { counter: number }> = + (storeApi) => (next) => (action) => {} + + const testThunk: ThunkAction< + void, + { counter: number }, + number, + UnknownAction + > = (dispatch, getState, extraArg) => { + expect(extraArg).toBe(extraArgument) + } + + const reducer = () => ({ counter: 123 }) + + const store = configureStore({ + reducer, + middleware: (gDM) => { + const middleware = gDM({ + thunk: { extraArgument }, + immutableCheck: false, + serializableCheck: false, + actionCreatorCheck: false, + }) + + const m3 = middleware.concat(dummyMiddleware, dummyMiddleware2) + + expectTypeOf(m3).toMatchTypeOf< + Tuple< + [ + ThunkMiddleware, + Middleware< + (action: Action<'actionListenerMiddleware/add'>) => () => void, + { + counter: number + }, + Dispatch + >, + Middleware<{}, any, Dispatch>, + ] + > + >() + + return m3 + }, + }) + + expectTypeOf(store.dispatch).toMatchTypeOf< + ThunkDispatch & Dispatch + >() + + store.dispatch(testThunk) + }) +}) diff --git a/packages/toolkit/src/tests/getDefaultMiddleware.test.ts b/packages/toolkit/src/tests/getDefaultMiddleware.test.ts index 6ee86933b2..b72a959b0b 100644 --- a/packages/toolkit/src/tests/getDefaultMiddleware.test.ts +++ b/packages/toolkit/src/tests/getDefaultMiddleware.test.ts @@ -1,20 +1,15 @@ -import { vi } from 'vitest' +import { Tuple } from '@internal/utils' import type { - UnknownAction, + Action, Middleware, ThunkAction, - Action, - ThunkDispatch, - Dispatch, + UnknownAction, } from '@reduxjs/toolkit' import { configureStore } from '@reduxjs/toolkit' import { thunk } from 'redux-thunk' -import type { ThunkMiddleware } from 'redux-thunk' - -import { expectType } from './helpers' +import { vi } from 'vitest' import { buildGetDefaultMiddleware } from '@internal/getDefaultMiddleware' -import { Tuple } from '@internal/utils' const getDefaultMiddleware = buildGetDefaultMiddleware() @@ -80,8 +75,6 @@ describe('getDefaultMiddleware', () => { thunk: false, }) - expectType>(m2) - const dummyMiddleware: Middleware< { (action: Action<'actionListenerMiddleware/add'>): () => void @@ -117,30 +110,10 @@ describe('getDefaultMiddleware', () => { const m3 = middleware.concat(dummyMiddleware, dummyMiddleware2) - expectType< - Tuple< - [ - ThunkMiddleware, - Middleware< - (action: Action<'actionListenerMiddleware/add'>) => () => void, - { - counter: number - }, - Dispatch - >, - Middleware<{}, any, Dispatch> - ] - > - >(m3) - return m3 }, }) - expectType & Dispatch>( - store.dispatch - ) - store.dispatch(testThunk) }) diff --git a/packages/toolkit/src/tests/getDefaultMiddleware.typetest.ts b/packages/toolkit/src/tests/getDefaultMiddleware.typetest.ts deleted file mode 100644 index 160f1260c4..0000000000 --- a/packages/toolkit/src/tests/getDefaultMiddleware.typetest.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { configureStore } from '@reduxjs/toolkit' -import type { Middleware } from 'redux' - -declare const expectType: (t: T) => T - -declare const middleware1: Middleware<{ - (_: string): number -}> - -declare const middleware2: Middleware<{ - (_: number): string -}> - -type ThunkReturn = Promise<'thunk'> -declare const thunkCreator: () => () => ThunkReturn - -{ - // prepend single element - { - const store = configureStore({ - reducer: () => 0, - middleware: (gDM) => gDM().prepend(middleware1), - }) - expectType(store.dispatch('foo')) - expectType(store.dispatch(thunkCreator())) - - // @ts-expect-error - expectType(store.dispatch('foo')) - } - - // prepend multiple (rest) - { - const store = configureStore({ - reducer: () => 0, - middleware: (gDM) => gDM().prepend(middleware1, middleware2), - }) - expectType(store.dispatch('foo')) - expectType(store.dispatch(5)) - expectType(store.dispatch(thunkCreator())) - - // @ts-expect-error - expectType(store.dispatch('foo')) - } - - // prepend multiple (array notation) - { - const store = configureStore({ - reducer: () => 0, - middleware: (gDM) => gDM().prepend([middleware1, middleware2] as const), - }) - - expectType(store.dispatch('foo')) - expectType(store.dispatch(5)) - expectType(store.dispatch(thunkCreator())) - - // @ts-expect-error - expectType(store.dispatch('foo')) - } - - // concat single element - { - const store = configureStore({ - reducer: () => 0, - middleware: (gDM) => gDM().concat(middleware1), - }) - - expectType(store.dispatch('foo')) - expectType(store.dispatch(thunkCreator())) - - // @ts-expect-error - expectType(store.dispatch('foo')) - } - - // prepend multiple (rest) - { - const store = configureStore({ - reducer: () => 0, - middleware: (gDM) => gDM().concat(middleware1, middleware2), - }) - - expectType(store.dispatch('foo')) - expectType(store.dispatch(5)) - expectType(store.dispatch(thunkCreator())) - - // @ts-expect-error - expectType(store.dispatch('foo')) - } - - // concat multiple (array notation) - { - const store = configureStore({ - reducer: () => 0, - middleware: (gDM) => gDM().concat([middleware1, middleware2] as const), - }) - - expectType(store.dispatch('foo')) - expectType(store.dispatch(5)) - expectType(store.dispatch(thunkCreator())) - - // @ts-expect-error - expectType(store.dispatch('foo')) - } - - // concat and prepend - { - const store = configureStore({ - reducer: () => 0, - middleware: (gDM) => gDM().concat(middleware1).prepend(middleware2), - }) - - expectType(store.dispatch('foo')) - expectType(store.dispatch(5)) - expectType(store.dispatch(thunkCreator())) - - // @ts-expect-error - expectType(store.dispatch('foo')) - } -} diff --git a/packages/toolkit/src/tests/helpers.ts b/packages/toolkit/src/tests/helpers.ts deleted file mode 100644 index 6146ca1ee0..0000000000 --- a/packages/toolkit/src/tests/helpers.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { IsAny, IsUnknown } from '../../src/tsHelpers' - -export function expectType(t: T): T { - return t -} - -type Equals = IsAny< - T, - never, - IsAny -> -export function expectExactType(t: T) { - return >(u: U) => {} -} - -type EnsureUnknown = IsUnknown -export function expectUnknown>(t: T) { - return t -} - -type EnsureAny = IsAny -export function expectExactAny>(t: T) { - return t -} - -type IsNotAny = IsAny -export function expectNotAny>(t: T): T { - return t -} - -expectType('5' as string) -expectType('5' as const) -expectType('5' as any) -expectExactType('5' as const)('5' as const) -// @ts-expect-error -expectExactType('5' as string)('5' as const) -// @ts-expect-error -expectExactType('5' as any)('5' as const) -expectUnknown('5' as unknown) -// @ts-expect-error -expectUnknown('5' as const) -// @ts-expect-error -expectUnknown('5' as any) -expectExactAny('5' as any) -// @ts-expect-error -expectExactAny('5' as const) -// @ts-expect-error -expectExactAny('5' as unknown) diff --git a/packages/toolkit/src/tests/immutableStateInvariantMiddleware.test.ts b/packages/toolkit/src/tests/immutableStateInvariantMiddleware.test.ts index dec7789032..63679ba0d8 100644 --- a/packages/toolkit/src/tests/immutableStateInvariantMiddleware.test.ts +++ b/packages/toolkit/src/tests/immutableStateInvariantMiddleware.test.ts @@ -151,7 +151,7 @@ describe('createImmutableStateInvariantMiddleware', () => { try { dispatch({ type: 'SOME_ACTION' }) expect(getLog().log).toMatch( - /^ImmutableStateInvariantMiddleware took \d*ms, which is more than the warning threshold of 4ms./ + /^ImmutableStateInvariantMiddleware took \d*ms, which is more than the warning threshold of 4ms./, ) } finally { restore() diff --git a/packages/toolkit/src/tests/mapBuilders.test-d.ts b/packages/toolkit/src/tests/mapBuilders.test-d.ts new file mode 100644 index 0000000000..63aece1c18 --- /dev/null +++ b/packages/toolkit/src/tests/mapBuilders.test-d.ts @@ -0,0 +1,268 @@ +import type { SerializedError } from '@internal/createAsyncThunk' +import { createAsyncThunk } from '@internal/createAsyncThunk' +import { executeReducerBuilderCallback } from '@internal/mapBuilders' +import type { UnknownAction } from '@reduxjs/toolkit' +import { createAction } from '@reduxjs/toolkit' + +describe('type tests', () => { + test('builder callback for actionMap', () => { + const increment = createAction('increment') + + const decrement = createAction('decrement') + + executeReducerBuilderCallback((builder) => { + builder.addCase(increment, (state, action) => { + expectTypeOf(state).toBeNumber() + + expectTypeOf(action).toEqualTypeOf<{ + type: 'increment' + payload: number + }>() + + expectTypeOf(state).not.toBeString() + + expectTypeOf(action).not.toMatchTypeOf<{ + type: 'increment' + payload: string + }>() + + expectTypeOf(action).not.toMatchTypeOf<{ + type: 'decrement' + payload: number + }>() + }) + + builder.addCase('increment', (state, action) => { + expectTypeOf(state).toBeNumber() + + expectTypeOf(action).toEqualTypeOf<{ type: 'increment' }>() + + expectTypeOf(state).not.toBeString() + + expectTypeOf(action).not.toMatchTypeOf<{ type: 'decrement' }>() + + // this cannot be inferred and has to be manually specified + expectTypeOf(action).not.toMatchTypeOf<{ + type: 'increment' + payload: number + }>() + }) + + builder.addCase( + increment, + (state, action: ReturnType) => state, + ) + + // @ts-expect-error + builder.addCase( + increment, + (state, action: ReturnType) => state, + ) + + builder.addCase( + 'increment', + (state, action: ReturnType) => state, + ) + + // @ts-expect-error + builder.addCase( + 'decrement', + (state, action: ReturnType) => state, + ) + + // action type is inferred + builder.addMatcher(increment.match, (state, action) => { + expectTypeOf(action).toEqualTypeOf>() + }) + + test('action type is inferred when type predicate lacks `type` property', () => { + type PredicateWithoutTypeProperty = { + payload: number + } + + builder.addMatcher( + (action): action is PredicateWithoutTypeProperty => true, + (state, action) => { + expectTypeOf(action).toMatchTypeOf() + + expectTypeOf(action).toMatchTypeOf() + }, + ) + }) + + // action type defaults to UnknownAction if no type predicate matcher is passed + builder.addMatcher( + () => true, + (state, action) => { + expectTypeOf(action).toMatchTypeOf() + }, + ) + + // with a boolean checker, action can also be typed by type argument + builder.addMatcher<{ foo: boolean }>( + () => true, + (state, action) => { + expectTypeOf(action).toMatchTypeOf<{ foo: boolean }>() + + expectTypeOf(action).toMatchTypeOf() + }, + ) + + // addCase().addMatcher() is possible, action type inferred correctly + builder + .addCase( + 'increment', + (state, action: ReturnType) => state, + ) + .addMatcher(decrement.match, (state, action) => { + expectTypeOf(action).toEqualTypeOf>() + }) + + // addCase().addDefaultCase() is possible, action type is UnknownAction + builder + .addCase( + 'increment', + (state, action: ReturnType) => state, + ) + .addDefaultCase((state, action) => { + expectTypeOf(action).toMatchTypeOf() + }) + + test('addMatcher() should prevent further calls to addCase()', () => { + const b = builder.addMatcher(increment.match, () => {}) + + expectTypeOf(b).not.toHaveProperty('addCase') + + expectTypeOf(b.addMatcher).toBeCallableWith(increment.match, () => {}) + + expectTypeOf(b.addDefaultCase).toBeCallableWith(() => {}) + }) + + test('addDefaultCase() should prevent further calls to addCase(), addMatcher() and addDefaultCase', () => { + const b = builder.addDefaultCase(() => {}) + + expectTypeOf(b).not.toHaveProperty('addCase') + + expectTypeOf(b).not.toHaveProperty('addMatcher') + + expectTypeOf(b).not.toHaveProperty('addDefaultCase') + }) + + describe('`createAsyncThunk` actions work with `mapBuilder`', () => { + test('case 1: normal `createAsyncThunk`', () => { + const thunk = createAsyncThunk('test', () => { + return 'ret' as const + }) + builder.addCase(thunk.pending, (_, action) => { + expectTypeOf(action).toMatchTypeOf<{ + payload: undefined + meta: { + arg: void + requestId: string + requestStatus: 'pending' + } + }>() + }) + + builder.addCase(thunk.rejected, (_, action) => { + expectTypeOf(action).toMatchTypeOf<{ + payload: unknown + error: SerializedError + meta: { + arg: void + requestId: string + requestStatus: 'rejected' + aborted: boolean + condition: boolean + rejectedWithValue: boolean + } + }>() + }) + builder.addCase(thunk.fulfilled, (_, action) => { + expectTypeOf(action).toMatchTypeOf<{ + payload: 'ret' + meta: { + arg: void + requestId: string + requestStatus: 'fulfilled' + } + }>() + }) + }) + }) + + test('case 2: `createAsyncThunk` with `meta`', () => { + const thunk = createAsyncThunk< + 'ret', + void, + { + pendingMeta: { startedTimeStamp: number } + fulfilledMeta: { + fulfilledTimeStamp: number + baseQueryMeta: 'meta!' + } + rejectedMeta: { + baseQueryMeta: 'meta!' + } + } + >( + 'test', + (_, api) => { + return api.fulfillWithValue('ret' as const, { + fulfilledTimeStamp: 5, + baseQueryMeta: 'meta!', + }) + }, + { + getPendingMeta() { + return { startedTimeStamp: 0 } + }, + }, + ) + + builder.addCase(thunk.pending, (_, action) => { + expectTypeOf(action).toMatchTypeOf<{ + payload: undefined + meta: { + arg: void + requestId: string + requestStatus: 'pending' + startedTimeStamp: number + } + }>() + }) + + builder.addCase(thunk.rejected, (_, action) => { + expectTypeOf(action).toMatchTypeOf<{ + payload: unknown + error: SerializedError + meta: { + arg: void + requestId: string + requestStatus: 'rejected' + aborted: boolean + condition: boolean + rejectedWithValue: boolean + baseQueryMeta?: 'meta!' + } + }>() + + if (action.meta.rejectedWithValue) { + expectTypeOf(action.meta.baseQueryMeta).toEqualTypeOf<'meta!'>() + } + }) + builder.addCase(thunk.fulfilled, (_, action) => { + expectTypeOf(action).toMatchTypeOf<{ + payload: 'ret' + meta: { + arg: void + requestId: string + requestStatus: 'fulfilled' + baseQueryMeta: 'meta!' + } + }>() + }) + }) + }) + }) +}) diff --git a/packages/toolkit/src/tests/mapBuilders.typetest.ts b/packages/toolkit/src/tests/mapBuilders.typetest.ts deleted file mode 100644 index 334572300e..0000000000 --- a/packages/toolkit/src/tests/mapBuilders.typetest.ts +++ /dev/null @@ -1,248 +0,0 @@ -import type { SerializedError } from '@internal/createAsyncThunk' -import { createAsyncThunk } from '@internal/createAsyncThunk' -import { executeReducerBuilderCallback } from '@internal/mapBuilders' -import type { UnknownAction } from '@reduxjs/toolkit' -import { createAction } from '@reduxjs/toolkit' -import { expectExactType, expectType } from './helpers' - -/** Test: builder callback for actionMap */ -{ - const increment = createAction('increment') - const decrement = createAction('decrement') - - executeReducerBuilderCallback((builder) => { - builder.addCase(increment, (state, action) => { - expectType(state) - expectType<{ type: 'increment'; payload: number }>(action) - // @ts-expect-error - expectType(state) - // @ts-expect-error - expectType<{ type: 'increment'; payload: string }>(action) - // @ts-expect-error - expectType<{ type: 'decrement'; payload: number }>(action) - }) - - builder.addCase('increment', (state, action) => { - expectType(state) - expectType<{ type: 'increment' }>(action) - // @ts-expect-error - expectType<{ type: 'decrement' }>(action) - // @ts-expect-error - this cannot be inferred and has to be manually specified - expectType<{ type: 'increment'; payload: number }>(action) - }) - - builder.addCase( - increment, - (state, action: ReturnType) => state - ) - // @ts-expect-error - builder.addCase( - increment, - (state, action: ReturnType) => state - ) - - builder.addCase( - 'increment', - (state, action: ReturnType) => state - ) - // @ts-expect-error - builder.addCase( - 'decrement', - (state, action: ReturnType) => state - ) - - // action type is inferred - builder.addMatcher(increment.match, (state, action) => { - expectType>(action) - }) - - { - // action type is inferred when type predicate lacks `type` property - type PredicateWithoutTypeProperty = { - payload: number - } - - builder.addMatcher( - (action): action is PredicateWithoutTypeProperty => true, - (state, action) => { - expectType(action) - expectType(action) - } - ) - } - - // action type defaults to UnknownAction if no type predicate matcher is passed - builder.addMatcher( - () => true, - (state, action) => { - expectExactType({} as UnknownAction)(action) - } - ) - - // with a boolean checker, action can also be typed by type argument - builder.addMatcher<{ foo: boolean }>( - () => true, - (state, action) => { - expectType<{ foo: boolean }>(action) - expectType(action) - } - ) - - // addCase().addMatcher() is possible, action type inferred correctly - builder - .addCase( - 'increment', - (state, action: ReturnType) => state - ) - .addMatcher(decrement.match, (state, action) => { - expectType>(action) - }) - - // addCase().addDefaultCase() is possible, action type is UnknownAction - builder - .addCase( - 'increment', - (state, action: ReturnType) => state - ) - .addDefaultCase((state, action) => { - expectType(action) - }) - - { - // addMatcher() should prevent further calls to addCase() - const b = builder.addMatcher(increment.match, () => {}) - // @ts-expect-error - b.addCase(increment, () => {}) - b.addMatcher(increment.match, () => {}) - b.addDefaultCase(() => {}) - } - - { - // addDefaultCase() should prevent further calls to addCase(), addMatcher() and addDefaultCase - const b = builder.addDefaultCase(() => {}) - // @ts-expect-error - b.addCase(increment, () => {}) - // @ts-expect-error - b.addMatcher(increment.match, () => {}) - // @ts-expect-error - b.addDefaultCase(() => {}) - } - - // `createAsyncThunk` actions work with `mapBuilder` - { - // case 1: normal `createAsyncThunk` - { - const thunk = createAsyncThunk('test', () => { - return 'ret' as const - }) - builder.addCase(thunk.pending, (_, action) => { - expectType<{ - payload: undefined - meta: { - arg: void - requestId: string - requestStatus: 'pending' - } - }>(action) - }) - - builder.addCase(thunk.rejected, (_, action) => { - expectType<{ - payload: unknown - error: SerializedError - meta: { - arg: void - requestId: string - requestStatus: 'rejected' - aborted: boolean - condition: boolean - rejectedWithValue: boolean - } - }>(action) - }) - builder.addCase(thunk.fulfilled, (_, action) => { - expectType<{ - payload: 'ret' - meta: { - arg: void - requestId: string - requestStatus: 'fulfilled' - } - }>(action) - }) - } - } - // case 2: `createAsyncThunk` with `meta` - { - const thunk = createAsyncThunk< - 'ret', - void, - { - pendingMeta: { startedTimeStamp: number } - fulfilledMeta: { - fulfilledTimeStamp: number - baseQueryMeta: 'meta!' - } - rejectedMeta: { - baseQueryMeta: 'meta!' - } - } - >( - 'test', - (_, api) => { - return api.fulfillWithValue('ret' as const, { - fulfilledTimeStamp: 5, - baseQueryMeta: 'meta!', - }) - }, - { - getPendingMeta() { - return { startedTimeStamp: 0 } - }, - } - ) - - builder.addCase(thunk.pending, (_, action) => { - expectType<{ - payload: undefined - meta: { - arg: void - requestId: string - requestStatus: 'pending' - startedTimeStamp: number - } - }>(action) - }) - - builder.addCase(thunk.rejected, (_, action) => { - expectType<{ - payload: unknown - error: SerializedError - meta: { - arg: void - requestId: string - requestStatus: 'rejected' - aborted: boolean - condition: boolean - rejectedWithValue: boolean - baseQueryMeta?: 'meta!' - } - }>(action) - if (action.meta.rejectedWithValue) { - expectType<'meta!'>(action.meta.baseQueryMeta) - } - }) - builder.addCase(thunk.fulfilled, (_, action) => { - expectType<{ - payload: 'ret' - meta: { - arg: void - requestId: string - requestStatus: 'fulfilled' - baseQueryMeta: 'meta!' - } - }>(action) - }) - } - }) -} diff --git a/packages/toolkit/src/tests/matchers.test-d.ts b/packages/toolkit/src/tests/matchers.test-d.ts new file mode 100644 index 0000000000..12d3246eec --- /dev/null +++ b/packages/toolkit/src/tests/matchers.test-d.ts @@ -0,0 +1,302 @@ +import type { UnknownAction } from 'redux' +import type { SerializedError } from '../../src' +import { + createAction, + createAsyncThunk, + isAllOf, + isAnyOf, + isAsyncThunkAction, + isFulfilled, + isPending, + isRejected, + isRejectedWithValue, +} from '../../src' + +const action: UnknownAction = { type: 'foo' } + +describe('type tests', () => { + describe('isAnyOf', () => { + test('isAnyOf correctly narrows types when used with action creators', () => { + const actionA = createAction('a', () => { + return { + payload: { + prop1: 1, + prop3: 2, + }, + } + }) + + const actionB = createAction('b', () => { + return { + payload: { + prop1: 1, + prop2: 2, + }, + } + }) + + if (isAnyOf(actionA, actionB)(action)) { + return { + prop1: action.payload.prop1, + // @ts-expect-error + prop2: action.payload.prop2, + // @ts-expect-error + prop3: action.payload.prop3, + } + } + }) + + test('isAnyOf correctly narrows types when used with async thunks', () => { + const asyncThunk1 = createAsyncThunk<{ prop1: number; prop3: number }>( + 'asyncThunk1', + + async () => { + return { + prop1: 1, + prop3: 3, + } + }, + ) + + const asyncThunk2 = createAsyncThunk<{ prop1: number; prop2: number }>( + 'asyncThunk2', + + async () => { + return { + prop1: 1, + prop2: 2, + } + }, + ) + + if (isAnyOf(asyncThunk1.fulfilled, asyncThunk2.fulfilled)(action)) { + return { + prop1: action.payload.prop1, + // @ts-expect-error + prop2: action.payload.prop2, + // @ts-expect-error + prop3: action.payload.prop3, + } + } + }) + + test('isAnyOf correctly narrows types when used with type guards', () => { + interface ActionA { + type: 'a' + payload: { + prop1: 1 + prop3: 2 + } + } + + interface ActionB { + type: 'b' + payload: { + prop1: 1 + prop2: 2 + } + } + + const guardA = (v: any): v is ActionA => { + return v.type === 'a' + } + + const guardB = (v: any): v is ActionB => { + return v.type === 'b' + } + + if (isAnyOf(guardA, guardB)(action)) { + return { + prop1: action.payload.prop1, + // @ts-expect-error + prop2: action.payload.prop2, + // @ts-expect-error + prop3: action.payload.prop3, + } + } + }) + }) + + describe('isAllOf', () => { + interface SpecialAction { + payload: { + special: boolean + } + } + + const isSpecialAction = (v: any): v is SpecialAction => { + return v.meta.isSpecial + } + + test('isAllOf correctly narrows types when used with action creators and type guards', () => { + const actionA = createAction('a', () => { + return { + payload: { + prop1: 1, + prop3: 2, + }, + } + }) + + if (isAllOf(actionA, isSpecialAction)(action)) { + return { + prop1: action.payload.prop1, + // @ts-expect-error + prop2: action.payload.prop2, + prop3: action.payload.prop3, + special: action.payload.special, + } + } + }) + + test('isAllOf correctly narrows types when used with async thunks and type guards', () => { + const asyncThunk1 = createAsyncThunk<{ prop1: number; prop3: number }>( + 'asyncThunk1', + + async () => { + return { + prop1: 1, + prop3: 3, + } + }, + ) + + if (isAllOf(asyncThunk1.fulfilled, isSpecialAction)(action)) { + return { + prop1: action.payload.prop1, + // @ts-expect-error + prop2: action.payload.prop2, + prop3: action.payload.prop3, + special: action.payload.special, + } + } + }) + + test('isAnyOf correctly narrows types when used with type guards', () => { + interface ActionA { + type: 'a' + payload: { + prop1: 1 + prop3: 2 + } + } + + const guardA = (v: any): v is ActionA => { + return v.type === 'a' + } + + if (isAllOf(guardA, isSpecialAction)(action)) { + return { + prop1: action.payload.prop1, + // @ts-expect-error + prop2: action.payload.prop2, + prop3: action.payload.prop3, + special: action.payload.special, + } + } + }) + + test('isPending correctly narrows types', () => { + if (isPending(action)) { + expectTypeOf(action.payload).toBeUndefined() + + expectTypeOf(action).not.toHaveProperty('error') + } + + const thunk = createAsyncThunk('a', () => 'result') + + if (isPending(thunk)(action)) { + expectTypeOf(action.payload).toBeUndefined() + + expectTypeOf(action).not.toHaveProperty('error') + } + }) + + test('isRejected correctly narrows types', () => { + if (isRejected(action)) { + // might be there if rejected with payload + expectTypeOf(action.payload).toBeUnknown() + + expectTypeOf(action.error).toEqualTypeOf() + } + + const thunk = createAsyncThunk('a', () => 'result') + + if (isRejected(thunk)(action)) { + // might be there if rejected with payload + expectTypeOf(action.payload).toBeUnknown() + + expectTypeOf(action.error).toEqualTypeOf() + } + }) + + test('isFulfilled correctly narrows types', () => { + if (isFulfilled(action)) { + expectTypeOf(action.payload).toBeUnknown() + + expectTypeOf(action).not.toHaveProperty('error') + } + + const thunk = createAsyncThunk('a', () => 'result') + if (isFulfilled(thunk)(action)) { + expectTypeOf(action.payload).toBeString() + + expectTypeOf(action).not.toHaveProperty('error') + } + }) + + test('isAsyncThunkAction correctly narrows types', () => { + if (isAsyncThunkAction(action)) { + expectTypeOf(action.payload).toBeUnknown() + + // do not expect an error property because pending/fulfilled lack it + expectTypeOf(action).not.toHaveProperty('error') + } + + const thunk = createAsyncThunk('a', () => 'result') + if (isAsyncThunkAction(thunk)(action)) { + // we should expect the payload to be available, but of unknown type because the action may be pending/rejected + expectTypeOf(action.payload).toBeUnknown() + + // do not expect an error property because pending/fulfilled lack it + expectTypeOf(action).not.toHaveProperty('error') + } + }) + + test('isRejectedWithValue correctly narrows types', () => { + if (isRejectedWithValue(action)) { + expectTypeOf(action.payload).toBeUnknown() + + expectTypeOf(action.error).toEqualTypeOf() + } + + const thunk = createAsyncThunk< + string, + void, + { rejectValue: { message: string } } + >('a', () => 'result') + if (isRejectedWithValue(thunk)(action)) { + expectTypeOf(action.payload).toEqualTypeOf({ message: '' as string }) + + expectTypeOf(action.error).toEqualTypeOf() + } + }) + }) + + test('matchersAcceptSpreadArguments', () => { + const thunk1 = createAsyncThunk('a', () => 'a') + const thunk2 = createAsyncThunk('b', () => 'b') + const interestingThunks = [thunk1, thunk2] + const interestingPendingThunks = interestingThunks.map( + (thunk) => thunk.pending, + ) + const interestingFulfilledThunks = interestingThunks.map( + (thunk) => thunk.fulfilled, + ) + + const isLoading = isAnyOf(...interestingPendingThunks) + const isNotLoading = isAnyOf(...interestingFulfilledThunks) + + const isAllLoading = isAllOf(...interestingPendingThunks) + }) +}) diff --git a/packages/toolkit/src/tests/matchers.test.ts b/packages/toolkit/src/tests/matchers.test.ts index 54dbbed37e..11a6fdb8cd 100644 --- a/packages/toolkit/src/tests/matchers.test.ts +++ b/packages/toolkit/src/tests/matchers.test.ts @@ -70,7 +70,7 @@ describe('isAnyOf', () => { expect(isAnyOf(thunkA.fulfilled, thunkB.fulfilled)(action)).toEqual(true) expect( - isAnyOf(thunkA.pending, thunkA.rejected, thunkB.fulfilled)(action) + isAnyOf(thunkA.pending, thunkA.rejected, thunkB.fulfilled)(action), ).toEqual(false) }) @@ -133,13 +133,13 @@ describe('isAllOf', () => { const specialThunkAction = thunkA.fulfilled('SPECIAL', 'fakeRequestId') expect(isAllOf(thunkA.fulfilled, isActionSpecial)(specialThunkAction)).toBe( - true + true, ) const ordinaryThunkAction = thunkA.fulfilled('ORDINARY', 'fakeRequestId') expect( - isAllOf(thunkA.fulfilled, isActionSpecial)(ordinaryThunkAction) + isAllOf(thunkA.fulfilled, isActionSpecial)(ordinaryThunkAction), ).toBe(false) }) }) @@ -162,7 +162,7 @@ describe('isPending', () => { const rejectedAction = thunk.rejected( new Error('rejected'), - 'fakeRequestId' + 'fakeRequestId', ) expect(isPending()(rejectedAction)).toBe(false) @@ -180,7 +180,7 @@ describe('isPending', () => { function testPendingAction( thunk: typeof thunkA | typeof thunkB | typeof thunkC, - expected: boolean + expected: boolean, ) { const pendingAction = thunk.pending('fakeRequestId') expect(matchAC(pendingAction)).toBe(expected) @@ -188,7 +188,7 @@ describe('isPending', () => { const rejectedAction = thunk.rejected( new Error('rejected'), - 'fakeRequestId' + 'fakeRequestId', ) expect(matchAC(rejectedAction)).toBe(false) @@ -219,7 +219,7 @@ describe('isRejected', () => { const rejectedAction = thunk.rejected( new Error('rejected'), - 'fakeRequestId' + 'fakeRequestId', ) expect(isRejected()(rejectedAction)).toBe(true) expect(isRejected(rejectedAction)).toBe(true) @@ -238,14 +238,14 @@ describe('isRejected', () => { function testRejectedAction( thunk: typeof thunkA | typeof thunkB | typeof thunkC, - expected: boolean + expected: boolean, ) { const pendingAction = thunk.pending('fakeRequestId') expect(matchAC(pendingAction)).toBe(false) const rejectedAction = thunk.rejected( new Error('rejected'), - 'fakeRequestId' + 'fakeRequestId', ) expect(matchAC(rejectedAction)).toBe(expected) expect(matchB(rejectedAction)).toBe(!expected) @@ -279,7 +279,7 @@ describe('isRejectedWithValue', () => { const rejectedAction = thunk.rejected( new Error('rejected'), - 'fakeRequestId' + 'fakeRequestId', ) expect(isRejectedWithValue()(rejectedAction)).toBe(false) @@ -310,14 +310,14 @@ describe('isRejectedWithValue', () => { async function testRejectedAction( thunk: typeof thunkA | typeof thunkB | typeof thunkC, - expected: boolean + expected: boolean, ) { const pendingAction = thunk.pending('fakeRequestId') expect(matchAC(pendingAction)).toBe(false) const rejectedAction = thunk.rejected( new Error('rejected'), - 'fakeRequestId' + 'fakeRequestId', ) // rejected-with-value is a narrower requirement than rejected expect(matchAC(rejectedAction)).toBe(false) @@ -359,7 +359,7 @@ describe('isFulfilled', () => { const rejectedAction = thunk.rejected( new Error('rejected'), - 'fakeRequestId' + 'fakeRequestId', ) expect(isFulfilled()(rejectedAction)).toBe(false) @@ -378,14 +378,14 @@ describe('isFulfilled', () => { function testFulfilledAction( thunk: typeof thunkA | typeof thunkB | typeof thunkC, - expected: boolean + expected: boolean, ) { const pendingAction = thunk.pending('fakeRequestId') expect(matchAC(pendingAction)).toBe(false) const rejectedAction = thunk.rejected( new Error('rejected'), - 'fakeRequestId' + 'fakeRequestId', ) expect(matchAC(rejectedAction)).toBe(false) @@ -418,7 +418,7 @@ describe('isAsyncThunkAction', () => { const rejectedAction = thunk.rejected( new Error('rejected'), - 'fakeRequestId' + 'fakeRequestId', ) expect(matcher(rejectedAction)).toBe(true) @@ -436,7 +436,7 @@ describe('isAsyncThunkAction', () => { function testAllActions( thunk: typeof thunkA | typeof thunkB | typeof thunkC, - expected: boolean + expected: boolean, ) { const pendingAction = thunk.pending('fakeRequestId') expect(matchAC(pendingAction)).toBe(expected) @@ -444,7 +444,7 @@ describe('isAsyncThunkAction', () => { const rejectedAction = thunk.rejected( new Error('rejected'), - 'fakeRequestId' + 'fakeRequestId', ) expect(matchAC(rejectedAction)).toBe(expected) expect(matchB(rejectedAction)).toBe(!expected) diff --git a/packages/toolkit/src/tests/matchers.typetest.ts b/packages/toolkit/src/tests/matchers.typetest.ts deleted file mode 100644 index 495796727f..0000000000 --- a/packages/toolkit/src/tests/matchers.typetest.ts +++ /dev/null @@ -1,330 +0,0 @@ -import { expectExactType, expectUnknown } from './helpers' -import type { UnknownAction } from 'redux' -import type { SerializedError } from '../../src' -import { - createAction, - createAsyncThunk, - isAllOf, - isAnyOf, - isAsyncThunkAction, - isFulfilled, - isPending, - isRejected, - isRejectedWithValue, -} from '../../src' - -/* isAnyOf */ - -/* - * Test: isAnyOf correctly narrows types when used with action creators - */ -function isAnyOfActionTest(action: UnknownAction) { - const actionA = createAction('a', () => { - return { - payload: { - prop1: 1, - prop3: 2, - }, - } - }) - - const actionB = createAction('b', () => { - return { - payload: { - prop1: 1, - prop2: 2, - }, - } - }) - - if (isAnyOf(actionA, actionB)(action)) { - return { - prop1: action.payload.prop1, - // @ts-expect-error - prop2: action.payload.prop2, - // @ts-expect-error - prop3: action.payload.prop3, - } - } -} - -/* - * Test: isAnyOf correctly narrows types when used with async thunks - */ -function isAnyOfThunkTest(action: UnknownAction) { - const asyncThunk1 = createAsyncThunk<{ prop1: number; prop3: number }>( - 'asyncThunk1', - - async () => { - return { - prop1: 1, - prop3: 3, - } - } - ) - - const asyncThunk2 = createAsyncThunk<{ prop1: number; prop2: number }>( - 'asyncThunk2', - - async () => { - return { - prop1: 1, - prop2: 2, - } - } - ) - - if (isAnyOf(asyncThunk1.fulfilled, asyncThunk2.fulfilled)(action)) { - return { - prop1: action.payload.prop1, - // @ts-expect-error - prop2: action.payload.prop2, - // @ts-expect-error - prop3: action.payload.prop3, - } - } -} - -/* - * Test: isAnyOf correctly narrows types when used with type guards - */ -function isAnyOfTypeGuardTest(action: UnknownAction) { - interface ActionA { - type: 'a' - payload: { - prop1: 1 - prop3: 2 - } - } - - interface ActionB { - type: 'b' - payload: { - prop1: 1 - prop2: 2 - } - } - - const guardA = (v: any): v is ActionA => { - return v.type === 'a' - } - - const guardB = (v: any): v is ActionB => { - return v.type === 'b' - } - - if (isAnyOf(guardA, guardB)(action)) { - return { - prop1: action.payload.prop1, - // @ts-expect-error - prop2: action.payload.prop2, - // @ts-expect-error - prop3: action.payload.prop3, - } - } -} - -/* isAllOf */ - -interface SpecialAction { - payload: { - special: boolean - } -} - -const isSpecialAction = (v: any): v is SpecialAction => { - return v.meta.isSpecial -} - -/* - * Test: isAllOf correctly narrows types when used with action creators - * and type guards - */ -function isAllOfActionTest(action: UnknownAction) { - const actionA = createAction('a', () => { - return { - payload: { - prop1: 1, - prop3: 2, - }, - } - }) - - if (isAllOf(actionA, isSpecialAction)(action)) { - return { - prop1: action.payload.prop1, - // @ts-expect-error - prop2: action.payload.prop2, - prop3: action.payload.prop3, - special: action.payload.special, - } - } -} - -/* - * Test: isAllOf correctly narrows types when used with async thunks - * and type guards - */ -function isAllOfThunkTest(action: UnknownAction) { - const asyncThunk1 = createAsyncThunk<{ prop1: number; prop3: number }>( - 'asyncThunk1', - - async () => { - return { - prop1: 1, - prop3: 3, - } - } - ) - - if (isAllOf(asyncThunk1.fulfilled, isSpecialAction)(action)) { - return { - prop1: action.payload.prop1, - // @ts-expect-error - prop2: action.payload.prop2, - prop3: action.payload.prop3, - special: action.payload.special, - } - } -} - -/* - * Test: isAnyOf correctly narrows types when used with type guards - */ -function isAllOfTypeGuardTest(action: UnknownAction) { - interface ActionA { - type: 'a' - payload: { - prop1: 1 - prop3: 2 - } - } - - const guardA = (v: any): v is ActionA => { - return v.type === 'a' - } - - if (isAllOf(guardA, isSpecialAction)(action)) { - return { - prop1: action.payload.prop1, - // @ts-expect-error - prop2: action.payload.prop2, - prop3: action.payload.prop3, - special: action.payload.special, - } - } -} - -/* - * Test: isPending correctly narrows types - */ -function isPendingTest(action: UnknownAction) { - if (isPending(action)) { - expectExactType(action.payload) - // @ts-expect-error - action.error - } - - const thunk = createAsyncThunk('a', () => 'result') - - if (isPending(thunk)(action)) { - expectExactType(action.payload) - // @ts-expect-error - action.error - } -} - -/* - * Test: isRejected correctly narrows types - */ -function isRejectedTest(action: UnknownAction) { - if (isRejected(action)) { - // might be there if rejected with payload - expectUnknown(action.payload) - expectExactType(action.error) - } - - const thunk = createAsyncThunk('a', () => 'result') - - if (isRejected(thunk)(action)) { - // might be there if rejected with payload - expectUnknown(action.payload) - expectExactType(action.error) - } -} - -/* - * Test: isFulfilled correctly narrows types - */ -function isFulfilledTest(action: UnknownAction) { - if (isFulfilled(action)) { - expectUnknown(action.payload) - // @ts-expect-error - action.error - } - - const thunk = createAsyncThunk('a', () => 'result') - if (isFulfilled(thunk)(action)) { - expectExactType('' as string)(action.payload) - // @ts-expect-error - action.error - } -} - -/* - * Test: isAsyncThunkAction correctly narrows types - */ -function isAsyncThunkActionTest(action: UnknownAction) { - if (isAsyncThunkAction(action)) { - expectUnknown(action.payload) - // do not expect an error property because pending/fulfilled lack it - // @ts-expect-error - action.error - } - - const thunk = createAsyncThunk('a', () => 'result') - if (isAsyncThunkAction(thunk)(action)) { - // we should expect the payload to be available, but of unknown type because the action may be pending/rejected - expectUnknown(action.payload) - // do not expect an error property because pending/fulfilled lack it - // @ts-expect-error - action.error - } -} - -/* - * Test: isRejectedWithValue correctly narrows types - */ -function isRejectedWithValueTest(action: UnknownAction) { - if (isRejectedWithValue(action)) { - expectUnknown(action.payload) - expectExactType(action.error) - } - - const thunk = createAsyncThunk< - string, - void, - { rejectValue: { message: string } } - >('a', () => 'result') - if (isRejectedWithValue(thunk)(action)) { - expectExactType({ message: '' as string })(action.payload) - expectExactType(action.error) - } -} - -function matchersAcceptSpreadArguments() { - const thunk1 = createAsyncThunk('a', () => 'a') - const thunk2 = createAsyncThunk('b', () => 'b') - const interestingThunks = [thunk1, thunk2] - const interestingPendingThunks = interestingThunks.map( - (thunk) => thunk.pending - ) - const interestingFulfilledThunks = interestingThunks.map( - (thunk) => thunk.fulfilled - ) - - const isLoading = isAnyOf(...interestingPendingThunks) - const isNotLoading = isAnyOf(...interestingFulfilledThunks) - - const isAllLoading = isAllOf(...interestingPendingThunks) -} diff --git a/packages/toolkit/src/tests/serializableStateInvariantMiddleware.test.ts b/packages/toolkit/src/tests/serializableStateInvariantMiddleware.test.ts index d9413671ed..0d0ffd7630 100644 --- a/packages/toolkit/src/tests/serializableStateInvariantMiddleware.test.ts +++ b/packages/toolkit/src/tests/serializableStateInvariantMiddleware.test.ts @@ -362,7 +362,7 @@ describe('serializableStateInvariantMiddleware', () => { new Tuple( createSerializableStateInvariantMiddleware({ ignoredActionPaths: [], - }) + }), ), }).dispatch({ type: 'test', meta: { arg: nonSerializableValue } }) @@ -386,7 +386,7 @@ describe('serializableStateInvariantMiddleware', () => { new Tuple( createSerializableStateInvariantMiddleware({ ignoredActionPaths: ['payload', 'meta.arg'], - }) + }), ), }).dispatch({ type: 'test', @@ -404,7 +404,7 @@ describe('serializableStateInvariantMiddleware', () => { new Tuple( createSerializableStateInvariantMiddleware({ ignoredActionPaths: [/^payload\..*$/], - }) + }), ), }).dispatch({ type: 'test', @@ -519,7 +519,7 @@ describe('serializableStateInvariantMiddleware', () => { return true }, ignoreState: true, - }) + }), ), }) @@ -548,7 +548,7 @@ describe('serializableStateInvariantMiddleware', () => { }, ignoreState: true, ignoreActions: true, - }) + }), ), }) @@ -580,7 +580,7 @@ describe('serializableStateInvariantMiddleware', () => { payload: new Array(10000).fill({ value: 'more' }), }) expect(getLog().log).toMatch( - /^SerializableStateInvariantMiddleware took \d*ms, which is more than the warning threshold of 4ms./ + /^SerializableStateInvariantMiddleware took \d*ms, which is more than the warning threshold of 4ms./, ) }) @@ -626,7 +626,7 @@ describe('serializableStateInvariantMiddleware', () => { }) const state = createNextState([], () => - new Array(50).fill(0).map((x, i) => ({ i })) + new Array(50).fill(0).map((x, i) => ({ i })), ) expect(isNestedFrozen(state)).toBe(true) diff --git a/packages/toolkit/src/tests/tsconfig.json b/packages/toolkit/src/tests/tsconfig.json deleted file mode 100644 index 3678164521..0000000000 --- a/packages/toolkit/src/tests/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../../tsconfig.test.json" -} diff --git a/packages/toolkit/src/tests/tsconfig.typetests.json b/packages/toolkit/src/tests/tsconfig.typetests.json deleted file mode 100644 index 5fe2280ed9..0000000000 --- a/packages/toolkit/src/tests/tsconfig.typetests.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig.test.json", - "compilerOptions": { - "skipLibCheck": true, - "rootDir": "../../src" - }, - "include": ["../dynamicMiddleware", "../entities", "../listenerMiddleware"] -} diff --git a/packages/toolkit/src/tests/utils/CustomMatchers.d.ts b/packages/toolkit/src/tests/utils/CustomMatchers.d.ts new file mode 100644 index 0000000000..955e51db36 --- /dev/null +++ b/packages/toolkit/src/tests/utils/CustomMatchers.d.ts @@ -0,0 +1,17 @@ +import type { Assertion, AsymmetricMatchersContaining } from 'vitest' + +interface CustomMatchers { + toHaveConsoleOutput(expectedOutput: string): Promise + toMatchSequence(...matchers: Array<(arg: any) => boolean>): R +} + +declare module 'vitest' { + interface Assertion extends CustomMatchers {} + interface AsymmetricMatchersContaining extends CustomMatchers {} +} + +declare global { + namespace jest { + interface Matchers extends CustomMatchers {} + } +} diff --git a/packages/toolkit/src/query/tests/helpers.tsx b/packages/toolkit/src/tests/utils/helpers.tsx similarity index 73% rename from packages/toolkit/src/query/tests/helpers.tsx rename to packages/toolkit/src/tests/utils/helpers.tsx index acf2bf097b..5ccedc434d 100644 --- a/packages/toolkit/src/query/tests/helpers.tsx +++ b/packages/toolkit/src/tests/utils/helpers.tsx @@ -1,29 +1,29 @@ -import React, { useCallback } from 'react' import type { - UnknownAction, EnhancedStore, Middleware, - Store, Reducer, + Store, + UnknownAction, } from '@reduxjs/toolkit' import { configureStore } from '@reduxjs/toolkit' import { setupListeners } from '@reduxjs/toolkit/query' +import { useCallback, useEffect, useRef } from 'react' import { Provider } from 'react-redux' +import { act, cleanup } from '@testing-library/react' import { - mockConsole, createConsole, getLog, + mockConsole, } from 'console-testing-library/pure' -import { cleanup, act } from '@testing-library/react' export const ANY = 0 as any export const DEFAULT_DELAY_MS = 150 export const getSerializedHeaders = (headers: Headers = new Headers()) => { - let result: Record = {} + const result: Record = {} headers.forEach((val, key) => { result[key] = val }) @@ -83,13 +83,13 @@ export const fakeTimerWaitFor = async (cb: () => void, time = 2000) => { } export const useRenderCounter = () => { - const countRef = React.useRef(0) + const countRef = useRef(0) - React.useEffect(() => { + useEffect(() => { countRef.current += 1 }) - React.useEffect(() => { + useEffect(() => { return () => { countRef.current = 0 } @@ -98,14 +98,6 @@ export const useRenderCounter = () => { return useCallback(() => countRef.current, []) } -declare global { - namespace jest { - interface Matchers { - toMatchSequence(...matchers: Array<(arg: any) => boolean>): R - } - } -} - expect.extend({ toMatchSequence( _actions: UnknownAction[], @@ -150,16 +142,16 @@ function normalize(str: string) { expect.extend({ async toHaveConsoleOutput( fn: () => void | Promise, - expectedOutput: string + expectedOutput: string, ) { const restore = mockConsole(createConsole()) await fn() - const log = getLog().log + const { log } = getLog() restore() if (normalize(log) === normalize(expectedOutput)) return { - message: () => `Console output matches + message: () => `Console output matches === ${expectedOutput} ===`, @@ -167,11 +159,11 @@ ${expectedOutput} } else return { - message: () => `Console output + message: () => `Console output === ${log} -=== -does not match +=== +does not match === ${expectedOutput} ===`, @@ -198,7 +190,7 @@ export function setupApiStore< middleware: Middleware util: { resetApiState(): any } }, - R extends Record> = Record + R extends Record> = Record, >( api: A, extraReducers?: R, @@ -209,7 +201,7 @@ export function setupApiStore< prepend?: Middleware[] concat?: Middleware[] } - } = {} + } = {}, ) { const { middleware } = options const getStore = () => @@ -276,62 +268,3 @@ export function setupApiStore< return refObj } - -// type test helpers - -export declare type IsAny = true | false extends ( - T extends never ? true : false -) - ? True - : False - -export declare type IsUnknown = unknown extends T - ? IsAny - : False - -export function expectType(t: T): T { - return t -} - -type Equals = IsAny< - T, - never, - IsAny -> -export function expectExactType(t: T) { - return >(u: U) => {} -} - -type EnsureUnknown = IsUnknown -export function expectUnknown>(t: T) { - return t -} - -type EnsureAny = IsAny -export function expectExactAny>(t: T) { - return t -} - -type IsNotAny = IsAny -export function expectNotAny>(t: T): T { - return t -} - -expectType('5' as string) -expectType('5' as const) -expectType('5' as any) -expectExactType('5' as const)('5' as const) -// @ts-expect-error -expectExactType('5' as string)('5' as const) -// @ts-expect-error -expectExactType('5' as any)('5' as const) -expectUnknown('5' as unknown) -// @ts-expect-error -expectUnknown('5' as const) -// @ts-expect-error -expectUnknown('5' as any) -expectExactAny('5' as any) -// @ts-expect-error -expectExactAny('5' as const) -// @ts-expect-error -expectExactAny('5' as unknown) diff --git a/packages/toolkit/src/tsHelpers.ts b/packages/toolkit/src/tsHelpers.ts index bd42de858e..45c90aeaef 100644 --- a/packages/toolkit/src/tsHelpers.ts +++ b/packages/toolkit/src/tsHelpers.ts @@ -87,14 +87,14 @@ export type UnionToIntersection = ( // Appears to have a convenient side effect of ignoring `never` even if that's not what you specified export type ExcludeFromTuple = T extends [ infer Head, - ...infer Tail + ...infer Tail, ] ? ExcludeFromTuple : Acc type ExtractDispatchFromMiddlewareTuple< MiddlewareTuple extends readonly any[], - Acc extends {} + Acc extends {}, > = MiddlewareTuple extends [infer Head, ...infer Tail] ? ExtractDispatchFromMiddlewareTuple< Tail, @@ -102,17 +102,16 @@ type ExtractDispatchFromMiddlewareTuple< > : Acc -export type ExtractDispatchExtensions = M extends Tuple< - infer MiddlewareTuple -> - ? ExtractDispatchFromMiddlewareTuple - : M extends ReadonlyArray - ? ExtractDispatchFromMiddlewareTuple<[...M], {}> - : never +export type ExtractDispatchExtensions = + M extends Tuple + ? ExtractDispatchFromMiddlewareTuple + : M extends ReadonlyArray + ? ExtractDispatchFromMiddlewareTuple<[...M], {}> + : never type ExtractStoreExtensionsFromEnhancerTuple< EnhancerTuple extends readonly any[], - Acc extends {} + Acc extends {}, > = EnhancerTuple extends [infer Head, ...infer Tail] ? ExtractStoreExtensionsFromEnhancerTuple< Tail, @@ -120,21 +119,22 @@ type ExtractStoreExtensionsFromEnhancerTuple< > : Acc -export type ExtractStoreExtensions = E extends Tuple - ? ExtractStoreExtensionsFromEnhancerTuple - : E extends ReadonlyArray - ? UnionToIntersection< - E[number] extends StoreEnhancer - ? Ext extends {} - ? IsAny - : {} - : {} - > - : never +export type ExtractStoreExtensions = + E extends Tuple + ? ExtractStoreExtensionsFromEnhancerTuple + : E extends ReadonlyArray + ? UnionToIntersection< + E[number] extends StoreEnhancer + ? Ext extends {} + ? IsAny + : {} + : {} + > + : never type ExtractStateExtensionsFromEnhancerTuple< EnhancerTuple extends readonly any[], - Acc extends {} + Acc extends {}, > = EnhancerTuple extends [infer Head, ...infer Tail] ? ExtractStateExtensionsFromEnhancerTuple< Tail, @@ -145,17 +145,18 @@ type ExtractStateExtensionsFromEnhancerTuple< > : Acc -export type ExtractStateExtensions = E extends Tuple - ? ExtractStateExtensionsFromEnhancerTuple - : E extends ReadonlyArray - ? UnionToIntersection< - E[number] extends StoreEnhancer - ? StateExt extends {} - ? IsAny - : {} - : {} - > - : never +export type ExtractStateExtensions = + E extends Tuple + ? ExtractStateExtensionsFromEnhancerTuple + : E extends ReadonlyArray + ? UnionToIntersection< + E[number] extends StoreEnhancer + ? StateExt extends {} + ? IsAny + : {} + : {} + > + : never /** * Helper type. Passes T out again, but boxes it in a way that it cannot @@ -185,7 +186,7 @@ export interface HasMatchFunction { } export const hasMatchFunction = ( - v: Matcher + v: Matcher, ): v is HasMatchFunction => { return v && typeof (v as HasMatchFunction).match === 'function' } @@ -194,11 +195,8 @@ export const hasMatchFunction = ( export type Matcher = HasMatchFunction | TypeGuard /** @public */ -export type ActionFromMatcher> = M extends Matcher< - infer T -> - ? T - : never +export type ActionFromMatcher> = + M extends Matcher ? T : never export type Id = { [K in keyof T]: T[K] } & {} @@ -207,3 +205,21 @@ export type Tail = T extends [any, ...infer Tail] : never export type UnknownIfNonSpecific = {} extends T ? unknown : T + +/** + * A Promise that will never reject. + * @see https://github.com/reduxjs/redux-toolkit/issues/4101 + */ +export type SafePromise = Promise & { + __linterBrands: 'SafePromise' +} + +/** + * Properly wraps a Promise as a {@link SafePromise} with .catch(fallback). + */ +export function asSafePromise( + promise: Promise, + fallback: (error: unknown) => Rejected, +) { + return promise.catch(fallback) as SafePromise +} diff --git a/packages/toolkit/src/utils.ts b/packages/toolkit/src/utils.ts index 7dfe43dc3a..11c04ab83c 100644 --- a/packages/toolkit/src/utils.ts +++ b/packages/toolkit/src/utils.ts @@ -29,7 +29,7 @@ export function delay(ms: number) { export function find( iterable: Iterable, - comparator: (item: T) => boolean + comparator: (item: T) => boolean, ): T | undefined { for (const entry of iterable) { if (comparator(entry)) { @@ -55,10 +55,10 @@ export class Tuple = []> extends Array< } concat>( - items: Tuple + items: Tuple, ): Tuple<[...Items, ...AdditionalItems]> concat>( - items: AdditionalItems + items: AdditionalItems, ): Tuple<[...Items, ...AdditionalItems]> concat>( ...items: AdditionalItems @@ -68,10 +68,10 @@ export class Tuple = []> extends Array< } prepend>( - items: Tuple + items: Tuple, ): Tuple<[...AdditionalItems, ...Items]> prepend>( - items: AdditionalItems + items: AdditionalItems, ): Tuple<[...AdditionalItems, ...Items]> prepend>( ...items: AdditionalItems @@ -113,12 +113,12 @@ interface MapEmplaceHandler { export function emplace( map: Map, key: K, - handler: MapEmplaceHandler + handler: MapEmplaceHandler, ): V export function emplace( map: WeakMap, key: K, - handler: WeakMapEmplaceHandler + handler: WeakMapEmplaceHandler, ): V /** * Allow inserting a new value, or updating an existing one @@ -150,7 +150,7 @@ export function emplace( export function emplace( map: WeakMap, key: K, - handler: WeakMapEmplaceHandler + handler: WeakMapEmplaceHandler, ): V { if (map.has(key)) { let value = map.get(key) as V diff --git a/packages/toolkit/tsconfig.base.json b/packages/toolkit/tsconfig.base.json index e06342c0cf..aad62c5c2c 100644 --- a/packages/toolkit/tsconfig.base.json +++ b/packages/toolkit/tsconfig.base.json @@ -1,8 +1,8 @@ { "compilerOptions": { "target": "ESnext", - "module": "esnext", - "lib": ["dom", "esnext"], + "module": "ESnext", + "lib": ["DOM", "ESNext"], "importHelpers": true, // output .d.ts declaration files for consumers "declaration": true, @@ -17,7 +17,7 @@ "noUnusedLocals": false, "noUnusedParameters": false, // use Node's module resolution algorithm, instead of the legacy TS one - "moduleResolution": "node", + "moduleResolution": "Node", // transpile JSX to React.createElement "jsx": "react", // interop between ESM and CJS modules. Recommended by TS @@ -32,7 +32,7 @@ "allowSyntheticDefaultImports": true, "emitDeclarationOnly": true, "baseUrl": ".", - "types": ["vitest/globals"], + "types": ["vitest/globals", "vitest/importMeta"], "paths": { "@reduxjs/toolkit": ["src/index.ts"], // @remap-prod-remove-line "@reduxjs/toolkit/react": ["src/react/index.ts"], // @remap-prod-remove-line diff --git a/packages/toolkit/tsconfig.build.json b/packages/toolkit/tsconfig.build.json new file mode 100644 index 0000000000..c643ccc7c0 --- /dev/null +++ b/packages/toolkit/tsconfig.build.json @@ -0,0 +1,15 @@ +{ + // For building the library. + "extends": "./tsconfig.base.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": ["src"], + "exclude": [ + "src/**/*.test.ts*", + "src/**/*.test-d.ts*", + "src/**/*.spec.ts*", + "src/**/tests/*", + "src/**/*.typetest.ts*" + ] +} diff --git a/packages/toolkit/tsconfig.json b/packages/toolkit/tsconfig.json index cb2e851486..f485db8fd3 100644 --- a/packages/toolkit/tsconfig.json +++ b/packages/toolkit/tsconfig.json @@ -1,13 +1,11 @@ { - "extends": "./tsconfig.base.json", + // For general development and intellisense. + // Scans the entire source code against the current TS version + // we are using during development. + "extends": "./tsconfig.test.json", "compilerOptions": { - "outDir": "dist" + "skipLibCheck": true, + "rootDir": ".", }, - "include": [ - "src" - ], - "exclude": [ - "src/**/*.test.ts*", - "src/**/tests/*" - ] -} \ No newline at end of file + "include": ["."], +} diff --git a/packages/toolkit/tsconfig.test.json b/packages/toolkit/tsconfig.test.json index c5938454a1..2bb74da6da 100644 --- a/packages/toolkit/tsconfig.test.json +++ b/packages/toolkit/tsconfig.test.json @@ -1,17 +1,20 @@ { - "extends": "../toolkit/tsconfig.base.json", + // For runtime and type tests during CI. + "extends": "./tsconfig.base.json", "compilerOptions": { - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", "emitDeclarationOnly": false, - "strict": true, "noEmit": true, - "target": "es2018", - "jsx": "react", - "baseUrl": ".", - "skipLibCheck": false, + "rootDir": "./src", + "jsx": "react-jsx", + "skipLibCheck": true, "noImplicitReturns": false - } + }, + "exclude": ["dist"], + "include": [ + "src/**/*.test.ts*", + "src/**/*.test-d.ts*", + "src/**/*.spec.ts*", + "src/**/tests/**/*", + "src/**/*.typetest.ts*" + ] } diff --git a/packages/toolkit/tsup.config.ts b/packages/toolkit/tsup.config.ts index 3b1f3ff417..a2726e030a 100644 --- a/packages/toolkit/tsup.config.ts +++ b/packages/toolkit/tsup.config.ts @@ -1,13 +1,11 @@ -import { fileURLToPath } from 'url' -import path from 'path' -import fs from 'fs' -import type { BuildOptions as ESBuildOptions, Plugin } from 'esbuild' -import type { Options as TsupOptions } from 'tsup' -import { defineConfig } from 'tsup' import * as babel from '@babel/core' +import type { Plugin } from 'esbuild' import { getBuildExtensions } from 'esbuild-extra' - -import { delay } from './src/utils' +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import type { Options as TsupOptions } from 'tsup' +import { defineConfig } from 'tsup' // No __dirname under Node ESM const __filename = fileURLToPath(import.meta.url) @@ -125,7 +123,7 @@ if (process.env.NODE_ENV === 'production') { module.exports = require('./${prefix}.production.min.cjs') } else { module.exports = require('./${prefix}.development.cjs') -}` +}`, ) } @@ -155,6 +153,11 @@ const mangleErrorsTransform: Plugin = { }, } +const tsconfig: NonNullable = path.join( + __dirname, + './tsconfig.build.json', +) + export default defineConfig((options) => { const configs = entryPoints .map((entryPointConfig) => { @@ -188,6 +191,7 @@ export default defineConfig((options) => { [outputFilename]: entryPoint, }, format, + tsconfig, outDir: outputFolder, target, outExtension: () => ({ js: extension }), @@ -214,7 +218,7 @@ export default defineConfig((options) => { fs.copyFileSync( 'src/uncheckedindexed.ts', - path.join(outputFolder, 'uncheckedindexed.ts') + path.join(outputFolder, 'uncheckedindexed.ts'), ) } // TODO Copy/generate `.d.mts` files? diff --git a/packages/toolkit/vitest.config.ts b/packages/toolkit/vitest.config.mts similarity index 83% rename from packages/toolkit/vitest.config.ts rename to packages/toolkit/vitest.config.mts index 45b67cf6bd..ff53069d54 100644 --- a/packages/toolkit/vitest.config.ts +++ b/packages/toolkit/vitest.config.mts @@ -9,10 +9,9 @@ const __dirname = path.dirname(__filename) export default defineConfig({ test: { - typecheck: { only: true, tsconfig: './src/tests/tsconfig.typetests.json' }, globals: true, environment: 'jsdom', - setupFiles: ['./vitest.setup.js'], + setupFiles: ['./vitest.setup.ts'], include: ['./src/**/*.(spec|test).[jt]s?(x)'], alias: { // prettier-ignore @@ -25,9 +24,6 @@ export default defineConfig({ //'^@reduxjs/toolkit/dist/(.*)$': '/src/*', '@internal': path.join(__dirname, './src'), }, - deps: { - interopDefault: true, - inline: ['redux', '@reduxjs/toolkit'], - }, + server: { deps: { inline: ['redux', '@reduxjs/toolkit'] } }, }, }) diff --git a/packages/toolkit/vitest.setup.js b/packages/toolkit/vitest.setup.js deleted file mode 100644 index fc4a30240e..0000000000 --- a/packages/toolkit/vitest.setup.js +++ /dev/null @@ -1,19 +0,0 @@ -//@ts-ignore -import nodeFetch from 'node-fetch' -//@ts-ignore -globalThis.fetch = nodeFetch -//@ts-ignore -globalThis.Request = nodeFetch.Request -globalThis.Headers = nodeFetch.Headers -import { server } from './src/query/tests/mocks/server' - -beforeAll(() => server.listen({ onUnhandledRequest: 'error' })) -afterEach(() => server.resetHandlers()) -afterAll(() => server.close()) - -process.on('unhandledRejection', (error) => { - // eslint-disable-next-line no-undef - fail(error) -}) - -process.env.NODE_ENV = 'development' diff --git a/packages/toolkit/vitest.setup.ts b/packages/toolkit/vitest.setup.ts new file mode 100644 index 0000000000..1be6b0b461 --- /dev/null +++ b/packages/toolkit/vitest.setup.ts @@ -0,0 +1,18 @@ +import nodeFetch, { Headers, Request } from 'node-fetch' +import { server } from './src/query/tests/mocks/server' + +vi.stubGlobal('fetch', nodeFetch) +vi.stubGlobal('Request', Request) +vi.stubGlobal('Headers', Headers) + +beforeAll(() => { + server.listen({ onUnhandledRequest: 'error' }) +}) + +afterEach(() => { + server.resetHandlers() +}) + +afterAll(() => { + server.close() +}) diff --git a/website/package.json b/website/package.json index 0cf8eb3dc4..14ce1cce33 100644 --- a/website/package.json +++ b/website/package.json @@ -32,6 +32,7 @@ ] }, "devDependencies": { - "netlify-plugin-cache": "^1.0.3" + "netlify-plugin-cache": "^1.0.3", + "prettier": "^3.2.4" } } diff --git a/website/src/css/custom.css b/website/src/css/custom.css index 4a61c52f6d..5bb4d94df8 100644 --- a/website/src/css/custom.css +++ b/website/src/css/custom.css @@ -173,12 +173,16 @@ a:visited { transform: rotateZ(180deg); -webkit-transition: -webkit-transform 0.2s linear; transition: -webkit-transform 0.2s linear; - transition-property: transform, -webkit-transform; + transition-property: + transform, + -webkit-transform; transition-duration: 0.2s, 0.2s; transition-timing-function: linear, linear; transition-delay: 0s, 0s; transition: transform 0.2s linear; - transition: transform 0.2s linear, -webkit-transform 0.2s linear; + transition: + transform 0.2s linear, + -webkit-transform 0.2s linear; color: var(--ifm-font-base-color) !important; } diff --git a/website/src/js/monokaiTheme.js b/website/src/js/monokaiTheme.js index e5c47f8be9..94e5cb451c 100644 --- a/website/src/js/monokaiTheme.js +++ b/website/src/js/monokaiTheme.js @@ -1,62 +1,62 @@ module.exports = { plain: { color: '#f8f8f2', - backgroundColor: '#272822' + backgroundColor: '#272822', }, styles: [ { types: ['comment', 'prolog', 'doctype', 'cdata'], style: { - color: '#778090' - } + color: '#778090', + }, }, { types: ['punctuation'], style: { - color: '#F8F8F2' - } + color: '#F8F8F2', + }, }, { types: ['property', 'tag', 'constant', 'symbol', 'deleted'], style: { - color: '#F92672' - } + color: '#F92672', + }, }, { types: ['boolean', 'number'], style: { - color: '#AE81FF' - } + color: '#AE81FF', + }, }, { types: ['selector', 'attr-name', 'string', 'char', 'builtin', 'inserted'], style: { - color: '#a6e22e' - } + color: '#a6e22e', + }, }, { types: ['operator', 'entity', 'url', 'variable'], style: { - color: '#F8F8F2' - } + color: '#F8F8F2', + }, }, { types: ['atrule', 'attr-value', 'function'], style: { - color: '#E6D874' - } + color: '#E6D874', + }, }, { types: ['keyword'], style: { - color: '#F92672' - } + color: '#F92672', + }, }, { types: ['regex', 'important'], style: { - color: '#FD971F' - } - } - ] + color: '#FD971F', + }, + }, + ], } diff --git a/website/src/pages/styles.module.css b/website/src/pages/styles.module.css index e8184048bd..54f977306d 100644 --- a/website/src/pages/styles.module.css +++ b/website/src/pages/styles.module.css @@ -99,7 +99,6 @@ margin-top: 0; } - .errorDetails { color: #ff6464; border-radius: 0.5rem; diff --git a/yarn.lock b/yarn.lock index a924d6a580..4ad2bb187e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,6 +5,13 @@ __metadata: version: 6 cacheKey: 8 +"@aashutoshrathi/word-wrap@npm:^1.2.3": + version: 1.2.6 + resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" + checksum: ada901b9e7c680d190f1d012c84217ce0063d8f5c5a7725bb91ec3c5ed99bb7572680eb2d2938a531ccbaec39a95422fcd8a6b4a13110c7d98dd75402f66a0cd + languageName: node + linkType: hard + "@algolia/autocomplete-core@npm:1.7.1": version: 1.7.1 resolution: "@algolia/autocomplete-core@npm:1.7.1" @@ -263,11 +270,11 @@ __metadata: languageName: node linkType: hard -"@arethetypeswrong/cli@npm:^0.13.1": - version: 0.13.1 - resolution: "@arethetypeswrong/cli@npm:0.13.1" +"@arethetypeswrong/cli@npm:^0.13.5": + version: 0.13.5 + resolution: "@arethetypeswrong/cli@npm:0.13.5" dependencies: - "@arethetypeswrong/core": 0.13.0 + "@arethetypeswrong/core": 0.13.5 chalk: ^4.1.2 cli-table3: ^0.6.3 commander: ^10.0.1 @@ -276,20 +283,21 @@ __metadata: semver: ^7.5.4 bin: attw: dist/index.js - checksum: a200d2c5cd6f6245e4e2afa3a1ea98eb588a4d2a2cf7e6b76c92451d430c7c1bdcd5075e5ab6f9929dcdea36dd072fdcdb32ef085609e40c801ab40cbc96100b + checksum: 6fe8ff6f529bbdd9427172bfb8a796d741aa17d0ba50cfa402f68cca8d288c0ada2e96d5ed01590da4d035da755e6156476e74e3d4c9fdfac1328a882ba61559 languageName: node linkType: hard -"@arethetypeswrong/core@npm:0.13.0": - version: 0.13.0 - resolution: "@arethetypeswrong/core@npm:0.13.0" +"@arethetypeswrong/core@npm:0.13.5": + version: 0.13.5 + resolution: "@arethetypeswrong/core@npm:0.13.5" dependencies: "@andrewbranch/untar.js": ^1.0.3 fflate: ^0.7.4 semver: ^7.5.4 - typescript: ^5.2.2 + ts-expose-internals-conditionally: 1.0.0-empty.0 + typescript: 5.3.3 validate-npm-package-name: ^5.0.0 - checksum: cfe30a1ca0259ae6021971f155f9cba83a8329144eeac00164db680d4e46ad244b3f4bfb47b972bc19117dd3c72f2885e74b8cc1d1edc95e95960f090908efd6 + checksum: f44d99cd453668aa1b171ebc6a05f2e3745f599effabbafbbca702a2f87b449eb73b8ea1db25a268affdff561493f807ae18f58297b7116b1a19396568709a88 languageName: node linkType: hard @@ -366,6 +374,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-annotate-as-pure@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 53da330f1835c46f26b7bf4da31f7a496dee9fd8696cca12366b94ba19d97421ce519a74a837f687749318f94d1a37f8d1abcbf35e8ed22c32d16373b2f6198d + languageName: node + linkType: hard + "@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.16.7": version: 7.16.7 resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.16.7" @@ -417,6 +434,25 @@ __metadata: languageName: node linkType: hard +"@babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.23.6": + version: 7.23.7 + resolution: "@babel/helper-create-class-features-plugin@npm:7.23.7" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-member-expression-to-functions": ^7.23.0 + "@babel/helper-optimise-call-expression": ^7.22.5 + "@babel/helper-replace-supers": ^7.22.20 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + semver: ^6.3.1 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 33e60714b856c3816a7965d4c76278cc8f430644a2dfc4eeafad2f7167c4fbd2becdb74cbfeb04b02efd6bbd07176ef53c6683262b588e65d378438e9c55c26b + languageName: node + linkType: hard + "@babel/helper-create-regexp-features-plugin@npm:^7.16.7, @babel/helper-create-regexp-features-plugin@npm:^7.17.12": version: 7.17.12 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.17.12" @@ -482,6 +518,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-environment-visitor@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-environment-visitor@npm:7.22.20" + checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 + languageName: node + linkType: hard + "@babel/helper-explode-assignable-expression@npm:^7.16.7": version: 7.16.7 resolution: "@babel/helper-explode-assignable-expression@npm:7.16.7" @@ -510,6 +553,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" + dependencies: + "@babel/template": ^7.22.15 + "@babel/types": ^7.23.0 + checksum: e44542257b2d4634a1f979244eb2a4ad8e6d75eb6761b4cfceb56b562f7db150d134bc538c8e6adca3783e3bc31be949071527aa8e3aab7867d1ad2d84a26e10 + languageName: node + linkType: hard + "@babel/helper-hoist-variables@npm:^7.16.7, @babel/helper-hoist-variables@npm:^7.18.6": version: 7.18.6 resolution: "@babel/helper-hoist-variables@npm:7.18.6" @@ -528,6 +581,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-member-expression-to-functions@npm:^7.22.15, @babel/helper-member-expression-to-functions@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0" + dependencies: + "@babel/types": ^7.23.0 + checksum: 494659361370c979ada711ca685e2efe9460683c36db1b283b446122596602c901e291e09f2f980ecedfe6e0f2bd5386cb59768285446530df10c14df1024e75 + languageName: node + linkType: hard + "@babel/helper-module-imports@npm:^7.10.4, @babel/helper-module-imports@npm:^7.12.13, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.18.6": version: 7.18.6 resolution: "@babel/helper-module-imports@npm:7.18.6" @@ -537,6 +599,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-imports@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-module-imports@npm:7.22.15" + dependencies: + "@babel/types": ^7.22.15 + checksum: ecd7e457df0a46f889228f943ef9b4a47d485d82e030676767e6a2fdcbdaa63594d8124d4b55fd160b41c201025aec01fc27580352b1c87a37c9c6f33d116702 + languageName: node + linkType: hard + "@babel/helper-module-transforms@npm:^7.18.0, @babel/helper-module-transforms@npm:^7.18.6, @babel/helper-module-transforms@npm:^7.19.0": version: 7.19.0 resolution: "@babel/helper-module-transforms@npm:7.19.0" @@ -553,6 +624,21 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/helper-module-transforms@npm:7.23.3" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-simple-access": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + "@babel/helper-validator-identifier": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 5d0895cfba0e16ae16f3aa92fee108517023ad89a855289c4eb1d46f7aef4519adf8e6f971e1d55ac20c5461610e17213f1144097a8f932e768a9132e2278d71 + languageName: node + linkType: hard + "@babel/helper-optimise-call-expression@npm:^7.16.7, @babel/helper-optimise-call-expression@npm:^7.18.6": version: 7.18.6 resolution: "@babel/helper-optimise-call-expression@npm:7.18.6" @@ -562,6 +648,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-optimise-call-expression@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: c70ef6cc6b6ed32eeeec4482127e8be5451d0e5282d5495d5d569d39eb04d7f1d66ec99b327f45d1d5842a9ad8c22d48567e93fc502003a47de78d122e355f7c + languageName: node + linkType: hard + "@babel/helper-plugin-utils@npm:7.10.4": version: 7.10.4 resolution: "@babel/helper-plugin-utils@npm:7.10.4" @@ -583,6 +678,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-plugin-utils@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-plugin-utils@npm:7.22.5" + checksum: c0fc7227076b6041acd2f0e818145d2e8c41968cc52fb5ca70eed48e21b8fe6dd88a0a91cbddf4951e33647336eb5ae184747ca706817ca3bef5e9e905151ff5 + languageName: node + linkType: hard + "@babel/helper-remap-async-to-generator@npm:^7.16.8": version: 7.16.8 resolution: "@babel/helper-remap-async-to-generator@npm:7.16.8" @@ -634,6 +736,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-replace-supers@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-replace-supers@npm:7.22.20" + dependencies: + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-member-expression-to-functions": ^7.22.15 + "@babel/helper-optimise-call-expression": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: a0008332e24daedea2e9498733e3c39b389d6d4512637e000f96f62b797e702ee24a407ccbcd7a236a551590a38f31282829a8ef35c50a3c0457d88218cae639 + languageName: node + linkType: hard + "@babel/helper-simple-access@npm:^7.18.6": version: 7.18.6 resolution: "@babel/helper-simple-access@npm:7.18.6" @@ -643,6 +758,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-simple-access@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-simple-access@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: fe9686714caf7d70aedb46c3cce090f8b915b206e09225f1e4dbc416786c2fdbbee40b38b23c268b7ccef749dd2db35f255338fb4f2444429874d900dede5ad2 + languageName: node + linkType: hard + "@babel/helper-skip-transparent-expression-wrappers@npm:^7.16.0, @babel/helper-skip-transparent-expression-wrappers@npm:^7.18.9": version: 7.18.9 resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.18.9" @@ -652,6 +776,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.22.5" + dependencies: + "@babel/types": ^7.22.5 + checksum: 1012ef2295eb12dc073f2b9edf3425661e9b8432a3387e62a8bc27c42963f1f216ab3124228015c748770b2257b4f1fda882ca8fa34c0bf485e929ae5bc45244 + languageName: node + linkType: hard + "@babel/helper-split-export-declaration@npm:^7.16.7, @babel/helper-split-export-declaration@npm:^7.18.6": version: 7.18.6 resolution: "@babel/helper-split-export-declaration@npm:7.18.6" @@ -661,6 +794,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-split-export-declaration@npm:^7.22.6": + version: 7.22.6 + resolution: "@babel/helper-split-export-declaration@npm:7.22.6" + dependencies: + "@babel/types": ^7.22.5 + checksum: e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921 + languageName: node + linkType: hard + "@babel/helper-string-parser@npm:^7.18.10": version: 7.18.10 resolution: "@babel/helper-string-parser@npm:7.18.10" @@ -675,6 +817,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-validator-identifier@npm:7.22.20" + checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc + languageName: node + linkType: hard + "@babel/helper-validator-option@npm:^7.16.7, @babel/helper-validator-option@npm:^7.18.6": version: 7.18.6 resolution: "@babel/helper-validator-option@npm:7.18.6" @@ -682,6 +831,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-option@npm:^7.22.15": + version: 7.23.5 + resolution: "@babel/helper-validator-option@npm:7.23.5" + checksum: 537cde2330a8aede223552510e8a13e9c1c8798afee3757995a7d4acae564124fe2bf7e7c3d90d62d3657434a74340a274b3b3b1c6f17e9a2be1f48af29cb09e + languageName: node + linkType: hard + "@babel/helper-wrap-function@npm:^7.16.8": version: 7.16.8 resolution: "@babel/helper-wrap-function@npm:7.16.8" @@ -737,7 +893,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.0.0, @babel/parser@npm:^7.1.0, @babel/parser@npm:^7.13.16, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.18.10, @babel/parser@npm:^7.18.8, @babel/parser@npm:^7.19.3, @babel/parser@npm:^7.3.3": +"@babel/parser@npm:^7.0.0, @babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.18.10, @babel/parser@npm:^7.18.8, @babel/parser@npm:^7.19.3, @babel/parser@npm:^7.3.3": version: 7.19.4 resolution: "@babel/parser@npm:7.19.4" bin: @@ -746,6 +902,15 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0": + version: 7.23.6 + resolution: "@babel/parser@npm:7.23.6" + bin: + parser: ./bin/babel-parser.js + checksum: 140801c43731a6c41fd193f5c02bc71fd647a0360ca616b23d2db8be4b9739b9f951a03fc7c2db4f9b9214f4b27c1074db0f18bc3fa653783082d5af7c8860d5 + languageName: node + linkType: hard + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.17.12": version: 7.17.12 resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.17.12" @@ -833,7 +998,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-proposal-class-properties@npm:^7.0.0, @babel/plugin-proposal-class-properties@npm:^7.13.0, @babel/plugin-proposal-class-properties@npm:^7.16.0, @babel/plugin-proposal-class-properties@npm:^7.17.12, @babel/plugin-proposal-class-properties@npm:^7.18.6": +"@babel/plugin-proposal-class-properties@npm:^7.0.0, @babel/plugin-proposal-class-properties@npm:^7.16.0, @babel/plugin-proposal-class-properties@npm:^7.17.12, @babel/plugin-proposal-class-properties@npm:^7.18.6": version: 7.18.6 resolution: "@babel/plugin-proposal-class-properties@npm:7.18.6" dependencies: @@ -983,7 +1148,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-proposal-nullish-coalescing-operator@npm:^7.13.8, @babel/plugin-proposal-nullish-coalescing-operator@npm:^7.16.0, @babel/plugin-proposal-nullish-coalescing-operator@npm:^7.17.12, @babel/plugin-proposal-nullish-coalescing-operator@npm:^7.18.6": +"@babel/plugin-proposal-nullish-coalescing-operator@npm:^7.16.0, @babel/plugin-proposal-nullish-coalescing-operator@npm:^7.17.12, @babel/plugin-proposal-nullish-coalescing-operator@npm:^7.18.6": version: 7.18.6 resolution: "@babel/plugin-proposal-nullish-coalescing-operator@npm:7.18.6" dependencies: @@ -1086,7 +1251,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-proposal-optional-chaining@npm:^7.13.12, @babel/plugin-proposal-optional-chaining@npm:^7.16.0, @babel/plugin-proposal-optional-chaining@npm:^7.17.12, @babel/plugin-proposal-optional-chaining@npm:^7.18.9": +"@babel/plugin-proposal-optional-chaining@npm:^7.16.0, @babel/plugin-proposal-optional-chaining@npm:^7.17.12, @babel/plugin-proposal-optional-chaining@npm:^7.18.9": version: 7.18.9 resolution: "@babel/plugin-proposal-optional-chaining@npm:7.18.9" dependencies: @@ -1263,6 +1428,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-flow@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-flow@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c6e6f355d6ace5f4a9e7bb19f1fed2398aeb9b62c4c671a189d81b124f9f5bb77c4225b6e85e19339268c60a021c1e49104e450375de5e6bb70612190d9678af + languageName: node + linkType: hard + "@babel/plugin-syntax-import-assertions@npm:^7.17.12": version: 7.17.12 resolution: "@babel/plugin-syntax-import-assertions@npm:7.17.12" @@ -1340,6 +1516,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-jsx@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 89037694314a74e7f0e7a9c8d3793af5bf6b23d80950c29b360db1c66859d67f60711ea437e70ad6b5b4b29affe17eababda841b6c01107c2b638e0493bafb4e + languageName: node + linkType: hard + "@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4, @babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" @@ -1439,6 +1626,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-typescript@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: abfad3a19290d258b028e285a1f34c9b8a0cbe46ef79eafed4ed7ffce11b5d0720b5e536c82f91cbd8442cde35a3dd8e861fa70366d87ff06fdc0d4756e30876 + languageName: node + linkType: hard + "@babel/plugin-transform-arrow-functions@npm:^7.0.0, @babel/plugin-transform-arrow-functions@npm:^7.17.12": version: 7.17.12 resolution: "@babel/plugin-transform-arrow-functions@npm:7.17.12" @@ -1531,6 +1729,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-class-properties@npm:^7.22.5": + version: 7.23.3 + resolution: "@babel/plugin-transform-class-properties@npm:7.23.3" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9c6f8366f667897541d360246de176dd29efc7a13d80a5b48361882f7173d9173be4646c3b7d9b003ccc0e01e25df122330308f33db921fa553aa17ad544b3fc + languageName: node + linkType: hard + "@babel/plugin-transform-classes@npm:^7.0.0, @babel/plugin-transform-classes@npm:^7.17.12": version: 7.18.4 resolution: "@babel/plugin-transform-classes@npm:7.18.4" @@ -1694,6 +1904,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-flow-strip-types@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-flow-strip-types@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-flow": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: de38cc5cf948bc19405ea041292181527a36f59f08d787a590415fac36e9b0c7992f0d3e2fd3b9402089bafdaa1a893291a0edf15beebfd29bdedbbe582fee9b + languageName: node + linkType: hard + "@babel/plugin-transform-for-of@npm:^7.0.0, @babel/plugin-transform-for-of@npm:^7.18.1": version: 7.18.1 resolution: "@babel/plugin-transform-for-of@npm:7.18.1" @@ -1812,7 +2034,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.0.0, @babel/plugin-transform-modules-commonjs@npm:^7.13.8, @babel/plugin-transform-modules-commonjs@npm:^7.18.2, @babel/plugin-transform-modules-commonjs@npm:^7.18.6": +"@babel/plugin-transform-modules-commonjs@npm:^7.0.0, @babel/plugin-transform-modules-commonjs@npm:^7.18.2, @babel/plugin-transform-modules-commonjs@npm:^7.18.6": version: 7.18.6 resolution: "@babel/plugin-transform-modules-commonjs@npm:7.18.6" dependencies: @@ -1826,6 +2048,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-modules-commonjs@npm:^7.23.0, @babel/plugin-transform-modules-commonjs@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" + dependencies: + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-simple-access": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 720a231ceade4ae4d2632478db4e7fecf21987d444942b72d523487ac8d715ca97de6c8f415c71e939595e1a4776403e7dc24ed68fe9125ad4acf57753c9bff7 + languageName: node + linkType: hard + "@babel/plugin-transform-modules-systemjs@npm:^7.18.0": version: 7.18.4 resolution: "@babel/plugin-transform-modules-systemjs@npm:7.18.4" @@ -1926,6 +2161,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.11": + version: 7.23.4 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a27d73ea134d3d9560a6b2e26ab60012fba15f1db95865aa0153c18f5ec82cfef6a7b3d8df74e3c2fca81534fa5efeb6cacaf7b08bdb7d123e3dafdd079886a3 + languageName: node + linkType: hard + "@babel/plugin-transform-object-super@npm:^7.0.0, @babel/plugin-transform-object-super@npm:^7.16.7": version: 7.16.7 resolution: "@babel/plugin-transform-object-super@npm:7.16.7" @@ -1950,6 +2197,19 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-optional-chaining@npm:^7.23.0": + version: 7.23.4 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: e7a4c08038288057b7a08d68c4d55396ada9278095509ca51ed8dfb72a7f13f26bdd7c5185de21079fe0a9d60d22c227cb32e300d266c1bda40f70eee9f4bc1e + languageName: node + linkType: hard + "@babel/plugin-transform-parameters@npm:^7.0.0, @babel/plugin-transform-parameters@npm:^7.12.1, @babel/plugin-transform-parameters@npm:^7.17.12": version: 7.17.12 resolution: "@babel/plugin-transform-parameters@npm:7.17.12" @@ -1972,6 +2232,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-private-methods@npm:^7.22.5": + version: 7.23.3 + resolution: "@babel/plugin-transform-private-methods@npm:7.23.3" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: cedc1285c49b5a6d9a3d0e5e413b756ac40b3ac2f8f68bdfc3ae268bc8d27b00abd8bb0861c72756ff5dd8bf1eb77211b7feb5baf4fdae2ebbaabe49b9adc1d0 + languageName: node + linkType: hard + "@babel/plugin-transform-property-literals@npm:^7.0.0, @babel/plugin-transform-property-literals@npm:^7.16.7": version: 7.16.7 resolution: "@babel/plugin-transform-property-literals@npm:7.16.7" @@ -2306,6 +2578,20 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-typescript@npm:^7.23.3": + version: 7.23.6 + resolution: "@babel/plugin-transform-typescript@npm:7.23.6" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-create-class-features-plugin": ^7.23.6 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-typescript": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 0462241843d14dff9f1a4c49ab182a6f01a5f7679957c786b08165dac3e8d49184011f05ca204183d164c54b9d3496d1b3005f904fa8708e394e6f15bf5548e6 + languageName: node + linkType: hard + "@babel/plugin-transform-unicode-escapes@npm:^7.16.7": version: 7.16.7 resolution: "@babel/plugin-transform-unicode-escapes@npm:7.16.7" @@ -2522,7 +2808,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-flow@npm:^7.12.1, @babel/preset-flow@npm:^7.13.13": +"@babel/preset-flow@npm:^7.12.1": version: 7.18.6 resolution: "@babel/preset-flow@npm:7.18.6" dependencies: @@ -2535,6 +2821,19 @@ __metadata: languageName: node linkType: hard +"@babel/preset-flow@npm:^7.22.15": + version: 7.23.3 + resolution: "@babel/preset-flow@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.22.15 + "@babel/plugin-transform-flow-strip-types": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 60b5dde79621ae89943af459c4dc5b6030795f595a20ca438c8100f8d82c9ebc986881719030521ff5925799518ac5aa7f3fe62af8c33ab96be3681a71f88d03 + languageName: node + linkType: hard + "@babel/preset-modules@npm:^0.1.5": version: 0.1.5 resolution: "@babel/preset-modules@npm:0.1.5" @@ -2582,7 +2881,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-typescript@npm:^7.12.7, @babel/preset-typescript@npm:^7.13.0, @babel/preset-typescript@npm:^7.15.0, @babel/preset-typescript@npm:^7.16.0, @babel/preset-typescript@npm:^7.18.6": +"@babel/preset-typescript@npm:^7.12.7, @babel/preset-typescript@npm:^7.15.0, @babel/preset-typescript@npm:^7.16.0, @babel/preset-typescript@npm:^7.18.6": version: 7.18.6 resolution: "@babel/preset-typescript@npm:7.18.6" dependencies: @@ -2595,18 +2894,33 @@ __metadata: languageName: node linkType: hard -"@babel/register@npm:^7.13.16": - version: 7.18.9 - resolution: "@babel/register@npm:7.18.9" +"@babel/preset-typescript@npm:^7.23.0": + version: 7.23.3 + resolution: "@babel/preset-typescript@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.22.15 + "@babel/plugin-syntax-jsx": ^7.23.3 + "@babel/plugin-transform-modules-commonjs": ^7.23.3 + "@babel/plugin-transform-typescript": ^7.23.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 105a2d39bbc464da0f7e1ad7f535c77c5f62d6b410219355b20e552e7d29933567a5c55339b5d0aec1a5c7a0a7dfdf1b54aae601a4fe15a157d54dcbfcb3e854 + languageName: node + linkType: hard + +"@babel/register@npm:^7.22.15": + version: 7.23.7 + resolution: "@babel/register@npm:7.23.7" dependencies: clone-deep: ^4.0.1 find-cache-dir: ^2.0.0 make-dir: ^2.1.0 - pirates: ^4.0.5 + pirates: ^4.0.6 source-map-support: ^0.5.16 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 4aeaff97e061a397f632659082ba86c539ef8194697b236d991c10d1c2ea8f73213d3b5b3b2c24625951a1ef726b7a7d2e70f70ffcb37f79ef0c1a745eebef21 + checksum: c72a6d4856ef04f13490370d805854d2d98a77786bfaec7d85e2c585e1217011c4f3df18197a890e14520906c9111bef95551ba1a9b59c88df4dfc2dfe2c8d1b languageName: node linkType: hard @@ -2659,6 +2973,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/template@npm:7.22.15" + dependencies: + "@babel/code-frame": ^7.22.13 + "@babel/parser": ^7.22.15 + "@babel/types": ^7.22.15 + checksum: 1f3e7dcd6c44f5904c184b3f7fe280394b191f2fed819919ffa1e529c259d5b197da8981b6ca491c235aee8dbad4a50b7e31304aa531271cb823a4a24a0dd8fd + languageName: node + linkType: hard + "@babel/traverse@npm:7.19.3": version: 7.19.3 resolution: "@babel/traverse@npm:7.19.3" @@ -2695,6 +3020,24 @@ __metadata: languageName: node linkType: hard +"@bundled-es-modules/cookie@npm:^2.0.0": + version: 2.0.0 + resolution: "@bundled-es-modules/cookie@npm:2.0.0" + dependencies: + cookie: ^0.5.0 + checksum: 53114eabbedda20ba6c63f45dcea35c568616d22adf5d1882cef9761f65ae636bf47e0c66325572cc8e3a335e0257caf5f76ff1287990d9e9265be7bc9767a87 + languageName: node + linkType: hard + +"@bundled-es-modules/statuses@npm:^1.0.1": + version: 1.0.1 + resolution: "@bundled-es-modules/statuses@npm:1.0.1" + dependencies: + statuses: ^2.0.1 + checksum: bcaa7de192e73056950b5fd20e75140d8d09074b1adc4437924b2051bb02b4dbf568c96e67d53b220fb7d735c3446e2ba746599cb1793ab2d23dd2ef230a8622 + languageName: node + linkType: hard + "@chakra-ui/accordion@npm:1.0.0": version: 1.0.0 resolution: "@chakra-ui/accordion@npm:1.0.0" @@ -4730,7 +5073,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.4.0": +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" dependencies: @@ -4741,7 +5084,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.5.1": +"@eslint-community/regexpp@npm:^4.4.0, @eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": version: 4.10.0 resolution: "@eslint-community/regexpp@npm:4.10.0" checksum: 2a6e345429ea8382aaaf3a61f865cae16ed44d31ca917910033c02dc00d505d939f10b81e079fa14d43b51499c640138e153b7e40743c4c094d9df97d4e56f7b @@ -4782,6 +5125,30 @@ __metadata: languageName: node linkType: hard +"@eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" + dependencies: + ajv: ^6.12.4 + debug: ^4.3.2 + espree: ^9.6.0 + globals: ^13.19.0 + ignore: ^5.2.0 + import-fresh: ^3.2.1 + js-yaml: ^4.1.0 + minimatch: ^3.1.2 + strip-json-comments: ^3.1.1 + checksum: 10957c7592b20ca0089262d8c2a8accbad14b4f6507e35416c32ee6b4dbf9cad67dfb77096bbd405405e9ada2b107f3797fe94362e1c55e0b09d6e90dd149127 + languageName: node + linkType: hard + +"@eslint/js@npm:8.56.0": + version: 8.56.0 + resolution: "@eslint/js@npm:8.56.0" + checksum: 5804130574ef810207bdf321c265437814e7a26f4e6fac9b496de3206afd52f533e09ec002a3be06cd9adcc9da63e727f1883938e663c4e4751c007d5b58e539 + languageName: node + linkType: hard + "@examples-action-listener/counter@workspace:examples/action-listener/counter": version: 0.0.0-use.local resolution: "@examples-action-listener/counter@workspace:examples/action-listener/counter" @@ -5183,77 +5550,6 @@ __metadata: languageName: node linkType: hard -"@glimmer/env@npm:0.1.7, @glimmer/env@npm:^0.1.7": - version: 0.1.7 - resolution: "@glimmer/env@npm:0.1.7" - checksum: d46686da1b21615c177792794ed11f725fbb1c32936d69ca54a3ac40e2314638a529b81afb23759d35cdf36462a7a6b2c02604a366473cd6a8abadfe56e9c335 - languageName: node - linkType: hard - -"@glimmer/global-context@npm:0.62.5": - version: 0.62.5 - resolution: "@glimmer/global-context@npm:0.62.5" - dependencies: - "@glimmer/env": ^0.1.7 - checksum: f60e893e9ace9536713694ddd82147fa2e8ae7106617bec661ba229af718c56fc8843e2e4afef57e9ebd77b6b7a7b9c15ca533d2ddb939febae341d2bd72aca6 - languageName: node - linkType: hard - -"@glimmer/interfaces@npm:0.62.5": - version: 0.62.5 - resolution: "@glimmer/interfaces@npm:0.62.5" - dependencies: - "@simple-dom/interface": ^1.4.0 - checksum: 9d726916324cb1eff40f9b14b562bddeb4146c57b688ec06d399294818b44c44cc0c05ae178d3d0bd3f872f27513ea646335e387d6c7a7c6ab3e2fba78f30524 - languageName: node - linkType: hard - -"@glimmer/reference@npm:^0.62.4": - version: 0.62.5 - resolution: "@glimmer/reference@npm:0.62.5" - dependencies: - "@glimmer/env": ^0.1.7 - "@glimmer/global-context": 0.62.5 - "@glimmer/interfaces": 0.62.5 - "@glimmer/util": 0.62.5 - "@glimmer/validator": 0.62.5 - checksum: 009a573c60b0cc026903a57716ae1a700ff3d1078e14618805fff0416b791a0465b7f5af03d57855b01aa9cb1e17e945fe9c05c015dd46a50faa1248d1342375 - languageName: node - linkType: hard - -"@glimmer/syntax@npm:^0.62.4": - version: 0.62.5 - resolution: "@glimmer/syntax@npm:0.62.5" - dependencies: - "@glimmer/interfaces": 0.62.5 - "@glimmer/util": 0.62.5 - "@handlebars/parser": ^1.1.0 - simple-html-tokenizer: ^0.5.10 - checksum: 1a69f1aa6bd51e9e2e5f39ce2e2ccd4bc7b3e7e4e1c91ccf4527c8bd16d5f1f99d02f60e0ec2e8eb2762d75dd07a5a5793e724c09c97680c81908d5acf9b03f8 - languageName: node - linkType: hard - -"@glimmer/util@npm:0.62.5": - version: 0.62.5 - resolution: "@glimmer/util@npm:0.62.5" - dependencies: - "@glimmer/env": 0.1.7 - "@glimmer/interfaces": 0.62.5 - "@simple-dom/interface": ^1.4.0 - checksum: 38fd1578f9985803b8ad858bb259cba223ee1ecdd308c73ccc043da1e62fa0d1f10bc4aa10de860e417f27d1d8aa98f0c1cec10322ee9f1f9423edae6a3d6fb6 - languageName: node - linkType: hard - -"@glimmer/validator@npm:0.62.5, @glimmer/validator@npm:^0.62.4": - version: 0.62.5 - resolution: "@glimmer/validator@npm:0.62.5" - dependencies: - "@glimmer/env": ^0.1.7 - "@glimmer/global-context": 0.62.5 - checksum: 58559481b35a2684c421b7fe98f5e21f660bbf37aa3abd65e27b49183a16f14ac93bfe87acef6d88951d3d8778de7afe2871eedd2822583e75f292460f4f57c8 - languageName: node - linkType: hard - "@graphql-codegen/add@npm:^2.0.2": version: 2.0.2 resolution: "@graphql-codegen/add@npm:2.0.2" @@ -5822,13 +6118,6 @@ __metadata: languageName: node linkType: hard -"@handlebars/parser@npm:^1.1.0": - version: 1.1.0 - resolution: "@handlebars/parser@npm:1.1.0" - checksum: f1ded58182780e1fdc0a9d40fe8485785118f7cf684210d538ea3847198d454cb2c122fd1849dfde545aba69502b382c4711cb084c82ca96c1f313178528dd17 - languageName: node - linkType: hard - "@hapi/hoek@npm:^9.0.0": version: 9.2.0 resolution: "@hapi/hoek@npm:9.2.0" @@ -5845,6 +6134,17 @@ __metadata: languageName: node linkType: hard +"@humanwhocodes/config-array@npm:^0.11.13": + version: 0.11.14 + resolution: "@humanwhocodes/config-array@npm:0.11.14" + dependencies: + "@humanwhocodes/object-schema": ^2.0.2 + debug: ^4.3.1 + minimatch: ^3.0.5 + checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 + languageName: node + linkType: hard + "@humanwhocodes/config-array@npm:^0.9.2": version: 0.9.5 resolution: "@humanwhocodes/config-array@npm:0.9.5" @@ -5856,6 +6156,13 @@ __metadata: languageName: node linkType: hard +"@humanwhocodes/module-importer@npm:^1.0.1": + version: 1.0.1 + resolution: "@humanwhocodes/module-importer@npm:1.0.1" + checksum: 0fd22007db8034a2cdf2c764b140d37d9020bbfce8a49d3ec5c05290e77d4b0263b1b972b752df8c89e5eaa94073408f2b7d977aed131faf6cf396ebb5d7fb61 + languageName: node + linkType: hard + "@humanwhocodes/object-schema@npm:^1.2.1": version: 1.2.1 resolution: "@humanwhocodes/object-schema@npm:1.2.1" @@ -5863,6 +6170,13 @@ __metadata: languageName: node linkType: hard +"@humanwhocodes/object-schema@npm:^2.0.2": + version: 2.0.2 + resolution: "@humanwhocodes/object-schema@npm:2.0.2" + checksum: 2fc11503361b5fb4f14714c700c02a3f4c7c93e9acd6b87a29f62c522d90470f364d6161b03d1cc618b979f2ae02aed1106fd29d302695d8927e2fc8165ba8ee + languageName: node + linkType: hard + "@iarna/toml@npm:2.2.5, @iarna/toml@npm:^2.2.5": version: 2.2.5 resolution: "@iarna/toml@npm:2.2.5" @@ -6498,7 +6812,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.13, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15": +"@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15": version: 1.4.15 resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 @@ -6667,6 +6981,16 @@ __metadata: languageName: node linkType: hard +"@mswjs/cookies@npm:^0.1.4": + version: 0.1.7 + resolution: "@mswjs/cookies@npm:0.1.7" + dependencies: + "@types/set-cookie-parser": ^2.4.0 + set-cookie-parser: ^2.4.6 + checksum: d9b152dfdeba08b282a236485610bcfe992626e3c638fe51ebc5c7b5273d41d74e5447ae556a6c76460a8d3c7a7de6f544c681232cb50ae05b6b1e112bb77286 + languageName: node + linkType: hard + "@mswjs/cookies@npm:^0.2.0": version: 0.2.0 resolution: "@mswjs/cookies@npm:0.2.0" @@ -6677,6 +7001,13 @@ __metadata: languageName: node linkType: hard +"@mswjs/cookies@npm:^1.1.0": + version: 1.1.0 + resolution: "@mswjs/cookies@npm:1.1.0" + checksum: 1d9be44548907b92ff6acd46795292968661be19f1c04c43fdb2beb98bc7e58b8ffcef3be19d0f2cb58df07a36a6b53b4bbc0ea34e023b7366dbc28ffee90338 + languageName: node + linkType: hard + "@mswjs/data@npm:^0.3.0": version: 0.3.0 resolution: "@mswjs/data@npm:0.3.0" @@ -6733,6 +7064,32 @@ __metadata: languageName: node linkType: hard +"@mswjs/interceptors@npm:^0.25.14": + version: 0.25.14 + resolution: "@mswjs/interceptors@npm:0.25.14" + dependencies: + "@open-draft/deferred-promise": ^2.2.0 + "@open-draft/logger": ^0.3.0 + "@open-draft/until": ^2.0.0 + is-node-process: ^1.2.0 + outvariant: ^1.2.1 + strict-event-emitter: ^0.5.1 + checksum: caf9513cf6848ff0c3f1402abf881d3c1333f68fae54076cfd3fd919b7edb709769342bd3afd2a60ef4ae698ef47776b6203e0ea6a5d8e788e97eda7ed9dbbd4 + languageName: node + linkType: hard + +"@mswjs/interceptors@npm:^0.8.0": + version: 0.8.1 + resolution: "@mswjs/interceptors@npm:0.8.1" + dependencies: + "@open-draft/until": ^1.0.3 + debug: ^4.3.0 + headers-utils: ^3.0.2 + strict-event-emitter: ^0.2.0 + checksum: cb4aaf4d83b0f12560f856952a4fa12b77cc50d273da08823b8a7c4a89602a770b0143823f1dcb38832c9a8fc064c9497c455f6079656fcf113b80561b3488a8 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -6760,6 +7117,16 @@ __metadata: languageName: node linkType: hard +"@nodelib/fs.walk@npm:^1.2.8": + version: 1.2.8 + resolution: "@nodelib/fs.walk@npm:1.2.8" + dependencies: + "@nodelib/fs.scandir": 2.1.5 + fastq: ^1.6.0 + checksum: 190c643f156d8f8f277bf2a6078af1ffde1fd43f498f187c2db24d35b4b4b5785c02c7dc52e356497b9a1b65b13edc996de08de0b961c32844364da02986dc53 + languageName: node + linkType: hard + "@npmcli/move-file@npm:^1.0.1": version: 1.1.2 resolution: "@npmcli/move-file@npm:1.1.2" @@ -6901,10 +7268,34 @@ __metadata: languageName: node linkType: hard -"@open-draft/until@npm:^1.0.3": - version: 1.0.3 - resolution: "@open-draft/until@npm:1.0.3" - checksum: 323e92ebef0150ed0f8caedc7d219b68cdc50784fa4eba0377eef93533d3f46514eb2400ced83dda8c51bddc3d2c7b8e9cf95e5ec85ab7f62dfc015d174f62f2 +"@open-draft/deferred-promise@npm:^2.2.0": + version: 2.2.0 + resolution: "@open-draft/deferred-promise@npm:2.2.0" + checksum: 7f29d39725bb8ab5b62f89d88a4202ce2439ac740860979f9e3d0015dfe4bc3daddcfa5727fa4eed482fdbee770aa591b1136b98b0a0f0569a65294f35bdf56a + languageName: node + linkType: hard + +"@open-draft/logger@npm:^0.3.0": + version: 0.3.0 + resolution: "@open-draft/logger@npm:0.3.0" + dependencies: + is-node-process: ^1.2.0 + outvariant: ^1.4.0 + checksum: 7adfe3d0ed8ca32333ce2a77f9a93d561ebc89c989eaa9722f1dc8a2d2854f5de1bef6fa6894cdf58e16fa4dd9cfa99444ea1f5cac6eb1518e9247911ed042d5 + languageName: node + linkType: hard + +"@open-draft/until@npm:^1.0.3": + version: 1.0.3 + resolution: "@open-draft/until@npm:1.0.3" + checksum: 323e92ebef0150ed0f8caedc7d219b68cdc50784fa4eba0377eef93533d3f46514eb2400ced83dda8c51bddc3d2c7b8e9cf95e5ec85ab7f62dfc015d174f62f2 + languageName: node + linkType: hard + +"@open-draft/until@npm:^2.0.0, @open-draft/until@npm:^2.1.0": + version: 2.1.0 + resolution: "@open-draft/until@npm:2.1.0" + checksum: 140ea3b16f4a3a6a729c1256050e20a93d408d7aa1e125648ce2665b3c526ed452510c6e4a6f4b15d95fb5e41203fb51510eb8fbc8812d5e5a91880293d66471 languageName: node linkType: hard @@ -6915,6 +7306,13 @@ __metadata: languageName: node linkType: hard +"@pkgr/core@npm:^0.1.0": + version: 0.1.1 + resolution: "@pkgr/core@npm:0.1.1" + checksum: 6f25fd2e3008f259c77207ac9915b02f1628420403b2630c92a07ff963129238c9262afc9e84344c7a23b5cc1f3965e2cd17e3798219f5fd78a63d144d3cceba + languageName: node + linkType: hard + "@pmmmwh/react-refresh-webpack-plugin@npm:^0.5.3": version: 0.5.7 resolution: "@pmmmwh/react-refresh-webpack-plugin@npm:0.5.7" @@ -7026,15 +7424,19 @@ __metadata: version: 0.0.0-use.local resolution: "@reduxjs/rtk-codemods@workspace:packages/rtk-codemods" dependencies: - "@types/jscodeshift": ^0.11.5 - codemod-cli: ^3.2.0 - eslint: ^7.25.0 - eslint-config-prettier: ^8.3.0 + "@types/jscodeshift": ^0.11.11 + "@typescript-eslint/parser": ^6.19.1 + eslint: ^8.56.0 + eslint-config-prettier: ^9.1.0 eslint-plugin-node: ^11.1.0 - eslint-plugin-prettier: ^3.4.0 - prettier: ^2.2.1 - typescript: ^4.8.0 - vitest: ^0.30.1 + eslint-plugin-prettier: ^5.1.3 + execa: ^8.0.1 + globby: ^14.0.0 + jscodeshift: ^0.15.1 + prettier: ^3.2.4 + ts-node: ^10.9.2 + typescript: ^5.3.3 + vitest: ^1.2.1 bin: rtk-codemods: ./bin/cli.js languageName: unknown @@ -7044,7 +7446,7 @@ __metadata: version: 0.0.0-use.local resolution: "@reduxjs/toolkit@workspace:packages/toolkit" dependencies: - "@arethetypeswrong/cli": ^0.13.1 + "@arethetypeswrong/cli": ^0.13.5 "@microsoft/api-extractor": ^7.13.2 "@phryneas/ts-version": ^1.0.2 "@size-limit/file": ^11.0.1 @@ -7064,12 +7466,12 @@ __metadata: console-testing-library: 0.6.1 esbuild-extra: ^0.3.1 eslint: ^7.25.0 - eslint-config-prettier: ^8.3.0 + eslint-config-prettier: ^9.1.0 eslint-config-react-app: ^7.0.1 eslint-plugin-flowtype: ^5.7.2 eslint-plugin-import: ^2.22.1 eslint-plugin-jsx-a11y: ^6.4.1 - eslint-plugin-prettier: ^3.4.0 + eslint-plugin-prettier: ^5.1.3 eslint-plugin-react: ^7.23.2 eslint-plugin-react-hooks: ^4.2.0 fs-extra: ^9.1.0 @@ -7077,9 +7479,9 @@ __metadata: invariant: ^2.2.4 jsdom: ^21.0.0 json-stringify-safe: ^5.0.1 - msw: ^0.40.2 - node-fetch: ^2.6.1 - prettier: ^2.2.1 + msw: ^2.1.4 + node-fetch: ^3.3.2 + prettier: ^3.2.4 query-string: ^7.0.1 redux: ^5.0.1 redux-thunk: ^3.1.0 @@ -7089,7 +7491,7 @@ __metadata: tslib: ^1.10.0 tsup: ^7.2.0 tsx: ^3.12.2 - typescript: 5.2 + typescript: ^5.3.3 vitest: ^1.1.3 yargs: ^15.3.1 peerDependencies: @@ -7470,13 +7872,6 @@ __metadata: languageName: node linkType: hard -"@simple-dom/interface@npm:^1.4.0": - version: 1.4.0 - resolution: "@simple-dom/interface@npm:1.4.0" - checksum: e0ce8b6174208c5a369c2650094d16080230bf90cb95cc8258f9fd6b93be8afedbffb9d63da7f1d295a4e8d901f5fff907a69e1d55556db9e8544f2615b2f1d7 - languageName: node - linkType: hard - "@sinclair/typebox@npm:^0.23.3": version: 0.23.5 resolution: "@sinclair/typebox@npm:0.23.5" @@ -8095,22 +8490,6 @@ __metadata: languageName: node linkType: hard -"@types/chai-subset@npm:^1.3.3": - version: 1.3.3 - resolution: "@types/chai-subset@npm:1.3.3" - dependencies: - "@types/chai": "*" - checksum: 4481da7345022995f5a105e6683744f7203d2c3d19cfe88d8e17274d045722948abf55e0adfd97709e0f043dade37a4d4e98cd4c660e2e8a14f23e6ecf79418f - languageName: node - linkType: hard - -"@types/chai@npm:*, @types/chai@npm:^4.3.4": - version: 4.3.4 - resolution: "@types/chai@npm:4.3.4" - checksum: 571184967beb03bf64c4392a13a7d44e72da9af5a1e83077ff81c39cf59c0fda2a5c78d2005084601cf8f3d11726608574d8b5b4a0e3e9736792807afd926cd0 - languageName: node - linkType: hard - "@types/commander@npm:^2.12.2": version: 2.12.2 resolution: "@types/commander@npm:2.12.2" @@ -8139,13 +8518,20 @@ __metadata: languageName: node linkType: hard -"@types/cookie@npm:^0.4.1": +"@types/cookie@npm:^0.4.0, @types/cookie@npm:^0.4.1": version: 0.4.1 resolution: "@types/cookie@npm:0.4.1" checksum: 3275534ed69a76c68eb1a77d547d75f99fedc80befb75a3d1d03662fb08d697e6f8b1274e12af1a74c6896071b11510631ba891f64d30c78528d0ec45a9c1a18 languageName: node linkType: hard +"@types/cookie@npm:^0.6.0": + version: 0.6.0 + resolution: "@types/cookie@npm:0.6.0" + checksum: 5edce7995775b0b196b142883e4d4f71fd93c294eaec973670f1fa2540b70ea7390408ed513ddefef5fcb12a578100c76596e8f2a714b0c2ae9f70ee773f4510 + languageName: node + linkType: hard + "@types/eslint-scope@npm:^3.7.3": version: 3.7.3 resolution: "@types/eslint-scope@npm:3.7.3" @@ -8300,6 +8686,16 @@ __metadata: languageName: node linkType: hard +"@types/inquirer@npm:8.2.1": + version: 8.2.1 + resolution: "@types/inquirer@npm:8.2.1" + dependencies: + "@types/through": "*" + rxjs: ^7.2.0 + checksum: 5362d0b1cbec3887c9d5a671a0b19c58cf54066456c8967dd7ee799dfcc242cc8cd8959440c0f2fe7768becaf721b45fd30c222e6b9bcca378f45c68af43bab5 + languageName: node + linkType: hard + "@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": version: 2.0.3 resolution: "@types/istanbul-lib-coverage@npm:2.0.3" @@ -8345,6 +8741,13 @@ __metadata: languageName: node linkType: hard +"@types/js-levenshtein@npm:^1.1.0": + version: 1.1.3 + resolution: "@types/js-levenshtein@npm:1.1.3" + checksum: eb338696da976925ea8448a42d775d7615a14323dceeb08909f187d0b3d3b4c1f67a1c36ef586b1c2318b70ab141bba8fc58311ba1c816711704605aec09db8b + languageName: node + linkType: hard + "@types/js-levenshtein@npm:^1.1.1": version: 1.1.1 resolution: "@types/js-levenshtein@npm:1.1.1" @@ -8359,13 +8762,13 @@ __metadata: languageName: node linkType: hard -"@types/jscodeshift@npm:^0.11.5": - version: 0.11.5 - resolution: "@types/jscodeshift@npm:0.11.5" +"@types/jscodeshift@npm:^0.11.11": + version: 0.11.11 + resolution: "@types/jscodeshift@npm:0.11.11" dependencies: ast-types: ^0.14.1 recast: ^0.20.3 - checksum: 5929f729477792a2c745289399ac0e2c0c46d4970031fa188073154262c6b0fcb03cf926d70a9fbcdc4c299df0e7fa1f0d6548e6bd1bb03c8245918c5b1a60de + checksum: 6224b781cbbc8e095cae3cb8f9dd1ca102d6c42d9c882b76ea84dfd0cd43870ce317369480ed6b593352efe9fe7199bd6c40ec2cb37646c474ba15f5b43d2109 languageName: node linkType: hard @@ -8688,6 +9091,13 @@ __metadata: languageName: node linkType: hard +"@types/semver@npm:^7.3.12, @types/semver@npm:^7.5.0": + version: 7.5.6 + resolution: "@types/semver@npm:7.5.6" + checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 + languageName: node + linkType: hard + "@types/semver@npm:^7.3.9": version: 7.3.9 resolution: "@types/semver@npm:7.3.9" @@ -8695,13 +9105,6 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:^7.5.0": - version: 7.5.6 - resolution: "@types/semver@npm:7.5.6" - checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 - languageName: node - linkType: hard - "@types/serve-index@npm:^1.9.1": version: 1.9.1 resolution: "@types/serve-index@npm:1.9.1" @@ -8746,6 +9149,13 @@ __metadata: languageName: node linkType: hard +"@types/statuses@npm:^2.0.4": + version: 2.0.4 + resolution: "@types/statuses@npm:2.0.4" + checksum: 3a806c3b96d1845e3e7441fbf0839037e95f717334760ddb7c29223c9a34a7206b68e2998631f89f1a1e3ef5b67b15652f6e8fa14987ebd7f6d38587c1bffd18 + languageName: node + linkType: hard + "@types/testing-library__jest-dom@npm:^5.9.1": version: 5.14.3 resolution: "@types/testing-library__jest-dom@npm:5.14.3" @@ -8755,6 +9165,15 @@ __metadata: languageName: node linkType: hard +"@types/through@npm:*": + version: 0.0.33 + resolution: "@types/through@npm:0.0.33" + dependencies: + "@types/node": "*" + checksum: fd0b73f873a64ed5366d1d757c42e5dbbb2201002667c8958eda7ca02fff09d73de91360572db465ee00240c32d50c6039ea736d8eca374300f9664f93e8da39 + languageName: node + linkType: hard + "@types/tinycolor2@npm:1.4.2": version: 1.4.2 resolution: "@types/tinycolor2@npm:1.4.2" @@ -8881,6 +9300,55 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/eslint-plugin@npm:^5.5.0": + version: 5.62.0 + resolution: "@typescript-eslint/eslint-plugin@npm:5.62.0" + dependencies: + "@eslint-community/regexpp": ^4.4.0 + "@typescript-eslint/scope-manager": 5.62.0 + "@typescript-eslint/type-utils": 5.62.0 + "@typescript-eslint/utils": 5.62.0 + debug: ^4.3.4 + graphemer: ^1.4.0 + ignore: ^5.2.0 + natural-compare-lite: ^1.4.0 + semver: ^7.3.7 + tsutils: ^3.21.0 + peerDependencies: + "@typescript-eslint/parser": ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: fc104b389c768f9fa7d45a48c86d5c1ad522c1d0512943e782a56b1e3096b2cbcc1eea3fcc590647bf0658eef61aac35120a9c6daf979bf629ad2956deb516a1 + languageName: node + linkType: hard + +"@typescript-eslint/eslint-plugin@npm:^6": + version: 6.19.1 + resolution: "@typescript-eslint/eslint-plugin@npm:6.19.1" + dependencies: + "@eslint-community/regexpp": ^4.5.1 + "@typescript-eslint/scope-manager": 6.19.1 + "@typescript-eslint/type-utils": 6.19.1 + "@typescript-eslint/utils": 6.19.1 + "@typescript-eslint/visitor-keys": 6.19.1 + debug: ^4.3.4 + graphemer: ^1.4.0 + ignore: ^5.2.4 + natural-compare: ^1.4.0 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependencies: + "@typescript-eslint/parser": ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: ad04000cd6c15d864ff92655baa3aec99bb0ccf4714fedd145fedde60a27590a5feafe480beb2f0f3864b416098bde1e9431bada7480eb7ca4efad891e1d2f6f + languageName: node + linkType: hard + "@typescript-eslint/experimental-utils@npm:^5.0.0": version: 5.27.1 resolution: "@typescript-eslint/experimental-utils@npm:5.27.1" @@ -8910,6 +9378,41 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/parser@npm:^5.5.0": + version: 5.62.0 + resolution: "@typescript-eslint/parser@npm:5.62.0" + dependencies: + "@typescript-eslint/scope-manager": 5.62.0 + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/typescript-estree": 5.62.0 + debug: ^4.3.4 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: d168f4c7f21a7a63f47002e2d319bcbb6173597af5c60c1cf2de046b46c76b4930a093619e69faf2d30214c29ab27b54dcf1efc7046a6a6bd6f37f59a990e752 + languageName: node + linkType: hard + +"@typescript-eslint/parser@npm:^6, @typescript-eslint/parser@npm:^6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/parser@npm:6.19.1" + dependencies: + "@typescript-eslint/scope-manager": 6.19.1 + "@typescript-eslint/types": 6.19.1 + "@typescript-eslint/typescript-estree": 6.19.1 + "@typescript-eslint/visitor-keys": 6.19.1 + debug: ^4.3.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: cd29619da08a2d9b7123ba4d8240989c747f8e0d5672179d8b147e413ee1334d1fa48570b0c37cf0ae4e26a275fd2d268cbe702c6fed639d3331abbb3292570a + languageName: node + linkType: hard + "@typescript-eslint/scope-manager@npm:5.27.1": version: 5.27.1 resolution: "@typescript-eslint/scope-manager@npm:5.27.1" @@ -8920,6 +9423,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/scope-manager@npm:5.62.0" + dependencies: + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/visitor-keys": 5.62.0 + checksum: 6062d6b797fe1ce4d275bb0d17204c827494af59b5eaf09d8a78cdd39dadddb31074dded4297aaf5d0f839016d601032857698b0e4516c86a41207de606e9573 + languageName: node + linkType: hard + "@typescript-eslint/scope-manager@npm:6.12.0": version: 6.12.0 resolution: "@typescript-eslint/scope-manager@npm:6.12.0" @@ -8930,6 +9443,33 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/scope-manager@npm:6.19.1" + dependencies: + "@typescript-eslint/types": 6.19.1 + "@typescript-eslint/visitor-keys": 6.19.1 + checksum: 848cdebc16a3803e8a6d6035a7067605309a652bb2425f475f755b5ace4d80d2c17c8c8901f0f4759556da8d0a5b71024d472b85c3f3c70d0e6dcfe2a972ef35 + languageName: node + linkType: hard + +"@typescript-eslint/type-utils@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/type-utils@npm:5.62.0" + dependencies: + "@typescript-eslint/typescript-estree": 5.62.0 + "@typescript-eslint/utils": 5.62.0 + debug: ^4.3.4 + tsutils: ^3.21.0 + peerDependencies: + eslint: "*" + peerDependenciesMeta: + typescript: + optional: true + checksum: fc41eece5f315dfda14320be0da78d3a971d650ea41300be7196934b9715f3fe1120a80207551eb71d39568275dbbcf359bde540d1ca1439d8be15e9885d2739 + languageName: node + linkType: hard + "@typescript-eslint/type-utils@npm:6.12.0": version: 6.12.0 resolution: "@typescript-eslint/type-utils@npm:6.12.0" @@ -8947,6 +9487,23 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/type-utils@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/type-utils@npm:6.19.1" + dependencies: + "@typescript-eslint/typescript-estree": 6.19.1 + "@typescript-eslint/utils": 6.19.1 + debug: ^4.3.4 + ts-api-utils: ^1.0.1 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: eab1a30f8d85f7c6e2545de5963fbec2f3bb91913d59623069b4b0db372a671ab048c7018376fc853c3af06ea39417f3e7b27dd665027dd812347a5e64cecd77 + languageName: node + linkType: hard + "@typescript-eslint/types@npm:5.27.1": version: 5.27.1 resolution: "@typescript-eslint/types@npm:5.27.1" @@ -8954,6 +9511,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/types@npm:5.62.0" + checksum: 48c87117383d1864766486f24de34086155532b070f6264e09d0e6139449270f8a9559cfef3c56d16e3bcfb52d83d42105d61b36743626399c7c2b5e0ac3b670 + languageName: node + linkType: hard + "@typescript-eslint/types@npm:6.12.0": version: 6.12.0 resolution: "@typescript-eslint/types@npm:6.12.0" @@ -8961,6 +9525,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/types@npm:6.19.1" + checksum: 598ce222b59c20432d06f60703d0c2dd16d9b2151569c192852136c57b8188e3ef6ef9fddaa2c136c9a756fcc7d873c0e29ec41cfd340564842287ef7b4571cd + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:5.27.1": version: 5.27.1 resolution: "@typescript-eslint/typescript-estree@npm:5.27.1" @@ -8979,6 +9550,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" + dependencies: + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/visitor-keys": 5.62.0 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + semver: ^7.3.7 + tsutils: ^3.21.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 3624520abb5807ed8f57b1197e61c7b1ed770c56dfcaca66372d584ff50175225798bccb701f7ef129d62c5989070e1ee3a0aa2d84e56d9524dcf011a2bb1a52 + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:6.12.0": version: 6.12.0 resolution: "@typescript-eslint/typescript-estree@npm:6.12.0" @@ -8997,6 +9586,25 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/typescript-estree@npm:6.19.1" + dependencies: + "@typescript-eslint/types": 6.19.1 + "@typescript-eslint/visitor-keys": 6.19.1 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + minimatch: 9.0.3 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependenciesMeta: + typescript: + optional: true + checksum: fb71a14aeee0468780219c5b8d39075f85d360b04ccd0ee88f4f0a615d2c232a6d3016e36d8c6eda2d9dfda86b4f4cc2c3d7582940fb29d33c7cf305e124d4e2 + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:5.27.1, @typescript-eslint/utils@npm:^5.13.0": version: 5.27.1 resolution: "@typescript-eslint/utils@npm:5.27.1" @@ -9013,6 +9621,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/utils@npm:5.62.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@types/json-schema": ^7.0.9 + "@types/semver": ^7.3.12 + "@typescript-eslint/scope-manager": 5.62.0 + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/typescript-estree": 5.62.0 + eslint-scope: ^5.1.1 + semver: ^7.3.7 + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: ee9398c8c5db6d1da09463ca7bf36ed134361e20131ea354b2da16a5fdb6df9ba70c62a388d19f6eebb421af1786dbbd79ba95ddd6ab287324fc171c3e28d931 + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:6.12.0": version: 6.12.0 resolution: "@typescript-eslint/utils@npm:6.12.0" @@ -9030,6 +9656,23 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/utils@npm:6.19.1" + dependencies: + "@eslint-community/eslint-utils": ^4.4.0 + "@types/json-schema": ^7.0.12 + "@types/semver": ^7.5.0 + "@typescript-eslint/scope-manager": 6.19.1 + "@typescript-eslint/types": 6.19.1 + "@typescript-eslint/typescript-estree": 6.19.1 + semver: ^7.5.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + checksum: fe72e75c3ea17a85772b83f148555ea94ff5d55d13586f3fc038833197a74f8071e14c2bbf1781c40eec20005f052f4be2513a725eea82a15da3cb9af3046c70 + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:5.27.1": version: 5.27.1 resolution: "@typescript-eslint/visitor-keys@npm:5.27.1" @@ -9040,6 +9683,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/visitor-keys@npm:5.62.0" + dependencies: + "@typescript-eslint/types": 5.62.0 + eslint-visitor-keys: ^3.3.0 + checksum: 976b05d103fe8335bef5c93ad3f76d781e3ce50329c0243ee0f00c0fcfb186c81df50e64bfdd34970148113f8ade90887f53e3c4938183afba830b4ba8e30a35 + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:6.12.0": version: 6.12.0 resolution: "@typescript-eslint/visitor-keys@npm:6.12.0" @@ -9050,14 +9703,20 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:0.30.1": - version: 0.30.1 - resolution: "@vitest/expect@npm:0.30.1" +"@typescript-eslint/visitor-keys@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/visitor-keys@npm:6.19.1" dependencies: - "@vitest/spy": 0.30.1 - "@vitest/utils": 0.30.1 - chai: ^4.3.7 - checksum: cd7728d1532fd9b9d9ca52f76be14af72f7cf28686e91f99b1537a30d46a4207021410163b1c460076d4ada7246f7f3bdc14989c44aff0814ef83e1cdf5e4ecf + "@typescript-eslint/types": 6.19.1 + eslint-visitor-keys: ^3.4.1 + checksum: bdf057a42e776970a89cdd568e493e3ea7ec085544d8f318d33084da63c3395ad2c0fb9cef9f61ceeca41f5dab54ab064b7078fe596889005e412ec74d2d1ae4 + languageName: node + linkType: hard + +"@ungap/structured-clone@npm:^1.2.0": + version: 1.2.0 + resolution: "@ungap/structured-clone@npm:1.2.0" + checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 languageName: node linkType: hard @@ -9072,15 +9731,14 @@ __metadata: languageName: node linkType: hard -"@vitest/runner@npm:0.30.1": - version: 0.30.1 - resolution: "@vitest/runner@npm:0.30.1" +"@vitest/expect@npm:1.2.1": + version: 1.2.1 + resolution: "@vitest/expect@npm:1.2.1" dependencies: - "@vitest/utils": 0.30.1 - concordance: ^5.0.4 - p-limit: ^4.0.0 - pathe: ^1.1.0 - checksum: b8f9faa63f3e98671804ab403a1dc466a48548fa5ee5e276855f0bcc1fae528ca65476584fb5528dd62ba9865c54d147b1ae78fb0cafe337c043669dcb93e67d + "@vitest/spy": 1.2.1 + "@vitest/utils": 1.2.1 + chai: ^4.3.10 + checksum: d87a2dd646f523eaf68185e85f05412969fda55f228be4806d038550f446d3235ebee57f7d3882d0fcf16cfe2e3ac7d10d311df4894fa71548ae9852c8dbd23d languageName: node linkType: hard @@ -9095,14 +9753,14 @@ __metadata: languageName: node linkType: hard -"@vitest/snapshot@npm:0.30.1": - version: 0.30.1 - resolution: "@vitest/snapshot@npm:0.30.1" +"@vitest/runner@npm:1.2.1": + version: 1.2.1 + resolution: "@vitest/runner@npm:1.2.1" dependencies: - magic-string: ^0.30.0 - pathe: ^1.1.0 - pretty-format: ^27.5.1 - checksum: 9e0b89ca6c2cb08f2061c3d6bf5f2a1a9481c0229b8772b8be1db515552f07ea184f4248ceb11ad976ee89e2402c14e48a5700bab6ea859167fe5d10920e939c + "@vitest/utils": 1.2.1 + p-limit: ^5.0.0 + pathe: ^1.1.1 + checksum: 3a3941392e8c6359e19c3ac5c2923150251d9d32bf1252bc2951487d799ac19a7cc43eb3c02eb642c1b02f65ad365273f053bcb37153659c35a345b628baef65 languageName: node linkType: hard @@ -9117,12 +9775,14 @@ __metadata: languageName: node linkType: hard -"@vitest/spy@npm:0.30.1": - version: 0.30.1 - resolution: "@vitest/spy@npm:0.30.1" +"@vitest/snapshot@npm:1.2.1": + version: 1.2.1 + resolution: "@vitest/snapshot@npm:1.2.1" dependencies: - tinyspy: ^2.1.0 - checksum: af2e0a3910dfaa6b5759acd4913ca3c21ac9ad543c0d1095c23bdbca1a7d4e5dab43d8bfc4b08025d24e84965d65ae83f2cdc6aad080eaf5faf06daf06af3271 + magic-string: ^0.30.5 + pathe: ^1.1.1 + pretty-format: ^29.7.0 + checksum: 6efee401eaab9868c7f7834fd8ec9495c83c0a5eeb632942e6a5eb1ae5a876e91ac9a1b0b760e7bfde5d80cfc3a618e668b080c01882f5eb3b79a4c588185aa4 languageName: node linkType: hard @@ -9135,14 +9795,12 @@ __metadata: languageName: node linkType: hard -"@vitest/utils@npm:0.30.1": - version: 0.30.1 - resolution: "@vitest/utils@npm:0.30.1" +"@vitest/spy@npm:1.2.1": + version: 1.2.1 + resolution: "@vitest/spy@npm:1.2.1" dependencies: - concordance: ^5.0.4 - loupe: ^2.3.6 - pretty-format: ^27.5.1 - checksum: a685b6ba34b0173e4da388055dc2a22ba335a74cf99679f7036cea1d183e0ee804a01984148eaad0e0f48bfb786d33800ff6dd549b94f3d064e14caa0857ee62 + tinyspy: ^2.2.0 + checksum: 22a4b4539f69b28f6b0d907d6b7997972a09d85c9a136e0f953dfea45a12bc2ec8678f8d62cbc1ecfc803a0926df8901c6b5d9f8625196f68785965e1c14172c languageName: node linkType: hard @@ -9158,6 +9816,18 @@ __metadata: languageName: node linkType: hard +"@vitest/utils@npm:1.2.1": + version: 1.2.1 + resolution: "@vitest/utils@npm:1.2.1" + dependencies: + diff-sequences: ^29.6.3 + estree-walker: ^3.0.3 + loupe: ^2.3.7 + pretty-format: ^29.7.0 + checksum: 72b54d27e55b9805ab9a8224712584e8db232bd4ce6406e845fbeaf95d8845595791071868b3fdb2ca234acfaea6e7b323d25e419059ef3eb66aa2b4f5c29354 + languageName: node + linkType: hard + "@webassemblyjs/ast@npm:1.11.1": version: 1.11.1 resolution: "@webassemblyjs/ast@npm:1.11.1" @@ -9593,7 +10263,7 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.0.0, acorn-walk@npm:^8.0.2, acorn-walk@npm:^8.1.1, acorn-walk@npm:^8.2.0": +"acorn-walk@npm:^8.0.0, acorn-walk@npm:^8.0.2, acorn-walk@npm:^8.1.1": version: 8.2.0 resolution: "acorn-walk@npm:8.2.0" checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 @@ -9607,6 +10277,13 @@ __metadata: languageName: node linkType: hard +"acorn-walk@npm:^8.3.2": + version: 8.3.2 + resolution: "acorn-walk@npm:8.3.2" + checksum: 3626b9d26a37b1b427796feaa5261faf712307a8920392c8dce9a5739fb31077667f4ad2ec71c7ac6aaf9f61f04a9d3d67ff56f459587206fc04aa31c27ef392 + languageName: node + linkType: hard + "acorn@npm:^7.0.0, acorn@npm:^7.1.1, acorn@npm:^7.4.0": version: 7.4.1 resolution: "acorn@npm:7.4.1" @@ -9634,7 +10311,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.10.0": +"acorn@npm:^8.10.0, acorn@npm:^8.9.0": version: 8.11.3 resolution: "acorn@npm:8.11.3" bin: @@ -10154,6 +10831,19 @@ __metadata: languageName: node linkType: hard +"assert@npm:^2.0.0": + version: 2.1.0 + resolution: "assert@npm:2.1.0" + dependencies: + call-bind: ^1.0.2 + is-nan: ^1.3.2 + object-is: ^1.1.5 + object.assign: ^4.1.4 + util: ^0.12.5 + checksum: 1ed1cabba9abe55f4109b3f7292b4e4f3cf2953aad8dc148c0b3c3bd676675c31b1abb32ef563b7d5a19d1715bf90d1e5f09fad2a4ee655199468902da80f7c2 + languageName: node + linkType: hard + "assertion-error@npm:^1.1.0": version: 1.1.0 resolution: "assertion-error@npm:1.1.0" @@ -10184,6 +10874,15 @@ __metadata: languageName: node linkType: hard +"ast-types@npm:^0.16.1": + version: 0.16.1 + resolution: "ast-types@npm:0.16.1" + dependencies: + tslib: ^2.0.1 + checksum: 21c186da9fdb1d8087b1b7dabbc4059f91aa5a1e593a9776b4393cc1eaa857e741b2dda678d20e34b16727b78fef3ab59cf8f0c75ed1ba649c78fe194e5c114b + languageName: node + linkType: hard + "astral-regex@npm:^2.0.0": version: 2.0.0 resolution: "astral-regex@npm:2.0.0" @@ -10200,16 +10899,6 @@ __metadata: languageName: node linkType: hard -"async-promise-queue@npm:^1.0.5": - version: 1.0.5 - resolution: "async-promise-queue@npm:1.0.5" - dependencies: - async: ^2.4.1 - debug: ^2.6.8 - checksum: 6f18b65e4bac8c12822d66c532aba6c8a8d81ee6e7d790bc7c399e882ff55b642a86379a58df9129db8560f57f76dea0af39b065f43568fb4bec4edf40e415a9 - languageName: node - linkType: hard - "async-retry@npm:1.3.3": version: 1.3.3 resolution: "async-retry@npm:1.3.3" @@ -10219,15 +10908,6 @@ __metadata: languageName: node linkType: hard -"async@npm:^2.4.1": - version: 2.6.4 - resolution: "async@npm:2.6.4" - dependencies: - lodash: ^4.17.14 - checksum: a52083fb32e1ebe1d63e5c5624038bb30be68ff07a6c8d7dfe35e47c93fc144bd8652cbec869e0ac07d57dde387aa5f1386be3559cdee799cb1f789678d88e19 - languageName: node - linkType: hard - "async@npm:^3.2.3": version: 3.2.4 resolution: "async@npm:3.2.4" @@ -10290,6 +10970,13 @@ __metadata: languageName: node linkType: hard +"available-typed-arrays@npm:^1.0.5": + version: 1.0.5 + resolution: "available-typed-arrays@npm:1.0.5" + checksum: 20eb47b3cefd7db027b9bbb993c658abd36d4edd3fe1060e83699a03ee275b0c9b216cc076ff3f2db29073225fb70e7613987af14269ac1fe2a19803ccc97f1a + languageName: node + linkType: hard + "axe-core@npm:^4.3.5": version: 4.4.2 resolution: "axe-core@npm:4.4.2" @@ -10849,13 +11536,6 @@ __metadata: languageName: node linkType: hard -"blueimp-md5@npm:^2.10.0": - version: 2.19.0 - resolution: "blueimp-md5@npm:2.19.0" - checksum: 28095dcbd2c67152a2938006e8d7c74c3406ba6556071298f872505432feb2c13241b0476644160ee0a5220383ba94cb8ccdac0053b51f68d168728f9c382530 - languageName: node - linkType: hard - "body-parser@npm:1.20.0": version: 1.20.0 resolution: "body-parser@npm:1.20.0" @@ -11205,6 +11885,17 @@ __metadata: languageName: node linkType: hard +"call-bind@npm:^1.0.4, call-bind@npm:^1.0.5": + version: 1.0.5 + resolution: "call-bind@npm:1.0.5" + dependencies: + function-bind: ^1.1.2 + get-intrinsic: ^1.2.1 + set-function-length: ^1.1.1 + checksum: 449e83ecbd4ba48e7eaac5af26fea3b50f8f6072202c2dd7c5a6e7a6308f2421abe5e13a3bbd55221087f76320c5e09f25a8fdad1bab2b77c68ae74d92234ea5 + languageName: node + linkType: hard + "call-me-maybe@npm:^1.0.1": version: 1.0.1 resolution: "call-me-maybe@npm:1.0.1" @@ -11362,21 +12053,6 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.3.7": - version: 4.3.7 - resolution: "chai@npm:4.3.7" - dependencies: - assertion-error: ^1.1.0 - check-error: ^1.0.2 - deep-eql: ^4.1.2 - get-func-name: ^2.0.0 - loupe: ^2.3.1 - pathval: ^1.1.1 - type-detect: ^4.0.5 - checksum: 0bba7d267848015246a66995f044ce3f0ebc35e530da3cbdf171db744e14cbe301ab913a8d07caf7952b430257ccbb1a4a983c570a7c5748dc537897e5131f7c - languageName: node - linkType: hard - "chalk-template@npm:0.4.0": version: 0.4.0 resolution: "chalk-template@npm:0.4.0" @@ -11555,13 +12231,6 @@ __metadata: languageName: node linkType: hard -"check-error@npm:^1.0.2": - version: 1.0.2 - resolution: "check-error@npm:1.0.2" - checksum: d9d106504404b8addd1ee3f63f8c0eaa7cd962a1a28eb9c519b1c4a1dc7098be38007fc0060f045ee00f075fbb7a2a4f42abcf61d68323677e11ab98dc16042e - languageName: node - linkType: hard - "check-error@npm:^1.0.3": version: 1.0.3 resolution: "check-error@npm:1.0.3" @@ -11811,6 +12480,17 @@ __metadata: languageName: node linkType: hard +"cliui@npm:^8.0.1": + version: 8.0.1 + resolution: "cliui@npm:8.0.1" + dependencies: + string-width: ^4.2.0 + strip-ansi: ^6.0.1 + wrap-ansi: ^7.0.0 + checksum: 79648b3b0045f2e285b76fb2e24e207c6db44323581e421c3acbd0e86454cba1b37aea976ab50195a49e7384b871e6dfb2247ad7dec53c02454ac6497394cb56 + languageName: node + linkType: hard + "clone-deep@npm:^4.0.1": version: 4.0.1 resolution: "clone-deep@npm:4.0.1" @@ -11877,30 +12557,6 @@ __metadata: languageName: node linkType: hard -"codemod-cli@npm:^3.2.0": - version: 3.2.0 - resolution: "codemod-cli@npm:3.2.0" - dependencies: - "@babel/parser": ^7.14.0 - chalk: ^4.1.1 - common-tags: ^1.8.0 - ember-template-recast: ^4.1.4 - execa: ^5.0.0 - fs-extra: ^9.1.0 - globby: ^11.0.2 - import-cwd: ^3.0.0 - import-local: ^3.0.2 - jscodeshift: ^0.11.0 - latest-version: ^5.1.0 - pkg-up: ^3.1.0 - recast: ^0.20.4 - yargs: ^16.2.0 - bin: - codemod-cli: bin/cli.js - checksum: c0448ef19a4f2b503c125236f7b4c568d43ec22b4f42a9b461645deb00ea709864646e5801cbb283dc2c2be0cd20cd953efcec043d18ffb5d4de32de3eb901c6 - languageName: node - linkType: hard - "collapse-white-space@npm:^1.0.2": version: 1.0.6 resolution: "collapse-white-space@npm:1.0.6" @@ -11991,13 +12647,6 @@ __metadata: languageName: node linkType: hard -"colors@npm:^1.4.0": - version: 1.4.0 - resolution: "colors@npm:1.4.0" - checksum: 98aa2c2418ad87dedf25d781be69dc5fc5908e279d9d30c34d8b702e586a0474605b3a189511482b9d5ed0d20c867515d22749537f7bc546256c6014f3ebdcec - languageName: node - linkType: hard - "colors@npm:~1.2.1": version: 1.2.5 resolution: "colors@npm:1.2.5" @@ -12159,22 +12808,6 @@ __metadata: languageName: node linkType: hard -"concordance@npm:^5.0.4": - version: 5.0.4 - resolution: "concordance@npm:5.0.4" - dependencies: - date-time: ^3.1.0 - esutils: ^2.0.3 - fast-diff: ^1.2.0 - js-string-escape: ^1.0.1 - lodash: ^4.17.15 - md5-hex: ^3.0.1 - semver: ^7.3.2 - well-known-symbols: ^2.0.0 - checksum: 749153ba711492feb7c3d2f5bb04c107157440b3e39509bd5dd19ee7b3ac751d1e4cd75796d9f702e0a713312dbc661421c68aa4a2c34d5f6d91f47e3a1c64a6 - languageName: node - linkType: hard - "concurrently@npm:^6.2.0": version: 6.2.0 resolution: "concurrently@npm:6.2.0" @@ -12322,14 +12955,14 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.5.0": +"cookie@npm:0.5.0, cookie@npm:^0.5.0": version: 0.5.0 resolution: "cookie@npm:0.5.0" checksum: 1f4bd2ca5765f8c9689a7e8954183f5332139eb72b6ff783d8947032ec1fdf43109852c178e21a953a30c0dd42257828185be01b49d1eb1a67fd054ca588a180 languageName: node linkType: hard -"cookie@npm:^0.4.2": +"cookie@npm:^0.4.1, cookie@npm:^0.4.2": version: 0.4.2 resolution: "cookie@npm:0.4.2" checksum: a00833c998bedf8e787b4c342defe5fa419abd96b32f4464f718b91022586b8f1bafbddd499288e75c037642493c83083da426c6a9080d309e3bd90fd11baa9b @@ -13070,6 +13703,13 @@ __metadata: languageName: node linkType: hard +"data-uri-to-buffer@npm:^4.0.0": + version: 4.0.1 + resolution: "data-uri-to-buffer@npm:4.0.1" + checksum: 0d0790b67ffec5302f204c2ccca4494f70b4e2d940fea3d36b09f0bb2b8539c2e86690429eb1f1dc4bcc9e4df0644193073e63d9ee48ac9fce79ec1506e4aa4c + languageName: node + linkType: hard + "data-urls@npm:^2.0.0": version: 2.0.0 resolution: "data-urls@npm:2.0.0" @@ -13113,15 +13753,6 @@ __metadata: languageName: node linkType: hard -"date-time@npm:^3.1.0": - version: 3.1.0 - resolution: "date-time@npm:3.1.0" - dependencies: - time-zone: ^1.0.0 - checksum: f9cfcd1b15dfeabab15c0b9d18eb9e4e2d9d4371713564178d46a8f91ad577a290b5178b80050718d02d9c0cf646f8a875011e12d1ed05871e9f72c72c8a8fe6 - languageName: node - linkType: hard - "debounce@npm:^1.2.0": version: 1.2.1 resolution: "debounce@npm:1.2.1" @@ -13129,7 +13760,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:2.6.9, debug@npm:^2.2.0, debug@npm:^2.3.3, debug@npm:^2.6.0, debug@npm:^2.6.8, debug@npm:^2.6.9": +"debug@npm:2.6.9, debug@npm:^2.2.0, debug@npm:^2.3.3, debug@npm:^2.6.0, debug@npm:^2.6.9": version: 2.6.9 resolution: "debug@npm:2.6.9" dependencies: @@ -13138,7 +13769,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.0.1, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:^4.0.1, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -13233,7 +13864,7 @@ __metadata: languageName: node linkType: hard -"deep-eql@npm:^4.1.2, deep-eql@npm:^4.1.3": +"deep-eql@npm:^4.1.3": version: 4.1.3 resolution: "deep-eql@npm:4.1.3" dependencies: @@ -13302,6 +13933,17 @@ __metadata: languageName: node linkType: hard +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": + version: 1.1.1 + resolution: "define-data-property@npm:1.1.1" + dependencies: + get-intrinsic: ^1.2.1 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.0 + checksum: a29855ad3f0630ea82e3c5012c812efa6ca3078d5c2aa8df06b5f597c1cde6f7254692df41945851d903e05a1668607b6d34e778f402b9ff9ffb38111f1a3f0d + languageName: node + linkType: hard + "define-lazy-prop@npm:^2.0.0": version: 2.0.0 resolution: "define-lazy-prop@npm:2.0.0" @@ -13319,6 +13961,17 @@ __metadata: languageName: node linkType: hard +"define-properties@npm:^1.2.1": + version: 1.2.1 + resolution: "define-properties@npm:1.2.1" + dependencies: + define-data-property: ^1.0.1 + has-property-descriptors: ^1.0.0 + object-keys: ^1.1.1 + checksum: b4ccd00597dd46cb2d4a379398f5b19fca84a16f3374e2249201992f36b30f6835949a9429669ee6b41b6e837205a163eadd745e472069e70dfc10f03e5fcc12 + languageName: node + linkType: hard + "define-property@npm:^0.2.5": version: 0.2.5 resolution: "define-property@npm:0.2.5" @@ -13852,27 +14505,6 @@ __metadata: languageName: node linkType: hard -"ember-template-recast@npm:^4.1.4": - version: 4.3.0 - resolution: "ember-template-recast@npm:4.3.0" - dependencies: - "@glimmer/reference": ^0.62.4 - "@glimmer/syntax": ^0.62.4 - "@glimmer/validator": ^0.62.4 - async-promise-queue: ^1.0.5 - colors: ^1.4.0 - commander: ^6.2.0 - globby: ^11.0.1 - ora: ^5.1.0 - slash: ^3.0.0 - tmp: ^0.2.1 - workerpool: ^6.0.3 - bin: - ember-template-recast: lib/bin.js - checksum: 1ed187176ee16ba1a35920bcc3d0be85971030d111dea3bd7843c4bd84a4f6d29cda153a781190191b6bb865a2e49338591d16f4442f69c7dec932b1956cc23a - languageName: node - linkType: hard - "emittery@npm:^0.10.2": version: 0.10.2 resolution: "emittery@npm:0.10.2" @@ -14291,14 +14923,14 @@ __metadata: languageName: node linkType: hard -"eslint-config-prettier@npm:^8.3.0": - version: 8.3.0 - resolution: "eslint-config-prettier@npm:8.3.0" +"eslint-config-prettier@npm:^9.1.0": + version: 9.1.0 + resolution: "eslint-config-prettier@npm:9.1.0" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: df4cea3032671995bb5ab07e016169072f7fa59f44a53251664d9ca60951b66cdc872683b5c6a3729c91497c11490ca44a79654b395dd6756beb0c3903a37196 + checksum: 9229b768c879f500ee54ca05925f31b0c0bafff3d9f5521f98ff05127356de78c81deb9365c86a5ec4efa990cb72b74df8612ae15965b14136044c73e1f6a907 languageName: node linkType: hard @@ -14462,18 +15094,23 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-prettier@npm:^3.4.0": - version: 3.4.0 - resolution: "eslint-plugin-prettier@npm:3.4.0" +"eslint-plugin-prettier@npm:^5.1.3": + version: 5.1.3 + resolution: "eslint-plugin-prettier@npm:5.1.3" dependencies: prettier-linter-helpers: ^1.0.0 + synckit: ^0.8.6 peerDependencies: - eslint: ">=5.0.0" - prettier: ">=1.13.0" + "@types/eslint": ">=8.0.0" + eslint: ">=8.0.0" + eslint-config-prettier: "*" + prettier: ">=3.0.0" peerDependenciesMeta: + "@types/eslint": + optional: true eslint-config-prettier: optional: true - checksum: 30a07e8d12637d2988e371f6a20ff4c86fd7fdc3596d1d18d62c0367804f38e06a65052d0281234aeb2552e4d1908dcb2de20543413e038251a2717a46400a9d + checksum: eb2a7d46a1887e1b93788ee8f8eb81e0b6b2a6f5a66a62bc6f375b033fc4e7ca16448da99380be800042786e76cf5c0df9c87a51a2c9b960ed47acbd7c0b9381 languageName: node linkType: hard @@ -14541,6 +15178,16 @@ __metadata: languageName: node linkType: hard +"eslint-scope@npm:^7.2.2": + version: 7.2.2 + resolution: "eslint-scope@npm:7.2.2" + dependencies: + esrecurse: ^4.3.0 + estraverse: ^5.2.0 + checksum: ec97dbf5fb04b94e8f4c5a91a7f0a6dd3c55e46bfc7bbcd0e3138c3a76977570e02ed89a1810c778dcd72072ff0e9621ba1379b4babe53921d71e2e4486fda3e + languageName: node + linkType: hard + "eslint-utils@npm:^2.0.0, eslint-utils@npm:^2.1.0": version: 2.1.0 resolution: "eslint-utils@npm:2.1.0" @@ -14582,7 +15229,7 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^3.4.1": +"eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": version: 3.4.3 resolution: "eslint-visitor-keys@npm:3.4.3" checksum: 36e9ef87fca698b6fd7ca5ca35d7b2b6eeaaf106572e2f7fd31c12d3bfdaccdb587bba6d3621067e5aece31c8c3a348b93922ab8f7b2cbc6aaab5e1d89040c60 @@ -14690,12 +15337,60 @@ __metadata: optionator: ^0.9.1 regexpp: ^3.2.0 strip-ansi: ^6.0.1 - strip-json-comments: ^3.1.0 + strip-json-comments: ^3.1.0 + text-table: ^0.2.0 + v8-compile-cache: ^2.0.3 + bin: + eslint: bin/eslint.js + checksum: b484c96681c6b19f5b437f664623f1cd310d3ee9be88400d8450e086e664cd968a9dc202f0b0678578fd50e7a445b92586efe8c787de5073ff2f83213b00bb7b + languageName: node + linkType: hard + +"eslint@npm:^8.56.0": + version: 8.56.0 + resolution: "eslint@npm:8.56.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@eslint-community/regexpp": ^4.6.1 + "@eslint/eslintrc": ^2.1.4 + "@eslint/js": 8.56.0 + "@humanwhocodes/config-array": ^0.11.13 + "@humanwhocodes/module-importer": ^1.0.1 + "@nodelib/fs.walk": ^1.2.8 + "@ungap/structured-clone": ^1.2.0 + ajv: ^6.12.4 + chalk: ^4.0.0 + cross-spawn: ^7.0.2 + debug: ^4.3.2 + doctrine: ^3.0.0 + escape-string-regexp: ^4.0.0 + eslint-scope: ^7.2.2 + eslint-visitor-keys: ^3.4.3 + espree: ^9.6.1 + esquery: ^1.4.2 + esutils: ^2.0.2 + fast-deep-equal: ^3.1.3 + file-entry-cache: ^6.0.1 + find-up: ^5.0.0 + glob-parent: ^6.0.2 + globals: ^13.19.0 + graphemer: ^1.4.0 + ignore: ^5.2.0 + imurmurhash: ^0.1.4 + is-glob: ^4.0.0 + is-path-inside: ^3.0.3 + js-yaml: ^4.1.0 + json-stable-stringify-without-jsonify: ^1.0.1 + levn: ^0.4.1 + lodash.merge: ^4.6.2 + minimatch: ^3.1.2 + natural-compare: ^1.4.0 + optionator: ^0.9.3 + strip-ansi: ^6.0.1 text-table: ^0.2.0 - v8-compile-cache: ^2.0.3 bin: eslint: bin/eslint.js - checksum: b484c96681c6b19f5b437f664623f1cd310d3ee9be88400d8450e086e664cd968a9dc202f0b0678578fd50e7a445b92586efe8c787de5073ff2f83213b00bb7b + checksum: 883436d1e809b4a25d9eb03d42f584b84c408dbac28b0019f6ea07b5177940bf3cca86208f749a6a1e0039b63e085ee47aca1236c30721e91f0deef5cc5a5136 languageName: node linkType: hard @@ -14721,6 +15416,17 @@ __metadata: languageName: node linkType: hard +"espree@npm:^9.6.0, espree@npm:^9.6.1": + version: 9.6.1 + resolution: "espree@npm:9.6.1" + dependencies: + acorn: ^8.9.0 + acorn-jsx: ^5.3.2 + eslint-visitor-keys: ^3.4.1 + checksum: eb8c149c7a2a77b3f33a5af80c10875c3abd65450f60b8af6db1bfcfa8f101e21c1e56a561c6dc13b848e18148d43469e7cd208506238554fb5395a9ea5a1ab9 + languageName: node + linkType: hard + "esprima@npm:^4.0.0, esprima@npm:^4.0.1, esprima@npm:~4.0.0": version: 4.0.1 resolution: "esprima@npm:4.0.1" @@ -14740,6 +15446,15 @@ __metadata: languageName: node linkType: hard +"esquery@npm:^1.4.2": + version: 1.5.0 + resolution: "esquery@npm:1.5.0" + dependencies: + estraverse: ^5.1.0 + checksum: aefb0d2596c230118656cd4ec7532d447333a410a48834d80ea648b1e7b5c9bc9ed8b5e33a89cb04e487b60d622f44cf5713bf4abed7c97343edefdc84a35900 + languageName: node + linkType: hard + "esrecurse@npm:^4.3.0": version: 4.3.0 resolution: "esrecurse@npm:4.3.0" @@ -14793,7 +15508,7 @@ __metadata: languageName: node linkType: hard -"esutils@npm:^2.0.2, esutils@npm:^2.0.3": +"esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" checksum: 22b5b08f74737379a840b8ed2036a5fb35826c709ab000683b092d9054e5c2a82c27818f12604bfc2a9a76b90b6834ef081edbc1c7ae30d1627012e067c6ec87 @@ -15092,7 +15807,7 @@ __metadata: languageName: node linkType: hard -"fast-diff@npm:^1.1.2, fast-diff@npm:^1.2.0": +"fast-diff@npm:^1.1.2": version: 1.2.0 resolution: "fast-diff@npm:1.2.0" checksum: 1b5306eaa9e826564d9e5ffcd6ebd881eb5f770b3f977fcbf38f05c824e42172b53c79920e8429c54eb742ce15a0caf268b0fdd5b38f6de52234c4a8368131ae @@ -15222,6 +15937,16 @@ __metadata: languageName: node linkType: hard +"fetch-blob@npm:^3.1.2, fetch-blob@npm:^3.1.4": + version: 3.2.0 + resolution: "fetch-blob@npm:3.2.0" + dependencies: + node-domexception: ^1.0.0 + web-streams-polyfill: ^3.0.3 + checksum: f19bc28a2a0b9626e69fd7cf3a05798706db7f6c7548da657cbf5026a570945f5eeaedff52007ea35c8bcd3d237c58a20bf1543bc568ab2422411d762dd3d5bf + languageName: node + linkType: hard + "fflate@npm:^0.7.4": version: 0.7.4 resolution: "fflate@npm:0.7.4" @@ -15482,6 +16207,15 @@ __metadata: languageName: node linkType: hard +"for-each@npm:^0.3.3": + version: 0.3.3 + resolution: "for-each@npm:0.3.3" + dependencies: + is-callable: ^1.1.3 + checksum: 6c48ff2bc63362319c65e2edca4a8e1e3483a2fabc72fbe7feaf8c73db94fc7861bd53bc02c8a66a0c1dd709da6b04eec42e0abdd6b40ce47305ae92a25e5d28 + languageName: node + linkType: hard + "for-in@npm:^1.0.2": version: 1.0.2 resolution: "for-in@npm:1.0.2" @@ -15542,6 +16276,15 @@ __metadata: languageName: node linkType: hard +"formdata-polyfill@npm:^4.0.10": + version: 4.0.10 + resolution: "formdata-polyfill@npm:4.0.10" + dependencies: + fetch-blob: ^3.1.2 + checksum: 82a34df292afadd82b43d4a740ce387bc08541e0a534358425193017bf9fb3567875dc5f69564984b1da979979b70703aa73dee715a17b6c229752ae736dd9db + languageName: node + linkType: hard + "formik@npm:^2.1.5": version: 2.2.9 resolution: "formik@npm:2.2.9" @@ -15731,6 +16474,13 @@ __metadata: languageName: node linkType: hard +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 2b0ff4ce708d99715ad14a6d1f894e2a83242e4a52ccfcefaee5e40050562e5f6dafc1adbb4ce2d4ab47279a45dc736ab91ea5042d843c3c092820dfe032efb1 + languageName: node + linkType: hard + "function.prototype.name@npm:^1.1.5": version: 1.1.5 resolution: "function.prototype.name@npm:1.1.5" @@ -15821,6 +16571,18 @@ __metadata: languageName: node linkType: hard +"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": + version: 1.2.2 + resolution: "get-intrinsic@npm:1.2.2" + dependencies: + function-bind: ^1.1.2 + has-proto: ^1.0.1 + has-symbols: ^1.0.3 + hasown: ^2.0.0 + checksum: 447ff0724df26829908dc033b62732359596fcf66027bc131ab37984afb33842d9cd458fd6cecadfe7eac22fd8a54b349799ed334cf2726025c921c7250e7417 + languageName: node + linkType: hard + "get-nonce@npm:^1.0.0": version: 1.0.1 resolution: "get-nonce@npm:1.0.1" @@ -16022,6 +16784,15 @@ __metadata: languageName: node linkType: hard +"globals@npm:^13.19.0": + version: 13.24.0 + resolution: "globals@npm:13.24.0" + dependencies: + type-fest: ^0.20.2 + checksum: 56066ef058f6867c04ff203b8a44c15b038346a62efbc3060052a1016be9f56f4cf0b2cd45b74b22b81e521a889fc7786c73691b0549c2f3a6e825b3d394f43c + languageName: node + linkType: hard + "globalyzer@npm:0.1.0": version: 0.1.0 resolution: "globalyzer@npm:0.1.0" @@ -16057,7 +16828,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:^11.0.1, globby@npm:^11.0.2, globby@npm:^11.0.3, globby@npm:^11.0.4, globby@npm:^11.1.0": +"globby@npm:^11.0.1, globby@npm:^11.0.3, globby@npm:^11.0.4, globby@npm:^11.1.0": version: 11.1.0 resolution: "globby@npm:11.1.0" dependencies: @@ -16105,6 +16876,15 @@ __metadata: languageName: node linkType: hard +"gopd@npm:^1.0.1": + version: 1.0.1 + resolution: "gopd@npm:1.0.1" + dependencies: + get-intrinsic: ^1.1.3 + checksum: a5ccfb8806e0917a94e0b3de2af2ea4979c1da920bc381667c260e00e7cafdbe844e2cb9c5bcfef4e5412e8bf73bab837285bc35c7ba73aaaf0134d4583393a6 + languageName: node + linkType: hard + "got@npm:11.8.3": version: 11.8.3 resolution: "got@npm:11.8.3" @@ -16223,6 +17003,13 @@ __metadata: languageName: node linkType: hard +"graphql@npm:^15.4.0": + version: 15.8.0 + resolution: "graphql@npm:15.8.0" + checksum: 423325271db8858428641b9aca01699283d1fe5b40ef6d4ac622569ecca927019fce8196208b91dd1d8eb8114f00263fe661d241d0eb40c10e5bfd650f86ec5e + languageName: node + linkType: hard + "graphql@npm:^15.5.0": version: 15.5.0 resolution: "graphql@npm:15.5.0" @@ -16237,6 +17024,13 @@ __metadata: languageName: node linkType: hard +"graphql@npm:^16.8.1": + version: 16.8.1 + resolution: "graphql@npm:16.8.1" + checksum: 8d304b7b6f708c8c5cc164b06e92467dfe36aff6d4f2cf31dd19c4c2905a0e7b89edac4b7e225871131fd24e21460836b369de0c06532644d15b461d55b1ccc0 + languageName: node + linkType: hard + "gray-matter@npm:^4.0.3": version: 4.0.3 resolution: "gray-matter@npm:4.0.3" @@ -16320,6 +17114,22 @@ __metadata: languageName: node linkType: hard +"has-property-descriptors@npm:^1.0.1": + version: 1.0.1 + resolution: "has-property-descriptors@npm:1.0.1" + dependencies: + get-intrinsic: ^1.2.2 + checksum: 2bcc6bf6ec6af375add4e4b4ef586e43674850a91ad4d46666d0b28ba8e1fd69e424c7677d24d60f69470ad0afaa2f3197f508b20b0bb7dd99a8ab77ffc4b7c4 + languageName: node + linkType: hard + +"has-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "has-proto@npm:1.0.1" + checksum: febc5b5b531de8022806ad7407935e2135f1cc9e64636c3916c6842bd7995994ca3b29871ecd7954bd35f9e2986c17b3b227880484d22259e2f8e6ce63fd383e + languageName: node + linkType: hard + "has-symbols@npm:^1.0.1, has-symbols@npm:^1.0.2, has-symbols@npm:^1.0.3": version: 1.0.3 resolution: "has-symbols@npm:1.0.3" @@ -16398,6 +17208,15 @@ __metadata: languageName: node linkType: hard +"hasown@npm:^2.0.0": + version: 2.0.0 + resolution: "hasown@npm:2.0.0" + dependencies: + function-bind: ^1.1.2 + checksum: 6151c75ca12554565098641c98a40f4cc86b85b0fd5b6fe92360967e4605a4f9610f7757260b4e8098dd1c2ce7f4b095f2006fe72a570e3b6d2d28de0298c176 + languageName: node + linkType: hard + "hast-to-hyperscript@npm:^9.0.0": version: 9.0.1 resolution: "hast-to-hyperscript@npm:9.0.1" @@ -16504,6 +17323,20 @@ __metadata: languageName: node linkType: hard +"headers-polyfill@npm:^4.0.2": + version: 4.0.2 + resolution: "headers-polyfill@npm:4.0.2" + checksum: a95280ed58df429fc86c4f49b21596be3ea3f5f3d790e7d75238668df9b90b292f15a968c7c19ae1db88c0ae036dd1bf363a71b8e771199d82848e2d8b3c6c2e + languageName: node + linkType: hard + +"headers-utils@npm:^3.0.2": + version: 3.0.2 + resolution: "headers-utils@npm:3.0.2" + checksum: 210fe65756d6de8a96afe68617463fb6faf675a24d864e849b17bddf051c4a24d621a510a1bb80fd9d4763b932eb44b5d8fd6fc4f14fa62fb211603456a57b4f + languageName: node + linkType: hard + "hex-color-regex@npm:^1.1.0": version: 1.1.0 resolution: "hex-color-regex@npm:1.1.0" @@ -17326,6 +18159,16 @@ __metadata: languageName: node linkType: hard +"is-arguments@npm:^1.0.4": + version: 1.1.1 + resolution: "is-arguments@npm:1.1.1" + dependencies: + call-bind: ^1.0.2 + has-tostringtag: ^1.0.0 + checksum: 7f02700ec2171b691ef3e4d0e3e6c0ba408e8434368504bb593d0d7c891c0dbfda6d19d30808b904a6cb1929bca648c061ba438c39f296c2a8ca083229c49f27 + languageName: node + linkType: hard + "is-arrayish@npm:^0.2.1": version: 0.2.1 resolution: "is-arrayish@npm:0.2.1" @@ -17379,6 +18222,13 @@ __metadata: languageName: node linkType: hard +"is-callable@npm:^1.1.3": + version: 1.2.7 + resolution: "is-callable@npm:1.2.7" + checksum: 61fd57d03b0d984e2ed3720fb1c7a897827ea174bd44402878e059542ea8c4aeedee0ea0985998aa5cc2736b2fa6e271c08587addb5b3959ac52cf665173d1ac + languageName: node + linkType: hard + "is-callable@npm:^1.1.4, is-callable@npm:^1.2.4": version: 1.2.4 resolution: "is-callable@npm:1.2.4" @@ -17554,6 +18404,15 @@ __metadata: languageName: node linkType: hard +"is-generator-function@npm:^1.0.7": + version: 1.0.10 + resolution: "is-generator-function@npm:1.0.10" + dependencies: + has-tostringtag: ^1.0.0 + checksum: d54644e7dbaccef15ceb1e5d91d680eb5068c9ee9f9eb0a9e04173eb5542c9b51b5ab52c5537f5703e48d5fddfd376817c1ca07a84a407b7115b769d4bdde72b + languageName: node + linkType: hard + "is-glob@npm:4.0.1": version: 4.0.1 resolution: "is-glob@npm:4.0.1" @@ -17619,6 +18478,16 @@ __metadata: languageName: node linkType: hard +"is-nan@npm:^1.3.2": + version: 1.3.2 + resolution: "is-nan@npm:1.3.2" + dependencies: + call-bind: ^1.0.0 + define-properties: ^1.1.3 + checksum: 5dfadcef6ad12d3029d43643d9800adbba21cf3ce2ec849f734b0e14ee8da4070d82b15fdb35138716d02587c6578225b9a22779cab34888a139cc43e4e3610a + languageName: node + linkType: hard + "is-negative-zero@npm:^2.0.2": version: 2.0.2 resolution: "is-negative-zero@npm:2.0.2" @@ -17633,6 +18502,13 @@ __metadata: languageName: node linkType: hard +"is-node-process@npm:^1.2.0": + version: 1.2.0 + resolution: "is-node-process@npm:1.2.0" + checksum: 930765cdc6d81ab8f1bbecbea4a8d35c7c6d88a3ff61f3630e0fc7f22d624d7661c1df05c58547d0eb6a639dfa9304682c8e342c4113a6ed51472b704cee2928 + languageName: node + linkType: hard + "is-npm@npm:^5.0.0": version: 5.0.0 resolution: "is-npm@npm:5.0.0" @@ -17693,7 +18569,7 @@ __metadata: languageName: node linkType: hard -"is-path-inside@npm:^3.0.2": +"is-path-inside@npm:^3.0.2, is-path-inside@npm:^3.0.3": version: 3.0.3 resolution: "is-path-inside@npm:3.0.3" checksum: abd50f06186a052b349c15e55b182326f1936c89a78bf6c8f2b707412517c097ce04bc49a0ca221787bc44e1049f51f09a2ffb63d22899051988d3a618ba13e9 @@ -17864,6 +18740,15 @@ __metadata: languageName: node linkType: hard +"is-typed-array@npm:^1.1.3": + version: 1.1.12 + resolution: "is-typed-array@npm:1.1.12" + dependencies: + which-typed-array: ^1.1.11 + checksum: 4c89c4a3be07186caddadf92197b17fda663a9d259ea0d44a85f171558270d36059d1c386d34a12cba22dfade5aba497ce22778e866adc9406098c8fc4771796 + languageName: node + linkType: hard + "is-typedarray@npm:^1.0.0": version: 1.0.0 resolution: "is-typedarray@npm:1.0.0" @@ -19151,13 +20036,6 @@ __metadata: languageName: node linkType: hard -"js-string-escape@npm:^1.0.1": - version: 1.0.1 - resolution: "js-string-escape@npm:1.0.1" - checksum: f11e0991bf57e0c183b55c547acec85bd2445f043efc9ea5aa68b41bd2a3e7d3ce94636cb233ae0d84064ba4c1a505d32e969813c5b13f81e7d4be12c59256fe - languageName: node - linkType: hard - "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -19188,34 +20066,38 @@ __metadata: languageName: node linkType: hard -"jscodeshift@npm:0.13.1": - version: 0.13.1 - resolution: "jscodeshift@npm:0.13.1" - dependencies: - "@babel/core": ^7.13.16 - "@babel/parser": ^7.13.16 - "@babel/plugin-proposal-class-properties": ^7.13.0 - "@babel/plugin-proposal-nullish-coalescing-operator": ^7.13.8 - "@babel/plugin-proposal-optional-chaining": ^7.13.12 - "@babel/plugin-transform-modules-commonjs": ^7.13.8 - "@babel/preset-flow": ^7.13.13 - "@babel/preset-typescript": ^7.13.0 - "@babel/register": ^7.13.16 +"jscodeshift@npm:^0.15.1": + version: 0.15.1 + resolution: "jscodeshift@npm:0.15.1" + dependencies: + "@babel/core": ^7.23.0 + "@babel/parser": ^7.23.0 + "@babel/plugin-transform-class-properties": ^7.22.5 + "@babel/plugin-transform-modules-commonjs": ^7.23.0 + "@babel/plugin-transform-nullish-coalescing-operator": ^7.22.11 + "@babel/plugin-transform-optional-chaining": ^7.23.0 + "@babel/plugin-transform-private-methods": ^7.22.5 + "@babel/preset-flow": ^7.22.15 + "@babel/preset-typescript": ^7.23.0 + "@babel/register": ^7.22.15 babel-core: ^7.0.0-bridge.0 chalk: ^4.1.2 flow-parser: 0.* graceful-fs: ^4.2.4 - micromatch: ^3.1.10 + micromatch: ^4.0.4 neo-async: ^2.5.0 node-dir: ^0.1.17 - recast: ^0.20.4 + recast: ^0.23.3 temp: ^0.8.4 write-file-atomic: ^2.3.0 peerDependencies: "@babel/preset-env": ^7.1.6 + peerDependenciesMeta: + "@babel/preset-env": + optional: true bin: jscodeshift: bin/jscodeshift.js - checksum: 1c35938de5fc29cafec80e2c37d5c3411f85cd5d40e0243b52f2da0c1ab4b659daddfd62de558eca5d562303616f7838097727b651f4ad8e32b1e96f169cdd76 + checksum: d760dee2b634fa8a4610bdbdf787ce117a9a6bcc73e9ae55a38be77e380698d928d34a375a93ed4685e8bbdecfbd3cdbb87eb4b7e22fc58381db3d59fb554687 languageName: node linkType: hard @@ -19763,13 +20645,6 @@ __metadata: languageName: node linkType: hard -"local-pkg@npm:^0.4.3": - version: 0.4.3 - resolution: "local-pkg@npm:0.4.3" - checksum: 7825aca531dd6afa3a3712a0208697aa4a5cd009065f32e3fb732aafcc42ed11f277b5ac67229222e96f4def55197171cdf3d5522d0381b489d2e5547b407d55 - languageName: node - linkType: hard - "local-pkg@npm:^0.5.0": version: 0.5.0 resolution: "local-pkg@npm:0.5.0" @@ -19972,7 +20847,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:4.17.21, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.7.0, lodash@npm:~4.17.0, lodash@npm:~4.17.15": +"lodash@npm:4.17.21, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.7.0, lodash@npm:~4.17.0, lodash@npm:~4.17.15": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -20020,7 +20895,7 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^2.3.1, loupe@npm:^2.3.6": +"loupe@npm:^2.3.6": version: 2.3.6 resolution: "loupe@npm:2.3.6" dependencies: @@ -20104,15 +20979,6 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.0": - version: 0.30.0 - resolution: "magic-string@npm:0.30.0" - dependencies: - "@jridgewell/sourcemap-codec": ^1.4.13 - checksum: 7bdf22e27334d8a393858a16f5f840af63a7c05848c000fd714da5aa5eefa09a1bc01d8469362f25cc5c4a14ec01b46557b7fff8751365522acddf21e57c488d - languageName: node - linkType: hard - "magic-string@npm:^0.30.5": version: 0.30.5 resolution: "magic-string@npm:0.30.5" @@ -20249,15 +21115,6 @@ __metadata: languageName: node linkType: hard -"md5-hex@npm:^3.0.1": - version: 3.0.1 - resolution: "md5-hex@npm:3.0.1" - dependencies: - blueimp-md5: ^2.10.0 - checksum: 6799a19e8bdd3e0c2861b94c1d4d858a89220488d7885c1fa236797e367d0c2e5f2b789e05309307083503f85be3603a9686a5915568a473137d6b4117419cc2 - languageName: node - linkType: hard - "md5@npm:^2.3.0": version: 2.3.0 resolution: "md5@npm:2.3.0" @@ -20437,7 +21294,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^3.1.10, micromatch@npm:^3.1.4": +"micromatch@npm:^3.1.4": version: 3.1.10 resolution: "micromatch@npm:3.1.10" dependencies: @@ -20616,7 +21473,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:3.1.2, minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.1.2": +"minimatch@npm:3.1.2, minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -20625,6 +21482,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:9.0.3": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" + dependencies: + brace-expansion: ^2.0.1 + checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 + languageName: node + linkType: hard + "minimatch@npm:^5.0.1": version: 5.1.0 resolution: "minimatch@npm:5.1.0" @@ -20800,7 +21666,7 @@ __metadata: languageName: node linkType: hard -"msw@npm:0.40.2": +"msw@npm:0.40.2, msw@npm:^0.40.2": version: 0.40.2 resolution: "msw@npm:0.40.2" dependencies: @@ -20834,37 +21700,64 @@ __metadata: languageName: node linkType: hard -"msw@patch:msw@npm:0.40.2#.yarn/patches/msw-npm-0.40.2-2107d48752::locator=rtk-monorepo%40workspace%3A.": - version: 0.40.2 - resolution: "msw@patch:msw@npm%3A0.40.2#.yarn/patches/msw-npm-0.40.2-2107d48752::version=0.40.2&hash=830779&locator=rtk-monorepo%40workspace%3A." +"msw@npm:^0.28.2": + version: 0.28.2 + resolution: "msw@npm:0.28.2" dependencies: - "@mswjs/cookies": ^0.2.0 - "@mswjs/interceptors": ^0.15.1 + "@mswjs/cookies": ^0.1.4 + "@mswjs/interceptors": ^0.8.0 "@open-draft/until": ^1.0.3 - "@types/cookie": ^0.4.1 - "@types/js-levenshtein": ^1.1.1 - chalk: 4.1.1 + "@types/cookie": ^0.4.0 + "@types/inquirer": ^7.3.1 + "@types/js-levenshtein": ^1.1.0 + chalk: ^4.1.0 chokidar: ^3.4.2 - cookie: ^0.4.2 - graphql: ^16.3.0 - headers-polyfill: ^3.0.4 - inquirer: ^8.2.0 - is-node-process: ^1.0.1 + cookie: ^0.4.1 + graphql: ^15.4.0 + headers-utils: ^3.0.2 + inquirer: ^7.3.3 js-levenshtein: ^1.1.6 - node-fetch: ^2.6.7 - path-to-regexp: ^6.2.0 + node-fetch: ^2.6.1 + node-match-path: ^0.6.1 statuses: ^2.0.0 strict-event-emitter: ^0.2.0 - type-fest: ^1.2.2 - yargs: ^17.3.1 + yargs: ^16.2.0 + bin: + msw: cli/index.js + checksum: bfcac14831d88ebee0375933a84294696410a2f93a8dd0cf0d37fb8f641ce93e9d2d840253fb5755003ea8bd7126dc83bd6844066bf5073f0a264cd8c768dec7 + languageName: node + linkType: hard + +"msw@npm:^2.1.4": + version: 2.1.4 + resolution: "msw@npm:2.1.4" + dependencies: + "@bundled-es-modules/cookie": ^2.0.0 + "@bundled-es-modules/statuses": ^1.0.1 + "@mswjs/cookies": ^1.1.0 + "@mswjs/interceptors": ^0.25.14 + "@open-draft/until": ^2.1.0 + "@types/cookie": ^0.6.0 + "@types/statuses": ^2.0.4 + chalk: ^4.1.2 + chokidar: ^3.4.2 + graphql: ^16.8.1 + headers-polyfill: ^4.0.2 + inquirer: ^8.2.0 + is-node-process: ^1.2.0 + outvariant: ^1.4.2 + path-to-regexp: ^6.2.0 + strict-event-emitter: ^0.5.1 + type-fest: ^4.9.0 + yargs: ^17.7.2 peerDependencies: - typescript: ">= 4.2.x <= 4.6.x" + typescript: ">= 4.7.x <= 5.3.x" peerDependenciesMeta: typescript: optional: true bin: msw: cli/index.js - checksum: 3a5cd03a451462b2198824438ef3b81372c5fb3f39a81d1909141b7207a9776302bb90b98b2c0ddc67fe179b32cdadb83a0c69b2f7a256e36b21e58f102a6b7b + checksum: da8aaf9682ac48a635966beef9add9493297de797b266066bcd8ae0c2708488b81558251412e41489511a63deda1774b42e28197e9b73ddf14d9ecf8bb916e7a languageName: node linkType: hard @@ -20966,6 +21859,13 @@ __metadata: languageName: node linkType: hard +"natural-compare-lite@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare-lite@npm:1.4.0" + checksum: 5222ac3986a2b78dd6069ac62cbb52a7bf8ffc90d972ab76dfe7b01892485d229530ed20d0c62e79a6b363a663b273db3bde195a1358ce9e5f779d4453887225 + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -21040,6 +21940,13 @@ __metadata: languageName: node linkType: hard +"node-domexception@npm:^1.0.0": + version: 1.0.0 + resolution: "node-domexception@npm:1.0.0" + checksum: ee1d37dd2a4eb26a8a92cd6b64dfc29caec72bff5e1ed9aba80c294f57a31ba4895a60fd48347cf17dd6e766da0ae87d75657dfd1f384ebfa60462c2283f5c7f + languageName: node + linkType: hard + "node-emoji@npm:^1.10.0": version: 1.10.0 resolution: "node-emoji@npm:1.10.0" @@ -21105,6 +22012,17 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:^3.3.2": + version: 3.3.2 + resolution: "node-fetch@npm:3.3.2" + dependencies: + data-uri-to-buffer: ^4.0.0 + fetch-blob: ^3.1.4 + formdata-polyfill: ^4.0.10 + checksum: 06a04095a2ddf05b0830a0d5302699704d59bda3102894ea64c7b9d4c865ecdff2d90fd042df7f5bc40337266961cb6183dcc808ea4f3000d024f422b462da92 + languageName: node + linkType: hard + "node-forge@npm:^1": version: 1.3.1 resolution: "node-forge@npm:1.3.1" @@ -21139,6 +22057,13 @@ __metadata: languageName: node linkType: hard +"node-match-path@npm:^0.6.1": + version: 0.6.3 + resolution: "node-match-path@npm:0.6.3" + checksum: d515bc069f293688109c058ee02567528fdaa856290d362b80a2254734975014e4eefcdcc5164a8adfd5560aa870e277c97fe8be648074d5088056cf61553c7c + languageName: node + linkType: hard + "node-readfiles@npm:^0.2.0": version: 0.2.0 resolution: "node-readfiles@npm:0.2.0" @@ -21449,6 +22374,16 @@ __metadata: languageName: node linkType: hard +"object-is@npm:^1.1.5": + version: 1.1.5 + resolution: "object-is@npm:1.1.5" + dependencies: + call-bind: ^1.0.2 + define-properties: ^1.1.3 + checksum: 989b18c4cba258a6b74dc1d74a41805c1a1425bce29f6cabb50dcb1a6a651ea9104a1b07046739a49a5bb1bc49727bcb00efd5c55f932f6ea04ec8927a7901fe + languageName: node + linkType: hard + "object-keys@npm:^1.1.1": version: 1.1.1 resolution: "object-keys@npm:1.1.1" @@ -21477,6 +22412,18 @@ __metadata: languageName: node linkType: hard +"object.assign@npm:^4.1.4": + version: 4.1.5 + resolution: "object.assign@npm:4.1.5" + dependencies: + call-bind: ^1.0.5 + define-properties: ^1.2.1 + has-symbols: ^1.0.3 + object-keys: ^1.1.1 + checksum: f9aeac0541661370a1fc86e6a8065eb1668d3e771f7dbb33ee54578201336c057b21ee61207a186dd42db0c62201d91aac703d20d12a79fc79c353eed44d4e25 + languageName: node + linkType: hard + "object.entries@npm:^1.1.5": version: 1.1.5 resolution: "object.entries@npm:1.1.5" @@ -21673,7 +22620,21 @@ __metadata: languageName: node linkType: hard -"ora@npm:5.4.1, ora@npm:^5.1.0, ora@npm:^5.4.1": +"optionator@npm:^0.9.3": + version: 0.9.3 + resolution: "optionator@npm:0.9.3" + dependencies: + "@aashutoshrathi/word-wrap": ^1.2.3 + deep-is: ^0.1.3 + fast-levenshtein: ^2.0.6 + levn: ^0.4.1 + prelude-ls: ^1.2.1 + type-check: ^0.4.0 + checksum: 09281999441f2fe9c33a5eeab76700795365a061563d66b098923eb719251a42bdbe432790d35064d0816ead9296dbeb1ad51a733edf4167c96bd5d0882e428a + languageName: node + linkType: hard + +"ora@npm:5.4.1, ora@npm:^5.4.1": version: 5.4.1 resolution: "ora@npm:5.4.1" dependencies: @@ -21714,6 +22675,13 @@ __metadata: languageName: node linkType: hard +"outvariant@npm:^1.4.0, outvariant@npm:^1.4.2": + version: 1.4.2 + resolution: "outvariant@npm:1.4.2" + checksum: 5d9e2b3edb1cc8be9cbfc1c8c97e8b05137c4384bbfc56e0a465de26c5d2f023e65732ddcda9d46599b06d667fbc0de32c30d2ecd11f6f3f43bcf8ce0d320918 + languageName: node + linkType: hard + "p-cancelable@npm:^1.0.0": version: 1.1.0 resolution: "p-cancelable@npm:1.1.0" @@ -21762,15 +22730,6 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^4.0.0": - version: 4.0.0 - resolution: "p-limit@npm:4.0.0" - dependencies: - yocto-queue: ^1.0.0 - checksum: 01d9d70695187788f984226e16c903475ec6a947ee7b21948d6f597bed788e3112cc7ec2e171c1d37125057a5f45f3da21d8653e04a3a793589e12e9e80e756b - languageName: node - linkType: hard - "p-limit@npm:^5.0.0": version: 5.0.0 resolution: "p-limit@npm:5.0.0" @@ -22239,13 +23198,20 @@ __metadata: languageName: node linkType: hard -"pirates@npm:^4.0.1, pirates@npm:^4.0.4, pirates@npm:^4.0.5": +"pirates@npm:^4.0.1, pirates@npm:^4.0.4": version: 4.0.5 resolution: "pirates@npm:4.0.5" checksum: c9994e61b85260bec6c4fc0307016340d9b0c4f4b6550a957afaaff0c9b1ad58fbbea5cfcf083860a25cb27a375442e2b0edf52e2e1e40e69934e08dcc52d227 languageName: node linkType: hard +"pirates@npm:^4.0.6": + version: 4.0.6 + resolution: "pirates@npm:4.0.6" + checksum: 46a65fefaf19c6f57460388a5af9ab81e3d7fd0e7bc44ca59d753cb5c4d0df97c6c6e583674869762101836d68675f027d60f841c105d72734df9dfca97cbcc6 + languageName: node + linkType: hard + "pkg-dir@npm:^3.0.0": version: 3.0.0 resolution: "pkg-dir@npm:3.0.0" @@ -23596,17 +24562,6 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.20": - version: 8.4.21 - resolution: "postcss@npm:8.4.21" - dependencies: - nanoid: ^3.3.4 - picocolors: ^1.0.0 - source-map-js: ^1.0.2 - checksum: e39ac60ccd1542d4f9d93d894048aac0d686b3bb38e927d8386005718e6793dbbb46930f0a523fe382f1bbd843c6d980aaea791252bf5e176180e5a4336d9679 - languageName: node - linkType: hard - "postcss@npm:^8.4.32": version: 8.4.33 resolution: "postcss@npm:8.4.33" @@ -23657,6 +24612,15 @@ __metadata: languageName: node linkType: hard +"prettier@npm:^3.2.4": + version: 3.2.4 + resolution: "prettier@npm:3.2.4" + bin: + prettier: bin/prettier.cjs + checksum: 6ec9385a836e0b9bac549e585101c086d1521c31d7b882d5c8bb7d7646da0693da5f31f4fff6dc080710e5e2d34c85e6fb2f8766876b3645c8be2f33b9c3d1a3 + languageName: node + linkType: hard + "pretty-bytes@npm:^3.0.0": version: 3.0.1 resolution: "pretty-bytes@npm:3.0.1" @@ -24585,7 +25549,7 @@ __metadata: languageName: node linkType: hard -"recast@npm:^0.20.3, recast@npm:^0.20.4": +"recast@npm:^0.20.3": version: 0.20.5 resolution: "recast@npm:0.20.5" dependencies: @@ -24597,6 +25561,19 @@ __metadata: languageName: node linkType: hard +"recast@npm:^0.23.3": + version: 0.23.4 + resolution: "recast@npm:0.23.4" + dependencies: + assert: ^2.0.0 + ast-types: ^0.16.1 + esprima: ~4.0.0 + source-map: ~0.6.1 + tslib: ^2.0.1 + checksum: edb63bbe0457e68c0f4892f55413000e92aa7c5c53f9e109ab975d1c801cd299a62511ea72734435791f4aea6f0edf560f6a275761f66b2b6069ff6d72686029 + languageName: node + linkType: hard + "rechoir@npm:^0.6.2": version: 0.6.2 resolution: "rechoir@npm:0.6.2" @@ -25148,9 +26125,9 @@ __metadata: linkType: hard "reselect@npm:^5.0.1": - version: 5.0.1 - resolution: "reselect@npm:5.0.1" - checksum: 7663b4c28a0e908e74dc25262e1d813d028b9c2ee96160cb0f40a16f09c5ac632fa16af6bafede7eb0ff16ab2d5bea2cd8814d9a9488e0262b8317fef90b1dc0 + version: 5.1.0 + resolution: "reselect@npm:5.1.0" + checksum: 5bc9c5d03d7caea00d0c0e24330bf23d91801227346fec1cef6a60988ab8d3dd7cee76e6994ca0915bc1c20845bb2bd929b95753763e0a9db74c0f9dff5cb845 languageName: node linkType: hard @@ -25447,23 +26424,9 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^3.2.5": - version: 3.20.2 - resolution: "rollup@npm:3.20.2" - dependencies: - fsevents: ~2.3.2 - dependenciesMeta: - fsevents: - optional: true - bin: - rollup: dist/bin/rollup - checksum: 34b0932839b7c2a5d1742fb21ce95a47e0b49a0849f4abee2dccf25833187aa7babb898ca90d4fc761cffa4102b9ed0ac6ad7f6f6b96c8b8e2d67305abc5da65 - languageName: node - linkType: hard - -"rollup@npm:^3.7.0": - version: 3.10.0 - resolution: "rollup@npm:3.10.0" +"rollup@npm:^3.2.5": + version: 3.20.2 + resolution: "rollup@npm:3.20.2" dependencies: fsevents: ~2.3.2 dependenciesMeta: @@ -25471,7 +26434,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: 31a882689c58d084ac36362aeaf2422dc4b80d671bd88c856693c37d63a26ddac9b9819dfba7f79c2d50d5207868b0e3d75f728fe551bbc347cf5dedf8ece18e + checksum: 34b0932839b7c2a5d1742fb21ce95a47e0b49a0849f4abee2dccf25833187aa7babb898ca90d4fc761cffa4102b9ed0ac6ad7f6f6b96c8b8e2d67305abc5da65 languageName: node linkType: hard @@ -25540,20 +26503,22 @@ __metadata: version: 0.0.0-use.local resolution: "rtk-monorepo@workspace:." dependencies: + "@typescript-eslint/eslint-plugin": 6.12.0 + "@typescript-eslint/parser": 6.12.0 eslint: ^7.25.0 - eslint-config-prettier: ^8.3.0 + eslint-config-prettier: ^9.1.0 eslint-config-react-app: ^7.0.1 eslint-plugin-flowtype: ^5.7.2 eslint-plugin-import: ^2.22.1 eslint-plugin-jsx-a11y: ^6.4.1 - eslint-plugin-prettier: ^3.4.0 + eslint-plugin-prettier: ^5.1.3 eslint-plugin-react: ^7.23.2 eslint-plugin-react-hooks: ^4.2.0 netlify-plugin-cache: ^1.0.3 - prettier: ^2.2.1 + prettier: ^3.2.4 release-it: ^14.12.5 serve: ^14.2.0 - typescript: 5.2 + typescript: ^5.2.2 languageName: unknown linkType: soft @@ -25913,6 +26878,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^6.3.1": + version: 6.3.1 + resolution: "semver@npm:6.3.1" + bin: + semver: bin/semver.js + checksum: ae47d06de28836adb9d3e25f22a92943477371292d9b665fb023fae278d345d508ca1958232af086d85e0155aee22e313e100971898bbb8d5d89b8b1d4054ca2 + languageName: node + linkType: hard + "semver@npm:^7.0.0, semver@npm:^7.5.4": version: 7.5.4 resolution: "semver@npm:7.5.4" @@ -26077,6 +27051,19 @@ __metadata: languageName: node linkType: hard +"set-function-length@npm:^1.1.1": + version: 1.2.0 + resolution: "set-function-length@npm:1.2.0" + dependencies: + define-data-property: ^1.1.1 + function-bind: ^1.1.2 + get-intrinsic: ^1.2.2 + gopd: ^1.0.1 + has-property-descriptors: ^1.0.1 + checksum: 63e34b45a2ff9abb419f52583481bf8ba597d33c0c85e56999085eb6078a0f7fbb4222051981c287feceeb358aa7789e7803cea2c82ac94c0ab37059596aff79 + languageName: node + linkType: hard + "set-value@npm:^2.0.0, set-value@npm:^2.0.1": version: 2.0.1 resolution: "set-value@npm:2.0.1" @@ -26280,13 +27267,6 @@ __metadata: languageName: node linkType: hard -"simple-html-tokenizer@npm:^0.5.10": - version: 0.5.11 - resolution: "simple-html-tokenizer@npm:0.5.11" - checksum: f834a5a0b169ffe10f74bd479a071a7161e0186669e28a1cd662efacdaedd27667469e2b965d5a8538d9d8e7373cb741ea8d748259221f40fa3e4bda2efbdbfc - languageName: node - linkType: hard - "simple-swizzle@npm:^0.2.2": version: 0.2.2 resolution: "simple-swizzle@npm:0.2.2" @@ -26328,25 +27308,9 @@ __metadata: languageName: node linkType: hard -"size-limit@npm:11.0.1": - version: 11.0.1 - resolution: "size-limit@npm:11.0.1" - dependencies: - bytes-iec: ^3.1.1 - chokidar: ^3.5.3 - globby: ^14.0.0 - lilconfig: ^3.0.0 - nanospinner: ^1.1.0 - picocolors: ^1.0.0 - bin: - size-limit: bin.js - checksum: 090fe64fd26d793a31c6549f7d4d41cfe360f18b9b75742a9a8c23c3721ec9fff3ae5056c776c0c0b17c840972ee8653e49134d8e87492c1ce9c7016bef99d09 - languageName: node - linkType: hard - -"size-limit@patch:size-limit@npm%3A11.0.1#./.yarn/patches/size-limit-npm-11.0.1-05996e44e7.patch::locator=rtk-monorepo%40workspace%3A.": - version: 11.0.1 - resolution: "size-limit@patch:size-limit@npm%3A11.0.1#./.yarn/patches/size-limit-npm-11.0.1-05996e44e7.patch::version=11.0.1&hash=524e35&locator=rtk-monorepo%40workspace%3A." +"size-limit@npm:^11.0.1": + version: 11.0.2 + resolution: "size-limit@npm:11.0.2" dependencies: bytes-iec: ^3.1.1 chokidar: ^3.5.3 @@ -26356,7 +27320,7 @@ __metadata: picocolors: ^1.0.0 bin: size-limit: bin.js - checksum: f0396369795abb846c8f2405735d7a14fdeab7d5f6cc7a0792864eb1084a8ca2fd3a730bdec58ba589fd49c9928ef4ea7bc97804b16da30476e551b125007756 + checksum: 41d5c4e1fbb5e8bd89bc6ea1a7ad16d584e2b5410524eeef2f7e40ca884a3ef107d1b6f904393fa30d51c42fed245fbadafc81872b29095e5cc42695309c48b5 languageName: node linkType: hard @@ -26787,7 +27751,7 @@ __metadata: languageName: node linkType: hard -"statuses@npm:2.0.1, statuses@npm:^2.0.0": +"statuses@npm:2.0.1, statuses@npm:^2.0.0, statuses@npm:^2.0.1": version: 2.0.1 resolution: "statuses@npm:2.0.1" checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb @@ -26808,13 +27772,6 @@ __metadata: languageName: node linkType: hard -"std-env@npm:^3.3.2": - version: 3.3.2 - resolution: "std-env@npm:3.3.2" - checksum: c02256bb041ba1870d23f8360bc7e47a9cf1fabcd02c8b7c4246d48f2c6bb47b4f45c70964348844e6d36521df84c4a9d09d468654b51e0eb5c600e3392b4570 - languageName: node - linkType: hard - "std-env@npm:^3.5.0": version: 3.7.0 resolution: "std-env@npm:3.7.0" @@ -26831,6 +27788,13 @@ __metadata: languageName: node linkType: hard +"strict-event-emitter@npm:^0.5.1": + version: 0.5.1 + resolution: "strict-event-emitter@npm:0.5.1" + checksum: 350480431bc1c28fdb601ef4976c2f8155fc364b4740f9692dd03e5bdd48aafc99a5e021fe655fbd986d0b803e9f3fc5c4b018b35cb838c4690d60f2a26f1cf3 + languageName: node + linkType: hard + "strict-uri-encode@npm:^2.0.0": version: 2.0.0 resolution: "strict-uri-encode@npm:2.0.0" @@ -27104,15 +28068,6 @@ __metadata: languageName: node linkType: hard -"strip-literal@npm:^1.0.1": - version: 1.0.1 - resolution: "strip-literal@npm:1.0.1" - dependencies: - acorn: ^8.8.2 - checksum: ab40496820f02220390d95cdd620a997168efb69d5bd7d180bc4ef83ca562a95447843d8c7c88b8284879a29cf4eedc89d8001d1e098c1a1e23d12a9c755dff4 - languageName: node - linkType: hard - "strip-literal@npm:^1.3.0": version: 1.3.0 resolution: "strip-literal@npm:1.3.0" @@ -27384,6 +28339,16 @@ __metadata: languageName: node linkType: hard +"synckit@npm:^0.8.6": + version: 0.8.8 + resolution: "synckit@npm:0.8.8" + dependencies: + "@pkgr/core": ^0.1.0 + tslib: ^2.6.2 + checksum: 9ed5d33abb785f5f24e2531efd53b2782ca77abf7912f734d170134552b99001915531be5a50297aa45c5701b5c9041e8762e6cd7a38e41e2461c1e7fccdedf8 + languageName: node + linkType: hard + "table@npm:^6.0.9": version: 6.7.1 resolution: "table@npm:6.7.1" @@ -27664,13 +28629,6 @@ __metadata: languageName: node linkType: hard -"time-zone@npm:^1.0.0": - version: 1.0.0 - resolution: "time-zone@npm:1.0.0" - checksum: e46f5a69b8c236dcd8e91e29d40d4e7a3495ed4f59888c3f84ce1d9678e20461421a6ba41233509d47dd94bc18f1a4377764838b21b584663f942b3426dcbce8 - languageName: node - linkType: hard - "timsort@npm:^0.3.0, timsort@npm:~0.3.0": version: 0.3.0 resolution: "timsort@npm:0.3.0" @@ -27702,13 +28660,6 @@ __metadata: languageName: node linkType: hard -"tinybench@npm:^2.4.0": - version: 2.4.0 - resolution: "tinybench@npm:2.4.0" - checksum: cfbe90f75755488653dde256019cc810f65e90f63fdd962e71e8b209b49598c5fc90c2227d2087eb807944895fafe7f12fe9ecae2b5e89db5adde66415e9b836 - languageName: node - linkType: hard - "tinybench@npm:^2.5.1": version: 2.5.1 resolution: "tinybench@npm:2.5.1" @@ -27723,13 +28674,6 @@ __metadata: languageName: node linkType: hard -"tinypool@npm:^0.4.0": - version: 0.4.0 - resolution: "tinypool@npm:0.4.0" - checksum: 8abcac9e784793499f1eeeace8290c026454b9d7338c74029ce6a821643bab8dcab7caeb4051e39006baf681d6a62d57c3319e9c0f6e2317a45ab0fdbd76ee26 - languageName: node - linkType: hard - "tinypool@npm:^0.8.1": version: 0.8.1 resolution: "tinypool@npm:0.8.1" @@ -27737,13 +28681,6 @@ __metadata: languageName: node linkType: hard -"tinyspy@npm:^2.1.0": - version: 2.1.0 - resolution: "tinyspy@npm:2.1.0" - checksum: cb83c1f74a79dd5934018bad94f60a304a29d98a2d909ea45fc367f7b80b21b0a7d8135a2ce588deb2b3ba56c7c607258b2a03e6001d89e4d564f9a95cc6a81f - languageName: node - linkType: hard - "tinyspy@npm:^2.2.0": version: 2.2.0 resolution: "tinyspy@npm:2.2.0" @@ -27769,15 +28706,6 @@ __metadata: languageName: node linkType: hard -"tmp@npm:^0.2.1": - version: 0.2.1 - resolution: "tmp@npm:0.2.1" - dependencies: - rimraf: ^3.0.0 - checksum: 8b1214654182575124498c87ca986ac53dc76ff36e8f0e0b67139a8d221eaecfdec108c0e6ec54d76f49f1f72ab9325500b246f562b926f85bcdfca8bf35df9e - languageName: node - linkType: hard - "tmpl@npm:1.0.5": version: 1.0.5 resolution: "tmpl@npm:1.0.5" @@ -27977,6 +28905,13 @@ __metadata: languageName: node linkType: hard +"ts-expose-internals-conditionally@npm:1.0.0-empty.0": + version: 1.0.0-empty.0 + resolution: "ts-expose-internals-conditionally@npm:1.0.0-empty.0" + checksum: 6b4f546fc59f04f68d579f1bc0704541ec17521f84d32a15b45bef5dbc7a787143a065e19541cc5b64ff494f16f223bce59f3f5bf10ec538e5739e23c0efb878 + languageName: node + linkType: hard + "ts-interface-checker@npm:^0.1.9": version: 0.1.13 resolution: "ts-interface-checker@npm:0.1.13" @@ -28114,6 +29049,13 @@ __metadata: languageName: node linkType: hard +"tslib@npm:^2.6.2": + version: 2.6.2 + resolution: "tslib@npm:2.6.2" + checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad + languageName: node + linkType: hard + "tslib@npm:~2.0.1": version: 2.0.3 resolution: "tslib@npm:2.0.3" @@ -28217,7 +29159,7 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:4.0.8, type-detect@npm:^4.0.0, type-detect@npm:^4.0.5, type-detect@npm:^4.0.8": +"type-detect@npm:4.0.8, type-detect@npm:^4.0.0, type-detect@npm:^4.0.8": version: 4.0.8 resolution: "type-detect@npm:4.0.8" checksum: 62b5628bff67c0eb0b66afa371bd73e230399a8d2ad30d852716efcc4656a7516904570cd8631a49a3ce57c10225adf5d0cbdcb47f6b0255fe6557c453925a15 @@ -28250,23 +29192,103 @@ __metadata: languageName: node linkType: hard -"typescript@npm:5.2.2": - version: 5.2.2 - resolution: "typescript@npm:5.2.2" +"typescript@npm:4.1.3": + version: 4.1.3 + resolution: "typescript@npm:4.1.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 7912821dac4d962d315c36800fe387cdc0a6298dba7ec171b350b4a6e988b51d7b8f051317786db1094bd7431d526b648aba7da8236607febb26cf5b871d2d3c + checksum: 0a25f7d7cebbc5ad23f41cb30918643460477be265bd3bcd400ffedb77d16e97d46f2b0c31393b2f990c5cf5b9f7a829ad6aff8636988b8f30abf81c656237c0 languageName: node linkType: hard -"typescript@patch:typescript@npm%3A5.2.2#~builtin": - version: 5.2.2 - resolution: "typescript@patch:typescript@npm%3A5.2.2#~builtin::version=5.2.2&hash=701156" +"typescript@npm:5.3.3, typescript@npm:^5.0.0, typescript@npm:^5.2.2, typescript@npm:^5.3.3": + version: 5.3.3 + resolution: "typescript@npm:5.3.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 2007ccb6e51bbbf6fde0a78099efe04dc1c3dfbdff04ca3b6a8bc717991862b39fd6126c0c3ebf2d2d98ac5e960bcaa873826bb2bb241f14277034148f41f6a2 + languageName: node + linkType: hard + +"typescript@npm:^4.1.3, typescript@npm:^4.3.4, typescript@npm:^4.9, typescript@npm:~4.9": + version: 4.9.5 + resolution: "typescript@npm:4.9.5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db + languageName: node + linkType: hard + +"typescript@npm:~4.2.4": + version: 4.2.4 + resolution: "typescript@npm:4.2.4" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 89c397df192f239359ad798b96d8e8d552e12c0c189ac5676cec4c20c410d6eec636b8e59a88f2aef0a56d961a9678d99c400099be9b7cae2f7b062eb4b7b171 + languageName: node + linkType: hard + +"typescript@npm:~4.3.2": + version: 4.3.5 + resolution: "typescript@npm:4.3.5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: bab033b5e2b0790dd35b77fd005df976ef80b8d84fd2c6e63cc31808151875beae9216e5a315fe7068e8499905c3c354248fe83272cdfc13b7705635f0c66c97 + languageName: node + linkType: hard + +"typescript@patch:typescript@4.1.3#~builtin": + version: 4.1.3 + resolution: "typescript@patch:typescript@npm%3A4.1.3#~builtin::version=4.1.3&hash=701156" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: ed3df76d9b6efb448e5e73bca671698cda353a3807199ad95c78782a857e7685ccc94b799ac885423ced65ee21c87cbbeb823642c5dfd715efae5ebbc6137070 + languageName: node + linkType: hard + +"typescript@patch:typescript@5.3.3#~builtin, typescript@patch:typescript@^5.0.0#~builtin, typescript@patch:typescript@^5.2.2#~builtin, typescript@patch:typescript@^5.3.3#~builtin": + version: 5.3.3 + resolution: "typescript@patch:typescript@npm%3A5.3.3#~builtin::version=5.3.3&hash=701156" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: f61375590b3162599f0f0d5b8737877ac0a7bc52761dbb585d67e7b8753a3a4c42d9a554c4cc929f591ffcf3a2b0602f65ae3ce74714fd5652623a816862b610 + languageName: node + linkType: hard + +"typescript@patch:typescript@^4.1.3#~builtin, typescript@patch:typescript@^4.3.4#~builtin, typescript@patch:typescript@^4.9#~builtin, typescript@patch:typescript@~4.9#~builtin": + version: 4.9.5 + resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=701156" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 + languageName: node + linkType: hard + +"typescript@patch:typescript@~4.2.4#~builtin": + version: 4.2.4 + resolution: "typescript@patch:typescript@npm%3A4.2.4#~builtin::version=4.2.4&hash=701156" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: eb86e0e8022e5297f7a7b871b6edfbf33b57049416ada8bf97c358760125c7c79f074fbebd1b8e8230f858ae05eb22ad0e805e8f6acd5eae1fa886681624c15e + languageName: node + linkType: hard + +"typescript@patch:typescript@~4.3.2#~builtin": + version: 4.3.5 + resolution: "typescript@patch:typescript@npm%3A4.3.5#~builtin::version=4.3.5&hash=701156" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 07106822b4305de3f22835cbba949a2b35451cad50888759b6818421290ff95d522b38ef7919e70fb381c5fe9c1c643d7dea22c8b31652a717ddbd57b7f4d554 + checksum: 365df18cf979c971ef9543b2acaa8694377a803f98e1804c41d0ede0b09d7046cb0cd98f2eaf3884b0fe923c01a60af1f653841bd8805c9715d5479c09a4ebe4 languageName: node linkType: hard @@ -28824,6 +29846,19 @@ __metadata: languageName: node linkType: hard +"util@npm:^0.12.5": + version: 0.12.5 + resolution: "util@npm:0.12.5" + dependencies: + inherits: ^2.0.3 + is-arguments: ^1.0.4 + is-generator-function: ^1.0.7 + is-typed-array: ^1.1.3 + which-typed-array: ^1.1.2 + checksum: 705e51f0de5b446f4edec10739752ac25856541e0254ea1e7e45e5b9f9b0cb105bc4bd415736a6210edc68245a7f903bf085ffb08dd7deb8a0e847f60538a38a + languageName: node + linkType: hard + "utila@npm:~0.4": version: 0.4.0 resolution: "utila@npm:0.4.0" @@ -28973,22 +30008,6 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:0.30.1": - version: 0.30.1 - resolution: "vite-node@npm:0.30.1" - dependencies: - cac: ^6.7.14 - debug: ^4.3.4 - mlly: ^1.2.0 - pathe: ^1.1.0 - picocolors: ^1.0.0 - vite: ^3.0.0 || ^4.0.0 - bin: - vite-node: vite-node.mjs - checksum: 2a17cca94aaf9ea689aeff0b5e900aab9e9385e97189446a7bc9c067f094556a5fcdff4a04367811694c3dcd2001bef7f5133ac66cdf4307d90742c30aff5fea - languageName: node - linkType: hard - "vite-node@npm:1.1.3": version: 1.1.3 resolution: "vite-node@npm:1.1.3" @@ -29004,41 +30023,18 @@ __metadata: languageName: node linkType: hard -"vite@npm:^3.0.0 || ^4.0.0": - version: 4.0.4 - resolution: "vite@npm:4.0.4" +"vite-node@npm:1.2.1": + version: 1.2.1 + resolution: "vite-node@npm:1.2.1" dependencies: - esbuild: ^0.16.3 - fsevents: ~2.3.2 - postcss: ^8.4.20 - resolve: ^1.22.1 - rollup: ^3.7.0 - peerDependencies: - "@types/node": ">= 14" - less: "*" - sass: "*" - stylus: "*" - sugarss: "*" - terser: ^5.4.0 - dependenciesMeta: - fsevents: - optional: true - peerDependenciesMeta: - "@types/node": - optional: true - less: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true + cac: ^6.7.14 + debug: ^4.3.4 + pathe: ^1.1.1 + picocolors: ^1.0.0 + vite: ^5.0.0 bin: - vite: bin/vite.js - checksum: eb86c8cdfe8dcb6644005486b31cb60bc596f2aa683cb194abb5c0afca7c2a5dfdb02bbc7f83f419ad170227ac9c3b898f4406a6d1433105fb61d79d78e47d52 + vite-node: vite-node.mjs + checksum: 2d2679a8dfecd8de6a2296c72a3d6662597ccf20cb90e4626a2df335556d8b18dbad3ae2be06e644bf905693dbdb558ff003c6dc990c6bc662adcee9e4f0fa6f languageName: node linkType: hard @@ -29082,48 +30078,43 @@ __metadata: languageName: node linkType: hard -"vitest@npm:^0.30.1": - version: 0.30.1 - resolution: "vitest@npm:0.30.1" +"vitest@npm:^1.1.3": + version: 1.1.3 + resolution: "vitest@npm:1.1.3" dependencies: - "@types/chai": ^4.3.4 - "@types/chai-subset": ^1.3.3 - "@types/node": "*" - "@vitest/expect": 0.30.1 - "@vitest/runner": 0.30.1 - "@vitest/snapshot": 0.30.1 - "@vitest/spy": 0.30.1 - "@vitest/utils": 0.30.1 - acorn: ^8.8.2 - acorn-walk: ^8.2.0 + "@vitest/expect": 1.1.3 + "@vitest/runner": 1.1.3 + "@vitest/snapshot": 1.1.3 + "@vitest/spy": 1.1.3 + "@vitest/utils": 1.1.3 + acorn-walk: ^8.3.1 cac: ^6.7.14 - chai: ^4.3.7 - concordance: ^5.0.4 + chai: ^4.3.10 debug: ^4.3.4 - local-pkg: ^0.4.3 - magic-string: ^0.30.0 - pathe: ^1.1.0 + execa: ^8.0.1 + local-pkg: ^0.5.0 + magic-string: ^0.30.5 + pathe: ^1.1.1 picocolors: ^1.0.0 - source-map: ^0.6.1 - std-env: ^3.3.2 - strip-literal: ^1.0.1 - tinybench: ^2.4.0 - tinypool: ^0.4.0 - vite: ^3.0.0 || ^4.0.0 - vite-node: 0.30.1 + std-env: ^3.5.0 + strip-literal: ^1.3.0 + tinybench: ^2.5.1 + tinypool: ^0.8.1 + vite: ^5.0.0 + vite-node: 1.1.3 why-is-node-running: ^2.2.2 peerDependencies: "@edge-runtime/vm": "*" - "@vitest/browser": "*" - "@vitest/ui": "*" + "@types/node": ^18.0.0 || >=20.0.0 + "@vitest/browser": ^1.0.0 + "@vitest/ui": ^1.0.0 happy-dom: "*" jsdom: "*" - playwright: "*" - safaridriver: "*" - webdriverio: "*" peerDependenciesMeta: "@edge-runtime/vm": optional: true + "@types/node": + optional: true "@vitest/browser": optional: true "@vitest/ui": @@ -29132,28 +30123,22 @@ __metadata: optional: true jsdom: optional: true - playwright: - optional: true - safaridriver: - optional: true - webdriverio: - optional: true bin: vitest: vitest.mjs - checksum: 68e33226dde914600270df9834bdc1f45fd225250051c046c9bc53ca51b8e0bf76dee29a5cf1a51a4c1524f00c414f81764bb463734bdcc9c3f483f2140ec516 + checksum: 35087400a0e2b2f0f1f451d0da41abafd8c55112e143a2643286bf0d3d4567b057b40dc391c4b2a05a947edc48d981a6b8c961dc32c6642d84cd8d717bd168bc languageName: node linkType: hard -"vitest@npm:^1.1.3": - version: 1.1.3 - resolution: "vitest@npm:1.1.3" - dependencies: - "@vitest/expect": 1.1.3 - "@vitest/runner": 1.1.3 - "@vitest/snapshot": 1.1.3 - "@vitest/spy": 1.1.3 - "@vitest/utils": 1.1.3 - acorn-walk: ^8.3.1 +"vitest@npm:^1.2.1": + version: 1.2.1 + resolution: "vitest@npm:1.2.1" + dependencies: + "@vitest/expect": 1.2.1 + "@vitest/runner": 1.2.1 + "@vitest/snapshot": 1.2.1 + "@vitest/spy": 1.2.1 + "@vitest/utils": 1.2.1 + acorn-walk: ^8.3.2 cac: ^6.7.14 chai: ^4.3.10 debug: ^4.3.4 @@ -29167,7 +30152,7 @@ __metadata: tinybench: ^2.5.1 tinypool: ^0.8.1 vite: ^5.0.0 - vite-node: 1.1.3 + vite-node: 1.2.1 why-is-node-running: ^2.2.2 peerDependencies: "@edge-runtime/vm": "*" @@ -29191,7 +30176,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 35087400a0e2b2f0f1f451d0da41abafd8c55112e143a2643286bf0d3d4567b057b40dc391c4b2a05a947edc48d981a6b8c961dc32c6642d84cd8d717bd168bc + checksum: be5cf1ebde0ff7fd534d4c5c710b9d63b3bd7a899f1fcceab82779949cfb8c962f82bb827652debe2d0553d6f786cf76998e6f346e46e03b14e720b121ff540e languageName: node linkType: hard @@ -29299,6 +30284,13 @@ __metadata: languageName: node linkType: hard +"web-streams-polyfill@npm:^3.0.3": + version: 3.3.2 + resolution: "web-streams-polyfill@npm:3.3.2" + checksum: 0292f4113c1bda40d8e8ecebee39eb14cc2e2e560a65a6867980e394537a2645130e2c73f5ef6e641fd3697d2f71720ccf659aebaf69a9d5a773f653a0fdf39d + languageName: node + linkType: hard + "webidl-conversions@npm:^3.0.0": version: 3.0.1 resolution: "webidl-conversions@npm:3.0.1" @@ -29639,6 +30631,7 @@ __metadata: "@docusaurus/preset-classic": 2.1.0 classnames: ^2.2.6 netlify-plugin-cache: ^1.0.3 + prettier: ^3.2.4 react: ^18.1.0 react-dom: ^18.1.0 react-lite-youtube-embed: ^2.0.3 @@ -29665,13 +30658,6 @@ __metadata: languageName: node linkType: hard -"well-known-symbols@npm:^2.0.0": - version: 2.0.0 - resolution: "well-known-symbols@npm:2.0.0" - checksum: 4f54bbc3012371cb4d228f436891b8e7536d34ac61a57541890257e96788608e096231e0121ac24d08ef2f908b3eb2dc0adba35023eaeb2a7df655da91415402 - languageName: node - linkType: hard - "whatwg-encoding@npm:^1.0.5": version: 1.0.5 resolution: "whatwg-encoding@npm:1.0.5" @@ -29780,6 +30766,19 @@ __metadata: languageName: node linkType: hard +"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.2": + version: 1.1.13 + resolution: "which-typed-array@npm:1.1.13" + dependencies: + available-typed-arrays: ^1.0.5 + call-bind: ^1.0.4 + for-each: ^0.3.3 + gopd: ^1.0.1 + has-tostringtag: ^1.0.0 + checksum: 3828a0d5d72c800e369d447e54c7620742a4cc0c9baf1b5e8c17e9b6ff90d8d861a3a6dd4800f1953dbf80e5e5cec954a289e5b4a223e3bee4aeb1f8c5f33309 + languageName: node + linkType: hard + "which@npm:^1.2.9, which@npm:^1.3.1": version: 1.3.1 resolution: "which@npm:1.3.1" @@ -30069,13 +31068,6 @@ __metadata: languageName: node linkType: hard -"workerpool@npm:^6.0.3": - version: 6.2.1 - resolution: "workerpool@npm:6.2.1" - checksum: c2c6eebbc5225f10f758d599a5c016fa04798bcc44e4c1dffb34050cd361d7be2e97891aa44419e7afe647b1f767b1dc0b85a5e046c409d890163f655028b09d - languageName: node - linkType: hard - "wrap-ansi@npm:^3.0.1": version: 3.0.1 resolution: "wrap-ansi@npm:3.0.1" @@ -30349,7 +31341,7 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:^21.0.1": +"yargs-parser@npm:^21.0.1, yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" checksum: ed2d96a616a9e3e1cc7d204c62ecc61f7aaab633dcbfab2c6df50f7f87b393993fe6640d017759fe112d0cb1e0119f2b4150a87305cc873fd90831c6a58ccf1c @@ -30405,6 +31397,21 @@ __metadata: languageName: node linkType: hard +"yargs@npm:^17.7.2": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + dependencies: + cliui: ^8.0.1 + escalade: ^3.1.1 + get-caller-file: ^2.0.5 + require-directory: ^2.1.1 + string-width: ^4.2.3 + y18n: ^5.0.5 + yargs-parser: ^21.1.1 + checksum: 73b572e863aa4a8cbef323dd911d79d193b772defd5a51aab0aca2d446655216f5002c42c5306033968193bdbf892a7a4c110b0d77954a7fdf563e653967b56a + languageName: node + linkType: hard + "yn@npm:3.1.1": version: 3.1.1 resolution: "yn@npm:3.1.1"