diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index beba5fd..9026e5e 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,16 +1,16 @@
version: 2
updates:
- - package-ecosystem: 'github-actions'
- directory: '/'
+ - package-ecosystem: "github-actions"
+ directory: "/"
schedule:
- interval: 'weekly'
- - package-ecosystem: 'npm'
- directory: '/'
+ interval: "weekly"
+ - package-ecosystem: "npm"
+ directory: "/"
open-pull-requests-limit: 10
schedule:
- interval: 'weekly'
+ interval: "weekly"
groups:
minor-upgrades:
update-types:
- - 'minor'
- - 'patch'
\ No newline at end of file
+ - "minor"
+ - "patch"
diff --git a/.github/lock.yml b/.github/lock.yml
index 74eee94..24b7466 100644
--- a/.github/lock.yml
+++ b/.github/lock.yml
@@ -11,7 +11,7 @@ daysUntilLock: 60
skipCreatedBefore: false
# Issues and pull requests with these labels will be ignored. Set to `[]` to disable
-exemptLabels: ['Type: Security']
+exemptLabels: ["Type: Security"]
# Label to add before locking, such as `outdated`. Set to `false` to disable
lockLabel: false
diff --git a/.github/stale.yml b/.github/stale.yml
index 8b47808..4b95d78 100644
--- a/.github/stale.yml
+++ b/.github/stale.yml
@@ -9,10 +9,10 @@ daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- - 'Type: Security'
+ - "Type: Security"
# Label to use when marking an issue as stale
-staleLabel: 'Status: Abandoned'
+staleLabel: "Status: Abandoned"
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 2634144..a0143ac 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -4,7 +4,7 @@ on:
types: [opened, synchronize, reopened]
push:
schedule:
- - cron: '0 16 * * *'
+ - cron: "0 16 * * *"
jobs:
linux:
@@ -44,4 +44,4 @@ jobs:
- name: Build
run: npm run build
- name: Run tests
- run: npm test
\ No newline at end of file
+ run: npm test
diff --git a/.gitignore b/.gitignore
index baf462d..800c854 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,4 +31,6 @@ public/assets/
*/.vitepress/cache
package-lock.json
-yarn.lock
\ No newline at end of file
+yarn.lock
+
+.react-router/
\ No newline at end of file
diff --git a/examples/with-tailwind-and-shadcn/package.json b/examples/with-tailwind-and-shadcn/package.json
index ef78ca3..d8d946d 100644
--- a/examples/with-tailwind-and-shadcn/package.json
+++ b/examples/with-tailwind-and-shadcn/package.json
@@ -43,7 +43,7 @@
"@japa/expect": "^3.0.2",
"@japa/plugin-adonisjs": "^3.0.1",
"@japa/runner": "^3.1.4",
- "@remix-run/dev": "^2.8.1",
+ "@react-router/dev": "^7.0.0",
"@swc/core": "^1.4.17",
"@types/luxon": "^3.4.2",
"@types/node": "^20.12.7",
@@ -70,10 +70,8 @@
"@adonisjs/vite": "^3.0.0-11",
"@matstack/remix-adonisjs": "^0.0.32",
"@radix-ui/react-popover": "^1.0.7",
- "@remix-run/css-bundle": "^2.8.1",
- "@remix-run/node": "^2.8.1",
- "@remix-run/react": "^2.8.1",
- "@remix-run/serve": "^2.8.1",
+ "@react-router/node": "^7.0.0",
+ "@react-router/serve": "^7.0.0",
"@vinejs/vine": "^2.0.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
@@ -83,6 +81,7 @@
"luxon": "^3.4.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-router": "^7.0.0",
"reflect-metadata": "^0.2.2",
"sqlite3": "^5.1.7",
"tailwind-merge": "^2.3.0",
@@ -104,4 +103,4 @@
"vite.config.ts.timestamp*"
]
}
-}
+}
\ No newline at end of file
diff --git a/examples/with-tailwind-and-shadcn/resources/remix_app/root.tsx b/examples/with-tailwind-and-shadcn/resources/remix_app/root.tsx
index 746e03d..b508847 100644
--- a/examples/with-tailwind-and-shadcn/resources/remix_app/root.tsx
+++ b/examples/with-tailwind-and-shadcn/resources/remix_app/root.tsx
@@ -1,13 +1,5 @@
-import { ActionFunctionArgs, LoaderFunctionArgs, json } from '@remix-run/node'
-import {
- Form,
- Links,
- Meta,
- Outlet,
- Scripts,
- ScrollRestoration,
- useLoaderData
-} from '@remix-run/react'
+import { ActionFunctionArgs, LoaderFunctionArgs, json } from 'react-router'
+import { Form, Links, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData } from 'react-router'
import { cn } from './lib/utils'
import vine from '@vinejs/vine'
@@ -21,9 +13,11 @@ export async function loader({ context }: LoaderFunctionArgs) {
// See the docs for more complex intent validation:
// https://matstack.dev/remix-adonisjs/recipes/validate-action-intent
-const actionValidator = vine.compile(vine.object({
- intent: vine.enum(['toggleColorScheme'])
-}))
+const actionValidator = vine.compile(
+ vine.object({
+ intent: vine.enum(['toggleColorScheme']),
+ })
+)
export async function action({ context }: ActionFunctionArgs) {
const { http } = context
@@ -49,7 +43,9 @@ export default function Page({ children }: { children: React.ReactNode }) {
{children}
diff --git a/examples/with-tailwind-and-shadcn/resources/remix_app/routes/_index.tsx b/examples/with-tailwind-and-shadcn/resources/remix_app/routes/_index.tsx
index a35ac6c..df9aeed 100644
--- a/examples/with-tailwind-and-shadcn/resources/remix_app/routes/_index.tsx
+++ b/examples/with-tailwind-and-shadcn/resources/remix_app/routes/_index.tsx
@@ -1,5 +1,5 @@
-import { json, type LoaderFunctionArgs, type MetaFunction } from '@remix-run/node'
-import { useLoaderData } from '@remix-run/react'
+import { json, type LoaderFunctionArgs, type MetaFunction } from 'react-router'
+import { useLoaderData } from 'react-router'
import { Popover, PopoverContent, PopoverTrigger } from '~/components/ui/popover'
export const meta: MetaFunction = () => {
@@ -15,33 +15,39 @@ export default function Index() {
const { message } = useLoaderData()
return (
-
-
-
Welcome to Remix
-
{message}
+
+
+
Welcome to Remix
+
{message}
-
+
-
-
+ rel="noreferrer"
+ >
15m Quickstart Blog Tutorial
-
-
+ rel="noreferrer"
+ >
Deep Dive Jokes App Tutorial
-
-
+ rel="noreferrer"
+ >
Remix Docs
diff --git a/examples/with-tailwind-and-shadcn/vite.config.ts b/examples/with-tailwind-and-shadcn/vite.config.ts
index e49eca1..9f5122b 100644
--- a/examples/with-tailwind-and-shadcn/vite.config.ts
+++ b/examples/with-tailwind-and-shadcn/vite.config.ts
@@ -1,4 +1,4 @@
-import { vitePlugin as remix } from '@remix-run/dev'
+import { reactRouter } from '@react-router/dev/vite'
import { defineConfig } from 'vite'
import tailwindcss from 'tailwindcss'
import autoprefixer from 'autoprefixer'
@@ -7,7 +7,7 @@ import tsconfigPaths from 'vite-tsconfig-paths'
export default defineConfig(({ isSsrBuild }) => ({
base: '/assets/',
plugins: [
- remix({
+ reactRouter({
appDirectory: 'resources/remix_app',
buildDirectory: 'build/remix',
serverBuildFile: 'server.js',
diff --git a/packages/adapter/commands/remix_route.ts b/packages/adapter/commands/remix_route.ts
index 10d3e26..9099a03 100644
--- a/packages/adapter/commands/remix_route.ts
+++ b/packages/adapter/commands/remix_route.ts
@@ -68,50 +68,48 @@ export default class MakeRemixRoute extends BaseCommand {
protected stubPath: string = 'make/route.tsx.stub'
private getImports() {
- const node = new Set()
- const react = new Set()
+ const localType = new Set()
+ const router = new Set()
if (this.action) {
- node.add('ActionFunctionArgs')
- react.add('useActionData')
+ localType.add('Route')
+ router.add('useActionData')
}
if (this.clientAction) {
- node.add('ClientActionFunctionArgs')
+ localType.add('Route')
}
if (this.loader) {
- node.add('LoaderFunctionArgs')
- node.add('json')
- react.add('useLoaderData')
+ localType.add('Route')
+ router.add('useLoaderData')
}
if (this.clientLoader) {
- node.add('ClientLoaderFunctionArgs')
+ localType.add('Route')
}
if (this.meta) {
- node.add('MetaFunction')
+ router.add('MetaFunction')
}
if (this.errorBoundary) {
- react.add('isRouteErrorResponse')
- react.add('useRouteError')
+ router.add('isRouteErrorResponse')
+ router.add('useRouteError')
}
if (this.headers) {
- node.add('HeadersFunction')
+ localType.add('Route')
}
return {
- node,
- react,
+ router,
+ localType,
}
}
async run() {
const imports = this.getImports()
const codemods = await this.createCodemods()
- console.log(this.parsed.flags)
await codemods.makeUsingStub(stubsRoot, this.stubPath, {
flags: this.parsed.flags,
name: this.name,
imports: {
- node: [...imports.node].join(', '),
- react: [...imports.react].join(', '),
+ localType: [...imports.localType].join(', '),
+ router: [...imports.router].join(', '),
},
})
}
diff --git a/packages/adapter/configure.ts b/packages/adapter/configure.ts
index 0373d4d..6dac4b7 100644
--- a/packages/adapter/configure.ts
+++ b/packages/adapter/configure.ts
@@ -7,15 +7,19 @@ export async function configure(command: Configure) {
const codemods = await command.createCodemods()
const dependencies = [
- '@remix-run/css-bundle',
- '@remix-run/node',
- '@remix-run/react',
- '@remix-run/serve',
+ '@react-router/node',
+ '@react-router/serve',
+ 'react-router',
'react',
'react-dom',
]
- const devDependencies = ['@remix-run/dev', '@types/react', '@types/react-dom']
+ const devDependencies = [
+ '@react-router/dev',
+ '@types/react',
+ '@types/react-dom',
+ '@react-router/fs-routes',
+ ]
await codemods.installPackages(
dependencies.map((name) => ({
diff --git a/packages/adapter/env.d.ts b/packages/adapter/env.d.ts
new file mode 100644
index 0000000..4ba8308
--- /dev/null
+++ b/packages/adapter/env.d.ts
@@ -0,0 +1,5 @@
+import type { AdonisApplicationContext } from './src/types/main.js'
+
+declare module 'react-router' {
+ interface AppLoadContext extends AdonisApplicationContext {}
+}
diff --git a/packages/adapter/package.json b/packages/adapter/package.json
index 4c35380..bd066f1 100644
--- a/packages/adapter/package.json
+++ b/packages/adapter/package.json
@@ -1,7 +1,7 @@
{
"name": "@matstack/remix-adonisjs",
"description": "An adapter for using Remix with AdonisJS",
- "version": "0.0.35",
+ "version": "1.0.0-rr7.6",
"engines": {
"node": ">=20.10.0"
},
@@ -81,12 +81,9 @@
"vite": "^5.4.11"
},
"peerDependencies": {
- "@adonisjs/core": "^6.7.0",
- "@remix-run/css-bundle": "^2.2.0",
- "@remix-run/dev": "^2.2.0",
- "@remix-run/node": "^2.2.0",
- "@remix-run/react": "^2.2.0",
+ "@react-router/node": "^7.0.0",
"react": "^18.2.0",
+ "react-router": "^7.0.0",
"react-dom": "^18.2.0"
},
"peerDependenciesMeta": {},
diff --git a/packages/adapter/providers/remix_provider.ts b/packages/adapter/providers/remix_provider.ts
index cc03409..cd66cfa 100644
--- a/packages/adapter/providers/remix_provider.ts
+++ b/packages/adapter/providers/remix_provider.ts
@@ -37,7 +37,7 @@ export default class RemixProvider {
const devServer = vite.getDevServer()
const build =
(this.app.inDev || this.app.inTest) && devServer
- ? () => devServer.ssrLoadModule('virtual:remix/server-build')
+ ? () => devServer.ssrLoadModule('virtual:react-router/server-build')
: await import(this.remixBundle)
const requestHandler = createRequestHandler({
diff --git a/packages/adapter/src/hooks/build_hook.ts b/packages/adapter/src/hooks/build_hook.ts
index dc6e119..fba2538 100644
--- a/packages/adapter/src/hooks/build_hook.ts
+++ b/packages/adapter/src/hooks/build_hook.ts
@@ -6,11 +6,11 @@ import path from 'node:path'
/**
*
- * The hook is responsible for launching the remix vite:build command when the application is built
+ * The hook is responsible for launching the react-router build command when the application is built
*/
export default async function remixBuildHook({ logger }: Parameters[0]) {
- logger.info('building remix app with vite')
- await runCommand('npx remix vite:build')
+ logger.info('building React Router app with vite')
+ await runCommand('npx react-router build')
const config = await resolveViteConfig()
// const cli = await import('@remix-run/dev')
// await cli.run(['vite:build'])
diff --git a/packages/adapter/src/remix_adapter.ts b/packages/adapter/src/remix_adapter.ts
index 6f3b5cb..dbdf54f 100644
--- a/packages/adapter/src/remix_adapter.ts
+++ b/packages/adapter/src/remix_adapter.ts
@@ -4,12 +4,14 @@ import type { Container } from '@adonisjs/core/container'
import type { HttpContext } from '@adonisjs/core/http'
import type { ContainerBindings } from '@adonisjs/core/types'
import type { Request as AdonisRequest, Response as AdonisResponse } from '@adonisjs/http-server'
+
import {
AppLoadContext,
ServerBuild,
- createReadableStreamFromReadable,
createRequestHandler as createRemixRequestHandler,
-} from '@remix-run/node'
+} from 'react-router'
+
+import { createReadableStreamFromReadable } from '@react-router/node'
import debug from './debug.js'
import { ReadableWebToNodeStream } from './stream_conversion.js'
@@ -18,7 +20,7 @@ export type HandlerContext = {
container: Container
}
-export type LoaderContext = {
+export type AdonisApplicationContext = {
http: HttpContext
make: Container['make']
}
diff --git a/packages/adapter/src/types/main.ts b/packages/adapter/src/types/main.ts
index 2c91399..33c962f 100644
--- a/packages/adapter/src/types/main.ts
+++ b/packages/adapter/src/types/main.ts
@@ -1,5 +1 @@
-import type { LoaderContext } from '../remix_adapter.js'
-
-declare module '@remix-run/node' {
- export interface AppLoadContext extends LoaderContext {}
-}
+export type { AdonisApplicationContext } from '../remix_adapter.js'
diff --git a/packages/adapter/stubs/_index.tsx.stub b/packages/adapter/stubs/_index.tsx.stub
index 1450f00..b844198 100644
--- a/packages/adapter/stubs/_index.tsx.stub
+++ b/packages/adapter/stubs/_index.tsx.stub
@@ -1,45 +1,26 @@
{{{
exports({ to: app.makePath('resources/remix_app/routes/_index.tsx') })
}}}
-import type { MetaFunction } from "@remix-run/node";
+import { useLoaderData } from "react-router";
+import type { Route } from "./+types/_index";
-export const meta: MetaFunction = () => {
+export function meta({ }: Route.MetaArgs) {
return [
- { title: "New Remix App" },
- { name: "description", content: "Welcome to Remix!" },
+ { title: "New React Router App" },
+ { name: "description", content: "Welcome to React Router!" },
];
-};
+}
+
+
+export async function loader({ context }: Route.LoaderArgs) {
+ const service = await context.make('hello_service')
+
+ return {
+ message: service.getMessage(),
+ }
+}
-export default function Index() {
- return (
-
-
Welcome to Remix
-
...powered by AdonisJS 😎
-
-
- );
+export default function Home() {
+ const { message } = useLoaderData()
+ return {message}
;
}
diff --git a/packages/adapter/stubs/app.css.stub b/packages/adapter/stubs/app.css.stub
new file mode 100644
index 0000000..7647a5c
--- /dev/null
+++ b/packages/adapter/stubs/app.css.stub
@@ -0,0 +1,15 @@
+{{{
+ exports({ to: app.makePath('resources/remix_app/app.css') })
+}}}
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+html,
+body {
+ @apply bg-white dark:bg-gray-950;
+
+ @media (prefers-color-scheme: dark) {
+ color-scheme: dark;
+ }
+}
diff --git a/packages/adapter/stubs/env.d.ts.stub b/packages/adapter/stubs/env.d.ts.stub
index e6f0938..02c2ef9 100644
--- a/packages/adapter/stubs/env.d.ts.stub
+++ b/packages/adapter/stubs/env.d.ts.stub
@@ -1,5 +1,8 @@
{{{
exports({ to: app.makePath("env.d.ts") })
}}}
-///
-///
\ No newline at end of file
+import type { AdonisApplicationContext } from '@matstack/remix-adonisjs/types';
+
+declare module 'react-router' {
+ interface AppLoadContext extends AdonisApplicationContext { }
+}
diff --git a/packages/adapter/stubs/make/route.tsx.stub b/packages/adapter/stubs/make/route.tsx.stub
index 7c20fd3..0d667d3 100644
--- a/packages/adapter/stubs/make/route.tsx.stub
+++ b/packages/adapter/stubs/make/route.tsx.stub
@@ -6,25 +6,24 @@
to: app.makePath('resources/remix_app/routes', routeFileName)
})
}}}
-{{#if imports.node}}
-import { {{imports.node}} } from '@remix-run/node'
+{{#if imports.router}}
+import { {{imports.router}} } from 'react-router'
{{/if}}
-{{#if imports.react}}
-import { {{imports.react}} } from '@remix-run/react'
+{{#if imports.localType}}
+import { {{imports.localType}} } from './+types/{{entity.name}}'
{{/if}}
{{{#if flags.loader}}}
-export const loader = ({ context }: LoaderFunctionArgs) => {
+export async function loader({ context }: Route.LoaderArgs) {
const { http, make } = context
- return json({
+ return {
message: 'Hello from ' + http.request.completeUrl(),
- })
+ }
}
{{{/if}}}
{{#if flags["client-loader"]}}
-// https://remix.run/docs/en/main/route/client-loader
-export const clientLoader = async ({ request, params, serverLoader }: ClientLoaderFunctionArgs) => {
+export async function clientLoader({ serverLoader }: Route.ClientLoaderArgs) {
// call the server loader
const serverData = await serverLoader();
// And/or fetch data on the client
@@ -34,16 +33,15 @@ export const clientLoader = async ({ request, params, serverLoader }: ClientLoad
}
{{/if}}
{{#if flags.action}}
-
-export const action = ({ context }: ActionFunctionArgs) => {
+export async function action({ context }: Route.ActionArgs) {
const { http, make } = context
return null
}
+
{{/if}}
{{#if flags["client-action"]}}
-// https://remix.run/docs/en/main/route/client-action
-export const clientAction = async ({ request, params, serverAction }: ClientActionFunctionArgs) => {
+export async function clientAction({ serverAction }: Route.ClientActionArgs) {
// invalidateClientSideCache()
const data = await serverAction()
return data
@@ -51,23 +49,18 @@ export const clientAction = async ({ request, params, serverAction }: ClientActi
{{/if}}
{{#if flags.meta}}
-// https://remix.run/docs/en/main/route/meta
-export const meta: MetaFunction = () => {
+export function meta({ }: Route.MetaArgs) {
return [{ title: '{{{name}}}' }, { name: 'description', content: 'Route {{{name}}}' }]
}
{{/if}}
{{#if flags.headers}}
-// https://remix.run/docs/en/main/route/headers
-export const headers: HeadersFunction = ({
- actionHeaders,
- errorHeaders,
- loaderHeaders,
- parentHeaders,
-}) => ({
- 'X-Stretchy-Pants': 'its for fun',
- 'Cache-Control': 'max-age=300, s-maxage=3600',
-})
+export function headers({ }: Route.HeadersArgs) {
+ return {
+ "X-Stretchy-Pants": "its for fun",
+ "Cache-Control": "max-age=300, s-maxage=3600",
+ };
+}
{{/if}}
export default function Page() {
@@ -81,7 +74,6 @@ export default function Page() {
}
{{#if flags['error-boundary']}}
-// https://remix.run/docs/en/main/route/error-boundary
export function ErrorBoundary() {
const error = useRouteError();
diff --git a/packages/adapter/stubs/react-router.config.ts.stub b/packages/adapter/stubs/react-router.config.ts.stub
new file mode 100644
index 0000000..c73a714
--- /dev/null
+++ b/packages/adapter/stubs/react-router.config.ts.stub
@@ -0,0 +1,10 @@
+{{{
+ exports({ to: app.makePath('resources/remix_app/react-router.config.ts') })
+}}}
+import type { Config } from '@react-router/dev/config'
+export default {
+ ssr: true,
+ appDirectory: 'resources/remix_app',
+ buildDirectory: 'build/remix',
+ serverBuildFile: 'server.js',
+} satisfies Config
diff --git a/packages/adapter/stubs/root.tsx.stub b/packages/adapter/stubs/root.tsx.stub
index 9cee13e..d3c3cac 100644
--- a/packages/adapter/stubs/root.tsx.stub
+++ b/packages/adapter/stubs/root.tsx.stub
@@ -1,21 +1,33 @@
{{{
exports({ to: app.makePath('resources/remix_app/root.tsx') })
}}}
-import { cssBundleHref } from "@remix-run/css-bundle";
-import type { LinksFunction } from "@remix-run/node";
import {
+ isRouteErrorResponse,
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
-} from "@remix-run/react";
+} from "react-router";
-export const links: LinksFunction = () => [
- ...(cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : []),
+import type { Route } from "./+types/root";
+import stylesheet from "./app.css?url";
+
+export const links: Route.LinksFunction = () => [
+ { rel: "preconnect", href: "https://fonts.googleapis.com" },
+ {
+ rel: "preconnect",
+ href: "https://fonts.gstatic.com",
+ crossOrigin: "anonymous",
+ },
+ {
+ rel: "stylesheet",
+ href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap",
+ },
+ { rel: "stylesheet", href: stylesheet },
];
-export default function App() {
+export function Layout({ children }: { children: React.ReactNode }) {
return (
@@ -25,10 +37,43 @@ export default function App() {
-
+ {children}
);
-}
\ No newline at end of file
+}
+
+export default function App() {
+ return ;
+}
+
+export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
+ let message = "Oops!";
+ let details = "An unexpected error occurred.";
+ let stack: string | undefined;
+
+ if (isRouteErrorResponse(error)) {
+ message = error.status === 404 ? "404" : "Error";
+ details =
+ error.status === 404
+ ? "The requested page could not be found."
+ : error.statusText || details;
+ } else if (import.meta.env.DEV && error && error instanceof Error) {
+ details = error.message;
+ stack = error.stack;
+ }
+
+ return (
+
+ {message}
+ {details}
+ {stack && (
+
+ {stack}
+
+ )}
+
+ );
+}
diff --git a/packages/adapter/stubs/routes.ts.stub b/packages/adapter/stubs/routes.ts.stub
new file mode 100644
index 0000000..5727c20
--- /dev/null
+++ b/packages/adapter/stubs/routes.ts.stub
@@ -0,0 +1,7 @@
+{{{
+ exports({ to: app.makePath("resources/remix_app/routes.ts") })
+}}}
+import { type RouteConfig } from '@react-router/dev/routes'
+import { flatRoutes } from '@react-router/fs-routes'
+
+export default flatRoutes() satisfies RouteConfig
diff --git a/packages/adapter/stubs/vite.config.ts.stub b/packages/adapter/stubs/vite.config.ts.stub
index 643dd3c..ee7b1f2 100644
--- a/packages/adapter/stubs/vite.config.ts.stub
+++ b/packages/adapter/stubs/vite.config.ts.stub
@@ -1,25 +1,18 @@
{{{
exports({ to: app.makePath("vite.config.ts") })
}}}
-import adonisjs from '@adonisjs/vite/client'
-import { vitePlugin as remix } from '@remix-run/dev'
-import { defineConfig } from 'vite'
+import { reactRouter } from '@react-router/dev/vite';
+import { defineConfig } from 'vite';
-export default defineConfig({
- base: '/assets/',
+export default defineConfig(({ isSsrBuild }) => ({
plugins: [
- remix({
- appDirectory: 'resources/remix_app',
- buildDirectory: 'build/remix',
- serverBuildFile: 'server.js',
- }),
- adonisjs({
- entrypoints: [],
- }),
+ reactRouter(),
],
- esbuildOptions: isSsrBuild
- ? {
- target: 'ES2022',
- }
- : {},
-})
+ optimizeDeps: {
+ esbuildOptions: isSsrBuild
+ ? {
+ target: 'ES2022',
+ }
+ : {},
+ },
+}))
diff --git a/packages/adapter/tests/adapter/http_server.ts b/packages/adapter/tests/adapter/http_server.ts
index 30aa7a8..54a86fb 100644
--- a/packages/adapter/tests/adapter/http_server.ts
+++ b/packages/adapter/tests/adapter/http_server.ts
@@ -8,9 +8,9 @@ import {
import { SessionMiddlewareFactory } from '@adonisjs/session/factories'
import { SessionConfig } from '@adonisjs/session/types'
import { getActiveTest } from '@japa/runner'
-import { RequestHandler } from '@remix-run/node'
import getPort from 'get-port'
import { IncomingMessage, Server, ServerResponse, createServer } from 'node:http'
+import { RequestHandler } from 'react-router'
import debug from '../../src/debug.js'
import { createRemixRequest, sendRemixResponse } from '../../src/remix_adapter.js'
import { CookieStore } from './cookie.js'
diff --git a/packages/adapter/tests/adapter/session.spec.ts b/packages/adapter/tests/adapter/session.spec.ts
index 8812430..fc6b848 100644
--- a/packages/adapter/tests/adapter/session.spec.ts
+++ b/packages/adapter/tests/adapter/session.spec.ts
@@ -1,5 +1,5 @@
import { test } from '@japa/runner'
-import { redirect } from '@remix-run/node'
+import { redirect } from 'react-router'
import setCookieParser from 'set-cookie-parser'
import supertest from 'supertest'
import { cookieClient, remixHandler } from './http_server.js'
diff --git a/packages/adapter/tests/commands/remix_route.spec.ts b/packages/adapter/tests/commands/remix_route.spec.ts
index f519463..680e690 100644
--- a/packages/adapter/tests/commands/remix_route.spec.ts
+++ b/packages/adapter/tests/commands/remix_route.spec.ts
@@ -36,29 +36,27 @@ test.group('Create remix route from stub', (group) => {
let flagRoutes: FlagRoute[] = [
{
flag: 'loader',
- codeMatch: 'export const loader = ({ context }: LoaderFunctionArgs) => {',
+ codeMatch: 'export async function loader({ context }: Route.LoaderArgs) {',
},
{
flag: 'client-loader',
- codeMatch:
- 'export const clientLoader = async ({ request, params, serverLoader }: ClientLoaderFunctionArgs) => {',
+ codeMatch: 'export async function clientLoader({ serverLoader }: Route.ClientLoaderArgs) {',
},
{
flag: 'action',
- codeMatch: 'export const action = ({ context }: ActionFunctionArgs) => {',
+ codeMatch: 'export async function action({ context }: Route.ActionArgs) {',
},
{
flag: 'client-action',
- codeMatch:
- 'export const clientAction = async ({ request, params, serverAction }: ClientActionFunctionArgs) => {',
+ codeMatch: 'export async function clientAction({ serverAction }: Route.ClientActionArgs) {',
},
{
flag: 'meta',
- codeMatch: 'export const meta: MetaFunction = () => {',
+ codeMatch: 'export function meta({ }: Route.MetaArgs) {',
},
{
flag: 'headers',
- codeMatch: 'export const headers: HeadersFunction = ({',
+ codeMatch: 'export function headers({ }: Route.HeadersArgs) {',
},
{
diff --git a/packages/reference-app/README.md b/packages/reference-app/README.md
index a48ea6f..5d5fcfe 100644
--- a/packages/reference-app/README.md
+++ b/packages/reference-app/README.md
@@ -1,4 +1,4 @@
# Reference app
This is a sample app built using remix-adonisjs.
-It is used as an integration test for making sure that everything works as expected.
\ No newline at end of file
+It is used as an integration test for making sure that everything works as expected.
diff --git a/packages/reference-app/adonisrc.ts b/packages/reference-app/adonisrc.ts
index 34f0e56..7a13fe5 100644
--- a/packages/reference-app/adonisrc.ts
+++ b/packages/reference-app/adonisrc.ts
@@ -10,7 +10,11 @@ export default defineConfig({
| will be scanned automatically from the "./commands" directory.
|
*/
- commands: [() => import('@adonisjs/core/commands'), () => import('@adonisjs/lucid/commands')],
+ commands: [
+ () => import('@adonisjs/core/commands'),
+ () => import('@adonisjs/lucid/commands'),
+ () => import('@matstack/remix-adonisjs/commands')
+ ],
/*
|--------------------------------------------------------------------------
diff --git a/packages/reference-app/env.d.ts b/packages/reference-app/env.d.ts
index ba4873c..db4f019 100644
--- a/packages/reference-app/env.d.ts
+++ b/packages/reference-app/env.d.ts
@@ -1,2 +1,5 @@
-///
-///
\ No newline at end of file
+import type { AdonisApplicationContext } from '@matstack/remix-adonisjs/types';
+
+declare module 'react-router' {
+ interface AppLoadContext extends AdonisApplicationContext { }
+}
\ No newline at end of file
diff --git a/packages/reference-app/package.json b/packages/reference-app/package.json
index ea2eb7a..3fc4a35 100644
--- a/packages/reference-app/package.json
+++ b/packages/reference-app/package.json
@@ -6,6 +6,7 @@
"license": "MIT",
"scripts": {
"start": "node bin/server.js",
+ "prebuild": "react-router typegen",
"build": "node ace build",
"dev": "node ace serve",
"test": "node ace test",
@@ -34,41 +35,42 @@
"@japa/file-system": "^2.3.0",
"@japa/plugin-adonisjs": "^3.0.1",
"@japa/runner": "^3.1.4",
- "@remix-run/dev": "^2.14.0",
- "@swc/core": "^1.9.2",
+ "@react-router/dev": "^7.0.2",
+ "@react-router/fs-routes": "^7.0.2",
+ "@swc/core": "^1.10.1",
"@types/luxon": "^3.4.2",
- "@types/node": "^22.9.0",
- "@types/react": "^18.3.12",
- "@types/react-dom": "^18.3.1",
+ "@types/node": "^22.10.2",
+ "@types/react": "^19.0.1",
+ "@types/react-dom": "^19.0.2",
"eslint": "^8.57.0",
"hot-hook": "^0.3.1",
- "prettier": "^3.3.3",
+ "prettier": "^3.4.2",
"ts-node": "^10.9.2",
"typescript": "5.6.3",
"vite": "^5.4.11"
},
"dependencies": {
"@adonisjs/auth": "^9.2.4",
- "@adonisjs/core": "^6.14.1",
- "@adonisjs/lucid": "^21.4.0",
+ "@adonisjs/core": "^6.16.0",
+ "@adonisjs/lucid": "^21.5.1",
"@adonisjs/session": "^7.5.0",
"@adonisjs/shield": "^8.1.1",
"@adonisjs/static": "^1.1.1",
"@adonisjs/vite": "^3.0.0",
- "@japa/api-client": "^2.0.3",
+ "@japa/api-client": "^2.0.4",
"@japa/browser-client": "^2.0.3",
"@matstack/remix-adonisjs": "*",
- "@remix-run/css-bundle": "^2.14.0",
- "@remix-run/node": "^2.14.0",
- "@remix-run/react": "^2.14.0",
- "@remix-run/serve": "^2.14.0",
- "@vinejs/vine": "^2.1.0",
+ "@react-router/node": "^7.0.2",
+ "@react-router/serve": "^7.0.2",
+ "@vinejs/vine": "^3.0.0",
"edge.js": "^6.2.0",
"isbot": "^5",
"luxon": "^3.5.0",
"pino-pretty": "^13.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
+ "react-router": "^7.0.2",
+ "react-router-dom": "^7.0.2",
"reflect-metadata": "^0.2.2",
"sqlite3": "^5.1.7"
},
diff --git a/packages/reference-app/react-router.config.ts b/packages/reference-app/react-router.config.ts
new file mode 100644
index 0000000..ae3698d
--- /dev/null
+++ b/packages/reference-app/react-router.config.ts
@@ -0,0 +1,7 @@
+import type { Config } from '@react-router/dev/config'
+export default {
+ ssr: true,
+ appDirectory: 'resources/remix_app',
+ buildDirectory: 'build/remix',
+ serverBuildFile: 'server.js',
+} satisfies Config
diff --git a/packages/reference-app/resources/remix_app/components/error_boundary.tsx b/packages/reference-app/resources/remix_app/components/error_boundary.tsx
index 8c105d9..ad40329 100644
--- a/packages/reference-app/resources/remix_app/components/error_boundary.tsx
+++ b/packages/reference-app/resources/remix_app/components/error_boundary.tsx
@@ -1,4 +1,4 @@
-import { isRouteErrorResponse, useRouteError } from '@remix-run/react'
+import { isRouteErrorResponse, useRouteError } from 'react-router'
export function ErrorBoundaryComponent() {
const error = useRouteError()
diff --git a/packages/reference-app/resources/remix_app/root.tsx b/packages/reference-app/resources/remix_app/root.tsx
index a303782..62da400 100644
--- a/packages/reference-app/resources/remix_app/root.tsx
+++ b/packages/reference-app/resources/remix_app/root.tsx
@@ -1,10 +1,4 @@
-import { cssBundleHref } from '@remix-run/css-bundle'
-import type { LinksFunction } from '@remix-run/node'
-import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react'
-
-export const links: LinksFunction = () => [
- ...(cssBundleHref ? [{ rel: 'stylesheet', href: cssBundleHref }] : []),
-]
+import { Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router'
export default function App() {
return (
@@ -17,11 +11,7 @@ export default function App() {
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css"
/>
-
+
diff --git a/packages/reference-app/resources/remix_app/routes.ts b/packages/reference-app/resources/remix_app/routes.ts
new file mode 100644
index 0000000..83c333f
--- /dev/null
+++ b/packages/reference-app/resources/remix_app/routes.ts
@@ -0,0 +1,4 @@
+import { type RouteConfig } from '@react-router/dev/routes'
+import { flatRoutes } from '@react-router/fs-routes'
+
+export default flatRoutes() satisfies RouteConfig
diff --git a/packages/reference-app/resources/remix_app/routes/_index.tsx b/packages/reference-app/resources/remix_app/routes/_index.tsx
index fa833c1..7fa3e79 100644
--- a/packages/reference-app/resources/remix_app/routes/_index.tsx
+++ b/packages/reference-app/resources/remix_app/routes/_index.tsx
@@ -1,4 +1,4 @@
-import type { MetaFunction } from '@remix-run/node'
+import type { MetaFunction } from 'react-router'
export const meta: MetaFunction = () => {
return [{ title: 'New Remix App' }, { name: 'description', content: 'Welcome to Remix!' }]
diff --git a/packages/reference-app/resources/remix_app/routes/adonis_redirect.tsx b/packages/reference-app/resources/remix_app/routes/adonis_redirect.tsx
index 24b17c8..590c3fe 100644
--- a/packages/reference-app/resources/remix_app/routes/adonis_redirect.tsx
+++ b/packages/reference-app/resources/remix_app/routes/adonis_redirect.tsx
@@ -1,19 +1,15 @@
-import type { LoaderFunctionArgs } from '@remix-run/node'
+import { Route } from "./+types/adonis_redirect.js"
-export const loader = async ({ context }: LoaderFunctionArgs) => {
+export const loader = async ({ context }: Route.LoaderArgs) => {
const { http } = context
http.response.redirect('/login')
return {
- message: 'Hello, world!'
+ message: 'Hello, world!',
}
}
export default function Page() {
- return (
-
- This should not be visible
-
- )
-}
\ No newline at end of file
+ return This should not be visible
+}
diff --git a/packages/reference-app/resources/remix_app/routes/dashboard.tsx b/packages/reference-app/resources/remix_app/routes/dashboard.tsx
index d2127fb..fee6853 100644
--- a/packages/reference-app/resources/remix_app/routes/dashboard.tsx
+++ b/packages/reference-app/resources/remix_app/routes/dashboard.tsx
@@ -1,10 +1,10 @@
-import { LoaderFunctionArgs, json } from '@remix-run/node'
-import { useLoaderData } from '@remix-run/react'
+import { useLoaderData } from 'react-router'
+import { Route } from './+types/dashboard.js'
-export const loader = ({ context }: LoaderFunctionArgs) => {
+export const loader = ({ context }: Route.LoaderArgs) => {
const { http } = context
- return json(http.session.all())
+ return http.session.all()
}
export default function Page() {
const data = useLoaderData()
diff --git a/packages/reference-app/resources/remix_app/routes/echo.tsx b/packages/reference-app/resources/remix_app/routes/echo.tsx
index 391ba84..524e1ae 100644
--- a/packages/reference-app/resources/remix_app/routes/echo.tsx
+++ b/packages/reference-app/resources/remix_app/routes/echo.tsx
@@ -1,12 +1,12 @@
-import { LoaderFunctionArgs, json } from '@remix-run/node'
-import { useLoaderData } from '@remix-run/react'
+import { useLoaderData } from 'react-router'
+import { Route } from './+types/echo.js'
-export const loader = ({ request }: LoaderFunctionArgs) => {
+export const loader = ({ request }: Route.LoaderArgs) => {
const params = new URL(request.url).searchParams
- return json({
+ return {
message: params.get('message'),
- })
+ }
}
export default function Page() {
diff --git a/packages/reference-app/resources/remix_app/routes/feedback.tsx b/packages/reference-app/resources/remix_app/routes/feedback.tsx
index 00c8f25..fd9560d 100644
--- a/packages/reference-app/resources/remix_app/routes/feedback.tsx
+++ b/packages/reference-app/resources/remix_app/routes/feedback.tsx
@@ -1,10 +1,9 @@
-import { json } from '@remix-run/node'
-import { Form, useActionData } from '@remix-run/react'
+import { Form, useActionData } from 'react-router'
export const action = () => {
- return json({
+ return {
message: 'Thank you for your feedback!',
- })
+ }
}
export default function Page() {
diff --git a/packages/reference-app/resources/remix_app/routes/login.tsx b/packages/reference-app/resources/remix_app/routes/login.tsx
index 792675a..f102554 100644
--- a/packages/reference-app/resources/remix_app/routes/login.tsx
+++ b/packages/reference-app/resources/remix_app/routes/login.tsx
@@ -1,7 +1,7 @@
-import { ActionFunctionArgs, redirect } from '@remix-run/node'
-import { Form } from '@remix-run/react'
+import { Form, redirect } from 'react-router'
+import { Route } from './+types/login.js'
-export const action = async ({ context }: ActionFunctionArgs) => {
+export const action = async ({ context }: Route.ActionArgs) => {
const { http } = context
const { password } = http.request.only(['password'])
diff --git a/packages/reference-app/resources/remix_app/routes/posts.tsx b/packages/reference-app/resources/remix_app/routes/posts.tsx
index c19345b..0f65b4f 100644
--- a/packages/reference-app/resources/remix_app/routes/posts.tsx
+++ b/packages/reference-app/resources/remix_app/routes/posts.tsx
@@ -1,15 +1,15 @@
-import { Await, defer, useLoaderData } from '@remix-run/react'
+import { Await, useLoaderData } from 'react-router'
import { Suspense } from 'react'
export const loader = async () => {
// simulate a slow loader
- return defer({
+ return {
lazyPosts: new Promise((resolve) => {
setTimeout(() => {
resolve(['Post 1', 'Post 2'])
}, 100)
}),
- })
+ }
}
export default function Page() {
diff --git a/packages/reference-app/resources/remix_app/routes/profile.tsx b/packages/reference-app/resources/remix_app/routes/profile.tsx
index ffc965d..e52f66f 100644
--- a/packages/reference-app/resources/remix_app/routes/profile.tsx
+++ b/packages/reference-app/resources/remix_app/routes/profile.tsx
@@ -1,11 +1,10 @@
-import { json } from '@remix-run/node'
-import { useLoaderData } from '@remix-run/react'
+import { useLoaderData } from 'react-router'
export const loader = () => {
- return json({
+ return {
userName: 'John Doe',
email: 'john.doe@example.com',
- })
+ }
}
export default function Page() {
diff --git a/packages/reference-app/resources/remix_app/routes/resolve_container.tsx b/packages/reference-app/resources/remix_app/routes/resolve_container.tsx
index 268e78f..9e2bdfc 100644
--- a/packages/reference-app/resources/remix_app/routes/resolve_container.tsx
+++ b/packages/reference-app/resources/remix_app/routes/resolve_container.tsx
@@ -1,11 +1,11 @@
-import { LoaderFunctionArgs, json } from '@remix-run/node'
-import { useLoaderData } from '@remix-run/react'
+import { useLoaderData } from 'react-router'
+import { Route } from './+types/resolve_container.js'
-export const loader = async ({ context }: LoaderFunctionArgs) => {
+export const loader = async ({ context }: Route.LoaderArgs) => {
const app = await context.make('app')
- return json({
+ return {
env: app.getEnvironment(),
- })
+ }
}
export default function Page() {
diff --git a/packages/reference-app/resources/remix_app/routes/webhooks.payment.tsx b/packages/reference-app/resources/remix_app/routes/webhooks.payment.tsx
index a100666..b46e67e 100644
--- a/packages/reference-app/resources/remix_app/routes/webhooks.payment.tsx
+++ b/packages/reference-app/resources/remix_app/routes/webhooks.payment.tsx
@@ -1,10 +1,18 @@
-import { ActionFunctionArgs, json } from '@remix-run/node'
+import { Route } from './+types/webhooks.payment.js'
-export const action = async ({ request, context }: ActionFunctionArgs) => {
+export const action = async ({ request, context }: Route.ActionArgs) => {
const body = await request.text()
const { http } = context
http.logger.info('webhook body', body)
- return json({
+ return Response.json({
status: 'ok',
})
}
+
+
+export function headers({ }: Route.HeadersArgs) {
+ return {
+ "X-Stretchy-Pants": "its for fun",
+ "Cache-Control": "max-age=300, s-maxage=3600",
+ };
+}
\ No newline at end of file
diff --git a/packages/reference-app/tsconfig.json b/packages/reference-app/tsconfig.json
index 8f2c9d3..3e758ce 100644
--- a/packages/reference-app/tsconfig.json
+++ b/packages/reference-app/tsconfig.json
@@ -1,10 +1,17 @@
{
"extends": "@adonisjs/tsconfig/tsconfig.app.json",
+ "include": [
+ "**/*",
+ "**/.server/**/*",
+ "**/.client/**/*",
+ ".react-router/types/**/*"
+ ],
"compilerOptions": {
- "rootDir": "./",
+ "rootDirs": ["./", "./.react-router/types"],
"outDir": "./build",
"moduleResolution": "bundler",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "types": ["@react-router/node", "vite/client"],
"module": "ESNext",
"jsx": "preserve",
"skipLibCheck": true,
diff --git a/packages/reference-app/vite.config.ts b/packages/reference-app/vite.config.ts
index 563ba6f..6698aea 100644
--- a/packages/reference-app/vite.config.ts
+++ b/packages/reference-app/vite.config.ts
@@ -1,14 +1,8 @@
-import { vitePlugin as remix } from '@remix-run/dev'
+import { reactRouter } from '@react-router/dev/vite'
import { defineConfig } from 'vite'
export default defineConfig(({ isSsrBuild }) => ({
- plugins: [
- remix({
- appDirectory: 'resources/remix_app',
- buildDirectory: 'build/remix',
- serverBuildFile: 'server.js',
- }),
- ],
+ plugins: [reactRouter()],
optimizeDeps: {
esbuildOptions: isSsrBuild
? {
diff --git a/tsconfig.build.json b/tsconfig.build.json
index b420878..2bc63c7 100644
--- a/tsconfig.build.json
+++ b/tsconfig.build.json
@@ -3,5 +3,8 @@
// list, TS won't automatically include all sources below root (the default).
"files": [],
// Building this project will build all of the following:
- "references": [{ "path": "packages/adapter" }, { "path": "packages/reference-app" }]
-}
\ No newline at end of file
+ "references": [
+ { "path": "packages/adapter" },
+ { "path": "packages/reference-app" }
+ ]
+}
diff --git a/tsconfig.json b/tsconfig.json
index 60df488..955248b 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -2,6 +2,6 @@
"extends": "@adonisjs/tsconfig/tsconfig.package.json",
"compilerOptions": {
"incremental": true,
- "composite": true,
+ "composite": true
}
-}
\ No newline at end of file
+}