diff --git a/exercises/01.exercises/01.problem.ssr/package.json b/exercises/01.exercises/01.problem.ssr/package.json index d645931..0d03b2d 100644 --- a/exercises/01.exercises/01.problem.ssr/package.json +++ b/exercises/01.exercises/01.problem.ssr/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/01.solution.ssr/package.json b/exercises/01.exercises/01.solution.ssr/package.json index 11c76e7..4abe357 100644 --- a/exercises/01.exercises/01.solution.ssr/package.json +++ b/exercises/01.exercises/01.solution.ssr/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/02.problem.server-context/package.json b/exercises/01.exercises/02.problem.server-context/package.json index b09dc32..4fc00a4 100644 --- a/exercises/01.exercises/02.problem.server-context/package.json +++ b/exercises/01.exercises/02.problem.server-context/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/02.solution.server-context/package.json b/exercises/01.exercises/02.solution.server-context/package.json index 96bf731..d13aefe 100644 --- a/exercises/01.exercises/02.solution.server-context/package.json +++ b/exercises/01.exercises/02.solution.server-context/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/03.problem.url/package.json b/exercises/01.exercises/03.problem.url/package.json index 14a3619..85e6661 100644 --- a/exercises/01.exercises/03.problem.url/package.json +++ b/exercises/01.exercises/03.problem.url/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/03.solution.url/package.json b/exercises/01.exercises/03.solution.url/package.json index a7bf38a..9ef148c 100644 --- a/exercises/01.exercises/03.solution.url/package.json +++ b/exercises/01.exercises/03.solution.url/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/04.problem.async-components/package.json b/exercises/01.exercises/04.problem.async-components/package.json index 3deecc1..76e8ceb 100644 --- a/exercises/01.exercises/04.problem.async-components/package.json +++ b/exercises/01.exercises/04.problem.async-components/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/04.solution.async-components/package.json b/exercises/01.exercises/04.solution.async-components/package.json index d0e333a..b4ced23 100644 --- a/exercises/01.exercises/04.solution.async-components/package.json +++ b/exercises/01.exercises/04.solution.async-components/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/05.problem.bootstrap/package.json b/exercises/01.exercises/05.problem.bootstrap/package.json index da19451..88cd509 100644 --- a/exercises/01.exercises/05.problem.bootstrap/package.json +++ b/exercises/01.exercises/05.problem.bootstrap/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/05.solution.bootstrap/package.json b/exercises/01.exercises/05.solution.bootstrap/package.json index f401064..2261900 100644 --- a/exercises/01.exercises/05.solution.bootstrap/package.json +++ b/exercises/01.exercises/05.solution.bootstrap/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/06.problem.import-map/package.json b/exercises/01.exercises/06.problem.import-map/package.json index 043ef52..2b29703 100644 --- a/exercises/01.exercises/06.problem.import-map/package.json +++ b/exercises/01.exercises/06.problem.import-map/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/06.problem.import-map/server/ssr.js b/exercises/01.exercises/06.problem.import-map/server/ssr.js index c2f3679..2b3a0d5 100644 --- a/exercises/01.exercises/06.problem.import-map/server/ssr.js +++ b/exercises/01.exercises/06.problem.import-map/server/ssr.js @@ -61,7 +61,7 @@ app.get('/:shipId?', async function (req, res) { // 'react-dom/': // 'https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/', // 'react-error-boundary': - // 'https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev', + // 'https://esm.sh/react-error-boundary@4.0.13?pin=126&dev', // 'react-server-dom-esm/client': '/js/react-server-dom-esm/client', // }, // }, diff --git a/exercises/01.exercises/06.solution.import-map/package.json b/exercises/01.exercises/06.solution.import-map/package.json index 9b0bad1..9ce53db 100644 --- a/exercises/01.exercises/06.solution.import-map/package.json +++ b/exercises/01.exercises/06.solution.import-map/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/06.solution.import-map/server/ssr.js b/exercises/01.exercises/06.solution.import-map/server/ssr.js index 141fbf9..04ca6ed 100644 --- a/exercises/01.exercises/06.solution.import-map/server/ssr.js +++ b/exercises/01.exercises/06.solution.import-map/server/ssr.js @@ -50,7 +50,7 @@ app.get('/:shipId?', async function (req, res) { 'react-dom/': 'https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/', 'react-error-boundary': - 'https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev', + 'https://esm.sh/react-error-boundary@4.0.13?pin=126&dev', 'react-server-dom-esm/client': '/js/react-server-dom-esm/client', }, }, diff --git a/exercises/01.exercises/07.problem.module-graph/package.json b/exercises/01.exercises/07.problem.module-graph/package.json index 0c6d667..72054f2 100644 --- a/exercises/01.exercises/07.problem.module-graph/package.json +++ b/exercises/01.exercises/07.problem.module-graph/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/07.problem.module-graph/server/ssr.js b/exercises/01.exercises/07.problem.module-graph/server/ssr.js index 141fbf9..04ca6ed 100644 --- a/exercises/01.exercises/07.problem.module-graph/server/ssr.js +++ b/exercises/01.exercises/07.problem.module-graph/server/ssr.js @@ -50,7 +50,7 @@ app.get('/:shipId?', async function (req, res) { 'react-dom/': 'https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/', 'react-error-boundary': - 'https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev', + 'https://esm.sh/react-error-boundary@4.0.13?pin=126&dev', 'react-server-dom-esm/client': '/js/react-server-dom-esm/client', }, }, diff --git a/exercises/01.exercises/07.solution.module-graph/package.json b/exercises/01.exercises/07.solution.module-graph/package.json index 54a64c1..1d95125 100644 --- a/exercises/01.exercises/07.solution.module-graph/package.json +++ b/exercises/01.exercises/07.solution.module-graph/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/07.solution.module-graph/server/ssr.js b/exercises/01.exercises/07.solution.module-graph/server/ssr.js index bcd69b6..bf5606f 100644 --- a/exercises/01.exercises/07.solution.module-graph/server/ssr.js +++ b/exercises/01.exercises/07.solution.module-graph/server/ssr.js @@ -86,7 +86,7 @@ app.get('/:shipId?', async function (req, res) { 'react-dom/': 'https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/', 'react-error-boundary': - 'https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev', + 'https://esm.sh/react-error-boundary@4.0.13?pin=126&dev', 'react-server-dom-esm/client': '/js/react-server-dom-esm/client', }, }, diff --git a/exercises/01.exercises/08.problem.hydrate/package.json b/exercises/01.exercises/08.problem.hydrate/package.json index 9c5ecd5..2460ed8 100644 --- a/exercises/01.exercises/08.problem.hydrate/package.json +++ b/exercises/01.exercises/08.problem.hydrate/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/08.problem.hydrate/server/ssr.js b/exercises/01.exercises/08.problem.hydrate/server/ssr.js index bcd69b6..bf5606f 100644 --- a/exercises/01.exercises/08.problem.hydrate/server/ssr.js +++ b/exercises/01.exercises/08.problem.hydrate/server/ssr.js @@ -86,7 +86,7 @@ app.get('/:shipId?', async function (req, res) { 'react-dom/': 'https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/', 'react-error-boundary': - 'https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev', + 'https://esm.sh/react-error-boundary@4.0.13?pin=126&dev', 'react-server-dom-esm/client': '/js/react-server-dom-esm/client', }, }, diff --git a/exercises/01.exercises/08.solution.hydrate/package.json b/exercises/01.exercises/08.solution.hydrate/package.json index aee715e..e5625ee 100644 --- a/exercises/01.exercises/08.solution.hydrate/package.json +++ b/exercises/01.exercises/08.solution.hydrate/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/08.solution.hydrate/server/ssr.js b/exercises/01.exercises/08.solution.hydrate/server/ssr.js index 910398e..100ee25 100644 --- a/exercises/01.exercises/08.solution.hydrate/server/ssr.js +++ b/exercises/01.exercises/08.solution.hydrate/server/ssr.js @@ -87,7 +87,7 @@ app.all('/:shipId?', async function (req, res) { 'react-dom/': 'https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/', 'react-error-boundary': - 'https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev', + 'https://esm.sh/react-error-boundary@4.0.13?pin=126&dev', 'react-server-dom-esm/client': '/js/react-server-dom-esm/client', }, }, diff --git a/exercises/01.exercises/09.problem.routing/package.json b/exercises/01.exercises/09.problem.routing/package.json index 8718069..0beb64a 100644 --- a/exercises/01.exercises/09.problem.routing/package.json +++ b/exercises/01.exercises/09.problem.routing/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/09.problem.routing/server/ssr.js b/exercises/01.exercises/09.problem.routing/server/ssr.js index 910398e..100ee25 100644 --- a/exercises/01.exercises/09.problem.routing/server/ssr.js +++ b/exercises/01.exercises/09.problem.routing/server/ssr.js @@ -87,7 +87,7 @@ app.all('/:shipId?', async function (req, res) { 'react-dom/': 'https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/', 'react-error-boundary': - 'https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev', + 'https://esm.sh/react-error-boundary@4.0.13?pin=126&dev', 'react-server-dom-esm/client': '/js/react-server-dom-esm/client', }, }, diff --git a/exercises/01.exercises/09.solution.routing/package.json b/exercises/01.exercises/09.solution.routing/package.json index 8168933..e81210d 100644 --- a/exercises/01.exercises/09.solution.routing/package.json +++ b/exercises/01.exercises/09.solution.routing/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/09.solution.routing/server/ssr.js b/exercises/01.exercises/09.solution.routing/server/ssr.js index c9ea08b..ef8c222 100644 --- a/exercises/01.exercises/09.solution.routing/server/ssr.js +++ b/exercises/01.exercises/09.solution.routing/server/ssr.js @@ -101,7 +101,7 @@ app.all('/:shipId?', async function (req, res) { 'react-dom/': 'https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/', 'react-error-boundary': - 'https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev', + 'https://esm.sh/react-error-boundary@4.0.13?pin=126&dev', 'react-server-dom-esm/client': '/js/react-server-dom-esm/client', }, }, diff --git a/exercises/01.exercises/10.problem.actions/package.json b/exercises/01.exercises/10.problem.actions/package.json index d04bf02..2660d84 100644 --- a/exercises/01.exercises/10.problem.actions/package.json +++ b/exercises/01.exercises/10.problem.actions/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/10.problem.actions/server/ssr.js b/exercises/01.exercises/10.problem.actions/server/ssr.js index c9ea08b..ef8c222 100644 --- a/exercises/01.exercises/10.problem.actions/server/ssr.js +++ b/exercises/01.exercises/10.problem.actions/server/ssr.js @@ -101,7 +101,7 @@ app.all('/:shipId?', async function (req, res) { 'react-dom/': 'https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/', 'react-error-boundary': - 'https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev', + 'https://esm.sh/react-error-boundary@4.0.13?pin=126&dev', 'react-server-dom-esm/client': '/js/react-server-dom-esm/client', }, }, diff --git a/exercises/01.exercises/10.solution.actions/package.json b/exercises/01.exercises/10.solution.actions/package.json index f799b52..9b5976e 100644 --- a/exercises/01.exercises/10.solution.actions/package.json +++ b/exercises/01.exercises/10.solution.actions/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/01.exercises/10.solution.actions/server/ssr.js b/exercises/01.exercises/10.solution.actions/server/ssr.js index c9ea08b..ef8c222 100644 --- a/exercises/01.exercises/10.solution.actions/server/ssr.js +++ b/exercises/01.exercises/10.solution.actions/server/ssr.js @@ -101,7 +101,7 @@ app.all('/:shipId?', async function (req, res) { 'react-dom/': 'https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/', 'react-error-boundary': - 'https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev', + 'https://esm.sh/react-error-boundary@4.0.13?pin=126&dev', 'react-server-dom-esm/client': '/js/react-server-dom-esm/client', }, }, diff --git a/exercises/02.no-ssr/01.solution.start/package.json b/exercises/02.no-ssr/01.solution.start/package.json index ffa9531..af3c34c 100644 --- a/exercises/02.no-ssr/01.solution.start/package.json +++ b/exercises/02.no-ssr/01.solution.start/package.json @@ -20,7 +20,7 @@ "express": "^4.19.1", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/02.no-ssr/01.solution.start/public/index.html b/exercises/02.no-ssr/01.solution.start/public/index.html index 9ca552d..ce15655 100644 --- a/exercises/02.no-ssr/01.solution.start/public/index.html +++ b/exercises/02.no-ssr/01.solution.start/public/index.html @@ -10,7 +10,7 @@ "react": "https://esm.sh/react@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom/": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/", - "react-error-boundary": "https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev", + "react-error-boundary": "https://esm.sh/react-error-boundary@4.0.13?pin=126&dev", "react-server-dom-esm/client": "/js/react-server-dom-esm/client" } } diff --git a/exercises/02.no-ssr/02.solution.rsc/package.json b/exercises/02.no-ssr/02.solution.rsc/package.json index 922aa97..7515b4f 100644 --- a/exercises/02.no-ssr/02.solution.rsc/package.json +++ b/exercises/02.no-ssr/02.solution.rsc/package.json @@ -20,7 +20,7 @@ "express": "^4.19.1", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/02.no-ssr/02.solution.rsc/public/index.html b/exercises/02.no-ssr/02.solution.rsc/public/index.html index 9ca552d..ce15655 100644 --- a/exercises/02.no-ssr/02.solution.rsc/public/index.html +++ b/exercises/02.no-ssr/02.solution.rsc/public/index.html @@ -10,7 +10,7 @@ "react": "https://esm.sh/react@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom/": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/", - "react-error-boundary": "https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev", + "react-error-boundary": "https://esm.sh/react-error-boundary@4.0.13?pin=126&dev", "react-server-dom-esm/client": "/js/react-server-dom-esm/client" } } diff --git a/exercises/02.no-ssr/03.solution.streaming/package.json b/exercises/02.no-ssr/03.solution.streaming/package.json index b1e0449..825b13a 100644 --- a/exercises/02.no-ssr/03.solution.streaming/package.json +++ b/exercises/02.no-ssr/03.solution.streaming/package.json @@ -20,7 +20,7 @@ "express": "^4.19.1", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/02.no-ssr/03.solution.streaming/public/index.html b/exercises/02.no-ssr/03.solution.streaming/public/index.html index 9ca552d..ce15655 100644 --- a/exercises/02.no-ssr/03.solution.streaming/public/index.html +++ b/exercises/02.no-ssr/03.solution.streaming/public/index.html @@ -10,7 +10,7 @@ "react": "https://esm.sh/react@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom/": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/", - "react-error-boundary": "https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev", + "react-error-boundary": "https://esm.sh/react-error-boundary@4.0.13?pin=126&dev", "react-server-dom-esm/client": "/js/react-server-dom-esm/client" } } diff --git a/exercises/02.no-ssr/04.solution.server-context/package.json b/exercises/02.no-ssr/04.solution.server-context/package.json index b173295..2a6f540 100644 --- a/exercises/02.no-ssr/04.solution.server-context/package.json +++ b/exercises/02.no-ssr/04.solution.server-context/package.json @@ -20,7 +20,7 @@ "express": "^4.19.1", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/02.no-ssr/04.solution.server-context/public/index.html b/exercises/02.no-ssr/04.solution.server-context/public/index.html index 9ca552d..ce15655 100644 --- a/exercises/02.no-ssr/04.solution.server-context/public/index.html +++ b/exercises/02.no-ssr/04.solution.server-context/public/index.html @@ -10,7 +10,7 @@ "react": "https://esm.sh/react@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom/": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/", - "react-error-boundary": "https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev", + "react-error-boundary": "https://esm.sh/react-error-boundary@4.0.13?pin=126&dev", "react-server-dom-esm/client": "/js/react-server-dom-esm/client" } } diff --git a/exercises/02.no-ssr/05.solution.client/package.json b/exercises/02.no-ssr/05.solution.client/package.json index 049690c..e17a917 100644 --- a/exercises/02.no-ssr/05.solution.client/package.json +++ b/exercises/02.no-ssr/05.solution.client/package.json @@ -20,7 +20,7 @@ "express": "^4.19.1", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/02.no-ssr/05.solution.client/public/index.html b/exercises/02.no-ssr/05.solution.client/public/index.html index 9ca552d..ce15655 100644 --- a/exercises/02.no-ssr/05.solution.client/public/index.html +++ b/exercises/02.no-ssr/05.solution.client/public/index.html @@ -10,7 +10,7 @@ "react": "https://esm.sh/react@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom/": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/", - "react-error-boundary": "https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev", + "react-error-boundary": "https://esm.sh/react-error-boundary@4.0.13?pin=126&dev", "react-server-dom-esm/client": "/js/react-server-dom-esm/client" } } diff --git a/exercises/02.no-ssr/05.solution.client/server/app.js b/exercises/02.no-ssr/05.solution.client/server/app.js index a9618b3..da5aaaf 100644 --- a/exercises/02.no-ssr/05.solution.client/server/app.js +++ b/exercises/02.no-ssr/05.solution.client/server/app.js @@ -69,7 +69,7 @@ app.get('/:shipId?', async function (req, res) { }) const server = app.listen(PORT, () => { - console.log(`✅ SSR: http://localhost:${PORT}`) + console.log(`✅ http://localhost:${PORT}`) }) closeWithGrace(async ({ signal, err }) => { diff --git a/exercises/02.no-ssr/06.solution.router/.gitignore b/exercises/02.no-ssr/06.solution.router/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/exercises/02.no-ssr/06.solution.router/.prettierignore b/exercises/02.no-ssr/06.solution.router/.prettierignore new file mode 100644 index 0000000..4dd9aa1 --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/.prettierignore @@ -0,0 +1,3 @@ +node_modules +package-lock.json +built_node_modules diff --git a/exercises/02.no-ssr/06.solution.router/.prettierrc b/exercises/02.no-ssr/06.solution.router/.prettierrc new file mode 100644 index 0000000..fc39ebe --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/.prettierrc @@ -0,0 +1,35 @@ +{ + "arrowParens": "avoid", + "bracketSameLine": false, + "bracketSpacing": true, + "embeddedLanguageFormatting": "auto", + "endOfLine": "lf", + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxSingleQuote": false, + "printWidth": 80, + "proseWrap": "always", + "quoteProps": "as-needed", + "requirePragma": false, + "semi": false, + "singleAttributePerLine": false, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "all", + "useTabs": true, + "overrides": [ + { + "files": ["**/*.json"], + "options": { + "useTabs": false + } + }, + { + "files": ["**/*.mdx"], + "options": { + "proseWrap": "preserve", + "htmlWhitespaceSensitivity": "ignore" + } + } + ] +} diff --git a/exercises/02.no-ssr/06.solution.router/README.mdx b/exercises/02.no-ssr/06.solution.router/README.mdx new file mode 100644 index 0000000..39829e6 --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/README.mdx @@ -0,0 +1 @@ +# Client Router diff --git a/exercises/02.no-ssr/06.solution.router/db/ship-api.js b/exercises/02.no-ssr/06.solution.router/db/ship-api.js new file mode 100644 index 0000000..262da8d --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/db/ship-api.js @@ -0,0 +1,59 @@ +import fs from 'node:fs/promises' + +const shipData = JSON.parse( + String(await fs.readFile(new URL('./ships.json', import.meta.url))), +) + +const MIN_DELAY = 200 +const MAX_DELAY = 500 + +export async function searchShips({ + search, + delay = Math.random() * (MAX_DELAY - MIN_DELAY) + MIN_DELAY, +}) { + const endTime = Date.now() + delay + const ships = shipData + .filter(ship => ship.name.toLowerCase().includes(search.toLowerCase())) + .slice(0, 13) + await new Promise(resolve => setTimeout(resolve, endTime - Date.now())) + return { + ships: ships.map(ship => ({ name: ship.name, id: ship.id })), + } +} + +export async function getShip({ + shipId, + delay = Math.random() * (MAX_DELAY - MIN_DELAY) + MIN_DELAY, +}) { + const endTime = Date.now() + delay + if (!shipId) { + throw new Error('No shipId provided') + } + const ship = shipData.find(ship => ship.id === shipId) + await new Promise(resolve => setTimeout(resolve, endTime - Date.now())) + if (!ship) { + throw new Error(`No ship with the id "${shipId}"`) + } + return ship +} + +export async function updateShipName({ + shipId, + shipName, + delay = Math.random() * (MAX_DELAY - MIN_DELAY) + MIN_DELAY, +}) { + const endTime = Date.now() + delay + const ship = shipData.find(ship => ship.id === shipId) + await new Promise(resolve => setTimeout(resolve, endTime - Date.now())) + if (!ship) { + throw new Error(`No ship with the id "${shipId}"`) + } + if (shipName.toLowerCase().includes('error')) { + throw new Error('Error updating ship name') + } + if (shipName === ship.name) { + throw new Error('New name is the same as the old name') + } + ship.name = shipName + return ship +} diff --git a/exercises/02.no-ssr/06.solution.router/db/ships.json b/exercises/02.no-ssr/06.solution.router/db/ships.json new file mode 100644 index 0000000..99a462f --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/db/ships.json @@ -0,0 +1,309 @@ +[ + { + "id": "bc4cbadf89bd3", + "name": "Infinity Drifter", + "image": "/ships/bc4cbadf89bd3.webp", + "topSpeed": 10, + "hyperdrive": true, + "weapons": [ + { + "name": "Laser", + "type": "beam", + "damage": 35 + }, + { + "name": "Photon Torpedo", + "type": "projectile", + "damage": 50 + }, + { + "name": "Plasma Cannon", + "type": "beam", + "damage": 75 + } + ] + }, + { + "id": "3ba8aa65ffe6c", + "name": "Star Hopper", + "image": "/ships/3ba8aa65ffe6c.webp", + "topSpeed": 8, + "hyperdrive": true, + "weapons": [ + { + "name": "Laser", + "type": "beam", + "damage": 25 + }, + { + "name": "Photon Torpedo", + "type": "projectile", + "damage": 40 + } + ] + }, + { + "id": "ab267a5984523", + "name": "Galaxy Cruiser", + "image": "/ships/ab267a5984523.webp", + "topSpeed": 6, + "hyperdrive": true, + "weapons": [ + { + "name": "Laser", + "type": "beam", + "damage": 15 + } + ] + }, + { + "id": "d3b8aa65ffe6c", + "name": "Planet Hopper", + "image": "/ships/d3b8aa65ffe6c.webp", + "topSpeed": 4, + "hyperdrive": false, + "weapons": [ + { + "name": "Laser", + "type": "beam", + "damage": 10 + } + ] + }, + { + "id": "1ff1991efe029", + "name": "Space Taxi", + "image": "/ships/1ff1991efe029.webp", + "topSpeed": 2, + "hyperdrive": false, + "weapons": [] + }, + { + "id": "f3d9a88e1c234", + "name": "Star Destroyer", + "image": "/ships/f3d9a88e1c234.webp", + "topSpeed": 12, + "hyperdrive": true, + "weapons": [ + { + "name": "Ion Cannon", + "type": "beam", + "damage": 60 + }, + { + "name": "Proton Torpedo", + "type": "projectile", + "damage": 80 + }, + { + "name": "Plasma Cannon", + "type": "beam", + "damage": 100 + } + ] + }, + { + "id": "cb03cc4e5717e", + "name": "Interceptor", + "image": "/ships/cb03cc4e5717e.webp", + "topSpeed": 9, + "hyperdrive": true, + "weapons": [ + { + "name": "Railgun", + "type": "projectile", + "damage": 45 + }, + { + "name": "EMP Blaster", + "type": "beam", + "damage": 70 + } + ] + }, + { + "id": "6c86fca8b9086", + "name": "Stealth Cruiser", + "image": "/ships/6c86fca8b9086.webp", + "topSpeed": 7, + "hyperdrive": true, + "weapons": [ + { + "name": "Cloaking Device", + "type": "special", + "damage": 0 + }, + { + "name": "Plasma Cannon", + "type": "beam", + "damage": 85 + } + ] + }, + { + "id": "fdc13cb488bf1", + "name": "Battleship", + "image": "/ships/fdc13cb488bf1.webp", + "topSpeed": 10, + "hyperdrive": false, + "weapons": [ + { + "name": "Cannon", + "type": "projectile", + "damage": 50 + }, + { + "name": "Missile Launcher", + "type": "projectile", + "damage": 70 + } + ] + }, + { + "id": "d486d48b82b81", + "name": "Dreadnought", + "image": "/ships/d486d48b82b81.webp", + "topSpeed": 8, + "hyperdrive": true, + "weapons": [ + { + "name": "Plasma Cannon", + "type": "beam", + "damage": 90 + }, + { + "name": "Quantum Torpedo", + "type": "projectile", + "damage": 120 + } + ] + }, + { + "id": "cfd10fcd2de6c", + "name": "Cruiser", + "image": "/ships/cfd10fcd2de6c.webp", + "topSpeed": 6, + "hyperdrive": false, + "weapons": [ + { + "name": "Laser Cannon", + "type": "beam", + "damage": 55 + }, + { + "name": "Missile Launcher", + "type": "projectile", + "damage": 75 + } + ] + }, + { + "id": "e92cefe4f6727", + "name": "Frigate", + "image": "/ships/e92cefe4f6727.webp", + "topSpeed": 5, + "hyperdrive": false, + "weapons": [ + { + "name": "Plasma Cannon", + "type": "beam", + "damage": 70 + }, + { + "name": "Torpedo Launcher", + "type": "projectile", + "damage": 60 + } + ] + }, + { + "id": "ec7a3f950f99f", + "name": "Scout Ship", + "image": "/ships/ec7a3f950f99f.webp", + "topSpeed": 11, + "hyperdrive": true, + "weapons": [] + }, + { + "id": "5c13d8b28a14a", + "name": "Bomber", + "image": "/ships/5c13d8b28a14a.webp", + "topSpeed": 8, + "hyperdrive": false, + "weapons": [ + { + "name": "Bomb Dropper", + "type": "projectile", + "damage": 90 + } + ] + }, + { + "id": "670003aed3795", + "name": "Transport Ship", + "image": "/ships/670003aed3795.webp", + "topSpeed": 4, + "hyperdrive": true, + "weapons": [] + }, + { + "id": "b442531ea32b2", + "name": "Gunship", + "image": "/ships/b442531ea32b2.webp", + "topSpeed": 7, + "hyperdrive": true, + "weapons": [ + { + "name": "Laser Cannon", + "type": "beam", + "damage": 65 + } + ] + }, + { + "id": "6f375578ead88", + "name": "Diplomatic Vessel", + "image": "/ships/6f375578ead88.webp", + "topSpeed": 3, + "hyperdrive": true, + "weapons": [ + { + "name": "Laser", + "type": "beam", + "damage": 5 + } + ] + }, + { + "id": "627c497212456", + "name": "Mining Ship", + "image": "/ships/627c497212456.webp", + "topSpeed": 4, + "hyperdrive": false, + "weapons": [] + }, + { + "id": "441f7092a8d44", + "name": "Research Vessel", + "image": "/ships/441f7092a8d44.webp", + "topSpeed": 3, + "hyperdrive": true, + "weapons": [] + }, + { + "id": "0268fc4817ad1", + "name": "Medical Ship", + "image": "/ships/0268fc4817ad1.webp", + "topSpeed": 2, + "hyperdrive": true, + "weapons": [] + }, + { + "id": "1ae7b4b92036b", + "name": "Cargo Ship", + "image": "/ships/1ae7b4b92036b.webp", + "topSpeed": 2, + "hyperdrive": true, + "weapons": [] + } +] diff --git a/exercises/02.no-ssr/06.solution.router/package-lock.json b/exercises/02.no-ssr/06.solution.router/package-lock.json new file mode 100644 index 0000000..babe051 --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/package-lock.json @@ -0,0 +1,1298 @@ +{ + "name": "super-simple-rsc", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "super-simple-rsc", + "version": "1.0.0", + "license": "MIT", + "workspaces": [ + "built_node_modules/*" + ], + "dependencies": { + "body-parser": "^1.20.2", + "busboy": "^1.6.0", + "chalk": "^5.3.0", + "compression": "^1.7.4", + "concurrently": "^8.2.2", + "cross-env": "^7.0.3", + "express": "^4.19.1", + "get-port": "^7.1.0", + "react": "0.0.0-experimental-2b036d3f1-20240327", + "react-dom": "0.0.0-experimental-2b036d3f1-20240327", + "react-error-boundary": "^4.0.13" + }, + "devDependencies": { + "prettier": "^3.2.5" + } + }, + "built_node_modules/react-server-dom-esm": { + "version": "0.0.0-experimental-5c65b2758-20240322", + "license": "MIT", + "dependencies": { + "acorn-loose": "^8.3.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "0.0.0-experimental-5c65b2758-20240322", + "react-dom": "0.0.0-experimental-5c65b2758-20240322" + } + }, + "node_modules/@babel/runtime": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-loose": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-8.4.0.tgz", + "integrity": "sha512-M0EUka6rb+QC4l9Z3T0nJEzNOO7JcoJlYMrBlyBCiFSXRyxjLKayd4TbQs2FDRWQU1h9FR7QVNHt+PEaoNL5rQ==", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "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" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/concurrently": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", + "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", + "dependencies": { + "chalk": "^4.1.2", + "date-fns": "^2.30.0", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.1.tgz", + "integrity": "sha512-K4w1/Bp7y8iSiVObmCrtq8Cs79XjJc/RU2YYkZQ7wpUu5ZyZ7MtPHkqoMz4pf+mgXfNvo2qft8D9OnrH2ABk9w==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-port": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-7.1.0.tgz", + "integrity": "sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "0.0.0-experimental-2b036d3f1-20240327", + "resolved": "https://registry.npmjs.org/react/-/react-0.0.0-experimental-2b036d3f1-20240327.tgz", + "integrity": "sha512-voyNichNzOf7n+hZYDg7snxYWukBr088SkfQ0jTBIoyWlYRR4MCY/ty/Z5yX2IS+SzyCwgHcuF1yYU3BOpAZvQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "0.0.0-experimental-2b036d3f1-20240327", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-0.0.0-experimental-2b036d3f1-20240327.tgz", + "integrity": "sha512-PLRQJr2Cr34vDjKdNKWP4YAUA0vhUfN1jXvuhiOurpDA6RIINANjDPBpQoASA1Eha/g4Zkey0aDi7rNWOmSqRA==", + "dependencies": { + "scheduler": "0.0.0-experimental-2b036d3f1-20240327" + }, + "peerDependencies": { + "react": "0.0.0-experimental-2b036d3f1-20240327" + } + }, + "node_modules/react-error-boundary": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz", + "integrity": "sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, + "node_modules/react-server-dom-esm": { + "resolved": "built_node_modules/react-server-dom-esm", + "link": true + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/scheduler": { + "version": "0.0.0-experimental-2b036d3f1-20240327", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.0.0-experimental-2b036d3f1-20240327.tgz", + "integrity": "sha512-AfEw/Icx++GJcnRpgbWeOTMmhrfOJqW8cewhzuL26wERWUjpyHI22NGetHSwu6xFU/9GuDfgrV5B308Fyxbk7w==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "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" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", + "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/spawn-command": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "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" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/exercises/02.no-ssr/06.solution.router/package.json b/exercises/02.no-ssr/06.solution.router/package.json new file mode 100644 index 0000000..e85dd2a --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/package.json @@ -0,0 +1,33 @@ +{ + "name": "exercises__sep__02.no-ssr__sep__06.solution.router", + "version": "1.0.0", + "type": "module", + "private": true, + "description": "Super simple implementation of RSCs with minimal deps", + "main": "index.js", + "scripts": { + "dev": "node --watch --import ./server/register-rsc-loader.js --conditions=react-server server/app.js" + }, + "keywords": [], + "author": "Kent C. Dodds (https://kentcdodds.com/)", + "license": "MIT", + "dependencies": { + "body-parser": "^1.20.2", + "busboy": "^1.6.0", + "chalk": "^5.3.0", + "close-with-grace": "^1.3.0", + "compression": "^1.7.4", + "express": "^4.19.1", + "react": "0.0.0-experimental-2b036d3f1-20240327", + "react-dom": "0.0.0-experimental-2b036d3f1-20240327", + "react-error-boundary": "^4.0.13", + "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" + }, + "devDependencies": { + "@types/node": "^20.11.30", + "prettier": "^3.2.5" + }, + "eslintIgnore": [ + "node_modules" + ] +} diff --git a/exercises/02.no-ssr/06.solution.router/public/favicon.ico b/exercises/02.no-ssr/06.solution.router/public/favicon.ico new file mode 100644 index 0000000..890afb6 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/favicon.ico differ diff --git a/exercises/02.no-ssr/06.solution.router/public/favicon.svg b/exercises/02.no-ssr/06.solution.router/public/favicon.svg new file mode 100644 index 0000000..67401c5 --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/public/favicon.svg @@ -0,0 +1,13 @@ + + + + diff --git a/exercises/02.no-ssr/06.solution.router/public/img/broken-ship.webp b/exercises/02.no-ssr/06.solution.router/public/img/broken-ship.webp new file mode 100644 index 0000000..1224fef Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/broken-ship.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/fallback-ship.png b/exercises/02.no-ssr/06.solution.router/public/img/fallback-ship.png new file mode 100644 index 0000000..9622c4b Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/fallback-ship.png differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/0268fc4817ad1.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/0268fc4817ad1.webp new file mode 100644 index 0000000..2238343 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/0268fc4817ad1.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/1ae7b4b92036b.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/1ae7b4b92036b.webp new file mode 100644 index 0000000..410f86d Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/1ae7b4b92036b.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/1ff1991efe029.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/1ff1991efe029.webp new file mode 100644 index 0000000..a0de0c3 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/1ff1991efe029.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/3ba8aa65ffe6c.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/3ba8aa65ffe6c.webp new file mode 100644 index 0000000..32fdb3d Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/3ba8aa65ffe6c.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/441f7092a8d44.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/441f7092a8d44.webp new file mode 100644 index 0000000..658aad9 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/441f7092a8d44.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/5c13d8b28a14a.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/5c13d8b28a14a.webp new file mode 100644 index 0000000..179ef6b Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/5c13d8b28a14a.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/627c497212456.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/627c497212456.webp new file mode 100644 index 0000000..2ded762 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/627c497212456.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/670003aed3795.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/670003aed3795.webp new file mode 100644 index 0000000..4cb1a25 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/670003aed3795.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/6c86fca8b9086.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/6c86fca8b9086.webp new file mode 100644 index 0000000..972f811 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/6c86fca8b9086.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/6f375578ead88.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/6f375578ead88.webp new file mode 100644 index 0000000..37b9c8b Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/6f375578ead88.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/ab267a5984523.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/ab267a5984523.webp new file mode 100644 index 0000000..bf96b34 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/ab267a5984523.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/b442531ea32b2.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/b442531ea32b2.webp new file mode 100644 index 0000000..dde2e65 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/b442531ea32b2.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/bc4cbadf89bd3.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/bc4cbadf89bd3.webp new file mode 100644 index 0000000..d920ab4 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/bc4cbadf89bd3.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/cb03cc4e5717e.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/cb03cc4e5717e.webp new file mode 100644 index 0000000..e79d50c Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/cb03cc4e5717e.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/cfd10fcd2de6c.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/cfd10fcd2de6c.webp new file mode 100644 index 0000000..79521fe Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/cfd10fcd2de6c.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/d3b8aa65ffe6c.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/d3b8aa65ffe6c.webp new file mode 100644 index 0000000..05fb624 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/d3b8aa65ffe6c.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/d486d48b82b81.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/d486d48b82b81.webp new file mode 100644 index 0000000..4933602 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/d486d48b82b81.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/e92cefe4f6727.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/e92cefe4f6727.webp new file mode 100644 index 0000000..377ecba Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/e92cefe4f6727.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/ec7a3f950f99f.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/ec7a3f950f99f.webp new file mode 100644 index 0000000..3457096 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/ec7a3f950f99f.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/f3d9a88e1c234.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/f3d9a88e1c234.webp new file mode 100644 index 0000000..216814c Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/f3d9a88e1c234.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/img/ships/fdc13cb488bf1.webp b/exercises/02.no-ssr/06.solution.router/public/img/ships/fdc13cb488bf1.webp new file mode 100644 index 0000000..fdebeb7 Binary files /dev/null and b/exercises/02.no-ssr/06.solution.router/public/img/ships/fdc13cb488bf1.webp differ diff --git a/exercises/02.no-ssr/06.solution.router/public/index.html b/exercises/02.no-ssr/06.solution.router/public/index.html new file mode 100644 index 0000000..ce15655 --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/public/index.html @@ -0,0 +1,27 @@ + + + + + + + + + Super Simple RSC + + + + +
+ + + diff --git a/exercises/02.no-ssr/06.solution.router/public/style.css b/exercises/02.no-ssr/06.solution.router/public/style.css new file mode 100644 index 0000000..1186ebb --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/public/style.css @@ -0,0 +1,157 @@ +html { + font-family: ui-sans-serif, system-ui; +} + +body { + margin: 0; +} + +* { + box-sizing: border-box; +} + +.app-wrapper { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; +} + +.app { + display: flex; + max-width: 1024px; + border: 1px solid #000; + border-start-end-radius: 0.5rem; + border-start-start-radius: 0.5rem; + border-end-start-radius: 50% 8%; + border-end-end-radius: 50% 8%; + overflow: hidden; +} + +.search { + width: 150px; + max-height: 400px; + overflow: hidden; + display: flex; + flex-direction: column; + + input { + width: 100%; + border: 0; + border-bottom: 1px solid #000; + padding: 8px; + line-height: 1.5; + border-top-left-radius: 0.5rem; + } + + ul { + flex: 1; + list-style: none; + padding: 4px; + padding-bottom: 30px; + margin: 0; + display: flex; + flex-direction: column; + gap: 8px; + overflow-y: auto; + li { + a { + font-size: 0.8rem; + text-decoration: none; + color: black; + padding: 1px 6px; + display: flex; + align-items: center; + gap: 4px; + border: none; + background-color: transparent; + &:hover { + text-decoration: underline; + } + img { + width: 20px; + height: 20px; + object-fit: contain; + border-radius: 50%; + } + } + } + } +} + +.details { + flex: 1; + border-left: 1px solid #000; + height: 400px; + position: relative; + overflow: hidden; +} + +.details > p { + padding: 20px; + width: 300px; +} + +.ship-info { + height: 100%; + width: 300px; + margin: auto; + overflow: auto; + background-color: #eee; + border-radius: 4px; + padding: 20px; + position: relative; +} + +.ship-info.ship-loading { + opacity: 0.6; +} + +.ship-info h2 { + font-weight: bold; + text-align: center; + margin-top: 0.3em; +} + +.ship-info img { + width: 100%; + height: 100%; + aspect-ratio: 1; + object-fit: contain; +} + +.ship-info .ship-info__img-wrapper { + margin-top: 20px; + width: 100%; + height: 200px; +} + +.ship-info .ship-info__fetch-time { + position: absolute; + top: 6px; + right: 10px; +} + +.app-error { + position: relative; + background-image: url('/img/broken-ship.webp'); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + width: 400px; + height: 400px; + p { + position: absolute; + top: 30%; + left: 50%; + transform: translate(-50%, -50%); + background-color: white; + padding: 6px 12px; + border-radius: 1rem; + font-size: 1.5rem; + font-weight: bold; + width: 300px; + text-align: center; + } +} diff --git a/exercises/02.no-ssr/06.solution.router/server/app.js b/exercises/02.no-ssr/06.solution.router/server/app.js new file mode 100644 index 0000000..da5aaaf --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/server/app.js @@ -0,0 +1,85 @@ +import { createRequire } from 'node:module' +import path from 'node:path' +import closeWithGrace from 'close-with-grace' +import compress from 'compression' +import express from 'express' +import { createElement as h } from 'react' +import { renderToPipeableStream } from 'react-server-dom-esm/server' +import { App } from '../src/app.js' +import { shipDataStorage } from './async-storage.js' + +const moduleBasePath = new URL('../src', import.meta.url).href + +const PORT = process.env.PORT || 3000 + +const app = express() + +app.use(compress()) + +app.head('/', (req, res) => res.status(200).end()) + +app.use(express.static('public', { index: false })) +app.use('/js/src', express.static('src')) + +// we have to server this file from our own server so dynamic imports are +// relative to our own server (this module is what loads client-side modules!) +app.use('/js/react-server-dom-esm/client', (req, res) => { + const require = createRequire(import.meta.url) + const pkgPath = require.resolve('react-server-dom-esm') + const modulePath = path.join( + path.dirname(pkgPath), + 'esm', + 'react-server-dom-esm-client.browser.development.js', + ) + res.sendFile(modulePath) +}) + +// This just cleans up the URL if the search ever gets cleared... Not important +// for RSCs... Just ... I just can't help myself. I like URLs clean. +app.use((req, res, next) => { + if (req.query.search === '') { + const searchParams = new URLSearchParams(req.search) + searchParams.delete('search') + const location = [req.path, searchParams.toString()] + .filter(Boolean) + .join('?') + return res.redirect(302, location) + } else { + next() + } +}) + +app.get('/rsc/:shipId?', async function (req, res) { + try { + const shipId = req.params.shipId || null + const search = req.query.search || '' + shipDataStorage.run({ shipId, search }, () => { + const { pipe } = renderToPipeableStream(h(App), moduleBasePath) + pipe(res) + }) + } catch (error) { + console.error(error) + res.status(500).json({ error: error.message }) + } +}) + +app.get('/:shipId?', async function (req, res) { + res.set('Content-type', 'text/html') + return res.sendFile('index.html', { root: 'public' }) +}) + +const server = app.listen(PORT, () => { + console.log(`✅ http://localhost:${PORT}`) +}) + +closeWithGrace(async ({ signal, err }) => { + if (err) console.error('Shutting down server due to error', err) + else console.log('Shutting down server due to signal', signal) + + await new Promise((resolve, reject) => { + server.close(err => { + if (err) reject(err) + else resolve() + }) + }) +}) diff --git a/exercises/02.no-ssr/06.solution.router/server/async-storage.js b/exercises/02.no-ssr/06.solution.router/server/async-storage.js new file mode 100644 index 0000000..b9a08b1 --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/server/async-storage.js @@ -0,0 +1,3 @@ +import { AsyncLocalStorage } from 'node:async_hooks' + +export const shipDataStorage = new AsyncLocalStorage() diff --git a/exercises/02.no-ssr/06.solution.router/server/register-rsc-loader.js b/exercises/02.no-ssr/06.solution.router/server/register-rsc-loader.js new file mode 100644 index 0000000..ba86d1a --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/server/register-rsc-loader.js @@ -0,0 +1,3 @@ +import { register } from 'node:module' + +register('./rsc-loader.js', import.meta.url) diff --git a/exercises/02.no-ssr/06.solution.router/server/rsc-loader.js b/exercises/02.no-ssr/06.solution.router/server/rsc-loader.js new file mode 100644 index 0000000..836ca6f --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/server/rsc-loader.js @@ -0,0 +1,23 @@ +import { resolve, load as reactLoad } from 'react-server-dom-esm/node-loader' + +export { resolve } + +async function textLoad(url, context, defaultLoad) { + const result = await defaultLoad(url, context, defaultLoad) + if (result.format === 'module') { + if (typeof result.source === 'string') { + return result + } + return { + source: Buffer.from(result.source).toString('utf8'), + format: 'module', + } + } + return result +} + +export async function load(url, context, defaultLoad) { + return await reactLoad(url, context, (u, c) => { + return textLoad(u, c, defaultLoad) + }) +} diff --git a/exercises/02.no-ssr/06.solution.router/src/app.js b/exercises/02.no-ssr/06.solution.router/src/app.js new file mode 100644 index 0000000..a6a221b --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/src/app.js @@ -0,0 +1,60 @@ +import { Fragment, Suspense, createElement as h } from 'react' +import { shipDataStorage } from '../server/async-storage.js' +import { ErrorBoundary } from './error-boundary.js' +import { ShipDetails, ShipError, ShipFallback } from './ship-details.js' +import { + SearchResults, + SearchResultsFallback, + ShipResultsErrorFallback, +} from './ship-search-results.js' + +export async function App() { + const { shipId, search } = shipDataStorage.getStore() + return h( + 'div', + { className: 'app' }, + h( + 'div', + { className: 'search' }, + h( + Fragment, + null, + h( + 'form', + {}, + h('input', { + name: 'search', + placeholder: 'Filter ships...', + type: 'search', + defaultValue: search, + autoFocus: true, + }), + ), + h( + ErrorBoundary, + { fallback: h(ShipResultsErrorFallback) }, + h( + 'ul', + null, + h( + Suspense, + { fallback: h(SearchResultsFallback) }, + h(SearchResults), + ), + ), + ), + ), + ), + h( + 'div', + { className: 'details' }, + h( + ErrorBoundary, + { fallback: h(ShipError) }, + shipId + ? h(Suspense, { fallback: h(ShipFallback) }, h(ShipDetails)) + : h('p', null, 'Select a ship from the list to see details'), + ), + ), + ) +} diff --git a/exercises/02.no-ssr/06.solution.router/src/error-boundary.js b/exercises/02.no-ssr/06.solution.router/src/error-boundary.js new file mode 100644 index 0000000..5ab3eca --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/src/error-boundary.js @@ -0,0 +1,3 @@ +'use client' + +export * from 'react-error-boundary' diff --git a/exercises/02.no-ssr/06.solution.router/src/img-utils.js b/exercises/02.no-ssr/06.solution.router/src/img-utils.js new file mode 100644 index 0000000..ef8f4e9 --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/src/img-utils.js @@ -0,0 +1,5 @@ +export const shipFallbackSrc = '/img/fallback-ship.png' + +export function getImageUrlForShip(shipId, { size }) { + return `/img/ships/${shipId}.webp?size=${size}` +} diff --git a/exercises/02.no-ssr/06.solution.router/src/index.js b/exercises/02.no-ssr/06.solution.router/src/index.js new file mode 100644 index 0000000..73438a5 --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/src/index.js @@ -0,0 +1,50 @@ +import { Suspense, createElement as h, startTransition, use } from 'react' +import { createRoot } from 'react-dom/client' +import { ErrorBoundary } from 'react-error-boundary' +import { createFromFetch } from 'react-server-dom-esm/client' +import { shipFallbackSrc } from './img-utils.js' + +const moduleBaseURL = '/js/src' + +const getGlobalLocation = () => + window.location.pathname + window.location.search + +const initialLocation = getGlobalLocation() +const initialContentFetchPromise = fetch(`/rsc${initialLocation}`) +const initialContentPromise = createFromFetch(initialContentFetchPromise, { + moduleBaseURL, +}) + +function Root() { + const content = use(initialContentPromise) + return content +} + +startTransition(() => { + createRoot(document.getElementById('root')).render( + h( + 'div', + { className: 'app-wrapper' }, + h( + ErrorBoundary, + { + fallback: h( + 'div', + { className: 'app-error' }, + h('p', null, 'Something went wrong!'), + ), + }, + h( + Suspense, + { + fallback: h('img', { + style: { maxWidth: 400 }, + src: shipFallbackSrc, + }), + }, + h(Root), + ), + ), + ), + ) +}) diff --git a/exercises/02.no-ssr/06.solution.router/src/ship-details.js b/exercises/02.no-ssr/06.solution.router/src/ship-details.js new file mode 100644 index 0000000..995bf3c --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/src/ship-details.js @@ -0,0 +1,99 @@ +import { createElement as h } from 'react' +import { getShip } from '../db/ship-api.js' +import { shipDataStorage } from '../server/async-storage.js' +import { getImageUrlForShip } from './img-utils.js' + +export async function ShipDetails() { + const { shipId } = shipDataStorage.getStore() + const ship = await getShip({ shipId }) + const shipImgSrc = getImageUrlForShip(ship.id, { size: 200 }) + return h( + 'div', + { className: 'ship-info' }, + h( + 'div', + { className: 'ship-info__img-wrapper' }, + h('img', { src: shipImgSrc, alt: ship.name }), + ), + h('section', null, h('h2', null, ship.name)), + h('div', null, 'Top Speed: ', ship.topSpeed, ' ', h('small', null, 'lyh')), + h( + 'section', + null, + ship.weapons.length + ? h( + 'ul', + null, + ship.weapons.map(weapon => + h( + 'li', + { key: weapon.name }, + h('label', null, weapon.name), + ':', + ' ', + h( + 'span', + null, + weapon.damage, + ' ', + h('small', null, '(', weapon.type, ')'), + ), + ), + ), + ) + : h('p', null, 'NOTE: This ship is not equipped with any weapons.'), + ), + ) +} + +export function ShipFallback() { + const { shipId } = shipDataStorage.getStore() + return h( + 'div', + { className: 'ship-info' }, + h( + 'div', + { className: 'ship-info__img-wrapper' }, + h('img', { + src: getImageUrlForShip(shipId, { size: 200 }), + // TODO: handle this better + alt: shipId, + }), + ), + h('section', null, h('h2', null, 'Loading...')), + h('div', null, 'Top Speed: XX', ' ', h('small', null, 'lyh')), + h( + 'section', + null, + h( + 'ul', + null, + Array.from({ length: 3 }).map((_, i) => + h( + 'li', + { key: i }, + h('label', null, 'loading'), + ':', + ' ', + h('span', null, 'XX ', h('small', null, '(loading)')), + ), + ), + ), + ), + ) +} + +export function ShipError() { + const { shipId } = shipDataStorage.getStore() + return h( + 'div', + { className: 'ship-info' }, + h( + 'div', + { className: 'ship-info__img-wrapper' }, + h('img', { src: '/img/broken-ship.webp', alt: 'broken ship' }), + ), + h('section', null, h('h2', null, 'There was an error')), + h('section', null, 'There was an error loading "', shipId, '"'), + ) +} diff --git a/exercises/02.no-ssr/06.solution.router/src/ship-search-results.js b/exercises/02.no-ssr/06.solution.router/src/ship-search-results.js new file mode 100644 index 0000000..4dd6852 --- /dev/null +++ b/exercises/02.no-ssr/06.solution.router/src/ship-search-results.js @@ -0,0 +1,58 @@ +import { createElement as h } from 'react' +import { searchShips } from '../db/ship-api.js' +import { shipDataStorage } from '../server/async-storage.js' +import { getImageUrlForShip, shipFallbackSrc } from './img-utils.js' + +export async function SearchResults() { + const { shipId: currentShipId, search } = shipDataStorage.getStore() + const shipResults = await searchShips({ search }) + return shipResults.ships.map(ship => { + const href = [ + `/${ship.id}`, + search ? `search=${encodeURIComponent(search)}` : null, + ] + .filter(Boolean) + .join('?') + return h( + 'li', + { key: ship.name }, + h( + 'a', + { + href, + style: { fontWeight: ship.id === currentShipId ? 'bold' : 'normal' }, + }, + h('img', { + src: getImageUrlForShip(ship.id, { size: 20 }), + alt: ship.name, + }), + ship.name, + ), + ) + }) +} + +export function SearchResultsFallback() { + return Array.from({ + length: 12, + }).map((_, i) => + h( + 'li', + { key: i }, + h( + 'a', + { href: '#' }, + h('img', { src: shipFallbackSrc, alt: 'loading' }), + '... loading', + ), + ), + ) +} + +export function ShipResultsErrorFallback() { + return h( + 'div', + { style: { padding: 6, color: '#CD0DD5' } }, + 'There was an error retrieving results', + ) +} diff --git a/exercises/02.no-ssr/11.solution.actions/README.mdx b/exercises/02.no-ssr/11.solution.actions/README.mdx index 102b75c..1060a65 100644 --- a/exercises/02.no-ssr/11.solution.actions/README.mdx +++ b/exercises/02.no-ssr/11.solution.actions/README.mdx @@ -1 +1 @@ -# No SSR +# Actions diff --git a/exercises/02.no-ssr/11.solution.actions/package.json b/exercises/02.no-ssr/11.solution.actions/package.json index 1039454..e490ad6 100644 --- a/exercises/02.no-ssr/11.solution.actions/package.json +++ b/exercises/02.no-ssr/11.solution.actions/package.json @@ -18,10 +18,9 @@ "close-with-grace": "^1.3.0", "compression": "^1.7.4", "express": "^4.19.1", - "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/02.no-ssr/11.solution.actions/public/index.html b/exercises/02.no-ssr/11.solution.actions/public/index.html index 9ca552d..ce15655 100644 --- a/exercises/02.no-ssr/11.solution.actions/public/index.html +++ b/exercises/02.no-ssr/11.solution.actions/public/index.html @@ -10,7 +10,7 @@ "react": "https://esm.sh/react@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom/": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/", - "react-error-boundary": "https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev", + "react-error-boundary": "https://esm.sh/react-error-boundary@4.0.13?pin=126&dev", "react-server-dom-esm/client": "/js/react-server-dom-esm/client" } } diff --git a/exercises/02.no-ssr/11.solution.actions/server/app.js b/exercises/02.no-ssr/11.solution.actions/server/app.js index ff7feb5..eb2da67 100644 --- a/exercises/02.no-ssr/11.solution.actions/server/app.js +++ b/exercises/02.no-ssr/11.solution.actions/server/app.js @@ -39,10 +39,24 @@ app.use('/js/react-server-dom-esm/client', (req, res) => { res.sendFile(modulePath) }) +// This just cleans up the URL if the search ever gets cleared... Not important +// for RSCs... Just ... I just can't help myself. I like URLs clean. +app.use((req, res, next) => { + if (req.query.search === '') { + const searchParams = new URLSearchParams(req.search) + searchParams.delete('search') + const location = [req.path, searchParams.toString()] + .filter(Boolean) + .join('?') + return res.redirect(302, location) + } else { + next() + } +}) + async function renderApp(res, returnValue) { const shipId = res.req.params.shipId || null const search = res.req.query.search || '' - res.set('x-location', res.req.url) shipDataStorage.run({ shipId, search }, () => { const root = h(App) const payload = { returnValue, root } @@ -51,16 +65,11 @@ async function renderApp(res, returnValue) { }) } -app.get('/:shipId?', async function (req, res) { - if (req.accepts('text/html')) { - res.set('Content-type', 'text/html') - return res.sendFile('index.html', { root: 'public' }) - } else { - await renderApp(res, null) - } +app.get('/rsc/:shipId?', async function (req, res) { + await renderApp(res, null) }) -app.post('/:shipId?', bodyParser.text(), async function (req, res) { +app.post('/action/:shipId?', bodyParser.text(), async function (req, res) { const serverReference = req.get('rsc-action') // This is the client-side case const [filepath, name] = serverReference.split('#') @@ -87,6 +96,11 @@ app.post('/:shipId?', bodyParser.text(), async function (req, res) { await renderApp(res, result) }) +app.get('/:shipId?', async function (req, res) { + res.set('Content-type', 'text/html') + return res.sendFile('index.html', { root: 'public' }) +}) + const server = app.listen(PORT, () => { console.log(`✅ http://localhost:${PORT}`) }) diff --git a/exercises/02.no-ssr/11.solution.actions/src/index.js b/exercises/02.no-ssr/11.solution.actions/src/index.js index ed888a5..01d013c 100644 --- a/exercises/02.no-ssr/11.solution.actions/src/index.js +++ b/exercises/02.no-ssr/11.solution.actions/src/index.js @@ -17,7 +17,7 @@ const getGlobalLocation = () => window.location.pathname + window.location.search function fetchContent(location) { - return fetch(location, { headers: { Accept: 'text/x-component' } }) + return fetch(`/rsc${location}`) } const moduleBaseURL = '/js/src' @@ -37,15 +37,17 @@ function createFromFetch(fetchPromise) { async function callServer(id, args) { // using the global location to avoid a stale closure over the location - const fetchPromise = fetch(getGlobalLocation(), { + const fetchPromise = fetch(`/action${getGlobalLocation()}`, { method: 'POST', headers: { Accept: 'text/x-component', 'rsc-action': id }, body: await RSC.encodeReply(args), }) + const contentKey = window.history.state?.key ?? generateKey() + onStreamFinished(fetchPromise, () => { + updateContentKey(contentKey, true) + }) const actionResponsePromise = createFromFetch(fetchPromise) - const newContentKey = generateKey() - contentCache.set(newContentKey, actionResponsePromise) - updateContentKey(newContentKey) + contentCache.set(contentKey, actionResponsePromise) const { returnValue } = await actionResponsePromise return returnValue } @@ -60,6 +62,17 @@ if (!initialContentKey) { } contentCache.set(initialContentKey, initialContentPromise) +function onStreamFinished(fetchPromise, onFinished) { + // create a promise chain that resolves when the stream is completely consumed + return ( + fetchPromise + // clone the response so createFromFetch can use it (otherwise we lock the reader) + // and wait for the text to be consumed so we know the stream is finished + .then(response => response.clone().text()) + .then(onFinished) + ) +} + export function Root() { const [, forceRender] = useReducer(() => Symbol(), Symbol()) const latestNav = useRef(null) @@ -69,8 +82,9 @@ export function Root() { // update the updateContentKey function to the latest every render useEffect(() => { - updateContentKey = newContentKey => { + updateContentKey = (newContentKey, triggerRerender = false) => { startTransition(() => setContentKey(newContentKey)) + if (triggerRerender) forceRender() } }) @@ -88,18 +102,13 @@ export function Root() { let nextContentPromise const fetchPromise = fetchContent(nextLocation) - // create a promise chain that resolves when the stream is completely consumed - fetchPromise - // clone the response so createFromFetch can use it (otherwise we lock the reader) - // and wait for the text to be consumed so we know the stream is finished - .then(response => response.clone().text()) - .then(() => { - contentCache.set(historyKey, nextContentPromise) - if (thisNav === latestNav.current) { - // trigger a rerender now that the updated content is in the cache - startTransition(() => forceRender()) - } - }) + onStreamFinished(fetchPromise, () => { + contentCache.set(historyKey, nextContentPromise) + if (thisNav === latestNav.current) { + // trigger a rerender now that the updated content is in the cache + startTransition(() => forceRender()) + } + }) nextContentPromise = createFromFetch(fetchPromise) if (!contentCache.has(historyKey)) { @@ -122,11 +131,10 @@ export function Root() { const nextContentPromise = createFromFetch( fetchContent(nextLocation).then(response => { if (thisNav !== latestNav.current) return - const newLocation = response.headers.get('x-location') if (replace) { - window.history.replaceState({ key: newContentKey }, '', newLocation) + window.history.replaceState({ key: newContentKey }, '', nextLocation) } else { - window.history.pushState({ key: newContentKey }, '', newLocation) + window.history.pushState({ key: newContentKey }, '', nextLocation) } return response }), diff --git a/exercises/02.no-ssr/12.solution.ssr/package.json b/exercises/02.no-ssr/12.solution.ssr/package.json index b38142b..4dbb17e 100644 --- a/exercises/02.no-ssr/12.solution.ssr/package.json +++ b/exercises/02.no-ssr/12.solution.ssr/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/02.no-ssr/12.solution.ssr/server/ssr.js b/exercises/02.no-ssr/12.solution.ssr/server/ssr.js index c9ea08b..ef8c222 100644 --- a/exercises/02.no-ssr/12.solution.ssr/server/ssr.js +++ b/exercises/02.no-ssr/12.solution.ssr/server/ssr.js @@ -101,7 +101,7 @@ app.all('/:shipId?', async function (req, res) { 'react-dom/': 'https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/', 'react-error-boundary': - 'https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev', + 'https://esm.sh/react-error-boundary@4.0.13?pin=126&dev', 'react-server-dom-esm/client': '/js/react-server-dom-esm/client', }, }, diff --git a/exercises/03.rsc/01.solution.super-simple/package.json b/exercises/03.rsc/01.solution.super-simple/package.json index 7ee39c2..3d43691 100644 --- a/exercises/03.rsc/01.solution.super-simple/package.json +++ b/exercises/03.rsc/01.solution.super-simple/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/03.rsc/01.solution.super-simple/public/index.html b/exercises/03.rsc/01.solution.super-simple/public/index.html index 7bc7f7d..859a7f4 100644 --- a/exercises/03.rsc/01.solution.super-simple/public/index.html +++ b/exercises/03.rsc/01.solution.super-simple/public/index.html @@ -9,7 +9,7 @@ "react": "https://esm.sh/react@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom/": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/", - "react-error-boundary": "https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev", + "react-error-boundary": "https://esm.sh/react-error-boundary@4.0.13?pin=126&dev", "react-server-dom-esm/client": "/js/react-server-dom-esm/client" } } diff --git a/exercises/03.rsc/02.solution.with-actions/package.json b/exercises/03.rsc/02.solution.with-actions/package.json index 6cd1410..2f20180 100644 --- a/exercises/03.rsc/02.solution.with-actions/package.json +++ b/exercises/03.rsc/02.solution.with-actions/package.json @@ -21,7 +21,7 @@ "get-port": "^7.1.0", "react": "0.0.0-experimental-2b036d3f1-20240327", "react-dom": "0.0.0-experimental-2b036d3f1-20240327", - "react-error-boundary": "npm:@kentcdodds/temp-react-error-boundary@4.0.13", + "react-error-boundary": "^4.0.13", "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" }, "devDependencies": { diff --git a/exercises/03.rsc/02.solution.with-actions/public/index.html b/exercises/03.rsc/02.solution.with-actions/public/index.html index 7bc7f7d..859a7f4 100644 --- a/exercises/03.rsc/02.solution.with-actions/public/index.html +++ b/exercises/03.rsc/02.solution.with-actions/public/index.html @@ -9,7 +9,7 @@ "react": "https://esm.sh/react@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327?pin=v126&dev", "react-dom/": "https://esm.sh/react-dom@0.0.0-experimental-2b036d3f1-20240327&pin=v126&dev/", - "react-error-boundary": "https://esm.sh/@kentcdodds/temp-react-error-boundary@4.0.13?pin=126&dev", + "react-error-boundary": "https://esm.sh/react-error-boundary@4.0.13?pin=126&dev", "react-server-dom-esm/client": "/js/react-server-dom-esm/client" } } diff --git a/package-lock.json b/package-lock.json index 933d803..7e95628 100644 --- a/package-lock.json +++ b/package-lock.json @@ -686,6 +686,297 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "exercises/02.no-ssr/01.solution.start": { + "name": "exercises__sep__02.no-ssr__sep__01.solution.start", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "body-parser": "^1.20.2", + "busboy": "^1.6.0", + "chalk": "^5.3.0", + "close-with-grace": "^1.3.0", + "compression": "^1.7.4", + "express": "^4.19.1", + "react": "0.0.0-experimental-2b036d3f1-20240327", + "react-dom": "0.0.0-experimental-2b036d3f1-20240327", + "react-error-boundary": "^4.0.13", + "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" + }, + "devDependencies": { + "@types/node": "^20.11.30", + "prettier": "^3.2.5" + } + }, + "exercises/02.no-ssr/01.solution.start/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "exercises/02.no-ssr/02.solution.rsc": { + "name": "exercises__sep__02.no-ssr__sep__02.solution.rsc", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "body-parser": "^1.20.2", + "busboy": "^1.6.0", + "chalk": "^5.3.0", + "close-with-grace": "^1.3.0", + "compression": "^1.7.4", + "express": "^4.19.1", + "react": "0.0.0-experimental-2b036d3f1-20240327", + "react-dom": "0.0.0-experimental-2b036d3f1-20240327", + "react-error-boundary": "^4.0.13", + "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" + }, + "devDependencies": { + "@types/node": "^20.11.30", + "prettier": "^3.2.5" + } + }, + "exercises/02.no-ssr/02.solution.rsc/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "exercises/02.no-ssr/03.solution.streaming": { + "name": "exercises__sep__02.no-ssr__sep__03.solution.streaming", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "body-parser": "^1.20.2", + "busboy": "^1.6.0", + "chalk": "^5.3.0", + "close-with-grace": "^1.3.0", + "compression": "^1.7.4", + "express": "^4.19.1", + "react": "0.0.0-experimental-2b036d3f1-20240327", + "react-dom": "0.0.0-experimental-2b036d3f1-20240327", + "react-error-boundary": "^4.0.13", + "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" + }, + "devDependencies": { + "@types/node": "^20.11.30", + "prettier": "^3.2.5" + } + }, + "exercises/02.no-ssr/03.solution.streaming/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "exercises/02.no-ssr/04.solution.server-context": { + "name": "exercises__sep__02.no-ssr__sep__04.solution.server-context", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "body-parser": "^1.20.2", + "busboy": "^1.6.0", + "chalk": "^5.3.0", + "close-with-grace": "^1.3.0", + "compression": "^1.7.4", + "express": "^4.19.1", + "react": "0.0.0-experimental-2b036d3f1-20240327", + "react-dom": "0.0.0-experimental-2b036d3f1-20240327", + "react-error-boundary": "^4.0.13", + "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" + }, + "devDependencies": { + "@types/node": "^20.11.30", + "prettier": "^3.2.5" + } + }, + "exercises/02.no-ssr/04.solution.server-context/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "exercises/02.no-ssr/05.solution.client": { + "name": "exercises__sep__02.no-ssr__sep__05.solution.client", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "body-parser": "^1.20.2", + "busboy": "^1.6.0", + "chalk": "^5.3.0", + "close-with-grace": "^1.3.0", + "compression": "^1.7.4", + "express": "^4.19.1", + "react": "0.0.0-experimental-2b036d3f1-20240327", + "react-dom": "0.0.0-experimental-2b036d3f1-20240327", + "react-error-boundary": "^4.0.13", + "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" + }, + "devDependencies": { + "@types/node": "^20.11.30", + "prettier": "^3.2.5" + } + }, + "exercises/02.no-ssr/05.solution.client/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "exercises/02.no-ssr/11.solution.actions": { + "name": "exercises__sep__02.no-ssr__sep__11.solution.actions", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "body-parser": "^1.20.2", + "busboy": "^1.6.0", + "chalk": "^5.3.0", + "close-with-grace": "^1.3.0", + "compression": "^1.7.4", + "express": "^4.19.1", + "react": "0.0.0-experimental-2b036d3f1-20240327", + "react-dom": "0.0.0-experimental-2b036d3f1-20240327", + "react-error-boundary": "^4.0.13", + "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" + }, + "devDependencies": { + "@types/node": "^20.11.30", + "prettier": "^3.2.5" + } + }, + "exercises/02.no-ssr/11.solution.actions/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "exercises/02.no-ssr/12.solution.ssr": { + "name": "exercises__sep__02.no-ssr__sep__12.solution.ssr", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "body-parser": "^1.20.2", + "busboy": "^1.6.0", + "chalk": "^5.3.0", + "close-with-grace": "^1.3.0", + "compression": "^1.7.4", + "express": "^4.19.1", + "get-port": "^7.1.0", + "react": "0.0.0-experimental-2b036d3f1-20240327", + "react-dom": "0.0.0-experimental-2b036d3f1-20240327", + "react-error-boundary": "^4.0.13", + "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" + }, + "devDependencies": { + "@types/node": "^20.11.30", + "prettier": "^3.2.5" + } + }, + "exercises/02.no-ssr/12.solution.ssr/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "exercises/03.rsc/01.solution.super-simple": { + "name": "exercises__sep__03.rsc__sep__01.solution.super-simple", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "body-parser": "^1.20.2", + "busboy": "^1.6.0", + "chalk": "^5.3.0", + "close-with-grace": "^1.3.0", + "compression": "^1.7.4", + "express": "^4.19.1", + "get-port": "^7.1.0", + "react": "0.0.0-experimental-2b036d3f1-20240327", + "react-dom": "0.0.0-experimental-2b036d3f1-20240327", + "react-error-boundary": "^4.0.13", + "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" + }, + "devDependencies": { + "@types/node": "^20.11.30", + "prettier": "^3.2.5" + } + }, + "exercises/03.rsc/01.solution.super-simple/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "exercises/03.rsc/02.solution.with-actions": { + "name": "exercises__sep__03.rsc__sep__02.solution.with-actions", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "body-parser": "^1.20.2", + "busboy": "^1.6.0", + "chalk": "^5.3.0", + "close-with-grace": "^1.3.0", + "compression": "^1.7.4", + "express": "^4.19.1", + "get-port": "^7.1.0", + "react": "0.0.0-experimental-2b036d3f1-20240327", + "react-dom": "0.0.0-experimental-2b036d3f1-20240327", + "react-error-boundary": "^4.0.13", + "react-server-dom-esm": "npm:@kentcdodds/tmp-react-server-dom-esm@0.0.0-experimental-2b036d3f1-20240327" + }, + "devDependencies": { + "@types/node": "^20.11.30", + "prettier": "^3.2.5" + } + }, + "exercises/03.rsc/02.solution.with-actions/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", @@ -825,9 +1116,9 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" }, "node_modules/@types/node": { - "version": "20.11.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", - "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "version": "20.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz", + "integrity": "sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -1441,9 +1732,9 @@ } }, "node_modules/es-abstract": { - "version": "1.23.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", - "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", @@ -1484,11 +1775,11 @@ "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.9", "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.7", + "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.2", "typed-array-byte-length": "^1.0.1", "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.5", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", "which-typed-array": "^1.1.15" }, @@ -1918,6 +2209,42 @@ "resolved": "exercises/01.exercises/10.solution.actions", "link": true }, + "node_modules/exercises__sep__02.no-ssr__sep__01.solution.start": { + "resolved": "exercises/02.no-ssr/01.solution.start", + "link": true + }, + "node_modules/exercises__sep__02.no-ssr__sep__02.solution.rsc": { + "resolved": "exercises/02.no-ssr/02.solution.rsc", + "link": true + }, + "node_modules/exercises__sep__02.no-ssr__sep__03.solution.streaming": { + "resolved": "exercises/02.no-ssr/03.solution.streaming", + "link": true + }, + "node_modules/exercises__sep__02.no-ssr__sep__04.solution.server-context": { + "resolved": "exercises/02.no-ssr/04.solution.server-context", + "link": true + }, + "node_modules/exercises__sep__02.no-ssr__sep__05.solution.client": { + "resolved": "exercises/02.no-ssr/05.solution.client", + "link": true + }, + "node_modules/exercises__sep__02.no-ssr__sep__11.solution.actions": { + "resolved": "exercises/02.no-ssr/11.solution.actions", + "link": true + }, + "node_modules/exercises__sep__02.no-ssr__sep__12.solution.ssr": { + "resolved": "exercises/02.no-ssr/12.solution.ssr", + "link": true + }, + "node_modules/exercises__sep__03.rsc__sep__01.solution.super-simple": { + "resolved": "exercises/03.rsc/01.solution.super-simple", + "link": true + }, + "node_modules/exercises__sep__03.rsc__sep__02.solution.with-actions": { + "resolved": "exercises/03.rsc/02.solution.with-actions", + "link": true + }, "node_modules/express": { "version": "4.19.2", "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",