From efa99d8c8a5bf3b86de35d2dca95dcc67b1c47be Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Mon, 28 Aug 2023 12:20:26 -0400 Subject: [PATCH 1/9] fix(remix-dev): don't allow unknown fields in TS future config (#7261) --- packages/remix-dev/config.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/remix-dev/config.ts b/packages/remix-dev/config.ts index 3294a34db38..e5598999a59 100644 --- a/packages/remix-dev/config.ts +++ b/packages/remix-dev/config.ts @@ -173,7 +173,9 @@ export interface AppConfig { | string[] | (() => Promise | string | string[]); - future?: Partial; + future?: Partial & { + [propName: string]: never; + }; } /** From fd31ce92d7bbf891a11a00f076211c9366b99405 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Mon, 28 Aug 2023 12:30:47 -0400 Subject: [PATCH 2/9] Update session docs for when methods are called --- docs/utils/sessions.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/utils/sessions.md b/docs/utils/sessions.md index ce06397db8e..ec38243e26b 100644 --- a/docs/utils/sessions.md +++ b/docs/utils/sessions.md @@ -210,6 +210,11 @@ console.log(isSession(session)); Remix makes it easy to store sessions in your own database if needed. The `createSessionStorage()` API requires a `cookie` (or options for creating a cookie, see [cookies][cookies]) and a set of create, read, update, and delete (CRUD) methods for managing the session data. The cookie is used to persist the session ID. +- `createData` will be called from `commitSession` on the initial session creation when no session ID exists in the cookie +- `readData` will be called from `getSession` when a session ID exists in the cookie +- `updateData` will be called from `commitSession` when a session ID already exists in the cookie +- `deleteData` is called from `destorySession` + The following example shows how you could do this using a generic database client: ```ts From 3f292e0ccfcbcab5f26d77760253ce7384643991 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Mon, 28 Aug 2023 12:43:13 -0400 Subject: [PATCH 3/9] Switch release branches to use new workflows (#7259) --- .github/workflows/release-test.yml | 19 -- .github/workflows/reusable-test.yml | 195 ------------------ .github/workflows/shared-build.yml | 3 - .github/workflows/shared-test-integration.yml | 3 - .github/workflows/shared-test-unit.yml | 3 - .github/workflows/test-full.yml | 16 +- .github/workflows/test-pr-ubuntu.yml | 4 + .github/workflows/test-pr-windows-macos.yml | 4 + 8 files changed, 18 insertions(+), 229 deletions(-) delete mode 100644 .github/workflows/release-test.yml delete mode 100644 .github/workflows/reusable-test.yml diff --git a/.github/workflows/release-test.yml b/.github/workflows/release-test.yml deleted file mode 100644 index 16a242ce61c..00000000000 --- a/.github/workflows/release-test.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: ๐Ÿงช Test (release) - -on: - push: - branches: - - release-* - tags: - - "v0.0.0-nightly-*" - paths-ignore: - - "docs/**" - - "scripts/**" - - "**/README.md" - -jobs: - test: - if: github.repository == 'remix-run/remix' - uses: ./.github/workflows/reusable-test.yml - with: - node_version: "[18, 20]" diff --git a/.github/workflows/reusable-test.yml b/.github/workflows/reusable-test.yml deleted file mode 100644 index 2b51c50ad5d..00000000000 --- a/.github/workflows/reusable-test.yml +++ /dev/null @@ -1,195 +0,0 @@ -name: ๐Ÿงช Test (shared) - -on: - workflow_call: - inputs: - node_version: - required: true - # this is limited to string | boolean | number (https://github.uint.cloudmunity/t/can-action-inputs-be-arrays/16457) - # but we want to pass an array (node_version: "[18, 20]"), - # so we'll need to manually stringify it for now - type: string - -env: - CI: true - CYPRESS_INSTALL_BINARY: 0 - -jobs: - build: - name: โš™๏ธ Build - runs-on: ubuntu-latest - steps: - - name: ๐Ÿ›‘ Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - - - name: โฌ‡๏ธ Checkout repo - uses: actions/checkout@v3 - - - name: โŽ” Setup node - uses: actions/setup-node@v3 - with: - node-version-file: ".nvmrc" - cache: "yarn" - - - name: Disable GitHub Actions Annotations - run: | - echo "::remove-matcher owner=tsc::" - echo "::remove-matcher owner=eslint-compact::" - echo "::remove-matcher owner=eslint-stylish::" - - - name: ๐Ÿ“ฅ Install deps - run: yarn --frozen-lockfile - - - name: ๐Ÿ— Build - run: yarn build - - test: - name: "๐Ÿงช Test: (OS: ${{ matrix.os }} Node: ${{ matrix.node }})" - strategy: - fail-fast: false - matrix: - os: - - ubuntu-latest - # - macos-latest - - windows-latest - node: ${{ fromJSON(inputs.node_version) }} - runs-on: ${{ matrix.os }} - steps: - - name: ๐Ÿ›‘ Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - - - name: โฌ‡๏ธ Checkout repo - uses: actions/checkout@v3 - - - name: โŽ” Setup node ${{ matrix.node }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node }} - cache: "yarn" - - - name: Disable GitHub Actions Annotations - run: | - echo "::remove-matcher owner=tsc::" - echo "::remove-matcher owner=eslint-compact::" - echo "::remove-matcher owner=eslint-stylish::" - - - name: ๐Ÿ“ฅ Install deps - run: yarn --frozen-lockfile - - # It's faster to use the built `cli.js` in tests if its available and up-to-date - - name: ๐Ÿ— Build - run: yarn build - - - name: ๐Ÿงช Run Primary Tests - run: "yarn test:primary" - - ubuntu-integration: - name: '๐Ÿ‘€ Integration Test: (OS: "ubuntu-latest" Node: "${{ matrix.node }}" Browser: "${{ matrix.browser }}")' - strategy: - fail-fast: false - matrix: - node: ${{ fromJSON(inputs.node_version) }} - browser: ["chromium", "firefox"] - - runs-on: ubuntu-latest - steps: - - name: ๐Ÿ›‘ Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - - - name: โฌ‡๏ธ Checkout repo - uses: actions/checkout@v3 - - - name: โŽ” Setup node ${{ matrix.node }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node }} - cache: "yarn" - - - name: Disable GitHub Actions Annotations - run: | - echo "::remove-matcher owner=tsc::" - echo "::remove-matcher owner=eslint-compact::" - echo "::remove-matcher owner=eslint-stylish::" - - - name: ๐Ÿ“ฅ Install deps - run: yarn --frozen-lockfile - - - name: ๐Ÿ“ฅ Install Playwright - run: npx playwright install --with-deps - - - name: ๐Ÿ‘€ Run Integration Tests ${{ matrix.browser }} - run: "yarn test:integration --project=${{ matrix.browser }}" - - macos-integration: - name: '๐Ÿ‘€ Integration Test: (OS: "macos-latest" Node: "${{ matrix.node }}" Browser: "${{ matrix.browser }}")' - strategy: - fail-fast: false - matrix: - node: ${{ fromJSON(inputs.node_version) }} - browser: ["webkit"] - - runs-on: macos-latest - steps: - - name: ๐Ÿ›‘ Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - - - name: โฌ‡๏ธ Checkout repo - uses: actions/checkout@v3 - - - name: โŽ” Setup node ${{ matrix.node }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node }} - cache: "yarn" - - - name: Disable GitHub Actions Annotations - run: | - echo "::remove-matcher owner=tsc::" - echo "::remove-matcher owner=eslint-compact::" - echo "::remove-matcher owner=eslint-stylish::" - - - name: ๐Ÿ“ฅ Install deps - run: yarn --frozen-lockfile - - - name: ๐Ÿ“ฅ Install Playwright - run: npx playwright install --with-deps - - - name: ๐Ÿ‘€ Run Integration Tests ${{ matrix.browser }} - run: "yarn test:integration --project=${{ matrix.browser }}" - - windows-integration: - name: '๐Ÿ‘€ Integration Test: (OS: "windows-latest" Node: "${{ matrix.node }}" Browser: "${{ matrix.browser }}")' - strategy: - fail-fast: false - matrix: - node: ${{ fromJSON(inputs.node_version) }} - browser: ["msedge"] - - runs-on: windows-latest - steps: - - name: ๐Ÿ›‘ Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - - - name: โฌ‡๏ธ Checkout repo - uses: actions/checkout@v3 - - - name: โŽ” Setup node ${{ matrix.node }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node }} - cache: "yarn" - - - name: Disable GitHub Actions Annotations - run: | - echo "::remove-matcher owner=tsc::" - echo "::remove-matcher owner=eslint-compact::" - echo "::remove-matcher owner=eslint-stylish::" - - - name: ๐Ÿ“ฅ Install deps - run: yarn --frozen-lockfile - - - name: ๐Ÿ“ฅ Install Playwright - run: npx playwright install --with-deps - - - name: ๐Ÿ‘€ Run Integration Tests ${{ matrix.browser }} - run: "yarn test:integration --project=${{ matrix.browser }}" diff --git a/.github/workflows/shared-build.yml b/.github/workflows/shared-build.yml index 7608c8668fb..c12b4c94058 100644 --- a/.github/workflows/shared-build.yml +++ b/.github/workflows/shared-build.yml @@ -11,9 +11,6 @@ jobs: build: runs-on: ubuntu-latest steps: - - name: ๐Ÿ›‘ Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - - name: โฌ‡๏ธ Checkout repo uses: actions/checkout@v3 diff --git a/.github/workflows/shared-test-integration.yml b/.github/workflows/shared-test-integration.yml index 5fcc4cba5f7..5af86ebbe95 100644 --- a/.github/workflows/shared-test-integration.yml +++ b/.github/workflows/shared-test-integration.yml @@ -34,9 +34,6 @@ jobs: runs-on: ${{ inputs.os }} steps: - - name: ๐Ÿ›‘ Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - - name: โฌ‡๏ธ Checkout repo uses: actions/checkout@v3 diff --git a/.github/workflows/shared-test-unit.yml b/.github/workflows/shared-test-unit.yml index 756645c0bdf..a094bbaaed7 100644 --- a/.github/workflows/shared-test-unit.yml +++ b/.github/workflows/shared-test-unit.yml @@ -26,9 +26,6 @@ jobs: node: ${{ fromJSON(inputs.node_version) }} runs-on: ${{ inputs.os }} steps: - - name: ๐Ÿ›‘ Cancel Previous Runs - uses: styfle/cancel-workflow-action@0.11.0 - - name: โฌ‡๏ธ Checkout repo uses: actions/checkout@v3 diff --git a/.github/workflows/test-full.yml b/.github/workflows/test-full.yml index 5d9a15561d7..9eb2c9f9bad 100644 --- a/.github/workflows/test-full.yml +++ b/.github/workflows/test-full.yml @@ -1,12 +1,16 @@ name: Branch -# main/dev branches will get the full run across all OS/browsers +# main/dev/release-* branches and nightly tags will get the full run across +# all OS/browsers for multiple node versions on: push: branches: - main - dev + - release-* + tags: + - "v0.0.0-nightly-*" paths-ignore: - "docs/**" - "scripts/**" @@ -25,7 +29,7 @@ jobs: uses: ./.github/workflows/shared-test-unit.yml with: os: "ubuntu-latest" - node_version: '["latest"]' + node_version: "[18, 20]" unit-windows: name: "๐Ÿงช Unit Test" @@ -33,7 +37,7 @@ jobs: uses: ./.github/workflows/shared-test-unit.yml with: os: "windows-latest" - node_version: '["latest"]' + node_version: "[18, 20]" integration-ubuntu: name: "๐Ÿ‘€ Integration Test" @@ -41,7 +45,7 @@ jobs: uses: ./.github/workflows/shared-test-integration.yml with: os: "ubuntu-latest" - node_version: '["latest"]' + node_version: "[18, 20]" browser: '["chromium", "firefox"]' integration-windows: @@ -50,7 +54,7 @@ jobs: uses: ./.github/workflows/shared-test-integration.yml with: os: "windows-latest" - node_version: '["latest"]' + node_version: "[18, 20]" browser: '["msedge"]' integration-macos: @@ -59,5 +63,5 @@ jobs: uses: ./.github/workflows/shared-test-integration.yml with: os: "macos-latest" - node_version: '["latest"]' + node_version: "[18, 20]" browser: '["webkit"]' diff --git a/.github/workflows/test-pr-ubuntu.yml b/.github/workflows/test-pr-ubuntu.yml index e7b8a536592..2e7b86eef3e 100644 --- a/.github/workflows/test-pr-ubuntu.yml +++ b/.github/workflows/test-pr-ubuntu.yml @@ -10,6 +10,10 @@ on: - "contributors.yml" - "**/*.md" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: name: "โš™๏ธ Build" diff --git a/.github/workflows/test-pr-windows-macos.yml b/.github/workflows/test-pr-windows-macos.yml index 7dc4a923a39..d0affe8f70e 100644 --- a/.github/workflows/test-pr-windows-macos.yml +++ b/.github/workflows/test-pr-windows-macos.yml @@ -9,6 +9,10 @@ on: - "packages/remix-dev/**" - "!**/*.md" +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: unit-windows: name: "๐Ÿงช Unit Test" From 0c888c11b21c86104e2378951b32219802d2fd51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20De=20Boey?= Date: Mon, 28 Aug 2023 19:01:09 +0200 Subject: [PATCH 4/9] test(remix-server-runtime): remove polyfill references (#7205) --- .../__tests__/formData-test.ts | 30 ++++++++----------- .../remix-server-runtime/__tests__/setup.ts | 1 + packages/remix-server-runtime/package.json | 1 - 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/packages/remix-server-runtime/__tests__/formData-test.ts b/packages/remix-server-runtime/__tests__/formData-test.ts index 65299dc885f..430f9e0b3b8 100644 --- a/packages/remix-server-runtime/__tests__/formData-test.ts +++ b/packages/remix-server-runtime/__tests__/formData-test.ts @@ -1,9 +1,3 @@ -import { - Request as NodeRequest, - FormData as NodeFormData, -} from "@remix-run/web-fetch"; -import { Blob, File } from "@remix-run/web-file"; - import { parseMultipartFormData } from "../formData"; class CustomError extends Error { @@ -14,12 +8,12 @@ class CustomError extends Error { describe("parseMultipartFormData", () => { it("can use a custom upload handler", async () => { - let formData = new NodeFormData(); + let formData = new FormData(); formData.set("a", "value"); formData.set("blob", new Blob(["blob".repeat(1000)]), "blob.txt"); formData.set("file", new File(["file".repeat(1000)], "file.txt")); - let req = new NodeRequest("https://test.com", { + let req = new Request("https://test.com", { method: "post", body: formData, }); @@ -48,12 +42,12 @@ describe("parseMultipartFormData", () => { }); it("can return undefined", async () => { - let formData = new NodeFormData(); + let formData = new FormData(); formData.set("a", "value"); formData.set("blob", new Blob(["blob".repeat(1000)]), "blob.txt"); formData.set("file", new File(["file".repeat(1000)], "file.txt")); - let req = new NodeRequest("https://test.com", { + let req = new Request("https://test.com", { method: "post", body: formData, }); @@ -69,10 +63,10 @@ describe("parseMultipartFormData", () => { }); it("can throw errors in upload handlers", async () => { - let formData = new NodeFormData(); + let formData = new FormData(); formData.set("blob", new Blob(["blob"]), "blob.txt"); - let req = new NodeRequest("https://test.com", { + let req = new Request("https://test.com", { method: "post", body: formData, }); @@ -92,12 +86,12 @@ describe("parseMultipartFormData", () => { describe("stream should propagate events", () => { it("when controller errors", async () => { - let formData = new NodeFormData(); + let formData = new FormData(); formData.set("a", "value"); formData.set("blob", new Blob(["blob".repeat(1000)]), "blob.txt"); formData.set("file", new File(["file".repeat(1000)], "file.txt")); - let underlyingRequest = new NodeRequest("https://test.com", { + let underlyingRequest = new Request("https://test.com", { method: "post", body: formData, }); @@ -113,7 +107,7 @@ describe("parseMultipartFormData", () => { }, }); - let req = new NodeRequest("https://test.com", { + let req = new Request("https://test.com", { method: "post", body, headers: underlyingRequest.headers, @@ -132,12 +126,12 @@ describe("parseMultipartFormData", () => { }); it("when controller is closed", async () => { - let formData = new NodeFormData(); + let formData = new FormData(); formData.set("a", "value"); formData.set("blob", new Blob(["blob".repeat(1000)]), "blob.txt"); formData.set("file", new File(["file".repeat(1000)], "file.txt")); - let underlyingRequest = new NodeRequest("https://test.com", { + let underlyingRequest = new Request("https://test.com", { method: "post", body: formData, }); @@ -153,7 +147,7 @@ describe("parseMultipartFormData", () => { }, }); - let req = new NodeRequest("https://test.com", { + let req = new Request("https://test.com", { method: "post", body, headers: underlyingRequest.headers, diff --git a/packages/remix-server-runtime/__tests__/setup.ts b/packages/remix-server-runtime/__tests__/setup.ts index 917305ac938..451031301ac 100644 --- a/packages/remix-server-runtime/__tests__/setup.ts +++ b/packages/remix-server-runtime/__tests__/setup.ts @@ -1,2 +1,3 @@ import { installGlobals } from "@remix-run/node"; + installGlobals(); diff --git a/packages/remix-server-runtime/package.json b/packages/remix-server-runtime/package.json index 861045b0e95..2e25087ab98 100644 --- a/packages/remix-server-runtime/package.json +++ b/packages/remix-server-runtime/package.json @@ -25,7 +25,6 @@ "type-fest": "^4.0.0" }, "devDependencies": { - "@remix-run/web-file": "^3.0.3", "@types/set-cookie-parser": "^2.4.1", "typescript": "^5.1.6" }, From 64f49ff2ed4f612550e2eded9a150ec1c0871c8e Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Mon, 28 Aug 2023 15:05:00 -0400 Subject: [PATCH 5/9] Temp change to trigger dev branch CI workflows --- packages/remix-react/components.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/remix-react/components.tsx b/packages/remix-react/components.tsx index feffe815fbc..a3a136e0878 100644 --- a/packages/remix-react/components.tsx +++ b/packages/remix-react/components.tsx @@ -1173,3 +1173,5 @@ function mergeRefs( }); }; } + +// temp comment to trigger GH workflows From f8ff9f57db5012bb1ea2a765b80ce304dc01eea2 Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Mon, 28 Aug 2023 15:05:41 -0400 Subject: [PATCH 6/9] Revert "Temp change to trigger dev branch CI workflows" This reverts commit 64f49ff2ed4f612550e2eded9a150ec1c0871c8e. --- packages/remix-react/components.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/remix-react/components.tsx b/packages/remix-react/components.tsx index a3a136e0878..feffe815fbc 100644 --- a/packages/remix-react/components.tsx +++ b/packages/remix-react/components.tsx @@ -1173,5 +1173,3 @@ function mergeRefs( }); }; } - -// temp comment to trigger GH workflows From 74e11ca3667fad8d5827240ac223aeb96f574dde Mon Sep 17 00:00:00 2001 From: Pedro Cattori Date: Mon, 28 Aug 2023 15:25:44 -0400 Subject: [PATCH 7/9] feat!(serve): pick an open port when 3000 is already taken (#7278) --- .changeset/beige-pugs-drive.md | 8 ++++++++ packages/remix-serve/cli.ts | 11 +++++++++-- packages/remix-serve/package.json | 1 + yarn.lock | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 .changeset/beige-pugs-drive.md diff --git a/.changeset/beige-pugs-drive.md b/.changeset/beige-pugs-drive.md new file mode 100644 index 00000000000..c1641d09fe1 --- /dev/null +++ b/.changeset/beige-pugs-drive.md @@ -0,0 +1,8 @@ +--- +"@remix-run/serve": major +--- + +`remix-serve` picks an open port if 3000 is taken + +- If `PORT` env var is set, `remix-serve` will use that port +- Otherwise, `remix-serve` picks an open port (3000 unless that is already taken) diff --git a/packages/remix-serve/cli.ts b/packages/remix-serve/cli.ts index f1ffe8b3791..d3d4f99abe1 100644 --- a/packages/remix-serve/cli.ts +++ b/packages/remix-serve/cli.ts @@ -14,6 +14,7 @@ import compression from "compression"; import express from "express"; import morgan from "morgan"; import sourceMapSupport from "source-map-support"; +import getPort from "get-port"; process.env.NODE_ENV = process.env.NODE_ENV ?? "production"; @@ -22,9 +23,15 @@ installGlobals(); run(); +function parseNumber(raw?: string) { + if (raw === undefined) return undefined; + let maybe = Number(raw); + if (Number.isNaN(maybe)) return undefined; + return maybe; +} + async function run() { - let port = process.env.PORT ? Number(process.env.PORT) : 3000; - if (Number.isNaN(port)) port = 3000; + let port = parseNumber(process.env.PORT) ?? (await getPort({ port: 3000 })); let buildPathArg = process.argv[2]; diff --git a/packages/remix-serve/package.json b/packages/remix-serve/package.json index 06524c6b710..6af8dfca8ff 100644 --- a/packages/remix-serve/package.json +++ b/packages/remix-serve/package.json @@ -20,6 +20,7 @@ "chokidar": "^3.5.3", "compression": "^1.7.4", "express": "^4.17.1", + "get-port": "5.1.1", "morgan": "^1.10.0", "source-map-support": "^0.5.21" }, diff --git a/yarn.lock b/yarn.lock index d389aea03e6..c648d376ea5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6083,7 +6083,7 @@ get-package-type@^0.1.0: resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== -get-port@^5.1.1: +get-port@5.1.1, get-port@^5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz#0469ed07563479de6efb986baf053dcd7d4e3193" integrity sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ== From 7260e12bffde1829bd86acff48214ebd39ee44df Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Mon, 28 Aug 2023 16:46:17 -0400 Subject: [PATCH 8/9] Bump router to prerelease (#7283) --- .changeset/light-rivers-tell.md | 7 +++++ packages/remix-react/package.json | 4 +-- packages/remix-server-runtime/package.json | 2 +- packages/remix-testing/package.json | 4 +-- yarn.lock | 30 +++++++++++----------- 5 files changed, 27 insertions(+), 20 deletions(-) create mode 100644 .changeset/light-rivers-tell.md diff --git a/.changeset/light-rivers-tell.md b/.changeset/light-rivers-tell.md new file mode 100644 index 00000000000..2afd8722b29 --- /dev/null +++ b/.changeset/light-rivers-tell.md @@ -0,0 +1,7 @@ +--- +"@remix-run/react": patch +"@remix-run/server-runtime": patch +"@remix-run/testing": patch +--- + +Bump router to 1.9.0/6.16.0 prereleases diff --git a/packages/remix-react/package.json b/packages/remix-react/package.json index 0eb8c7a4876..d529afbaaf9 100644 --- a/packages/remix-react/package.json +++ b/packages/remix-react/package.json @@ -16,9 +16,9 @@ "typings": "dist/index.d.ts", "module": "dist/esm/index.js", "dependencies": { - "@remix-run/router": "0.0.0-experimental-7b1bbb00", + "@remix-run/router": "1.9.0-pre.0", "@remix-run/server-runtime": "1.19.3", - "react-router-dom": "0.0.0-experimental-7b1bbb00" + "react-router-dom": "6.16.0-pre.0" }, "devDependencies": { "@testing-library/jest-dom": "^5.17.0", diff --git a/packages/remix-server-runtime/package.json b/packages/remix-server-runtime/package.json index 2e25087ab98..7e35babfd04 100644 --- a/packages/remix-server-runtime/package.json +++ b/packages/remix-server-runtime/package.json @@ -16,7 +16,7 @@ "typings": "dist/index.d.ts", "module": "dist/esm/index.js", "dependencies": { - "@remix-run/router": "0.0.0-experimental-7b1bbb00", + "@remix-run/router": "1.9.0-pre.0", "@types/cookie": "^0.4.1", "@web3-storage/multipart-parser": "^1.0.0", "cookie": "^0.4.1", diff --git a/packages/remix-testing/package.json b/packages/remix-testing/package.json index 14756c44afa..78545580012 100644 --- a/packages/remix-testing/package.json +++ b/packages/remix-testing/package.json @@ -18,8 +18,8 @@ "dependencies": { "@remix-run/node": "1.19.3", "@remix-run/react": "1.19.3", - "@remix-run/router": "0.0.0-experimental-7b1bbb00", - "react-router-dom": "0.0.0-experimental-7b1bbb00" + "@remix-run/router": "1.9.0-pre.0", + "react-router-dom": "6.16.0-pre.0" }, "devDependencies": { "@types/node": "^18.17.1", diff --git a/yarn.lock b/yarn.lock index c648d376ea5..dbe9fe2fb08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2132,10 +2132,10 @@ "@changesets/types" "^5.0.0" dotenv "^8.1.0" -"@remix-run/router@0.0.0-experimental-7b1bbb00": - version "0.0.0-experimental-7b1bbb00" - resolved "https://registry.npmjs.org/@remix-run/router/-/router-0.0.0-experimental-7b1bbb00.tgz#53e8f0f94d4ae59cc5c96472582b9eed4277fc0c" - integrity sha512-ftRs73TmSs1muFgzrFqglifvRQKL4IXPp+FWpB+Vro9nPrYJrvT9U0zxqPpNOa11LT6zYH2+2YVsWsjfHnbErw== +"@remix-run/router@1.9.0-pre.0": + version "1.9.0-pre.0" + resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.9.0-pre.0.tgz#a91357c467c7f171096482241729446dde23a499" + integrity sha512-E0r4uaA2kS3Ks02KLXC2XD7vSlTMQmvfgb7rhaA1ni0O73GHMP38qsR3IjFvlnWNZWhOyzv2rHBtaYBZz2+I1w== "@remix-run/web-blob@^3.0.5": version "3.0.5" @@ -10128,20 +10128,20 @@ react-refresh@^0.14.0: resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz" integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== -react-router-dom@0.0.0-experimental-7b1bbb00: - version "0.0.0-experimental-7b1bbb00" - resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-0.0.0-experimental-7b1bbb00.tgz#ac53ec77036ec4de08719677370b0dbd6a94a976" - integrity sha512-fGWVuY0LVaSM+FloQ9urDy1e1a9fX5Pq/lNP1dSnA2az2+M9qAkOeadSOdR0IMJmJU3l8rsh688Arhg/j3QAPQ== +react-router-dom@6.16.0-pre.0: + version "6.16.0-pre.0" + resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.16.0-pre.0.tgz#29b1f11c6352c64a835379724caf6d3884fab819" + integrity sha512-2SiKRx2hxtk97B0eOtX8Oj6Ei8JjTKd02NQRbrHWYi20oJtOOVOYeXIcwq/kDinqkGAKjp2+5q7hDoc35YNJCA== dependencies: - "@remix-run/router" "0.0.0-experimental-7b1bbb00" - react-router "0.0.0-experimental-7b1bbb00" + "@remix-run/router" "1.9.0-pre.0" + react-router "6.16.0-pre.0" -react-router@0.0.0-experimental-7b1bbb00: - version "0.0.0-experimental-7b1bbb00" - resolved "https://registry.npmjs.org/react-router/-/react-router-0.0.0-experimental-7b1bbb00.tgz#eae87bbfba7d28265ea55287b97c95eb147f7e91" - integrity sha512-7fdfoYJKv73CqivkA8VwXpkF+juw6GflK3HSXVQ+5wC/49for/+2mxk3Y/294C17xRSqiLeTb4mHC/olwNeZeQ== +react-router@6.16.0-pre.0: + version "6.16.0-pre.0" + resolved "https://registry.npmjs.org/react-router/-/react-router-6.16.0-pre.0.tgz#85ed4b71e01185349e8fb9e822676d2057995759" + integrity sha512-dvaErR6mV3UVZV9rzAOKaraG6s+Qkl78FnkVTC4MI83ZqKA2jqpF+aIxN8S7JY2Fhw1EcfB5HtvKRlyVQpBt7A== dependencies: - "@remix-run/router" "0.0.0-experimental-7b1bbb00" + "@remix-run/router" "1.9.0-pre.0" react@^18.2.0: version "18.2.0" From 9154f350c7796de4ca892e7b10eceb34a125e0a2 Mon Sep 17 00:00:00 2001 From: Mark Dalgleish Date: Tue, 29 Aug 2023 07:28:21 +1000 Subject: [PATCH 9/9] fix(dev): get deps from ESM packages without main (#7272) --- .../get-dependencies-from-esm-without-main.md | 5 +++ integration/compiler-test.ts | 32 +++++++++++++++++++ packages/remix-dev/dependencies.ts | 24 +++++++++++++- 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 .changeset/get-dependencies-from-esm-without-main.md diff --git a/.changeset/get-dependencies-from-esm-without-main.md b/.changeset/get-dependencies-from-esm-without-main.md new file mode 100644 index 00000000000..614a898bea6 --- /dev/null +++ b/.changeset/get-dependencies-from-esm-without-main.md @@ -0,0 +1,5 @@ +--- +"@remix-run/dev": patch +--- + +Update `getDependenciesToBundle` to handle ESM packages without main exports. Note that these packages must expose `package.json` in their `exports` field so that their path can be resolved. diff --git a/integration/compiler-test.ts b/integration/compiler-test.ts index 116e94abde7..12cbe904c37 100644 --- a/integration/compiler-test.ts +++ b/integration/compiler-test.ts @@ -28,6 +28,7 @@ test.describe("compiler", () => { "esm-only-pkg", "esm-only-single-export", ...getDependenciesToBundle("esm-only-exports-pkg"), + ...getDependenciesToBundle("esm-only-nested-exports-pkg"), ], }; `, @@ -84,6 +85,13 @@ test.describe("compiler", () => { return
{esmOnlyPkg}
; } `, + "app/routes/esm-only-nested-exports-pkg.tsx": js` + import esmOnlyPkg from "esm-only-nested-exports-pkg/nested"; + + export default function EsmOnlyPkg() { + return
{esmOnlyPkg}
; + } + `, "app/routes/esm-only-single-export.tsx": js` import esmOnlyPkg from "esm-only-single-export"; @@ -129,6 +137,18 @@ test.describe("compiler", () => { "node_modules/esm-only-exports-pkg/esm-only-exports-pkg.js": js` export default "esm-only-exports-pkg"; `, + "node_modules/esm-only-nested-exports-pkg/package.json": json({ + name: "esm-only-nested-exports-pkg", + version: "1.0.0", + type: "module", + exports: { + "./package.json": "./package.json", + "./nested": "./esm-only-nested-exports-pkg.js", + }, + }), + "node_modules/esm-only-nested-exports-pkg/esm-only-nested-exports-pkg.js": js` + export default "esm-only-nested-exports-pkg"; + `, "node_modules/esm-only-single-export/package.json": json({ name: "esm-only-exports-pkg", version: "1.0.0", @@ -288,6 +308,18 @@ test.describe("compiler", () => { ); }); + test("allows consumption of ESM modules with only nested exports in CJS builds with `serverDependenciesToBundle` and `getDependenciesToBundle`", async ({ + page, + }) => { + let app = new PlaywrightFixture(appFixture, page); + let res = await app.goto("/esm-only-nested-exports-pkg", true); + expect(res.status()).toBe(200); // server rendered fine + // rendered the page instead of the error boundary + expect(await app.getHtml("#esm-only-nested-exports-pkg")).toBe( + '
esm-only-nested-exports-pkg
' + ); + }); + test("allows consumption of packages with sub modules", async ({ page }) => { let app = new PlaywrightFixture(appFixture, page); let res = await app.goto("/package-with-submodule", true); diff --git a/packages/remix-dev/dependencies.ts b/packages/remix-dev/dependencies.ts index cbf53c10781..e3d6393aab8 100644 --- a/packages/remix-dev/dependencies.ts +++ b/packages/remix-dev/dependencies.ts @@ -40,6 +40,17 @@ export function getDependenciesToBundle(...pkg: string[]): string[] { return Array.from(aggregatedDeps); } +interface ErrorWithCode extends Error { + code: string; +} + +function isErrorWithCode(error: unknown): error is ErrorWithCode { + return ( + error instanceof Error && + typeof (error as NodeJS.ErrnoException).code === "string" + ); +} + function getPackageDependenciesRecursive( pkg: string, aggregatedDeps: Set, @@ -47,7 +58,18 @@ function getPackageDependenciesRecursive( ): void { visitedPackages.add(pkg); - let pkgPath = require.resolve(pkg); + let pkgPath: string; + try { + pkgPath = require.resolve(pkg); + } catch (err) { + if (isErrorWithCode(err) && err.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") { + // Handle packages without main exports. + // They at least need to have package.json exported. + pkgPath = require.resolve(`${pkg}/package.json`); + } else { + throw err; + } + } let lastIndexOfPackageName = pkgPath.lastIndexOf(pkg); if (lastIndexOfPackageName !== -1) { pkgPath = pkgPath.substring(0, lastIndexOfPackageName);