From 6b4d1e992944703bcac68cb4b47d211f5ca49bc1 Mon Sep 17 00:00:00 2001 From: TonyStark106 Date: Tue, 26 Nov 2024 12:32:22 +0800 Subject: [PATCH 1/2] feat: add support for React Router --- package-lock.json | 61 ++++++++++++++++-- package.json | 17 +++++ src/react-router/dev.ts | 32 ++++++++++ src/react-router/handlers/cloudflare-pages.ts | 36 +++++++++++ .../handlers/cloudflare-workers.ts | 29 +++++++++ src/react-router/handlers/node/index.ts | 37 +++++++++++ src/react-router/handlers/node/middleware.ts | 24 +++++++ src/react-router/handlers/node/remix.ts | 13 ++++ src/react-router/middleware.ts | 24 +++++++ src/react-router/remix.ts | 43 +++++++++++++ src/react-router/vite-plugin.ts | 62 +++++++++++++++++++ tsup.config.ts | 9 +++ 12 files changed, 381 insertions(+), 6 deletions(-) create mode 100644 src/react-router/dev.ts create mode 100644 src/react-router/handlers/cloudflare-pages.ts create mode 100644 src/react-router/handlers/cloudflare-workers.ts create mode 100644 src/react-router/handlers/node/index.ts create mode 100644 src/react-router/handlers/node/middleware.ts create mode 100644 src/react-router/handlers/node/remix.ts create mode 100644 src/react-router/middleware.ts create mode 100644 src/react-router/remix.ts create mode 100644 src/react-router/vite-plugin.ts diff --git a/package-lock.json b/package-lock.json index 38081f8..b864f4b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ ], "dependencies": { "@hono/vite-dev-server": "^0.17.0", + "react-router": "^7.0.1", "remix-hono": "^0.0.16" }, "devDependencies": { @@ -3336,6 +3337,21 @@ } } }, + "node_modules/@remix-run/react/node_modules/react-router": { + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz", + "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.21.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, "node_modules/@remix-run/router": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz", @@ -13908,18 +13924,27 @@ } }, "node_modules/react-router": { - "version": "6.28.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz", - "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.0.1.tgz", + "integrity": "sha512-WVAhv9oWCNsja5AkK6KLpXJDSJCQizOIyOd4vvB/+eHGbYx5vkhcmcmwWjQ9yqkRClogi+xjEg9fNEOd5EX/tw==", "license": "MIT", "dependencies": { - "@remix-run/router": "1.21.0" + "@types/cookie": "^0.6.0", + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0", + "turbo-stream": "2.4.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" }, "peerDependencies": { - "react": ">=16.8" + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } } }, "node_modules/react-router-dom": { @@ -13939,6 +13964,30 @@ "react-dom": ">=16.8" } }, + "node_modules/react-router-dom/node_modules/react-router": { + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz", + "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.21.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/read-package-up": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", diff --git a/package.json b/package.json index 37b61a5..e9f4087 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,22 @@ "./node": { "types": "./dist/handlers/node/index.d.ts", "import": "./dist/handlers/node/index.js" + }, + "./vite@react-router": { + "types": "./dist/react-router/vite-plugin.d.ts", + "import": "./dist/react-router/vite-plugin.js" + }, + "./cloudflare-pages@react-router": { + "types": "./dist/react-router/handlers/cloudflare-pages.d.ts", + "import": "./dist/react-router/handlers/cloudflare-pages.js" + }, + "./cloudflare-workers@react-router": { + "types": "./dist/react-router/handlers/cloudflare-workers.d.ts", + "import": "./dist/react-router/handlers/cloudflare-workers.js" + }, + "./node@react-router": { + "types": "./dist/react-router/handlers/node/index.d.ts", + "import": "./dist/react-router/handlers/node/index.js" } }, "author": "Yusuke Wada (https://github.com/yusukebe)", @@ -73,6 +89,7 @@ }, "dependencies": { "@hono/vite-dev-server": "^0.17.0", + "react-router": "^7.0.1", "remix-hono": "^0.0.16" }, "peerDependencies": { diff --git a/src/react-router/dev.ts b/src/react-router/dev.ts new file mode 100644 index 0000000..c4afece --- /dev/null +++ b/src/react-router/dev.ts @@ -0,0 +1,32 @@ +import { Hono } from 'hono' +import type { GetLoadContext } from './remix' +import { createGetLoadContextArgs, defaultGetLoadContext } from './remix' + +type Options = { + getLoadContext: GetLoadContext +} + +export const handle = (userApp?: Hono, options?: Options) => { + const app = new Hono() + + if (userApp) { + app.route('/', userApp) + } + + app.all('*', async (c) => { + // @ts-expect-error it's not typed + const build = await import('virtual:react-router/server-build') + const { createRequestHandler } = await import('react-router') + const handler = createRequestHandler(build, 'development') + + const getLoadContext = options?.getLoadContext ?? defaultGetLoadContext + const args = createGetLoadContextArgs(c) + + const remixContext = getLoadContext(args) + return handler(c.req.raw, remixContext instanceof Promise ? await remixContext : remixContext) + }) + + return app +} + +export default handle diff --git a/src/react-router/handlers/cloudflare-pages.ts b/src/react-router/handlers/cloudflare-pages.ts new file mode 100644 index 0000000..c36d5fd --- /dev/null +++ b/src/react-router/handlers/cloudflare-pages.ts @@ -0,0 +1,36 @@ +import { Hono } from 'hono' +import { handle } from 'hono/cloudflare-pages' +import { staticAssets } from 'remix-hono/cloudflare' +import { remix } from '../middleware' +import { defaultGetLoadContext } from '../remix' +import type { GetLoadContext } from '../remix' + +type Options = { + getLoadContext: GetLoadContext +} + +// Relaxing the type definitions +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const handler = (serverBuild: any, userApp?: Hono, options?: Options) => { + const app = new Hono() + + if (userApp) { + app.route('/', userApp) + } + + app.use( + async (c, next) => { + return staticAssets()(c, next) + }, + async (c, next) => { + return remix({ + build: serverBuild, + mode: 'production', + getLoadContext: options?.getLoadContext ?? defaultGetLoadContext, + })(c, next) + } + ) + return handle(app) +} + +export default handler diff --git a/src/react-router/handlers/cloudflare-workers.ts b/src/react-router/handlers/cloudflare-workers.ts new file mode 100644 index 0000000..acff9be --- /dev/null +++ b/src/react-router/handlers/cloudflare-workers.ts @@ -0,0 +1,29 @@ +import { Hono } from 'hono' +import { remix } from '../middleware' +import { defaultGetLoadContext } from '../remix' +import type { GetLoadContext } from '../remix' + +type Options = { + getLoadContext: GetLoadContext +} + +// Relaxing the type definitions +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const handler = (serverBuild: any, userApp?: Hono, options?: Options) => { + const app = new Hono() + + if (userApp) { + app.route('/', userApp) + } + + app.use(async (c, next) => { + return remix({ + build: serverBuild, + mode: 'production', + getLoadContext: options?.getLoadContext ?? defaultGetLoadContext, + })(c, next) + }) + return app +} + +export default handler diff --git a/src/react-router/handlers/node/index.ts b/src/react-router/handlers/node/index.ts new file mode 100644 index 0000000..0f1e84a --- /dev/null +++ b/src/react-router/handlers/node/index.ts @@ -0,0 +1,37 @@ +import { Hono } from 'hono' +import type { AppLoadContext } from 'react-router' +import { remix } from './middleware' +import type { GetLoadContext } from './remix' + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const defaultGetLoadContext = ({ context }: any): AppLoadContext => { + return { + ...context, + } +} + +type Options = { + getLoadContext: GetLoadContext +} + +// Relaxing the type definitions +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const handler = (serverBuild: any, userApp?: Hono, options?: Options) => { + const app = new Hono() + + if (userApp) { + app.route('/', userApp) + } + + app.use(async (c, next) => { + return remix({ + build: serverBuild, + mode: 'production', + getLoadContext: options?.getLoadContext ?? defaultGetLoadContext, + })(c, next) + }) + + return app +} + +export default handler diff --git a/src/react-router/handlers/node/middleware.ts b/src/react-router/handlers/node/middleware.ts new file mode 100644 index 0000000..4062ef5 --- /dev/null +++ b/src/react-router/handlers/node/middleware.ts @@ -0,0 +1,24 @@ +import { createMiddleware } from 'hono/factory' +import { createRequestHandler } from 'react-router' +import type { ServerBuild } from 'react-router' +import { createGetLoadContextArgs } from './remix' +import type { GetLoadContext } from './remix' + +interface RemixMiddlewareOptions { + build: ServerBuild + mode?: 'development' | 'production' + getLoadContext: GetLoadContext +} + +export const remix = ({ mode, build, getLoadContext }: RemixMiddlewareOptions) => { + return createMiddleware(async (c) => { + const requestHandler = createRequestHandler(build, mode) + const args = createGetLoadContextArgs(c) + + const loadContext = getLoadContext(args) + return await requestHandler( + c.req.raw, + loadContext instanceof Promise ? await loadContext : loadContext + ) + }) +} diff --git a/src/react-router/handlers/node/remix.ts b/src/react-router/handlers/node/remix.ts new file mode 100644 index 0000000..d626247 --- /dev/null +++ b/src/react-router/handlers/node/remix.ts @@ -0,0 +1,13 @@ +import type { Context } from 'hono' +import type { AppLoadContext } from 'react-router' + +export type GetLoadContext = (args: { + request: Request +}) => AppLoadContext | Promise + +export const createGetLoadContextArgs = (c: Context) => { + return { + context: {}, + request: c.req.raw, + } +} diff --git a/src/react-router/middleware.ts b/src/react-router/middleware.ts new file mode 100644 index 0000000..ab370c6 --- /dev/null +++ b/src/react-router/middleware.ts @@ -0,0 +1,24 @@ +import { createMiddleware } from 'hono/factory' +import type { ServerBuild } from 'react-router' +import { createRequestHandler } from 'react-router' +import { createGetLoadContextArgs } from './remix' +import type { GetLoadContext } from './remix' + +interface RemixMiddlewareOptions { + build: ServerBuild + mode?: 'development' | 'production' + getLoadContext: GetLoadContext +} + +export const remix = ({ mode, build, getLoadContext }: RemixMiddlewareOptions) => { + return createMiddleware(async (c) => { + const requestHandler = createRequestHandler(build, mode) + const args = createGetLoadContextArgs(c) + + const loadContext = getLoadContext(args) + return await requestHandler( + c.req.raw, + loadContext instanceof Promise ? await loadContext : loadContext + ) + }) +} diff --git a/src/react-router/remix.ts b/src/react-router/remix.ts new file mode 100644 index 0000000..cb7280c --- /dev/null +++ b/src/react-router/remix.ts @@ -0,0 +1,43 @@ +import type { Context } from 'hono' +import type { AppLoadContext } from 'react-router' + +type GetLoadContextArgs = { + request: Request + context: { + // Relaxing the type definition + // eslint-disable-next-line @typescript-eslint/no-explicit-any + cloudflare: any + hono: { + context: Context + } + } +} + +export type GetLoadContext = (args: GetLoadContextArgs) => AppLoadContext | Promise + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const defaultGetLoadContext = ({ context }: any): AppLoadContext => { + return { + ...context, + } +} + +export const createGetLoadContextArgs = (c: Context): GetLoadContextArgs => { + return { + context: { + cloudflare: { + env: c.env, + cf: c.req.raw.cf, + ctx: { + ...c.executionCtx, + }, + // @ts-expect-error globalThis.caches is not typed + caches: globalThis.caches ? caches : undefined, + }, + hono: { + context: c, + }, + }, + request: c.req.raw, + } +} diff --git a/src/react-router/vite-plugin.ts b/src/react-router/vite-plugin.ts new file mode 100644 index 0000000..0baddec --- /dev/null +++ b/src/react-router/vite-plugin.ts @@ -0,0 +1,62 @@ +import devServer, { defaultOptions } from '@hono/vite-dev-server' +import type { Hono } from 'hono' +import type { Plugin } from 'vite' +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import type { GetLoadContext } from './remix' + +interface Adapter { + env?: Record | Promise> + onServerClose?: () => Promise + executionContext?: { + waitUntil(promise: Promise): void + passThroughOnException(): void + } +} + +interface Options { + entry: string + adapter?: () => Adapter | Promise + getLoadContext?: GetLoadContext + exclude?: (string | RegExp)[] +} + +export default (options: Options): Plugin => { + return devServer({ + adapter: options?.adapter, + entry: options.entry, + exclude: options?.exclude ?? [...defaultOptions.exclude, '/assets/**', '/app/**'], + injectClientScript: false, + loadModule: async (server, entry) => { + const appModule = await server.ssrLoadModule(entry) + const app = appModule['default'] as Hono + + if (!app) { + throw new Error(`Failed to find the module from ${entry}`) + } + + const __filename = fileURLToPath(import.meta.url) + const __dirname = path.dirname(__filename) + const dir = __dirname + + const tsPath = path.resolve(dir, 'dev.ts') + const jsPath = path.resolve(dir, 'dev.js') + + let devPath + + if (fs.existsSync(tsPath)) { + devPath = tsPath + } else if (fs.existsSync(jsPath)) { + devPath = jsPath + } else { + throw new Error('Neither dev.ts nor dev.js found') + } + + const devModule = await server.ssrLoadModule(devPath) + return devModule['default'](app, { + getLoadContext: options.getLoadContext, + }) + }, + }) +} diff --git a/tsup.config.ts b/tsup.config.ts index 681bb10..2c9687e 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -8,6 +8,12 @@ export default defineConfig({ 'src/handlers/cloudflare-workers.ts', 'src/handlers/node/index.ts', 'src/remix.ts', + 'src/react-router/vite-plugin.ts', + 'src/react-router/dev.ts', + 'src/react-router/handlers/cloudflare-pages.ts', + 'src/react-router/handlers/cloudflare-workers.ts', + 'src/react-router/handlers/node/index.ts', + 'src/react-router/remix.ts', ], external: [ '../server', @@ -16,6 +22,9 @@ export default defineConfig({ '@remix-run/cloudflare', 'vite', '@remix-run/node', + 'react-router', + '@react-router/cloudflare', + 'virtual:react-router/server-build' ], format: 'esm', splitting: false, From 184855cd722957f98410e5cf14280a4a6099c3a9 Mon Sep 17 00:00:00 2001 From: TonyStark106 Date: Tue, 26 Nov 2024 21:36:55 +0800 Subject: [PATCH 2/2] chore: add examples for React Router --- .gitignore | 3 +- .../react-router/cloudflare-pages/.gitignore | 10 + .../cloudflare-pages/app/entry.client.tsx | 18 + .../cloudflare-pages/app/entry.server.tsx | 44 + .../cloudflare-pages/app/root.tsx | 20 + .../cloudflare-pages/app/routes.ts | 7 + .../cloudflare-pages/app/routes/_index.tsx | 26 + .../react-router/cloudflare-pages/e2e.test.ts | 30 + .../cloudflare-pages/functions/[[path]].ts | 7 + .../cloudflare-pages/load-context.ts | 40 + .../cloudflare-pages/package.json | 40 + .../playwright-pages.config.ts | 26 + .../playwright-vite.config.ts | 26 + .../cloudflare-pages/server/index.ts | 26 + .../cloudflare-pages/tsconfig.json | 45 + .../cloudflare-pages/vite.config.ts | 21 + .../cloudflare-pages/wrangler.toml | 86 + .../cloudflare-workers/.gitignore | 10 + .../cloudflare-workers/app/entry.client.tsx | 18 + .../cloudflare-workers/app/entry.server.tsx | 58 + .../cloudflare-workers/app/root.tsx | 20 + .../cloudflare-workers/app/routes.ts | 7 + .../cloudflare-workers/app/routes/_index.tsx | 26 + .../cloudflare-workers/e2e.test.ts | 30 + .../cloudflare-workers/load-context.ts | 42 + .../cloudflare-workers/package.json | 39 + .../playwright-vite.config.ts | 26 + .../playwright-workers.config.ts | 26 + .../cloudflare-workers/public/.assetsignore | 0 .../cloudflare-workers/public/favicon.ico | Bin 0 -> 16958 bytes .../cloudflare-workers/server/index.ts | 26 + .../cloudflare-workers/tsconfig.json | 46 + .../cloudflare-workers/vite.config.ts | 21 + .../react-router/cloudflare-workers/worker.ts | 6 + .../cloudflare-workers/wrangler.toml | 8 + examples/react-router/node/.gitignore | 10 + .../react-router/node/app/entry.client.tsx | 18 + .../react-router/node/app/entry.server.tsx | 122 ++ examples/react-router/node/app/root.tsx | 20 + examples/react-router/node/app/routes.ts | 7 + .../react-router/node/app/routes/_index.tsx | 19 + examples/react-router/node/e2e.test.ts | 24 + examples/react-router/node/load-context.ts | 17 + examples/react-router/node/main.ts | 17 + examples/react-router/node/package.json | 40 + .../node/playwright-node.config.ts | 26 + .../node/playwright-vite.config.ts | 26 + examples/react-router/node/public/favicon.ico | Bin 0 -> 16958 bytes examples/react-router/node/server/index.ts | 17 + examples/react-router/node/tsconfig.json | 44 + examples/react-router/node/vite.config.ts | 16 + package-lock.json | 1424 +++++++++++------ package.json | 8 +- 53 files changed, 2236 insertions(+), 503 deletions(-) create mode 100644 examples/react-router/cloudflare-pages/.gitignore create mode 100644 examples/react-router/cloudflare-pages/app/entry.client.tsx create mode 100644 examples/react-router/cloudflare-pages/app/entry.server.tsx create mode 100644 examples/react-router/cloudflare-pages/app/root.tsx create mode 100644 examples/react-router/cloudflare-pages/app/routes.ts create mode 100644 examples/react-router/cloudflare-pages/app/routes/_index.tsx create mode 100644 examples/react-router/cloudflare-pages/e2e.test.ts create mode 100644 examples/react-router/cloudflare-pages/functions/[[path]].ts create mode 100644 examples/react-router/cloudflare-pages/load-context.ts create mode 100644 examples/react-router/cloudflare-pages/package.json create mode 100644 examples/react-router/cloudflare-pages/playwright-pages.config.ts create mode 100644 examples/react-router/cloudflare-pages/playwright-vite.config.ts create mode 100644 examples/react-router/cloudflare-pages/server/index.ts create mode 100644 examples/react-router/cloudflare-pages/tsconfig.json create mode 100644 examples/react-router/cloudflare-pages/vite.config.ts create mode 100644 examples/react-router/cloudflare-pages/wrangler.toml create mode 100644 examples/react-router/cloudflare-workers/.gitignore create mode 100644 examples/react-router/cloudflare-workers/app/entry.client.tsx create mode 100644 examples/react-router/cloudflare-workers/app/entry.server.tsx create mode 100644 examples/react-router/cloudflare-workers/app/root.tsx create mode 100644 examples/react-router/cloudflare-workers/app/routes.ts create mode 100644 examples/react-router/cloudflare-workers/app/routes/_index.tsx create mode 100644 examples/react-router/cloudflare-workers/e2e.test.ts create mode 100644 examples/react-router/cloudflare-workers/load-context.ts create mode 100644 examples/react-router/cloudflare-workers/package.json create mode 100644 examples/react-router/cloudflare-workers/playwright-vite.config.ts create mode 100644 examples/react-router/cloudflare-workers/playwright-workers.config.ts create mode 100644 examples/react-router/cloudflare-workers/public/.assetsignore create mode 100644 examples/react-router/cloudflare-workers/public/favicon.ico create mode 100644 examples/react-router/cloudflare-workers/server/index.ts create mode 100644 examples/react-router/cloudflare-workers/tsconfig.json create mode 100644 examples/react-router/cloudflare-workers/vite.config.ts create mode 100644 examples/react-router/cloudflare-workers/worker.ts create mode 100644 examples/react-router/cloudflare-workers/wrangler.toml create mode 100644 examples/react-router/node/.gitignore create mode 100644 examples/react-router/node/app/entry.client.tsx create mode 100644 examples/react-router/node/app/entry.server.tsx create mode 100644 examples/react-router/node/app/root.tsx create mode 100644 examples/react-router/node/app/routes.ts create mode 100644 examples/react-router/node/app/routes/_index.tsx create mode 100644 examples/react-router/node/e2e.test.ts create mode 100644 examples/react-router/node/load-context.ts create mode 100644 examples/react-router/node/main.ts create mode 100644 examples/react-router/node/package.json create mode 100644 examples/react-router/node/playwright-node.config.ts create mode 100644 examples/react-router/node/playwright-vite.config.ts create mode 100644 examples/react-router/node/public/favicon.ico create mode 100644 examples/react-router/node/server/index.ts create mode 100644 examples/react-router/node/tsconfig.json create mode 100644 examples/react-router/node/vite.config.ts diff --git a/.gitignore b/.gitignore index 9cc1e61..038825d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules .wrangler .mf *.tgz -dist \ No newline at end of file +dist +.react-router \ No newline at end of file diff --git a/examples/react-router/cloudflare-pages/.gitignore b/examples/react-router/cloudflare-pages/.gitignore new file mode 100644 index 0000000..2cef2d0 --- /dev/null +++ b/examples/react-router/cloudflare-pages/.gitignore @@ -0,0 +1,10 @@ +node_modules + +test-results + +/.cache +/build +.env +.dev.vars + +.wrangler diff --git a/examples/react-router/cloudflare-pages/app/entry.client.tsx b/examples/react-router/cloudflare-pages/app/entry.client.tsx new file mode 100644 index 0000000..38f2bbb --- /dev/null +++ b/examples/react-router/cloudflare-pages/app/entry.client.tsx @@ -0,0 +1,18 @@ +/** + * By default, Remix will handle hydrating your app on the client for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.client + */ + +import { startTransition, StrictMode } from 'react' +import { hydrateRoot } from 'react-dom/client' +import { HydratedRouter } from 'react-router/dom' + +startTransition(() => { + hydrateRoot( + document, + + + + ) +}) diff --git a/examples/react-router/cloudflare-pages/app/entry.server.tsx b/examples/react-router/cloudflare-pages/app/entry.server.tsx new file mode 100644 index 0000000..144d6cc --- /dev/null +++ b/examples/react-router/cloudflare-pages/app/entry.server.tsx @@ -0,0 +1,44 @@ +/** + * By default, Remix will handle generating the HTTP Response for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.server + */ + +import { isbot } from 'isbot' +// @ts-expect-error `react-dom/server.browser` is not typed +import { renderToReadableStream } from 'react-dom/server.browser' +import type { AppLoadContext, EntryContext } from 'react-router' +import { ServerRouter } from 'react-router' + +export default async function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars + loadContext: AppLoadContext +) { + const body = await renderToReadableStream( + , + { + signal: request.signal, + onError(error: unknown) { + // Log streaming rendering errors from inside the shell + console.error(error) + responseStatusCode = 500 + }, + } + ) + + if (isbot(request.headers.get('user-agent') || '')) { + await body.allReady + } + + responseHeaders.set('Content-Type', 'text/html') + return new Response(body, { + headers: responseHeaders, + status: responseStatusCode, + }) +} diff --git a/examples/react-router/cloudflare-pages/app/root.tsx b/examples/react-router/cloudflare-pages/app/root.tsx new file mode 100644 index 0000000..da639de --- /dev/null +++ b/examples/react-router/cloudflare-pages/app/root.tsx @@ -0,0 +1,20 @@ +import { Outlet, Scripts } from 'react-router' + +export function Layout({ children }: { children: React.ReactNode }) { + return ( + + + + + + + {children} + + + + ) +} + +export default function App() { + return +} diff --git a/examples/react-router/cloudflare-pages/app/routes.ts b/examples/react-router/cloudflare-pages/app/routes.ts new file mode 100644 index 0000000..d48c140 --- /dev/null +++ b/examples/react-router/cloudflare-pages/app/routes.ts @@ -0,0 +1,7 @@ +import { index } from '@react-router/dev/routes' +import type {RouteConfig} from '@react-router/dev/routes' + +export default [ + index('routes/_index.tsx'), + +] satisfies RouteConfig diff --git a/examples/react-router/cloudflare-pages/app/routes/_index.tsx b/examples/react-router/cloudflare-pages/app/routes/_index.tsx new file mode 100644 index 0000000..8ae82d7 --- /dev/null +++ b/examples/react-router/cloudflare-pages/app/routes/_index.tsx @@ -0,0 +1,26 @@ +import { useLoaderData } from 'react-router' +import type { Route } from './+types/_index' + +export const loader = (args: Route.LoaderArgs) => { + const extra = args.context.extra + const cloudflare = args.context.cloudflare + const myVarInVariables = args.context.hono.context.get('MY_VAR_IN_VARIABLES') + return { cloudflare, extra, myVarInVariables } +} + +export default function Index() { + const { cloudflare, extra, myVarInVariables } = useLoaderData() + return ( +
+

Remix and Hono

+

Var is {cloudflare.env.MY_VAR}

+

+ {cloudflare.cf ? 'cf,' : ''} + {cloudflare.ctx ? 'ctx,' : ''} + {cloudflare.caches ? 'caches are available' : ''} +

+

Extra is {extra}

+
Var in Variables is {myVarInVariables}
+
+ ) +} diff --git a/examples/react-router/cloudflare-pages/e2e.test.ts b/examples/react-router/cloudflare-pages/e2e.test.ts new file mode 100644 index 0000000..1af16bd --- /dev/null +++ b/examples/react-router/cloudflare-pages/e2e.test.ts @@ -0,0 +1,30 @@ +import { expect, test } from '@playwright/test' + +test('Should return 200 response - /', async ({ page }) => { + const response = await page.goto('/') + expect(response?.status()).toBe(200) + + const headers = response?.headers() ?? {} + expect(headers['x-powered-by']).toBe('Remix and Hono') + + const contentH1 = await page.textContent('h1') + expect(contentH1).toBe('Remix and Hono') + + const contentH2 = await page.textContent('h2') + expect(contentH2).toBe('Var is My Value') + + const contentH3 = await page.textContent('h3') + expect(contentH3).toBe('cf,ctx,caches are available') + + const contentH4 = await page.textContent('h4') + expect(contentH4).toBe('Extra is stuff') + + const contentH5 = await page.textContent('h5') + expect(contentH5).toBe('Var in Variables is My variable set in c.set') +}) + +test('Should return 200 response - /api', async ({ page }) => { + const response = await page.goto('/api') + expect(response?.status()).toBe(200) + expect(await response?.json()).toEqual({ message: 'Hello', var: 'My Value' }) +}) diff --git a/examples/react-router/cloudflare-pages/functions/[[path]].ts b/examples/react-router/cloudflare-pages/functions/[[path]].ts new file mode 100644 index 0000000..e2b321e --- /dev/null +++ b/examples/react-router/cloudflare-pages/functions/[[path]].ts @@ -0,0 +1,7 @@ +// functions/[[path]].ts +import handle from 'hono-remix-adapter/cloudflare-pages' +import { getLoadContext } from 'load-context' +import * as build from '../build/server' +import server from '../server' + +export const onRequest = handle(build, server, { getLoadContext }) diff --git a/examples/react-router/cloudflare-pages/load-context.ts b/examples/react-router/cloudflare-pages/load-context.ts new file mode 100644 index 0000000..2ec22c4 --- /dev/null +++ b/examples/react-router/cloudflare-pages/load-context.ts @@ -0,0 +1,40 @@ +import type { Context } from 'hono' +import type { AppLoadContext } from 'react-router' +import type { PlatformProxy } from 'wrangler' + +type Env = { + Bindings: { + MY_VAR: string + } + Variables: { + MY_VAR_IN_VARIABLES: string + } +} + +type Cloudflare = Omit, 'dispose'> + +declare module 'react-router' { + interface AppLoadContext { + cloudflare: Cloudflare + extra: string + hono: { + context: Context + } + } +} + +type GetLoadContext = (args: { + request: Request + context: { + cloudflare: Cloudflare + hono: { context: Context } + } +}) => AppLoadContext + +// Shared implementation compatible with Vite, Wrangler, and Cloudflare Pages +export const getLoadContext: GetLoadContext = ({ context }) => { + return { + ...context, + extra: 'stuff', + } +} diff --git a/examples/react-router/cloudflare-pages/package.json b/examples/react-router/cloudflare-pages/package.json new file mode 100644 index 0000000..ed5ed2c --- /dev/null +++ b/examples/react-router/cloudflare-pages/package.json @@ -0,0 +1,40 @@ +{ + "name": "example-cloudflare-pages-react-router", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "build": "react-router build", + "deploy": "npm run build && wrangler pages deploy", + "dev": "react-router dev", + "start": "wrangler pages dev ./build/client", + "typecheck": "tsc", + "preview": "npm run build && wrangler pages dev", + "test:e2e:vite": "playwright test -c playwright-vite.config.ts e2e.test.ts", + "test:e2e:pages": "npm run build && playwright test -c playwright-pages.config.ts e2e.test.ts" + }, + "dependencies": { + "@react-router/cloudflare": "^7.0.1", + "hono": "^4.5.11", + "isbot": "^4.1.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "remix-hono": "^0.0.16", + "react-router": "^7.0.1" + }, + "devDependencies": { + "@hono/vite-dev-server": "^0.16.0", + "@playwright/test": "^1.48.2", + "@react-router/dev": "^7.0.1", + "@types/react": "^18.2.20", + "@types/react-dom": "^18.2.7", + "playwright": "^1.47.0", + "typescript": "^5.1.6", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1", + "wrangler": "3.57.1" + }, + "engines": { + "node": ">=20.0.0" + } +} \ No newline at end of file diff --git a/examples/react-router/cloudflare-pages/playwright-pages.config.ts b/examples/react-router/cloudflare-pages/playwright-pages.config.ts new file mode 100644 index 0000000..da2c1e8 --- /dev/null +++ b/examples/react-router/cloudflare-pages/playwright-pages.config.ts @@ -0,0 +1,26 @@ +import { defineConfig, devices } from '@playwright/test' + +const port = 8798 + +export default defineConfig({ + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + use: { + baseURL: `http://localhost:${port.toString()}`, + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + timeout: 5000, + retries: 2, + }, + ], + webServer: { + command: `npm exec wrangler pages dev -- --port ${port.toString()}`, + port, + reuseExistingServer: !process.env.CI, + }, +}) diff --git a/examples/react-router/cloudflare-pages/playwright-vite.config.ts b/examples/react-router/cloudflare-pages/playwright-vite.config.ts new file mode 100644 index 0000000..af0c1ec --- /dev/null +++ b/examples/react-router/cloudflare-pages/playwright-vite.config.ts @@ -0,0 +1,26 @@ +import { defineConfig, devices } from '@playwright/test' + +const port = 6173 + +export default defineConfig({ + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + use: { + baseURL: `http://localhost:${port.toString()}`, + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + timeout: 5000, + retries: 2, + }, + ], + webServer: { + command: `npm exec vite -- --port ${port.toString()} -c ./vite.config.ts`, + port, + reuseExistingServer: !process.env.CI, + }, +}) diff --git a/examples/react-router/cloudflare-pages/server/index.ts b/examples/react-router/cloudflare-pages/server/index.ts new file mode 100644 index 0000000..3c1df33 --- /dev/null +++ b/examples/react-router/cloudflare-pages/server/index.ts @@ -0,0 +1,26 @@ +// server/index.ts +import { Hono } from 'hono' + +const app = new Hono<{ + Bindings: { + MY_VAR: string + } + Variables: { + MY_VAR_IN_VARIABLES: string + } +}>() + +app.use(async (c, next) => { + c.set('MY_VAR_IN_VARIABLES', 'My variable set in c.set') + await next() + c.header('X-Powered-By', 'Remix and Hono') +}) + +app.get('/api', (c) => { + return c.json({ + message: 'Hello', + var: c.env.MY_VAR, + }) +}) + +export default app diff --git a/examples/react-router/cloudflare-pages/tsconfig.json b/examples/react-router/cloudflare-pages/tsconfig.json new file mode 100644 index 0000000..2199bb3 --- /dev/null +++ b/examples/react-router/cloudflare-pages/tsconfig.json @@ -0,0 +1,45 @@ +{ + "include": [ + "**/*.ts", + "**/*.tsx", + "**/.server/**/*.ts", + "**/.server/**/*.tsx", + "**/.client/**/*.ts", + "**/.client/**/*.tsx" + ], + "compilerOptions": { + "lib": [ + "DOM", + "DOM.Iterable", + "ES2022" + ], + "types": [ + "@react-router/cloudflare", + "vite/client", + "@cloudflare/workers-types/2023-07-01" + ], + "isolatedModules": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "target": "ES2022", + "strict": true, + "allowJs": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "rootDirs": [ + ".", + "./.react-router/types" + ], + "baseUrl": ".", + "paths": { + "~/*": [ + "./app/*" + ] + }, + // Vite takes care of building everything, not tsc. + "noEmit": true + } +} \ No newline at end of file diff --git a/examples/react-router/cloudflare-pages/vite.config.ts b/examples/react-router/cloudflare-pages/vite.config.ts new file mode 100644 index 0000000..fd11c59 --- /dev/null +++ b/examples/react-router/cloudflare-pages/vite.config.ts @@ -0,0 +1,21 @@ +// vite.config.ts +import adapter from '@hono/vite-dev-server/cloudflare' +import { reactRouter } from '@react-router/dev/vite' +import { cloudflareDevProxy } from '@react-router/dev/vite/cloudflare' +import serverAdapter from 'hono-remix-adapter/vite@react-router' +import { defineConfig } from 'vite' +import tsconfigPaths from 'vite-tsconfig-paths' +import { getLoadContext } from './load-context' + +export default defineConfig({ + plugins: [ + cloudflareDevProxy(), + reactRouter(), + serverAdapter({ + adapter, + getLoadContext, + entry: 'server/index.ts', + }), + tsconfigPaths(), + ], +}) diff --git a/examples/react-router/cloudflare-pages/wrangler.toml b/examples/react-router/cloudflare-pages/wrangler.toml new file mode 100644 index 0000000..f1861dc --- /dev/null +++ b/examples/react-router/cloudflare-pages/wrangler.toml @@ -0,0 +1,86 @@ +#:schema node_modules/wrangler/config-schema.json +name = "example-cloudflare-pages" +compatibility_date = "2024-09-03" +pages_build_output_dir = "./build/client" + +# Automatically place your workloads in an optimal location to minimize latency. +# If you are running back-end logic in a Pages Function, running it closer to your back-end infrastructure +# rather than the end user may result in better performance. +# Docs: https://developers.cloudflare.com/pages/functions/smart-placement/#smart-placement +# [placement] +# mode = "smart" + +# Variable bindings. These are arbitrary, plaintext strings (similar to environment variables) +# Docs: +# - https://developers.cloudflare.com/pages/functions/bindings/#environment-variables +# Note: Use secrets to store sensitive data. +# - https://developers.cloudflare.com/pages/functions/bindings/#secrets + +[vars] +MY_VAR = "My Value" + +# Bind the Workers AI model catalog. Run machine learning models, powered by serverless GPUs, on Cloudflare’s global network +# Docs: https://developers.cloudflare.com/pages/functions/bindings/#workers-ai +# [ai] +# binding = "AI" + +# Bind a D1 database. D1 is Cloudflare’s native serverless SQL database. +# Docs: https://developers.cloudflare.com/pages/functions/bindings/#d1-databases +# [[d1_databases]] +# binding = "MY_DB" +# database_name = "my-database" +# database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + +# Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model. +# Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps. +# Docs: https://developers.cloudflare.com/workers/runtime-apis/durable-objects +# [[durable_objects.bindings]] +# name = "MY_DURABLE_OBJECT" +# class_name = "MyDurableObject" +# script_name = 'my-durable-object' + +# Bind a KV Namespace. Use KV as persistent storage for small key-value pairs. +# Docs: https://developers.cloudflare.com/pages/functions/bindings/#kv-namespaces +# [[kv_namespaces]] +# binding = "MY_KV_NAMESPACE" +# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +# Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer. +# Docs: https://developers.cloudflare.com/pages/functions/bindings/#queue-producers +# [[queues.producers]] +# binding = "MY_QUEUE" +# queue = "my-queue" + +# Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files. +# Docs: https://developers.cloudflare.com/pages/functions/bindings/#r2-buckets +# [[r2_buckets]] +# binding = "MY_BUCKET" +# bucket_name = "my-bucket" + +# Bind another Worker service. Use this binding to call another Worker without network overhead. +# Docs: https://developers.cloudflare.com/pages/functions/bindings/#service-bindings +# [[services]] +# binding = "MY_SERVICE" +# service = "my-service" + +# To use different bindings for preview and production environments, follow the examples below. +# When using environment-specific overrides for bindings, ALL bindings must be specified on a per-environment basis. +# Docs: https://developers.cloudflare.com/pages/functions/wrangler-configuration#environment-specific-overrides + +######## PREVIEW environment config ######## + +# [env.preview.vars] +# API_KEY = "xyz789" + +# [[env.preview.kv_namespaces]] +# binding = "MY_KV_NAMESPACE" +# id = "" + +######## PRODUCTION environment config ######## + +# [env.production.vars] +# API_KEY = "abc123" + +# [[env.production.kv_namespaces]] +# binding = "MY_KV_NAMESPACE" +# id = "" diff --git a/examples/react-router/cloudflare-workers/.gitignore b/examples/react-router/cloudflare-workers/.gitignore new file mode 100644 index 0000000..2cef2d0 --- /dev/null +++ b/examples/react-router/cloudflare-workers/.gitignore @@ -0,0 +1,10 @@ +node_modules + +test-results + +/.cache +/build +.env +.dev.vars + +.wrangler diff --git a/examples/react-router/cloudflare-workers/app/entry.client.tsx b/examples/react-router/cloudflare-workers/app/entry.client.tsx new file mode 100644 index 0000000..38f2bbb --- /dev/null +++ b/examples/react-router/cloudflare-workers/app/entry.client.tsx @@ -0,0 +1,18 @@ +/** + * By default, Remix will handle hydrating your app on the client for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.client + */ + +import { startTransition, StrictMode } from 'react' +import { hydrateRoot } from 'react-dom/client' +import { HydratedRouter } from 'react-router/dom' + +startTransition(() => { + hydrateRoot( + document, + + + + ) +}) diff --git a/examples/react-router/cloudflare-workers/app/entry.server.tsx b/examples/react-router/cloudflare-workers/app/entry.server.tsx new file mode 100644 index 0000000..6ee6df0 --- /dev/null +++ b/examples/react-router/cloudflare-workers/app/entry.server.tsx @@ -0,0 +1,58 @@ +/** + * By default, Remix will handle generating the HTTP Response for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.server + */ + +import { isbot } from 'isbot' +// @ts-expect-error `react-dom/server.browser` is not typed +import { renderToReadableStream } from 'react-dom/server.browser' +import type { AppLoadContext, EntryContext } from 'react-router' +import { ServerRouter } from 'react-router' + +const ABORT_DELAY = 5000 + +export default async function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars + loadContext: AppLoadContext, +) { + const controller = new AbortController() + const timeoutId = setTimeout(() => controller.abort(), ABORT_DELAY) + + const body = await renderToReadableStream( + , + { + signal: controller.signal, + onError(error: unknown) { + if (!controller.signal.aborted) { + // Log streaming rendering errors from inside the shell + console.error(error) + } + // biome-ignore lint/style/noParameterAssign: + responseStatusCode = 500 + }, + }, + ) + + body.allReady.then(() => clearTimeout(timeoutId)) + + if (isbot(request.headers.get('user-agent') || '')) { + await body.allReady + } + + responseHeaders.set('Content-Type', 'text/html') + return new Response(body, { + headers: responseHeaders, + status: responseStatusCode, + }) +} diff --git a/examples/react-router/cloudflare-workers/app/root.tsx b/examples/react-router/cloudflare-workers/app/root.tsx new file mode 100644 index 0000000..da639de --- /dev/null +++ b/examples/react-router/cloudflare-workers/app/root.tsx @@ -0,0 +1,20 @@ +import { Outlet, Scripts } from 'react-router' + +export function Layout({ children }: { children: React.ReactNode }) { + return ( + + + + + + + {children} + + + + ) +} + +export default function App() { + return +} diff --git a/examples/react-router/cloudflare-workers/app/routes.ts b/examples/react-router/cloudflare-workers/app/routes.ts new file mode 100644 index 0000000..d48c140 --- /dev/null +++ b/examples/react-router/cloudflare-workers/app/routes.ts @@ -0,0 +1,7 @@ +import { index } from '@react-router/dev/routes' +import type {RouteConfig} from '@react-router/dev/routes' + +export default [ + index('routes/_index.tsx'), + +] satisfies RouteConfig diff --git a/examples/react-router/cloudflare-workers/app/routes/_index.tsx b/examples/react-router/cloudflare-workers/app/routes/_index.tsx new file mode 100644 index 0000000..8ae82d7 --- /dev/null +++ b/examples/react-router/cloudflare-workers/app/routes/_index.tsx @@ -0,0 +1,26 @@ +import { useLoaderData } from 'react-router' +import type { Route } from './+types/_index' + +export const loader = (args: Route.LoaderArgs) => { + const extra = args.context.extra + const cloudflare = args.context.cloudflare + const myVarInVariables = args.context.hono.context.get('MY_VAR_IN_VARIABLES') + return { cloudflare, extra, myVarInVariables } +} + +export default function Index() { + const { cloudflare, extra, myVarInVariables } = useLoaderData() + return ( +
+

Remix and Hono

+

Var is {cloudflare.env.MY_VAR}

+

+ {cloudflare.cf ? 'cf,' : ''} + {cloudflare.ctx ? 'ctx,' : ''} + {cloudflare.caches ? 'caches are available' : ''} +

+

Extra is {extra}

+
Var in Variables is {myVarInVariables}
+
+ ) +} diff --git a/examples/react-router/cloudflare-workers/e2e.test.ts b/examples/react-router/cloudflare-workers/e2e.test.ts new file mode 100644 index 0000000..1af16bd --- /dev/null +++ b/examples/react-router/cloudflare-workers/e2e.test.ts @@ -0,0 +1,30 @@ +import { expect, test } from '@playwright/test' + +test('Should return 200 response - /', async ({ page }) => { + const response = await page.goto('/') + expect(response?.status()).toBe(200) + + const headers = response?.headers() ?? {} + expect(headers['x-powered-by']).toBe('Remix and Hono') + + const contentH1 = await page.textContent('h1') + expect(contentH1).toBe('Remix and Hono') + + const contentH2 = await page.textContent('h2') + expect(contentH2).toBe('Var is My Value') + + const contentH3 = await page.textContent('h3') + expect(contentH3).toBe('cf,ctx,caches are available') + + const contentH4 = await page.textContent('h4') + expect(contentH4).toBe('Extra is stuff') + + const contentH5 = await page.textContent('h5') + expect(contentH5).toBe('Var in Variables is My variable set in c.set') +}) + +test('Should return 200 response - /api', async ({ page }) => { + const response = await page.goto('/api') + expect(response?.status()).toBe(200) + expect(await response?.json()).toEqual({ message: 'Hello', var: 'My Value' }) +}) diff --git a/examples/react-router/cloudflare-workers/load-context.ts b/examples/react-router/cloudflare-workers/load-context.ts new file mode 100644 index 0000000..02b949d --- /dev/null +++ b/examples/react-router/cloudflare-workers/load-context.ts @@ -0,0 +1,42 @@ +import type { Context } from 'hono' +import type { PlatformProxy } from 'wrangler' + +type Env = { + Bindings: { + MY_VAR: string + } + Variables: { + MY_VAR_IN_VARIABLES: string + } +} + +type GetLoadContextArgs = { + request: Request + context: { + cloudflare: Omit, 'dispose' | 'caches' | 'cf'> & { + caches: PlatformProxy['caches'] | CacheStorage + cf: Request['cf'] + } + hono: { + context: Context + } + } +} + +declare module 'react-router' { + + interface AppLoadContext extends ReturnType { + // This will merge the result of `getLoadContext` into the `AppLoadContext` + extra: string + hono: { + context: Context + } + } +} + +export function getLoadContext({ context }: GetLoadContextArgs) { + return { + ...context, + extra: 'stuff', + } +} diff --git a/examples/react-router/cloudflare-workers/package.json b/examples/react-router/cloudflare-workers/package.json new file mode 100644 index 0000000..8ae4d1a --- /dev/null +++ b/examples/react-router/cloudflare-workers/package.json @@ -0,0 +1,39 @@ +{ + "name": "example-cloudflare-workers-react-router", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "build": "react-router build", + "deploy": "npm run build && wrangler deploy", + "dev": "react-router dev", + "start": "wrangler dev", + "typecheck": "tsc", + "preview": "npm run build && wrangler dev", + "test:e2e:vite": "playwright test -c playwright-vite.config.ts e2e.test.ts", + "test:e2e:workers": "npm run build && playwright test -c playwright-workers.config.ts e2e.test.ts" + }, + "dependencies": { + "@react-router/cloudflare": "^7.0.1", + "hono": "^4.6.9", + "isbot": "^4.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^7.0.1" + }, + "devDependencies": { + "@hono/vite-dev-server": "^0.16.0", + "@playwright/test": "^1.48.2", + "@react-router/dev": "^7.0.1", + "@types/react": "^18.2.20", + "@types/react-dom": "^18.2.7", + "playwright": "^1.47.0", + "typescript": "^5.1.6", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1", + "wrangler": "^3.86.0" + }, + "engines": { + "node": ">=20.0.0" + } +} diff --git a/examples/react-router/cloudflare-workers/playwright-vite.config.ts b/examples/react-router/cloudflare-workers/playwright-vite.config.ts new file mode 100644 index 0000000..af0c1ec --- /dev/null +++ b/examples/react-router/cloudflare-workers/playwright-vite.config.ts @@ -0,0 +1,26 @@ +import { defineConfig, devices } from '@playwright/test' + +const port = 6173 + +export default defineConfig({ + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + use: { + baseURL: `http://localhost:${port.toString()}`, + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + timeout: 5000, + retries: 2, + }, + ], + webServer: { + command: `npm exec vite -- --port ${port.toString()} -c ./vite.config.ts`, + port, + reuseExistingServer: !process.env.CI, + }, +}) diff --git a/examples/react-router/cloudflare-workers/playwright-workers.config.ts b/examples/react-router/cloudflare-workers/playwright-workers.config.ts new file mode 100644 index 0000000..544bfa0 --- /dev/null +++ b/examples/react-router/cloudflare-workers/playwright-workers.config.ts @@ -0,0 +1,26 @@ +import { defineConfig, devices } from '@playwright/test' + +const port = 8797 + +export default defineConfig({ + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + use: { + baseURL: `http://localhost:${port.toString()}`, + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + timeout: 5000, + retries: 2, + }, + ], + webServer: { + command: `npm exec wrangler dev -- --port ${port.toString()} ./worker.ts`, + port, + reuseExistingServer: !process.env.CI, + }, +}) diff --git a/examples/react-router/cloudflare-workers/public/.assetsignore b/examples/react-router/cloudflare-workers/public/.assetsignore new file mode 100644 index 0000000..e69de29 diff --git a/examples/react-router/cloudflare-workers/public/favicon.ico b/examples/react-router/cloudflare-workers/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8830cf6821b354114848e6354889b8ecf6d2bc61 GIT binary patch literal 16958 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 EKbET!0{{R3 literal 0 HcmV?d00001 diff --git a/examples/react-router/cloudflare-workers/server/index.ts b/examples/react-router/cloudflare-workers/server/index.ts new file mode 100644 index 0000000..3c1df33 --- /dev/null +++ b/examples/react-router/cloudflare-workers/server/index.ts @@ -0,0 +1,26 @@ +// server/index.ts +import { Hono } from 'hono' + +const app = new Hono<{ + Bindings: { + MY_VAR: string + } + Variables: { + MY_VAR_IN_VARIABLES: string + } +}>() + +app.use(async (c, next) => { + c.set('MY_VAR_IN_VARIABLES', 'My variable set in c.set') + await next() + c.header('X-Powered-By', 'Remix and Hono') +}) + +app.get('/api', (c) => { + return c.json({ + message: 'Hello', + var: c.env.MY_VAR, + }) +}) + +export default app diff --git a/examples/react-router/cloudflare-workers/tsconfig.json b/examples/react-router/cloudflare-workers/tsconfig.json new file mode 100644 index 0000000..9d92975 --- /dev/null +++ b/examples/react-router/cloudflare-workers/tsconfig.json @@ -0,0 +1,46 @@ +{ + "include": [ + "worker-configuration.d.ts", + "env.d.ts", + "**/*.ts", + "**/*.tsx", + "**/.server/**/*.ts", + "**/.server/**/*.tsx", + "**/.client/**/*.ts", + "**/.client/**/*.tsx" + ], + "compilerOptions": { + "lib": [ + "DOM", + "DOM.Iterable", + "ES2022" + ], + "types": [ + "@react-router/cloudflare", + "vite/client", + "@cloudflare/workers-types/2023-07-01" + ], + "isolatedModules": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "target": "ES2022", + "strict": true, + "allowJs": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "rootDirs": [ + ".", + "./.react-router/types" + ], + "baseUrl": ".", + "paths": { + "~/*": [ + "./app/*" + ] + }, + // Remix takes care of building everything in `remix build`. + "noEmit": true + } +} \ No newline at end of file diff --git a/examples/react-router/cloudflare-workers/vite.config.ts b/examples/react-router/cloudflare-workers/vite.config.ts new file mode 100644 index 0000000..fd11c59 --- /dev/null +++ b/examples/react-router/cloudflare-workers/vite.config.ts @@ -0,0 +1,21 @@ +// vite.config.ts +import adapter from '@hono/vite-dev-server/cloudflare' +import { reactRouter } from '@react-router/dev/vite' +import { cloudflareDevProxy } from '@react-router/dev/vite/cloudflare' +import serverAdapter from 'hono-remix-adapter/vite@react-router' +import { defineConfig } from 'vite' +import tsconfigPaths from 'vite-tsconfig-paths' +import { getLoadContext } from './load-context' + +export default defineConfig({ + plugins: [ + cloudflareDevProxy(), + reactRouter(), + serverAdapter({ + adapter, + getLoadContext, + entry: 'server/index.ts', + }), + tsconfigPaths(), + ], +}) diff --git a/examples/react-router/cloudflare-workers/worker.ts b/examples/react-router/cloudflare-workers/worker.ts new file mode 100644 index 0000000..931425d --- /dev/null +++ b/examples/react-router/cloudflare-workers/worker.ts @@ -0,0 +1,6 @@ +import handle from 'hono-remix-adapter/cloudflare-workers@react-router' +import * as build from './build/server' +import { getLoadContext } from './load-context' +import app from './server' + +export default handle(build, app, { getLoadContext }) diff --git a/examples/react-router/cloudflare-workers/wrangler.toml b/examples/react-router/cloudflare-workers/wrangler.toml new file mode 100644 index 0000000..b9d1b3e --- /dev/null +++ b/examples/react-router/cloudflare-workers/wrangler.toml @@ -0,0 +1,8 @@ +#:schema node_modules/wrangler/config-schema.json +name = "example-cloudflare-workers" +compatibility_date = "2024-11-06" +main = "./worker.ts" +assets = { directory = "./build/client" } + +[vars] +MY_VAR = "My Value" \ No newline at end of file diff --git a/examples/react-router/node/.gitignore b/examples/react-router/node/.gitignore new file mode 100644 index 0000000..2cef2d0 --- /dev/null +++ b/examples/react-router/node/.gitignore @@ -0,0 +1,10 @@ +node_modules + +test-results + +/.cache +/build +.env +.dev.vars + +.wrangler diff --git a/examples/react-router/node/app/entry.client.tsx b/examples/react-router/node/app/entry.client.tsx new file mode 100644 index 0000000..38f2bbb --- /dev/null +++ b/examples/react-router/node/app/entry.client.tsx @@ -0,0 +1,18 @@ +/** + * By default, Remix will handle hydrating your app on the client for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.client + */ + +import { startTransition, StrictMode } from 'react' +import { hydrateRoot } from 'react-dom/client' +import { HydratedRouter } from 'react-router/dom' + +startTransition(() => { + hydrateRoot( + document, + + + + ) +}) diff --git a/examples/react-router/node/app/entry.server.tsx b/examples/react-router/node/app/entry.server.tsx new file mode 100644 index 0000000..947887f --- /dev/null +++ b/examples/react-router/node/app/entry.server.tsx @@ -0,0 +1,122 @@ +/** + * By default, Remix will handle generating the HTTP Response for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.server + */ + + +import { createReadableStreamFromReadable } from '@react-router/node' +import { isbot } from 'isbot' +import { renderToPipeableStream } from 'react-dom/server' +import type { AppLoadContext, EntryContext } from 'react-router' +import { ServerRouter } from 'react-router' +import { PassThrough } from 'node:stream' + +const ABORT_DELAY = 5_000 + +export default function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars + loadContext: AppLoadContext +) { + return isbot(request.headers.get('user-agent') || '') + ? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext) + : handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext) +} + +function handleBotRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +) { + return new Promise((resolve, reject) => { + let shellRendered = false + const { pipe, abort } = renderToPipeableStream( + , + { + onAllReady() { + shellRendered = true + const body = new PassThrough() + const stream = createReadableStreamFromReadable(body) + + responseHeaders.set('Content-Type', 'text/html') + + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }) + ) + + pipe(body) + }, + onShellError(error: unknown) { + reject(error) + }, + onError(error: unknown) { + responseStatusCode = 500 + // Log streaming rendering errors from inside the shell. Don't log + // errors encountered during initial shell rendering since they'll + // reject and get logged in handleDocumentRequest. + if (shellRendered) { + console.error(error) + } + }, + } + ) + + setTimeout(abort, ABORT_DELAY) + }) +} + +function handleBrowserRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +) { + return new Promise((resolve, reject) => { + let shellRendered = false + const { pipe, abort } = renderToPipeableStream( + , + { + onShellReady() { + shellRendered = true + const body = new PassThrough() + const stream = createReadableStreamFromReadable(body) + + responseHeaders.set('Content-Type', 'text/html') + + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }) + ) + + pipe(body) + }, + onShellError(error: unknown) { + reject(error) + }, + onError(error: unknown) { + responseStatusCode = 500 + // Log streaming rendering errors from inside the shell. Don't log + // errors encountered during initial shell rendering since they'll + // reject and get logged in handleDocumentRequest. + if (shellRendered) { + console.error(error) + } + }, + } + ) + + setTimeout(abort, ABORT_DELAY) + }) +} diff --git a/examples/react-router/node/app/root.tsx b/examples/react-router/node/app/root.tsx new file mode 100644 index 0000000..da639de --- /dev/null +++ b/examples/react-router/node/app/root.tsx @@ -0,0 +1,20 @@ +import { Outlet, Scripts } from 'react-router' + +export function Layout({ children }: { children: React.ReactNode }) { + return ( + + + + + + + {children} + + + + ) +} + +export default function App() { + return +} diff --git a/examples/react-router/node/app/routes.ts b/examples/react-router/node/app/routes.ts new file mode 100644 index 0000000..d48c140 --- /dev/null +++ b/examples/react-router/node/app/routes.ts @@ -0,0 +1,7 @@ +import { index } from '@react-router/dev/routes' +import type {RouteConfig} from '@react-router/dev/routes' + +export default [ + index('routes/_index.tsx'), + +] satisfies RouteConfig diff --git a/examples/react-router/node/app/routes/_index.tsx b/examples/react-router/node/app/routes/_index.tsx new file mode 100644 index 0000000..74dd351 --- /dev/null +++ b/examples/react-router/node/app/routes/_index.tsx @@ -0,0 +1,19 @@ +import { useLoaderData } from 'react-router' +import type { Route } from './+types/_index' + +export const loader = (args: Route.LoaderArgs) => { + const extra = args.context.extra + const url = args.context.url + return { extra, url } +} + +export default function Index() { + const { extra, url } = useLoaderData() + return ( +
+

Remix and Hono

+

URL is {url}

+

Extra is {extra}

+
+ ) +} diff --git a/examples/react-router/node/e2e.test.ts b/examples/react-router/node/e2e.test.ts new file mode 100644 index 0000000..d0e8022 --- /dev/null +++ b/examples/react-router/node/e2e.test.ts @@ -0,0 +1,24 @@ +import { expect, test } from '@playwright/test' + +test('Should return 200 response - /', async ({ page }) => { + const response = await page.goto('/') + expect(response?.status()).toBe(200) + + const headers = response?.headers() ?? {} + expect(headers['x-powered-by']).toBe('Remix and Hono') + + const contentH1 = await page.textContent('h1') + expect(contentH1).toBe('Remix and Hono') + + const contentH2 = await page.textContent('h2') + expect(contentH2).toMatch(/URL is http:\/\/localhost:\d+/) + + const contentH3 = await page.textContent('h3') + expect(contentH3).toBe('Extra is stuff') +}) + +test('Should return 200 response - /api', async ({ page }) => { + const response = await page.goto('/api') + expect(response?.status()).toBe(200) + expect(await response?.json()).toEqual({ message: 'Hello' }) +}) diff --git a/examples/react-router/node/load-context.ts b/examples/react-router/node/load-context.ts new file mode 100644 index 0000000..7922de7 --- /dev/null +++ b/examples/react-router/node/load-context.ts @@ -0,0 +1,17 @@ +type GetLoadContextArgs = { + request: Request +} + +declare module 'react-router' { + interface AppLoadContext extends ReturnType { + url: string + extra: string + } +} + +export function getLoadContext(args: GetLoadContextArgs) { + return { + url: args.request.url, + extra: 'stuff', + } +} diff --git a/examples/react-router/node/main.ts b/examples/react-router/node/main.ts new file mode 100644 index 0000000..65ac659 --- /dev/null +++ b/examples/react-router/node/main.ts @@ -0,0 +1,17 @@ +// main.ts +import { serve } from '@hono/node-server' +import { serveStatic } from '@hono/node-server/serve-static' +import handle from 'hono-remix-adapter/node' +import * as build from './build/server' +import { getLoadContext } from './load-context' +import server from './server' + +server.use( + serveStatic({ + root: './build/client', + }) +) + +const handler = handle(build, server, { getLoadContext }) + +serve({ fetch: handler.fetch, port: 3010 }) diff --git a/examples/react-router/node/package.json b/examples/react-router/node/package.json new file mode 100644 index 0000000..f10046d --- /dev/null +++ b/examples/react-router/node/package.json @@ -0,0 +1,40 @@ +{ + "name": "example-node-react-router", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "build": "react-router build", + "dev": "react-router dev", + "start": "react-router-serve ./build/server/index.js", + "start-with-adapter": "tsx main.ts", + "test:e2e:vite": "playwright test -c playwright-vite.config.ts e2e.test.ts", + "test:e2e:node": "npm run build && playwright test -c playwright-node.config.ts e2e.test.ts", + "typecheck": "tsc" + }, + "dependencies": { + "@hono/node-server": "^1.13.7", + "@react-router/node": "^7.0.1", + "@react-router/serve": "^7.0.1", + "hono": "^4.6.11", + "isbot": "^4.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^7.0.1" + }, + "devDependencies": { + "@playwright/test": "^1.48.2", + "@react-router/dev": "^7.0.1", + "@types/react": "^18.2.20", + "@types/react-dom": "^18.2.7", + "autoprefixer": "^10.4.19", + "playwright": "^1.47.0", + "tsx": "^4.19.2", + "typescript": "^5.1.6", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1" + }, + "engines": { + "node": ">=20.0.0" + } +} diff --git a/examples/react-router/node/playwright-node.config.ts b/examples/react-router/node/playwright-node.config.ts new file mode 100644 index 0000000..958d1a2 --- /dev/null +++ b/examples/react-router/node/playwright-node.config.ts @@ -0,0 +1,26 @@ +import { defineConfig, devices } from '@playwright/test' + +const port = 3010 + +export default defineConfig({ + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + use: { + baseURL: `http://localhost:${port.toString()}`, + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + timeout: 5000, + retries: 2, + }, + ], + webServer: { + command: 'npm exec tsx ./main.ts', + port, + reuseExistingServer: !process.env.CI, + }, +}) diff --git a/examples/react-router/node/playwright-vite.config.ts b/examples/react-router/node/playwright-vite.config.ts new file mode 100644 index 0000000..af0c1ec --- /dev/null +++ b/examples/react-router/node/playwright-vite.config.ts @@ -0,0 +1,26 @@ +import { defineConfig, devices } from '@playwright/test' + +const port = 6173 + +export default defineConfig({ + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + workers: process.env.CI ? 1 : undefined, + use: { + baseURL: `http://localhost:${port.toString()}`, + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + timeout: 5000, + retries: 2, + }, + ], + webServer: { + command: `npm exec vite -- --port ${port.toString()} -c ./vite.config.ts`, + port, + reuseExistingServer: !process.env.CI, + }, +}) diff --git a/examples/react-router/node/public/favicon.ico b/examples/react-router/node/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8830cf6821b354114848e6354889b8ecf6d2bc61 GIT binary patch literal 16958 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 EKbET!0{{R3 literal 0 HcmV?d00001 diff --git a/examples/react-router/node/server/index.ts b/examples/react-router/node/server/index.ts new file mode 100644 index 0000000..387be72 --- /dev/null +++ b/examples/react-router/node/server/index.ts @@ -0,0 +1,17 @@ +// server/index.ts +import { Hono } from 'hono' + +const app = new Hono() + +app.use(async (c, next) => { + await next() + c.header('X-Powered-By', 'Remix and Hono') +}) + +app.get('/api', (c) => { + return c.json({ + message: 'Hello', + }) +}) + +export default app diff --git a/examples/react-router/node/tsconfig.json b/examples/react-router/node/tsconfig.json new file mode 100644 index 0000000..58ff9b6 --- /dev/null +++ b/examples/react-router/node/tsconfig.json @@ -0,0 +1,44 @@ +{ + "include": [ + "**/*.ts", + "**/*.tsx", + "**/.server/**/*.ts", + "**/.server/**/*.tsx", + "**/.client/**/*.ts", + "**/.client/**/*.tsx" + ], + "compilerOptions": { + "lib": [ + "DOM", + "DOM.Iterable", + "ES2022" + ], + "types": [ + "@react-router/node", + "vite/client" + ], + "isolatedModules": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "target": "ES2022", + "strict": true, + "allowJs": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "rootDirs": [ + ".", + "./.react-router/types" + ], + "baseUrl": ".", + "paths": { + "~/*": [ + "./app/*" + ] + }, + // Vite takes care of building everything, not tsc. + "noEmit": true + } +} \ No newline at end of file diff --git a/examples/react-router/node/vite.config.ts b/examples/react-router/node/vite.config.ts new file mode 100644 index 0000000..5c77287 --- /dev/null +++ b/examples/react-router/node/vite.config.ts @@ -0,0 +1,16 @@ +import { reactRouter } from '@react-router/dev/vite' +import serverAdapter from 'hono-remix-adapter/vite@react-router' +import { defineConfig } from 'vite' +import tsconfigPaths from 'vite-tsconfig-paths' +import { getLoadContext } from './load-context' + +export default defineConfig({ + plugins: [ + reactRouter(), + serverAdapter({ + getLoadContext, + entry: './server/index.ts', + }), + tsconfigPaths(), + ], +}) diff --git a/package-lock.json b/package-lock.json index b864f4b..942ca89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,10 @@ "/", "./examples/cloudflare-pages", "./examples/cloudflare-workers", - "./examples/node" + "./examples/node", + "./examples/react-router/cloudflare-pages", + "./examples/react-router/cloudflare-workers", + "./examples/react-router/node" ], "dependencies": { "@hono/vite-dev-server": "^0.17.0", @@ -541,6 +544,357 @@ "node": ">=20.0.0" } }, + "examples/react-router/cloudflare-pages": { + "name": "example-cloudflare-pages-react-router", + "dependencies": { + "@react-router/cloudflare": "^7.0.1", + "hono": "^4.5.11", + "isbot": "^4.1.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router": "^7.0.1", + "remix-hono": "^0.0.16" + }, + "devDependencies": { + "@hono/vite-dev-server": "^0.16.0", + "@playwright/test": "^1.48.2", + "@react-router/dev": "^7.0.1", + "@types/react": "^18.2.20", + "@types/react-dom": "^18.2.7", + "playwright": "^1.47.0", + "typescript": "^5.1.6", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1", + "wrangler": "3.57.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "examples/react-router/cloudflare-pages/node_modules/@cloudflare/kv-asset-handler": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.2.tgz", + "integrity": "sha512-EeEjMobfuJrwoctj7FA1y1KEbM0+Q1xSjobIEyie9k4haVEBB7vkDvsasw1pM3rO39mL2akxIAzLMUAtrMHZhA==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "mime": "^3.0.0" + }, + "engines": { + "node": ">=16.13" + } + }, + "examples/react-router/cloudflare-pages/node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20240512.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240512.0.tgz", + "integrity": "sha512-VMp+CsSHFALQiBzPdQ5dDI4T1qwLu0mQ0aeKVNDosXjueN0f3zj/lf+mFil5/9jBbG3t4mG0y+6MMnalP9Lobw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "examples/react-router/cloudflare-pages/node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20240512.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240512.0.tgz", + "integrity": "sha512-lZktXGmzMrB5rJqY9+PmnNfv1HKlj/YLZwMjPfF0WVKHUFdvQbAHsi7NlKv6mW9uIvlZnS+K4sIkWc0MDXcRnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "examples/react-router/cloudflare-pages/node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20240512.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240512.0.tgz", + "integrity": "sha512-wrHvqCZZqXz6Y3MUTn/9pQNsvaoNjbJpuA6vcXsXu8iCzJi911iVW2WUEBX+MpUWD+mBIP0oXni5tTlhkokOPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "examples/react-router/cloudflare-pages/node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20240512.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240512.0.tgz", + "integrity": "sha512-YPezHMySL9J9tFdzxz390eBswQ//QJNYcZolz9Dgvb3FEfdpK345cE/bsWbMOqw5ws2f82l388epoenghtYvAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "examples/react-router/cloudflare-pages/node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20240512.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240512.0.tgz", + "integrity": "sha512-SxKapDrIYSscMR7lGIp/av0l6vokjH4xQ9ACxHgXh+OdOus9azppSmjaPyw4/ePvg7yqpkaNjf9o258IxWtvKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "examples/react-router/cloudflare-pages/node_modules/@hono/vite-dev-server": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@hono/vite-dev-server/-/vite-dev-server-0.16.0.tgz", + "integrity": "sha512-zGPaYY7DyDr33id677fUuaPiV2qQJoPrxv+nrcLc7g8M9PkcvlV8kO2XRkrwZT64rUSBxyWOuGN3vEIFiH9l0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@hono/node-server": "^1.12.0", + "minimatch": "^9.0.3" + }, + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "*", + "miniflare": "*", + "wrangler": "*" + }, + "peerDependenciesMeta": { + "hono": { + "optional": false + }, + "miniflare": { + "optional": true + }, + "wrangler": { + "optional": true + } + } + }, + "examples/react-router/cloudflare-pages/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "examples/react-router/cloudflare-pages/node_modules/miniflare": { + "version": "3.20240512.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20240512.0.tgz", + "integrity": "sha512-X0PlKR0AROKpxFoJNmRtCMIuJxj+ngEcyTOlEokj2rAQ0TBwUhB4/1uiPvdI6ofW5NugPOD1uomAv+gLjwsLDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "acorn": "^8.8.0", + "acorn-walk": "^8.2.0", + "capnp-ts": "^0.7.0", + "exit-hook": "^2.2.1", + "glob-to-regexp": "^0.4.1", + "stoppable": "^1.1.0", + "undici": "^5.28.2", + "workerd": "1.20240512.0", + "ws": "^8.11.0", + "youch": "^3.2.2", + "zod": "^3.20.6" + }, + "bin": { + "miniflare": "bootstrap.js" + }, + "engines": { + "node": ">=16.13" + } + }, + "examples/react-router/cloudflare-pages/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "examples/react-router/cloudflare-pages/node_modules/workerd": { + "version": "1.20240512.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20240512.0.tgz", + "integrity": "sha512-VUBmR1PscAPHEE0OF/G2K7/H1gnr9aDWWZzdkIgWfNKkv8dKFCT75H+GJtUHjfwqz3rYCzaNZmatSXOpLGpF8A==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20240512.0", + "@cloudflare/workerd-darwin-arm64": "1.20240512.0", + "@cloudflare/workerd-linux-64": "1.20240512.0", + "@cloudflare/workerd-linux-arm64": "1.20240512.0", + "@cloudflare/workerd-windows-64": "1.20240512.0" + } + }, + "examples/react-router/cloudflare-pages/node_modules/wrangler": { + "version": "3.57.1", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.57.1.tgz", + "integrity": "sha512-M8YnWUwdrb8AFiRePtVnzlDn02OX4osWvdl8oVh6eyZqqkqXYg7lwlYBr14Qj92pMN4JvMBmDZoukkYHvwpJRg==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/kv-asset-handler": "0.3.2", + "@esbuild-plugins/node-globals-polyfill": "^0.2.3", + "@esbuild-plugins/node-modules-polyfill": "^0.2.2", + "blake3-wasm": "^2.1.5", + "chokidar": "^3.5.3", + "esbuild": "0.17.19", + "miniflare": "3.20240512.0", + "nanoid": "^3.3.3", + "path-to-regexp": "^6.2.0", + "resolve": "^1.22.8", + "resolve.exports": "^2.0.2", + "selfsigned": "^2.0.1", + "source-map": "0.6.1", + "xxhash-wasm": "^1.0.1" + }, + "bin": { + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=16.17.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.20240512.0" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "examples/react-router/cloudflare-workers": { + "name": "example-cloudflare-workers-react-router", + "dependencies": { + "@react-router/cloudflare": "^7.0.1", + "hono": "^4.6.9", + "isbot": "^4.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^7.0.1" + }, + "devDependencies": { + "@hono/vite-dev-server": "^0.16.0", + "@playwright/test": "^1.48.2", + "@react-router/dev": "^7.0.1", + "@types/react": "^18.2.20", + "@types/react-dom": "^18.2.7", + "playwright": "^1.47.0", + "typescript": "^5.1.6", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1", + "wrangler": "^3.86.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "examples/react-router/cloudflare-workers/node_modules/@hono/vite-dev-server": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@hono/vite-dev-server/-/vite-dev-server-0.16.0.tgz", + "integrity": "sha512-zGPaYY7DyDr33id677fUuaPiV2qQJoPrxv+nrcLc7g8M9PkcvlV8kO2XRkrwZT64rUSBxyWOuGN3vEIFiH9l0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@hono/node-server": "^1.12.0", + "minimatch": "^9.0.3" + }, + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "*", + "miniflare": "*", + "wrangler": "*" + }, + "peerDependenciesMeta": { + "hono": { + "optional": false + }, + "miniflare": { + "optional": true + }, + "wrangler": { + "optional": true + } + } + }, + "examples/react-router/node": { + "name": "example-node-react-router", + "dependencies": { + "@hono/node-server": "^1.13.7", + "@react-router/node": "^7.0.1", + "@react-router/serve": "^7.0.1", + "hono": "^4.6.11", + "isbot": "^4.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router": "^7.0.1" + }, + "devDependencies": { + "@playwright/test": "^1.48.2", + "@react-router/dev": "^7.0.1", + "@types/react": "^18.2.20", + "@types/react-dom": "^18.2.7", + "autoprefixer": "^10.4.19", + "playwright": "^1.47.0", + "tsx": "^4.19.2", + "typescript": "^5.1.6", + "vite": "^5.1.0", + "vite-tsconfig-paths": "^4.2.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -1723,12 +2077,12 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "openbsd" ], + "peer": true, "engines": { "node": ">=18" } @@ -2079,7 +2433,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^5.1.2", @@ -2097,7 +2450,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -2110,7 +2462,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -2139,7 +2490,6 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -2154,7 +2504,6 @@ "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -2165,7 +2514,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "devOptional": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -2175,7 +2523,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -2185,7 +2532,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "devOptional": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -2236,6 +2582,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/@mjackson/node-fetch-server": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@mjackson/node-fetch-server/-/node-fetch-server-0.2.0.tgz", + "integrity": "sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng==", + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2465,7 +2817,6 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, "license": "MIT", "optional": true, "engines": { @@ -2498,39 +2849,253 @@ "node": ">=12.22.0" } }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dev": true, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "license": "ISC" + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", + "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@react-router/cloudflare": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@react-router/cloudflare/-/cloudflare-7.0.1.tgz", + "integrity": "sha512-naYG/aB5BJdiVf93Y8WVT76kw8PSYoWPYTOHUpsGZ1Iuhr/dS3P3glAZKAoHRIbeE3kvwba2t5iv1GNpMeEs1A==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^4.0.0", + "react-router": "^7.0.1", + "tsup": "^8.3.0", + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@react-router/dev": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@react-router/dev/-/dev-7.0.1.tgz", + "integrity": "sha512-7B9xUb/5um3Pe/zqpObQP/Yhypw49q6CFxn7NWWS78DJnuO7axXuH4IerrMLIiqv+8Ft0uo3UQVj+ztTr0T2+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.8", + "@babel/generator": "^7.21.5", + "@babel/parser": "^7.21.8", + "@babel/plugin-syntax-decorators": "^7.22.10", + "@babel/plugin-syntax-jsx": "^7.21.4", + "@babel/preset-typescript": "^7.21.5", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.22.5", + "@npmcli/package-json": "^4.0.1", + "@react-router/node": "7.0.1", + "arg": "^5.0.1", + "babel-dead-code-elimination": "^1.0.6", + "chokidar": "^4.0.0", + "dedent": "^1.5.3", + "es-module-lexer": "^1.3.1", + "exit-hook": "2.2.1", + "fs-extra": "^10.0.0", + "gunzip-maybe": "^1.4.2", + "jsesc": "3.0.2", + "lodash": "^4.17.21", + "pathe": "^1.1.2", + "picocolors": "^1.1.1", + "picomatch": "^2.3.1", + "prettier": "^2.7.1", + "react-refresh": "^0.14.0", + "semver": "^7.3.7", + "set-cookie-parser": "^2.6.0", + "valibot": "^0.41.0", + "vite-node": "^1.6.0" + }, + "bin": { + "react-router": "bin.js" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@react-router/serve": "^7.0.1", + "react-router": "^7.0.1", + "typescript": "^5.1.0", + "vite": "^5.1.0", + "wrangler": "^3.28.2" + }, + "peerDependenciesMeta": { + "@react-router/serve": { + "optional": true + }, + "typescript": { + "optional": true + }, + "wrangler": { + "optional": true + } + } + }, + "node_modules/@react-router/dev/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@react-router/dev/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@react-router/dev/node_modules/vite-node": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", + "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@react-router/express": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@react-router/express/-/express-7.0.1.tgz", + "integrity": "sha512-zAw65RMiF5TshPVvmoCpUjjpNwC7vmpp38lqP2xX6Rfp+K99LhMaNyhsIeG9pKNIXQ7EuMwp3zG7kjr5suQAiA==", + "license": "MIT", + "dependencies": { + "@react-router/node": "7.0.1" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "express": "^4.17.1", + "react-router": "7.0.1", + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@react-router/node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@react-router/node/-/node-7.0.1.tgz", + "integrity": "sha512-09AkG1jobbMApTx4Wx8lf1u+nZeYG2ZOBAhxTLz7dgnr7sQpUVD3ewe9gizedXpJrCfP4Sx272aGywX1gEqoSQ==", "license": "MIT", "dependencies": { - "graceful-fs": "4.2.10" + "@mjackson/node-fetch-server": "^0.2.0", + "source-map-support": "^0.5.21", + "stream-slice": "^0.1.2", + "undici": "^6.19.2" }, "engines": { - "node": ">=12.22.0" + "node": ">=20.0.0" + }, + "peerDependencies": { + "react-router": "7.0.1", + "typescript": "^5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true, - "license": "ISC" + "node_modules/@react-router/node/node_modules/undici": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.0.tgz", + "integrity": "sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } }, - "node_modules/@pnpm/npm-conf": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", - "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", - "dev": true, + "node_modules/@react-router/serve": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@react-router/serve/-/serve-7.0.1.tgz", + "integrity": "sha512-JkU9aCtj61P7o+cZt+4NWHpij7c71jBnj/lF06zGIp+4VP9q6hUN3pMjdLZe91mBZu6dfmWUTh8hlY6pCoeUIA==", "license": "MIT", "dependencies": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" + "@react-router/express": "7.0.1", + "@react-router/node": "7.0.1", + "compression": "^1.7.4", + "express": "^4.19.2", + "get-port": "5.1.1", + "morgan": "^1.10.0", + "source-map-support": "^0.5.21" + }, + "bin": { + "react-router-serve": "bin.js" }, "engines": { - "node": ">=12" + "node": ">=20.0.0" + }, + "peerDependencies": { + "react-router": "7.0.1" } }, "node_modules/@remix-run/cloudflare": { @@ -3475,13 +4040,12 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.2.tgz", - "integrity": "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.4.tgz", + "integrity": "sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3489,13 +4053,12 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.2.tgz", - "integrity": "sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.4.tgz", + "integrity": "sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3503,13 +4066,12 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.2.tgz", - "integrity": "sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.4.tgz", + "integrity": "sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3517,27 +4079,51 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.2.tgz", - "integrity": "sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz", + "integrity": "sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.4.tgz", + "integrity": "sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.4.tgz", + "integrity": "sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.2.tgz", - "integrity": "sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.4.tgz", + "integrity": "sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3545,13 +4131,12 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.2.tgz", - "integrity": "sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.4.tgz", + "integrity": "sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3559,13 +4144,12 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.2.tgz", - "integrity": "sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.4.tgz", + "integrity": "sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3573,13 +4157,12 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.2.tgz", - "integrity": "sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.4.tgz", + "integrity": "sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3587,13 +4170,12 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.2.tgz", - "integrity": "sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.4.tgz", + "integrity": "sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==", "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3601,13 +4183,12 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.2.tgz", - "integrity": "sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.4.tgz", + "integrity": "sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==", "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3615,13 +4196,12 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.2.tgz", - "integrity": "sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.4.tgz", + "integrity": "sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==", "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3629,13 +4209,12 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.2.tgz", - "integrity": "sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz", + "integrity": "sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3643,13 +4222,12 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.2.tgz", - "integrity": "sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz", + "integrity": "sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3657,13 +4235,12 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.2.tgz", - "integrity": "sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.4.tgz", + "integrity": "sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3671,13 +4248,12 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.2.tgz", - "integrity": "sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.4.tgz", + "integrity": "sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==", "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3685,13 +4261,12 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.2.tgz", - "integrity": "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==", + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.4.tgz", + "integrity": "sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3753,10 +4328,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "license": "MIT" }, "node_modules/@types/estree-jsx": { @@ -4394,7 +4968,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4404,7 +4977,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -4430,7 +5002,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, "license": "MIT" }, "node_modules/anymatch": { @@ -4483,16 +5054,6 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", @@ -4609,6 +5170,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/babel-dead-code-elimination": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/babel-dead-code-elimination/-/babel-dead-code-elimination-1.0.6.tgz", + "integrity": "sha512-JxFi9qyRJpN0LjEbbjbN8g0ux71Qppn9R8Qe3k6QzHg2CaKsbUQtbn307LQGiDLGjV6JCtEFqfxzVig9MyDCHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + } + }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -5003,7 +5577,6 @@ "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5548,7 +6121,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -5561,7 +6133,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/comma-separated-tokens": { @@ -5579,7 +6150,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -5694,7 +6264,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", - "dev": true, "license": "MIT", "engines": { "node": "^14.18.0 || >=16.10.0" @@ -5784,7 +6353,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -5904,7 +6472,6 @@ "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "devOptional": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -6335,7 +6902,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, "license": "MIT" }, "node_modules/ee-first": { @@ -6365,7 +6931,6 @@ "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, "license": "MIT" }, "node_modules/encodeurl": { @@ -7208,14 +7773,26 @@ "resolved": "examples/cloudflare-pages", "link": true }, + "node_modules/example-cloudflare-pages-react-router": { + "resolved": "examples/react-router/cloudflare-pages", + "link": true + }, "node_modules/example-cloudflare-workers": { "resolved": "examples/cloudflare-workers", "link": true }, + "node_modules/example-cloudflare-workers-react-router": { + "resolved": "examples/react-router/cloudflare-workers", + "link": true + }, "node_modules/example-node": { "resolved": "examples/node", "link": true }, + "node_modules/example-node-react-router": { + "resolved": "examples/react-router/node", + "link": true + }, "node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -7574,7 +8151,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", @@ -7852,7 +8428,7 @@ "version": "4.8.0", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.0.tgz", "integrity": "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -7980,27 +8556,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/globrex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", @@ -9078,7 +9633,6 @@ "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==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9521,7 +10075,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, "node_modules/issue-regex": { @@ -9548,7 +10101,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -9571,7 +10123,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -9737,7 +10288,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "dev": true, "license": "MIT", "engines": { "node": ">=14" @@ -9750,7 +10300,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, "license": "MIT" }, "node_modules/listr": { @@ -10274,7 +10823,6 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", - "dev": true, "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" @@ -10355,7 +10903,6 @@ "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", - "dev": true, "license": "MIT" }, "node_modules/lodash.zip": { @@ -10518,7 +11065,6 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, "license": "ISC" }, "node_modules/magic-string": { @@ -11594,7 +12140,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" @@ -11837,7 +12382,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, "license": "MIT", "dependencies": { "any-promise": "^1.0.0", @@ -12599,7 +13143,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -13041,7 +13584,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true, "license": "BlueOak-1.0.0" }, "node_modules/pako": { @@ -13147,7 +13689,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -13164,7 +13705,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", @@ -13236,10 +13776,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { @@ -13281,7 +13820,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -13375,7 +13913,7 @@ "version": "8.4.45", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz", "integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==", - "dev": true, + "devOptional": true, "funding": [ { "type": "opencollective", @@ -13417,7 +13955,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", - "dev": true, "funding": [ { "type": "opencollective", @@ -13766,7 +14303,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -14345,7 +14881,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, + "devOptional": true, "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" @@ -14444,13 +14980,12 @@ } }, "node_modules/rollup": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz", - "integrity": "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==", - "dev": true, + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.4.tgz", + "integrity": "sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==", "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -14460,22 +14995,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.2", - "@rollup/rollup-android-arm64": "4.21.2", - "@rollup/rollup-darwin-arm64": "4.21.2", - "@rollup/rollup-darwin-x64": "4.21.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.2", - "@rollup/rollup-linux-arm-musleabihf": "4.21.2", - "@rollup/rollup-linux-arm64-gnu": "4.21.2", - "@rollup/rollup-linux-arm64-musl": "4.21.2", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.2", - "@rollup/rollup-linux-riscv64-gnu": "4.21.2", - "@rollup/rollup-linux-s390x-gnu": "4.21.2", - "@rollup/rollup-linux-x64-gnu": "4.21.2", - "@rollup/rollup-linux-x64-musl": "4.21.2", - "@rollup/rollup-win32-arm64-msvc": "4.21.2", - "@rollup/rollup-win32-ia32-msvc": "4.21.2", - "@rollup/rollup-win32-x64-msvc": "4.21.2", + "@rollup/rollup-android-arm-eabi": "4.27.4", + "@rollup/rollup-android-arm64": "4.27.4", + "@rollup/rollup-darwin-arm64": "4.27.4", + "@rollup/rollup-darwin-x64": "4.27.4", + "@rollup/rollup-freebsd-arm64": "4.27.4", + "@rollup/rollup-freebsd-x64": "4.27.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.27.4", + "@rollup/rollup-linux-arm-musleabihf": "4.27.4", + "@rollup/rollup-linux-arm64-gnu": "4.27.4", + "@rollup/rollup-linux-arm64-musl": "4.27.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.27.4", + "@rollup/rollup-linux-riscv64-gnu": "4.27.4", + "@rollup/rollup-linux-s390x-gnu": "4.27.4", + "@rollup/rollup-linux-x64-gnu": "4.27.4", + "@rollup/rollup-linux-x64-musl": "4.27.4", + "@rollup/rollup-win32-arm64-msvc": "4.27.4", + "@rollup/rollup-win32-ia32-msvc": "4.27.4", + "@rollup/rollup-win32-x64-msvc": "4.27.4", "fsevents": "~2.3.2" } }, @@ -14849,7 +15386,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -14862,7 +15398,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -14907,7 +15442,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "license": "ISC", "engines": { "node": ">=14" @@ -14916,16 +15450,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/slice-ansi": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", @@ -14949,7 +15473,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, + "devOptional": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -15128,7 +15652,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", @@ -15147,7 +15670,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -15162,14 +15684,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -15182,7 +15702,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -15284,7 +15803,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -15298,7 +15816,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -15383,7 +15900,6 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", @@ -15406,7 +15922,6 @@ "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -15642,7 +16157,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, "license": "MIT", "dependencies": { "any-promise": "^1.0.0" @@ -15652,7 +16166,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" @@ -15728,6 +16241,51 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyexec": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", + "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", + "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", + "license": "MIT", + "dependencies": { + "fdir": "^6.4.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", + "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tinypool": { "version": "0.8.4", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", @@ -15793,7 +16351,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", - "dev": true, "license": "MIT", "dependencies": { "punycode": "^2.1.0" @@ -15803,7 +16360,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, "license": "MIT", "bin": { "tree-kill": "cli.js" @@ -15848,7 +16404,6 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true, "license": "Apache-2.0" }, "node_modules/tsconfck": { @@ -15895,27 +16450,26 @@ "license": "0BSD" }, "node_modules/tsup": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.2.4.tgz", - "integrity": "sha512-akpCPePnBnC/CXgRrcy72ZSntgIEUa1jN0oJbbvpALWKNOz1B7aM+UVDWGRGIO/T/PZugAESWDJUAb5FD48o8Q==", - "dev": true, + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.3.5.tgz", + "integrity": "sha512-Tunf6r6m6tnZsG9GYWndg0z8dEV7fD733VBFzFJ5Vcm1FtlXB8xBD/rtrBi2a3YKEV7hHtxiZtW5EAVADoe1pA==", "license": "MIT", "dependencies": { "bundle-require": "^5.0.0", "cac": "^6.7.14", - "chokidar": "^3.6.0", + "chokidar": "^4.0.1", "consola": "^3.2.3", - "debug": "^4.3.5", - "esbuild": "^0.23.0", - "execa": "^5.1.1", - "globby": "^11.1.0", + "debug": "^4.3.7", + "esbuild": "^0.24.0", "joycon": "^3.1.1", - "picocolors": "^1.0.1", + "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", - "rollup": "^4.19.0", + "rollup": "^4.24.0", "source-map": "0.8.0-beta.0", "sucrase": "^3.35.0", + "tinyexec": "^0.3.1", + "tinyglobby": "^0.2.9", "tree-kill": "^1.2.2" }, "bin": { @@ -15947,13 +16501,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/aix-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", + "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -15964,13 +16517,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", + "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -15981,13 +16533,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", + "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -15998,13 +16549,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", + "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16015,13 +16565,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", + "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16032,13 +16581,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", + "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16049,13 +16597,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", + "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16064,15 +16611,14 @@ "engines": { "node": ">=18" } - }, - "node_modules/tsup/node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + }, + "node_modules/tsup/node_modules/@esbuild/freebsd-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", + "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16083,13 +16629,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", + "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16100,13 +16645,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", + "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16117,13 +16661,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", + "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16134,13 +16677,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", + "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16151,13 +16693,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", + "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16168,13 +16709,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", + "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16185,13 +16725,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", + "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16202,13 +16741,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", + "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16219,13 +16757,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16236,13 +16773,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", + "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16252,14 +16788,29 @@ "node": ">=18" } }, + "node_modules/tsup/node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", + "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/tsup/node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", + "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16270,13 +16821,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", + "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16287,13 +16837,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", + "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16304,13 +16853,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", + "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16321,13 +16869,12 @@ } }, "node_modules/tsup/node_modules/@esbuild/win32-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", + "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16341,7 +16888,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.0.0.tgz", "integrity": "sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==", - "dev": true, "license": "MIT", "dependencies": { "load-tsconfig": "^0.2.3" @@ -16353,167 +16899,86 @@ "esbuild": ">=0.18" } }, - "node_modules/tsup/node_modules/esbuild": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", - "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.1", - "@esbuild/android-arm": "0.23.1", - "@esbuild/android-arm64": "0.23.1", - "@esbuild/android-x64": "0.23.1", - "@esbuild/darwin-arm64": "0.23.1", - "@esbuild/darwin-x64": "0.23.1", - "@esbuild/freebsd-arm64": "0.23.1", - "@esbuild/freebsd-x64": "0.23.1", - "@esbuild/linux-arm": "0.23.1", - "@esbuild/linux-arm64": "0.23.1", - "@esbuild/linux-ia32": "0.23.1", - "@esbuild/linux-loong64": "0.23.1", - "@esbuild/linux-mips64el": "0.23.1", - "@esbuild/linux-ppc64": "0.23.1", - "@esbuild/linux-riscv64": "0.23.1", - "@esbuild/linux-s390x": "0.23.1", - "@esbuild/linux-x64": "0.23.1", - "@esbuild/netbsd-x64": "0.23.1", - "@esbuild/openbsd-arm64": "0.23.1", - "@esbuild/openbsd-x64": "0.23.1", - "@esbuild/sunos-x64": "0.23.1", - "@esbuild/win32-arm64": "0.23.1", - "@esbuild/win32-ia32": "0.23.1", - "@esbuild/win32-x64": "0.23.1" - } - }, - "node_modules/tsup/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, + "node_modules/tsup/node_modules/chokidar": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" + "readdirp": "^4.0.1" }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/tsup/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 14.16.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tsup/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/tsup/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, + "node_modules/tsup/node_modules/esbuild": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", + "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", + "hasInstallScript": true, "license": "MIT", - "engines": { - "node": ">=8" + "bin": { + "esbuild": "bin/esbuild" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tsup/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=6" - } - }, - "node_modules/tsup/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" + "node": ">=18" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsup/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" + } + }, + "node_modules/tsup/node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, "engines": { - "node": ">=6" + "node": ">= 14.16.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/tsup/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/tsup/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, "node_modules/tsup/node_modules/source-map": { "version": "0.8.0-beta.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "whatwg-url": "^7.0.0" @@ -16522,21 +16987,11 @@ "node": ">= 8" } }, - "node_modules/tsup/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/tsx": { "version": "4.19.2", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "esbuild": "~0.23.0", @@ -16559,7 +17014,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16577,7 +17031,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16595,7 +17048,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16613,7 +17065,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16631,7 +17082,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16649,7 +17099,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16667,7 +17116,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16685,7 +17133,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16703,7 +17150,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16721,7 +17167,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16739,7 +17184,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16757,7 +17201,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16775,7 +17218,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16793,7 +17235,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16811,7 +17252,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16829,7 +17269,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16847,7 +17286,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16865,7 +17303,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16883,7 +17320,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16901,7 +17337,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16919,7 +17354,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16937,7 +17371,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16955,7 +17388,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -16970,7 +17402,7 @@ "version": "0.23.1", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", - "dev": true, + "devOptional": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -18267,14 +18699,12 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/whatwg-url": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dev": true, "license": "MIT", "dependencies": { "lodash.sortby": "^4.7.0", @@ -18292,7 +18722,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -18677,7 +19106,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", @@ -18696,7 +19124,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -18714,14 +19141,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/wrap-ansi-cjs/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==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -18736,7 +19161,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -18749,7 +19173,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -18762,7 +19185,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -18844,7 +19266,7 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "yaml": "bin.mjs" diff --git a/package.json b/package.json index e9f4087..65bfbd2 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,9 @@ "test:e2e:cloudflare-pages": "npm run test:e2e:pages -w example-cloudflare-pages", "test:e2e:cloudflare-workers": "npm run test:e2e:workers -w example-cloudflare-workers", "test:e2e:node": "npm run test:e2e:node -w example-node", + "test:e2e:cloudflare-pages-react-router": "npm run test:e2e:pages -w example-cloudflare-pages-react-router", + "test:e2e:cloudflare-workers-react-router": "npm run test:e2e:workers -w example-cloudflare-workers-react-router", + "test:e2e:node-react-router": "npm run test:e2e:node -w example-node-react-router", "build": "tsup", "watch": "tsup --watch", "lint": "eslint src examples/cloudflare-pages/app examples/cloudflare-pages/server examples/cloudflare-workers/app examples/cloudflare-workers/server", @@ -26,7 +29,10 @@ "/", "./examples/cloudflare-pages", "./examples/cloudflare-workers", - "./examples/node" + "./examples/node", + "./examples/react-router/cloudflare-pages", + "./examples/react-router/cloudflare-workers", + "./examples/react-router/node" ], "exports": { "./vite": {