Skip to content

Commit

Permalink
Merge pull request #169 from seasonedcc/update-remix-to-rr
Browse files Browse the repository at this point in the history
  • Loading branch information
gustavoguichard authored Dec 3, 2024
2 parents dd54c43 + 5bf96eb commit 4857c80
Show file tree
Hide file tree
Showing 25 changed files with 4,224 additions and 8,052 deletions.
2 changes: 2 additions & 0 deletions examples/react-router/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules

.react-router/
/.cache
/build
.env

6 changes: 3 additions & 3 deletions examples/remix/README.md → examples/react-router/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Welcome to Remix + Vite!
# Welcome to React Router!

📖 See the [Remix docs](https://remix.run/docs) and the [Remix Vite docs](https://remix.run/docs/en/main/future/vite) for details on supported features.
📖 See the [React-router docs](https://reactrouter.com/home) for details on supported features.

## Development

Expand Down Expand Up @@ -28,7 +28,7 @@ Now you'll need to pick a host to deploy it to.

### DIY

If you're familiar with deploying Node applications, the built-in Remix app server is production-ready.
If you're familiar with deploying Node applications, the built-in React Router app server is production-ready.

Make sure to deploy the output of `npm run build`

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { z } from 'zod'
import { applySchema } from 'composable-functions'
import { createCookie } from '@remix-run/node'
import { createCookie } from 'react-router';

const cookie = createCookie('gpd', {
maxAge: 20, // seconds
Expand Down
File renamed without changes.
31 changes: 31 additions & 0 deletions examples/react-router/app/lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Cookie } from 'react-router'
import { data } from 'react-router'
import type { Result } from 'composable-functions'
import { catchFailure, serialize, fromSuccess } from 'composable-functions'

/**
* Given a Cookie and a Request it returns the stored cookie's value as an object, in case of failure it returns an empty object.
*/
const safeReadCookie = catchFailure(
async (request: Request, cookie: Cookie) => {
const cookieHeader = request.headers.get('Cookie')
const cookieObj = (await cookie.parse(cookieHeader)) as Record<
string,
unknown
>
if (!cookieObj) throw new Error('Cookie not found')

return cookieObj
},
() => ({}),
)

const ctxFromCookie = fromSuccess(safeReadCookie)

const actionResponse = <X>(result: Result<X>, opts?: RequestInit): Result<X> =>
data(serialize(result), {
status: result.success ? 200 : 422,
...opts,
}) as unknown as Result<X>

export { ctxFromCookie, actionResponse }
32 changes: 13 additions & 19 deletions examples/remix/app/root.tsx → examples/react-router/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,18 @@ import {
Outlet,
Scripts,
ScrollRestoration,
useActionData,
useLoaderData,
useRouteError,
} from '@remix-run/react'
import {
ActionFunctionArgs,
LinksFunction,
LoaderFunctionArgs,
} from '@remix-run/node'
} from 'react-router'

import styles from './tailwind.css?url'

import { actionResponse, ctxFromCookie, loaderResponseOrThrow } from '~/lib'
import { actionResponse, ctxFromCookie } from '~/lib'
import { agreeToGPD, cookie, getGPDInfo } from '~/business/gpd'
import { inputFromForm } from 'composable-functions'
import { Route } from './+types/root'

export const links: LinksFunction = () => [{ rel: 'stylesheet', href: styles }]
export const links: Route.LinksFunction = () => [
{ rel: 'stylesheet', href: styles },
]

export function Layout({ children }: { children: React.ReactNode }) {
return (
Expand All @@ -41,12 +36,13 @@ export function Layout({ children }: { children: React.ReactNode }) {
)
}

export const loader = async ({ request }: LoaderFunctionArgs) => {
export const loader = async ({ request }: Route.LoaderArgs) => {
const result = await getGPDInfo(null, await ctxFromCookie(request, cookie))
return loaderResponseOrThrow(result)
if (!result.success) throw new Error('Internal server error')
return result.data
}

export const action = async ({ request }: ActionFunctionArgs) => {
export const action = async ({ request }: Route.ActionArgs) => {
const result = await agreeToGPD(await inputFromForm(request))
if (!result.success || result.data.agreed === false) {
return actionResponse(result)
Expand All @@ -56,9 +52,8 @@ export const action = async ({ request }: ActionFunctionArgs) => {
})
}

export default function App() {
const { agreed } = useLoaderData<typeof loader>()
const actionData = useActionData<typeof action>()
export default function App({ loaderData, actionData }: Route.ComponentProps) {
const { agreed } = loaderData
const disagreed = actionData?.success && actionData.data.agreed === false
return (
<main className="isolate flex w-full grow flex-col items-center justify-center">
Expand Down Expand Up @@ -96,8 +91,7 @@ export default function App() {
)
}

export function ErrorBoundary() {
const error = useRouteError()
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
console.error(error)
return (
<div>
Expand Down
7 changes: 7 additions & 0 deletions examples/react-router/app/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { index, route, type RouteConfig } from '@react-router/dev/routes'

export default [
index('./routes/home.tsx'),
route('color/:id', './routes/color.tsx'),
route('user/:id', './routes/user.tsx'),
] satisfies RouteConfig
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
import { ActionFunctionArgs, LoaderFunctionArgs } from '@remix-run/node'
import { Form, Link, useActionData, useLoaderData } from '@remix-run/react'
import { Form, Link } from 'react-router'
import { applySchema, inputFromForm } from 'composable-functions'
import tinycolor from 'tinycolor2'
import { getColor, mutateColor } from '~/business/colors'
import { actionResponse, loaderResponseOrThrow } from '~/lib'
import { actionResponse } from '~/lib'
import { z } from 'zod'
import { Route } from '../routes/+types/color'

export const loader = async ({ params }: LoaderFunctionArgs) => {
export const loader = async ({ params }: Route.LoaderArgs) => {
const result = await applySchema(z.object({ id: z.string() }))(getColor)(
params,
)
return loaderResponseOrThrow(result)
if (!result.success) throw new Error('Could not load data')
return result.data
}

export const action = async ({ request }: ActionFunctionArgs) => {
export const action = async ({ request }: Route.ActionArgs) => {
const input = await inputFromForm(request)
const result = await mutateColor(input)
return actionResponse(result)
}

export default function Index() {
const { data } = useLoaderData<typeof loader>()
const actionData = useActionData<typeof action>()
export default function Index({
loaderData,
actionData,
}: Route.ComponentProps) {
const { data } = loaderData
const color = actionData?.success ? actionData.data.color : data.color
return (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { LoaderFunctionArgs } from '@remix-run/node'
import { Link, useLoaderData, useLocation } from '@remix-run/react'
import { Link, useLocation } from 'react-router'
import { inputFromUrl, collect, map, applySchema } from 'composable-functions'
import { listColors } from '~/business/colors'
import { listUsers } from '~/business/users'
import { loaderResponseOrThrow } from '~/lib'
import { z } from 'zod'
import { Route } from '../routes/+types/home'

const getData = applySchema(
// We are applying a schema for runtime safety
Expand All @@ -19,14 +18,16 @@ const getData = applySchema(
users: listUsers,
}),
)
export const loader = async ({ request }: LoaderFunctionArgs) => {
export const loader = async ({ request }: Route.LoaderArgs) => {
// inputFromUrl gets the queryString out of the request and turns it into an object
const result = await getData(inputFromUrl(request))
return loaderResponseOrThrow(result)
if (!result.success) throw new Error('Could not load data')
return result.data
}

export default function Index() {
const { users, colors } = useLoaderData<typeof loader>()
export default function Index({
loaderData: { users, colors },
}: Route.ComponentProps) {
const location = useLocation()
const qs = new URLSearchParams(location.search)
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
import { LoaderFunctionArgs } from '@remix-run/node'
import { Link, useLoaderData } from '@remix-run/react'
import { Link } from 'react-router'
import { applySchema, pipe } from 'composable-functions'
import { formatUser, getUser } from '~/business/users'
import { loaderResponseOrThrow } from '~/lib'
import { z } from 'zod'
import { Route } from '../routes/+types/user'

const getData = applySchema(
// We are adding runtime validation because the Remix's `Params` object is not strongly typed
// We are adding runtime validation to the React-Router's `Params` object
z.object({ id: z.string() }),
)(
// The output of getUser will be the input of formatUser
// We could also be using `map` instead of `pipe` here
pipe(getUser, formatUser),
)

export const loader = async ({ params }: LoaderFunctionArgs) => {
export const loader = async ({ params }: Route.LoaderArgs) => {
const result = await getData(params)
return loaderResponseOrThrow(result)
if (!result.success) throw new Error('Could not load data')
return result.data
}

export default function Index() {
const { user } = useLoaderData<typeof loader>()
export default function Index({ loaderData: { user } }: Route.ComponentProps) {
return (
<>
<a
Expand Down
File renamed without changes.
19 changes: 9 additions & 10 deletions examples/remix/package.json → examples/react-router/package.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
{
"name": "remix",
"name": "react-router-example",
"private": true,
"sideEffects": false,
"type": "module",
"scripts": {
"build": "remix vite:build",
"dev": "remix vite:dev",
"build": "react-router build",
"dev": "react-router dev",
"lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
"start": "remix-serve ./build/server/index.js",
"typecheck": "tsc"
"start": "react-router-serve ./build/server/index.js",
"typecheck": "react-router typegen && tsc"
},
"dependencies": {
"@remix-run/node": "^2.10.2",
"@remix-run/react": "^2.10.2",
"@remix-run/serve": "^2.10.2",
"@react-router/node": "^7.0.1",
"@react-router/serve": "^7.0.1",
"@types/tinycolor2": "^1.4.6",
"composable-functions": "file:../../npm",
"isbot": "^5.1.13",
"make-service": "^3.0.0",
"postcss": "^8.4.39",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router": "^7.0.1",
"tinycolor2": "^1.6.0",
"zod": "^3.23.8"
},
"devDependencies": {
"@remix-run/dev": "^2.10.2",
"@remix-run/eslint-config": "^2.10.2",
"@react-router/dev": "^7.0.1",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.16.0",
Expand Down
Loading

0 comments on commit 4857c80

Please sign in to comment.