Skip to content

Commit

Permalink
Migrate to React Router 7 (#67)
Browse files Browse the repository at this point in the history
  • Loading branch information
jarle authored Jan 15, 2025
1 parent 11e9c3b commit 4c24d96
Show file tree
Hide file tree
Showing 50 changed files with 342 additions and 277 deletions.
16 changes: 8 additions & 8 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -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'
- "minor"
- "patch"
2 changes: 1 addition & 1 deletion .github/lock.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions .github/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: >
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
types: [opened, synchronize, reopened]
push:
schedule:
- cron: '0 16 * * *'
- cron: "0 16 * * *"

jobs:
linux:
Expand Down Expand Up @@ -44,4 +44,4 @@ jobs:
- name: Build
run: npm run build
- name: Run tests
run: npm test
run: npm test
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@ public/assets/
*/.vitepress/cache

package-lock.json
yarn.lock
yarn.lock

.react-router/
11 changes: 5 additions & 6 deletions examples/with-tailwind-and-shadcn/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand All @@ -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",
Expand All @@ -104,4 +103,4 @@
"vite.config.ts.timestamp*"
]
}
}
}
24 changes: 10 additions & 14 deletions examples/with-tailwind-and-shadcn/resources/remix_app/root.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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
Expand All @@ -49,7 +43,9 @@ export default function Page({ children }: { children: React.ReactNode }) {
{children}
<Form method="post">
<input type="hidden" name="intent" value="toggleColorScheme" />
<button className='underline' type="submit">{prefersDarkMode ? 'Light' : 'Dark'} mode</button>
<button className="underline" type="submit">
{prefersDarkMode ? 'Light' : 'Dark'} mode
</button>
</Form>
<ScrollRestoration />
<Outlet />
Expand Down
Original file line number Diff line number Diff line change
@@ -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 = () => {
Expand All @@ -15,33 +15,39 @@ export default function Index() {
const { message } = useLoaderData<typeof loader>()

return (
<div className='flex flex-col gap-7'>
<div className='flex flex-col gap-3'>
<h1 className='text-4xl font-black'>Welcome to Remix</h1>
<p className='font-thin text-lg'>{message}</p>
<div className="flex flex-col gap-7">
<div className="flex flex-col gap-3">
<h1 className="text-4xl font-black">Welcome to Remix</h1>
<p className="font-thin text-lg">{message}</p>
</div>
<ul className='list-disc'>
<ul className="list-disc">
<li>
<a className='hover:font-semibold'
<a
className="hover:font-semibold"
target="_blank"
href="https://remix.run/tutorials/blog"
rel="noreferrer">
rel="noreferrer"
>
15m Quickstart Blog Tutorial
</a>
</li>
<li>
<a className='hover:font-semibold'
<a
className="hover:font-semibold"
target="_blank"
href="https://remix.run/tutorials/blog"
rel="noreferrer">
rel="noreferrer"
>
Deep Dive Jokes App Tutorial
</a>
</li>
<li>
<a className='hover:font-semibold'
<a
className="hover:font-semibold"
target="_blank"
href="https://remix.run/tutorials/blog"
rel="noreferrer">
rel="noreferrer"
>
Remix Docs
</a>
</li>
Expand Down
4 changes: 2 additions & 2 deletions examples/with-tailwind-and-shadcn/vite.config.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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',
Expand Down
34 changes: 16 additions & 18 deletions packages/adapter/commands/remix_route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(', '),
},
})
}
Expand Down
14 changes: 9 additions & 5 deletions packages/adapter/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => ({
Expand Down
5 changes: 5 additions & 0 deletions packages/adapter/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { AdonisApplicationContext } from './src/types/main.js'

declare module 'react-router' {
interface AppLoadContext extends AdonisApplicationContext {}
}
9 changes: 3 additions & 6 deletions packages/adapter/package.json
Original file line number Diff line number Diff line change
@@ -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"
},
Expand Down Expand Up @@ -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": {},
Expand Down
2 changes: 1 addition & 1 deletion packages/adapter/providers/remix_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
6 changes: 3 additions & 3 deletions packages/adapter/src/hooks/build_hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<AssemblerHookHandler>[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'])
Expand Down
8 changes: 5 additions & 3 deletions packages/adapter/src/remix_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand All @@ -18,7 +20,7 @@ export type HandlerContext = {
container: Container<ContainerBindings>
}

export type LoaderContext = {
export type AdonisApplicationContext = {
http: HttpContext
make: Container<ContainerBindings>['make']
}
Expand Down
Loading

0 comments on commit 4c24d96

Please sign in to comment.