From 6b8010702cb1bc4c1b81a61bb1a2db0afbb03871 Mon Sep 17 00:00:00 2001 From: Liad Yosef Date: Tue, 19 Mar 2024 19:56:06 +0200 Subject: [PATCH 1/2] initial --- utopia-remix/.gitignore | 2 + utopia-remix/package.json | 25 ++- utopia-remix/pnpm-lock.yaml | 356 ++++++++++++++++++++++++++++------- utopia-remix/remix.config.js | 1 + utopia-remix/server.ts | 215 +++++++++++++++++++++ utopia-remix/tsconfig.json | 1 + 6 files changed, 528 insertions(+), 72 deletions(-) create mode 100644 utopia-remix/server.ts diff --git a/utopia-remix/.gitignore b/utopia-remix/.gitignore index ded956b3deaa..f95f2a818575 100644 --- a/utopia-remix/.gitignore +++ b/utopia-remix/.gitignore @@ -5,3 +5,5 @@ node_modules /public/build .env vegeta + +server.js \ No newline at end of file diff --git a/utopia-remix/package.json b/utopia-remix/package.json index 7c7e1b1942b1..c7b16a18ff1f 100644 --- a/utopia-remix/package.json +++ b/utopia-remix/package.json @@ -4,8 +4,11 @@ "sideEffects": false, "type": "module", "scripts": { - "build": "remix build", - "dev": "remix dev -c \"node server.js\"", + "build": "pnpm run build:server && pnpm run build:remix", + "build:server": "esbuild --platform=node --format=esm ./server.ts --outdir=./", + "build:remix": "remix build", + "dev": "remix dev -c \"npm run dev:server\" --manual", + "dev:server": "tsx watch --clear-screen=false --ignore 'app/**' --ignore 'build/**' --ignore 'node_modules/**' --inspect ./server.ts", "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "node ./server.js", "typecheck": "tsc", @@ -28,16 +31,17 @@ "@radix-ui/react-slot": "1.0.2", "@radix-ui/react-tooltip": "1.0.7", "@radix-ui/themes": "2.0.3", - "@remix-run/css-bundle": "2.5.1", - "@remix-run/express": "2.8.0", - "@remix-run/node": "2.5.1", - "@remix-run/react": "2.5.1", - "@remix-run/serve": "2.5.1", + "@remix-run/css-bundle": "2.8.1", + "@remix-run/express": "2.8.1", + "@remix-run/node": "2.8.1", + "@remix-run/react": "2.8.1", + "@remix-run/serve": "2.8.1", "@tailwindcss/aspect-ratio": "0.4.2", "@tailwindcss/typography": "0.5.10", "classnames": "2.5.1", "cookie": "0.6.0", "cors": "2.8.5", + "cross-env": "7.0.3", "dotenv": "16.4.1", "express": "4.18.3", "framer-motion": "11.0.6", @@ -49,6 +53,7 @@ "react-dom": "18.2.0", "slugify": "1.6.6", "tiny-invariant": "1.3.1", + "tsx": "4.7.1", "url-join": "5.0.0", "zustand": "4.5.0" }, @@ -64,6 +69,7 @@ "@types/node": "20.11.15", "@types/react": "18.2.20", "@types/react-dom": "18.2.7", + "@types/source-map-support": "0.5.10", "@types/uuid": "9.0.8", "@typescript-eslint/eslint-plugin": "6.7.4", "@typescript-eslint/parser": ">=6.0.0 <7.0.0", @@ -73,16 +79,17 @@ "@vanilla-extract/sprinkles": "1.6.1", "babel-eslint": "10.0.1", "chokidar": "3.6.0", + "esbuild": "0.20.2", "eslint": "8.38.0", "eslint-config-prettier": "6.9.0", + "eslint-config-utopia": "link:../eslint-config-utopia", "eslint-import-resolver-typescript": "3.6.1", - "eslint-plugin-prettier": "3.1.2", "eslint-plugin-import": "2.28.1", "eslint-plugin-jest": "25.3.0", "eslint-plugin-jsx-a11y": "6.7.1", + "eslint-plugin-prettier": "3.1.2", "eslint-plugin-react": "7.33.2", "eslint-plugin-react-hooks": "4.6.0", - "eslint-config-utopia": "link:../eslint-config-utopia", "jest": "29.7.0", "prettier": "3.0.3", "prisma": "5.9.0", diff --git a/utopia-remix/pnpm-lock.yaml b/utopia-remix/pnpm-lock.yaml index 430dcf65db52..da49757fe9a6 100644 --- a/utopia-remix/pnpm-lock.yaml +++ b/utopia-remix/pnpm-lock.yaml @@ -17,12 +17,12 @@ specifiers: '@radix-ui/react-slot': 1.0.2 '@radix-ui/react-tooltip': 1.0.7 '@radix-ui/themes': 2.0.3 - '@remix-run/css-bundle': 2.5.1 + '@remix-run/css-bundle': 2.8.1 '@remix-run/dev': 2.5.1 - '@remix-run/express': 2.8.0 - '@remix-run/node': 2.5.1 - '@remix-run/react': 2.5.1 - '@remix-run/serve': 2.5.1 + '@remix-run/express': 2.8.1 + '@remix-run/node': 2.8.1 + '@remix-run/react': 2.8.1 + '@remix-run/serve': 2.8.1 '@tailwindcss/aspect-ratio': 0.4.2 '@tailwindcss/typography': 0.5.10 '@types/cookie': 0.6.0 @@ -33,6 +33,7 @@ specifiers: '@types/node': 20.11.15 '@types/react': 18.2.20 '@types/react-dom': 18.2.7 + '@types/source-map-support': 0.5.10 '@types/uuid': 9.0.8 '@typescript-eslint/eslint-plugin': 6.7.4 '@typescript-eslint/parser': '>=6.0.0 <7.0.0' @@ -45,7 +46,9 @@ specifiers: classnames: 2.5.1 cookie: 0.6.0 cors: 2.8.5 + cross-env: 7.0.3 dotenv: 16.4.1 + esbuild: 0.20.2 eslint: 8.38.0 eslint-config-prettier: 6.9.0 eslint-config-utopia: link:../eslint-config-utopia @@ -72,6 +75,7 @@ specifiers: tailwindcss: 3.4.1 tiny-invariant: 1.3.1 ts-node: 10.9.2 + tsx: 4.7.1 typescript: 5.1.6 url-join: 5.0.0 uuid: 9.0.1 @@ -92,16 +96,17 @@ dependencies: '@radix-ui/react-slot': 1.0.2_j3ahe22lw6ac2w6qvqp4kjqnqy '@radix-ui/react-tooltip': 1.0.7_gltvt74xzh7f5lvw2hzxriz5bu '@radix-ui/themes': 2.0.3_gltvt74xzh7f5lvw2hzxriz5bu - '@remix-run/css-bundle': 2.5.1 - '@remix-run/express': 2.8.0_agmaczb3qlb3you2ogdoykwerq - '@remix-run/node': 2.5.1_typescript@5.1.6 - '@remix-run/react': 2.5.1_i4rjfizg7pnsmg7p6yi76gfzdq - '@remix-run/serve': 2.5.1_typescript@5.1.6 + '@remix-run/css-bundle': 2.8.1 + '@remix-run/express': 2.8.1_agmaczb3qlb3you2ogdoykwerq + '@remix-run/node': 2.8.1_typescript@5.1.6 + '@remix-run/react': 2.8.1_i4rjfizg7pnsmg7p6yi76gfzdq + '@remix-run/serve': 2.8.1_typescript@5.1.6 '@tailwindcss/aspect-ratio': 0.4.2_tailwindcss@3.4.1 '@tailwindcss/typography': 0.5.10_tailwindcss@3.4.1 classnames: 2.5.1 cookie: 0.6.0 cors: 2.8.5 + cross-env: 7.0.3 dotenv: 16.4.1 express: 4.18.3 framer-motion: 11.0.6_biqbaboplfbrettd7655fr4n2y @@ -113,13 +118,14 @@ dependencies: react-dom: 18.2.0_react@18.2.0 slugify: 1.6.6 tiny-invariant: 1.3.1 + tsx: 4.7.1 url-join: 5.0.0 zustand: 4.5.0_j3ahe22lw6ac2w6qvqp4kjqnqy devDependencies: '@babel/core': 7.23.9 '@babel/preset-env': 7.23.9_@babel+core@7.23.9 - '@remix-run/dev': 2.5.1_mnvgn3pnbscn2kjs5c6zondszi + '@remix-run/dev': 2.5.1_3qxlguwqkztjbusnrumqdnclsm '@types/cookie': 0.6.0 '@types/cors': 2.8.17 '@types/eslint': 7.2.2 @@ -128,6 +134,7 @@ devDependencies: '@types/node': 20.11.15 '@types/react': 18.2.20 '@types/react-dom': 18.2.7 + '@types/source-map-support': 0.5.10 '@types/uuid': 9.0.8 '@typescript-eslint/eslint-plugin': 6.7.4_shtvzkt6s7gm4npckmp2z5nvfi '@typescript-eslint/parser': 6.20.0_mcioginrgbuoxxpmyisevjswdq @@ -137,6 +144,7 @@ devDependencies: '@vanilla-extract/sprinkles': 1.6.1_z6bawfcloyu65obf65prni7ivu babel-eslint: 10.0.1_eslint@8.38.0 chokidar: 3.6.0 + esbuild: 0.20.2 eslint: 8.38.0 eslint-config-prettier: 6.9.0_eslint@8.38.0 eslint-config-utopia: link:../eslint-config-utopia @@ -1438,6 +1446,14 @@ packages: cpu: [ppc64] os: [aix] requiresBuild: true + optional: true + + /@esbuild/aix-ppc64/0.20.2: + resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true dev: true optional: true @@ -1456,6 +1472,14 @@ packages: cpu: [arm] os: [android] requiresBuild: true + optional: true + + /@esbuild/android-arm/0.20.2: + resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true dev: true optional: true @@ -1474,6 +1498,14 @@ packages: cpu: [arm64] os: [android] requiresBuild: true + optional: true + + /@esbuild/android-arm64/0.20.2: + resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true dev: true optional: true @@ -1492,6 +1524,14 @@ packages: cpu: [x64] os: [android] requiresBuild: true + optional: true + + /@esbuild/android-x64/0.20.2: + resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true dev: true optional: true @@ -1510,6 +1550,14 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true + optional: true + + /@esbuild/darwin-arm64/0.20.2: + resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true dev: true optional: true @@ -1528,6 +1576,14 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true + optional: true + + /@esbuild/darwin-x64/0.20.2: + resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true dev: true optional: true @@ -1546,6 +1602,14 @@ packages: cpu: [arm64] os: [freebsd] requiresBuild: true + optional: true + + /@esbuild/freebsd-arm64/0.20.2: + resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true dev: true optional: true @@ -1564,6 +1628,14 @@ packages: cpu: [x64] os: [freebsd] requiresBuild: true + optional: true + + /@esbuild/freebsd-x64/0.20.2: + resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true dev: true optional: true @@ -1582,6 +1654,14 @@ packages: cpu: [arm] os: [linux] requiresBuild: true + optional: true + + /@esbuild/linux-arm/0.20.2: + resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true dev: true optional: true @@ -1600,6 +1680,14 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true + optional: true + + /@esbuild/linux-arm64/0.20.2: + resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true dev: true optional: true @@ -1618,6 +1706,14 @@ packages: cpu: [ia32] os: [linux] requiresBuild: true + optional: true + + /@esbuild/linux-ia32/0.20.2: + resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true dev: true optional: true @@ -1636,6 +1732,14 @@ packages: cpu: [loong64] os: [linux] requiresBuild: true + optional: true + + /@esbuild/linux-loong64/0.20.2: + resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true dev: true optional: true @@ -1654,6 +1758,14 @@ packages: cpu: [mips64el] os: [linux] requiresBuild: true + optional: true + + /@esbuild/linux-mips64el/0.20.2: + resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true dev: true optional: true @@ -1672,6 +1784,14 @@ packages: cpu: [ppc64] os: [linux] requiresBuild: true + optional: true + + /@esbuild/linux-ppc64/0.20.2: + resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true dev: true optional: true @@ -1690,6 +1810,14 @@ packages: cpu: [riscv64] os: [linux] requiresBuild: true + optional: true + + /@esbuild/linux-riscv64/0.20.2: + resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true dev: true optional: true @@ -1708,6 +1836,14 @@ packages: cpu: [s390x] os: [linux] requiresBuild: true + optional: true + + /@esbuild/linux-s390x/0.20.2: + resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true dev: true optional: true @@ -1726,6 +1862,14 @@ packages: cpu: [x64] os: [linux] requiresBuild: true + optional: true + + /@esbuild/linux-x64/0.20.2: + resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true dev: true optional: true @@ -1744,6 +1888,14 @@ packages: cpu: [x64] os: [netbsd] requiresBuild: true + optional: true + + /@esbuild/netbsd-x64/0.20.2: + resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true dev: true optional: true @@ -1762,6 +1914,14 @@ packages: cpu: [x64] os: [openbsd] requiresBuild: true + optional: true + + /@esbuild/openbsd-x64/0.20.2: + resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true dev: true optional: true @@ -1780,6 +1940,14 @@ packages: cpu: [x64] os: [sunos] requiresBuild: true + optional: true + + /@esbuild/sunos-x64/0.20.2: + resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true dev: true optional: true @@ -1798,6 +1966,14 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true + optional: true + + /@esbuild/win32-arm64/0.20.2: + resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true dev: true optional: true @@ -1816,6 +1992,14 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true + optional: true + + /@esbuild/win32-ia32/0.20.2: + resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true dev: true optional: true @@ -1834,6 +2018,14 @@ packages: cpu: [x64] os: [win32] requiresBuild: true + optional: true + + /@esbuild/win32-x64/0.20.2: + resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true dev: true optional: true @@ -3450,12 +3642,12 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: false - /@remix-run/css-bundle/2.5.1: - resolution: {integrity: sha512-QPeNvgD7fj4NmXB9CuGM5Mp0ZtM43dMeda8Ik3AUoQOMgMWb0d4jK4Cye6eoTGwJOron6XISKh0mq8MorucWEQ==} + /@remix-run/css-bundle/2.8.1: + resolution: {integrity: sha512-rn72xyUJ+rR5I0IxjlDWPPBddV1kpLvOT2FY9SMIUTFqyxq3ZK2W7FCtFzBt2JZQGZ9oDYidXYMWkW6tXY//rg==} engines: {node: '>=18.0.0'} dev: false - /@remix-run/dev/2.5.1_mnvgn3pnbscn2kjs5c6zondszi: + /@remix-run/dev/2.5.1_3qxlguwqkztjbusnrumqdnclsm: resolution: {integrity: sha512-IrYhWANubH+WM62Wz55n8NWT5kBqfbyytXDFlP0VoZLrr1IpJf2GtaT4IA+CODMaNoeXeMACOD5Tw5/Y2bO5lA==} engines: {node: '>=18.0.0'} hasBin: true @@ -3483,7 +3675,7 @@ packages: '@npmcli/package-json': 4.0.1 '@remix-run/node': 2.5.1_typescript@5.1.6 '@remix-run/router': 1.14.2 - '@remix-run/serve': 2.5.1_typescript@5.1.6 + '@remix-run/serve': 2.8.1_typescript@5.1.6 '@remix-run/server-runtime': 2.5.1_typescript@5.1.6 '@types/mdx': 2.0.11 '@vanilla-extract/integration': 6.5.0_@types+node@20.11.15 @@ -3541,8 +3733,8 @@ packages: - utf-8-validate dev: true - /@remix-run/express/2.5.1_agmaczb3qlb3you2ogdoykwerq: - resolution: {integrity: sha512-ISaf2hzHxDTS1hNsOovRoSfIQC29m4ogzXvBC6xp2BuJj0K8R0yQ4RFD4+qUFEUnS2n6MyWyjFQRhOC6PhQhRw==} + /@remix-run/express/2.8.1_agmaczb3qlb3you2ogdoykwerq: + resolution: {integrity: sha512-p1eo8uwZk8uLihSDpUnPOPsTDfghWikVPQfa+e0ZMk6tnJCjcpHAyENKDFtn9vDh9h7YNUg6A7+19CStHgxd7Q==} engines: {node: '>=18.0.0'} peerDependencies: express: ^4.17.1 @@ -3551,25 +3743,10 @@ packages: typescript: optional: true dependencies: - '@remix-run/node': 2.5.1_typescript@5.1.6 + '@remix-run/node': 2.8.1_typescript@5.1.6 express: 4.18.3 typescript: 5.1.6 - /@remix-run/express/2.8.0_agmaczb3qlb3you2ogdoykwerq: - resolution: {integrity: sha512-15qnPt+vrvv66pvdcRiodNF5I5Rot07HoKjVlrXYSO4KbSg9WTE0jCPX0rFStD4QNTa2hIl8YftPlmZXjFxQoQ==} - engines: {node: '>=18.0.0'} - peerDependencies: - express: ^4.17.1 - typescript: ^5.1.0 - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@remix-run/node': 2.8.0_typescript@5.1.6 - express: 4.18.3 - typescript: 5.1.6 - dev: false - /@remix-run/node/2.5.1_typescript@5.1.6: resolution: {integrity: sha512-UI442xzHAiokmsfrYOabMQB024+IizmRhZBGcNa42QjJWsNqogy1bNwYhzEpB6oQEB1wF3vwOKK1AD1/iYA/9A==} engines: {node: '>=18.0.0'} @@ -3588,9 +3765,10 @@ packages: source-map-support: 0.5.21 stream-slice: 0.1.2 typescript: 5.1.6 + dev: true - /@remix-run/node/2.8.0_typescript@5.1.6: - resolution: {integrity: sha512-UGAckayyhw14v70O1Lcf75Nr/ipLOG5e20tMiMee96sCXWaHGHpv9VbAVoDXiVKqI3sw4dJarNc0qo794zwAbg==} + /@remix-run/node/2.8.1_typescript@5.1.6: + resolution: {integrity: sha512-ddCwBVlfLvRxTQJHPcaM1lhfMjsFYG3EGmYpWJIWnnzDX5EbX9pUNHBWisMuH1eA0c7pbw0PbW0UtCttKYx2qg==} engines: {node: '>=18.0.0'} peerDependencies: typescript: ^5.1.0 @@ -3598,7 +3776,7 @@ packages: typescript: optional: true dependencies: - '@remix-run/server-runtime': 2.8.0_typescript@5.1.6 + '@remix-run/server-runtime': 2.8.1_typescript@5.1.6 '@remix-run/web-fetch': 4.4.2 '@remix-run/web-file': 3.1.0 '@remix-run/web-stream': 1.1.0 @@ -3607,10 +3785,9 @@ packages: source-map-support: 0.5.21 stream-slice: 0.1.2 typescript: 5.1.6 - dev: false - /@remix-run/react/2.5.1_i4rjfizg7pnsmg7p6yi76gfzdq: - resolution: {integrity: sha512-MNXHLj4Iu9Iyi+3uY61JZJ1Rtx2nM/z11j9AtwQdEADkh1/t9GruhtT/8VLplToOl0qWZKItboWScKf6uRQsrw==} + /@remix-run/react/2.8.1_i4rjfizg7pnsmg7p6yi76gfzdq: + resolution: {integrity: sha512-HTPm1U8+xz2jPaVjZnssrckfmFMA8sUZUdaWnoF5lmLWdReqcQv+XlBhIrQQ3jO9L8iYYdnzaSZZcRFYSdpTYg==} engines: {node: '>=18.0.0'} peerDependencies: react: ^18.0.0 @@ -3620,31 +3797,31 @@ packages: typescript: optional: true dependencies: - '@remix-run/router': 1.14.2 - '@remix-run/server-runtime': 2.5.1_typescript@5.1.6 + '@remix-run/router': 1.15.3 + '@remix-run/server-runtime': 2.8.1_typescript@5.1.6 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 - react-router: 6.21.3_react@18.2.0 - react-router-dom: 6.21.3_biqbaboplfbrettd7655fr4n2y + react-router: 6.22.3_react@18.2.0 + react-router-dom: 6.22.3_biqbaboplfbrettd7655fr4n2y typescript: 5.1.6 dev: false /@remix-run/router/1.14.2: resolution: {integrity: sha512-ACXpdMM9hmKZww21yEqWwiLws/UPLhNKvimN8RrYSqPSvB3ov7sLvAcfvaxePeLvccTQKGdkDIhLYApZVDFuKg==} engines: {node: '>=14.0.0'} + dev: true - /@remix-run/router/1.15.2: - resolution: {integrity: sha512-+Rnav+CaoTE5QJc4Jcwh5toUpnVLKYbpU6Ys0zqbakqbaLQHeglLVHPfxOiQqdNmUy5C2lXz5dwC6tQNX2JW2Q==} + /@remix-run/router/1.15.3: + resolution: {integrity: sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==} engines: {node: '>=14.0.0'} - dev: false - /@remix-run/serve/2.5.1_typescript@5.1.6: - resolution: {integrity: sha512-r1IWfirwkLrxADd8uFUIpLR1wMU8VeRI4ED4SpbhrKwqODLrYtv5irzjei+r/w0y0Oob8DMHnYxg03UY4T7ejg==} + /@remix-run/serve/2.8.1_typescript@5.1.6: + resolution: {integrity: sha512-PyCV7IMnRshwfFw7JJ2hZJppX88VAhZyYjeTAmYb6PK7IDtdmqUf5eOrYDi8gCu914C+aZRu6blxpLRlpyCY8Q==} engines: {node: '>=18.0.0'} hasBin: true dependencies: - '@remix-run/express': 2.5.1_agmaczb3qlb3you2ogdoykwerq - '@remix-run/node': 2.5.1_typescript@5.1.6 + '@remix-run/express': 2.8.1_agmaczb3qlb3you2ogdoykwerq + '@remix-run/node': 2.8.1_typescript@5.1.6 chokidar: 3.6.0 compression: 1.7.4 express: 4.18.3 @@ -3671,9 +3848,10 @@ packages: set-cookie-parser: 2.6.0 source-map: 0.7.4 typescript: 5.1.6 + dev: true - /@remix-run/server-runtime/2.8.0_typescript@5.1.6: - resolution: {integrity: sha512-bb6rRefxEqA1fHGUo2i2s1uMztYqQlxupVCVsAs+sUkzTXtORJW+b0oFIKf5yWyaarBJ4zeLyoPsAMBqVX8P3w==} + /@remix-run/server-runtime/2.8.1_typescript@5.1.6: + resolution: {integrity: sha512-fh4SOEoONrN73Kvzc0gMDCmYpVRVbvoj9j3BUXHAcn0An8iX+HD/22gU7nTkIBzExM/F9xgEcwTewOnWqLw0Bg==} engines: {node: '>=18.0.0'} peerDependencies: typescript: ^5.1.0 @@ -3681,14 +3859,13 @@ packages: typescript: optional: true dependencies: - '@remix-run/router': 1.15.2 + '@remix-run/router': 1.15.3 '@types/cookie': 0.6.0 '@web3-storage/multipart-parser': 1.0.0 cookie: 0.6.0 set-cookie-parser: 2.6.0 source-map: 0.7.4 typescript: 5.1.6 - dev: false /@remix-run/web-blob/3.1.0: resolution: {integrity: sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==} @@ -4114,6 +4291,12 @@ packages: '@types/node': 20.11.16 dev: true + /@types/source-map-support/0.5.10: + resolution: {integrity: sha512-tgVP2H469x9zq34Z0m/fgPewGhg/MLClalNOiPIzQlXrSS2YrKu/xCdSCKnEDwkFha51VKEKB6A9wW26/ZNwzA==} + dependencies: + source-map: 0.6.1 + dev: true + /@types/stack-utils/2.0.3: resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} dev: true @@ -5258,6 +5441,14 @@ packages: /create-require/1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + /cross-env/7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + dependencies: + cross-spawn: 7.0.3 + dev: false + /cross-spawn/7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -5664,6 +5855,36 @@ packages: '@esbuild/win32-arm64': 0.19.12 '@esbuild/win32-ia32': 0.19.12 '@esbuild/win32-x64': 0.19.12 + + /esbuild/0.20.2: + resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.20.2 + '@esbuild/android-arm': 0.20.2 + '@esbuild/android-arm64': 0.20.2 + '@esbuild/android-x64': 0.20.2 + '@esbuild/darwin-arm64': 0.20.2 + '@esbuild/darwin-x64': 0.20.2 + '@esbuild/freebsd-arm64': 0.20.2 + '@esbuild/freebsd-x64': 0.20.2 + '@esbuild/linux-arm': 0.20.2 + '@esbuild/linux-arm64': 0.20.2 + '@esbuild/linux-ia32': 0.20.2 + '@esbuild/linux-loong64': 0.20.2 + '@esbuild/linux-mips64el': 0.20.2 + '@esbuild/linux-ppc64': 0.20.2 + '@esbuild/linux-riscv64': 0.20.2 + '@esbuild/linux-s390x': 0.20.2 + '@esbuild/linux-x64': 0.20.2 + '@esbuild/netbsd-x64': 0.20.2 + '@esbuild/openbsd-x64': 0.20.2 + '@esbuild/sunos-x64': 0.20.2 + '@esbuild/win32-arm64': 0.20.2 + '@esbuild/win32-ia32': 0.20.2 + '@esbuild/win32-x64': 0.20.2 dev: true /escalade/3.1.1: @@ -6466,7 +6687,6 @@ packages: resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} dependencies: resolve-pkg-maps: 1.0.0 - dev: true /glob-parent/5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -9108,26 +9328,26 @@ packages: use-sidecar: 1.1.2_j3ahe22lw6ac2w6qvqp4kjqnqy dev: false - /react-router-dom/6.21.3_biqbaboplfbrettd7655fr4n2y: - resolution: {integrity: sha512-kNzubk7n4YHSrErzjLK72j0B5i969GsuCGazRl3G6j1zqZBLjuSlYBdVdkDOgzGdPIffUOc9nmgiadTEVoq91g==} + /react-router-dom/6.22.3_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' react-dom: '>=16.8' dependencies: - '@remix-run/router': 1.14.2 + '@remix-run/router': 1.15.3 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 - react-router: 6.21.3_react@18.2.0 + react-router: 6.22.3_react@18.2.0 dev: false - /react-router/6.21.3_react@18.2.0: - resolution: {integrity: sha512-a0H638ZXULv1OdkmiK6s6itNhoy33ywxmUFT/xtSoVyf9VnC7n7+VT4LjVzdIHSaF5TIh9ylUgxMXksHTgGrKg==} + /react-router/6.22.3_react@18.2.0: + resolution: {integrity: sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' dependencies: - '@remix-run/router': 1.14.2 + '@remix-run/router': 1.15.3 react: 18.2.0 dev: false @@ -9322,7 +9542,6 @@ packages: /resolve-pkg-maps/1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - dev: true /resolve.exports/2.0.2: resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} @@ -10004,6 +10223,17 @@ packages: typescript: 5.1.6 dev: true + /tsx/4.7.1: + resolution: {integrity: sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==} + engines: {node: '>=18.0.0'} + hasBin: true + dependencies: + esbuild: 0.19.12 + get-tsconfig: 4.7.2 + optionalDependencies: + fsevents: 2.3.3 + dev: false + /type-check/0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} diff --git a/utopia-remix/remix.config.js b/utopia-remix/remix.config.js index e97e6b136e87..3fc5282bcc75 100644 --- a/utopia-remix/remix.config.js +++ b/utopia-remix/remix.config.js @@ -6,6 +6,7 @@ export default { v3_fetcherPersist: true, }, serverModuleFormat: 'esm', + server: './server.ts', // appDirectory: "app", // assetsBuildDirectory: "public/build", // publicPath: "/build/", diff --git a/utopia-remix/server.ts b/utopia-remix/server.ts new file mode 100644 index 000000000000..da566905861c --- /dev/null +++ b/utopia-remix/server.ts @@ -0,0 +1,215 @@ +/* eslint-disable no-console */ +import { createRequestHandler } from '@remix-run/express' +import type { ServerBuild } from '@remix-run/node' +import { broadcastDevReady, installGlobals } from '@remix-run/node' +import cors from 'cors' +import express from 'express' +import * as fs from 'node:fs' +import * as http from 'node:http' +import * as path from 'node:path' +import * as url from 'node:url' +import sourceMapSupport from 'source-map-support' + +// To make sure everything keeps working and the server doesn't crash, if +// there are any uncaught errors, log them out gracefully +process.on('uncaughtException', (err) => { + console.error('server uncaught exception', err) +}) +process.on('unhandledRejection', (err) => { + console.error('server unhandled rejection', err) +}) + +// figlet -f isometric3 'utopia' +const asciiBanner = ` + ___ ___ ___ ___ + /__/\\ ___ / /\\ / /\\ ___ / /\\ + \\ \\:\\ / /\\ / /::\\ / /::\\ / /\\ / /::\\ + \\ \\:\\ / /:/ / /:/\\:\\ / /:/\\:\\ / /:/ / /:/\\:\\ + ___ \\ \\:\\ / /:/ / /:/ \\:\\ / /:/~/:/ /__/::\\ / /:/~/::\\ + /__/\\ \\__\\:\\ / /::\\ /__/:/ \\__\\:\\ /__/:/ /:/ \\__\\/\\:\\__ /__/:/ /:/\\:\\ + \\ \\:\\ / /:/ /__/:/\\:\\ \\ \\:\\ / /:/ \\ \\:\\/:/ \\ \\:\\/\\ \\ \\:\\/:/__\\/ + \\ \\:\\ /:/ \\__\\/ \\:\\ \\ \\:\\ /:/ \\ \\::/ \\__\\::/ \\ \\::/ + \\ \\:\\/:/ \\ \\:\\ \\ \\:\\/:/ \\ \\:\\ /__/:/ \\ \\:\\ + \\ \\::/ \\__\\/ \\ \\::/ \\ \\:\\ \\__\\/ \\ \\:\\ + \\__\\/ \\__\\/ \\__\\/ \\__\\/ +` + +// ----------------------------------------------------------------------------- +// From: https://github.com/remix-run/remix/tree/main/templates/express +// ----------------------------------------------------------------------------- +const BUILD_PATH = path.resolve('build/index.js') +const VERSION_PATH = path.resolve('build/version.txt') + +const nodeEnv = process.env.NODE_ENV +console.info(`Server environment: ${nodeEnv}`) + +const environment = { + NODE_ENV: nodeEnv, + BACKEND_URL: new URL(mustEnvOrLocalFallback('BACKEND_URL', 'http://localhost:8002')), + EDITOR_URL: mustEnvOrLocalFallback('EDITOR_URL', 'http://localhost:8000'), + PORT: Number.parseInt(mustEnvOrLocalFallback('PORT', '8000')), +} + +// counterpart of `env.server.ts`'s mustEnvOrLocalFallback +function mustEnvOrLocalFallback(key: string, localFallback: string) { + const value = process.env[key] ?? '' + if (value !== '') { + return value + } + if (nodeEnv === 'development' || nodeEnv === 'test') { + return localFallback + } + throw new Error(`missing required environment variable ${key}`) +} + +sourceMapSupport.install({ + retrieveSourceMap: function (source) { + const match = source.startsWith('file://') + if (match) { + const filePath = url.fileURLToPath(source) + const sourceMapPath = `${filePath}.map` + if (fs.existsSync(sourceMapPath)) { + return { + url: source, + map: fs.readFileSync(sourceMapPath, 'utf8'), + } + } + } + return null + }, +}) +installGlobals() + +async function createDevRequestHandler(initialBuild: ServerBuild) { + let build = initialBuild + async function handleServerUpdate() { + // 0. give the rebuild time to breathe + await new Promise((res) => setTimeout(res, 1000)) + + // 1. re-import the server build + build = await reimportServer() + + // 2. tell Remix that this app server is now up-to-date and ready + broadcastDevReady(build) + } + + const chokidar = await import('chokidar') + chokidar + .watch(VERSION_PATH, { ignoreInitial: true }) + .on('add', handleServerUpdate) + .on('change', handleServerUpdate) + + // wrap request handler to make sure its recreated with the latest build for every request + return async (req: express.Request, res: express.Response, next: express.NextFunction) => { + try { + return createRequestHandler({ + build: build, + mode: 'development', + })(req, res, next) + } catch (error) { + next(error) + } + } +} +async function reimportServer() { + const stat = fs.statSync(BUILD_PATH) + + // convert build path to URL for Windows compatibility with dynamic `import` + const BUILD_URL = url.pathToFileURL(BUILD_PATH).href + // use a timestamp query parameter to bust the import cache + return await import(BUILD_URL + '?t=' + stat.mtimeMs) +} + +const initialBuild = await reimportServer() + +const remixHandler = + environment.NODE_ENV === 'development' + ? await createDevRequestHandler(initialBuild) + : createRequestHandler({ build: initialBuild }) + +// ----------------------------------------------------------------------------- + +function proxy(originalRequest: express.Request, originalResponse: express.Response) { + let headers = new Headers() + + for (const [key, value] of Object.entries(originalRequest.headers)) { + // add headers to ignore here, with simple comparisons to make it faster than i.e. an array lookup + // NOTE! this should match the check in `proxy.server.ts`! + if (key !== 'host') { + headers.set(key, value as string) + } + } + + const proxyRequest = http.request( + { + // target the right server + protocol: originalRequest.protocol + ':', + host: environment.BACKEND_URL.hostname, + port: environment.BACKEND_URL.port, + + // proxy everything + path: originalRequest.originalUrl, + method: originalRequest.method, + headers: headers as unknown as http.OutgoingHttpHeaders, + }, + (proxyResponse) => { + originalResponse.writeHead(proxyResponse.statusCode!, proxyResponse.headers) + proxyResponse.pipe(originalResponse) + }, + ) + + originalRequest + .pipe(proxyRequest) + // if the request fails for any non-explicit reason (e.g. ERRCONNREFUSED), + // handle the error gracefully and return a common status code back to the client + .on('error', (err) => { + console.error('failed proxy request', err) + originalResponse.status(502).json({ error: 'Service temporarily unavailable' }) + }) +} + +const corsMiddleware = cors({ + origin: environment.EDITOR_URL, + credentials: true, +}) + +const app = express() + +app.disable('x-powered-by') + +// proxy middleware hooks +app.use('/authenticate', proxy) +app.use('/editor', proxy) +app.use('/hashed-assets.json', proxy) +app.use('/logout', proxy) +app.use('/p', proxy) +app.use('/project', proxy) +app.use('/share', proxy) +app.use('/sockjs-node', proxy) +app.use('/v1/javascript/packager', proxy) +app.use('/vscode', proxy) + +// other middlewares +app.use(corsMiddleware) + +// static files +app.use('/build', express.static('public/build', { immutable: true, maxAge: '1y' })) +app.use(express.static('public')) + +// remix handler +app.all('*', remixHandler) + +function listenCallback(portNumber: number) { + return () => { + console.log(asciiBanner) + console.log(`Express listening on http://localhost:${portNumber}`) + if (environment.NODE_ENV === 'development') { + broadcastDevReady(initialBuild) + } + } +} + +app.listen(environment.PORT, listenCallback(environment.PORT)) +if (environment.NODE_ENV === 'development') { + app.listen(environment.PORT + 1, listenCallback(environment.PORT + 1)) +} diff --git a/utopia-remix/tsconfig.json b/utopia-remix/tsconfig.json index 277e7dd11f5d..38a556d78cb1 100644 --- a/utopia-remix/tsconfig.json +++ b/utopia-remix/tsconfig.json @@ -12,6 +12,7 @@ "allowJs": true, "forceConsistentCasingInFileNames": true, "baseUrl": ".", + "module": "ESNext", "paths": { "~/*": ["./app/*"] }, From f1cc0d53e8b17855da8fba6b9962e4bffb9b1407 Mon Sep 17 00:00:00 2001 From: Liad Yosef Date: Tue, 19 Mar 2024 20:25:23 +0200 Subject: [PATCH 2/2] change chokidar --- utopia-remix/package.json | 2 +- utopia-remix/server.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/utopia-remix/package.json b/utopia-remix/package.json index c7b16a18ff1f..247f2ffe305e 100644 --- a/utopia-remix/package.json +++ b/utopia-remix/package.json @@ -4,7 +4,7 @@ "sideEffects": false, "type": "module", "scripts": { - "build": "pnpm run build:server && pnpm run build:remix", + "build": "pnpm run build:remix && pnpm run build:server", "build:server": "esbuild --platform=node --format=esm ./server.ts --outdir=./", "build:remix": "remix build", "dev": "remix dev -c \"npm run dev:server\" --manual", diff --git a/utopia-remix/server.ts b/utopia-remix/server.ts index da566905861c..af7f298155f2 100644 --- a/utopia-remix/server.ts +++ b/utopia-remix/server.ts @@ -9,6 +9,7 @@ import * as http from 'node:http' import * as path from 'node:path' import * as url from 'node:url' import sourceMapSupport from 'source-map-support' +import chokidar from 'chokidar' // To make sure everything keeps working and the server doesn't crash, if // there are any uncaught errors, log them out gracefully @@ -93,7 +94,6 @@ async function createDevRequestHandler(initialBuild: ServerBuild) { broadcastDevReady(build) } - const chokidar = await import('chokidar') chokidar .watch(VERSION_PATH, { ignoreInitial: true }) .on('add', handleServerUpdate)