Skip to content

Commit

Permalink
Update to React Router v7 (#415)
Browse files Browse the repository at this point in the history
A lot of issues with this, mainly:
Some types are not exported anymore
The tests fail a lot due to installGlobals missing
The json method has been removed and that kind of changes the dynamic of
the whole test suites, and a lot of utils

---------

Co-authored-by: Sergio Xalambrí <hello@sergiodxa.com>
  • Loading branch information
AlemTuzlak and sergiodxa authored Dec 4, 2024
1 parent e4d599d commit 3930d8a
Show file tree
Hide file tree
Showing 71 changed files with 722 additions and 1,158 deletions.
26 changes: 11 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
name: CI

on:
pull_request:
push:
branches:
- main
on: [push]

jobs:
build:
Expand All @@ -16,23 +12,23 @@ jobs:
- run: bun install --frozen-lockfile
- run: bun run build

exports:
name: Verify Exports
typecheck:
name: Typechecker
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run test:exports
- run: bun run typecheck

typecheck:
name: Typechecker
quality:
name: Code Quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run typecheck
- run: bun run quality

test:
name: Tests
Expand All @@ -41,13 +37,13 @@ jobs:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run test
- run: bun test

quality:
name: Code Quality
exports:
name: Verify Exports
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run check
- run: bun run exports
13 changes: 0 additions & 13 deletions .npmignore

This file was deleted.

4 changes: 2 additions & 2 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
"formulahendry.auto-close-tag",
"formulahendry.auto-rename-tag",
"github.vscode-github-actions",
"vitest.explorer",
"vscode-icons-team.vscode-icons",
"waderyan.gitblame"
"waderyan.gitblame",
"oven.bun-vscode"
]
}
31 changes: 15 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ npm install remix-utils

Additional optional dependencies may be needed, all optional dependencies are:

- `@remix-run/react` (also `@remix-run/router` but you should be using the React one)
- `@remix-run/node` or `@remix-run/cloudflare` or `@remix-run/deno` (actually it's `@remix-run/server-runtime` but you should use one of the others)
- `react-router`
- `crypto-js`
- `is-ip`
- `intl-parse-accept-language`
Expand Down Expand Up @@ -427,7 +426,7 @@ First create a new CSRF instance.
```ts
// app/utils/csrf.server.ts
import { CSRF } from "remix-utils/csrf/server";
import { createCookie } from "@remix-run/node"; // or cloudflare/deno
import { createCookie } from "react-router"; // or cloudflare/deno

export const cookie = createCookie("csrf", {
path: "/",
Expand Down Expand Up @@ -494,7 +493,7 @@ Render it in your `root` component and wrap the `Outlet` with it.
When you create a form in some route, you can use the `AuthenticityTokenInput` component to add the authenticity token to the form.

```tsx
import { Form } from "@remix-run/react";
import { Form } from "react-router";
import { AuthenticityTokenInput } from "remix-utils/csrf/react";

export default function Component() {
Expand All @@ -520,7 +519,7 @@ You should only customize the name if you also changed it on `createAuthenticity
If you need to use `useFetcher` (or `useSubmit`) instead of `Form` you can also get the authenticity token with the `useAuthenticityToken` hook.

```tsx
import { useFetcher } from "@remix-run/react";
import { useFetcher } from "react-router";
import { useAuthenticityToken } from "remix-utils/csrf/react";

export function useMarkAsRead() {
Expand Down Expand Up @@ -593,7 +592,7 @@ import { ExistingSearchParams } from "remix-utils/existing-search-params";
```

> **Note**
> This depends on `react` and `@remix-run/react`
> This depends on `react` and `react-router`
When you submit a GET form, the browser will replace all of the search params in the URL with your form data. This component copies existing search params into hidden inputs so they will not be overwritten.

Expand Down Expand Up @@ -632,7 +631,7 @@ By excluding the `page` param, from the search form, the user will return to the
### External Scripts

> **Note**
> This depends on `react`, `@remix-run/react`, and a Remix server runtime.
> This depends on `react`, and `react-router`.
If you need to load different external scripts on certain routes, you can use the `ExternalScripts` component together with the `ExternalScriptsFunction` and `ScriptDescriptor` types.

Expand Down Expand Up @@ -770,7 +769,7 @@ return (
### useGlobalNavigationState

> **Note**
> This depends on `react`, and `@remix-run/react`.
> This depends on `react`, and `react-router`.
This hook allows you to read the value of `transition.state`, every `fetcher.state` in the app, and `revalidator.state`.

Expand Down Expand Up @@ -800,7 +799,7 @@ The return value of `useGlobalNavigationState` can be `"idle"`, `"loading"` or `
### useGlobalPendingState

> **Note**
> This depends on `react`, and `@remix-run/react`.
> This depends on `react`, and `react-router`.
This hook lets you know if the global navigation, if one of any active fetchers is either loading or submitting, or if the revalidator is running.

Expand All @@ -824,7 +823,7 @@ The return value of `useGlobalPendingState` is either `"idle"` or `"pending"`.
### useGlobalSubmittingState

> **Note**
> This depends on `react`, and `@remix-run/react`.
> This depends on `react`, and `react-router`.
This hook lets you know if the global transition or if one of any active fetchers is submitting.

Expand All @@ -844,7 +843,7 @@ The return value of `useGlobalSubmittingState` is either `"idle"` or `"submittin
### useGlobalLoadingState

> **Note**
> This depends on `react`, and `@remix-run/react`.
> This depends on `react`, and `react-router`.
This hook lets you know if the global transition, if one of any active fetchers is loading, or if the revalidator is running

Expand Down Expand Up @@ -922,15 +921,15 @@ The return type of `useLocales` is ready to be used with the Intl API.
### useShouldHydrate

> **Note**
> This depends on `@remix-run/react` and `react`.
> This depends on `react-router` and `react`.
If you are building a Remix application where most routes are static, and you want to avoid loading client-side JS, you can use this hook, plus some conventions, to detect if one or more active routes needs JS and only render the Scripts component in that case.

In your document component, you can call this hook to dynamically render the Scripts component if needed.

```tsx
import type { ReactNode } from "react";
import { Links, LiveReload, Meta, Scripts } from "@remix-run/react";
import { Links, LiveReload, Meta, Scripts } from "react-router";
import { useShouldHydrate } from "remix-utils/use-should-hydrate";

interface DocumentProps {
Expand Down Expand Up @@ -1205,7 +1204,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
Cookie objects in Remix allows any type, the typed cookies from Remix Utils lets you use Zod to parse the cookie values and ensure they conform to a schema.

```ts
import { createCookie } from "@remix-run/node";
import { createCookie } from "react-router";
import { createTypedCookie } from "remix-utils/typed-cookie";
import { z } from "zod";

Expand Down Expand Up @@ -1300,7 +1299,7 @@ await typedCookie.serialize("some fake url to pass schema validation", {
Session objects in Remix allows any type, the typed sessions from Remix Utils lets you use Zod to parse the session data and ensure they conform to a schema.

```ts
import { createCookieSessionStorage } from "@remix-run/node";
import { createCookieSessionStorage } from "react-router";
import { createTypedSessionStorage } from "remix-utils/typed-session";
import { z } from "zod";

Expand Down Expand Up @@ -1775,7 +1774,7 @@ Now you can see in your DevTools that when the user hovers an anchor it will pre
### Debounced Fetcher and Submit

> **Note**
> This depends on `react`, and `@remix-run/react`.
> This depends on `react`, and `react-router`.
`useDebounceFetcher` and `useDebounceSubmit` are wrappers of `useFetcher` and `useSubmit` that add debounce support.

Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 2 additions & 0 deletions bunfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[test]
preload = "./src/test/setup.ts"
71 changes: 25 additions & 46 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@
"version": "7.7.0",
"license": "MIT",
"engines": {
"node": ">=18.0.0"
"node": ">=20.0.0"
},
"type": "module",
"funding": [
"https://github.com/sponsors/sergiodxa"
],
"funding": ["https://github.com/sponsors/sergiodxa"],
"exports": {
"./package.json": "./package.json",
"./promise": "./build/common/promise.js",
Expand Down Expand Up @@ -51,16 +49,11 @@
},
"sideEffects": false,
"scripts": {
"prepare": "npm run build",
"build": "tsc --project tsconfig.json --outDir ./build",
"format": "biome format --write .",
"typecheck": "tsc --project tsconfig.json --noEmit",
"check": "biome check .",
"lint": "biome lint .",
"test": "vitest --run",
"test:watch": "vitest",
"test:coverage": "vitest --coverage",
"test:exports": "bun scripts/check-pkg-exports.ts"
"build": "tsc",
"typecheck": "tsc --noEmit",
"quality": "biome check .",
"quality:fix": "biome check . --write --unsafe",
"exports": "bun run ./scripts/exports.ts"
},
"author": {
"name": "Sergio Xalambrí",
Expand Down Expand Up @@ -95,27 +88,15 @@
"named action"
],
"peerDependencies": {
"@remix-run/cloudflare": "^2.0.0",
"@remix-run/node": "^2.0.0",
"@remix-run/react": "^2.0.0",
"@remix-run/router": "^1.7.2",
"react-router": "^7.0.0",
"crypto-js": "^4.1.1",
"intl-parse-accept-language": "^1.0.0",
"is-ip": "^5.0.1",
"react": "^18.0.0",
"zod": "^3.22.4"
},
"peerDependenciesMeta": {
"@remix-run/cloudflare": {
"optional": true
},
"@remix-run/node": {
"optional": true
},
"@remix-run/react": {
"optional": true
},
"@remix-run/router": {
"react-router": {
"optional": true
},
"crypto-js": {
Expand All @@ -135,35 +116,33 @@
}
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.15.0",
"@arethetypeswrong/cli": "^0.17.0",
"@biomejs/biome": "^1.7.2",
"@remix-run/node": "^2.0.0",
"@remix-run/react": "^2.0.0",
"@remix-run/router": "^1.7.2",
"@remix-run/testing": "^2.0.0",
"@happy-dom/global-registrator": "^15.11.7",
"@testing-library/jest-dom": "^6.1.3",
"@testing-library/react": "^15.0.2",
"@types/bun": "^1.1.1",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@total-typescript/tsconfig": "^1.0.4",
"@types/bun": "^1.1.14",
"@types/crypto-js": "^4.1.2",
"@types/react": "^18.2.78",
"@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-v8": "^1.5.0",
"@vitejs/plugin-react": "^4.3.4",
"crypto-js": "^4.1.1",
"happy-dom": "^14.7.1",
"intl-parse-accept-language": "^1.0.0",
"is-ip": "5.0.1",
"msw": "^2.2.13",
"msw": "^2.6.6",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-router": "^7.0.2",
"ts-node": "^10.9.1",
"typedoc": "^0.25.13",
"typedoc-plugin-mdn-links": "^3.1.23",
"typescript": "^5.2.2",
"vite": "^5.2.8",
"vitest": "^1.4.0",
"typedoc": "^0.27.2",
"typedoc-plugin-mdn-links": "^4.0.3",
"typescript": "^5.7.2",
"vite": "^6.0.2",
"zod": "^3.22.4"
},
"dependencies": {
"type-fest": "^4.18.1"
}
"type-fest": "^4.30.0"
},
"files": ["build", "package.json", "README.md"]
}
19 changes: 13 additions & 6 deletions src/client/cache-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,19 @@ export async function cacheAssets({
function getFilePaths() {
try {
return unique([
...Object.values(window.__remixManifest.routes).flatMap((route) => {
return [route.module, ...(route.imports ?? [])];
}),
window.__remixManifest.url,
window.__remixManifest.entry.module,
...window.__remixManifest.entry.imports,
// biome-ignore lint/suspicious/noExplicitAny: global window type is missing proper typing
...Object.values((window as any).__reactRouterManifest.routes).flatMap(
// biome-ignore lint/suspicious/noExplicitAny: global window type is missing proper typing
(route: any) => {
return [route.module, ...(route.imports ?? [])];
},
),
// biome-ignore lint/suspicious/noExplicitAny: global window type is missing proper typing
(window as any).__reactRouterManifest.url,
// biome-ignore lint/suspicious/noExplicitAny: global window type is missing proper typing
(window as any).__reactRouterManifest.entry.module,
// biome-ignore lint/suspicious/noExplicitAny: global window type is missing proper typing
...(window as any).__reactRouterManifest.entry.imports,
]);
} catch {
throw new Error("Failed to get file paths from Remix manifest");
Expand Down
Loading

0 comments on commit 3930d8a

Please sign in to comment.