├── .gitignore ├── LICENSE ├── README.md ├── build.js ├── build ├── server.js └── server.js.map ├── demo ├── entry-client.js ├── entry-server.js ├── pages │ └── index.js └── routes.js ├── package.json ├── public └── build │ ├── entry-client.js │ └── entry-client.js.map ├── server.js ├── src ├── client │ └── index.js ├── index.js ├── loadable.js ├── match-route.js ├── react-shim.js ├── render-app.js └── server │ └── request.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 伊撒尔 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fremix 2 | Remix for fre 3 | -------------------------------------------------------------------------------- /build.js: -------------------------------------------------------------------------------- 1 | const esbuild = require('esbuild'); 2 | const pkg = require('./package.json'); 3 | 4 | const isProd = process.env.NODE_ENV === 'production'; 5 | const shouldWatch = process.env.WATCH === 'true' 6 | 7 | const buildServer = () => { 8 | esbuild.build({ 9 | entryPoints: ['./server.js'], 10 | platform: 'node', 11 | outdir: 'build', 12 | loader:{ '.js': 'jsx' }, 13 | external: [ 14 | ...Object.keys(pkg.dependencies), 15 | ...Object.keys(pkg.devDependencies), 16 | ], 17 | inject: ['./src/react-shim.js'], 18 | bundle: true, 19 | watch: shouldWatch, 20 | publicPath: '/build', 21 | plugins: [], 22 | define: { 23 | 'process.env.NODE_ENV': isProd ? "'production'" : "'development'", 24 | }, 25 | metafile: true, 26 | sourcemap: true, 27 | }) 28 | } 29 | 30 | const buildClient = () => { 31 | esbuild.build({ 32 | entryPoints: ['./demo/entry-client.js'], 33 | platform: 'node', 34 | outdir: 'public/build', 35 | format: 'esm', 36 | loader: { '.js': 'jsx' }, 37 | // splitting: true, 38 | inject: ['./src/react-shim.js'], 39 | bundle: true, 40 | watch: shouldWatch, 41 | publicPath: '/build', 42 | plugins: [], 43 | define: { 44 | 'process.env.NODE_ENV': isProd ? "'production'" : "'development'", 45 | }, 46 | metafile: true, 47 | sourcemap: true, 48 | }) 49 | } 50 | 51 | async function build() { 52 | await Promise.all([buildServer(), buildClient()]); 53 | } 54 | 55 | build() -------------------------------------------------------------------------------- /build/server.js: -------------------------------------------------------------------------------- 1 | var __create = Object.create; 2 | var __defProp = Object.defineProperty; 3 | var __getOwnPropDesc = Object.getOwnPropertyDescriptor; 4 | var __getOwnPropNames = Object.getOwnPropertyNames; 5 | var __getProtoOf = Object.getPrototypeOf; 6 | var __hasOwnProp = Object.prototype.hasOwnProperty; 7 | var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); 8 | var __esm = (fn, res) => function __init() { 9 | return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; 10 | }; 11 | var __export = (target, all) => { 12 | for (var name in all) 13 | __defProp(target, name, { get: all[name], enumerable: true }); 14 | }; 15 | var __reExport = (target, module2, copyDefault, desc) => { 16 | if (module2 && typeof module2 === "object" || typeof module2 === "function") { 17 | for (let key of __getOwnPropNames(module2)) 18 | if (!__hasOwnProp.call(target, key) && (copyDefault || key !== "default")) 19 | __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable }); 20 | } 21 | return target; 22 | }; 23 | var __toESM = (module2, isNodeMode) => { 24 | return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", !isNodeMode && module2 && module2.__esModule ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2); 25 | }; 26 | 27 | // src/react-shim.js 28 | var React; 29 | var init_react_shim = __esm({ 30 | "src/react-shim.js"() { 31 | React = __toESM(require("react")); 32 | } 33 | }); 34 | 35 | // src/index.js 36 | var import_react2, RouteDataContext, useLoaderData; 37 | var init_src = __esm({ 38 | "src/index.js"() { 39 | init_react_shim(); 40 | import_react2 = __toESM(require("react")); 41 | RouteDataContext = (0, import_react2.createContext)(null); 42 | useLoaderData = () => { 43 | const context = (0, import_react2.useContext)(RouteDataContext); 44 | if (typeof window !== "undefined") { 45 | return window.__fremix_data; 46 | } 47 | return context; 48 | }; 49 | } 50 | }); 51 | 52 | // demo/pages/index.js 53 | var pages_exports = {}; 54 | __export(pages_exports, { 55 | default: () => Home, 56 | loader: () => loader 57 | }); 58 | function Home() { 59 | const { posts } = useLoaderData(); 60 | console.log(posts); 61 | return /* @__PURE__ */ React.createElement(React.Fragment, null, posts.map((post) => /* @__PURE__ */ React.createElement("li", { 62 | key: post 63 | }, post))); 64 | } 65 | var loader; 66 | var init_pages = __esm({ 67 | "demo/pages/index.js"() { 68 | init_react_shim(); 69 | init_src(); 70 | loader = async () => { 71 | return { 72 | posts: ["yisar", 132] 73 | }; 74 | }; 75 | } 76 | }); 77 | 78 | // server.js 79 | init_react_shim(); 80 | var import_express = __toESM(require("express")); 81 | 82 | // src/render-app.js 83 | init_react_shim(); 84 | 85 | // demo/routes.js 86 | init_react_shim(); 87 | 88 | // src/loadable.js 89 | init_react_shim(); 90 | var import_react = require("react"); 91 | function useForceUpdate() { 92 | const [, dispatch] = (0, import_react.useState)({}); 93 | const forceUpdate = (0, import_react.useCallback)(() => { 94 | dispatch({}); 95 | }, []); 96 | return forceUpdate; 97 | } 98 | function loadable(importFn, { fallback = () => null } = {}) { 99 | return function LoadableComponent(props) { 100 | const component = (0, import_react.useRef)(fallback); 101 | const forceUpdate = useForceUpdate(); 102 | (0, import_react.useEffect)(() => { 103 | importFn(props).then((mod) => { 104 | component.current = mod.default; 105 | forceUpdate(); 106 | }); 107 | }, []); 108 | return /* @__PURE__ */ React.createElement(component.current, { 109 | ...props 110 | }); 111 | }; 112 | } 113 | 114 | // demo/routes.js 115 | var routes = makeRoutes([ 116 | { 117 | path: "/", 118 | page: () => Promise.resolve().then(() => (init_pages(), pages_exports)) 119 | } 120 | ]); 121 | function makeRoutes(routes2) { 122 | return routes2.map((route) => ({ 123 | ...route, 124 | component: route.component || loadable(route.page) 125 | })); 126 | } 127 | 128 | // src/match-route.js 129 | init_react_shim(); 130 | var import_regexparam = __toESM(require("regexparam")); 131 | function matchRoute(route, toMatch) { 132 | const routeRegex = (0, import_regexparam.default)(route); 133 | return routeRegex.pattern.test(toMatch); 134 | } 135 | 136 | // src/render-app.js 137 | init_src(); 138 | async function renderApp(url) { 139 | const urlWithoutQuery = new URL(`https://example.com${url}`).pathname; 140 | const route = routes.find((x) => matchRoute(x.path, urlWithoutQuery)); 141 | if (!route) { 142 | return { notFound: true }; 143 | } 144 | const page = await route.page(); 145 | const data = await page.loader(); 146 | const component = page.default; 147 | return () => { 148 | return /* @__PURE__ */ React.createElement(RouteDataContext.Provider, { 149 | value: data 150 | }, /* @__PURE__ */ React.createElement(App, { 151 | Component: component, 152 | data 153 | })); 154 | }; 155 | } 156 | function App({ Component, data }) { 157 | return /* @__PURE__ */ React.createElement("html", { 158 | lang: "en" 159 | }, /* @__PURE__ */ React.createElement("head", null, /* @__PURE__ */ React.createElement("meta", { 160 | charSet: "UTF-8" 161 | }), /* @__PURE__ */ React.createElement("meta", { 162 | name: "viewport", 163 | content: "width=device-width, initial-scale=1.0" 164 | })), /* @__PURE__ */ React.createElement("body", null, /* @__PURE__ */ React.createElement("template", { 165 | id: "__fremix_data" 166 | }, JSON.stringify(data)), /* @__PURE__ */ React.createElement("div", { 167 | id: "__fremix" 168 | }, /* @__PURE__ */ React.createElement(Component, null)), /* @__PURE__ */ React.createElement("script", { 169 | src: "/build/entry-client.js" 170 | }))); 171 | } 172 | 173 | // demo/entry-server.js 174 | init_react_shim(); 175 | var import_server = __toESM(require("react-dom/server")); 176 | function handleRequest(App2) { 177 | const markup = import_server.default.renderToString(/* @__PURE__ */ React.createElement(App2, null)); 178 | return `${markup}`; 179 | } 180 | 181 | // server.js 182 | var import_ohmyfetch = require("ohmyfetch"); 183 | global.fetch = import_ohmyfetch.$fetch; 184 | var app = (0, import_express.default)(); 185 | app.use(import_express.default.static("public")); 186 | app.use(import_express.default.json()); 187 | app.use(import_express.default.urlencoded({ extended: true })); 188 | app.use("/", async function(req, res) { 189 | const RemixApp = await renderApp(req.originalUrl); 190 | if (RemixApp.notFound === true) { 191 | return res.status(404).send("Page not found"); 192 | } 193 | const html = handleRequest(RemixApp); 194 | res.setHeader("content-type", "text/html"); 195 | res.send(html); 196 | }); 197 | app.listen(3e3, () => { 198 | console.log("Server started on http://localhost:3000"); 199 | }); 200 | //# sourceMappingURL=/build/server.js.map 201 | -------------------------------------------------------------------------------- /build/server.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "sources": ["../src/react-shim.js", "../src/index.js", "../demo/pages/index.js", "../server.js", "../src/render-app.js", "../demo/routes.js", "../src/loadable.js", "../src/match-route.js", "../demo/entry-server.js"], 4 | "sourcesContent": ["export * as React from 'react';", "import React, { createContext, useContext } from \"react\";\r\n\r\nexport const RouteDataContext = createContext(null)\r\n\r\nexport const useLoaderData = () => {\r\n const context = useContext(RouteDataContext);\r\n\r\n if (typeof window !== 'undefined'){\r\n return window.__fremix_data\r\n }\r\n\r\n return context;\r\n}", "import { useLoaderData } from '../../src/index';\n\nexport const loader = async () => {\n return {\n posts: ['yisar', 132],\n };\n};\n\nexport default function Home() {\n const { posts } = useLoaderData();\n\n console.log(posts)\n\n return (\n <>\n {posts.map(post => (\n
  • {post}\n
  • \n ))}\n \n );\n}\n", "import express from 'express';\r\nimport { renderApp } from './src/render-app';\r\nimport handleRequest from './demo/entry-server'\r\nimport { $fetch } from 'ohmyfetch'\r\n\r\nglobal.fetch = $fetch\r\n\r\n\r\nconst app = express();\r\n\r\napp.use(express.static('public'));\r\napp.use(express.json());\r\napp.use(express.urlencoded({ extended: true }));\r\n\r\napp.use('/', async function (req, res) {\r\n const RemixApp = await renderApp(req.originalUrl);\r\n\r\n if (RemixApp.notFound === true) {\r\n return res.status(404).send('Page not found');\r\n }\r\n\r\n const html = handleRequest(RemixApp);\r\n res.setHeader('content-type', 'text/html');\r\n res.send(html);\r\n});\r\n\r\napp.listen(3000, () => {\r\n console.log('Server started on http://localhost:3000');\r\n})", "import { routes } from \"../demo/routes\";\r\nimport matchRoute from \"./match-route\";\r\nimport {RouteDataContext} from './index'\r\n\r\nexport async function renderApp(url) {\r\n const urlWithoutQuery = new URL(`https://example.com${url}`).pathname;\r\n const route = routes.find(x => matchRoute(x.path, urlWithoutQuery))\r\n if (!route) {\r\n return { notFound: true }\r\n }\r\n const page = await route.page()\r\n const data = await page.loader()\r\n const component = page.default\r\n\r\n return () => {\r\n return \r\n }\r\n}\r\n\r\nexport function App({ Component, data }) {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
    \r\n \r\n
    \r\n \r\n \r\n \r\n );\r\n}", "import loadable from '../src/loadable';\n\nexport const routes = makeRoutes([\n {\n path: '/',\n page: () => import('./pages'),\n }\n]);\n\nfunction makeRoutes(\n routes\n) {\n return routes.map(route => ({\n ...route,\n component: route.component || loadable(route.page),\n }));\n}\n", "import { useRef, useEffect, useCallback, useState } from 'react';\r\n\r\nfunction useForceUpdate() {\r\n const [, dispatch] = useState({});\r\n\r\n const forceUpdate = useCallback(() => {\r\n dispatch({});\r\n }, []);\r\n\r\n return forceUpdate;\r\n}\r\n\r\nexport default function loadable(importFn, { fallback = () => null } = {}) {\r\n return function LoadableComponent(props) {\r\n const component = useRef(fallback);\r\n const forceUpdate = useForceUpdate();\r\n\r\n useEffect(() => {\r\n importFn(props).then(mod => {\r\n component.current = mod.default;\r\n forceUpdate();\r\n });\r\n }, []);\r\n\r\n return ;\r\n };\r\n}", "import param from 'regexparam'\r\n\r\nexport default function matchRoute(route, toMatch) {\r\n const routeRegex = param(route);\r\n return routeRegex.pattern.test(toMatch);\r\n}", "import ReactDOMServer from 'react-dom/server';\n\nexport default function handleRequest(App) {\n const markup = ReactDOMServer.renderToString();\n return `${markup}`;\n}\n"], 5 | "mappings": "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", 6 | "names": [] 7 | } 8 | -------------------------------------------------------------------------------- /demo/entry-client.js: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom'; 2 | import { Route,Switch } from "wouter" 3 | import matchRoute from '../src/match-route'; 4 | import { routes } from './routes'; 5 | import { App } from '../src/render-app'; 6 | 7 | const fremixData = document.getElementById('__fremix_data'); 8 | window.__fremix_data = JSON.parse(fremixData.innerHTML) 9 | 10 | function Router() { 11 | return ( 12 | 13 | {routes.map(route => ( 14 | 20 | ))} 21 | 22 | ); 23 | } 24 | 25 | async function init() { 26 | const route = routes.find(x => matchRoute(x.path, window.location.pathname)); 27 | await route.page(); 28 | 29 | ReactDOM.render( 30 | , document 31 | ); 32 | } 33 | 34 | init(); 35 | -------------------------------------------------------------------------------- /demo/entry-server.js: -------------------------------------------------------------------------------- 1 | import ReactDOMServer from 'react-dom/server'; 2 | 3 | export default function handleRequest(App) { 4 | const markup = ReactDOMServer.renderToString(); 5 | return `${markup}`; 6 | } 7 | -------------------------------------------------------------------------------- /demo/pages/index.js: -------------------------------------------------------------------------------- 1 | import { useLoaderData } from '../../src/index'; 2 | 3 | export const loader = async () => { 4 | return { 5 | posts: ['yisar', 132], 6 | }; 7 | }; 8 | 9 | export default function Home() { 10 | const { posts } = useLoaderData(); 11 | 12 | console.log(posts) 13 | 14 | return ( 15 | <> 16 | {posts.map(post => ( 17 |
  • {post} 18 |
  • 19 | ))} 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /demo/routes.js: -------------------------------------------------------------------------------- 1 | import loadable from '../src/loadable'; 2 | 3 | export const routes = makeRoutes([ 4 | { 5 | path: '/', 6 | page: () => import('./pages'), 7 | } 8 | ]); 9 | 10 | function makeRoutes( 11 | routes 12 | ) { 13 | return routes.map(route => ({ 14 | ...route, 15 | component: route.component || loadable(route.page), 16 | })); 17 | } 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fremix", 3 | "version": "1.0.0", 4 | "description": "Remix for fre", 5 | "main": "build.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node build.js && node ./build/server.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/yisar/fremix.git" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/yisar/fremix/issues" 19 | }, 20 | "homepage": "https://github.com/yisar/fremix#readme", 21 | "dependencies": { 22 | "ohmyfetch": "^0.4.15", 23 | "react": "^17.0.2", 24 | "react-dom": "^17.0.2", 25 | "wouter": "^2.8.0-alpha.2" 26 | }, 27 | "devDependencies": { 28 | "esbuild": "^0.14.25", 29 | "express": "^4.17.3", 30 | "react-router-dom": "^6.2.2", 31 | "regexparam": "1.3.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import { renderApp } from './src/render-app'; 3 | import handleRequest from './demo/entry-server' 4 | import { $fetch } from 'ohmyfetch' 5 | 6 | global.fetch = $fetch 7 | 8 | 9 | const app = express(); 10 | 11 | app.use(express.static('public')); 12 | app.use(express.json()); 13 | app.use(express.urlencoded({ extended: true })); 14 | 15 | app.use('/', async function (req, res) { 16 | const RemixApp = await renderApp(req.originalUrl); 17 | 18 | if (RemixApp.notFound === true) { 19 | return res.status(404).send('Page not found'); 20 | } 21 | 22 | const html = handleRequest(RemixApp); 23 | res.setHeader('content-type', 'text/html'); 24 | res.send(html); 25 | }); 26 | 27 | app.listen(3000, () => { 28 | console.log('Server started on http://localhost:3000'); 29 | }) -------------------------------------------------------------------------------- /src/client/index.js: -------------------------------------------------------------------------------- 1 | import { useLoaderData } from '../index'; 2 | import { routes } from '../../demo/routes'; 3 | import matchRoute from '../match-route'; 4 | 5 | export function useFetchRouteData() { 6 | const [, setRouteData] = useLoaderData(); 7 | 8 | return async (url) => { 9 | console.log('FETCHING'); 10 | const route = routes.find(x => matchRoute(x.path, url)); 11 | const res = await fetch(`/data?path=${route.path}&href=${url}`); 12 | const data = await res.json(); 13 | 14 | setRouteData(data.data.props); 15 | setRemix(data); 16 | console.log('SET'); 17 | }; 18 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React, { createContext, useContext } from "react"; 2 | 3 | export const RouteDataContext = createContext(null) 4 | 5 | export const useLoaderData = () => { 6 | const context = useContext(RouteDataContext); 7 | 8 | if (typeof window !== 'undefined'){ 9 | return window.__fremix_data 10 | } 11 | 12 | return context; 13 | } -------------------------------------------------------------------------------- /src/loadable.js: -------------------------------------------------------------------------------- 1 | import { useRef, useEffect, useCallback, useState } from 'react'; 2 | 3 | function useForceUpdate() { 4 | const [, dispatch] = useState({}); 5 | 6 | const forceUpdate = useCallback(() => { 7 | dispatch({}); 8 | }, []); 9 | 10 | return forceUpdate; 11 | } 12 | 13 | export default function loadable(importFn, { fallback = () => null } = {}) { 14 | return function LoadableComponent(props) { 15 | const component = useRef(fallback); 16 | const forceUpdate = useForceUpdate(); 17 | 18 | useEffect(() => { 19 | importFn(props).then(mod => { 20 | component.current = mod.default; 21 | forceUpdate(); 22 | }); 23 | }, []); 24 | 25 | return ; 26 | }; 27 | } -------------------------------------------------------------------------------- /src/match-route.js: -------------------------------------------------------------------------------- 1 | import param from 'regexparam' 2 | 3 | export default function matchRoute(route, toMatch) { 4 | const routeRegex = param(route); 5 | return routeRegex.pattern.test(toMatch); 6 | } -------------------------------------------------------------------------------- /src/react-shim.js: -------------------------------------------------------------------------------- 1 | export * as React from 'react'; -------------------------------------------------------------------------------- /src/render-app.js: -------------------------------------------------------------------------------- 1 | import { routes } from "../demo/routes"; 2 | import matchRoute from "./match-route"; 3 | import {RouteDataContext} from './index' 4 | 5 | export async function renderApp(url) { 6 | const urlWithoutQuery = new URL(`https://example.com${url}`).pathname; 7 | const route = routes.find(x => matchRoute(x.path, urlWithoutQuery)) 8 | if (!route) { 9 | return { notFound: true } 10 | } 11 | const page = await route.page() 12 | const data = await page.loader() 13 | const component = page.default 14 | 15 | return () => { 16 | return 17 | } 18 | } 19 | 20 | export function App({ Component, data }) { 21 | return ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | 31 |
    32 | 33 |
    34 | 35 | 36 | 37 | ); 38 | } -------------------------------------------------------------------------------- /src/server/request.js: -------------------------------------------------------------------------------- 1 | export function createRequestHandler(){} -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/runtime@^7.7.6": 6 | version "7.17.2" 7 | resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" 8 | integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== 9 | dependencies: 10 | regenerator-runtime "^0.13.4" 11 | 12 | accepts@~1.3.8: 13 | version "1.3.8" 14 | resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" 15 | integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== 16 | dependencies: 17 | mime-types "~2.1.34" 18 | negotiator "0.6.3" 19 | 20 | array-flatten@1.1.1: 21 | version "1.1.1" 22 | resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 23 | integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= 24 | 25 | body-parser@1.19.2: 26 | version "1.19.2" 27 | resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" 28 | integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== 29 | dependencies: 30 | bytes "3.1.2" 31 | content-type "~1.0.4" 32 | debug "2.6.9" 33 | depd "~1.1.2" 34 | http-errors "1.8.1" 35 | iconv-lite "0.4.24" 36 | on-finished "~2.3.0" 37 | qs "6.9.7" 38 | raw-body "2.4.3" 39 | type-is "~1.6.18" 40 | 41 | bytes@3.1.2: 42 | version "3.1.2" 43 | resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 44 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 45 | 46 | content-disposition@0.5.4: 47 | version "0.5.4" 48 | resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" 49 | integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== 50 | dependencies: 51 | safe-buffer "5.2.1" 52 | 53 | content-type@~1.0.4: 54 | version "1.0.4" 55 | resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" 56 | integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== 57 | 58 | cookie-signature@1.0.6: 59 | version "1.0.6" 60 | resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 61 | integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= 62 | 63 | cookie@0.4.2: 64 | version "0.4.2" 65 | resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" 66 | integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== 67 | 68 | data-uri-to-buffer@^4.0.0: 69 | version "4.0.0" 70 | resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" 71 | integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== 72 | 73 | debug@2.6.9: 74 | version "2.6.9" 75 | resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 76 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 77 | dependencies: 78 | ms "2.0.0" 79 | 80 | depd@~1.1.2: 81 | version "1.1.2" 82 | resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" 83 | integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= 84 | 85 | destr@^1.1.0: 86 | version "1.1.0" 87 | resolved "https://registry.npmjs.org/destr/-/destr-1.1.0.tgz#2da6add6ba71e04fd0abfb1e642d4f6763235095" 88 | integrity sha512-Ev/sqS5AzzDwlpor/5wFCDu0dYMQu/0x2D6XfAsQ0E7uQmamIgYJ6Dppo2T2EOFVkeVYWjc+PCLKaqZZ57qmLg== 89 | 90 | destroy@~1.0.4: 91 | version "1.0.4" 92 | resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" 93 | integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= 94 | 95 | ee-first@1.1.1: 96 | version "1.1.1" 97 | resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 98 | integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= 99 | 100 | encodeurl@~1.0.2: 101 | version "1.0.2" 102 | resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 103 | integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= 104 | 105 | esbuild-android-64@0.14.25: 106 | version "0.14.25" 107 | resolved "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.25.tgz#d532d38cb5fe0ae45167ce35f4bbc784c636be40" 108 | integrity sha512-L5vCUk7TzFbBnoESNoXjU3x9+/+7TDIE/1mTfy/erAfvZAqC+S3sp/Qa9wkypFMcFvN9FzvESkTlpeQDolREtQ== 109 | 110 | esbuild-android-arm64@0.14.25: 111 | version "0.14.25" 112 | resolved "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.25.tgz#9c5bb3366aabfd14a1c726d36978b79441dfcb6e" 113 | integrity sha512-4jv5xPjM/qNm27T5j3ZEck0PvjgQtoMHnz4FzwF5zNP56PvY2CT0WStcAIl6jNlsuDdN63rk2HRBIsO6xFbcFw== 114 | 115 | esbuild-darwin-64@0.14.25: 116 | version "0.14.25" 117 | resolved "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.25.tgz#05dcdb6d884f427039ffee5e92ff97527e56c26d" 118 | integrity sha512-TGp8tuudIxOyWd1+8aYPxQmC1ZQyvij/AfNBa35RubixD0zJ1vkKHVAzo0Zao1zcG6pNqiSyzfPto8vmg0s7oA== 119 | 120 | esbuild-darwin-arm64@0.14.25: 121 | version "0.14.25" 122 | resolved "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.25.tgz#28e080da4ea0cfe9498071e7f8060498caee1a95" 123 | integrity sha512-oTcDgdm0MDVEmw2DWu8BV68pYuImpFgvWREPErBZmNA4MYKGuBRaCiJqq6jZmBR1x+3y1DWCjez+5uLtuAm6mw== 124 | 125 | esbuild-freebsd-64@0.14.25: 126 | version "0.14.25" 127 | resolved "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.25.tgz#200d3664a3b945bc9fdcba73614b49a11ebd1cfa" 128 | integrity sha512-ueAqbnMZ8arnuLH8tHwTCQYeptnHOUV7vA6px6j4zjjQwDx7TdP7kACPf3TLZLdJQ3CAD1XCvQ2sPhX+8tacvQ== 129 | 130 | esbuild-freebsd-arm64@0.14.25: 131 | version "0.14.25" 132 | resolved "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.25.tgz#624b08c5da6013bdc312aaa23c4ff409580f5c3c" 133 | integrity sha512-+ZVWud2HKh+Ob6k/qiJWjBtUg4KmJGGmbvEXXW1SNKS7hW7HU+Zq2ZCcE1akFxOPkVB+EhOty/sSek30tkCYug== 134 | 135 | esbuild-linux-32@0.14.25: 136 | version "0.14.25" 137 | resolved "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.25.tgz#0238e597eb0b60aa06c7e98fccbbfd6bb9a0d6c5" 138 | integrity sha512-3OP/lwV3kCzEz45tobH9nj+uE4ubhGsfx+tn0L26WAGtUbmmcRpqy7XRG/qK7h1mClZ+eguIANcQntYMdYklfw== 139 | 140 | esbuild-linux-64@0.14.25: 141 | version "0.14.25" 142 | resolved "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.25.tgz#8a8b8cf47dfce127c858e71229d9a385a82c62e8" 143 | integrity sha512-+aKHdHZmX9qwVlQmu5xYXh7GsBFf4TWrePgeJTalhXHOG7NNuUwoHmketGiZEoNsWyyqwH9rE5BC+iwcLY30Ug== 144 | 145 | esbuild-linux-arm64@0.14.25: 146 | version "0.14.25" 147 | resolved "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.25.tgz#7ac94371418a2640ba413bc1700aaedeb2794e52" 148 | integrity sha512-UxfenPx/wSZx55gScCImPtXekvZQLI2GW3qe5dtlmU7luiqhp5GWPzGeQEbD3yN3xg/pHc671m5bma5Ns7lBHw== 149 | 150 | esbuild-linux-arm@0.14.25: 151 | version "0.14.25" 152 | resolved "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.25.tgz#034bd18e9310b9f010c89f90ef7f05706689600b" 153 | integrity sha512-aTLcE2VBoLydL943REcAcgnDi3bHtmULSXWLbjtBdtykRatJVSxKMjK9YlBXUZC4/YcNQfH7AxwVeQr9fNxPhw== 154 | 155 | esbuild-linux-mips64le@0.14.25: 156 | version "0.14.25" 157 | resolved "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.25.tgz#05f98a8cf6b578eab6b4e6b0ab094f37530934f4" 158 | integrity sha512-wLWYyqVfYx9Ur6eU5RT92yJVsaBGi5RdkoWqRHOqcJ38Kn60QMlcghsKeWfe9jcYut8LangYZ98xO1LxIoSXrQ== 159 | 160 | esbuild-linux-ppc64le@0.14.25: 161 | version "0.14.25" 162 | resolved "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.25.tgz#46fd0add8d8535678439d7a9c2876ad20042d952" 163 | integrity sha512-0dR6Csl6Zas3g4p9ULckEl8Mo8IInJh33VCJ3eaV1hj9+MHGdmDOakYMN8MZP9/5nl+NU/0ygpd14cWgy8uqRw== 164 | 165 | esbuild-linux-riscv64@0.14.25: 166 | version "0.14.25" 167 | resolved "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.25.tgz#ea2e986f0f3e5df73c635135dd778051734fc605" 168 | integrity sha512-J4d20HDmTrgvhR0bdkDhvvJGaikH3LzXQnNaseo8rcw9Yqby9A90gKUmWpfwqLVNRILvNnAmKLfBjCKU9ajg8w== 169 | 170 | esbuild-linux-s390x@0.14.25: 171 | version "0.14.25" 172 | resolved "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.25.tgz#efe89486e9a1b1508925048076e3f3a6698aa6a3" 173 | integrity sha512-YI2d5V6nTE73ZnhEKQD7MtsPs1EtUZJ3obS21oxQxGbbRw1G+PtJKjNyur+3t6nzHP9oTg6GHQ3S3hOLLmbDIQ== 174 | 175 | esbuild-netbsd-64@0.14.25: 176 | version "0.14.25" 177 | resolved "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.25.tgz#439fe27d8ee3b5887501ee63988e85f920107db6" 178 | integrity sha512-TKIVgNWLUOkr+Exrye70XTEE1lJjdQXdM4tAXRzfHE9iBA7LXWcNtVIuSnphTqpanPzTDFarF0yqq4kpbC6miA== 179 | 180 | esbuild-openbsd-64@0.14.25: 181 | version "0.14.25" 182 | resolved "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.25.tgz#31ebf616aadf6e60674469f2b92cec92280d9930" 183 | integrity sha512-QgFJ37A15D7NIXBTYEqz29+uw3nNBOIyog+3kFidANn6kjw0GHZ0lEYQn+cwjyzu94WobR+fes7cTl/ZYlHb1A== 184 | 185 | esbuild-sunos-64@0.14.25: 186 | version "0.14.25" 187 | resolved "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.25.tgz#815e4f936d74970292a63ccfd5791fe5e3569f5f" 188 | integrity sha512-rmWfjUItYIVlqr5EnTH1+GCxXiBOC42WBZ3w++qh7n2cS9Xo0lO5pGSG2N+huOU2fX5L+6YUuJ78/vOYvefeFw== 189 | 190 | esbuild-windows-32@0.14.25: 191 | version "0.14.25" 192 | resolved "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.25.tgz#189e14df2478f2c193c86968ab1fb54e1ceaafd2" 193 | integrity sha512-HGAxVUofl3iUIz9W10Y9XKtD0bNsK9fBXv1D55N/ljNvkrAYcGB8YCm0v7DjlwtyS6ws3dkdQyXadbxkbzaKOA== 194 | 195 | esbuild-windows-64@0.14.25: 196 | version "0.14.25" 197 | resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.25.tgz#3d5fbfdc3856850bb47439299e3b60dd18be111f" 198 | integrity sha512-TirEohRkfWU9hXLgoDxzhMQD1g8I2mOqvdQF2RS9E/wbkORTAqJHyh7wqGRCQAwNzdNXdg3JAyhQ9/177AadWA== 199 | 200 | esbuild-windows-arm64@0.14.25: 201 | version "0.14.25" 202 | resolved "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.25.tgz#8b243cbbad8a86cf98697da9ccb88c05df2ef458" 203 | integrity sha512-4ype9ERiI45rSh+R8qUoBtaj6kJvUOI7oVLhKqPEpcF4Pa5PpT3hm/mXAyotJHREkHpM87PAJcA442mLnbtlNA== 204 | 205 | esbuild@^0.14.25: 206 | version "0.14.25" 207 | resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.25.tgz#ddb9d47b91ca76abb7d850ce3dfed0bc3dc88d16" 208 | integrity sha512-4JHEIOMNFvK09ziiL+iVmldIhLbn49V4NAVo888tcGFKedEZY/Y8YapfStJ6zSE23tzYPKxqKwQBnQoIO0BI/Q== 209 | optionalDependencies: 210 | esbuild-android-64 "0.14.25" 211 | esbuild-android-arm64 "0.14.25" 212 | esbuild-darwin-64 "0.14.25" 213 | esbuild-darwin-arm64 "0.14.25" 214 | esbuild-freebsd-64 "0.14.25" 215 | esbuild-freebsd-arm64 "0.14.25" 216 | esbuild-linux-32 "0.14.25" 217 | esbuild-linux-64 "0.14.25" 218 | esbuild-linux-arm "0.14.25" 219 | esbuild-linux-arm64 "0.14.25" 220 | esbuild-linux-mips64le "0.14.25" 221 | esbuild-linux-ppc64le "0.14.25" 222 | esbuild-linux-riscv64 "0.14.25" 223 | esbuild-linux-s390x "0.14.25" 224 | esbuild-netbsd-64 "0.14.25" 225 | esbuild-openbsd-64 "0.14.25" 226 | esbuild-sunos-64 "0.14.25" 227 | esbuild-windows-32 "0.14.25" 228 | esbuild-windows-64 "0.14.25" 229 | esbuild-windows-arm64 "0.14.25" 230 | 231 | escape-html@~1.0.3: 232 | version "1.0.3" 233 | resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 234 | integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= 235 | 236 | etag@~1.8.1: 237 | version "1.8.1" 238 | resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 239 | integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= 240 | 241 | express@^4.17.3: 242 | version "4.17.3" 243 | resolved "https://registry.npmjs.org/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" 244 | integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== 245 | dependencies: 246 | accepts "~1.3.8" 247 | array-flatten "1.1.1" 248 | body-parser "1.19.2" 249 | content-disposition "0.5.4" 250 | content-type "~1.0.4" 251 | cookie "0.4.2" 252 | cookie-signature "1.0.6" 253 | debug "2.6.9" 254 | depd "~1.1.2" 255 | encodeurl "~1.0.2" 256 | escape-html "~1.0.3" 257 | etag "~1.8.1" 258 | finalhandler "~1.1.2" 259 | fresh "0.5.2" 260 | merge-descriptors "1.0.1" 261 | methods "~1.1.2" 262 | on-finished "~2.3.0" 263 | parseurl "~1.3.3" 264 | path-to-regexp "0.1.7" 265 | proxy-addr "~2.0.7" 266 | qs "6.9.7" 267 | range-parser "~1.2.1" 268 | safe-buffer "5.2.1" 269 | send "0.17.2" 270 | serve-static "1.14.2" 271 | setprototypeof "1.2.0" 272 | statuses "~1.5.0" 273 | type-is "~1.6.18" 274 | utils-merge "1.0.1" 275 | vary "~1.1.2" 276 | 277 | fetch-blob@^3.1.2, fetch-blob@^3.1.4: 278 | version "3.1.4" 279 | resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz#e8c6567f80ad7fc22fd302e7dcb72bafde9c1717" 280 | integrity sha512-Eq5Xv5+VlSrYWEqKrusxY1C3Hm/hjeAsCGVG3ft7pZahlUAChpGZT/Ms1WmSLnEAisEXszjzu/s+ce6HZB2VHA== 281 | dependencies: 282 | node-domexception "^1.0.0" 283 | web-streams-polyfill "^3.0.3" 284 | 285 | finalhandler@~1.1.2: 286 | version "1.1.2" 287 | resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" 288 | integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== 289 | dependencies: 290 | debug "2.6.9" 291 | encodeurl "~1.0.2" 292 | escape-html "~1.0.3" 293 | on-finished "~2.3.0" 294 | parseurl "~1.3.3" 295 | statuses "~1.5.0" 296 | unpipe "~1.0.0" 297 | 298 | formdata-polyfill@^4.0.10: 299 | version "4.0.10" 300 | resolved "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" 301 | integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== 302 | dependencies: 303 | fetch-blob "^3.1.2" 304 | 305 | forwarded@0.2.0: 306 | version "0.2.0" 307 | resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" 308 | integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== 309 | 310 | fresh@0.5.2: 311 | version "0.5.2" 312 | resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 313 | integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= 314 | 315 | history@^5.2.0: 316 | version "5.3.0" 317 | resolved "https://registry.npmjs.org/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b" 318 | integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ== 319 | dependencies: 320 | "@babel/runtime" "^7.7.6" 321 | 322 | http-errors@1.8.1: 323 | version "1.8.1" 324 | resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" 325 | integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== 326 | dependencies: 327 | depd "~1.1.2" 328 | inherits "2.0.4" 329 | setprototypeof "1.2.0" 330 | statuses ">= 1.5.0 < 2" 331 | toidentifier "1.0.1" 332 | 333 | iconv-lite@0.4.24: 334 | version "0.4.24" 335 | resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 336 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 337 | dependencies: 338 | safer-buffer ">= 2.1.2 < 3" 339 | 340 | inherits@2.0.4: 341 | version "2.0.4" 342 | resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 343 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 344 | 345 | ipaddr.js@1.9.1: 346 | version "1.9.1" 347 | resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" 348 | integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== 349 | 350 | "js-tokens@^3.0.0 || ^4.0.0": 351 | version "4.0.0" 352 | resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 353 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 354 | 355 | loose-envify@^1.1.0: 356 | version "1.4.0" 357 | resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" 358 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== 359 | dependencies: 360 | js-tokens "^3.0.0 || ^4.0.0" 361 | 362 | media-typer@0.3.0: 363 | version "0.3.0" 364 | resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 365 | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= 366 | 367 | merge-descriptors@1.0.1: 368 | version "1.0.1" 369 | resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 370 | integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= 371 | 372 | methods@~1.1.2: 373 | version "1.1.2" 374 | resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 375 | integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= 376 | 377 | mime-db@1.52.0: 378 | version "1.52.0" 379 | resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" 380 | integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== 381 | 382 | mime-types@~2.1.24, mime-types@~2.1.34: 383 | version "2.1.35" 384 | resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" 385 | integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== 386 | dependencies: 387 | mime-db "1.52.0" 388 | 389 | mime@1.6.0: 390 | version "1.6.0" 391 | resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" 392 | integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== 393 | 394 | ms@2.0.0: 395 | version "2.0.0" 396 | resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 397 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 398 | 399 | ms@2.1.3: 400 | version "2.1.3" 401 | resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 402 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 403 | 404 | negotiator@0.6.3: 405 | version "0.6.3" 406 | resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" 407 | integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== 408 | 409 | node-domexception@^1.0.0: 410 | version "1.0.0" 411 | resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" 412 | integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== 413 | 414 | node-fetch@^3.0.0: 415 | version "3.2.3" 416 | resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.3.tgz#a03c9cc2044d21d1a021566bd52f080f333719a6" 417 | integrity sha512-AXP18u4pidSZ1xYXRDPY/8jdv3RAozIt/WLNR/MBGZAz+xjtlr90RvCnsvHQRiXyWliZF/CpytExp32UU67/SA== 418 | dependencies: 419 | data-uri-to-buffer "^4.0.0" 420 | fetch-blob "^3.1.4" 421 | formdata-polyfill "^4.0.10" 422 | 423 | object-assign@^4.1.1: 424 | version "4.1.1" 425 | resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 426 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 427 | 428 | ohmyfetch@^0.4.15: 429 | version "0.4.15" 430 | resolved "https://registry.npmjs.org/ohmyfetch/-/ohmyfetch-0.4.15.tgz#c7059d2952abacfaaaebd82efab754aca53a5c04" 431 | integrity sha512-AJKiMh4s+VYLLiAQi3tZn4Zh/xYr94nOX9FLGVVdbXo7QWrrKIfGweACIKaB06PjQdZtkICzcmNN+CQSR+9vQQ== 432 | dependencies: 433 | destr "^1.1.0" 434 | node-fetch "^3.0.0" 435 | ufo "^0.7.9" 436 | undici "^4.9.5" 437 | 438 | on-finished@~2.3.0: 439 | version "2.3.0" 440 | resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 441 | integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= 442 | dependencies: 443 | ee-first "1.1.1" 444 | 445 | parseurl@~1.3.3: 446 | version "1.3.3" 447 | resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" 448 | integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== 449 | 450 | path-to-regexp@0.1.7: 451 | version "0.1.7" 452 | resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 453 | integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= 454 | 455 | proxy-addr@~2.0.7: 456 | version "2.0.7" 457 | resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" 458 | integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== 459 | dependencies: 460 | forwarded "0.2.0" 461 | ipaddr.js "1.9.1" 462 | 463 | qs@6.9.7: 464 | version "6.9.7" 465 | resolved "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" 466 | integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw== 467 | 468 | range-parser@~1.2.1: 469 | version "1.2.1" 470 | resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" 471 | integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== 472 | 473 | raw-body@2.4.3: 474 | version "2.4.3" 475 | resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" 476 | integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g== 477 | dependencies: 478 | bytes "3.1.2" 479 | http-errors "1.8.1" 480 | iconv-lite "0.4.24" 481 | unpipe "1.0.0" 482 | 483 | react-dom@^17.0.2: 484 | version "17.0.2" 485 | resolved "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" 486 | integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== 487 | dependencies: 488 | loose-envify "^1.1.0" 489 | object-assign "^4.1.1" 490 | scheduler "^0.20.2" 491 | 492 | react-router-dom@^6.2.2: 493 | version "6.2.2" 494 | resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.2.tgz#f1a2c88365593c76b9612ae80154a13fcb72e442" 495 | integrity sha512-AtYEsAST7bDD4dLSQHDnk/qxWLJdad5t1HFa1qJyUrCeGgEuCSw0VB/27ARbF9Fi/W5598ujvJOm3ujUCVzuYQ== 496 | dependencies: 497 | history "^5.2.0" 498 | react-router "6.2.2" 499 | 500 | react-router@6.2.2: 501 | version "6.2.2" 502 | resolved "https://registry.npmjs.org/react-router/-/react-router-6.2.2.tgz#495e683a0c04461eeb3d705fe445d6cf42f0c249" 503 | integrity sha512-/MbxyLzd7Q7amp4gDOGaYvXwhEojkJD5BtExkuKmj39VEE0m3l/zipf6h2WIB2jyAO0lI6NGETh4RDcktRm4AQ== 504 | dependencies: 505 | history "^5.2.0" 506 | 507 | react@^17.0.2: 508 | version "17.0.2" 509 | resolved "https://registry.npmjs.org/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" 510 | integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== 511 | dependencies: 512 | loose-envify "^1.1.0" 513 | object-assign "^4.1.1" 514 | 515 | regenerator-runtime@^0.13.4: 516 | version "0.13.9" 517 | resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" 518 | integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== 519 | 520 | regexparam@1.3.0: 521 | version "1.3.0" 522 | resolved "https://registry.npmjs.org/regexparam/-/regexparam-1.3.0.tgz#2fe42c93e32a40eff6235d635e0ffa344b92965f" 523 | integrity sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g== 524 | 525 | safe-buffer@5.2.1: 526 | version "5.2.1" 527 | resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 528 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 529 | 530 | "safer-buffer@>= 2.1.2 < 3": 531 | version "2.1.2" 532 | resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 533 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 534 | 535 | scheduler@^0.20.2: 536 | version "0.20.2" 537 | resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" 538 | integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== 539 | dependencies: 540 | loose-envify "^1.1.0" 541 | object-assign "^4.1.1" 542 | 543 | send@0.17.2: 544 | version "0.17.2" 545 | resolved "https://registry.npmjs.org/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" 546 | integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== 547 | dependencies: 548 | debug "2.6.9" 549 | depd "~1.1.2" 550 | destroy "~1.0.4" 551 | encodeurl "~1.0.2" 552 | escape-html "~1.0.3" 553 | etag "~1.8.1" 554 | fresh "0.5.2" 555 | http-errors "1.8.1" 556 | mime "1.6.0" 557 | ms "2.1.3" 558 | on-finished "~2.3.0" 559 | range-parser "~1.2.1" 560 | statuses "~1.5.0" 561 | 562 | serve-static@1.14.2: 563 | version "1.14.2" 564 | resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" 565 | integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== 566 | dependencies: 567 | encodeurl "~1.0.2" 568 | escape-html "~1.0.3" 569 | parseurl "~1.3.3" 570 | send "0.17.2" 571 | 572 | setprototypeof@1.2.0: 573 | version "1.2.0" 574 | resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 575 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 576 | 577 | "statuses@>= 1.5.0 < 2", statuses@~1.5.0: 578 | version "1.5.0" 579 | resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" 580 | integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= 581 | 582 | toidentifier@1.0.1: 583 | version "1.0.1" 584 | resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 585 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 586 | 587 | type-is@~1.6.18: 588 | version "1.6.18" 589 | resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" 590 | integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== 591 | dependencies: 592 | media-typer "0.3.0" 593 | mime-types "~2.1.24" 594 | 595 | ufo@^0.7.9: 596 | version "0.7.11" 597 | resolved "https://registry.npmjs.org/ufo/-/ufo-0.7.11.tgz#17defad497981290383c5d26357773431fdbadcb" 598 | integrity sha512-IT3q0lPvtkqQ8toHQN/BkOi4VIqoqheqM1FnkNWT9y0G8B3xJhwnoKBu5OHx8zHDOvveQzfKuFowJ0VSARiIDg== 599 | 600 | undici@^4.9.5: 601 | version "4.15.1" 602 | resolved "https://registry.npmjs.org/undici/-/undici-4.15.1.tgz#c2c0e75f232178f0e6781f6b46c81ccc15065f6e" 603 | integrity sha512-h8LJybhMKD09IyQZoQadNtIR/GmugVhTOVREunJrpV6RStriKBFdSVoFzEzTihwXi/27DIBO+Z0OGF+Mzfi0lA== 604 | 605 | unpipe@1.0.0, unpipe@~1.0.0: 606 | version "1.0.0" 607 | resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 608 | integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= 609 | 610 | utils-merge@1.0.1: 611 | version "1.0.1" 612 | resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 613 | integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= 614 | 615 | vary@~1.1.2: 616 | version "1.1.2" 617 | resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 618 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= 619 | 620 | web-streams-polyfill@^3.0.3: 621 | version "3.2.0" 622 | resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" 623 | integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA== 624 | 625 | wouter@^2.8.0-alpha.2: 626 | version "2.8.0-alpha.2" 627 | resolved "https://registry.npmjs.org/wouter/-/wouter-2.8.0-alpha.2.tgz#d57dfbd23b964b8bd848f2ed3eb2b38cf3c00e00" 628 | integrity sha512-aPsL5m5rW9RiceClOmGj6t5gn9Ut2TJVr98UDi1u9MIRNYiYVflg6vFIjdDYJ4IAyH0JdnkSgGwfo0LQS3k2zg== 629 | --------------------------------------------------------------------------------