diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 139d6c2..e5a35c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,12 @@ jobs: with: fetch-depth: 0 + - name: Setup Dotenv + run: | + echo "${{secrets.DOTENV_APP_WEB_DEV }}" > projects/app-web/.env.development.local + echo "${{secrets.DOTENV_APP_WEB_E2E }}" > projects/app-web-e2e/.env + echo "${{secrets.DOTENV_DB_POSTGRES }}" > projects/db-postgres/.env.production + - name: Setup Node uses: actions/setup-node@v3 with: @@ -76,9 +82,7 @@ jobs: - name: Deploy Postgres Migrations if: ${{ github.ref_name == 'main' && contains(steps.record-affected-projects.outputs.affected-projects, 'db-postgres') }} - run: | - echo "${{secrets.DOTENV_DB_POSTGRES }}" > projects/db-postgres/.env.production - yarn postgres:migrations-run:prod + run: yarn postgres:migrations-run:prod - name: Deploy API Service if: ${{ github.ref_name == 'main' && contains(steps.record-affected-projects.outputs.affected-projects, 'service-api') }} diff --git a/.gitignore b/.gitignore index 2233c7d..af245aa 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ testem.log # System Files .DS_Store Thumbs.db +*Zone.Identifier # caches .cache @@ -47,3 +48,5 @@ Thumbs.db # secrets projects/db-postgres/.env.production projects/service-*/.env.production +projects/app-web-e2e/.env +**/.env*.local diff --git a/.husky/pre-commit b/.husky/pre-commit index ad9c69f..f99738b 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1 @@ -yarn dlx lint-staged --concurrent false --relative \ No newline at end of file +yarn dlx lint-staged --concurrent false --relative --allow-empty \ No newline at end of file diff --git a/.pnp.cjs b/.pnp.cjs index acdae90..68d6d53 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -41,6 +41,7 @@ const RAW_RUNTIME_STATE = ["@graphql-tools/executor-http", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.0.9"],\ ["@graphql-typed-document-node/core", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.2.0"],\ ["@hono/node-server", "npm:1.10.0"],\ + ["@mswjs/data", "npm:0.16.1"],\ ["@nx/devkit", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.3.3"],\ ["@nx/esbuild", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.3.3"],\ ["@nx/eslint", "virtual:41cfb0d93d8f1f80cb47f3ad08355c786f8049206e268f2d7164dc0f5fe99e7f8c9c0fed5b3dd539eb6429bc94158ac9084e8291ac1c7be0f1f25182ce597da3#npm:18.3.3"],\ @@ -51,6 +52,7 @@ const RAW_RUNTIME_STATE = ["@nx/vite", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.3.3"],\ ["@nx/web", "npm:18.3.3"],\ ["@nx/workspace", "npm:18.3.3"],\ + ["@paralleldrive/cuid2", "npm:2.2.2"],\ ["@parcel/watcher", "npm:2.4.1"],\ ["@playwright/test", "npm:1.43.0"],\ ["@pothos/core", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.41.1"],\ @@ -58,28 +60,33 @@ const RAW_RUNTIME_STATE = ["@remix-run/node", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/serve", "npm:2.9.1"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/testing", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@swc-node/register", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.9.0"],\ ["@swc/cli", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:0.3.12"],\ ["@swc/core", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.4.13"],\ ["@swc/helpers", "npm:0.5.8"],\ ["@testcontainers/postgresql", "npm:10.9.0"],\ + ["@testing-library/dom", "npm:10.0.0"],\ ["@testing-library/jest-dom", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:6.4.2"],\ ["@testing-library/react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:14.3.0"],\ + ["@testing-library/user-event", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:14.5.2"],\ ["@types/jsonwebtoken", "npm:9.0.6"],\ ["@types/node", "npm:20.12.7"],\ ["@types/react", "npm:18.2.75"],\ ["@types/react-dom", "npm:18.2.24"],\ ["@types/react-is", "npm:18.2.4"],\ - ["@types/styled-components", "npm:5.1.34"],\ ["@typescript-eslint/eslint-plugin", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:7.6.0"],\ ["@typescript-eslint/parser", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:7.6.0"],\ ["@typescript-eslint/utils", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:7.7.1"],\ + ["@vanilla-extract/css", "npm:1.14.2"],\ + ["@vanilla-extract/sprinkles", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.6.1"],\ + ["@vanilla-extract/vite-plugin", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.0.7"],\ ["@vitejs/plugin-react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.2.1"],\ - ["@vitest/coverage-v8", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"],\ - ["@vitest/ui", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"],\ + ["@vitest/coverage-v8", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"],\ + ["@vitest/expect", "npm:1.5.2"],\ + ["@vitest/ui", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"],\ ["auth0", "npm:4.3.1"],\ - ["cuid", "npm:3.0.0"],\ ["drizzle-kit", "npm:0.20.17"],\ ["drizzle-orm", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:0.30.9"],\ ["envalid", "npm:8.0.0"],\ @@ -92,8 +99,11 @@ const RAW_RUNTIME_STATE = ["eslint-plugin-react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:7.34.1"],\ ["eslint-plugin-react-hooks", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.6.0"],\ ["eslint-plugin-unicorn", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:52.0.0"],\ + ["got", "npm:14.2.1"],\ ["graphql", "npm:16.8.1"],\ ["graphql-request", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:6.1.0"],\ + ["graphql-scalars", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.23.0"],\ + ["graphql-transform-scalars", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.2.1"],\ ["graphql-yoga", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:5.3.0"],\ ["happy-dom", "npm:14.7.1"],\ ["hono", "npm:4.2.4"],\ @@ -102,9 +112,11 @@ const RAW_RUNTIME_STATE = ["jest-extended", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.0.2"],\ ["jsonwebtoken", "npm:9.0.2"],\ ["jwks-rsa", "npm:3.1.0"],\ + ["jwt-decode", "npm:4.0.0"],\ ["lint-staged", "npm:15.2.2"],\ - ["mock-jwks", "npm:3.1.0"],\ + ["mock-jwks", "patch:mock-jwks@npm%3A3.1.0#~/.yarn/patches/mock-jwks-npm-3.1.0-131e3bbc29.patch::version=3.1.0&hash=3d08e1"],\ ["msw", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.2.14"],\ + ["node-mocks-http", "npm:1.14.1"],\ ["nx", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.3.3"],\ ["playwright", "npm:1.43.0"],\ ["postgres", "npm:3.4.4"],\ @@ -113,15 +125,21 @@ const RAW_RUNTIME_STATE = ["react-dom", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.2.0"],\ ["react-is", "npm:18.2.0"],\ ["react-router-dom", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:6.22.3"],\ + ["remix-auth", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.6.0"],\ + ["remix-auth-auth0", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.10.0"],\ + ["remix-auth-oauth2", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.11.2"],\ + ["remix-flat-routes", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:0.6.4"],\ ["remix-hono", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:0.0.16"],\ - ["styled-components", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:6.1.8"],\ ["tiny-invariant", "npm:1.3.3"],\ + ["tsconfig-paths", "npm:4.2.0"],\ ["tslib", "npm:2.6.2"],\ ["tsx", "npm:4.7.3"],\ + ["type-fest", "npm:4.17.0"],\ ["typescript", "patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c"],\ ["typescript-eslint", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:7.6.0"],\ + ["uuid", "npm:9.0.1"],\ ["vite", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:5.2.10"],\ - ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"]\ + ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"]\ ],\ "linkType": "SOFT"\ }]\ @@ -287,7 +305,7 @@ const RAW_RUNTIME_STATE = ["@babel/traverse", "npm:7.24.1"],\ ["@babel/types", "npm:7.24.0"],\ ["convert-source-map", "npm:2.0.0"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["gensync", "npm:1.0.0-beta.2"],\ ["json5", "npm:2.2.3"],\ ["semver", "npm:6.3.1"]\ @@ -414,7 +432,7 @@ const RAW_RUNTIME_STATE = ["@babel/helper-compilation-targets", "npm:7.23.6"],\ ["@babel/helper-plugin-utils", "npm:7.24.0"],\ ["@types/babel__core", null],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["lodash.debounce", "npm:4.0.8"],\ ["resolve", "patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d"]\ ],\ @@ -3193,7 +3211,7 @@ const RAW_RUNTIME_STATE = ["@babel/helper-split-export-declaration", "npm:7.22.6"],\ ["@babel/parser", "npm:7.24.4"],\ ["@babel/types", "npm:7.24.0"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["globals", "npm:11.12.0"]\ ],\ "linkType": "HARD"\ @@ -3264,6 +3282,7 @@ const RAW_RUNTIME_STATE = ["@graphql-tools/executor-http", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.0.9"],\ ["@graphql-typed-document-node/core", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.2.0"],\ ["@hono/node-server", "npm:1.10.0"],\ + ["@mswjs/data", "npm:0.16.1"],\ ["@nx/devkit", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.3.3"],\ ["@nx/esbuild", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.3.3"],\ ["@nx/eslint", "virtual:41cfb0d93d8f1f80cb47f3ad08355c786f8049206e268f2d7164dc0f5fe99e7f8c9c0fed5b3dd539eb6429bc94158ac9084e8291ac1c7be0f1f25182ce597da3#npm:18.3.3"],\ @@ -3274,6 +3293,7 @@ const RAW_RUNTIME_STATE = ["@nx/vite", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.3.3"],\ ["@nx/web", "npm:18.3.3"],\ ["@nx/workspace", "npm:18.3.3"],\ + ["@paralleldrive/cuid2", "npm:2.2.2"],\ ["@parcel/watcher", "npm:2.4.1"],\ ["@playwright/test", "npm:1.43.0"],\ ["@pothos/core", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.41.1"],\ @@ -3281,28 +3301,33 @@ const RAW_RUNTIME_STATE = ["@remix-run/node", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/serve", "npm:2.9.1"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/testing", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@swc-node/register", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.9.0"],\ ["@swc/cli", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:0.3.12"],\ ["@swc/core", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.4.13"],\ ["@swc/helpers", "npm:0.5.8"],\ ["@testcontainers/postgresql", "npm:10.9.0"],\ + ["@testing-library/dom", "npm:10.0.0"],\ ["@testing-library/jest-dom", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:6.4.2"],\ ["@testing-library/react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:14.3.0"],\ + ["@testing-library/user-event", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:14.5.2"],\ ["@types/jsonwebtoken", "npm:9.0.6"],\ ["@types/node", "npm:20.12.7"],\ ["@types/react", "npm:18.2.75"],\ ["@types/react-dom", "npm:18.2.24"],\ ["@types/react-is", "npm:18.2.4"],\ - ["@types/styled-components", "npm:5.1.34"],\ ["@typescript-eslint/eslint-plugin", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:7.6.0"],\ ["@typescript-eslint/parser", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:7.6.0"],\ ["@typescript-eslint/utils", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:7.7.1"],\ + ["@vanilla-extract/css", "npm:1.14.2"],\ + ["@vanilla-extract/sprinkles", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.6.1"],\ + ["@vanilla-extract/vite-plugin", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.0.7"],\ ["@vitejs/plugin-react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.2.1"],\ - ["@vitest/coverage-v8", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"],\ - ["@vitest/ui", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"],\ + ["@vitest/coverage-v8", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"],\ + ["@vitest/expect", "npm:1.5.2"],\ + ["@vitest/ui", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"],\ ["auth0", "npm:4.3.1"],\ - ["cuid", "npm:3.0.0"],\ ["drizzle-kit", "npm:0.20.17"],\ ["drizzle-orm", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:0.30.9"],\ ["envalid", "npm:8.0.0"],\ @@ -3315,8 +3340,11 @@ const RAW_RUNTIME_STATE = ["eslint-plugin-react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:7.34.1"],\ ["eslint-plugin-react-hooks", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.6.0"],\ ["eslint-plugin-unicorn", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:52.0.0"],\ + ["got", "npm:14.2.1"],\ ["graphql", "npm:16.8.1"],\ ["graphql-request", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:6.1.0"],\ + ["graphql-scalars", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.23.0"],\ + ["graphql-transform-scalars", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.2.1"],\ ["graphql-yoga", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:5.3.0"],\ ["happy-dom", "npm:14.7.1"],\ ["hono", "npm:4.2.4"],\ @@ -3325,9 +3353,11 @@ const RAW_RUNTIME_STATE = ["jest-extended", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.0.2"],\ ["jsonwebtoken", "npm:9.0.2"],\ ["jwks-rsa", "npm:3.1.0"],\ + ["jwt-decode", "npm:4.0.0"],\ ["lint-staged", "npm:15.2.2"],\ - ["mock-jwks", "npm:3.1.0"],\ + ["mock-jwks", "patch:mock-jwks@npm%3A3.1.0#~/.yarn/patches/mock-jwks-npm-3.1.0-131e3bbc29.patch::version=3.1.0&hash=3d08e1"],\ ["msw", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.2.14"],\ + ["node-mocks-http", "npm:1.14.1"],\ ["nx", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.3.3"],\ ["playwright", "npm:1.43.0"],\ ["postgres", "npm:3.4.4"],\ @@ -3336,15 +3366,21 @@ const RAW_RUNTIME_STATE = ["react-dom", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.2.0"],\ ["react-is", "npm:18.2.0"],\ ["react-router-dom", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:6.22.3"],\ + ["remix-auth", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.6.0"],\ + ["remix-auth-auth0", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.10.0"],\ + ["remix-auth-oauth2", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.11.2"],\ + ["remix-flat-routes", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:0.6.4"],\ ["remix-hono", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:0.0.16"],\ - ["styled-components", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:6.1.8"],\ ["tiny-invariant", "npm:1.3.3"],\ + ["tsconfig-paths", "npm:4.2.0"],\ ["tslib", "npm:2.6.2"],\ ["tsx", "npm:4.7.3"],\ + ["type-fest", "npm:4.17.0"],\ ["typescript", "patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c"],\ ["typescript-eslint", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:7.6.0"],\ + ["uuid", "npm:9.0.1"],\ ["vite", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:5.2.10"],\ - ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"]\ + ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"]\ ],\ "linkType": "SOFT"\ }]\ @@ -3616,34 +3652,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@emotion/is-prop-valid", [\ - ["npm:1.2.1", {\ - "packageLocation": "./.yarn/cache/@emotion-is-prop-valid-npm-1.2.1-794afe6a94-7c2aabdf0c.zip/node_modules/@emotion/is-prop-valid/",\ - "packageDependencies": [\ - ["@emotion/is-prop-valid", "npm:1.2.1"],\ - ["@emotion/memoize", "npm:0.8.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ - ["@emotion/memoize", [\ - ["npm:0.8.1", {\ - "packageLocation": "./.yarn/cache/@emotion-memoize-npm-0.8.1-9b1e35ff15-dffed372fc.zip/node_modules/@emotion/memoize/",\ - "packageDependencies": [\ - ["@emotion/memoize", "npm:0.8.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ - ["@emotion/unitless", [\ - ["npm:0.8.0", {\ - "packageLocation": "./.yarn/cache/@emotion-unitless-npm-0.8.0-aa125284fa-1f2cfb7c0c.zip/node_modules/@emotion/unitless/",\ - "packageDependencies": [\ - ["@emotion/unitless", "npm:0.8.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@envelop/core", [\ ["npm:5.0.0", {\ "packageLocation": "./.yarn/cache/@envelop-core-npm-5.0.0-262546b302-abc0658517.zip/node_modules/@envelop/core/",\ @@ -4415,7 +4423,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@eslint/eslintrc", "npm:2.1.4"],\ ["ajv", "npm:6.12.6"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["espree", "npm:9.6.1"],\ ["globals", "npm:13.24.0"],\ ["ignore", "npm:5.3.1"],\ @@ -4431,7 +4439,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@eslint/eslintrc", "npm:3.0.2"],\ ["ajv", "npm:6.12.6"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["espree", "npm:10.0.1"],\ ["globals", "npm:14.0.0"],\ ["ignore", "npm:5.3.1"],\ @@ -5332,7 +5340,7 @@ const RAW_RUNTIME_STATE = ["@types/json-stable-stringify", "npm:1.0.36"],\ ["@whatwg-node/fetch", "npm:0.9.17"],\ ["chalk", "npm:4.1.2"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["dotenv", "npm:16.4.5"],\ ["graphql", "npm:16.8.1"],\ ["graphql-request", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:6.1.0"],\ @@ -5620,7 +5628,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@humanwhocodes/config-array", "npm:0.11.14"],\ ["@humanwhocodes/object-schema", "npm:2.0.3"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["minimatch", "npm:3.1.2"]\ ],\ "linkType": "HARD"\ @@ -5630,7 +5638,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@humanwhocodes/config-array", "npm:0.12.3"],\ ["@humanwhocodes/object-schema", "npm:2.0.3"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["minimatch", "npm:3.1.2"]\ ],\ "linkType": "HARD"\ @@ -6114,15 +6122,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@mswjs/cookies", [\ - ["npm:0.2.2", {\ - "packageLocation": "./.yarn/cache/@mswjs-cookies-npm-0.2.2-fdd3f4ab67-f950062538.zip/node_modules/@mswjs/cookies/",\ - "packageDependencies": [\ - ["@mswjs/cookies", "npm:0.2.2"],\ - ["@types/set-cookie-parser", "npm:2.4.7"],\ - ["set-cookie-parser", "npm:2.6.0"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:1.1.0", {\ "packageLocation": "./.yarn/cache/@mswjs-cookies-npm-1.1.0-a9e9053518-c8442b77f4.zip/node_modules/@mswjs/cookies/",\ "packageDependencies": [\ @@ -6131,22 +6130,30 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@mswjs/interceptors", [\ - ["npm:0.17.10", {\ - "packageLocation": "./.yarn/cache/@mswjs-interceptors-npm-0.17.10-c1199a9424-0343a93711.zip/node_modules/@mswjs/interceptors/",\ + ["@mswjs/data", [\ + ["npm:0.16.1", {\ + "packageLocation": "./.yarn/cache/@mswjs-data-npm-0.16.1-e80ee691e1-9518f5e918.zip/node_modules/@mswjs/data/",\ "packageDependencies": [\ - ["@mswjs/interceptors", "npm:0.17.10"],\ - ["@open-draft/until", "npm:1.0.3"],\ - ["@types/debug", "npm:4.1.12"],\ - ["@xmldom/xmldom", "npm:0.8.10"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ - ["headers-polyfill", "npm:3.2.5"],\ + ["@mswjs/data", "npm:0.16.1"],\ + ["@types/lodash", "npm:4.17.0"],\ + ["@types/md5", "npm:2.3.5"],\ + ["@types/pluralize", "npm:0.0.29"],\ + ["@types/uuid", "npm:8.3.4"],\ + ["date-fns", "npm:2.30.0"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ + ["graphql", "npm:16.8.1"],\ + ["lodash", "npm:4.17.21"],\ + ["md5", "npm:2.3.0"],\ + ["msw", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:2.2.14"],\ ["outvariant", "npm:1.4.2"],\ - ["strict-event-emitter", "npm:0.2.8"],\ - ["web-encoding", "npm:1.1.5"]\ + ["pluralize", "npm:8.0.0"],\ + ["strict-event-emitter", "npm:0.5.1"],\ + ["uuid", "npm:8.3.2"]\ ],\ "linkType": "HARD"\ - }],\ + }]\ + ]],\ + ["@mswjs/interceptors", [\ ["npm:0.26.15", {\ "packageLocation": "./.yarn/cache/@mswjs-interceptors-npm-0.26.15-0819076884-378c4b14ad.zip/node_modules/@mswjs/interceptors/",\ "packageDependencies": [\ @@ -6161,6 +6168,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@noble/hashes", [\ + ["npm:1.4.0", {\ + "packageLocation": "./.yarn/cache/@noble-hashes-npm-1.4.0-9389282fd6-8c3f005ee7.zip/node_modules/@noble/hashes/",\ + "packageDependencies": [\ + ["@noble/hashes", "npm:1.4.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@nodelib/fs.scandir", [\ ["npm:2.1.5", {\ "packageLocation": "./.yarn/cache/@nodelib-fs.scandir-npm-2.1.5-89c67370dd-732c3b6d1b.zip/node_modules/@nodelib/fs.scandir/",\ @@ -6796,7 +6812,7 @@ const RAW_RUNTIME_STATE = ["enquirer", "npm:2.3.6"],\ ["tsconfig-paths", "npm:4.2.0"],\ ["vite", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:5.2.10"],\ - ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"]\ + ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"]\ ],\ "packagePeers": [\ "@types/vite",\ @@ -6820,7 +6836,7 @@ const RAW_RUNTIME_STATE = ["enquirer", "npm:2.3.6"],\ ["tsconfig-paths", "npm:4.2.0"],\ ["vite", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:5.2.10"],\ - ["vitest", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:1.5.1"]\ + ["vitest", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:1.5.2"]\ ],\ "packagePeers": [\ "@types/vite",\ @@ -6884,13 +6900,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@open-draft/until", [\ - ["npm:1.0.3", {\ - "packageLocation": "./.yarn/cache/@open-draft-until-npm-1.0.3-c0d6a46a29-f88bcd774b.zip/node_modules/@open-draft/until/",\ - "packageDependencies": [\ - ["@open-draft/until", "npm:1.0.3"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:2.1.0", {\ "packageLocation": "./.yarn/cache/@open-draft-until-npm-2.1.0-e27da33c52-61d3f99718.zip/node_modules/@open-draft/until/",\ "packageDependencies": [\ @@ -6899,6 +6908,16 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@paralleldrive/cuid2", [\ + ["npm:2.2.2", {\ + "packageLocation": "./.yarn/cache/@paralleldrive-cuid2-npm-2.2.2-e6061749b2-af5826df93.zip/node_modules/@paralleldrive/cuid2/",\ + "packageDependencies": [\ + ["@paralleldrive/cuid2", "npm:2.2.2"],\ + ["@noble/hashes", "npm:1.4.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@parcel/watcher", [\ ["npm:2.4.1", {\ "packageLocation": "./.yarn/cache/@parcel-watcher-npm-2.4.1-2b3c6bb4aa-33b7112094.zip/node_modules/@parcel/watcher/",\ @@ -7168,7 +7187,7 @@ const RAW_RUNTIME_STATE = ["@remix-run/react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/router", "npm:1.16.0"],\ ["@remix-run/serve", "npm:2.9.1"],\ - ["@remix-run/server-runtime", "virtual:671118d6e1f8aff5a14828b7fd7c6c6de0ff60c5c6a46b04abba12efbb497e3fbef80c3b676276352b3ed3ddb86862b639b5bff86bfcec745927cc8a9ee657f0#npm:2.9.1"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@types/mdx", "npm:2.0.13"],\ ["@types/remix-run__react", null],\ ["@types/remix-run__serve", null],\ @@ -7250,7 +7269,7 @@ const RAW_RUNTIME_STATE = ["@remix-run/react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/router", "npm:1.16.0"],\ ["@remix-run/serve", null],\ - ["@remix-run/server-runtime", "virtual:671118d6e1f8aff5a14828b7fd7c6c6de0ff60c5c6a46b04abba12efbb497e3fbef80c3b676276352b3ed3ddb86862b639b5bff86bfcec745927cc8a9ee657f0#npm:2.9.1"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@types/mdx", "npm:2.0.13"],\ ["@types/remix-run__react", null],\ ["@types/remix-run__serve", null],\ @@ -7354,7 +7373,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/__virtual__/@remix-run-node-virtual-b379f8bc63/0/cache/@remix-run-node-npm-2.9.1-e4d6090eb4-e8a3869998.zip/node_modules/@remix-run/node/",\ "packageDependencies": [\ ["@remix-run/node", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ - ["@remix-run/server-runtime", "virtual:671118d6e1f8aff5a14828b7fd7c6c6de0ff60c5c6a46b04abba12efbb497e3fbef80c3b676276352b3ed3ddb86862b639b5bff86bfcec745927cc8a9ee657f0#npm:2.9.1"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/web-fetch", "npm:4.4.2"],\ ["@types/typescript", null],\ ["@web3-storage/multipart-parser", "npm:1.0.0"],\ @@ -7404,7 +7423,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@remix-run/react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/router", "npm:1.16.0"],\ - ["@remix-run/server-runtime", "virtual:671118d6e1f8aff5a14828b7fd7c6c6de0ff60c5c6a46b04abba12efbb497e3fbef80c3b676276352b3ed3ddb86862b639b5bff86bfcec745927cc8a9ee657f0#npm:2.9.1"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@types/react", "npm:18.2.75"],\ ["@types/react-dom", "npm:18.2.24"],\ ["@types/typescript", null],\ @@ -7430,7 +7449,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["@remix-run/react", "virtual:8357736ef134b7863f91d42eddce98478ba946d8fa91d035087f581e8019ab4c100fd43e82438b7deae8c5c6a0342e97150e5a38e5a30c47f1258390b04d764a#npm:2.9.1"],\ ["@remix-run/router", "npm:1.16.0"],\ - ["@remix-run/server-runtime", "virtual:671118d6e1f8aff5a14828b7fd7c6c6de0ff60c5c6a46b04abba12efbb497e3fbef80c3b676276352b3ed3ddb86862b639b5bff86bfcec745927cc8a9ee657f0#npm:2.9.1"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@types/react", "npm:18.2.75"],\ ["@types/react-dom", null],\ ["@types/typescript", null],\ @@ -7500,18 +7519,19 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:5c7fe6728d933369472b327a3b9ce7cea28aa44fd0918a7fec242784a51f6fa9f70e7bddab7fe6e24b00373fc044c5d30e789bba3f42502e81da90a6edc7106d#npm:2.8.1", {\ - "packageLocation": "./.yarn/__virtual__/@remix-run-server-runtime-virtual-98586feb2a/0/cache/@remix-run-server-runtime-npm-2.8.1-f97405752d-68386ab092.zip/node_modules/@remix-run/server-runtime/",\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1", {\ + "packageLocation": "./.yarn/__virtual__/@remix-run-server-runtime-virtual-a9fe4b7a4e/0/cache/@remix-run-server-runtime-npm-2.9.1-49c29e8df2-941329c6a7.zip/node_modules/@remix-run/server-runtime/",\ "packageDependencies": [\ - ["@remix-run/server-runtime", "virtual:5c7fe6728d933369472b327a3b9ce7cea28aa44fd0918a7fec242784a51f6fa9f70e7bddab7fe6e24b00373fc044c5d30e789bba3f42502e81da90a6edc7106d#npm:2.8.1"],\ - ["@remix-run/router", "npm:1.15.3"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ + ["@remix-run/router", "npm:1.16.0"],\ ["@types/cookie", "npm:0.6.0"],\ ["@types/typescript", null],\ ["@web3-storage/multipart-parser", "npm:1.0.0"],\ ["cookie", "npm:0.6.0"],\ ["set-cookie-parser", "npm:2.6.0"],\ ["source-map", "npm:0.7.4"],\ - ["typescript", null]\ + ["turbo-stream", "npm:2.0.0"],\ + ["typescript", "patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c"]\ ],\ "packagePeers": [\ "@types/typescript",\ @@ -7519,19 +7539,18 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:671118d6e1f8aff5a14828b7fd7c6c6de0ff60c5c6a46b04abba12efbb497e3fbef80c3b676276352b3ed3ddb86862b639b5bff86bfcec745927cc8a9ee657f0#npm:2.9.1", {\ - "packageLocation": "./.yarn/__virtual__/@remix-run-server-runtime-virtual-747de1c98f/0/cache/@remix-run-server-runtime-npm-2.9.1-49c29e8df2-941329c6a7.zip/node_modules/@remix-run/server-runtime/",\ + ["virtual:5c7fe6728d933369472b327a3b9ce7cea28aa44fd0918a7fec242784a51f6fa9f70e7bddab7fe6e24b00373fc044c5d30e789bba3f42502e81da90a6edc7106d#npm:2.8.1", {\ + "packageLocation": "./.yarn/__virtual__/@remix-run-server-runtime-virtual-98586feb2a/0/cache/@remix-run-server-runtime-npm-2.8.1-f97405752d-68386ab092.zip/node_modules/@remix-run/server-runtime/",\ "packageDependencies": [\ - ["@remix-run/server-runtime", "virtual:671118d6e1f8aff5a14828b7fd7c6c6de0ff60c5c6a46b04abba12efbb497e3fbef80c3b676276352b3ed3ddb86862b639b5bff86bfcec745927cc8a9ee657f0#npm:2.9.1"],\ - ["@remix-run/router", "npm:1.16.0"],\ + ["@remix-run/server-runtime", "virtual:5c7fe6728d933369472b327a3b9ce7cea28aa44fd0918a7fec242784a51f6fa9f70e7bddab7fe6e24b00373fc044c5d30e789bba3f42502e81da90a6edc7106d#npm:2.8.1"],\ + ["@remix-run/router", "npm:1.15.3"],\ ["@types/cookie", "npm:0.6.0"],\ ["@types/typescript", null],\ ["@web3-storage/multipart-parser", "npm:1.0.0"],\ ["cookie", "npm:0.6.0"],\ ["set-cookie-parser", "npm:2.6.0"],\ ["source-map", "npm:0.7.4"],\ - ["turbo-stream", "npm:2.0.0"],\ - ["typescript", "patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c"]\ + ["typescript", null]\ ],\ "packagePeers": [\ "@types/typescript",\ @@ -7590,6 +7609,43 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@remix-run/v1-route-convention", [\ + ["npm:0.1.4", {\ + "packageLocation": "./.yarn/cache/@remix-run-v1-route-convention-npm-0.1.4-d336e45418-f9984d9212.zip/node_modules/@remix-run/v1-route-convention/",\ + "packageDependencies": [\ + ["@remix-run/v1-route-convention", "npm:0.1.4"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:61f03cbbff78bf8d18a7331382e9626bcfb3b250f8b5bb18d7b79cba6fb51b5e3d83764aa3051e3658908bb6641b40c15523c34f836b9e77d7e987d154b51c23#npm:0.1.4", {\ + "packageLocation": "./.yarn/__virtual__/@remix-run-v1-route-convention-virtual-4adb1ce454/0/cache/@remix-run-v1-route-convention-npm-0.1.4-d336e45418-f9984d9212.zip/node_modules/@remix-run/v1-route-convention/",\ + "packageDependencies": [\ + ["@remix-run/v1-route-convention", "virtual:61f03cbbff78bf8d18a7331382e9626bcfb3b250f8b5bb18d7b79cba6fb51b5e3d83764aa3051e3658908bb6641b40c15523c34f836b9e77d7e987d154b51c23#npm:0.1.4"],\ + ["@remix-run/dev", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ + ["@types/remix-run__dev", null],\ + ["minimatch", "npm:7.4.6"]\ + ],\ + "packagePeers": [\ + "@remix-run/dev",\ + "@types/remix-run__dev"\ + ],\ + "linkType": "HARD"\ + }],\ + ["virtual:68459c0c85ca646a10107f3b38fc63a47b5e64300cc2d9f9db6462a01903420a230bcd21782478dd7bf9d012e6865f9e42c01dc797fc4756d6e7ee83ffb7802e#npm:0.1.4", {\ + "packageLocation": "./.yarn/__virtual__/@remix-run-v1-route-convention-virtual-4a9d0ff1ed/0/cache/@remix-run-v1-route-convention-npm-0.1.4-d336e45418-f9984d9212.zip/node_modules/@remix-run/v1-route-convention/",\ + "packageDependencies": [\ + ["@remix-run/v1-route-convention", "virtual:68459c0c85ca646a10107f3b38fc63a47b5e64300cc2d9f9db6462a01903420a230bcd21782478dd7bf9d012e6865f9e42c01dc797fc4756d6e7ee83ffb7802e#npm:0.1.4"],\ + ["@remix-run/dev", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:2.9.1"],\ + ["@types/remix-run__dev", null],\ + ["minimatch", "npm:7.4.6"]\ + ],\ + "packagePeers": [\ + "@remix-run/dev",\ + "@types/remix-run__dev"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@remix-run/web-blob", [\ ["npm:3.1.0", {\ "packageLocation": "./.yarn/cache/@remix-run-web-blob-npm-3.1.0-933a5434f2-045796faca.zip/node_modules/@remix-run/web-blob/",\ @@ -7808,6 +7864,13 @@ const RAW_RUNTIME_STATE = ["@sindresorhus/is", "npm:4.6.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:6.3.0", {\ + "packageLocation": "./.yarn/cache/@sindresorhus-is-npm-6.3.0-0c6ba20d57-40d201fc1a.zip/node_modules/@sindresorhus/is/",\ + "packageDependencies": [\ + ["@sindresorhus/is", "npm:6.3.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@sinonjs/commons", [\ @@ -8173,7 +8236,7 @@ const RAW_RUNTIME_STATE = ["@types/swc__core", null],\ ["@types/typescript", null],\ ["colorette", "npm:2.0.20"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["pirates", "npm:4.0.6"],\ ["tslib", "npm:2.6.2"],\ ["typescript", "patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c"]\ @@ -8394,6 +8457,14 @@ const RAW_RUNTIME_STATE = ["defer-to-connect", "npm:2.0.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:5.0.1", {\ + "packageLocation": "./.yarn/cache/@szmarczak-http-timer-npm-5.0.1-52261e5986-4629d2fbb2.zip/node_modules/@szmarczak/http-timer/",\ + "packageDependencies": [\ + ["@szmarczak/http-timer", "npm:5.0.1"],\ + ["defer-to-connect", "npm:2.0.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@testcontainers/postgresql", [\ @@ -8407,6 +8478,21 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@testing-library/dom", [\ + ["npm:10.0.0", {\ + "packageLocation": "./.yarn/cache/@testing-library-dom-npm-10.0.0-708b4ef7e6-2d12d2a601.zip/node_modules/@testing-library/dom/",\ + "packageDependencies": [\ + ["@testing-library/dom", "npm:10.0.0"],\ + ["@babel/code-frame", "npm:7.24.2"],\ + ["@babel/runtime", "npm:7.24.4"],\ + ["@types/aria-query", "npm:5.0.4"],\ + ["aria-query", "npm:5.3.0"],\ + ["chalk", "npm:4.1.2"],\ + ["dom-accessibility-api", "npm:0.5.16"],\ + ["lz-string", "npm:1.5.0"],\ + ["pretty-format", "npm:27.5.1"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:9.3.4", {\ "packageLocation": "./.yarn/cache/@testing-library-dom-npm-9.3.4-cfb609c4fc-147da340e8.zip/node_modules/@testing-library/dom/",\ "packageDependencies": [\ @@ -8449,7 +8535,7 @@ const RAW_RUNTIME_STATE = ["jest", null],\ ["lodash", "npm:4.17.21"],\ ["redent", "npm:3.0.0"],\ - ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"]\ + ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"]\ ],\ "packagePeers": [\ "@jest/globals",\ @@ -8480,7 +8566,7 @@ const RAW_RUNTIME_STATE = ["jest", null],\ ["lodash", "npm:4.17.21"],\ ["redent", "npm:3.0.0"],\ - ["vitest", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:1.5.1"]\ + ["vitest", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:1.5.2"]\ ],\ "packagePeers": [\ "@jest/globals",\ @@ -8522,6 +8608,28 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@testing-library/user-event", [\ + ["npm:14.5.2", {\ + "packageLocation": "./.yarn/cache/@testing-library-user-event-npm-14.5.2-ec9587901c-68a0c2aa28.zip/node_modules/@testing-library/user-event/",\ + "packageDependencies": [\ + ["@testing-library/user-event", "npm:14.5.2"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:14.5.2", {\ + "packageLocation": "./.yarn/__virtual__/@testing-library-user-event-virtual-72c2f4cb94/0/cache/@testing-library-user-event-npm-14.5.2-ec9587901c-68a0c2aa28.zip/node_modules/@testing-library/user-event/",\ + "packageDependencies": [\ + ["@testing-library/user-event", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:14.5.2"],\ + ["@testing-library/dom", "npm:10.0.0"],\ + ["@types/testing-library__dom", null]\ + ],\ + "packagePeers": [\ + "@testing-library/dom",\ + "@types/testing-library__dom"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@tokenizer/token", [\ ["npm:0.3.0", {\ "packageLocation": "./.yarn/cache/@tokenizer-token-npm-0.3.0-4441352cc5-7ab9a822d4.zip/node_modules/@tokenizer/token/",\ @@ -8685,13 +8793,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@types/cookie", [\ - ["npm:0.4.1", {\ - "packageLocation": "./.yarn/cache/@types-cookie-npm-0.4.1-274a704dc6-f96afe12bd.zip/node_modules/@types/cookie/",\ - "packageDependencies": [\ - ["@types/cookie", "npm:0.4.1"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:0.6.0", {\ "packageLocation": "./.yarn/cache/@types-cookie-npm-0.6.0-1f4c3f48f0-5b326bd018.zip/node_modules/@types/cookie/",\ "packageDependencies": [\ @@ -8798,17 +8899,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@types/hoist-non-react-statics", [\ - ["npm:3.3.5", {\ - "packageLocation": "./.yarn/cache/@types-hoist-non-react-statics-npm-3.3.5-98b8d8e47b-2a3b64bf3d.zip/node_modules/@types/hoist-non-react-statics/",\ - "packageDependencies": [\ - ["@types/hoist-non-react-statics", "npm:3.3.5"],\ - ["@types/react", "npm:18.2.75"],\ - ["hoist-non-react-statics", "npm:3.3.2"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@types/http-cache-semantics", [\ ["npm:4.0.4", {\ "packageLocation": "./.yarn/cache/@types-http-cache-semantics-npm-4.0.4-6d4f413ddd-51b72568b4.zip/node_modules/@types/http-cache-semantics/",\ @@ -8856,15 +8946,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@types/js-levenshtein", [\ - ["npm:1.1.3", {\ - "packageLocation": "./.yarn/cache/@types-js-levenshtein-npm-1.1.3-417b5f0c21-025f2bd8d8.zip/node_modules/@types/js-levenshtein/",\ - "packageDependencies": [\ - ["@types/js-levenshtein", "npm:1.1.3"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@types/js-yaml", [\ ["npm:4.0.9", {\ "packageLocation": "./.yarn/cache/@types-js-yaml-npm-4.0.9-6a16d01bd2-24de857aa8.zip/node_modules/@types/js-yaml/",\ @@ -8912,6 +8993,24 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@types/lodash", [\ + ["npm:4.17.0", {\ + "packageLocation": "./.yarn/cache/@types-lodash-npm-4.17.0-11e757616b-4c5b41c9a6.zip/node_modules/@types/lodash/",\ + "packageDependencies": [\ + ["@types/lodash", "npm:4.17.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/md5", [\ + ["npm:2.3.5", {\ + "packageLocation": "./.yarn/cache/@types-md5-npm-2.3.5-bd5c825c57-aef9c40ab0.zip/node_modules/@types/md5/",\ + "packageDependencies": [\ + ["@types/md5", "npm:2.3.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/mdast", [\ ["npm:3.0.15", {\ "packageLocation": "./.yarn/cache/@types-mdast-npm-3.0.15-66e5bbbc2b-fcbf716c03.zip/node_modules/@types/mdast/",\ @@ -8995,6 +9094,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@types/pluralize", [\ + ["npm:0.0.29", {\ + "packageLocation": "./.yarn/cache/@types-pluralize-npm-0.0.29-a6b8916fba-840796fa1d.zip/node_modules/@types/pluralize/",\ + "packageDependencies": [\ + ["@types/pluralize", "npm:0.0.29"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/prop-types", [\ ["npm:15.7.12", {\ "packageLocation": "./.yarn/cache/@types-prop-types-npm-15.7.12-b093f43531-1babcc7db6.zip/node_modules/@types/prop-types/",\ @@ -9095,16 +9203,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@types/set-cookie-parser", [\ - ["npm:2.4.7", {\ - "packageLocation": "./.yarn/cache/@types-set-cookie-parser-npm-2.4.7-e9d6d979b1-3c4b5168fe.zip/node_modules/@types/set-cookie-parser/",\ - "packageDependencies": [\ - ["@types/set-cookie-parser", "npm:2.4.7"],\ - ["@types/node", "npm:20.12.7"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@types/ssh2", [\ ["npm:0.5.52", {\ "packageLocation": "./.yarn/cache/@types-ssh2-npm-0.5.52-db874bb656-95c52fd343.zip/node_modules/@types/ssh2/",\ @@ -9152,27 +9250,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@types/styled-components", [\ - ["npm:5.1.34", {\ - "packageLocation": "./.yarn/cache/@types-styled-components-npm-5.1.34-c1fd4bac77-5bce93ea2c.zip/node_modules/@types/styled-components/",\ - "packageDependencies": [\ - ["@types/styled-components", "npm:5.1.34"],\ - ["@types/hoist-non-react-statics", "npm:3.3.5"],\ - ["@types/react", "npm:18.2.75"],\ - ["csstype", "npm:3.1.3"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ - ["@types/stylis", [\ - ["npm:4.2.0", {\ - "packageLocation": "./.yarn/cache/@types-stylis-npm-4.2.0-5addc9ed60-c76c13e76c.zip/node_modules/@types/stylis/",\ - "packageDependencies": [\ - ["@types/stylis", "npm:4.2.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@types/triple-beam", [\ ["npm:1.3.5", {\ "packageLocation": "./.yarn/cache/@types-triple-beam-npm-1.3.5-0f1b823630-d5d7f25da6.zip/node_modules/@types/triple-beam/",\ @@ -9191,6 +9268,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@types/uuid", [\ + ["npm:8.3.4", {\ + "packageLocation": "./.yarn/cache/@types-uuid-npm-8.3.4-7547f4402c-b9ac98f82f.zip/node_modules/@types/uuid/",\ + "packageDependencies": [\ + ["@types/uuid", "npm:8.3.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/wrap-ansi", [\ ["npm:3.0.0", {\ "packageLocation": "./.yarn/cache/@types-wrap-ansi-npm-3.0.0-b7f3369360-8d8f53363f.zip/node_modules/@types/wrap-ansi/",\ @@ -9250,7 +9336,7 @@ const RAW_RUNTIME_STATE = ["@typescript-eslint/type-utils", "virtual:28e51baebb53225c5255229d4f92ebf4d4f79a69653ac13cdd1625f5127c18ba297508fd79daf80ea63b60eebee2c016c979b2f6475015cce6587544d65679f3#npm:7.6.0"],\ ["@typescript-eslint/utils", "virtual:28e51baebb53225c5255229d4f92ebf4d4f79a69653ac13cdd1625f5127c18ba297508fd79daf80ea63b60eebee2c016c979b2f6475015cce6587544d65679f3#npm:7.6.0"],\ ["@typescript-eslint/visitor-keys", "npm:7.6.0"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["eslint", "npm:9.0.0"],\ ["graphemer", "npm:1.4.0"],\ ["ignore", "npm:5.3.1"],\ @@ -9288,7 +9374,7 @@ const RAW_RUNTIME_STATE = ["@typescript-eslint/types", "npm:7.6.0"],\ ["@typescript-eslint/typescript-estree", "virtual:26f248b18dbe434d67d4ff7b46468bbb50a4d9ecc7355ab54a03b11de157910552dba84f99df7324f5098283431cc5f5c692c3d246a62985eb59cbd0f5eec812#npm:7.6.0"],\ ["@typescript-eslint/visitor-keys", "npm:7.6.0"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["eslint", "npm:9.0.0"],\ ["typescript", "patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c"]\ ],\ @@ -9337,7 +9423,7 @@ const RAW_RUNTIME_STATE = ["@types/typescript", null],\ ["@typescript-eslint/typescript-estree", "virtual:26f248b18dbe434d67d4ff7b46468bbb50a4d9ecc7355ab54a03b11de157910552dba84f99df7324f5098283431cc5f5c692c3d246a62985eb59cbd0f5eec812#npm:7.6.0"],\ ["@typescript-eslint/utils", "virtual:28e51baebb53225c5255229d4f92ebf4d4f79a69653ac13cdd1625f5127c18ba297508fd79daf80ea63b60eebee2c016c979b2f6475015cce6587544d65679f3#npm:7.6.0"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["eslint", "npm:9.0.0"],\ ["ts-api-utils", "virtual:28e51baebb53225c5255229d4f92ebf4d4f79a69653ac13cdd1625f5127c18ba297508fd79daf80ea63b60eebee2c016c979b2f6475015cce6587544d65679f3#npm:1.3.0"],\ ["typescript", "patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c"]\ @@ -9389,7 +9475,7 @@ const RAW_RUNTIME_STATE = ["@types/typescript", null],\ ["@typescript-eslint/types", "npm:7.7.1"],\ ["@typescript-eslint/visitor-keys", "npm:7.7.1"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["globby", "npm:11.1.0"],\ ["is-glob", "npm:4.0.3"],\ ["minimatch", "npm:9.0.4"],\ @@ -9410,7 +9496,7 @@ const RAW_RUNTIME_STATE = ["@types/typescript", null],\ ["@typescript-eslint/types", "npm:7.6.0"],\ ["@typescript-eslint/visitor-keys", "npm:7.6.0"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["globby", "npm:11.1.0"],\ ["is-glob", "npm:4.0.3"],\ ["minimatch", "npm:9.0.4"],\ @@ -9431,7 +9517,7 @@ const RAW_RUNTIME_STATE = ["@types/typescript", null],\ ["@typescript-eslint/types", "npm:7.6.0"],\ ["@typescript-eslint/visitor-keys", "npm:7.6.0"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["globby", "npm:11.1.0"],\ ["is-glob", "npm:4.0.3"],\ ["minimatch", "npm:9.0.4"],\ @@ -9581,6 +9667,26 @@ const RAW_RUNTIME_STATE = ["vite-node", "npm:1.5.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.1.2", {\ + "packageLocation": "./.yarn/cache/@vanilla-extract-integration-npm-7.1.2-fadf75bb6c-c4bb99d3ca.zip/node_modules/@vanilla-extract/integration/",\ + "packageDependencies": [\ + ["@vanilla-extract/integration", "npm:7.1.2"],\ + ["@babel/core", "npm:7.24.4"],\ + ["@babel/plugin-syntax-typescript", "virtual:5537aa75a0f56c37db7b98e1ccb9e64f7d3c5ed71c00ad7c534074d67f055813f8680164af56426c752632bfe9a61d35552fc0af1c65c545845b96f1da717dc1#npm:7.24.1"],\ + ["@vanilla-extract/babel-plugin-debug-ids", "npm:1.0.5"],\ + ["@vanilla-extract/css", "npm:1.14.2"],\ + ["esbuild", "npm:0.19.12"],\ + ["eval", "npm:0.1.8"],\ + ["find-up", "npm:5.0.0"],\ + ["javascript-stringify", "npm:2.1.0"],\ + ["lodash", "npm:4.17.21"],\ + ["mlly", "npm:1.6.1"],\ + ["outdent", "npm:0.8.0"],\ + ["vite", "virtual:f9483072b2353c1fbd838417066556018bdd2c3c9dc66c6cefdbefdbe6c382cfbb0a4c3b83ce4906c7fcb73d4a8b3d536837e9cf85c7902cf57216360d194b8e#npm:5.2.10"],\ + ["vite-node", "npm:1.5.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@vanilla-extract/private", [\ @@ -9592,6 +9698,51 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@vanilla-extract/sprinkles", [\ + ["npm:1.6.1", {\ + "packageLocation": "./.yarn/cache/@vanilla-extract-sprinkles-npm-1.6.1-e524ee399f-7ddd2ab7c8.zip/node_modules/@vanilla-extract/sprinkles/",\ + "packageDependencies": [\ + ["@vanilla-extract/sprinkles", "npm:1.6.1"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.6.1", {\ + "packageLocation": "./.yarn/__virtual__/@vanilla-extract-sprinkles-virtual-a1c16f4109/0/cache/@vanilla-extract-sprinkles-npm-1.6.1-e524ee399f-7ddd2ab7c8.zip/node_modules/@vanilla-extract/sprinkles/",\ + "packageDependencies": [\ + ["@vanilla-extract/sprinkles", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.6.1"],\ + ["@types/vanilla-extract__css", null],\ + ["@vanilla-extract/css", "npm:1.14.2"]\ + ],\ + "packagePeers": [\ + "@types/vanilla-extract__css",\ + "@vanilla-extract/css"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@vanilla-extract/vite-plugin", [\ + ["npm:4.0.7", {\ + "packageLocation": "./.yarn/cache/@vanilla-extract-vite-plugin-npm-4.0.7-55893955b8-1d9dd8bdd7.zip/node_modules/@vanilla-extract/vite-plugin/",\ + "packageDependencies": [\ + ["@vanilla-extract/vite-plugin", "npm:4.0.7"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.0.7", {\ + "packageLocation": "./.yarn/__virtual__/@vanilla-extract-vite-plugin-virtual-41a7c6a813/0/cache/@vanilla-extract-vite-plugin-npm-4.0.7-55893955b8-1d9dd8bdd7.zip/node_modules/@vanilla-extract/vite-plugin/",\ + "packageDependencies": [\ + ["@vanilla-extract/vite-plugin", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.0.7"],\ + ["@types/vite", null],\ + ["@vanilla-extract/integration", "npm:7.1.2"],\ + ["vite", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:5.2.10"]\ + ],\ + "packagePeers": [\ + "@types/vite",\ + "vite"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@vitejs/plugin-react", [\ ["npm:4.2.1", {\ "packageLocation": "./.yarn/cache/@vitejs-plugin-react-npm-4.2.1-8b9705c544-de1eec44d7.zip/node_modules/@vitejs/plugin-react/",\ @@ -9620,21 +9771,21 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@vitest/coverage-v8", [\ - ["npm:1.5.1", {\ - "packageLocation": "./.yarn/cache/@vitest-coverage-v8-npm-1.5.1-12c3829e02-614b0a7ca0.zip/node_modules/@vitest/coverage-v8/",\ + ["npm:1.5.2", {\ + "packageLocation": "./.yarn/cache/@vitest-coverage-v8-npm-1.5.2-0f1947c29f-cc98275396.zip/node_modules/@vitest/coverage-v8/",\ "packageDependencies": [\ - ["@vitest/coverage-v8", "npm:1.5.1"]\ + ["@vitest/coverage-v8", "npm:1.5.2"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1", {\ - "packageLocation": "./.yarn/__virtual__/@vitest-coverage-v8-virtual-bee0ce99a5/0/cache/@vitest-coverage-v8-npm-1.5.1-12c3829e02-614b0a7ca0.zip/node_modules/@vitest/coverage-v8/",\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2", {\ + "packageLocation": "./.yarn/__virtual__/@vitest-coverage-v8-virtual-a1bfa4af20/0/cache/@vitest-coverage-v8-npm-1.5.2-0f1947c29f-cc98275396.zip/node_modules/@vitest/coverage-v8/",\ "packageDependencies": [\ - ["@vitest/coverage-v8", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"],\ + ["@vitest/coverage-v8", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"],\ ["@ampproject/remapping", "npm:2.3.0"],\ ["@bcoe/v8-coverage", "npm:0.2.3"],\ ["@types/vitest", null],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["istanbul-lib-coverage", "npm:3.2.2"],\ ["istanbul-lib-report", "npm:3.0.1"],\ ["istanbul-lib-source-maps", "npm:5.0.4"],\ @@ -9645,7 +9796,7 @@ const RAW_RUNTIME_STATE = ["std-env", "npm:3.7.0"],\ ["strip-literal", "npm:2.1.0"],\ ["test-exclude", "npm:6.0.0"],\ - ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"]\ + ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"]\ ],\ "packagePeers": [\ "@types/vitest",\ @@ -9655,23 +9806,23 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@vitest/expect", [\ - ["npm:1.5.1", {\ - "packageLocation": "./.yarn/cache/@vitest-expect-npm-1.5.1-9cc59d304b-4743ca8de3.zip/node_modules/@vitest/expect/",\ + ["npm:1.5.2", {\ + "packageLocation": "./.yarn/cache/@vitest-expect-npm-1.5.2-3b855b8075-4e8400a55f.zip/node_modules/@vitest/expect/",\ "packageDependencies": [\ - ["@vitest/expect", "npm:1.5.1"],\ - ["@vitest/spy", "npm:1.5.1"],\ - ["@vitest/utils", "npm:1.5.1"],\ + ["@vitest/expect", "npm:1.5.2"],\ + ["@vitest/spy", "npm:1.5.2"],\ + ["@vitest/utils", "npm:1.5.2"],\ ["chai", "npm:4.4.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@vitest/runner", [\ - ["npm:1.5.1", {\ - "packageLocation": "./.yarn/cache/@vitest-runner-npm-1.5.1-1bd8a6b0c9-a079c111c9.zip/node_modules/@vitest/runner/",\ + ["npm:1.5.2", {\ + "packageLocation": "./.yarn/cache/@vitest-runner-npm-1.5.2-c6689dee82-9fc3e66881.zip/node_modules/@vitest/runner/",\ "packageDependencies": [\ - ["@vitest/runner", "npm:1.5.1"],\ - ["@vitest/utils", "npm:1.5.1"],\ + ["@vitest/runner", "npm:1.5.2"],\ + ["@vitest/utils", "npm:1.5.2"],\ ["p-limit", "npm:5.0.0"],\ ["pathe", "npm:1.1.2"]\ ],\ @@ -9679,10 +9830,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@vitest/snapshot", [\ - ["npm:1.5.1", {\ - "packageLocation": "./.yarn/cache/@vitest-snapshot-npm-1.5.1-87cae6bf67-d3d769873b.zip/node_modules/@vitest/snapshot/",\ + ["npm:1.5.2", {\ + "packageLocation": "./.yarn/cache/@vitest-snapshot-npm-1.5.2-791e3d9f82-67ae235e59.zip/node_modules/@vitest/snapshot/",\ "packageDependencies": [\ - ["@vitest/snapshot", "npm:1.5.1"],\ + ["@vitest/snapshot", "npm:1.5.2"],\ ["magic-string", "npm:0.30.9"],\ ["pathe", "npm:1.1.2"],\ ["pretty-format", "npm:29.7.0"]\ @@ -9691,36 +9842,36 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@vitest/spy", [\ - ["npm:1.5.1", {\ - "packageLocation": "./.yarn/cache/@vitest-spy-npm-1.5.1-9ec8baf765-865b94bc99.zip/node_modules/@vitest/spy/",\ + ["npm:1.5.2", {\ + "packageLocation": "./.yarn/cache/@vitest-spy-npm-1.5.2-b9c126ac34-d66de2873f.zip/node_modules/@vitest/spy/",\ "packageDependencies": [\ - ["@vitest/spy", "npm:1.5.1"],\ + ["@vitest/spy", "npm:1.5.2"],\ ["tinyspy", "npm:2.2.1"]\ ],\ "linkType": "HARD"\ }]\ ]],\ ["@vitest/ui", [\ - ["npm:1.5.1", {\ - "packageLocation": "./.yarn/cache/@vitest-ui-npm-1.5.1-18a33515ae-efba22a08b.zip/node_modules/@vitest/ui/",\ + ["npm:1.5.2", {\ + "packageLocation": "./.yarn/cache/@vitest-ui-npm-1.5.2-b335b96316-85fc78e0b3.zip/node_modules/@vitest/ui/",\ "packageDependencies": [\ - ["@vitest/ui", "npm:1.5.1"]\ + ["@vitest/ui", "npm:1.5.2"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1", {\ - "packageLocation": "./.yarn/__virtual__/@vitest-ui-virtual-bdd5f85159/0/cache/@vitest-ui-npm-1.5.1-18a33515ae-efba22a08b.zip/node_modules/@vitest/ui/",\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2", {\ + "packageLocation": "./.yarn/__virtual__/@vitest-ui-virtual-01c9b8e99c/0/cache/@vitest-ui-npm-1.5.2-b335b96316-85fc78e0b3.zip/node_modules/@vitest/ui/",\ "packageDependencies": [\ - ["@vitest/ui", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"],\ + ["@vitest/ui", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"],\ ["@types/vitest", null],\ - ["@vitest/utils", "npm:1.5.1"],\ + ["@vitest/utils", "npm:1.5.2"],\ ["fast-glob", "npm:3.3.2"],\ ["fflate", "npm:0.8.2"],\ ["flatted", "npm:3.3.1"],\ ["pathe", "npm:1.1.2"],\ ["picocolors", "npm:1.0.0"],\ ["sirv", "npm:2.0.4"],\ - ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"]\ + ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"]\ ],\ "packagePeers": [\ "@types/vitest",\ @@ -9730,10 +9881,10 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@vitest/utils", [\ - ["npm:1.5.1", {\ - "packageLocation": "./.yarn/cache/@vitest-utils-npm-1.5.1-e51d68286e-45bef3c3c5.zip/node_modules/@vitest/utils/",\ + ["npm:1.5.2", {\ + "packageLocation": "./.yarn/cache/@vitest-utils-npm-1.5.2-7cf804c58e-019eeac016.zip/node_modules/@vitest/utils/",\ "packageDependencies": [\ - ["@vitest/utils", "npm:1.5.1"],\ + ["@vitest/utils", "npm:1.5.2"],\ ["diff-sequences", "npm:29.6.3"],\ ["estree-walker", "npm:3.0.3"],\ ["loupe", "npm:2.3.7"],\ @@ -9827,15 +9978,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["@xmldom/xmldom", [\ - ["npm:0.8.10", {\ - "packageLocation": "./.yarn/cache/@xmldom-xmldom-npm-0.8.10-c1bd991e61-c7647c4425.zip/node_modules/@xmldom/xmldom/",\ - "packageDependencies": [\ - ["@xmldom/xmldom", "npm:0.8.10"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["@yarnpkg/lockfile", [\ ["npm:1.1.0", {\ "packageLocation": "./.yarn/cache/@yarnpkg-lockfile-npm-1.1.0-6e0da4acd2-0bfa50a3d7.zip/node_modules/@yarnpkg/lockfile/",\ @@ -9970,7 +10112,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/agent-base-npm-7.1.1-c9e1a4b59e-e59ce7bed9.zip/node_modules/agent-base/",\ "packageDependencies": [\ ["agent-base", "npm:7.1.1"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"]\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"]\ ],\ "linkType": "HARD"\ }]\ @@ -10146,17 +10288,26 @@ const RAW_RUNTIME_STATE = ["app-web", "workspace:projects/app-web"],\ ["@graphql-typed-document-node/core", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.2.0"],\ ["@hono/node-server", "npm:1.11.0"],\ + ["@mswjs/data", "npm:0.16.1"],\ ["@nx/vite", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:18.3.3"],\ + ["@paralleldrive/cuid2", "npm:2.2.2"],\ ["@remix-run/dev", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:2.9.1"],\ ["@remix-run/node", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ ["@remix-run/testing", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ + ["@testing-library/dom", "npm:10.0.0"],\ ["@testing-library/jest-dom", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:6.4.2"],\ ["@testing-library/react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:14.3.0"],\ + ["@testing-library/user-event", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:14.5.2"],\ ["@types/node", "npm:20.12.7"],\ ["@types/react", "npm:18.2.75"],\ ["@types/react-dom", "npm:18.2.24"],\ + ["@vanilla-extract/css", "npm:1.14.2"],\ + ["@vanilla-extract/sprinkles", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.6.1"],\ + ["@vanilla-extract/vite-plugin", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.0.7"],\ ["@vitejs/plugin-react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.2.1"],\ + ["@vitest/expect", "npm:1.5.2"],\ ["eslint-plugin-jsx-a11y", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:6.8.0"],\ ["eslint-plugin-react", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:7.34.1"],\ ["eslint-plugin-react-hooks", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:4.6.0"],\ @@ -10165,14 +10316,21 @@ const RAW_RUNTIME_STATE = ["hono", "npm:4.2.4"],\ ["isbot", "npm:4.4.0"],\ ["jest-extended", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:4.0.2"],\ + ["jwt-decode", "npm:4.0.0"],\ ["msw", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.2.14"],\ ["react", "npm:18.2.0"],\ ["react-dom", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.2.0"],\ + ["remix-auth", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.6.0"],\ + ["remix-auth-auth0", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.10.0"],\ + ["remix-auth-oauth2", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.11.2"],\ + ["remix-flat-routes", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:0.6.4"],\ ["remix-hono", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:0.0.16"],\ + ["tiny-invariant", "npm:1.3.3"],\ ["tslib", "npm:2.6.2"],\ ["typescript", "patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c"],\ + ["uuid", "npm:9.0.1"],\ ["vite", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:5.2.10"],\ - ["vitest", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:1.5.1"]\ + ["vitest", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:1.5.2"]\ ],\ "linkType": "SOFT"\ }]\ @@ -11358,9 +11516,30 @@ const RAW_RUNTIME_STATE = ["cacheable-lookup", "npm:5.0.4"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.0.0", {\ + "packageLocation": "./.yarn/cache/cacheable-lookup-npm-7.0.0-b6cd95c14a-63a9c144c5.zip/node_modules/cacheable-lookup/",\ + "packageDependencies": [\ + ["cacheable-lookup", "npm:7.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["cacheable-request", [\ + ["npm:10.2.14", {\ + "packageLocation": "./.yarn/cache/cacheable-request-npm-10.2.14-fd919b07d7-41b6658db3.zip/node_modules/cacheable-request/",\ + "packageDependencies": [\ + ["cacheable-request", "npm:10.2.14"],\ + ["@types/http-cache-semantics", "npm:4.0.4"],\ + ["get-stream", "npm:6.0.1"],\ + ["http-cache-semantics", "npm:4.1.1"],\ + ["keyv", "npm:4.5.4"],\ + ["mimic-response", "npm:4.0.0"],\ + ["normalize-url", "npm:8.0.1"],\ + ["responselike", "npm:3.0.0"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:7.0.4", {\ "packageLocation": "./.yarn/cache/cacheable-request-npm-7.0.4-92bf077a92-0834a7d17a.zip/node_modules/cacheable-request/",\ "packageDependencies": [\ @@ -11433,15 +11612,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["camelize", [\ - ["npm:1.0.1", {\ - "packageLocation": "./.yarn/cache/camelize-npm-1.0.1-d86ebe085a-4c9ac55efd.zip/node_modules/camelize/",\ - "packageDependencies": [\ - ["camelize", "npm:1.0.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["caniuse-lite", [\ ["npm:1.0.30001608", {\ "packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001608-e327d8108a-eb77c78fb5.zip/node_modules/caniuse-lite/",\ @@ -11619,6 +11789,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["charenc", [\ + ["npm:0.0.2", {\ + "packageLocation": "./.yarn/cache/charenc-npm-0.0.2-aca0c2f207-a45ec39363.zip/node_modules/charenc/",\ + "packageDependencies": [\ + ["charenc", "npm:0.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["check-error", [\ ["npm:1.0.3", {\ "packageLocation": "./.yarn/cache/check-error-npm-1.0.3-137994eabc-94aa37a731.zip/node_modules/check-error/",\ @@ -12136,13 +12315,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["cookie", [\ - ["npm:0.4.2", {\ - "packageLocation": "./.yarn/cache/cookie-npm-0.4.2-7761894d5f-beab41fbd7.zip/node_modules/cookie/",\ - "packageDependencies": [\ - ["cookie", "npm:0.4.2"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:0.5.0", {\ "packageLocation": "./.yarn/cache/cookie-npm-0.5.0-e2d58a161a-c01ca3ef8d.zip/node_modules/cookie/",\ "packageDependencies": [\ @@ -12386,11 +12558,11 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["css-color-keywords", [\ - ["npm:1.0.0", {\ - "packageLocation": "./.yarn/cache/css-color-keywords-npm-1.0.0-fc176df58b-af205a86c6.zip/node_modules/css-color-keywords/",\ + ["crypt", [\ + ["npm:0.0.2", {\ + "packageLocation": "./.yarn/cache/crypt-npm-0.0.2-033627d94f-adbf263441.zip/node_modules/crypt/",\ "packageDependencies": [\ - ["css-color-keywords", "npm:1.0.0"]\ + ["crypt", "npm:0.0.2"]\ ],\ "linkType": "HARD"\ }]\ @@ -12409,18 +12581,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["css-to-react-native", [\ - ["npm:3.2.0", {\ - "packageLocation": "./.yarn/cache/css-to-react-native-npm-3.2.0-46e31a25e3-fde850a511.zip/node_modules/css-to-react-native/",\ - "packageDependencies": [\ - ["css-to-react-native", "npm:3.2.0"],\ - ["camelize", "npm:1.0.1"],\ - ["css-color-keywords", "npm:1.0.0"],\ - ["postcss-value-parser", "npm:4.2.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["css-tree", [\ ["npm:2.2.1", {\ "packageLocation": "./.yarn/cache/css-tree-npm-2.2.1-ee98ac48a8-47e87b0f02.zip/node_modules/css-tree/",\ @@ -12479,13 +12639,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["csstype", [\ - ["npm:3.1.2", {\ - "packageLocation": "./.yarn/cache/csstype-npm-3.1.2-cead7d99b2-32c038af25.zip/node_modules/csstype/",\ - "packageDependencies": [\ - ["csstype", "npm:3.1.2"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:3.1.3", {\ "packageLocation": "./.yarn/cache/csstype-npm-3.1.3-e9a1c85013-80c089d6f7.zip/node_modules/csstype/",\ "packageDependencies": [\ @@ -12494,15 +12647,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["cuid", [\ - ["npm:3.0.0", {\ - "packageLocation": "./.yarn/cache/cuid-npm-3.0.0-66e229f427-e1cac04b8d.zip/node_modules/cuid/",\ - "packageDependencies": [\ - ["cuid", "npm:3.0.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["cuint", [\ ["npm:0.2.2", {\ "packageLocation": "./.yarn/cache/cuint-npm-0.2.2-3990651cc6-ba56735799.zip/node_modules/cuint/",\ @@ -12595,6 +12739,16 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["date-fns", [\ + ["npm:2.30.0", {\ + "packageLocation": "./.yarn/cache/date-fns-npm-2.30.0-895c790e0f-e4b521fbf2.zip/node_modules/date-fns/",\ + "packageDependencies": [\ + ["date-fns", "npm:2.30.0"],\ + ["@babel/runtime", "npm:7.24.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["debounce", [\ ["npm:1.2.1", {\ "packageLocation": "./.yarn/cache/debounce-npm-1.2.1-b09266a260-6c9320aa09.zip/node_modules/debounce/",\ @@ -12650,12 +12804,12 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4", {\ - "packageLocation": "./.yarn/__virtual__/debug-virtual-11377b508d/0/cache/debug-npm-4.3.4-4513954577-cedbec4529.zip/node_modules/debug/",\ + ["virtual:e0cd6afa69db469de21c754be1546e018ea723a8653bf7c1fdbb52b3d67b9c4065461f2d7632852c8644c3b36b5304269483ba2eb51ad39f9eae03847036d7a9#npm:2.6.9", {\ + "packageLocation": "./.yarn/__virtual__/debug-virtual-3f5cb29632/0/cache/debug-npm-2.6.9-7d4cb597dc-121908fb83.zip/node_modules/debug/",\ "packageDependencies": [\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e0cd6afa69db469de21c754be1546e018ea723a8653bf7c1fdbb52b3d67b9c4065461f2d7632852c8644c3b36b5304269483ba2eb51ad39f9eae03847036d7a9#npm:2.6.9"],\ ["@types/supports-color", null],\ - ["ms", "npm:2.1.2"],\ + ["ms", "npm:2.0.0"],\ ["supports-color", null]\ ],\ "packagePeers": [\ @@ -12664,12 +12818,12 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:e0cd6afa69db469de21c754be1546e018ea723a8653bf7c1fdbb52b3d67b9c4065461f2d7632852c8644c3b36b5304269483ba2eb51ad39f9eae03847036d7a9#npm:2.6.9", {\ - "packageLocation": "./.yarn/__virtual__/debug-virtual-3f5cb29632/0/cache/debug-npm-2.6.9-7d4cb597dc-121908fb83.zip/node_modules/debug/",\ + ["virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4", {\ + "packageLocation": "./.yarn/__virtual__/debug-virtual-c3c08891d2/0/cache/debug-npm-4.3.4-4513954577-cedbec4529.zip/node_modules/debug/",\ "packageDependencies": [\ - ["debug", "virtual:e0cd6afa69db469de21c754be1546e018ea723a8653bf7c1fdbb52b3d67b9c4065461f2d7632852c8644c3b36b5304269483ba2eb51ad39f9eae03847036d7a9#npm:2.6.9"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["@types/supports-color", null],\ - ["ms", "npm:2.0.0"],\ + ["ms", "npm:2.1.2"],\ ["supports-color", null]\ ],\ "packagePeers": [\ @@ -12856,6 +13010,13 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["depd", [\ + ["npm:1.1.2", {\ + "packageLocation": "./.yarn/cache/depd-npm-1.1.2-b0c8414da7-acb24aaf93.zip/node_modules/depd/",\ + "packageDependencies": [\ + ["depd", "npm:1.1.2"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/depd-npm-2.0.0-b6c51a4b43-58bd06ec20.zip/node_modules/depd/",\ "packageDependencies": [\ @@ -12924,7 +13085,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["detect-port", "npm:1.5.1"],\ ["address", "npm:1.2.2"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"]\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"]\ ],\ "linkType": "HARD"\ }]\ @@ -12989,7 +13150,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/docker-modem-npm-3.0.8-9923fc0db1-5c00592297.zip/node_modules/docker-modem/",\ "packageDependencies": [\ ["docker-modem", "npm:3.0.8"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["readable-stream", "npm:3.6.2"],\ ["split-ca", "npm:1.0.1"],\ ["ssh2", "npm:1.15.0"]\ @@ -13882,7 +14043,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["esbuild-register", "virtual:ff13502fbfa0775c8e35e50634d03677fd00063c1604264d0219e3abb9732adf04146d0048f117b34640a3bd1f15729c96cc57c972efc20ba50dd72938c0306a#npm:3.5.0"],\ ["@types/esbuild", null],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["esbuild", "npm:0.19.12"]\ ],\ "packagePeers": [\ @@ -13956,7 +14117,7 @@ const RAW_RUNTIME_STATE = ["ajv", "npm:6.12.6"],\ ["chalk", "npm:4.1.2"],\ ["cross-spawn", "npm:7.0.3"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["doctrine", "npm:3.0.0"],\ ["escape-string-regexp", "npm:4.0.0"],\ ["eslint-scope", "npm:7.2.2"],\ @@ -14000,7 +14161,7 @@ const RAW_RUNTIME_STATE = ["ajv", "npm:6.12.6"],\ ["chalk", "npm:4.1.2"],\ ["cross-spawn", "npm:7.0.3"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["escape-string-regexp", "npm:4.0.0"],\ ["eslint-scope", "npm:8.0.1"],\ ["eslint-visitor-keys", "npm:4.0.0"],\ @@ -14565,15 +14726,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["events", [\ - ["npm:3.3.0", {\ - "packageLocation": "./.yarn/cache/events-npm-3.3.0-c280bc7e48-d6b6f2adbc.zip/node_modules/events/",\ - "packageDependencies": [\ - ["events", "npm:3.3.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["execa", [\ ["npm:0.7.0", {\ "packageLocation": "./.yarn/cache/execa-npm-0.7.0-3f4e53d884-812f1776e2.zip/node_modules/execa/",\ @@ -15210,6 +15362,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["form-data-encoder", [\ + ["npm:4.0.2", {\ + "packageLocation": "./.yarn/cache/form-data-encoder-npm-4.0.2-aa021c3f21-559d3130e2.zip/node_modules/form-data-encoder/",\ + "packageDependencies": [\ + ["form-data-encoder", "npm:4.0.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["format", [\ ["npm:0.2.2", {\ "packageLocation": "./.yarn/cache/format-npm-0.2.2-679f3acc64-6032ba7475.zip/node_modules/format/",\ @@ -15631,6 +15792,24 @@ const RAW_RUNTIME_STATE = ["responselike", "npm:2.0.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:14.2.1", {\ + "packageLocation": "./.yarn/cache/got-npm-14.2.1-e13379605e-6592f70d57.zip/node_modules/got/",\ + "packageDependencies": [\ + ["got", "npm:14.2.1"],\ + ["@sindresorhus/is", "npm:6.3.0"],\ + ["@szmarczak/http-timer", "npm:5.0.1"],\ + ["cacheable-lookup", "npm:7.0.0"],\ + ["cacheable-request", "npm:10.2.14"],\ + ["decompress-response", "npm:6.0.0"],\ + ["form-data-encoder", "npm:4.0.2"],\ + ["get-stream", "npm:8.0.1"],\ + ["http2-wrapper", "npm:2.2.1"],\ + ["lowercase-keys", "npm:3.0.0"],\ + ["p-cancelable", "npm:4.0.1"],\ + ["responselike", "npm:3.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["graceful-fs", [\ @@ -15721,6 +15900,29 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["graphql-scalars", [\ + ["npm:1.23.0", {\ + "packageLocation": "./.yarn/cache/graphql-scalars-npm-1.23.0-afcf92cba2-7666c305b8.zip/node_modules/graphql-scalars/",\ + "packageDependencies": [\ + ["graphql-scalars", "npm:1.23.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.23.0", {\ + "packageLocation": "./.yarn/__virtual__/graphql-scalars-virtual-4ae8f4b8b2/0/cache/graphql-scalars-npm-1.23.0-afcf92cba2-7666c305b8.zip/node_modules/graphql-scalars/",\ + "packageDependencies": [\ + ["graphql-scalars", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.23.0"],\ + ["@types/graphql", null],\ + ["graphql", "npm:16.8.1"],\ + ["tslib", "npm:2.6.2"]\ + ],\ + "packagePeers": [\ + "@types/graphql",\ + "graphql"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["graphql-tag", [\ ["npm:2.12.6", {\ "packageLocation": "./.yarn/cache/graphql-tag-npm-2.12.6-99a5a7f6de-7763a72011.zip/node_modules/graphql-tag/",\ @@ -15744,6 +15946,28 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["graphql-transform-scalars", [\ + ["npm:1.2.1", {\ + "packageLocation": "./.yarn/cache/graphql-transform-scalars-npm-1.2.1-419c342fcf-d170e808a2.zip/node_modules/graphql-transform-scalars/",\ + "packageDependencies": [\ + ["graphql-transform-scalars", "npm:1.2.1"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.2.1", {\ + "packageLocation": "./.yarn/__virtual__/graphql-transform-scalars-virtual-308b200c1e/0/cache/graphql-transform-scalars-npm-1.2.1-419c342fcf-d170e808a2.zip/node_modules/graphql-transform-scalars/",\ + "packageDependencies": [\ + ["graphql-transform-scalars", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.2.1"],\ + ["@types/graphql", null],\ + ["graphql", "npm:16.8.1"]\ + ],\ + "packagePeers": [\ + "@types/graphql",\ + "graphql"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["graphql-ws", [\ ["npm:5.16.0", {\ "packageLocation": "./.yarn/cache/graphql-ws-npm-5.16.0-98146e34fe-5e538c3460.zip/node_modules/graphql-ws/",\ @@ -15973,13 +16197,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["headers-polyfill", [\ - ["npm:3.2.5", {\ - "packageLocation": "./.yarn/cache/headers-polyfill-npm-3.2.5-5873ac13a0-10202f4ebf.zip/node_modules/headers-polyfill/",\ - "packageDependencies": [\ - ["headers-polyfill", "npm:3.2.5"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:4.0.3", {\ "packageLocation": "./.yarn/cache/headers-polyfill-npm-4.0.3-65ca63b329-53e85b2c63.zip/node_modules/headers-polyfill/",\ "packageDependencies": [\ @@ -15997,16 +16214,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["hoist-non-react-statics", [\ - ["npm:3.3.2", {\ - "packageLocation": "./.yarn/cache/hoist-non-react-statics-npm-3.3.2-e7b709e6c1-fe0889169e.zip/node_modules/hoist-non-react-statics/",\ - "packageDependencies": [\ - ["hoist-non-react-statics", "npm:3.3.2"],\ - ["react-is", "npm:16.13.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["hono", [\ ["npm:4.2.4", {\ "packageLocation": "./.yarn/cache/hono-npm-4.2.4-c183465ffc-f6e7d21ebd.zip/node_modules/hono/",\ @@ -16115,7 +16322,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["http-proxy-agent", "npm:7.0.2"],\ ["agent-base", "npm:7.1.1"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"]\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"]\ ],\ "linkType": "HARD"\ }]\ @@ -16151,6 +16358,15 @@ const RAW_RUNTIME_STATE = ["resolve-alpn", "npm:1.2.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:2.2.1", {\ + "packageLocation": "./.yarn/cache/http2-wrapper-npm-2.2.1-c033aaabde-7207201d3c.zip/node_modules/http2-wrapper/",\ + "packageDependencies": [\ + ["http2-wrapper", "npm:2.2.1"],\ + ["quick-lru", "npm:5.1.1"],\ + ["resolve-alpn", "npm:1.2.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["https-proxy-agent", [\ @@ -16159,7 +16375,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["https-proxy-agent", "npm:7.0.4"],\ ["agent-base", "npm:7.1.1"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"]\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"]\ ],\ "linkType": "HARD"\ }]\ @@ -16528,6 +16744,13 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["is-buffer", [\ + ["npm:1.1.6", {\ + "packageLocation": "./.yarn/cache/is-buffer-npm-1.1.6-08199d9ccc-ae18aa0b6e.zip/node_modules/is-buffer/",\ + "packageDependencies": [\ + ["is-buffer", "npm:1.1.6"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:2.0.5", {\ "packageLocation": "./.yarn/cache/is-buffer-npm-2.0.5-17e563f277-e603f6fced.zip/node_modules/is-buffer/",\ "packageDependencies": [\ @@ -17141,7 +17364,7 @@ const RAW_RUNTIME_STATE = "packageLocation": "./.yarn/cache/istanbul-lib-source-maps-npm-4.0.1-af0f859df7-19e4cc4050.zip/node_modules/istanbul-lib-source-maps/",\ "packageDependencies": [\ ["istanbul-lib-source-maps", "npm:4.0.1"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["istanbul-lib-coverage", "npm:3.2.2"],\ ["source-map", "npm:0.6.1"]\ ],\ @@ -17152,7 +17375,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["istanbul-lib-source-maps", "npm:5.0.4"],\ ["@jridgewell/trace-mapping", "npm:0.3.25"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["istanbul-lib-coverage", "npm:3.2.2"]\ ],\ "linkType": "HARD"\ @@ -17675,15 +17898,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["js-levenshtein", [\ - ["npm:1.1.6", {\ - "packageLocation": "./.yarn/cache/js-levenshtein-npm-1.1.6-ab883e61a3-1404573532.zip/node_modules/js-levenshtein/",\ - "packageDependencies": [\ - ["js-levenshtein", "npm:1.1.6"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["js-tokens", [\ ["npm:4.0.0", {\ "packageLocation": "./.yarn/cache/js-tokens-npm-4.0.0-0ac852e9e2-e248708d37.zip/node_modules/js-tokens/",\ @@ -17951,7 +18165,7 @@ const RAW_RUNTIME_STATE = ["jwks-rsa", "npm:3.1.0"],\ ["@types/express", "npm:4.17.21"],\ ["@types/jsonwebtoken", "npm:9.0.6"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["jose", "npm:4.15.5"],\ ["limiter", "npm:1.1.5"],\ ["lru-memoizer", "npm:2.2.0"]\ @@ -17970,6 +18184,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["jwt-decode", [\ + ["npm:4.0.0", {\ + "packageLocation": "./.yarn/cache/jwt-decode-npm-4.0.0-4cd8e89909-de75bbf892.zip/node_modules/jwt-decode/",\ + "packageDependencies": [\ + ["jwt-decode", "npm:4.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["keyv", [\ ["npm:4.5.4", {\ "packageLocation": "./.yarn/cache/keyv-npm-4.5.4-4c8e2cf7f7-aa52f3c5e1.zip/node_modules/keyv/",\ @@ -18095,7 +18318,7 @@ const RAW_RUNTIME_STATE = ["lint-staged", "npm:15.2.2"],\ ["chalk", "npm:5.3.0"],\ ["commander", "npm:11.1.0"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["execa", "npm:8.0.1"],\ ["lilconfig", "npm:3.0.0"],\ ["listr2", "npm:8.0.1"],\ @@ -18538,6 +18761,13 @@ const RAW_RUNTIME_STATE = ["lowercase-keys", "npm:2.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:3.0.0", {\ + "packageLocation": "./.yarn/cache/lowercase-keys-npm-3.0.0-f8c4730215-ef62b9fa56.zip/node_modules/lowercase-keys/",\ + "packageDependencies": [\ + ["lowercase-keys", "npm:3.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["lru-cache", [\ @@ -18709,6 +18939,18 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["md5", [\ + ["npm:2.3.0", {\ + "packageLocation": "./.yarn/cache/md5-npm-2.3.0-86c49d3915-14a21d597d.zip/node_modules/md5/",\ + "packageDependencies": [\ + ["md5", "npm:2.3.0"],\ + ["charenc", "npm:0.0.2"],\ + ["crypt", "npm:0.0.2"],\ + ["is-buffer", "npm:1.1.6"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["mdast-util-definitions", [\ ["npm:5.1.2", {\ "packageLocation": "./.yarn/cache/mdast-util-definitions-npm-5.1.2-45a5b0f1bf-da9049c155.zip/node_modules/mdast-util-definitions/",\ @@ -18940,6 +19182,13 @@ const RAW_RUNTIME_STATE = ["merge-descriptors", "npm:1.0.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.3", {\ + "packageLocation": "./.yarn/cache/merge-descriptors-npm-1.0.3-10b44ad75c-866b7094af.zip/node_modules/merge-descriptors/",\ + "packageDependencies": [\ + ["merge-descriptors", "npm:1.0.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["merge-stream", [\ @@ -18995,7 +19244,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["micromark", "npm:3.2.0"],\ ["@types/debug", "npm:4.1.12"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["decode-named-character-reference", "npm:1.0.2"],\ ["micromark-core-commonmark", "npm:1.1.0"],\ ["micromark-factory-space", "npm:1.1.0"],\ @@ -19454,6 +19703,13 @@ const RAW_RUNTIME_STATE = ["mimic-response", "npm:3.1.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.0.0", {\ + "packageLocation": "./.yarn/cache/mimic-response-npm-4.0.0-c080547e26-761d788d26.zip/node_modules/mimic-response/",\ + "packageDependencies": [\ + ["mimic-response", "npm:4.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["min-indent", [\ @@ -19660,13 +19916,13 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["mock-jwks", [\ - ["npm:3.1.0", {\ - "packageLocation": "./.yarn/cache/mock-jwks-npm-3.1.0-131e3bbc29-e21560db1c.zip/node_modules/mock-jwks/",\ + ["patch:mock-jwks@npm%3A3.1.0#~/.yarn/patches/mock-jwks-npm-3.1.0-131e3bbc29.patch::version=3.1.0&hash=3d08e1", {\ + "packageLocation": "./.yarn/cache/mock-jwks-patch-9a7688505b-678cdce347.zip/node_modules/mock-jwks/",\ "packageDependencies": [\ - ["mock-jwks", "npm:3.1.0"],\ + ["mock-jwks", "patch:mock-jwks@npm%3A3.1.0#~/.yarn/patches/mock-jwks-npm-3.1.0-131e3bbc29.patch::version=3.1.0&hash=3d08e1"],\ ["base64-url", "npm:2.3.3"],\ ["jsonwebtoken", "npm:9.0.2"],\ - ["msw", "virtual:131e3bbc29d795d4bff911411a2ad06b6c6444e3c9fc80bdf90ae5eafec2f31e52e8af5bb0f131cd97b0c37a9f6a2c8892ca7a384d43c4d2061239cc01490a35#npm:1.3.3"],\ + ["msw", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:2.2.14"],\ ["node-forge", "npm:1.3.1"],\ ["node-rsa", "npm:1.1.1"]\ ],\ @@ -19745,13 +20001,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["msw", [\ - ["npm:1.3.3", {\ - "packageLocation": "./.yarn/unplugged/msw-virtual-7bdf7ce27c/node_modules/msw/",\ - "packageDependencies": [\ - ["msw", "npm:1.3.3"]\ - ],\ - "linkType": "SOFT"\ - }],\ ["npm:2.2.14", {\ "packageLocation": "./.yarn/unplugged/msw-virtual-a1e287bf96/node_modules/msw/",\ "packageDependencies": [\ @@ -19759,30 +20008,28 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:131e3bbc29d795d4bff911411a2ad06b6c6444e3c9fc80bdf90ae5eafec2f31e52e8af5bb0f131cd97b0c37a9f6a2c8892ca7a384d43c4d2061239cc01490a35#npm:1.3.3", {\ - "packageLocation": "./.yarn/unplugged/msw-virtual-7bdf7ce27c/node_modules/msw/",\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.2.14", {\ + "packageLocation": "./.yarn/unplugged/msw-virtual-a1e287bf96/node_modules/msw/",\ "packageDependencies": [\ - ["msw", "virtual:131e3bbc29d795d4bff911411a2ad06b6c6444e3c9fc80bdf90ae5eafec2f31e52e8af5bb0f131cd97b0c37a9f6a2c8892ca7a384d43c4d2061239cc01490a35#npm:1.3.3"],\ - ["@mswjs/cookies", "npm:0.2.2"],\ - ["@mswjs/interceptors", "npm:0.17.10"],\ - ["@open-draft/until", "npm:1.0.3"],\ - ["@types/cookie", "npm:0.4.1"],\ - ["@types/js-levenshtein", "npm:1.1.3"],\ + ["msw", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.2.14"],\ + ["@bundled-es-modules/cookie", "npm:2.0.0"],\ + ["@bundled-es-modules/statuses", "npm:1.0.1"],\ + ["@inquirer/confirm", "npm:3.1.5"],\ + ["@mswjs/cookies", "npm:1.1.0"],\ + ["@mswjs/interceptors", "npm:0.26.15"],\ + ["@open-draft/until", "npm:2.1.0"],\ + ["@types/cookie", "npm:0.6.0"],\ + ["@types/statuses", "npm:2.0.5"],\ ["@types/typescript", null],\ ["chalk", "npm:4.1.2"],\ - ["chokidar", "npm:3.6.0"],\ - ["cookie", "npm:0.4.2"],\ ["graphql", "npm:16.8.1"],\ - ["headers-polyfill", "npm:3.2.5"],\ - ["inquirer", "npm:8.2.6"],\ + ["headers-polyfill", "npm:4.0.3"],\ ["is-node-process", "npm:1.2.0"],\ - ["js-levenshtein", "npm:1.1.6"],\ - ["node-fetch", "virtual:5e637fd56a9dc88fac941d74d36ae62bb174e2a095814480a8c5aa84455b10d8b3b88a3aeb7396ee63088f87b724c0c5a23604be8cd13b3bb36bcecbdbb2e3f9#npm:2.7.0"],\ ["outvariant", "npm:1.4.2"],\ ["path-to-regexp", "npm:6.2.2"],\ - ["strict-event-emitter", "npm:0.4.6"],\ - ["type-fest", "npm:2.19.0"],\ - ["typescript", null],\ + ["strict-event-emitter", "npm:0.5.1"],\ + ["type-fest", "npm:4.15.0"],\ + ["typescript", "patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c"],\ ["yargs", "npm:17.7.2"]\ ],\ "packagePeers": [\ @@ -19791,10 +20038,10 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.2.14", {\ - "packageLocation": "./.yarn/unplugged/msw-virtual-a1e287bf96/node_modules/msw/",\ + ["virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:2.2.14", {\ + "packageLocation": "./.yarn/unplugged/msw-virtual-f6503316cf/node_modules/msw/",\ "packageDependencies": [\ - ["msw", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.2.14"],\ + ["msw", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:2.2.14"],\ ["@bundled-es-modules/cookie", "npm:2.0.0"],\ ["@bundled-es-modules/statuses", "npm:1.0.1"],\ ["@inquirer/confirm", "npm:3.1.5"],\ @@ -19812,7 +20059,7 @@ const RAW_RUNTIME_STATE = ["path-to-regexp", "npm:6.2.2"],\ ["strict-event-emitter", "npm:0.5.1"],\ ["type-fest", "npm:4.15.0"],\ - ["typescript", "patch:typescript@npm%3A5.4.5#optional!builtin::version=5.4.5&hash=5adc0c"],\ + ["typescript", null],\ ["yargs", "npm:17.7.2"]\ ],\ "packagePeers": [\ @@ -20003,6 +20250,27 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["node-mocks-http", [\ + ["npm:1.14.1", {\ + "packageLocation": "./.yarn/cache/node-mocks-http-npm-1.14.1-92277e4de4-bd091ea1de.zip/node_modules/node-mocks-http/",\ + "packageDependencies": [\ + ["node-mocks-http", "npm:1.14.1"],\ + ["@types/express", "npm:4.17.21"],\ + ["@types/node", "npm:20.12.7"],\ + ["accepts", "npm:1.3.8"],\ + ["content-disposition", "npm:0.5.4"],\ + ["depd", "npm:1.1.2"],\ + ["fresh", "npm:0.5.2"],\ + ["merge-descriptors", "npm:1.0.3"],\ + ["methods", "npm:1.1.2"],\ + ["mime", "npm:1.6.0"],\ + ["parseurl", "npm:1.3.3"],\ + ["range-parser", "npm:1.2.1"],\ + ["type-is", "npm:1.6.18"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["node-releases", [\ ["npm:2.0.14", {\ "packageLocation": "./.yarn/cache/node-releases-npm-2.0.14-d39047cad8-199fc93773.zip/node_modules/node-releases/",\ @@ -20080,6 +20348,13 @@ const RAW_RUNTIME_STATE = ["normalize-url", "npm:6.1.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:8.0.1", {\ + "packageLocation": "./.yarn/cache/normalize-url-npm-8.0.1-c87adbf3f1-eb439231c4.zip/node_modules/normalize-url/",\ + "packageDependencies": [\ + ["normalize-url", "npm:8.0.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["npm-install-checks", [\ @@ -20601,6 +20876,13 @@ const RAW_RUNTIME_STATE = ["p-cancelable", "npm:2.1.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.0.1", {\ + "packageLocation": "./.yarn/cache/p-cancelable-npm-4.0.1-759b614353-12636623f4.zip/node_modules/p-cancelable/",\ + "packageDependencies": [\ + ["p-cancelable", "npm:4.0.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["p-finally", [\ @@ -21109,16 +21391,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["postcss", [\ - ["npm:8.4.31", {\ - "packageLocation": "./.yarn/cache/postcss-npm-8.4.31-385051a82b-748b82e6e5.zip/node_modules/postcss/",\ - "packageDependencies": [\ - ["postcss", "npm:8.4.31"],\ - ["nanoid", "npm:3.3.7"],\ - ["picocolors", "npm:1.0.0"],\ - ["source-map-js", "npm:1.2.0"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:8.4.38", {\ "packageLocation": "./.yarn/cache/postcss-npm-8.4.38-495621b279-955407b8f7.zip/node_modules/postcss/",\ "packageDependencies": [\ @@ -22142,6 +22414,154 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["remix-auth", [\ + ["npm:3.6.0", {\ + "packageLocation": "./.yarn/cache/remix-auth-npm-3.6.0-c96fab9c4d-2b9d9f5ad0.zip/node_modules/remix-auth/",\ + "packageDependencies": [\ + ["remix-auth", "npm:3.6.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.6.0", {\ + "packageLocation": "./.yarn/__virtual__/remix-auth-virtual-fd664fa930/0/cache/remix-auth-npm-3.6.0-c96fab9c4d-2b9d9f5ad0.zip/node_modules/remix-auth/",\ + "packageDependencies": [\ + ["remix-auth", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.6.0"],\ + ["@remix-run/react", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ + ["@types/remix-run__react", null],\ + ["@types/remix-run__server-runtime", null],\ + ["uuid", "npm:8.3.2"]\ + ],\ + "packagePeers": [\ + "@remix-run/react",\ + "@remix-run/server-runtime",\ + "@types/remix-run__react",\ + "@types/remix-run__server-runtime"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["remix-auth-auth0", [\ + ["npm:1.10.0", {\ + "packageLocation": "./.yarn/cache/remix-auth-auth0-npm-1.10.0-d618cd38cb-86d0170c80.zip/node_modules/remix-auth-auth0/",\ + "packageDependencies": [\ + ["remix-auth-auth0", "npm:1.10.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.10.0", {\ + "packageLocation": "./.yarn/__virtual__/remix-auth-auth0-virtual-1e55c85c3f/0/cache/remix-auth-auth0-npm-1.10.0-d618cd38cb-86d0170c80.zip/node_modules/remix-auth-auth0/",\ + "packageDependencies": [\ + ["remix-auth-auth0", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.10.0"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ + ["@types/remix-auth", null],\ + ["@types/remix-run__server-runtime", null],\ + ["remix-auth", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.6.0"],\ + ["remix-auth-oauth2", "virtual:1e55c85c3f8f28bf47332a03f1f6805aae6aced2f90b59b33e6aed58654352d63fb5c9c2e81ba3f1df9bb4ad4c2b194bb9a2df649d92483e70eed866778120d9#npm:1.10.0"]\ + ],\ + "packagePeers": [\ + "@remix-run/server-runtime",\ + "@types/remix-auth",\ + "@types/remix-run__server-runtime",\ + "remix-auth"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["remix-auth-oauth2", [\ + ["npm:1.10.0", {\ + "packageLocation": "./.yarn/cache/remix-auth-oauth2-npm-1.10.0-ac7ff3e733-88d7f0da60.zip/node_modules/remix-auth-oauth2/",\ + "packageDependencies": [\ + ["remix-auth-oauth2", "npm:1.10.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["npm:1.11.2", {\ + "packageLocation": "./.yarn/cache/remix-auth-oauth2-npm-1.11.2-8879fabf71-382cfcc05d.zip/node_modules/remix-auth-oauth2/",\ + "packageDependencies": [\ + ["remix-auth-oauth2", "npm:1.11.2"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:1e55c85c3f8f28bf47332a03f1f6805aae6aced2f90b59b33e6aed58654352d63fb5c9c2e81ba3f1df9bb4ad4c2b194bb9a2df649d92483e70eed866778120d9#npm:1.10.0", {\ + "packageLocation": "./.yarn/__virtual__/remix-auth-oauth2-virtual-9559886ae1/0/cache/remix-auth-oauth2-npm-1.10.0-ac7ff3e733-88d7f0da60.zip/node_modules/remix-auth-oauth2/",\ + "packageDependencies": [\ + ["remix-auth-oauth2", "virtual:1e55c85c3f8f28bf47332a03f1f6805aae6aced2f90b59b33e6aed58654352d63fb5c9c2e81ba3f1df9bb4ad4c2b194bb9a2df649d92483e70eed866778120d9#npm:1.10.0"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ + ["@types/remix-auth", null],\ + ["@types/remix-run__server-runtime", null],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ + ["remix-auth", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.6.0"]\ + ],\ + "packagePeers": [\ + "@remix-run/server-runtime",\ + "@types/remix-auth",\ + "@types/remix-run__server-runtime",\ + "remix-auth"\ + ],\ + "linkType": "HARD"\ + }],\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.11.2", {\ + "packageLocation": "./.yarn/__virtual__/remix-auth-oauth2-virtual-c1f6d1ce27/0/cache/remix-auth-oauth2-npm-1.11.2-8879fabf71-382cfcc05d.zip/node_modules/remix-auth-oauth2/",\ + "packageDependencies": [\ + ["remix-auth-oauth2", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.11.2"],\ + ["@remix-run/server-runtime", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ + ["@types/remix-auth", null],\ + ["@types/remix-run__server-runtime", null],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ + ["remix-auth", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:3.6.0"],\ + ["uuid", "npm:9.0.1"]\ + ],\ + "packagePeers": [\ + "@remix-run/server-runtime",\ + "@types/remix-auth",\ + "@types/remix-run__server-runtime",\ + "remix-auth"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["remix-flat-routes", [\ + ["npm:0.6.4", {\ + "packageLocation": "./.yarn/cache/remix-flat-routes-npm-0.6.4-7e2639fc72-84a2c19be9.zip/node_modules/remix-flat-routes/",\ + "packageDependencies": [\ + ["remix-flat-routes", "npm:0.6.4"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:0.6.4", {\ + "packageLocation": "./.yarn/__virtual__/remix-flat-routes-virtual-61f03cbbff/0/cache/remix-flat-routes-npm-0.6.4-7e2639fc72-84a2c19be9.zip/node_modules/remix-flat-routes/",\ + "packageDependencies": [\ + ["remix-flat-routes", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:0.6.4"],\ + ["@remix-run/dev", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:2.9.1"],\ + ["@remix-run/v1-route-convention", "virtual:61f03cbbff78bf8d18a7331382e9626bcfb3b250f8b5bb18d7b79cba6fb51b5e3d83764aa3051e3658908bb6641b40c15523c34f836b9e77d7e987d154b51c23#npm:0.1.4"],\ + ["@types/remix-run__dev", null],\ + ["fs-extra", "npm:11.2.0"],\ + ["minimatch", "npm:5.1.6"]\ + ],\ + "packagePeers": [\ + "@remix-run/dev",\ + "@types/remix-run__dev"\ + ],\ + "linkType": "HARD"\ + }],\ + ["virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:0.6.4", {\ + "packageLocation": "./.yarn/__virtual__/remix-flat-routes-virtual-68459c0c85/0/cache/remix-flat-routes-npm-0.6.4-7e2639fc72-84a2c19be9.zip/node_modules/remix-flat-routes/",\ + "packageDependencies": [\ + ["remix-flat-routes", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:0.6.4"],\ + ["@remix-run/dev", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:2.9.1"],\ + ["@remix-run/v1-route-convention", "virtual:68459c0c85ca646a10107f3b38fc63a47b5e64300cc2d9f9db6462a01903420a230bcd21782478dd7bf9d012e6865f9e42c01dc797fc4756d6e7ee83ffb7802e#npm:0.1.4"],\ + ["@types/remix-run__dev", null],\ + ["fs-extra", "npm:11.2.0"],\ + ["minimatch", "npm:5.1.6"]\ + ],\ + "packagePeers": [\ + "@remix-run/dev",\ + "@types/remix-run__dev"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["remix-hono", [\ ["npm:0.0.16", {\ "packageLocation": "./.yarn/cache/remix-hono-npm-0.0.16-ae6771ade2-fc13cb4db1.zip/node_modules/remix-hono/",\ @@ -22322,6 +22742,14 @@ const RAW_RUNTIME_STATE = ["lowercase-keys", "npm:2.0.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:3.0.0", {\ + "packageLocation": "./.yarn/cache/responselike-npm-3.0.0-9ab07af81f-8af27153f7.zip/node_modules/responselike/",\ + "packageDependencies": [\ + ["responselike", "npm:3.0.0"],\ + ["lowercase-keys", "npm:3.0.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["restore-cursor", [\ @@ -22706,15 +23134,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["shallowequal", [\ - ["npm:1.1.0", {\ - "packageLocation": "./.yarn/cache/shallowequal-npm-1.1.0-6688d419cb-b926efb51c.zip/node_modules/shallowequal/",\ - "packageDependencies": [\ - ["shallowequal", "npm:1.1.0"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["shebang-command", [\ ["npm:1.2.0", {\ "packageLocation": "./.yarn/cache/shebang-command-npm-1.2.0-8990ba5d1d-7b20dbf041.zip/node_modules/shebang-command/",\ @@ -22922,7 +23341,7 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["socks-proxy-agent", "npm:8.0.3"],\ ["agent-base", "npm:7.1.1"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["socks", "npm:2.8.3"]\ ],\ "linkType": "HARD"\ @@ -23225,21 +23644,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["strict-event-emitter", [\ - ["npm:0.2.8", {\ - "packageLocation": "./.yarn/cache/strict-event-emitter-npm-0.2.8-e8b9131760-6891e19fea.zip/node_modules/strict-event-emitter/",\ - "packageDependencies": [\ - ["strict-event-emitter", "npm:0.2.8"],\ - ["events", "npm:3.3.0"]\ - ],\ - "linkType": "HARD"\ - }],\ - ["npm:0.4.6", {\ - "packageLocation": "./.yarn/cache/strict-event-emitter-npm-0.4.6-b845d23c7d-d0231ef081.zip/node_modules/strict-event-emitter/",\ - "packageDependencies": [\ - ["strict-event-emitter", "npm:0.4.6"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:0.5.1", {\ "packageLocation": "./.yarn/cache/strict-event-emitter-npm-0.5.1-8414bf36b3-f5228a6e6b.zip/node_modules/strict-event-emitter/",\ "packageDependencies": [\ @@ -23535,50 +23939,6 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ - ["styled-components", [\ - ["npm:6.1.8", {\ - "packageLocation": "./.yarn/cache/styled-components-npm-6.1.8-ae8d84c2da-fafe4b9198.zip/node_modules/styled-components/",\ - "packageDependencies": [\ - ["styled-components", "npm:6.1.8"]\ - ],\ - "linkType": "SOFT"\ - }],\ - ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:6.1.8", {\ - "packageLocation": "./.yarn/__virtual__/styled-components-virtual-cc91be02b2/0/cache/styled-components-npm-6.1.8-ae8d84c2da-fafe4b9198.zip/node_modules/styled-components/",\ - "packageDependencies": [\ - ["styled-components", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:6.1.8"],\ - ["@emotion/is-prop-valid", "npm:1.2.1"],\ - ["@emotion/unitless", "npm:0.8.0"],\ - ["@types/react", "npm:18.2.75"],\ - ["@types/react-dom", "npm:18.2.24"],\ - ["@types/stylis", "npm:4.2.0"],\ - ["css-to-react-native", "npm:3.2.0"],\ - ["csstype", "npm:3.1.2"],\ - ["postcss", "npm:8.4.31"],\ - ["react", "npm:18.2.0"],\ - ["react-dom", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:18.2.0"],\ - ["shallowequal", "npm:1.1.0"],\ - ["stylis", "npm:4.3.1"],\ - ["tslib", "npm:2.5.0"]\ - ],\ - "packagePeers": [\ - "@types/react-dom",\ - "@types/react",\ - "react-dom",\ - "react"\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ - ["stylis", [\ - ["npm:4.3.1", {\ - "packageLocation": "./.yarn/cache/stylis-npm-4.3.1-df21265105-33e8ebd2bf.zip/node_modules/stylis/",\ - "packageDependencies": [\ - ["stylis", "npm:4.3.1"]\ - ],\ - "linkType": "HARD"\ - }]\ - ]],\ ["superjson", [\ ["npm:2.2.1", {\ "packageLocation": "./.yarn/cache/superjson-npm-2.2.1-4e5de95cff-5d8202c955.zip/node_modules/superjson/",\ @@ -23755,7 +24115,7 @@ const RAW_RUNTIME_STATE = ["archiver", "npm:5.3.2"],\ ["async-lock", "npm:1.4.1"],\ ["byline", "npm:5.0.0"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["docker-compose", "npm:0.24.8"],\ ["dockerode", "npm:3.3.5"],\ ["get-port", "npm:5.1.1"],\ @@ -24113,13 +24473,6 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["tslib", [\ - ["npm:2.5.0", {\ - "packageLocation": "./.yarn/cache/tslib-npm-2.5.0-bb364efebd-e32fc99cc7.zip/node_modules/tslib/",\ - "packageDependencies": [\ - ["tslib", "npm:2.5.0"]\ - ],\ - "linkType": "HARD"\ - }],\ ["npm:2.6.2", {\ "packageLocation": "./.yarn/cache/tslib-npm-2.6.2-4fc8c068d9-e03a8a4271.zip/node_modules/tslib/",\ "packageDependencies": [\ @@ -24215,17 +24568,17 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["npm:2.19.0", {\ - "packageLocation": "./.yarn/cache/type-fest-npm-2.19.0-918b953248-a5a7ecf2e6.zip/node_modules/type-fest/",\ + ["npm:4.15.0", {\ + "packageLocation": "./.yarn/cache/type-fest-npm-4.15.0-abb5a84ffb-677a7da18d.zip/node_modules/type-fest/",\ "packageDependencies": [\ - ["type-fest", "npm:2.19.0"]\ + ["type-fest", "npm:4.15.0"]\ ],\ "linkType": "HARD"\ }],\ - ["npm:4.15.0", {\ - "packageLocation": "./.yarn/cache/type-fest-npm-4.15.0-abb5a84ffb-677a7da18d.zip/node_modules/type-fest/",\ + ["npm:4.17.0", {\ + "packageLocation": "./.yarn/cache/type-fest-npm-4.17.0-e154bcb7a2-7c474dca23.zip/node_modules/type-fest/",\ "packageDependencies": [\ - ["type-fest", "npm:4.15.0"]\ + ["type-fest", "npm:4.17.0"]\ ],\ "linkType": "HARD"\ }]\ @@ -24724,6 +25077,13 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["uuid", [\ + ["npm:8.3.2", {\ + "packageLocation": "./.yarn/cache/uuid-npm-8.3.2-eca0baba53-bcbb807a91.zip/node_modules/uuid/",\ + "packageDependencies": [\ + ["uuid", "npm:8.3.2"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:9.0.1", {\ "packageLocation": "./.yarn/cache/uuid-npm-9.0.1-39a8442bc6-1607dd32ac.zip/node_modules/uuid/",\ "packageDependencies": [\ @@ -24922,10 +25282,10 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:c8accb5ca782364c24154d1f350b9826a040fc4daaa014d0d835f03af8814a71f5ab57c86b0b470a30a828d18db6c9983db47f634d1ceeebd925893f97a96573#npm:5.2.8", {\ - "packageLocation": "./.yarn/__virtual__/vite-virtual-0abe43c7a4/0/cache/vite-npm-5.2.8-618ece674d-b5717bb00c.zip/node_modules/vite/",\ + ["virtual:bd1f08852d067a639e3172abe37893eb5e211e315e94db0aef41b640e63051b506f25e24923bd01fb2897af683dd8bbffc4d7b53b647f050bf3db809253b8295#npm:5.2.8", {\ + "packageLocation": "./.yarn/__virtual__/vite-virtual-da960aa09b/0/cache/vite-npm-5.2.8-618ece674d-b5717bb00c.zip/node_modules/vite/",\ "packageDependencies": [\ - ["vite", "virtual:c8accb5ca782364c24154d1f350b9826a040fc4daaa014d0d835f03af8814a71f5ab57c86b0b470a30a828d18db6c9983db47f634d1ceeebd925893f97a96573#npm:5.2.8"],\ + ["vite", "virtual:bd1f08852d067a639e3172abe37893eb5e211e315e94db0aef41b640e63051b506f25e24923bd01fb2897af683dd8bbffc4d7b53b647f050bf3db809253b8295#npm:5.2.8"],\ ["@types/less", null],\ ["@types/lightningcss", null],\ ["@types/node", "npm:20.12.7"],\ @@ -25007,19 +25367,19 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["vite-node", "npm:1.5.0"],\ ["cac", "npm:6.7.14"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["pathe", "npm:1.1.2"],\ ["picocolors", "npm:1.0.0"],\ ["vite", "virtual:231bd830519c975d6e142167646edd028538c46a384a9b8698b9b3218f572b63d5b2815d19e56e1bc499a4cdeadc44536b8e95322dcd5751eea4f6815a445aa4#npm:5.2.8"]\ ],\ "linkType": "HARD"\ }],\ - ["npm:1.5.1", {\ - "packageLocation": "./.yarn/cache/vite-node-npm-1.5.1-fd703ad005-d3591d9c30.zip/node_modules/vite-node/",\ + ["npm:1.5.2", {\ + "packageLocation": "./.yarn/cache/vite-node-npm-1.5.2-3f4f4e44d5-a5e90ae2b3.zip/node_modules/vite-node/",\ "packageDependencies": [\ - ["vite-node", "npm:1.5.1"],\ + ["vite-node", "npm:1.5.2"],\ ["cac", "npm:6.7.14"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["pathe", "npm:1.1.2"],\ ["picocolors", "npm:1.0.0"],\ ["vite", "virtual:231bd830519c975d6e142167646edd028538c46a384a9b8698b9b3218f572b63d5b2815d19e56e1bc499a4cdeadc44536b8e95322dcd5751eea4f6815a445aa4#npm:5.2.8"]\ @@ -25028,17 +25388,17 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["vitest", [\ - ["npm:1.5.1", {\ - "packageLocation": "./.yarn/cache/vitest-npm-1.5.1-da8c0fa81f-85f6b9250c.zip/node_modules/vitest/",\ + ["npm:1.5.2", {\ + "packageLocation": "./.yarn/cache/vitest-npm-1.5.2-db4ab193ee-1ad3a33d3a.zip/node_modules/vitest/",\ "packageDependencies": [\ - ["vitest", "npm:1.5.1"]\ + ["vitest", "npm:1.5.2"]\ ],\ "linkType": "SOFT"\ }],\ - ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1", {\ - "packageLocation": "./.yarn/__virtual__/vitest-virtual-c8accb5ca7/0/cache/vitest-npm-1.5.1-da8c0fa81f-85f6b9250c.zip/node_modules/vitest/",\ + ["virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2", {\ + "packageLocation": "./.yarn/__virtual__/vitest-virtual-bd1f08852d/0/cache/vitest-npm-1.5.2-db4ab193ee-1ad3a33d3a.zip/node_modules/vitest/",\ "packageDependencies": [\ - ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"],\ + ["vitest", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"],\ ["@edge-runtime/vm", null],\ ["@types/edge-runtime__vm", null],\ ["@types/happy-dom", null],\ @@ -25047,15 +25407,15 @@ const RAW_RUNTIME_STATE = ["@types/vitest__browser", null],\ ["@types/vitest__ui", null],\ ["@vitest/browser", null],\ - ["@vitest/expect", "npm:1.5.1"],\ - ["@vitest/runner", "npm:1.5.1"],\ - ["@vitest/snapshot", "npm:1.5.1"],\ - ["@vitest/spy", "npm:1.5.1"],\ - ["@vitest/ui", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.1"],\ - ["@vitest/utils", "npm:1.5.1"],\ + ["@vitest/expect", "npm:1.5.2"],\ + ["@vitest/runner", "npm:1.5.2"],\ + ["@vitest/snapshot", "npm:1.5.2"],\ + ["@vitest/spy", "npm:1.5.2"],\ + ["@vitest/ui", "virtual:4693e2adf740857f263b3cecb982e42dfab2bbaea841273a76fd4bb0d3ba85e3b6808c5d98439071448ab2131d3c0226971ce4e558290b9a29867f6017ede1e3#npm:1.5.2"],\ + ["@vitest/utils", "npm:1.5.2"],\ ["acorn-walk", "npm:8.3.2"],\ ["chai", "npm:4.4.1"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["execa", "npm:8.0.1"],\ ["happy-dom", "npm:14.7.1"],\ ["jsdom", null],\ @@ -25067,8 +25427,8 @@ const RAW_RUNTIME_STATE = ["strip-literal", "npm:2.1.0"],\ ["tinybench", "npm:2.6.0"],\ ["tinypool", "npm:0.8.3"],\ - ["vite", "virtual:c8accb5ca782364c24154d1f350b9826a040fc4daaa014d0d835f03af8814a71f5ab57c86b0b470a30a828d18db6c9983db47f634d1ceeebd925893f97a96573#npm:5.2.8"],\ - ["vite-node", "npm:1.5.1"],\ + ["vite", "virtual:bd1f08852d067a639e3172abe37893eb5e211e315e94db0aef41b640e63051b506f25e24923bd01fb2897af683dd8bbffc4d7b53b647f050bf3db809253b8295#npm:5.2.8"],\ + ["vite-node", "npm:1.5.2"],\ ["why-is-node-running", "npm:2.2.2"]\ ],\ "packagePeers": [\ @@ -25086,10 +25446,10 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ - ["virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:1.5.1", {\ - "packageLocation": "./.yarn/__virtual__/vitest-virtual-0046d0c926/0/cache/vitest-npm-1.5.1-da8c0fa81f-85f6b9250c.zip/node_modules/vitest/",\ + ["virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:1.5.2", {\ + "packageLocation": "./.yarn/__virtual__/vitest-virtual-8ed5ee8d0d/0/cache/vitest-npm-1.5.2-db4ab193ee-1ad3a33d3a.zip/node_modules/vitest/",\ "packageDependencies": [\ - ["vitest", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:1.5.1"],\ + ["vitest", "virtual:b4dbac12e8c0eac19977455c27007fa0bab83d73d73781bdd06afb97db468ee42cd13130e5a6cca03948b2e68a51074131e9ffe5919a808a1f95312007ab4bc4#npm:1.5.2"],\ ["@edge-runtime/vm", null],\ ["@types/edge-runtime__vm", null],\ ["@types/happy-dom", null],\ @@ -25098,15 +25458,15 @@ const RAW_RUNTIME_STATE = ["@types/vitest__browser", null],\ ["@types/vitest__ui", null],\ ["@vitest/browser", null],\ - ["@vitest/expect", "npm:1.5.1"],\ - ["@vitest/runner", "npm:1.5.1"],\ - ["@vitest/snapshot", "npm:1.5.1"],\ - ["@vitest/spy", "npm:1.5.1"],\ + ["@vitest/expect", "npm:1.5.2"],\ + ["@vitest/runner", "npm:1.5.2"],\ + ["@vitest/snapshot", "npm:1.5.2"],\ + ["@vitest/spy", "npm:1.5.2"],\ ["@vitest/ui", null],\ - ["@vitest/utils", "npm:1.5.1"],\ + ["@vitest/utils", "npm:1.5.2"],\ ["acorn-walk", "npm:8.3.2"],\ ["chai", "npm:4.4.1"],\ - ["debug", "virtual:c9e1a4b59e37cb479517edede3bf2093b28c0ca1a9d0e517f3c345075bd1e468980b94b4957e389116607ee7155441dfd7d09e19a4229d5d09bcf06244401590#npm:4.3.4"],\ + ["debug", "virtual:e80ee691e1471061b2fa4aa86f86ff0dcaf67db5ccb8fe206d99a78dff177cc8cd6a308ebabe15e3e31fe6a0e1673dcbbf417b63d8c5b5b6c5c22abce38ec44a#npm:4.3.4"],\ ["execa", "npm:8.0.1"],\ ["happy-dom", null],\ ["jsdom", null],\ @@ -25118,8 +25478,8 @@ const RAW_RUNTIME_STATE = ["strip-literal", "npm:2.1.0"],\ ["tinybench", "npm:2.6.0"],\ ["tinypool", "npm:0.8.3"],\ - ["vite", "virtual:c8accb5ca782364c24154d1f350b9826a040fc4daaa014d0d835f03af8814a71f5ab57c86b0b470a30a828d18db6c9983db47f634d1ceeebd925893f97a96573#npm:5.2.8"],\ - ["vite-node", "npm:1.5.1"],\ + ["vite", "virtual:bd1f08852d067a639e3172abe37893eb5e211e315e94db0aef41b640e63051b506f25e24923bd01fb2897af683dd8bbffc4d7b53b647f050bf3db809253b8295#npm:5.2.8"],\ + ["vite-node", "npm:1.5.2"],\ ["why-is-node-running", "npm:2.2.2"]\ ],\ "packagePeers": [\ diff --git a/.yarn/cache/@emotion-is-prop-valid-npm-1.2.1-794afe6a94-7c2aabdf0c.zip b/.yarn/cache/@emotion-is-prop-valid-npm-1.2.1-794afe6a94-7c2aabdf0c.zip deleted file mode 100644 index dc84fa8..0000000 Binary files a/.yarn/cache/@emotion-is-prop-valid-npm-1.2.1-794afe6a94-7c2aabdf0c.zip and /dev/null differ diff --git a/.yarn/cache/@emotion-memoize-npm-0.8.1-9b1e35ff15-dffed372fc.zip b/.yarn/cache/@emotion-memoize-npm-0.8.1-9b1e35ff15-dffed372fc.zip deleted file mode 100644 index 320c9e5..0000000 Binary files a/.yarn/cache/@emotion-memoize-npm-0.8.1-9b1e35ff15-dffed372fc.zip and /dev/null differ diff --git a/.yarn/cache/@emotion-unitless-npm-0.8.0-aa125284fa-1f2cfb7c0c.zip b/.yarn/cache/@emotion-unitless-npm-0.8.0-aa125284fa-1f2cfb7c0c.zip deleted file mode 100644 index ae5ecea..0000000 Binary files a/.yarn/cache/@emotion-unitless-npm-0.8.0-aa125284fa-1f2cfb7c0c.zip and /dev/null differ diff --git a/.yarn/cache/@mswjs-cookies-npm-0.2.2-fdd3f4ab67-f950062538.zip b/.yarn/cache/@mswjs-cookies-npm-0.2.2-fdd3f4ab67-f950062538.zip deleted file mode 100644 index 35a0c47..0000000 Binary files a/.yarn/cache/@mswjs-cookies-npm-0.2.2-fdd3f4ab67-f950062538.zip and /dev/null differ diff --git a/.yarn/cache/@mswjs-data-npm-0.16.1-e80ee691e1-9518f5e918.zip b/.yarn/cache/@mswjs-data-npm-0.16.1-e80ee691e1-9518f5e918.zip new file mode 100644 index 0000000..df190bd Binary files /dev/null and b/.yarn/cache/@mswjs-data-npm-0.16.1-e80ee691e1-9518f5e918.zip differ diff --git a/.yarn/cache/@mswjs-interceptors-npm-0.17.10-c1199a9424-0343a93711.zip b/.yarn/cache/@mswjs-interceptors-npm-0.17.10-c1199a9424-0343a93711.zip deleted file mode 100644 index 13e3acd..0000000 Binary files a/.yarn/cache/@mswjs-interceptors-npm-0.17.10-c1199a9424-0343a93711.zip and /dev/null differ diff --git a/.yarn/cache/@noble-hashes-npm-1.4.0-9389282fd6-8c3f005ee7.zip b/.yarn/cache/@noble-hashes-npm-1.4.0-9389282fd6-8c3f005ee7.zip new file mode 100644 index 0000000..6bccd24 Binary files /dev/null and b/.yarn/cache/@noble-hashes-npm-1.4.0-9389282fd6-8c3f005ee7.zip differ diff --git a/.yarn/cache/@open-draft-until-npm-1.0.3-c0d6a46a29-f88bcd774b.zip b/.yarn/cache/@open-draft-until-npm-1.0.3-c0d6a46a29-f88bcd774b.zip deleted file mode 100644 index 3c62dd6..0000000 Binary files a/.yarn/cache/@open-draft-until-npm-1.0.3-c0d6a46a29-f88bcd774b.zip and /dev/null differ diff --git a/.yarn/cache/@paralleldrive-cuid2-npm-2.2.2-e6061749b2-af5826df93.zip b/.yarn/cache/@paralleldrive-cuid2-npm-2.2.2-e6061749b2-af5826df93.zip new file mode 100644 index 0000000..e7963f4 Binary files /dev/null and b/.yarn/cache/@paralleldrive-cuid2-npm-2.2.2-e6061749b2-af5826df93.zip differ diff --git a/.yarn/cache/@remix-run-v1-route-convention-npm-0.1.4-d336e45418-f9984d9212.zip b/.yarn/cache/@remix-run-v1-route-convention-npm-0.1.4-d336e45418-f9984d9212.zip new file mode 100644 index 0000000..c366b83 Binary files /dev/null and b/.yarn/cache/@remix-run-v1-route-convention-npm-0.1.4-d336e45418-f9984d9212.zip differ diff --git a/.yarn/cache/@sindresorhus-is-npm-6.3.0-0c6ba20d57-40d201fc1a.zip b/.yarn/cache/@sindresorhus-is-npm-6.3.0-0c6ba20d57-40d201fc1a.zip new file mode 100644 index 0000000..0a41cce Binary files /dev/null and b/.yarn/cache/@sindresorhus-is-npm-6.3.0-0c6ba20d57-40d201fc1a.zip differ diff --git a/.yarn/cache/@szmarczak-http-timer-npm-5.0.1-52261e5986-4629d2fbb2.zip b/.yarn/cache/@szmarczak-http-timer-npm-5.0.1-52261e5986-4629d2fbb2.zip new file mode 100644 index 0000000..fc32050 Binary files /dev/null and b/.yarn/cache/@szmarczak-http-timer-npm-5.0.1-52261e5986-4629d2fbb2.zip differ diff --git a/.yarn/cache/@testing-library-dom-npm-10.0.0-708b4ef7e6-2d12d2a601.zip b/.yarn/cache/@testing-library-dom-npm-10.0.0-708b4ef7e6-2d12d2a601.zip new file mode 100644 index 0000000..cbbfe07 Binary files /dev/null and b/.yarn/cache/@testing-library-dom-npm-10.0.0-708b4ef7e6-2d12d2a601.zip differ diff --git a/.yarn/cache/@testing-library-user-event-npm-14.5.2-ec9587901c-68a0c2aa28.zip b/.yarn/cache/@testing-library-user-event-npm-14.5.2-ec9587901c-68a0c2aa28.zip new file mode 100644 index 0000000..dc34e29 Binary files /dev/null and b/.yarn/cache/@testing-library-user-event-npm-14.5.2-ec9587901c-68a0c2aa28.zip differ diff --git a/.yarn/cache/@types-cookie-npm-0.4.1-274a704dc6-f96afe12bd.zip b/.yarn/cache/@types-cookie-npm-0.4.1-274a704dc6-f96afe12bd.zip deleted file mode 100644 index 939d7b1..0000000 Binary files a/.yarn/cache/@types-cookie-npm-0.4.1-274a704dc6-f96afe12bd.zip and /dev/null differ diff --git a/.yarn/cache/@types-hoist-non-react-statics-npm-3.3.5-98b8d8e47b-2a3b64bf3d.zip b/.yarn/cache/@types-hoist-non-react-statics-npm-3.3.5-98b8d8e47b-2a3b64bf3d.zip deleted file mode 100644 index 84ef124..0000000 Binary files a/.yarn/cache/@types-hoist-non-react-statics-npm-3.3.5-98b8d8e47b-2a3b64bf3d.zip and /dev/null differ diff --git a/.yarn/cache/@types-js-levenshtein-npm-1.1.3-417b5f0c21-025f2bd8d8.zip b/.yarn/cache/@types-js-levenshtein-npm-1.1.3-417b5f0c21-025f2bd8d8.zip deleted file mode 100644 index bb235ce..0000000 Binary files a/.yarn/cache/@types-js-levenshtein-npm-1.1.3-417b5f0c21-025f2bd8d8.zip and /dev/null differ diff --git a/.yarn/cache/@types-lodash-npm-4.17.0-11e757616b-4c5b41c9a6.zip b/.yarn/cache/@types-lodash-npm-4.17.0-11e757616b-4c5b41c9a6.zip new file mode 100644 index 0000000..fbf2d55 Binary files /dev/null and b/.yarn/cache/@types-lodash-npm-4.17.0-11e757616b-4c5b41c9a6.zip differ diff --git a/.yarn/cache/@types-md5-npm-2.3.5-bd5c825c57-aef9c40ab0.zip b/.yarn/cache/@types-md5-npm-2.3.5-bd5c825c57-aef9c40ab0.zip new file mode 100644 index 0000000..cf2dce8 Binary files /dev/null and b/.yarn/cache/@types-md5-npm-2.3.5-bd5c825c57-aef9c40ab0.zip differ diff --git a/.yarn/cache/@types-pluralize-npm-0.0.29-a6b8916fba-840796fa1d.zip b/.yarn/cache/@types-pluralize-npm-0.0.29-a6b8916fba-840796fa1d.zip new file mode 100644 index 0000000..c7d021d Binary files /dev/null and b/.yarn/cache/@types-pluralize-npm-0.0.29-a6b8916fba-840796fa1d.zip differ diff --git a/.yarn/cache/@types-set-cookie-parser-npm-2.4.7-e9d6d979b1-3c4b5168fe.zip b/.yarn/cache/@types-set-cookie-parser-npm-2.4.7-e9d6d979b1-3c4b5168fe.zip deleted file mode 100644 index 86041c2..0000000 Binary files a/.yarn/cache/@types-set-cookie-parser-npm-2.4.7-e9d6d979b1-3c4b5168fe.zip and /dev/null differ diff --git a/.yarn/cache/@types-styled-components-npm-5.1.34-c1fd4bac77-5bce93ea2c.zip b/.yarn/cache/@types-styled-components-npm-5.1.34-c1fd4bac77-5bce93ea2c.zip deleted file mode 100644 index 5080e3d..0000000 Binary files a/.yarn/cache/@types-styled-components-npm-5.1.34-c1fd4bac77-5bce93ea2c.zip and /dev/null differ diff --git a/.yarn/cache/@types-stylis-npm-4.2.0-5addc9ed60-c76c13e76c.zip b/.yarn/cache/@types-stylis-npm-4.2.0-5addc9ed60-c76c13e76c.zip deleted file mode 100644 index b1f7803..0000000 Binary files a/.yarn/cache/@types-stylis-npm-4.2.0-5addc9ed60-c76c13e76c.zip and /dev/null differ diff --git a/.yarn/cache/@types-uuid-npm-8.3.4-7547f4402c-b9ac98f82f.zip b/.yarn/cache/@types-uuid-npm-8.3.4-7547f4402c-b9ac98f82f.zip new file mode 100644 index 0000000..929871b Binary files /dev/null and b/.yarn/cache/@types-uuid-npm-8.3.4-7547f4402c-b9ac98f82f.zip differ diff --git a/.yarn/cache/@vanilla-extract-integration-npm-7.1.2-fadf75bb6c-c4bb99d3ca.zip b/.yarn/cache/@vanilla-extract-integration-npm-7.1.2-fadf75bb6c-c4bb99d3ca.zip new file mode 100644 index 0000000..142cab3 Binary files /dev/null and b/.yarn/cache/@vanilla-extract-integration-npm-7.1.2-fadf75bb6c-c4bb99d3ca.zip differ diff --git a/.yarn/cache/@vanilla-extract-sprinkles-npm-1.6.1-e524ee399f-7ddd2ab7c8.zip b/.yarn/cache/@vanilla-extract-sprinkles-npm-1.6.1-e524ee399f-7ddd2ab7c8.zip new file mode 100644 index 0000000..275d531 Binary files /dev/null and b/.yarn/cache/@vanilla-extract-sprinkles-npm-1.6.1-e524ee399f-7ddd2ab7c8.zip differ diff --git a/.yarn/cache/@vanilla-extract-vite-plugin-npm-4.0.7-55893955b8-1d9dd8bdd7.zip b/.yarn/cache/@vanilla-extract-vite-plugin-npm-4.0.7-55893955b8-1d9dd8bdd7.zip new file mode 100644 index 0000000..f5390e3 Binary files /dev/null and b/.yarn/cache/@vanilla-extract-vite-plugin-npm-4.0.7-55893955b8-1d9dd8bdd7.zip differ diff --git a/.yarn/cache/@vitest-coverage-v8-npm-1.5.1-12c3829e02-614b0a7ca0.zip b/.yarn/cache/@vitest-coverage-v8-npm-1.5.2-0f1947c29f-cc98275396.zip similarity index 99% rename from .yarn/cache/@vitest-coverage-v8-npm-1.5.1-12c3829e02-614b0a7ca0.zip rename to .yarn/cache/@vitest-coverage-v8-npm-1.5.2-0f1947c29f-cc98275396.zip index ac3525a..1833867 100644 Binary files a/.yarn/cache/@vitest-coverage-v8-npm-1.5.1-12c3829e02-614b0a7ca0.zip and b/.yarn/cache/@vitest-coverage-v8-npm-1.5.2-0f1947c29f-cc98275396.zip differ diff --git a/.yarn/cache/@vitest-expect-npm-1.5.1-9cc59d304b-4743ca8de3.zip b/.yarn/cache/@vitest-expect-npm-1.5.2-3b855b8075-4e8400a55f.zip similarity index 99% rename from .yarn/cache/@vitest-expect-npm-1.5.1-9cc59d304b-4743ca8de3.zip rename to .yarn/cache/@vitest-expect-npm-1.5.2-3b855b8075-4e8400a55f.zip index 7be4649..e9f512d 100644 Binary files a/.yarn/cache/@vitest-expect-npm-1.5.1-9cc59d304b-4743ca8de3.zip and b/.yarn/cache/@vitest-expect-npm-1.5.2-3b855b8075-4e8400a55f.zip differ diff --git a/.yarn/cache/@vitest-runner-npm-1.5.1-1bd8a6b0c9-a079c111c9.zip b/.yarn/cache/@vitest-runner-npm-1.5.2-c6689dee82-9fc3e66881.zip similarity index 99% rename from .yarn/cache/@vitest-runner-npm-1.5.1-1bd8a6b0c9-a079c111c9.zip rename to .yarn/cache/@vitest-runner-npm-1.5.2-c6689dee82-9fc3e66881.zip index 68c132c..34f8e81 100644 Binary files a/.yarn/cache/@vitest-runner-npm-1.5.1-1bd8a6b0c9-a079c111c9.zip and b/.yarn/cache/@vitest-runner-npm-1.5.2-c6689dee82-9fc3e66881.zip differ diff --git a/.yarn/cache/@vitest-snapshot-npm-1.5.1-87cae6bf67-d3d769873b.zip b/.yarn/cache/@vitest-snapshot-npm-1.5.2-791e3d9f82-67ae235e59.zip similarity index 99% rename from .yarn/cache/@vitest-snapshot-npm-1.5.1-87cae6bf67-d3d769873b.zip rename to .yarn/cache/@vitest-snapshot-npm-1.5.2-791e3d9f82-67ae235e59.zip index 6d143ca..d6ba201 100644 Binary files a/.yarn/cache/@vitest-snapshot-npm-1.5.1-87cae6bf67-d3d769873b.zip and b/.yarn/cache/@vitest-snapshot-npm-1.5.2-791e3d9f82-67ae235e59.zip differ diff --git a/.yarn/cache/@vitest-spy-npm-1.5.1-9ec8baf765-865b94bc99.zip b/.yarn/cache/@vitest-spy-npm-1.5.2-b9c126ac34-d66de2873f.zip similarity index 99% rename from .yarn/cache/@vitest-spy-npm-1.5.1-9ec8baf765-865b94bc99.zip rename to .yarn/cache/@vitest-spy-npm-1.5.2-b9c126ac34-d66de2873f.zip index 918de04..52e5529 100644 Binary files a/.yarn/cache/@vitest-spy-npm-1.5.1-9ec8baf765-865b94bc99.zip and b/.yarn/cache/@vitest-spy-npm-1.5.2-b9c126ac34-d66de2873f.zip differ diff --git a/.yarn/cache/@vitest-ui-npm-1.5.1-18a33515ae-efba22a08b.zip b/.yarn/cache/@vitest-ui-npm-1.5.2-b335b96316-85fc78e0b3.zip similarity index 99% rename from .yarn/cache/@vitest-ui-npm-1.5.1-18a33515ae-efba22a08b.zip rename to .yarn/cache/@vitest-ui-npm-1.5.2-b335b96316-85fc78e0b3.zip index 61aca48..6fa4f4f 100644 Binary files a/.yarn/cache/@vitest-ui-npm-1.5.1-18a33515ae-efba22a08b.zip and b/.yarn/cache/@vitest-ui-npm-1.5.2-b335b96316-85fc78e0b3.zip differ diff --git a/.yarn/cache/@vitest-utils-npm-1.5.1-e51d68286e-45bef3c3c5.zip b/.yarn/cache/@vitest-utils-npm-1.5.2-7cf804c58e-019eeac016.zip similarity index 99% rename from .yarn/cache/@vitest-utils-npm-1.5.1-e51d68286e-45bef3c3c5.zip rename to .yarn/cache/@vitest-utils-npm-1.5.2-7cf804c58e-019eeac016.zip index 2b634a5..682dce4 100644 Binary files a/.yarn/cache/@vitest-utils-npm-1.5.1-e51d68286e-45bef3c3c5.zip and b/.yarn/cache/@vitest-utils-npm-1.5.2-7cf804c58e-019eeac016.zip differ diff --git a/.yarn/cache/@xmldom-xmldom-npm-0.8.10-c1bd991e61-c7647c4425.zip b/.yarn/cache/@xmldom-xmldom-npm-0.8.10-c1bd991e61-c7647c4425.zip deleted file mode 100644 index 21c4314..0000000 Binary files a/.yarn/cache/@xmldom-xmldom-npm-0.8.10-c1bd991e61-c7647c4425.zip and /dev/null differ diff --git a/.yarn/cache/cacheable-lookup-npm-7.0.0-b6cd95c14a-63a9c144c5.zip b/.yarn/cache/cacheable-lookup-npm-7.0.0-b6cd95c14a-63a9c144c5.zip new file mode 100644 index 0000000..c0bc5de Binary files /dev/null and b/.yarn/cache/cacheable-lookup-npm-7.0.0-b6cd95c14a-63a9c144c5.zip differ diff --git a/.yarn/cache/cacheable-request-npm-10.2.14-fd919b07d7-41b6658db3.zip b/.yarn/cache/cacheable-request-npm-10.2.14-fd919b07d7-41b6658db3.zip new file mode 100644 index 0000000..112b012 Binary files /dev/null and b/.yarn/cache/cacheable-request-npm-10.2.14-fd919b07d7-41b6658db3.zip differ diff --git a/.yarn/cache/camelize-npm-1.0.1-d86ebe085a-4c9ac55efd.zip b/.yarn/cache/camelize-npm-1.0.1-d86ebe085a-4c9ac55efd.zip deleted file mode 100644 index ba4735a..0000000 Binary files a/.yarn/cache/camelize-npm-1.0.1-d86ebe085a-4c9ac55efd.zip and /dev/null differ diff --git a/.yarn/cache/charenc-npm-0.0.2-aca0c2f207-a45ec39363.zip b/.yarn/cache/charenc-npm-0.0.2-aca0c2f207-a45ec39363.zip new file mode 100644 index 0000000..10ef15c Binary files /dev/null and b/.yarn/cache/charenc-npm-0.0.2-aca0c2f207-a45ec39363.zip differ diff --git a/.yarn/cache/cookie-npm-0.4.2-7761894d5f-beab41fbd7.zip b/.yarn/cache/cookie-npm-0.4.2-7761894d5f-beab41fbd7.zip deleted file mode 100644 index 9c19a61..0000000 Binary files a/.yarn/cache/cookie-npm-0.4.2-7761894d5f-beab41fbd7.zip and /dev/null differ diff --git a/.yarn/cache/crypt-npm-0.0.2-033627d94f-adbf263441.zip b/.yarn/cache/crypt-npm-0.0.2-033627d94f-adbf263441.zip new file mode 100644 index 0000000..0de38b1 Binary files /dev/null and b/.yarn/cache/crypt-npm-0.0.2-033627d94f-adbf263441.zip differ diff --git a/.yarn/cache/css-color-keywords-npm-1.0.0-fc176df58b-af205a86c6.zip b/.yarn/cache/css-color-keywords-npm-1.0.0-fc176df58b-af205a86c6.zip deleted file mode 100644 index cc088c1..0000000 Binary files a/.yarn/cache/css-color-keywords-npm-1.0.0-fc176df58b-af205a86c6.zip and /dev/null differ diff --git a/.yarn/cache/css-to-react-native-npm-3.2.0-46e31a25e3-fde850a511.zip b/.yarn/cache/css-to-react-native-npm-3.2.0-46e31a25e3-fde850a511.zip deleted file mode 100644 index 974f7d0..0000000 Binary files a/.yarn/cache/css-to-react-native-npm-3.2.0-46e31a25e3-fde850a511.zip and /dev/null differ diff --git a/.yarn/cache/csstype-npm-3.1.2-cead7d99b2-32c038af25.zip b/.yarn/cache/csstype-npm-3.1.2-cead7d99b2-32c038af25.zip deleted file mode 100644 index edf361b..0000000 Binary files a/.yarn/cache/csstype-npm-3.1.2-cead7d99b2-32c038af25.zip and /dev/null differ diff --git a/.yarn/cache/cuid-npm-3.0.0-66e229f427-e1cac04b8d.zip b/.yarn/cache/cuid-npm-3.0.0-66e229f427-e1cac04b8d.zip deleted file mode 100644 index d5c35ca..0000000 Binary files a/.yarn/cache/cuid-npm-3.0.0-66e229f427-e1cac04b8d.zip and /dev/null differ diff --git a/.yarn/cache/date-fns-npm-2.30.0-895c790e0f-e4b521fbf2.zip b/.yarn/cache/date-fns-npm-2.30.0-895c790e0f-e4b521fbf2.zip new file mode 100644 index 0000000..28d87e1 Binary files /dev/null and b/.yarn/cache/date-fns-npm-2.30.0-895c790e0f-e4b521fbf2.zip differ diff --git a/.yarn/cache/depd-npm-1.1.2-b0c8414da7-acb24aaf93.zip b/.yarn/cache/depd-npm-1.1.2-b0c8414da7-acb24aaf93.zip new file mode 100644 index 0000000..73a0240 Binary files /dev/null and b/.yarn/cache/depd-npm-1.1.2-b0c8414da7-acb24aaf93.zip differ diff --git a/.yarn/cache/events-npm-3.3.0-c280bc7e48-d6b6f2adbc.zip b/.yarn/cache/events-npm-3.3.0-c280bc7e48-d6b6f2adbc.zip deleted file mode 100644 index 4a41e81..0000000 Binary files a/.yarn/cache/events-npm-3.3.0-c280bc7e48-d6b6f2adbc.zip and /dev/null differ diff --git a/.yarn/cache/form-data-encoder-npm-4.0.2-aa021c3f21-559d3130e2.zip b/.yarn/cache/form-data-encoder-npm-4.0.2-aa021c3f21-559d3130e2.zip new file mode 100644 index 0000000..70c100c Binary files /dev/null and b/.yarn/cache/form-data-encoder-npm-4.0.2-aa021c3f21-559d3130e2.zip differ diff --git a/.yarn/cache/got-npm-14.2.1-e13379605e-6592f70d57.zip b/.yarn/cache/got-npm-14.2.1-e13379605e-6592f70d57.zip new file mode 100644 index 0000000..cbea23b Binary files /dev/null and b/.yarn/cache/got-npm-14.2.1-e13379605e-6592f70d57.zip differ diff --git a/.yarn/cache/graphql-scalars-npm-1.23.0-afcf92cba2-7666c305b8.zip b/.yarn/cache/graphql-scalars-npm-1.23.0-afcf92cba2-7666c305b8.zip new file mode 100644 index 0000000..ab86c45 Binary files /dev/null and b/.yarn/cache/graphql-scalars-npm-1.23.0-afcf92cba2-7666c305b8.zip differ diff --git a/.yarn/cache/graphql-transform-scalars-npm-1.2.1-419c342fcf-d170e808a2.zip b/.yarn/cache/graphql-transform-scalars-npm-1.2.1-419c342fcf-d170e808a2.zip new file mode 100644 index 0000000..884bada Binary files /dev/null and b/.yarn/cache/graphql-transform-scalars-npm-1.2.1-419c342fcf-d170e808a2.zip differ diff --git a/.yarn/cache/headers-polyfill-npm-3.2.5-5873ac13a0-10202f4ebf.zip b/.yarn/cache/headers-polyfill-npm-3.2.5-5873ac13a0-10202f4ebf.zip deleted file mode 100644 index a80a3d6..0000000 Binary files a/.yarn/cache/headers-polyfill-npm-3.2.5-5873ac13a0-10202f4ebf.zip and /dev/null differ diff --git a/.yarn/cache/hoist-non-react-statics-npm-3.3.2-e7b709e6c1-fe0889169e.zip b/.yarn/cache/hoist-non-react-statics-npm-3.3.2-e7b709e6c1-fe0889169e.zip deleted file mode 100644 index 5f7b8a8..0000000 Binary files a/.yarn/cache/hoist-non-react-statics-npm-3.3.2-e7b709e6c1-fe0889169e.zip and /dev/null differ diff --git a/.yarn/cache/http2-wrapper-npm-2.2.1-c033aaabde-7207201d3c.zip b/.yarn/cache/http2-wrapper-npm-2.2.1-c033aaabde-7207201d3c.zip new file mode 100644 index 0000000..fb0c8f5 Binary files /dev/null and b/.yarn/cache/http2-wrapper-npm-2.2.1-c033aaabde-7207201d3c.zip differ diff --git a/.yarn/cache/is-buffer-npm-1.1.6-08199d9ccc-ae18aa0b6e.zip b/.yarn/cache/is-buffer-npm-1.1.6-08199d9ccc-ae18aa0b6e.zip new file mode 100644 index 0000000..082d5a6 Binary files /dev/null and b/.yarn/cache/is-buffer-npm-1.1.6-08199d9ccc-ae18aa0b6e.zip differ diff --git a/.yarn/cache/js-levenshtein-npm-1.1.6-ab883e61a3-1404573532.zip b/.yarn/cache/js-levenshtein-npm-1.1.6-ab883e61a3-1404573532.zip deleted file mode 100644 index 4776ca8..0000000 Binary files a/.yarn/cache/js-levenshtein-npm-1.1.6-ab883e61a3-1404573532.zip and /dev/null differ diff --git a/.yarn/cache/jwt-decode-npm-4.0.0-4cd8e89909-de75bbf892.zip b/.yarn/cache/jwt-decode-npm-4.0.0-4cd8e89909-de75bbf892.zip new file mode 100644 index 0000000..a0523c1 Binary files /dev/null and b/.yarn/cache/jwt-decode-npm-4.0.0-4cd8e89909-de75bbf892.zip differ diff --git a/.yarn/cache/lowercase-keys-npm-3.0.0-f8c4730215-ef62b9fa56.zip b/.yarn/cache/lowercase-keys-npm-3.0.0-f8c4730215-ef62b9fa56.zip new file mode 100644 index 0000000..bda5d66 Binary files /dev/null and b/.yarn/cache/lowercase-keys-npm-3.0.0-f8c4730215-ef62b9fa56.zip differ diff --git a/.yarn/cache/md5-npm-2.3.0-86c49d3915-14a21d597d.zip b/.yarn/cache/md5-npm-2.3.0-86c49d3915-14a21d597d.zip new file mode 100644 index 0000000..6770dd3 Binary files /dev/null and b/.yarn/cache/md5-npm-2.3.0-86c49d3915-14a21d597d.zip differ diff --git a/.yarn/cache/merge-descriptors-npm-1.0.3-10b44ad75c-866b7094af.zip b/.yarn/cache/merge-descriptors-npm-1.0.3-10b44ad75c-866b7094af.zip new file mode 100644 index 0000000..c55a6d3 Binary files /dev/null and b/.yarn/cache/merge-descriptors-npm-1.0.3-10b44ad75c-866b7094af.zip differ diff --git a/.yarn/cache/mimic-response-npm-4.0.0-c080547e26-761d788d26.zip b/.yarn/cache/mimic-response-npm-4.0.0-c080547e26-761d788d26.zip new file mode 100644 index 0000000..e4d2c2d Binary files /dev/null and b/.yarn/cache/mimic-response-npm-4.0.0-c080547e26-761d788d26.zip differ diff --git a/.yarn/cache/mock-jwks-patch-9a7688505b-678cdce347.zip b/.yarn/cache/mock-jwks-patch-9a7688505b-678cdce347.zip new file mode 100644 index 0000000..4949bab Binary files /dev/null and b/.yarn/cache/mock-jwks-patch-9a7688505b-678cdce347.zip differ diff --git a/.yarn/cache/msw-npm-1.3.3-7cd6e8f445-0c63b282a5.zip b/.yarn/cache/msw-npm-1.3.3-7cd6e8f445-0c63b282a5.zip deleted file mode 100644 index 0abfad9..0000000 Binary files a/.yarn/cache/msw-npm-1.3.3-7cd6e8f445-0c63b282a5.zip and /dev/null differ diff --git a/.yarn/cache/node-mocks-http-npm-1.14.1-92277e4de4-bd091ea1de.zip b/.yarn/cache/node-mocks-http-npm-1.14.1-92277e4de4-bd091ea1de.zip new file mode 100644 index 0000000..e2ed805 Binary files /dev/null and b/.yarn/cache/node-mocks-http-npm-1.14.1-92277e4de4-bd091ea1de.zip differ diff --git a/.yarn/cache/normalize-url-npm-8.0.1-c87adbf3f1-eb439231c4.zip b/.yarn/cache/normalize-url-npm-8.0.1-c87adbf3f1-eb439231c4.zip new file mode 100644 index 0000000..7f06232 Binary files /dev/null and b/.yarn/cache/normalize-url-npm-8.0.1-c87adbf3f1-eb439231c4.zip differ diff --git a/.yarn/cache/p-cancelable-npm-4.0.1-759b614353-12636623f4.zip b/.yarn/cache/p-cancelable-npm-4.0.1-759b614353-12636623f4.zip new file mode 100644 index 0000000..e4e3c23 Binary files /dev/null and b/.yarn/cache/p-cancelable-npm-4.0.1-759b614353-12636623f4.zip differ diff --git a/.yarn/cache/postcss-npm-8.4.31-385051a82b-748b82e6e5.zip b/.yarn/cache/postcss-npm-8.4.31-385051a82b-748b82e6e5.zip deleted file mode 100644 index d814012..0000000 Binary files a/.yarn/cache/postcss-npm-8.4.31-385051a82b-748b82e6e5.zip and /dev/null differ diff --git a/.yarn/cache/remix-auth-auth0-npm-1.10.0-d618cd38cb-86d0170c80.zip b/.yarn/cache/remix-auth-auth0-npm-1.10.0-d618cd38cb-86d0170c80.zip new file mode 100644 index 0000000..902f1be Binary files /dev/null and b/.yarn/cache/remix-auth-auth0-npm-1.10.0-d618cd38cb-86d0170c80.zip differ diff --git a/.yarn/cache/remix-auth-npm-3.6.0-c96fab9c4d-2b9d9f5ad0.zip b/.yarn/cache/remix-auth-npm-3.6.0-c96fab9c4d-2b9d9f5ad0.zip new file mode 100644 index 0000000..a7ade23 Binary files /dev/null and b/.yarn/cache/remix-auth-npm-3.6.0-c96fab9c4d-2b9d9f5ad0.zip differ diff --git a/.yarn/cache/remix-auth-oauth2-npm-1.10.0-ac7ff3e733-88d7f0da60.zip b/.yarn/cache/remix-auth-oauth2-npm-1.10.0-ac7ff3e733-88d7f0da60.zip new file mode 100644 index 0000000..89df85e Binary files /dev/null and b/.yarn/cache/remix-auth-oauth2-npm-1.10.0-ac7ff3e733-88d7f0da60.zip differ diff --git a/.yarn/cache/remix-auth-oauth2-npm-1.11.2-8879fabf71-382cfcc05d.zip b/.yarn/cache/remix-auth-oauth2-npm-1.11.2-8879fabf71-382cfcc05d.zip new file mode 100644 index 0000000..19b402d Binary files /dev/null and b/.yarn/cache/remix-auth-oauth2-npm-1.11.2-8879fabf71-382cfcc05d.zip differ diff --git a/.yarn/cache/remix-flat-routes-npm-0.6.4-7e2639fc72-84a2c19be9.zip b/.yarn/cache/remix-flat-routes-npm-0.6.4-7e2639fc72-84a2c19be9.zip new file mode 100644 index 0000000..25983a8 Binary files /dev/null and b/.yarn/cache/remix-flat-routes-npm-0.6.4-7e2639fc72-84a2c19be9.zip differ diff --git a/.yarn/cache/responselike-npm-3.0.0-9ab07af81f-8af27153f7.zip b/.yarn/cache/responselike-npm-3.0.0-9ab07af81f-8af27153f7.zip new file mode 100644 index 0000000..a88bd09 Binary files /dev/null and b/.yarn/cache/responselike-npm-3.0.0-9ab07af81f-8af27153f7.zip differ diff --git a/.yarn/cache/shallowequal-npm-1.1.0-6688d419cb-b926efb51c.zip b/.yarn/cache/shallowequal-npm-1.1.0-6688d419cb-b926efb51c.zip deleted file mode 100644 index b4686dc..0000000 Binary files a/.yarn/cache/shallowequal-npm-1.1.0-6688d419cb-b926efb51c.zip and /dev/null differ diff --git a/.yarn/cache/strict-event-emitter-npm-0.2.8-e8b9131760-6891e19fea.zip b/.yarn/cache/strict-event-emitter-npm-0.2.8-e8b9131760-6891e19fea.zip deleted file mode 100644 index 70e65f5..0000000 Binary files a/.yarn/cache/strict-event-emitter-npm-0.2.8-e8b9131760-6891e19fea.zip and /dev/null differ diff --git a/.yarn/cache/strict-event-emitter-npm-0.4.6-b845d23c7d-d0231ef081.zip b/.yarn/cache/strict-event-emitter-npm-0.4.6-b845d23c7d-d0231ef081.zip deleted file mode 100644 index b176dc0..0000000 Binary files a/.yarn/cache/strict-event-emitter-npm-0.4.6-b845d23c7d-d0231ef081.zip and /dev/null differ diff --git a/.yarn/cache/styled-components-npm-6.1.8-ae8d84c2da-fafe4b9198.zip b/.yarn/cache/styled-components-npm-6.1.8-ae8d84c2da-fafe4b9198.zip deleted file mode 100644 index f10649e..0000000 Binary files a/.yarn/cache/styled-components-npm-6.1.8-ae8d84c2da-fafe4b9198.zip and /dev/null differ diff --git a/.yarn/cache/stylis-npm-4.3.1-df21265105-33e8ebd2bf.zip b/.yarn/cache/stylis-npm-4.3.1-df21265105-33e8ebd2bf.zip deleted file mode 100644 index 89db3b8..0000000 Binary files a/.yarn/cache/stylis-npm-4.3.1-df21265105-33e8ebd2bf.zip and /dev/null differ diff --git a/.yarn/cache/tslib-npm-2.5.0-bb364efebd-e32fc99cc7.zip b/.yarn/cache/tslib-npm-2.5.0-bb364efebd-e32fc99cc7.zip deleted file mode 100644 index 90604d9..0000000 Binary files a/.yarn/cache/tslib-npm-2.5.0-bb364efebd-e32fc99cc7.zip and /dev/null differ diff --git a/.yarn/cache/type-fest-npm-2.19.0-918b953248-a5a7ecf2e6.zip b/.yarn/cache/type-fest-npm-2.19.0-918b953248-a5a7ecf2e6.zip deleted file mode 100644 index 788d393..0000000 Binary files a/.yarn/cache/type-fest-npm-2.19.0-918b953248-a5a7ecf2e6.zip and /dev/null differ diff --git a/.yarn/cache/type-fest-npm-4.17.0-e154bcb7a2-7c474dca23.zip b/.yarn/cache/type-fest-npm-4.17.0-e154bcb7a2-7c474dca23.zip new file mode 100644 index 0000000..7af7d87 Binary files /dev/null and b/.yarn/cache/type-fest-npm-4.17.0-e154bcb7a2-7c474dca23.zip differ diff --git a/.yarn/cache/uuid-npm-8.3.2-eca0baba53-bcbb807a91.zip b/.yarn/cache/uuid-npm-8.3.2-eca0baba53-bcbb807a91.zip new file mode 100644 index 0000000..ea304f8 Binary files /dev/null and b/.yarn/cache/uuid-npm-8.3.2-eca0baba53-bcbb807a91.zip differ diff --git a/.yarn/cache/vite-node-npm-1.5.1-fd703ad005-d3591d9c30.zip b/.yarn/cache/vite-node-npm-1.5.2-3f4f4e44d5-a5e90ae2b3.zip similarity index 99% rename from .yarn/cache/vite-node-npm-1.5.1-fd703ad005-d3591d9c30.zip rename to .yarn/cache/vite-node-npm-1.5.2-3f4f4e44d5-a5e90ae2b3.zip index 5743865..73f46c4 100644 Binary files a/.yarn/cache/vite-node-npm-1.5.1-fd703ad005-d3591d9c30.zip and b/.yarn/cache/vite-node-npm-1.5.2-3f4f4e44d5-a5e90ae2b3.zip differ diff --git a/.yarn/cache/vitest-npm-1.5.1-da8c0fa81f-85f6b9250c.zip b/.yarn/cache/vitest-npm-1.5.2-db4ab193ee-1ad3a33d3a.zip similarity index 99% rename from .yarn/cache/vitest-npm-1.5.1-da8c0fa81f-85f6b9250c.zip rename to .yarn/cache/vitest-npm-1.5.2-db4ab193ee-1ad3a33d3a.zip index 52b29ed..d24d585 100644 Binary files a/.yarn/cache/vitest-npm-1.5.1-da8c0fa81f-85f6b9250c.zip and b/.yarn/cache/vitest-npm-1.5.2-db4ab193ee-1ad3a33d3a.zip differ diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz index ad29ca7..268e5ab 100644 Binary files a/.yarn/install-state.gz and b/.yarn/install-state.gz differ diff --git a/.yarn/patches/mock-jwks-npm-3.1.0-131e3bbc29.patch b/.yarn/patches/mock-jwks-npm-3.1.0-131e3bbc29.patch new file mode 100644 index 0000000..c0dd490 --- /dev/null +++ b/.yarn/patches/mock-jwks-npm-3.1.0-131e3bbc29.patch @@ -0,0 +1,61 @@ +diff --git a/build/index.d.ts b/build/index.d.ts +index 575dc0e00c51ac7dac66c4e4885c2414ee98fa91..50717f586aba777a4239b726a90347d9c3dcea45 100644 +--- a/build/index.d.ts ++++ b/build/index.d.ts +@@ -1,5 +1,8 @@ + import { JwtPayload } from 'jsonwebtoken'; ++import { HttpHandler } from 'msw'; ++ + declare const createJWKSMock: (jwksBase: string, jwksPath?: string) => { ++ handler: HttpHandler + start: () => void; + stop: () => void; + kid: () => string; +diff --git a/build/index.js b/build/index.js +index 289a2dac6cd569eef5dbc9329914a7517b442829..bfe7abde0ad358d21b707cc2fa69f721b02b8955 100644 +--- a/build/index.js ++++ b/build/index.js +@@ -1,13 +1,20 @@ + import { createJWKS, createKeyPair, signJwt } from './tools.js'; + import { setupServer } from 'msw/node'; +-import { rest } from 'msw'; ++import { http, HttpResponse } from 'msw'; ++ + const createJWKSMock = (jwksBase, jwksPath = '/.well-known/jwks.json') => { + const keypair = createKeyPair(); + const JWKS = createJWKS({ + ...keypair, + jwksOrigin: jwksBase, + }); +- const server = setupServer(rest.get(new URL(jwksPath, jwksBase).href, (_, res, ctx) => res(ctx.status(200), ctx.json(JWKS)))); ++ ++ // we patch & expose the actual msw handler so we can plug it into our own server rather than ++ // creating a conflicting instance. we also bump the msw version to match our own to avoid any ++ // compatibility issues. ++ const handler = http.get(new URL(jwksPath, jwksBase).href, () => HttpResponse.json(JWKS)); ++ ++ const server = setupServer(handler); + const kid = () => JWKS.keys[0].kid; + const start = () => { + server.listen({ onUnhandledRequest: 'bypass' }); +@@ -17,6 +24,7 @@ const createJWKSMock = (jwksBase, jwksPath = '/.well-known/jwks.json') => { + }; + const token = (token = {}) => signJwt(keypair.privateKey, token, kid()); + return { ++ handler, + start, + stop, + kid, +diff --git a/package.json b/package.json +index e5a5c2fc6b6b5dfec0c88bbf2adf4a88ba33e18b..412355319913b9b7a3743974c47d29fb834c9a93 100644 +--- a/package.json ++++ b/package.json +@@ -91,7 +91,7 @@ + "dependencies": { + "base64-url": "^2.3.3", + "jsonwebtoken": "^9.0.0", +- "msw": "^1.2.2", ++ "msw": "2.2.14", + "node-forge": "^1.3.1", + "node-rsa": "^1.1.1" + }, diff --git a/codegen.ts b/codegen.ts index c480853..4cb4872 100644 --- a/codegen.ts +++ b/codegen.ts @@ -14,13 +14,12 @@ const config: CodegenConfig = { plugins: ['schema-ast'], }, }, - // TODO: enable when introducing graphql-scalars - // config: { - // scalars: { - // UUID: 'string', - // DateTime: 'Date', - // }, - // }, + config: { + scalars: { + Date: 'Date', + DateTime: 'Date', + }, + }, }; export default config; diff --git a/eslint.config.cjs b/eslint.config.cjs index db2fcca..b8a4404 100644 --- a/eslint.config.cjs +++ b/eslint.config.cjs @@ -24,6 +24,13 @@ module.exports = tseslint.config( // }, rules: { + '@typescript-eslint/no-unused-vars': [ + 'error', + { + ignoreRestSiblings: true, + }, + ], + 'unicorn/no-null': 'off', 'unicorn/prevent-abbreviations': 'off', }, diff --git a/lint-staged.config.js b/lint-staged.config.js index 759429d..58801cb 100755 --- a/lint-staged.config.js +++ b/lint-staged.config.js @@ -8,5 +8,6 @@ export default { (files) => `yarn nx affected:lint --files=${files.join(',')}`, (files) => `yarn nx format:write --files=${files.join(',')}`, ], + 'projects/lib-postgres-schema/**/*.ts': ['yarn postgres:migrations-generate'], '**/*.graphql': ['yarn nx format:write'], }; diff --git a/package.json b/package.json index cbd9f5b..e216b42 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,13 @@ "private": true, "type": "module", "scripts": { + "clean": "rm -rf '.nx/' 'tmp/' '**/.cache' '**/build/' '**/node_modules/' '**/dist/' '**/*.timestamp*.mjs'", "build": "nx run-many -t build", "lint": "nx run-many -t lint", "test": "nx run-many -t test", "typecheck": "nx run-many -t typecheck", "e2e": "nx run-many -t e2e", - "codegen:graphql": "graphql-codegen", + "codegen:graphql": "TS_NODE_PROJECT=tsconfig.base.json graphql-codegen --require tsconfig-paths/register", "postgres:start": "docker-compose -f ./docker-compose.yml up -d", "postgres:migrations-generate": "nx migrations-generate db-postgres", "postgres:migrations-run:dev": "nx migrations-run-dev db-postgres", @@ -45,6 +46,7 @@ "@graphql-codegen/schema-ast": "4.0.2", "@graphql-tools/executor-http": "1.0.9", "@graphql-typed-document-node/core": "3.2.0", + "@mswjs/data": "0.16.1", "@nx/devkit": "18.3.3", "@nx/esbuild": "18.3.3", "@nx/eslint": "18.3.3", @@ -64,20 +66,23 @@ "@swc/core": "1.4.13", "@swc/helpers": "0.5.8", "@testcontainers/postgresql": "10.9.0", + "@testing-library/dom": "10.0.0", "@testing-library/jest-dom": "6.4.2", "@testing-library/react": "14.3.0", + "@testing-library/user-event": "14.5.2", "@types/jsonwebtoken": "9.0.6", "@types/node": "20.12.7", "@types/react": "18.2.75", "@types/react-dom": "18.2.24", "@types/react-is": "18.2.4", - "@types/styled-components": "5.1.34", "@typescript-eslint/eslint-plugin": "7.6.0", "@typescript-eslint/parser": "7.6.0", "@typescript-eslint/utils": "7.7.1", + "@vanilla-extract/vite-plugin": "4.0.7", "@vitejs/plugin-react": "4.2.1", - "@vitest/coverage-v8": "1.5.1", - "@vitest/ui": "1.5.1", + "@vitest/coverage-v8": "1.5.2", + "@vitest/expect": "1.5.2", + "@vitest/ui": "1.5.2", "drizzle-kit": "0.20.17", "esbuild": "0.20.2", "eslint": "9.0.0", @@ -88,34 +93,45 @@ "eslint-plugin-react": "7.34.1", "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-unicorn": "52.0.0", + "graphql-transform-scalars": "1.2.1", "happy-dom": "14.7.1", "husky": "9.0.11", "jest-extended": "4.0.2", + "jwt-decode": "4.0.0", "lint-staged": "15.2.2", - "mock-jwks": "3.1.0", + "mock-jwks": "patch:mock-jwks@npm%3A3.1.0#~/.yarn/patches/mock-jwks-npm-3.1.0-131e3bbc29.patch", "msw": "2.2.14", + "node-mocks-http": "1.14.1", "nx": "18.3.3", "playwright": "1.43.0", "prettier": "3.2.5", + "remix-flat-routes": "0.6.4", + "tsconfig-paths": "4.2.0", "tslib": "2.6.2", "tsx": "4.7.3", + "type-fest": "4.17.0", "typescript": "5.4.5", "typescript-eslint": "7.6.0", "vite": "5.2.10", - "vitest": "1.5.1" + "vitest": "1.5.2" }, "dependencies": { "@hono/node-server": "1.10.0", + "@paralleldrive/cuid2": "2.2.2", "@pothos/core": "3.41.1", "@remix-run/node": "2.9.1", "@remix-run/react": "2.9.1", "@remix-run/serve": "2.9.1", + "@remix-run/server-runtime": "2.9.1", + "@vanilla-extract/css": "1.14.2", + "@vanilla-extract/sprinkles": "1.6.1", "auth0": "4.3.1", - "cuid": "3.0.0", "drizzle-orm": "0.30.9", "envalid": "8.0.0", + "got": "14.2.1", "graphql": "16.8.1", "graphql-request": "6.1.0", + "graphql-scalars": "1.23.0", "graphql-yoga": "5.3.0", "hono": "4.2.4", "isbot": "4", @@ -126,9 +142,12 @@ "react-dom": "18.2.0", "react-is": "18.2.0", "react-router-dom": "6.22.3", + "remix-auth": "3.6.0", + "remix-auth-auth0": "1.10.0", + "remix-auth-oauth2": "1.11.2", "remix-hono": "0.0.16", - "styled-components": "6.1.8", - "tiny-invariant": "1.3.3" + "tiny-invariant": "1.3.3", + "uuid": "9.0.1" }, "packageManager": "yarn@4.1.1", "dockerfile": { @@ -137,5 +156,8 @@ }, "workspaces": [ "projects/*" - ] + ], + "resolutions": { + "msw@npm:^1.2.2": "2.2.14" + } } diff --git a/projects/app-web-e2e/playwright.config.ts b/projects/app-web-e2e/playwright.config.ts index c012dc2..28df77b 100644 --- a/projects/app-web-e2e/playwright.config.ts +++ b/projects/app-web-e2e/playwright.config.ts @@ -1,4 +1,5 @@ import { fileURLToPath } from 'node:url'; +import path from 'node:path'; import { defineConfig, devices } from '@playwright/test'; import { nxE2EPreset } from '@nx/playwright/preset'; import { workspaceRoot } from '@nx/devkit'; @@ -9,11 +10,16 @@ const __filename = fileURLToPath(import.meta.url); // For CI, you may want to set BASE_URL to the deployed application. const baseURL = process.env['BASE_URL'] || 'http://localhost:4000'; -/** - * Read environment variables from file. - * https://github.com/motdotla/dotenv - */ -// require('dotenv').config(); +// having a million issues trying to use __dirname to establish a reliable path +// so it's easier to do this to handle the case when this file gets parsed for +// building our nx graph +const projectRoot = process.cwd().includes('app-web-e2e') + ? process.cwd() + : `${process.cwd()}/projects/app-web-e2e`; + +const dotEnvFile = path.join(projectRoot, '.env'); + +process.loadEnvFile(dotEnvFile); /** * See https://playwright.dev/docs/test-configuration. diff --git a/projects/app-web-e2e/src/env.ts b/projects/app-web-e2e/src/env.ts new file mode 100755 index 0000000..3a1de9b --- /dev/null +++ b/projects/app-web-e2e/src/env.ts @@ -0,0 +1,13 @@ +import { cleanEnv, str } from 'envalid'; +import { Env } from './types'; + +export const env: Env = cleanEnv(process.env, { + NODE_ENV: str({ choices: ['development', 'test', 'e2e', 'production'] }), + LOGGING: str({ + choices: ['debug', 'info', 'warn', 'error'], + default: 'info', + }), + + TEST_USER_EMAIL: str(), + TEST_USER_PASSWORD: str(), +}); diff --git a/projects/app-web-e2e/src/example.test.ts b/projects/app-web-e2e/src/example.test.ts deleted file mode 100644 index abe155d..0000000 --- a/projects/app-web-e2e/src/example.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { test, expect } from '@playwright/test'; - -test('has title', async ({ page }) => { - await page.goto('/'); - - await expect(page.getByText('hello, world', { exact: true })).toBeVisible(); -}); diff --git a/projects/app-web-e2e/src/sign-up.test.ts b/projects/app-web-e2e/src/sign-up.test.ts new file mode 100644 index 0000000..afb131b --- /dev/null +++ b/projects/app-web-e2e/src/sign-up.test.ts @@ -0,0 +1,18 @@ +import { test, expect } from '@playwright/test'; +import { env } from './env'; + +test('it signs the user in and welcomes them', async ({ page }) => { + await page.goto('/'); + + await page.getByRole('button', { name: 'Log in' }).click(); + + await expect(page).toHaveURL(/chrononomicon\.us\.auth0\.com\/u\/login/); + + await page.getByLabel('Email address').fill(env.TEST_USER_EMAIL); + await page.getByLabel('Password').fill(env.TEST_USER_PASSWORD); + await page.getByRole('button', { name: 'Continue', exact: true }).click(); + + await expect(page).toHaveURL(/localhost:4000/); + + await expect(page.getByText('Hello, Test User')).toBeVisible(); +}); diff --git a/projects/app-web-e2e/src/types.ts b/projects/app-web-e2e/src/types.ts new file mode 100755 index 0000000..41964ed --- /dev/null +++ b/projects/app-web-e2e/src/types.ts @@ -0,0 +1,11 @@ +export type Env = { + LOGGING: 'debug' | 'info' | 'warn' | 'error'; + NODE_ENV: 'development' | 'test' | 'e2e' | 'production'; + + TEST_USER_EMAIL: string; + TEST_USER_PASSWORD: string; + + // utils + isProduction: boolean; + isDevelopment: boolean; +}; diff --git a/projects/app-web-e2e/tsconfig.json b/projects/app-web-e2e/tsconfig.json index 1f228cb..120b1ca 100644 --- a/projects/app-web-e2e/tsconfig.json +++ b/projects/app-web-e2e/tsconfig.json @@ -1,17 +1,15 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "allowJs": true, - "outDir": "../../dist/out-tsc", - "module": "esnext", - "sourceMap": false + "module": "ESNext", + "types": ["node"], + "sourceMap": false, + "esModuleInterop": true }, "include": [ "**/*.ts", - "**/*.js", "playwright.config.ts", "src/**/*.test.ts", - "src/**/*.test.js", "src/**/*.d.ts" ] } diff --git a/projects/app-web/.env.development b/projects/app-web/.env.development index 0d97b9f..96b1d70 100644 --- a/projects/app-web/.env.development +++ b/projects/app-web/.env.development @@ -1,2 +1,11 @@ +VITE_DOMAIN=localhost VITE_API_URL=http://localhost:3000/graphql -VITE_ENABLE_MSW=true \ No newline at end of file + +VITE_AUTH0_AUDIENCE="http://localhost:3000/" +VITE_AUTH0_CALLBACK_URL="http://localhost:4000/auth/callback" +VITE_AUTH0_CLIENT_ID="F7PgBpbgFpgNmkXdlbDIiAnugC0Lggb0" +VITE_AUTH0_DOMAIN="chrononomicon.us.auth0.com" +VITE_AUTH0_LOGOUT_URL="https://chrononomicon.us.auth0.com/v2/logout" +VITE_AUTH0_RETURN_URL="http://localhost:4000" + +VITE_ENABLE_MSW=false diff --git a/projects/app-web/.env.production b/projects/app-web/.env.production index 8fd9680..8cfaabb 100644 --- a/projects/app-web/.env.production +++ b/projects/app-web/.env.production @@ -1,2 +1,11 @@ -VITE_API_URL=https://service-api.fly.dev/graphql -VITE_ENABLE_MSW=false \ No newline at end of file +VITE_DOMAIN="app-web.fly.dev" +VITE_API_URL="https://service-api.fly.dev/graphql" + +VITE_AUTH0_AUDIENCE="https://service-api.fly.dev" +VITE_AUTH0_CALLBACK_URL="https://app-web.fly.dev/auth/callback" +VITE_AUTH0_CLIENT_ID="F7PgBpbgFpgNmkXdlbDIiAnugC0Lggb0" +VITE_AUTH0_DOMAIN="chrononomicon.us.auth0.com" +VITE_AUTH0_LOGOUT_URL="https://chrononomicon.us.auth0.com/v2/logout" +VITE_AUTH0_RETURN_URL="https://app-web.fly.dev" + +VITE_ENABLE_MSW="false" \ No newline at end of file diff --git a/projects/app-web/.env.test b/projects/app-web/.env.test index 0d97b9f..f930b30 100644 --- a/projects/app-web/.env.test +++ b/projects/app-web/.env.test @@ -1,2 +1,9 @@ -VITE_API_URL=http://localhost:3000/graphql -VITE_ENABLE_MSW=true \ No newline at end of file +VITE_DOMAIN=test.com +VITE_API_URL=https://test.com/graphql +VITE_AUTH0_AUDIENCE="https://test.com/" +VITE_AUTH0_CALLBACK_URL="https://test.com/auth/callback" +VITE_AUTH0_CLIENT_ID="auth0_client_id" +VITE_AUTH0_DOMAIN="auth0domain.com" +VITE_AUTH0_LOGOUT_URL="https://auth0.com/v2/logout" +VITE_AUTH0_RETURN_URL="https://test.com" +VITE_ENABLE_MSW=true diff --git a/projects/app-web/app/app.css.ts b/projects/app-web/app/app.css.ts new file mode 100644 index 0000000..10ecb06 --- /dev/null +++ b/projects/app-web/app/app.css.ts @@ -0,0 +1,22 @@ +import { globalStyle } from '@vanilla-extract/css'; + +// primary - #095191 +// dark - #181b26 +// light - #76a5ce +// foreground - #ddefff +// background - #07080b + +globalStyle('html, body', { + all: 'unset', + boxSizing: 'border-box', + display: 'block', + height: '100%', +}); + +globalStyle('html', { + // +}); + +globalStyle('body', { + backgroundColor: '#07080b;', +}); diff --git a/projects/app-web/app/authenticator.server.ts b/projects/app-web/app/authenticator.server.ts new file mode 100644 index 0000000..0f74882 --- /dev/null +++ b/projects/app-web/app/authenticator.server.ts @@ -0,0 +1,80 @@ +import { Authenticator } from 'remix-auth'; +import { + Auth0Strategy, + Auth0Profile, + Auth0ExtraParams, +} from 'remix-auth-auth0'; +import { OAuth2StrategyVerifyParams } from 'remix-auth-oauth2'; +import invariant from 'tiny-invariant'; +import { client } from './client'; +import { graphql } from './gql'; +import { User } from './gql/graphql'; +import { sessionStorage } from './session-storage.server'; +import { isMutationError } from './utils'; + +export const authenticator = new Authenticator(sessionStorage, { + sessionKey: 'userID', +}); + +invariant(process.env.AUTH0_CLIENT_SECRET, '$AUTH0_CLIENT_SECRET is required'); + +const config = { + callbackURL: import.meta.env.VITE_AUTH0_CALLBACK_URL, + clientID: import.meta.env.VITE_AUTH0_CLIENT_ID, + clientSecret: process.env.AUTH0_CLIENT_SECRET, + domain: import.meta.env.VITE_AUTH0_DOMAIN, + audience: import.meta.env.VITE_AUTH0_AUDIENCE, +}; + +const auth0Strategy = new Auth0Strategy(config, handleVerifySuccess); + +const GetOrCreateUser = graphql(/* GraphQL */ ` + mutation GetOrCreateUser($input: GetOrCreateUserInput!) { + getOrCreateUser(input: $input) { + ... on User { + id + name + firstName + email + emailVerified + createdAt + } + + ... on MutationErrorPayload { + error { + title + message + } + } + } + } +`); + +async function handleVerifySuccess( + params: OAuth2StrategyVerifyParams, +): Promise> { + client.setHeader('authorization', `Bearer ${params.accessToken}`); + + const email = params.profile.emails?.[0].value; + + invariant(email, 'email is required'); + + const { getOrCreateUser } = await client.request(GetOrCreateUser, { + input: { email }, + }); + + if (isMutationError(getOrCreateUser)) { + const error = new Error(getOrCreateUser.error.message); + + error.name = getOrCreateUser.error.title; + + // TODO(#16): capture via Sentry + throw error; + } + + const { __typename, ...user } = getOrCreateUser; + + return user; +} + +authenticator.use(auth0Strategy); diff --git a/projects/app-web/app/components/button.css.ts b/projects/app-web/app/components/button.css.ts new file mode 100644 index 0000000..1e31f38 --- /dev/null +++ b/projects/app-web/app/components/button.css.ts @@ -0,0 +1,41 @@ +import { style, styleVariants } from '@vanilla-extract/css'; + +const buttonBase = style({ + borderRadius: '4px', + display: 'flex', + fontFamily: 'Josefin Slab Bold, sans-serif', + fontSize: '18px', + justifyContent: 'center', + marginBottom: '8px', + minWidth: '160px', + padding: '13px 16px 8px', + textAlign: 'center', + textTransform: 'uppercase', +}); + +export const buttonVariants = styleVariants({ + primary: [ + buttonBase, + { + backgroundColor: '#0087ff', + border: 'none', + color: '#ddefff', + }, + ], + secondary: [ + buttonBase, + { + backgroundColor: '#ffffff0d', + border: '1px solid #0087ff', + color: '#0087ff', + }, + ], + transparent: [ + buttonBase, + { + backgroundColor: '#ffffff0d', + border: '1px solid #0087ff', + color: '#0087ff', + }, + ], +}); diff --git a/projects/app-web/app/components/button.tsx b/projects/app-web/app/components/button.tsx new file mode 100644 index 0000000..2e6ef5b --- /dev/null +++ b/projects/app-web/app/components/button.tsx @@ -0,0 +1,15 @@ +import * as styles from './button.css'; + +type Props = { + children: React.ReactNode; + variant?: 'primary' | 'secondary' | 'transparent'; +}; + +export function Button(props: Props) { + return ( + + + ); +} diff --git a/projects/app-web/app/components/log-out-button.test.tsx b/projects/app-web/app/components/log-out-button.test.tsx new file mode 100644 index 0000000..20f622e --- /dev/null +++ b/projects/app-web/app/components/log-out-button.test.tsx @@ -0,0 +1,34 @@ +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { LogOutButton } from './log-out-button'; +import { createRemixStub } from '@remix-run/testing'; +import { Routes } from '../types'; + +function ExpectedRoute() { + return 'Logged out'; +} + +function setupTest() { + const user = userEvent.setup(); + + const LogOutButtonStub = createRemixStub([ + { path: Routes.Index, Component: LogOutButton }, + { path: Routes.AuthLogout, Component: ExpectedRoute, action: () => null }, + ]); + + render(); + + return { user }; +} + +test('it renders a log out button that redirects to the log out route when pressed', async () => { + const { user } = setupTest(); + + const logOutButton = await screen.findByRole('button', { name: 'Log out' }); + + await waitFor(() => user.click(logOutButton)); + + const loggedOutMessage = await screen.findByText('Logged out'); + + expect(loggedOutMessage).toBeInTheDocument(); +}); diff --git a/projects/app-web/app/components/log-out-button.tsx b/projects/app-web/app/components/log-out-button.tsx new file mode 100644 index 0000000..ec0d8b5 --- /dev/null +++ b/projects/app-web/app/components/log-out-button.tsx @@ -0,0 +1,12 @@ +import { Form } from '@remix-run/react'; +import { Button } from './button'; + +export function LogOutButton() { + return ( + <> +
+ +
+ + ); +} diff --git a/projects/app-web/app/components/sign-up-button.test.tsx b/projects/app-web/app/components/sign-up-button.test.tsx new file mode 100644 index 0000000..daa2a6a --- /dev/null +++ b/projects/app-web/app/components/sign-up-button.test.tsx @@ -0,0 +1,34 @@ +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { SignUpButton } from './sign-up-button'; +import { createRemixStub } from '@remix-run/testing'; +import { Routes } from '../types'; + +function ExpectedRoute() { + return 'Auth0'; +} + +function setupTest() { + const user = userEvent.setup(); + + const SignUpButtonStub = createRemixStub([ + { path: Routes.Index, Component: SignUpButton }, + { path: Routes.AuthAuth0, Component: ExpectedRoute, action: () => null }, + ]); + + render(); + + return { user }; +} + +test('it renders a sign up button that redirects to auth0 when pressed', async () => { + const { user } = setupTest(); + + const signUpButton = await screen.findByRole('button', { name: 'Sign up' }); + + await waitFor(() => user.click(signUpButton)); + + const auth0Page = await screen.findByText('Auth0'); + + expect(auth0Page).toBeInTheDocument(); +}); diff --git a/projects/app-web/app/components/sign-up-button.tsx b/projects/app-web/app/components/sign-up-button.tsx new file mode 100644 index 0000000..a1e3938 --- /dev/null +++ b/projects/app-web/app/components/sign-up-button.tsx @@ -0,0 +1,12 @@ +import { Form } from '@remix-run/react'; +import { Button } from './button'; + +export function SignUpButton() { + return ( + <> +
+ +
+ + ); +} diff --git a/projects/app-web/app/entry.server.tsx b/projects/app-web/app/entry.server.tsx index 7c1b2c8..83e8530 100644 --- a/projects/app-web/app/entry.server.tsx +++ b/projects/app-web/app/entry.server.tsx @@ -19,6 +19,11 @@ if (!import.meta.env.PROD && import.meta.env.VITE_ENABLE_MSW === 'true') { server.listen(); } +// if we're in dev mode, load our local environment variables which should include our server secrets +if (!import.meta.env.PROD) { + process.loadEnvFile('.env.development.local'); +} + export default function handleRequest( request: Request, responseStatusCode: number, diff --git a/projects/app-web/app/gql/gql.ts b/projects/app-web/app/gql/gql.ts index 0d082fb..94dd539 100644 --- a/projects/app-web/app/gql/gql.ts +++ b/projects/app-web/app/gql/gql.ts @@ -13,7 +13,10 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ * Therefore it is highly recommended to use the babel or swc plugin for production. */ const documents = { - '\n query GetHelloWorld {\n hello\n }\n': types.GetHelloWorldDocument, + '\n mutation GetOrCreateUser($input: GetOrCreateUserInput!) {\n getOrCreateUser(input: $input) {\n ... on User {\n id\n name\n firstName\n email\n emailVerified\n createdAt\n }\n\n ... on MutationErrorPayload {\n error {\n title\n message\n }\n }\n }\n }\n': + types.GetOrCreateUserDocument, + '\n query GetCurrentUser {\n getCurrentUser {\n id\n name\n }\n }\n': + types.GetCurrentUserDocument, }; /** @@ -34,8 +37,14 @@ export function graphql(source: string): unknown; * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: '\n query GetHelloWorld {\n hello\n }\n', -): (typeof documents)['\n query GetHelloWorld {\n hello\n }\n']; + source: '\n mutation GetOrCreateUser($input: GetOrCreateUserInput!) {\n getOrCreateUser(input: $input) {\n ... on User {\n id\n name\n firstName\n email\n emailVerified\n createdAt\n }\n\n ... on MutationErrorPayload {\n error {\n title\n message\n }\n }\n }\n }\n', +): (typeof documents)['\n mutation GetOrCreateUser($input: GetOrCreateUserInput!) {\n getOrCreateUser(input: $input) {\n ... on User {\n id\n name\n firstName\n email\n emailVerified\n createdAt\n }\n\n ... on MutationErrorPayload {\n error {\n title\n message\n }\n }\n }\n }\n']; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql( + source: '\n query GetCurrentUser {\n getCurrentUser {\n id\n name\n }\n }\n', +): (typeof documents)['\n query GetCurrentUser {\n getCurrentUser {\n id\n name\n }\n }\n']; export function graphql(source: string) { return (documents as any)[source] ?? {}; diff --git a/projects/app-web/app/gql/graphql.ts b/projects/app-web/app/gql/graphql.ts index 4c07ba5..257145f 100644 --- a/projects/app-web/app/gql/graphql.ts +++ b/projects/app-web/app/gql/graphql.ts @@ -27,32 +27,214 @@ export type Scalars = { Boolean: { input: boolean; output: boolean }; Int: { input: number; output: number }; Float: { input: number; output: number }; + /** A date string, such as 2007-12-03, compliant with the `full-date` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. */ + Date: { input: Date; output: Date }; + /** A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. */ + DateTime: { input: Date; output: Date }; +}; + +export type GetOrCreateUserInput = { + email: Scalars['String']['input']; +}; + +export type GetOrCreateUserPayload = MutationErrorPayload | User; + +export type Mutation = { + __typename?: 'Mutation'; + getOrCreateUser: GetOrCreateUserPayload; +}; + +export type MutationGetOrCreateUserArgs = { + input: GetOrCreateUserInput; +}; + +export type MutationError = { + __typename?: 'MutationError'; + message: Scalars['String']['output']; + title: Scalars['String']['output']; +}; + +export type MutationErrorPayload = { + __typename?: 'MutationErrorPayload'; + error: MutationError; }; export type Query = { __typename?: 'Query'; - hello: Scalars['String']['output']; + getCurrentUser: User; }; -export type QueryHelloArgs = { - name?: InputMaybe; +export type User = { + __typename?: 'User'; + createdAt: Scalars['DateTime']['output']; + email: Scalars['String']['output']; + emailVerified: Scalars['Boolean']['output']; + firstName?: Maybe; + id: Scalars['ID']['output']; + name: Scalars['String']['output']; }; -export type GetHelloWorldQueryVariables = Exact<{ [key: string]: never }>; +export type GetOrCreateUserMutationVariables = Exact<{ + input: GetOrCreateUserInput; +}>; + +export type GetOrCreateUserMutation = { + __typename?: 'Mutation'; + getOrCreateUser: + | { + __typename?: 'MutationErrorPayload'; + error: { __typename?: 'MutationError'; title: string; message: string }; + } + | { + __typename?: 'User'; + id: string; + name: string; + firstName?: string | null; + email: string; + emailVerified: boolean; + createdAt: Date; + }; +}; -export type GetHelloWorldQuery = { __typename?: 'Query'; hello: string }; +export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never }>; -export const GetHelloWorldDocument = { +export type GetCurrentUserQuery = { + __typename?: 'Query'; + getCurrentUser: { __typename?: 'User'; id: string; name: string }; +}; + +export const GetOrCreateUserDocument = { + kind: 'Document', + definitions: [ + { + kind: 'OperationDefinition', + operation: 'mutation', + name: { kind: 'Name', value: 'GetOrCreateUser' }, + variableDefinitions: [ + { + kind: 'VariableDefinition', + variable: { + kind: 'Variable', + name: { kind: 'Name', value: 'input' }, + }, + type: { + kind: 'NonNullType', + type: { + kind: 'NamedType', + name: { kind: 'Name', value: 'GetOrCreateUserInput' }, + }, + }, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: 'getOrCreateUser' }, + arguments: [ + { + kind: 'Argument', + name: { kind: 'Name', value: 'input' }, + value: { + kind: 'Variable', + name: { kind: 'Name', value: 'input' }, + }, + }, + ], + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'InlineFragment', + typeCondition: { + kind: 'NamedType', + name: { kind: 'Name', value: 'User' }, + }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: 'id' } }, + { kind: 'Field', name: { kind: 'Name', value: 'name' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'firstName' }, + }, + { kind: 'Field', name: { kind: 'Name', value: 'email' } }, + { + kind: 'Field', + name: { kind: 'Name', value: 'emailVerified' }, + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'createdAt' }, + }, + ], + }, + }, + { + kind: 'InlineFragment', + typeCondition: { + kind: 'NamedType', + name: { kind: 'Name', value: 'MutationErrorPayload' }, + }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: 'error' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: 'title' }, + }, + { + kind: 'Field', + name: { kind: 'Name', value: 'message' }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode< + GetOrCreateUserMutation, + GetOrCreateUserMutationVariables +>; +export const GetCurrentUserDocument = { kind: 'Document', definitions: [ { kind: 'OperationDefinition', operation: 'query', - name: { kind: 'Name', value: 'GetHelloWorld' }, + name: { kind: 'Name', value: 'GetCurrentUser' }, selectionSet: { kind: 'SelectionSet', - selections: [{ kind: 'Field', name: { kind: 'Name', value: 'hello' } }], + selections: [ + { + kind: 'Field', + name: { kind: 'Name', value: 'getCurrentUser' }, + selectionSet: { + kind: 'SelectionSet', + selections: [ + { kind: 'Field', name: { kind: 'Name', value: 'id' } }, + { kind: 'Field', name: { kind: 'Name', value: 'name' } }, + ], + }, + }, + ], }, }, ], -} as unknown as DocumentNode; +} as unknown as DocumentNode; diff --git a/projects/app-web/app/mocks/db.ts b/projects/app-web/app/mocks/db.ts new file mode 100644 index 0000000..260ef92 --- /dev/null +++ b/projects/app-web/app/mocks/db.ts @@ -0,0 +1,13 @@ +import { factory, primaryKey } from '@mswjs/data'; + +export const db = factory({ + user: { + id: primaryKey(() => 'test_id'), + auth0ID: () => 'auth0|test_id', + email: () => 'user@test.com', + emailVerified: () => true, + name: () => 'Test User', + firstName: () => 'John', + createdAt: () => new Date(), + }, +}); diff --git a/projects/app-web/app/mocks/handlers.ts b/projects/app-web/app/mocks/handlers.ts deleted file mode 100644 index b25eb58..0000000 --- a/projects/app-web/app/mocks/handlers.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { graphql, HttpResponse } from 'msw'; - -export const handlers = [ - graphql.query('GetHelloWorld', () => { - return HttpResponse.json({ - data: { - hello: 'hello, world', - }, - }); - }), -]; diff --git a/projects/app-web/app/mocks/handlers/gql/get-current-user.ts b/projects/app-web/app/mocks/handlers/gql/get-current-user.ts new file mode 100644 index 0000000..2798f27 --- /dev/null +++ b/projects/app-web/app/mocks/handlers/gql/get-current-user.ts @@ -0,0 +1,65 @@ +import { graphql, HttpResponse } from 'msw'; +import { jwtDecode } from 'jwt-decode'; +import { db } from '../../db'; +import { MutationResponse } from './types'; + +type GetCurrentUserResponse = MutationResponse<{ + getCurrentUser: { + id: string; + auth0ID: string; + email: string; + emailVerified: boolean; + name: string; + firstName?: string; + createdAt: Date; + }; +}>; + +type GetOrCreateUserVariables = { + // +}; + +export const GetCurrentUser = graphql.query< + GetCurrentUserResponse, + GetOrCreateUserVariables +>('GetCurrentUser', async ({ request }) => { + const authHeader = request.headers.get('authorization'); + + if (!authHeader) { + return HttpResponse.json({ + data: { + getCurrentUser: { + error: { + title: 'Unauthorized', + message: 'Access token not provided', + }, + }, + }, + }); + } + + const token = authHeader.replace('Bearer ', ''); + const payload = jwtDecode(token); + const user = db.user.findFirst({ + where: { auth0ID: { equals: payload.sub } }, + }); + + if (!user) { + return HttpResponse.json({ + data: { + getCurrentUser: { + error: { + title: 'Not found', + message: 'User not found', + }, + }, + }, + }); + } + + return HttpResponse.json({ + data: { + getCurrentUser: user, + }, + }); +}); diff --git a/projects/app-web/app/mocks/handlers/gql/get-or-create-user.ts b/projects/app-web/app/mocks/handlers/gql/get-or-create-user.ts new file mode 100644 index 0000000..d6c4b4a --- /dev/null +++ b/projects/app-web/app/mocks/handlers/gql/get-or-create-user.ts @@ -0,0 +1,70 @@ +import { graphql, HttpResponse } from 'msw'; +import { jwtDecode } from 'jwt-decode'; +import { createId } from '@paralleldrive/cuid2'; +import { db } from '../../db'; +import { MutationResponse } from './types'; + +type GetOrCreateUserResponse = MutationResponse<{ + getOrCreateUser: { + id: string; + auth0ID: string; + email: string; + emailVerified: boolean; + name: string; + firstName?: string; + createdAt: Date; + }; +}>; + +type GetOrCreateUserVariables = { + input: { + email: string; + }; +}; + +export const GetOrCreateUser = graphql.mutation< + GetOrCreateUserResponse, + GetOrCreateUserVariables +>('GetOrCreateUser', async ({ request, variables }) => { + const authHeader = request.headers.get('authorization'); + + if (!authHeader) { + return HttpResponse.json({ + data: { + getOrCreateUser: { + error: { + title: 'Unauthorized', + message: 'Access token not provided', + }, + }, + }, + }); + } + + const token = authHeader.replace('Bearer ', ''); + const payload = jwtDecode(token); + + const existingUser = db.user.findFirst({ + where: { email: { equals: variables.input.email } }, + }); + + if (existingUser) { + return HttpResponse.json({ + data: { + getOrCreateUser: existingUser, + }, + }); + } + + const user = db.user.create({ + id: createId(), + auth0ID: payload.sub, + email: variables.input.email, + }); + + return HttpResponse.json({ + data: { + getOrCreateUser: user, + }, + }); +}); diff --git a/projects/app-web/app/mocks/handlers/gql/index.ts b/projects/app-web/app/mocks/handlers/gql/index.ts new file mode 100644 index 0000000..46b6e3d --- /dev/null +++ b/projects/app-web/app/mocks/handlers/gql/index.ts @@ -0,0 +1,4 @@ +import { GetCurrentUser } from './get-current-user'; +import { GetOrCreateUser } from './get-or-create-user'; + +export const handlers = [GetCurrentUser, GetOrCreateUser]; diff --git a/projects/app-web/app/mocks/handlers/gql/types.ts b/projects/app-web/app/mocks/handlers/gql/types.ts new file mode 100644 index 0000000..1a4859f --- /dev/null +++ b/projects/app-web/app/mocks/handlers/gql/types.ts @@ -0,0 +1,3 @@ +export type MutationError = { error: { title: string; message: string } }; + +export type MutationResponse = T | { [key in keyof T]: MutationError }; diff --git a/projects/app-web/app/mocks/handlers/index.ts b/projects/app-web/app/mocks/handlers/index.ts new file mode 100644 index 0000000..6929b69 --- /dev/null +++ b/projects/app-web/app/mocks/handlers/index.ts @@ -0,0 +1,3 @@ +import { handlers as gqlHandlers } from './gql'; + +export const handlers = [...gqlHandlers]; diff --git a/projects/app-web/app/root.tsx b/projects/app-web/app/root.tsx index 9445256..7e6ba66 100644 --- a/projects/app-web/app/root.tsx +++ b/projects/app-web/app/root.tsx @@ -1,4 +1,4 @@ -import type { MetaFunction } from '@remix-run/node'; +import type { LinksFunction, MetaFunction } from '@remix-run/node'; import { Links, Meta, @@ -6,12 +6,16 @@ import { Scripts, ScrollRestoration, } from '@remix-run/react'; +import styles from './styles/fonts.css?url'; +import './app.css'; + +export const links: LinksFunction = () => [{ rel: 'stylesheet', href: styles }]; export const meta: MetaFunction = () => [ { // eslint-disable-next-line unicorn/text-encoding-identifier-case charset: 'utf-8', - title: 'New Remix App', + title: 'Chrononomicon', viewport: 'width=device-width,initial-scale=1', }, ]; diff --git a/projects/app-web/app/routes/_index.css.ts b/projects/app-web/app/routes/_index.css.ts new file mode 100644 index 0000000..4d569c0 --- /dev/null +++ b/projects/app-web/app/routes/_index.css.ts @@ -0,0 +1,67 @@ +import { style } from '@vanilla-extract/css'; + +export const container = style({ + margin: '0 auto', + maxWidth: '1140px', + padding: '0 24px', + textAlign: 'center', +}); + +export const brandIcon = style({ + height: '42px', + marginTop: '-2px', + width: '42px', +}); + +export const brandName = style({ + alignSelf: 'center', + color: '#0087ff', + display: 'flex', + fontFamily: 'Josefin Sans Medium, sans-serif', + fontSize: '48px', + fontWeight: 500, + lineHeight: 1, + padding: 0, + textTransform: 'uppercase', +}); + +export const heroSection = style({ + alignItems: 'center', + display: 'flex', + flexFlow: 'column', + justifyContent: 'center', +}); + +export const heroDescriptionContainer = style({ + alignItems: 'center', + display: 'flex', + justifyContent: 'center', +}); + +export const heroDescriptionIcon = style({ + height: '192px', + marginLeft: '-16px', + width: '192px', +}); + +export const heroDescription = style({ + color: '#76a5ce', + fontFamily: 'Karla Bold, sans-serif', + fontSize: '36px', + fontWeight: 600, +}); + +export const authSection = style({ + alignItems: 'center', + display: 'flex', + flexFlow: 'column', + justifyContent: 'center', +}); + +export const existingAccountText = style({ + color: '#ddefff', + fontFamily: 'Karla Regular, sans-serif', + fontSize: '16px', + fontWeight: 400, + marginBottom: '8px', +}); diff --git a/projects/app-web/app/routes/_index.test.tsx b/projects/app-web/app/routes/_index.test.tsx index 010b5a2..4999bec 100644 --- a/projects/app-web/app/routes/_index.test.tsx +++ b/projects/app-web/app/routes/_index.test.tsx @@ -1,21 +1,46 @@ import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { createRemixStub } from '@remix-run/testing'; -import IndexRoute, { loader } from './_index'; +import { Index } from './_index'; +import { Routes } from '../types'; + +function ExpectedRoute() { + return 'Auth0'; +} function setupTest() { - const IndexRouteStub = createRemixStub([ - { - path: '/', - Component: IndexRoute, - loader, - }, + const user = userEvent.setup(); + + const IndexStub = createRemixStub([ + { path: '/', Component: Index }, + { path: Routes.AuthAuth0, Component: ExpectedRoute, action: () => null }, ]); - render(); + render(); + + return { user }; } -test('it renders a greeting', async () => { - setupTest(); +test('it renders a sign up button that navigates to auth0 when clicked', async () => { + const { user } = setupTest(); + + const signUpButton = await screen.findByRole('button', { name: 'Sign up' }); + + await waitFor(() => user.click(signUpButton)); + + const loggedOutMessage = await screen.findByText('Auth0'); + + expect(loggedOutMessage).toBeInTheDocument(); +}); + +test('it renders a log in button that navigates to auth0 when clicked', async () => { + const { user } = setupTest(); + + const logInButton = await screen.findByRole('button', { name: 'Log in' }); + + await waitFor(() => user.click(logInButton)); + + const loggedOutMessage = await screen.findByText('Auth0'); - await waitFor(() => screen.findByText('hello, world')); + expect(loggedOutMessage).toBeInTheDocument(); }); diff --git a/projects/app-web/app/routes/_index.tsx b/projects/app-web/app/routes/_index.tsx index 7340bb5..a52e815 100644 --- a/projects/app-web/app/routes/_index.tsx +++ b/projects/app-web/app/routes/_index.tsx @@ -1,19 +1,6 @@ -import { useLoaderData, json } from '@remix-run/react'; import { MetaFunction } from '@remix-run/node'; -import { client } from '../client'; -import { graphql } from '../gql'; - -const GetHelloWorld = graphql(/* GraphQL */ ` - query GetHelloWorld { - hello - } -`); - -export const loader = async () => { - const { hello } = await client.request(GetHelloWorld); - - return json({ hello }); -}; +import { LogInButton, SignUpButton } from '../components'; +import * as styles from './_index.css'; export const meta: MetaFunction = () => [ { @@ -22,8 +9,39 @@ export const meta: MetaFunction = () => [ }, ]; -export default function Index() { - const { hello } = useLoaderData(); - - return
{hello}
; +export function Index() { + return ( + <> +
+
+

+ Chron + Chrononomicon brand icon + nomicon +

+ Book icon +

+ Create immersive worlds and run your tabletop campaigns with ease. +

+
+
+
+ + + Already have an account? + + +
+ + ); } + +export default Index; diff --git a/projects/app-web/app/routes/auth+/auth0.test.tsx b/projects/app-web/app/routes/auth+/auth0.test.tsx new file mode 100644 index 0000000..ee4ef3e --- /dev/null +++ b/projects/app-web/app/routes/auth+/auth0.test.tsx @@ -0,0 +1,34 @@ +import { redirect } from '@remix-run/node'; +import { loader, action } from './auth0'; + +const { authenticateMock } = vi.hoisted(() => ({ + authenticateMock: vi.fn(), +})); + +vi.mock('../../authenticator.server', async (importOriginal) => { + const original = + await importOriginal(); + + const authenticator = { + ...original.authenticator, + authenticate: authenticateMock, + }; + + return { authenticator }; +}); + +test('it authenticates the user', async () => { + const request = new Request('https://test.com/'); + const params = {}; + const context = {}; + + await action({ request, params, context }); + + expect(authenticateMock).toBeCalled(); +}); + +test('it redirects to the login page', () => { + const response = loader(); + + expect(response).toEqual(redirect('/login')); +}); diff --git a/projects/app-web/app/routes/auth+/auth0.tsx b/projects/app-web/app/routes/auth+/auth0.tsx new file mode 100644 index 0000000..6383c86 --- /dev/null +++ b/projects/app-web/app/routes/auth+/auth0.tsx @@ -0,0 +1,10 @@ +import { ActionFunctionArgs, redirect } from '@remix-run/node'; +import { authenticator } from '../../authenticator.server'; + +export const loader = () => redirect('/login'); + +export const action = async ({ request }: ActionFunctionArgs) => { + return authenticator.authenticate('auth0', request, { + throwOnError: true, + }); +}; diff --git a/projects/app-web/app/routes/auth+/callback.test.tsx b/projects/app-web/app/routes/auth+/callback.test.tsx new file mode 100644 index 0000000..709f1c5 --- /dev/null +++ b/projects/app-web/app/routes/auth+/callback.test.tsx @@ -0,0 +1,29 @@ +import { redirect } from '@remix-run/node'; +import { loader } from './callback'; + +const { authenticateMock } = vi.hoisted(() => ({ + authenticateMock: vi.fn(async () => ({ id: 'test_id' })), +})); + +vi.mock('../../authenticator.server', async (importOriginal) => { + const original = + await importOriginal(); + + const authenticator = { + ...original.authenticator, + authenticate: authenticateMock, + }; + + return { authenticator }; +}); + +test('it redirects to the dashboard with the correct headers', async () => { + const request = new Request('https://test.com/'); + const params = {}; + const context = {}; + + const response = await loader({ request, params, context }); + + expect(request.headers.get('set-cookie')).toBeNull(); + expect(response).toEqual(redirect('/dashboard')); +}); diff --git a/projects/app-web/app/routes/auth+/callback.tsx b/projects/app-web/app/routes/auth+/callback.tsx new file mode 100644 index 0000000..0ddf4dd --- /dev/null +++ b/projects/app-web/app/routes/auth+/callback.tsx @@ -0,0 +1,37 @@ +import { LoaderFunctionArgs, redirect } from '@remix-run/node'; +import { AuthorizationError } from 'remix-auth'; +import { authenticator } from '../../authenticator.server'; +import { sessionStorage } from '../../session-storage.server'; + +export const loader = async ({ request }: LoaderFunctionArgs) => { + try { + const user = await authenticator.authenticate('auth0', request, { + throwOnError: true, + }); + + const session = await sessionStorage.getSession( + request.headers.get('cookie'), + ); + + session.set(authenticator.sessionKey, user.id); + + const headers = new Headers({ + 'set-cookie': await sessionStorage.commitSession(session), + }); + + return redirect('/dashboard', { headers }); + } catch (error: unknown) { + if (error instanceof Response) { + return error; + } + + // TODO(#15): handle auth errors + if (error instanceof AuthorizationError) { + // TODO(#16): capture via Sentry + throw error; + } + + // TODO(#16): capture via Sentry + throw error; + } +}; diff --git a/projects/app-web/app/routes/auth+/logout.test.tsx b/projects/app-web/app/routes/auth+/logout.test.tsx new file mode 100644 index 0000000..ac34be4 --- /dev/null +++ b/projects/app-web/app/routes/auth+/logout.test.tsx @@ -0,0 +1,25 @@ +import { redirect } from '@remix-run/node'; +import { action } from './logout'; +import { sessionStorage } from '../../session-storage.server'; +import { authenticator } from '../../authenticator.server'; + +test('it redirects to the logout URL with the correct headers', async () => { + const request = new Request('https://test.com/'); + const params = {}; + const context = {}; + + request.headers.set('cookie', 'session=1'); + + const session = await sessionStorage.getSession('session=1'); + + session.set(authenticator.sessionKey, '1'); + + const response = await action({ request, params, context }); + + expect(request.headers.get('set-cookie')).toBeNull(); + expect(response).toEqual( + redirect( + 'https://auth0.com/v2/logout?client_id=auth0_client_id&returnTo=https%3A%2F%2Ftest.com', + ), + ); +}); diff --git a/projects/app-web/app/routes/auth+/logout.ts b/projects/app-web/app/routes/auth+/logout.ts new file mode 100644 index 0000000..1b69a1f --- /dev/null +++ b/projects/app-web/app/routes/auth+/logout.ts @@ -0,0 +1,19 @@ +import { ActionFunctionArgs, redirect } from '@remix-run/node'; +import { sessionStorage } from '../../session-storage.server'; + +export const action = async ({ request }: ActionFunctionArgs) => { + const logoutURL = new URL(import.meta.env.VITE_AUTH0_LOGOUT_URL); + + logoutURL.searchParams.set('client_id', import.meta.env.VITE_AUTH0_CLIENT_ID); + logoutURL.searchParams.set('returnTo', import.meta.env.VITE_AUTH0_RETURN_URL); + + const session = await sessionStorage.getSession( + request.headers.get('cookie'), + ); + + return redirect(logoutURL.toString(), { + headers: { + 'set-cookie': await sessionStorage.destroySession(session), + }, + }); +}; diff --git a/projects/app-web/app/routes/dashboard.test.tsx b/projects/app-web/app/routes/dashboard.test.tsx new file mode 100644 index 0000000..59e99ed --- /dev/null +++ b/projects/app-web/app/routes/dashboard.test.tsx @@ -0,0 +1,59 @@ +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { createRemixStub } from '@remix-run/testing'; +import { Dashboard, loader } from './dashboard'; +import { Routes } from '../types'; +import { db } from '../mocks/db'; +import { client } from '../client'; +import { drop } from '@mswjs/data'; + +function ExpectedRoute() { + return 'Logged out'; +} + +const MOCK_TOKEN = `eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJ0ZXN0IiwiaWF0IjoxNzE0NDA5NTMxLCJleHAiOjE3NDU5NDU1MzEsImF1ZCI6Ind3dy50ZXN0LmNvbSIsInN1YiI6ImF1dGgwfHRlc3RfaWQifQ.Drta5B74QNaMfKpZtFyCde5YG-e1eTU6tySwknytnig`; + +function setupTest() { + const user = userEvent.setup(); + + const DashboardStub = createRemixStub([ + { path: '/', Component: Dashboard, loader }, + { path: Routes.AuthLogout, Component: ExpectedRoute, action: () => null }, + ]); + + client.setHeader('authorization', MOCK_TOKEN); + db.user.create({ auth0ID: 'auth0|test_id', name: 'Test User' }); + + render(); + + return { user }; +} + +function teardownTest() { + drop(db); + client.setHeader('authorization', ''); +} + +test('it renders a greeting from the server', async () => { + setupTest(); + + const greeting = await screen.findByText('Hello, Test User'); + + expect(greeting).toBeInTheDocument(); + + teardownTest(); +}); + +test('it renders a log out button that navigates to the logout route when clicked', async () => { + const { user } = setupTest(); + + const logOutButton = await screen.findByRole('button', { name: 'Log out' }); + + await waitFor(() => user.click(logOutButton)); + + const loggedOutMessage = await screen.findByText('Logged out'); + + expect(loggedOutMessage).toBeInTheDocument(); + + teardownTest(); +}); diff --git a/projects/app-web/app/routes/dashboard.tsx b/projects/app-web/app/routes/dashboard.tsx new file mode 100644 index 0000000..c9abfd7 --- /dev/null +++ b/projects/app-web/app/routes/dashboard.tsx @@ -0,0 +1,40 @@ +import { useLoaderData, json } from '@remix-run/react'; +import { MetaFunction } from '@remix-run/node'; +import { client } from '../client'; +import { graphql } from '../gql'; +import { LogOutButton } from '../components'; + +const GetCurrentUser = graphql(/* GraphQL */ ` + query GetCurrentUser { + getCurrentUser { + id + name + } + } +`); + +export const loader = async () => { + const { getCurrentUser } = await client.request(GetCurrentUser); + + return json({ user: getCurrentUser }); +}; + +export const meta: MetaFunction = () => [ + { + title: '', + description: '', + }, +]; + +export function Dashboard() { + const { user } = useLoaderData(); + + return ( + <> +
Hello, {user.name}
+ + + ); +} + +export default Dashboard; diff --git a/projects/app-web/app/session-storage.server.ts b/projects/app-web/app/session-storage.server.ts new file mode 100644 index 0000000..ed3b2b1 --- /dev/null +++ b/projects/app-web/app/session-storage.server.ts @@ -0,0 +1,28 @@ +import invariant from 'tiny-invariant'; +import { createCookieSessionStorage } from '@remix-run/node'; + +type SessionData = { + [key: string]: string; +}; + +type SessionFlashData = { + error: string; +}; + +invariant(process.env.SESSION_SECRET, '$SESSION_SECRET is required'); + +export const sessionStorage = createCookieSessionStorage< + SessionData, + SessionFlashData +>({ + cookie: { + name: '__session', + domain: import.meta.env.VITE_DOMAIN, + httpOnly: true, + maxAge: 60, + path: '/', + sameSite: 'lax', + secrets: [process.env.SESSION_SECRET], + secure: true, + }, +}); diff --git a/projects/app-web/app/styles/fonts.css b/projects/app-web/app/styles/fonts.css new file mode 100644 index 0000000..ff1034c --- /dev/null +++ b/projects/app-web/app/styles/fonts.css @@ -0,0 +1,44 @@ +@font-face { + font-family: 'Josefin Sans Medium'; + src: + url('/assets/fonts/josefin-sans-semi-bold.woff2') format('woff2'), + url('/assets/fonts/josefin-sans-semi-bold.woff') format('woff'); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: 'Josefin Slab Bold'; + src: + url('/assets/fonts/josefin-slab-bold.woff2') format('woff2'), + url('/assets/fonts/josefin-slab-bold.woff') format('woff'); + font-weight: 700; + font-style: normal; +} + +@font-face { + font-family: 'Karla Light'; + src: + url('/assets/fonts/karla-light.woff2') format('woff2'), + url('/assets/fonts/karla-light.woff') format('woff'); + font-weight: 200; + font-style: normal; +} + +@font-face { + font-family: 'Karla Regular'; + src: + url('/assets/fonts/karla-regular.woff2') format('woff2'), + url('/assets/fonts/karla-regular.woff') format('woff'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'Karla Bold'; + src: + url('/assets/fonts/karla-bold.woff2') format('woff2'), + url('/assets/fonts/karla-bold.woff') format('woff'); + font-weight: 600; + font-style: normal; +} diff --git a/projects/app-web/app/types.ts b/projects/app-web/app/types.ts new file mode 100644 index 0000000..e36ecd8 --- /dev/null +++ b/projects/app-web/app/types.ts @@ -0,0 +1,9 @@ +export enum Routes { + Index = '/', + + AuthAuth0 = '/auth/auth0', + AuthCallback = '/auth/callback', + AuthLogout = '/auth/logout', + + Dashboard = '/dashboard', +} diff --git a/projects/app-web/app/utils/index.ts b/projects/app-web/app/utils/index.ts new file mode 100644 index 0000000..e91593e --- /dev/null +++ b/projects/app-web/app/utils/index.ts @@ -0,0 +1 @@ +export { isMutationError } from './is-mutation-error'; diff --git a/projects/app-web/app/utils/is-mutation-error.test.ts b/projects/app-web/app/utils/is-mutation-error.test.ts new file mode 100644 index 0000000..4303427 --- /dev/null +++ b/projects/app-web/app/utils/is-mutation-error.test.ts @@ -0,0 +1,21 @@ +import { isMutationError } from './is-mutation-error'; + +test('it returns true if the provided data is a mutation error', () => { + const result = isMutationError({ + error: { + message: 'Test error', + }, + }); + + expect(result).toBeTrue(); +}); + +test('it returns false if the provided data is not a mutation error', () => { + const result = isMutationError({ + data: { + test: true, + }, + }); + + expect(result).toBeFalse(); +}); diff --git a/projects/app-web/app/utils/is-mutation-error.ts b/projects/app-web/app/utils/is-mutation-error.ts new file mode 100644 index 0000000..c8f8b48 --- /dev/null +++ b/projects/app-web/app/utils/is-mutation-error.ts @@ -0,0 +1,7 @@ +import { MutationErrorPayload } from '../gql/graphql'; + +export function isMutationError( + payload: T | MutationErrorPayload, +): payload is MutationErrorPayload { + return 'error' in payload; +} diff --git a/projects/app-web/app/vite-env.d.ts b/projects/app-web/app/vite-env.d.ts new file mode 100644 index 0000000..48b7281 --- /dev/null +++ b/projects/app-web/app/vite-env.d.ts @@ -0,0 +1,18 @@ +/// + +interface ImportMetaEnv { + readonly VITE_API_URL: string; + + readonly VITE_AUTH0_AUDIENCE: string; + readonly VITE_AUTH0_CALLBACK_URL: string; + readonly VITE_AUTH0_CLIENT_ID: string; + readonly VITE_AUTH0_DOMAIN: string; + readonly VITE_AUTH0_LOGOUT_URL: string; + readonly VITE_AUTH0_RETURN_URL: string; + + readonly VITE_ENABLE_MSW: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/projects/app-web/app/vitest.d.ts b/projects/app-web/app/vitest.d.ts new file mode 100644 index 0000000..fa5faba --- /dev/null +++ b/projects/app-web/app/vitest.d.ts @@ -0,0 +1,13 @@ +import * as matchers from '@testing-library/jest-dom/matchers'; +import { expect } from 'vitest'; + +expect.extend(matchers); + +// vitest instead `@vitest/expect` +declare module 'vitest' { + interface JestAssertion + extends matchers.TestingLibraryMatchers< + ReturnType, + T + > {} +} diff --git a/projects/app-web/package.json b/projects/app-web/package.json index a860b99..ef47ecb 100644 --- a/projects/app-web/package.json +++ b/projects/app-web/package.json @@ -11,34 +11,50 @@ "@hono/node-server": "1.11.0", "@remix-run/node": "2.9.1", "@remix-run/react": "2.9.1", + "@remix-run/server-runtime": "2.9.1", + "@vanilla-extract/css": "1.14.2", + "@vanilla-extract/sprinkles": "1.6.1", "graphql-request": "6.1.0", "hono": "4.2.4", "isbot": "4", "msw": "2.2.14", "react": "18.2.0", "react-dom": "18.2.0", - "remix-hono": "0.0.16" + "remix-auth": "3.6.0", + "remix-auth-auth0": "1.10.0", + "remix-auth-oauth2": "1.11.2", + "remix-hono": "0.0.16", + "tiny-invariant": "1.3.3" }, "devDependencies": { "@graphql-typed-document-node/core": "3.2.0", + "@mswjs/data": "0.16.1", "@nx/vite": "18.3.3", + "@paralleldrive/cuid2": "2.2.2", "@remix-run/dev": "2.9.1", "@remix-run/testing": "2.9.1", + "@testing-library/dom": "10.0.0", "@testing-library/jest-dom": "6.4.2", "@testing-library/react": "14.3.0", + "@testing-library/user-event": "14.5.2", "@types/node": "20.12.7", "@types/react": "18.2.75", "@types/react-dom": "18.2.24", + "@vanilla-extract/vite-plugin": "4.0.7", "@vitejs/plugin-react": "4.2.1", + "@vitest/expect": "1.5.2", "eslint-plugin-jsx-a11y": "6.8.0", "eslint-plugin-react": "7.34.1", "eslint-plugin-react-hooks": "4.6.0", "graphql": "16.8.1", "jest-extended": "4.0.2", + "jwt-decode": "4.0.0", + "remix-flat-routes": "0.6.4", "tslib": "2.6.2", "typescript": "5.4.5", + "uuid": "9.0.1", "vite": "5.2.10", - "vitest": "1.5.1" + "vitest": "1.5.2" }, "engines": { "node": "20.12.2" diff --git a/projects/app-web/public/assets/fonts/josefin-sans-semi-bold.woff b/projects/app-web/public/assets/fonts/josefin-sans-semi-bold.woff new file mode 100644 index 0000000..e29b5b1 Binary files /dev/null and b/projects/app-web/public/assets/fonts/josefin-sans-semi-bold.woff differ diff --git a/projects/app-web/public/assets/fonts/josefin-sans-semi-bold.woff2 b/projects/app-web/public/assets/fonts/josefin-sans-semi-bold.woff2 new file mode 100644 index 0000000..d438cd3 Binary files /dev/null and b/projects/app-web/public/assets/fonts/josefin-sans-semi-bold.woff2 differ diff --git a/projects/app-web/public/assets/fonts/josefin-slab-bold.woff b/projects/app-web/public/assets/fonts/josefin-slab-bold.woff new file mode 100644 index 0000000..6fc3d99 Binary files /dev/null and b/projects/app-web/public/assets/fonts/josefin-slab-bold.woff differ diff --git a/projects/app-web/public/assets/fonts/josefin-slab-bold.woff2 b/projects/app-web/public/assets/fonts/josefin-slab-bold.woff2 new file mode 100644 index 0000000..780717d Binary files /dev/null and b/projects/app-web/public/assets/fonts/josefin-slab-bold.woff2 differ diff --git a/projects/app-web/public/assets/fonts/karla-bold.woff b/projects/app-web/public/assets/fonts/karla-bold.woff new file mode 100644 index 0000000..f956988 Binary files /dev/null and b/projects/app-web/public/assets/fonts/karla-bold.woff differ diff --git a/projects/app-web/public/assets/fonts/karla-bold.woff2 b/projects/app-web/public/assets/fonts/karla-bold.woff2 new file mode 100644 index 0000000..586b473 Binary files /dev/null and b/projects/app-web/public/assets/fonts/karla-bold.woff2 differ diff --git a/projects/app-web/public/assets/fonts/karla-light.woff b/projects/app-web/public/assets/fonts/karla-light.woff new file mode 100644 index 0000000..167c985 Binary files /dev/null and b/projects/app-web/public/assets/fonts/karla-light.woff differ diff --git a/projects/app-web/public/assets/fonts/karla-light.woff2 b/projects/app-web/public/assets/fonts/karla-light.woff2 new file mode 100644 index 0000000..5bec01b Binary files /dev/null and b/projects/app-web/public/assets/fonts/karla-light.woff2 differ diff --git a/projects/app-web/public/assets/fonts/karla-regular.woff b/projects/app-web/public/assets/fonts/karla-regular.woff new file mode 100644 index 0000000..84ef93a Binary files /dev/null and b/projects/app-web/public/assets/fonts/karla-regular.woff differ diff --git a/projects/app-web/public/assets/fonts/karla-regular.woff2 b/projects/app-web/public/assets/fonts/karla-regular.woff2 new file mode 100644 index 0000000..dd48387 Binary files /dev/null and b/projects/app-web/public/assets/fonts/karla-regular.woff2 differ diff --git a/projects/app-web/public/assets/images/brand-icon-dark.png b/projects/app-web/public/assets/images/brand-icon-dark.png new file mode 100644 index 0000000..623fbe8 Binary files /dev/null and b/projects/app-web/public/assets/images/brand-icon-dark.png differ diff --git a/projects/app-web/public/assets/images/brand-icon-light.png b/projects/app-web/public/assets/images/brand-icon-light.png new file mode 100644 index 0000000..8f8e946 Binary files /dev/null and b/projects/app-web/public/assets/images/brand-icon-light.png differ diff --git a/projects/app-web/public/assets/images/icon-book.png b/projects/app-web/public/assets/images/icon-book.png new file mode 100644 index 0000000..94441c3 Binary files /dev/null and b/projects/app-web/public/assets/images/icon-book.png differ diff --git a/projects/app-web/vite.config.ts b/projects/app-web/vite.config.ts index 62930f1..53bc6ac 100755 --- a/projects/app-web/vite.config.ts +++ b/projects/app-web/vite.config.ts @@ -6,6 +6,8 @@ import { vitePlugin as remix } from '@remix-run/dev'; import { installGlobals } from '@remix-run/node'; import react from '@vitejs/plugin-react'; import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; +import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin'; +import { flatRoutes } from 'remix-flat-routes'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -35,9 +37,28 @@ export default defineConfig({ plugins: [ react(), + vanillaExtractPlugin(), !process.env.VITEST && remix({ - ignoredRouteFiles: ['**/*.test.*'], + ignoredRouteFiles: ['**/*'], + routes: async (defineRoutes) => { + return flatRoutes('routes', defineRoutes, { + // because `nx` builds our project graph from the workspace root, we need to + // adjust the appDir to the correct location of the app-web folder for that case + appDir: + process.cwd() === __dirname ? 'app' : 'projects/app-web/app', + ignoredRouteFiles: [ + '.*', + '**/*.css', + '**/*.test.{ts,tsx}', + '**/__*.*', + // this allows server files to be colocated with routes. use escape brackets to user 'server' or 'client' + // in the filename ex. my-route.[server].tsx + '**/*.server.*', + '**/*.client.*', + ], + }); + }, }), nxViteTsPaths(), ], @@ -47,7 +68,13 @@ export default defineConfig({ setupFiles: ['vitest.setup.ts'], globals: true, environment: 'happy-dom', - env: loadEnv('test', process.cwd(), ''), + env: { + ...loadEnv('test', process.cwd(), ''), + + // set secret env vars here so we don't need to load a `.local` env file in tests + SESSION_SECRET: 'secret', + AUTH0_CLIENT_SECRET: 'secret', + }, include: ['app/**/*.test.{ts,tsx}'], reporters: ['default'], coverage: { diff --git a/projects/app-web/vitest.setup.ts b/projects/app-web/vitest.setup.ts index 79d3e28..f1ae48d 100644 --- a/projects/app-web/vitest.setup.ts +++ b/projects/app-web/vitest.setup.ts @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom/matchers'; +import '@testing-library/jest-dom/vitest'; import * as matchers from 'jest-extended'; // import { installGlobals } from '@remix-run/node'; import { server } from './app/mocks/node'; diff --git a/projects/db-postgres/drizzle.config.ts b/projects/db-postgres/drizzle.config.ts index 3019352..bd2d115 100644 --- a/projects/db-postgres/drizzle.config.ts +++ b/projects/db-postgres/drizzle.config.ts @@ -1,7 +1,7 @@ import type { Config } from 'drizzle-kit'; export default { - schema: './src/schema.ts', + schema: '../lib-postgres-schema/src/index.ts', out: './migrations', driver: 'pg', } satisfies Config; diff --git a/projects/db-postgres/migrations/0001_yummy_prodigy.sql b/projects/db-postgres/migrations/0001_yummy_prodigy.sql new file mode 100644 index 0000000..8ae8d9c --- /dev/null +++ b/projects/db-postgres/migrations/0001_yummy_prodigy.sql @@ -0,0 +1,7 @@ +ALTER TABLE "users" ALTER COLUMN "email" SET NOT NULL;--> statement-breakpoint +ALTER TABLE "users" ALTER COLUMN "email_verified" SET NOT NULL;--> statement-breakpoint +ALTER TABLE "users" ALTER COLUMN "name" SET NOT NULL;--> statement-breakpoint +ALTER TABLE "users" ALTER COLUMN "created_at" SET NOT NULL;--> statement-breakpoint +ALTER TABLE "users" ADD COLUMN "auth0_id" text NOT NULL;--> statement-breakpoint +ALTER TABLE "users" ADD COLUMN "first_name" text;--> statement-breakpoint +ALTER TABLE "users" ADD CONSTRAINT "users_auth0_id_unique" UNIQUE("auth0_id"); \ No newline at end of file diff --git a/projects/db-postgres/migrations/meta/0001_snapshot.json b/projects/db-postgres/migrations/meta/0001_snapshot.json new file mode 100644 index 0000000..8bfae7f --- /dev/null +++ b/projects/db-postgres/migrations/meta/0001_snapshot.json @@ -0,0 +1,79 @@ +{ + "id": "b9cd3f67-6398-4e1b-bf34-56edd9c360b7", + "prevId": "ef8f887a-ba0d-4635-96de-08a6d58fb7d7", + "version": "5", + "dialect": "pg", + "tables": { + "users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "auth0_id": { + "name": "auth0_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_auth0_id_unique": { + "name": "users_auth0_id_unique", + "nullsNotDistinct": false, + "columns": ["auth0_id"] + }, + "users_email_unique": { + "name": "users_email_unique", + "nullsNotDistinct": false, + "columns": ["email"] + } + } + } + }, + "enums": {}, + "schemas": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} diff --git a/projects/db-postgres/migrations/meta/_journal.json b/projects/db-postgres/migrations/meta/_journal.json index 5a0a6fa..704f8c0 100644 --- a/projects/db-postgres/migrations/meta/_journal.json +++ b/projects/db-postgres/migrations/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1714110253584, "tag": "0000_careful_wrecking_crew", "breakpoints": true + }, + { + "idx": 1, + "version": "5", + "when": 1714230768356, + "tag": "0001_yummy_prodigy", + "breakpoints": true } ] } diff --git a/projects/lib-postgres-schema/src/users.ts b/projects/lib-postgres-schema/src/users.ts index 8f70b1c..ea206f6 100644 --- a/projects/lib-postgres-schema/src/users.ts +++ b/projects/lib-postgres-schema/src/users.ts @@ -1,9 +1,11 @@ import { boolean, pgTable, text, timestamp } from 'drizzle-orm/pg-core'; export const users = pgTable('users', { - id: text('id').primaryKey(), - email: text('email').unique(), - emailVerified: boolean('email_verified'), - name: text('name'), - createdAt: timestamp('created_at').defaultNow(), + id: text('id').notNull().primaryKey(), + auth0ID: text('auth0_id').notNull().unique(), + email: text('email').notNull().unique(), + emailVerified: boolean('email_verified').notNull(), + name: text('name').notNull(), + firstName: text('first_name'), + createdAt: timestamp('created_at').notNull().defaultNow(), }); diff --git a/projects/lib-postgres-schema/vitest.config.ts b/projects/lib-postgres-schema/vitest.config.ts index 21801bf..6f09fb6 100755 --- a/projects/lib-postgres-schema/vitest.config.ts +++ b/projects/lib-postgres-schema/vitest.config.ts @@ -1,6 +1,8 @@ import { defineConfig } from 'vitest/config'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ + plugins: [nxViteTsPaths()], test: { globals: true, environment: 'node', diff --git a/projects/lib-service-test-utils/src/postgres-test-utils.ts b/projects/lib-service-test-utils/src/postgres-test-utils.ts index 5331468..17f8652 100644 --- a/projects/lib-service-test-utils/src/postgres-test-utils.ts +++ b/projects/lib-service-test-utils/src/postgres-test-utils.ts @@ -6,7 +6,7 @@ import { PostgresJsDatabase, drizzle } from 'drizzle-orm/postgres-js'; import { migrate } from 'drizzle-orm/postgres-js/migrator'; import path from 'node:path'; import postgres, { Sql } from 'postgres'; -import cuid from 'cuid'; +import { createId } from '@paralleldrive/cuid2'; import * as schema from '@campaign/postgres-schema'; const TEST_TEMPLATE_DB = 'test_template'; @@ -41,7 +41,7 @@ export const PostgresTestUtils: IPostgresTestUtils = { 'postgres', ); - const testDBID = cuid(); + const testDBID = createId(); // create a new DB for this test from our pre-migrated template DB // for some reason we need to jump into unsafe mode otherwise `postgres` wont inline our params diff --git a/projects/lib-service-test-utils/vitest.config.ts b/projects/lib-service-test-utils/vitest.config.ts index d81ac80..60ead0f 100755 --- a/projects/lib-service-test-utils/vitest.config.ts +++ b/projects/lib-service-test-utils/vitest.config.ts @@ -1,6 +1,8 @@ import { defineConfig } from 'vitest/config'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ + plugins: [nxViteTsPaths()], test: { globals: true, environment: 'node', diff --git a/projects/lib-service-utils/src/context-utils/get-user-from-context.ts b/projects/lib-service-utils/src/context-utils/get-user-from-context.ts deleted file mode 100644 index 4882f73..0000000 --- a/projects/lib-service-utils/src/context-utils/get-user-from-context.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Context } from 'hono'; -import { HTTPException } from 'hono/http-exception'; - -type User = { - id: string; - email: string; - emailVerified: boolean; - name: string; -}; - -export function getUserFromContext(ctx: Context): User { - const tokenPayload = ctx.get('jwtPayload'); - - if (!tokenPayload) { - throw new HTTPException(401, { message: 'Unauthorized' }); - } - - return { - id: tokenPayload.sub, // TODO: what does this look like? can we pull a clean user ID? - email: tokenPayload.email, - emailVerified: tokenPayload.email_verified === 'true', - name: tokenPayload.name, - }; -} diff --git a/projects/lib-service-utils/src/index.ts b/projects/lib-service-utils/src/index.ts index 453e789..5668291 100644 --- a/projects/lib-service-utils/src/index.ts +++ b/projects/lib-service-utils/src/index.ts @@ -1,5 +1,6 @@ -export { getTokenFromContext } from './context-utils/get-token-from-context'; -export { getUserFromContext } from './context-utils/get-user-from-context'; -export { createTokenVerifier } from './context-utils/create-token-verifier'; +export { createTokenVerifier } from './utils/create-token-verifier'; +export { getTokenFromContext } from './utils/get-token-from-context'; +export { getTokenFromHeader } from './utils/get-token-from-header'; +export { getUserIDFromContext } from './utils/get-user-id-from-context'; export { createAuthMiddleware } from './middleware/create-auth-middleware'; diff --git a/projects/lib-service-utils/src/middleware/create-auth-middleware.test.ts b/projects/lib-service-utils/src/middleware/create-auth-middleware.test.ts index e66f392..65ace52 100644 --- a/projects/lib-service-utils/src/middleware/create-auth-middleware.test.ts +++ b/projects/lib-service-utils/src/middleware/create-auth-middleware.test.ts @@ -61,6 +61,23 @@ test('it returns a 401 if no token is provided', async () => { expect(res.status).toBe(401); }); +test('it rejects an invalid authorization header', async () => { + const { app } = setupTest(); + + const req = new Request('http://localhost/test'); + + req.headers.set('Authorization', `Bearer`); + + const res = await app.request(req); + + expect(testHandlerSpy).not.toHaveBeenCalled(); + expect(await res.text()).toBe('Unauthorized'); + expect(res.status).toBe(401); + expect(res.headers.get('www-authenticate')).toMatchInlineSnapshot( + `"Bearer realm="http://localhost/test",error="invalid_request",error_description="invalid authorization header structure""`, + ); +}); + test('it rejects an invalid token', async () => { const { app } = setupTest(); diff --git a/projects/lib-service-utils/src/middleware/create-auth-middleware.ts b/projects/lib-service-utils/src/middleware/create-auth-middleware.ts index f7b01ac..c74e4f7 100644 --- a/projects/lib-service-utils/src/middleware/create-auth-middleware.ts +++ b/projects/lib-service-utils/src/middleware/create-auth-middleware.ts @@ -3,7 +3,8 @@ import { HTTPException } from 'hono/http-exception'; import { createTokenVerifier, TokenVerifierConfig, -} from '../context-utils/create-token-verifier'; +} from '../utils/create-token-verifier.js'; +import { getTokenFromHeader } from '../utils/get-token-from-header'; type AuthMiddlewareConfig = { tokenVerifierConfig: TokenVerifierConfig; @@ -33,9 +34,9 @@ export function createAuthMiddleware(config: AuthMiddlewareConfig) { }); } - const parts = authHeader.split(/\s+/); + const token = getTokenFromHeader(authHeader); - if (parts.length !== 2) { + if (!token) { const errorDescription = 'invalid authorization header structure'; throw new HTTPException(401, { @@ -48,8 +49,6 @@ export function createAuthMiddleware(config: AuthMiddlewareConfig) { }); } - const [, token] = parts; - try { const payload = await verifyToken(token); diff --git a/projects/lib-service-utils/src/context-utils/create-token-verifier.test.ts b/projects/lib-service-utils/src/utils/create-token-verifier.test.ts similarity index 100% rename from projects/lib-service-utils/src/context-utils/create-token-verifier.test.ts rename to projects/lib-service-utils/src/utils/create-token-verifier.test.ts diff --git a/projects/lib-service-utils/src/context-utils/create-token-verifier.ts b/projects/lib-service-utils/src/utils/create-token-verifier.ts similarity index 100% rename from projects/lib-service-utils/src/context-utils/create-token-verifier.ts rename to projects/lib-service-utils/src/utils/create-token-verifier.ts diff --git a/projects/lib-service-utils/src/context-utils/get-token-from-context.test.ts b/projects/lib-service-utils/src/utils/get-token-from-context.test.ts similarity index 100% rename from projects/lib-service-utils/src/context-utils/get-token-from-context.test.ts rename to projects/lib-service-utils/src/utils/get-token-from-context.test.ts diff --git a/projects/lib-service-utils/src/context-utils/get-token-from-context.ts b/projects/lib-service-utils/src/utils/get-token-from-context.ts similarity index 100% rename from projects/lib-service-utils/src/context-utils/get-token-from-context.ts rename to projects/lib-service-utils/src/utils/get-token-from-context.ts diff --git a/projects/lib-service-utils/src/utils/get-token-from-header.test.ts b/projects/lib-service-utils/src/utils/get-token-from-header.test.ts new file mode 100644 index 0000000..d39dc4a --- /dev/null +++ b/projects/lib-service-utils/src/utils/get-token-from-header.test.ts @@ -0,0 +1,25 @@ +import { getTokenFromHeader } from './get-token-from-header'; + +test('it extracts the token from the header', () => { + const header = 'Bearer token'; + + const token = getTokenFromHeader(header); + + expect(token).toBe('token'); +}); + +test('it returns null if the provided header is null', () => { + const header = null; + + const token = getTokenFromHeader(header); + + expect(token).toBeNull(); +}); + +test('it returns null if the provided header is invalid', () => { + const header = 'Bearer'; + + const token = getTokenFromHeader(header); + + expect(token).toBeNull(); +}); diff --git a/projects/lib-service-utils/src/utils/get-token-from-header.ts b/projects/lib-service-utils/src/utils/get-token-from-header.ts new file mode 100644 index 0000000..4d93136 --- /dev/null +++ b/projects/lib-service-utils/src/utils/get-token-from-header.ts @@ -0,0 +1,9 @@ +export function getTokenFromHeader(header: string | null): string | null { + if (header === null) { + return null; + } + + const [, token] = header.split(/\s+/); + + return token ?? null; +} diff --git a/projects/lib-service-utils/src/context-utils/get-user-from-context.test.ts b/projects/lib-service-utils/src/utils/get-user-id-from-context.test.ts similarity index 63% rename from projects/lib-service-utils/src/context-utils/get-user-from-context.test.ts rename to projects/lib-service-utils/src/utils/get-user-id-from-context.test.ts index 9d79f4a..3fd939b 100644 --- a/projects/lib-service-utils/src/context-utils/get-user-from-context.test.ts +++ b/projects/lib-service-utils/src/utils/get-user-id-from-context.test.ts @@ -1,5 +1,5 @@ import { Context, Hono } from 'hono'; -import { getUserFromContext } from './get-user-from-context'; +import { getUserIDFromContext } from './get-user-id-from-context'; function setupTest() { const app = new Hono(); @@ -12,40 +12,30 @@ test('it extracts the user from the context', async () => { const jwtPayload = { sub: 'test_id', - email: 'user@test.com', - email_verified: 'true', - name: 'Test User', }; app.get('/test', (ctx: Context) => { ctx.set('jwtPayload', jwtPayload); - const user = getUserFromContext(ctx); + const userID = getUserIDFromContext(ctx); - return ctx.json({ user }); + return ctx.json({ userID }); }); const req = new Request('http://localhost/test'); const res = await app.request(req); expect(res.status).toBe(200); - expect(await res.json()).toMatchObject({ - user: { - id: 'test_id', - email: 'user@test.com', - emailVerified: true, - name: 'Test User', - }, - }); + expect(await res.json()).toMatchObject({ userID: 'test_id' }); }); test('it throws a 401 error if no token was provided', async () => { const { app } = setupTest(); app.get('/test', (ctx: Context) => { - const user = getUserFromContext(ctx); + const userID = getUserIDFromContext(ctx); - return ctx.json({ user }); + return ctx.json({ userID }); }); const req = new Request('http://localhost/test'); diff --git a/projects/lib-service-utils/src/utils/get-user-id-from-context.ts b/projects/lib-service-utils/src/utils/get-user-id-from-context.ts new file mode 100644 index 0000000..b776b80 --- /dev/null +++ b/projects/lib-service-utils/src/utils/get-user-id-from-context.ts @@ -0,0 +1,12 @@ +import { Context } from 'hono'; +import { HTTPException } from 'hono/http-exception'; + +export function getUserIDFromContext(ctx: Context): string { + const tokenPayload = ctx.get('jwtPayload'); + + if (!tokenPayload) { + throw new HTTPException(401, { message: 'Unauthorized' }); + } + + return tokenPayload.sub; +} diff --git a/projects/lib-service-utils/vitest.config.ts b/projects/lib-service-utils/vitest.config.ts index e63939c..2927488 100755 --- a/projects/lib-service-utils/vitest.config.ts +++ b/projects/lib-service-utils/vitest.config.ts @@ -1,6 +1,8 @@ import { defineConfig } from 'vitest/config'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ + plugins: [nxViteTsPaths()], test: { globals: true, environment: 'node', diff --git a/projects/service-api/.env b/projects/service-api/.env deleted file mode 100644 index e69de29..0000000 diff --git a/projects/service-api/.env.development b/projects/service-api/.env.development new file mode 100644 index 0000000..8c577f4 --- /dev/null +++ b/projects/service-api/.env.development @@ -0,0 +1,3 @@ +USERS_API_URL=http://localhost:3001/ +API_IDENTIFIER="http://localhost:3000/" +AUTH0_DOMAIN="chrononomicon.us.auth0.com" \ No newline at end of file diff --git a/projects/service-api/.env.test b/projects/service-api/.env.test new file mode 100644 index 0000000..b440031 --- /dev/null +++ b/projects/service-api/.env.test @@ -0,0 +1,3 @@ +USERS_API_URL=http://localhost:3001/ +API_IDENTIFIER="https://test.com/" +AUTH0_DOMAIN="test.com" \ No newline at end of file diff --git a/projects/service-api/src/db.ts b/projects/service-api/src/db.ts deleted file mode 100644 index 02ccaaa..0000000 --- a/projects/service-api/src/db.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { drizzle } from 'drizzle-orm/postgres-js'; -import postgres from 'postgres'; -import { env } from './env'; - -const queryClient = postgres(env.POSTGRES_URL); - -export const db = drizzle(queryClient); diff --git a/projects/service-api/src/env.ts b/projects/service-api/src/env.ts index d98a975..7dfef43 100755 --- a/projects/service-api/src/env.ts +++ b/projects/service-api/src/env.ts @@ -1,11 +1,16 @@ -import { cleanEnv, str } from 'envalid'; +import { cleanEnv, str, url } from 'envalid'; import { Env } from './types'; export const env: Env = cleanEnv(process.env, { - POSTGRES_URL: str(), + NODE_ENV: str({ choices: ['development', 'test', 'production'] }), LOGGING: str({ choices: ['debug', 'info', 'warn', 'error'], default: 'info', }), - NODE_ENV: str({ choices: ['development', 'test', 'production'] }), + + API_IDENTIFIER: str(), + AUTH0_DOMAIN: str(), + + // service URLs + USERS_API_URL: url(), }); diff --git a/projects/service-api/src/init-yoga.ts b/projects/service-api/src/init-yoga.ts index fe7dc39..4780bf1 100644 --- a/projects/service-api/src/init-yoga.ts +++ b/projects/service-api/src/init-yoga.ts @@ -1,7 +1,9 @@ -import { createYoga } from 'graphql-yoga'; +import { YogaInitialContext, createYoga } from 'graphql-yoga'; import { schema } from './schema'; import { env } from './env'; import { app } from './app'; +import { createUserService } from './services/user-service/create-user-service'; +import { getTokenFromHeader } from '@campaign/service-utils'; export function initYoga() { app.on(['GET', 'POST'], '/graphql', async (ctx) => { @@ -11,8 +13,23 @@ export function initYoga() { graphqlEndpoint: '/graphql', graphiql: env.isDevelopment, schema: schema, + context: createYogaContext, }); return yoga.fetch(ctx.req.raw, ctx.env); }); } + +export function createYogaContext(ctx: YogaInitialContext) { + const authHeader = ctx.request.headers.get('authorization'); + + return { + request: ctx.request, + services: { + users: createUserService({ + accessToken: getTokenFromHeader(authHeader), + apiURL: env.USERS_API_URL, + }), + }, + }; +} diff --git a/projects/service-api/src/main.ts b/projects/service-api/src/main.ts index 37f122f..2c54871 100644 --- a/projects/service-api/src/main.ts +++ b/projects/service-api/src/main.ts @@ -1,8 +1,12 @@ import { serve } from '@hono/node-server'; +import { logger } from 'hono/logger'; import { app } from './app'; import { initYoga } from './init-yoga'; +app.use(logger()); + initYoga(); -serve(app); + +serve({ fetch: app.fetch, port: 3000 }); console.log('⚡️ Serving GraphQL API @ http://localhost:3000/graphql'); diff --git a/projects/service-api/src/mocks/db.ts b/projects/service-api/src/mocks/db.ts new file mode 100644 index 0000000..260ef92 --- /dev/null +++ b/projects/service-api/src/mocks/db.ts @@ -0,0 +1,13 @@ +import { factory, primaryKey } from '@mswjs/data'; + +export const db = factory({ + user: { + id: primaryKey(() => 'test_id'), + auth0ID: () => 'auth0|test_id', + email: () => 'user@test.com', + emailVerified: () => true, + name: () => 'Test User', + firstName: () => 'John', + createdAt: () => new Date(), + }, +}); diff --git a/projects/service-api/src/mocks/handlers/http/get-current-user.ts b/projects/service-api/src/mocks/handlers/http/get-current-user.ts new file mode 100644 index 0000000..4d35f22 --- /dev/null +++ b/projects/service-api/src/mocks/handlers/http/get-current-user.ts @@ -0,0 +1,30 @@ +import { http, HttpResponse } from 'msw'; +import { + createTokenVerifier, + getTokenFromHeader, +} from '@campaign/service-utils'; +import { env } from '../../../env'; +import { db } from '../../db'; + +const verifyToken = createTokenVerifier({ + audience: env.API_IDENTIFIER, + issuer: `https://${env.AUTH0_DOMAIN}/`, +}); + +const ENDPOINT_URL = `${env.USERS_API_URL}get-current-user`; + +export const getCurrentUser = http.get(ENDPOINT_URL, async ({ request }) => { + const authHeader = request.headers.get('authorization'); + const accessToken = getTokenFromHeader(authHeader); + + if (!accessToken) { + return new HttpResponse(null, { status: 401 }); + } + + const payload = (await verifyToken(accessToken)) as { sub: string }; + + const userID = payload.sub; + const user = db.user.findFirst({ where: { id: { equals: userID } } }); + + return HttpResponse.json({ success: true, data: user }); +}); diff --git a/projects/service-api/src/mocks/handlers/http/get-or-create-user.ts b/projects/service-api/src/mocks/handlers/http/get-or-create-user.ts new file mode 100644 index 0000000..ce63cfc --- /dev/null +++ b/projects/service-api/src/mocks/handlers/http/get-or-create-user.ts @@ -0,0 +1,39 @@ +import { http, HttpResponse } from 'msw'; +import { + createTokenVerifier, + getTokenFromHeader, +} from '@campaign/service-utils'; +import { env } from '../../../env'; +import { db } from '../../db'; + +const verifyToken = createTokenVerifier({ + audience: env.API_IDENTIFIER, + issuer: `https://${env.AUTH0_DOMAIN}/`, +}); + +const ENDPOINT_URL = `${env.USERS_API_URL}get-or-create-user`; + +export const getOrCreateUser = http.post(ENDPOINT_URL, async ({ request }) => { + const authHeader = request.headers.get('authorization'); + const accessToken = getTokenFromHeader(authHeader); + + if (!accessToken) { + return new HttpResponse(null, { status: 401 }); + } + + const payload = (await verifyToken(accessToken)) as { sub: string }; + + const userID = payload.sub; + const existingUser = db.user.findFirst({ where: { id: { equals: userID } } }); + + if (existingUser) { + return HttpResponse.json({ success: true, data: existingUser }); + } + + const user = db.user.create({ + id: userID, + auth0ID: `auth0|${userID}`, + }); + + return HttpResponse.json({ success: true, data: user }); +}); diff --git a/projects/service-api/src/mocks/handlers/http/index.ts b/projects/service-api/src/mocks/handlers/http/index.ts new file mode 100644 index 0000000..b0e581b --- /dev/null +++ b/projects/service-api/src/mocks/handlers/http/index.ts @@ -0,0 +1,4 @@ +import { getCurrentUser } from './get-current-user'; +import { getOrCreateUser } from './get-or-create-user'; + +export const handlers = [getCurrentUser, getOrCreateUser]; diff --git a/projects/service-api/src/mocks/handlers/index.ts b/projects/service-api/src/mocks/handlers/index.ts new file mode 100644 index 0000000..1ee3062 --- /dev/null +++ b/projects/service-api/src/mocks/handlers/index.ts @@ -0,0 +1,3 @@ +import { handlers as httpHandlers } from './http'; + +export const handlers = [...httpHandlers]; diff --git a/projects/service-api/src/mocks/node.ts b/projects/service-api/src/mocks/node.ts new file mode 100644 index 0000000..e52fee0 --- /dev/null +++ b/projects/service-api/src/mocks/node.ts @@ -0,0 +1,4 @@ +import { setupServer } from 'msw/node'; +import { handlers } from './handlers'; + +export const server = setupServer(...handlers); diff --git a/projects/service-api/src/schema/builder.ts b/projects/service-api/src/schema/builder.ts index abd8c72..a196c4e 100755 --- a/projects/service-api/src/schema/builder.ts +++ b/projects/service-api/src/schema/builder.ts @@ -1,3 +1,26 @@ import SchemaBuilder from '@pothos/core'; +import { DateResolver, DateTimeResolver } from 'graphql-scalars'; +import { Context } from '../types'; -export const builder = new SchemaBuilder({}); +type SchemaConfig = { + Scalars: { + DateTime: { + Input: Date; + Output: Date; + }; + Date: { + Input: Date; + Output: Date; + }; + }; + Context: Context; +}; + +export const builder = new SchemaBuilder({}); + +builder.queryType({}); + +builder.mutationType({}); + +builder.addScalarType('Date', DateResolver); +builder.addScalarType('DateTime', DateTimeResolver); diff --git a/projects/service-api/src/schema/index.ts b/projects/service-api/src/schema/index.ts index 7e8768f..b6b1c75 100755 --- a/projects/service-api/src/schema/index.ts +++ b/projects/service-api/src/schema/index.ts @@ -1,7 +1,11 @@ import { builder } from './builder'; -builder.queryType({}); - export const schema = builder.toSchema(); -export * from './queries/hello'; +export * from './types/mutation-error'; +export * from './types/mutation-error-payload'; +export * from './types/user'; + +export * from './mutations/get-or-create-user'; + +export * from './queries/get-current-user'; diff --git a/projects/service-api/src/schema/mutations/get-or-create-user.test.ts b/projects/service-api/src/schema/mutations/get-or-create-user.test.ts new file mode 100644 index 0000000..f6aeb00 --- /dev/null +++ b/projects/service-api/src/schema/mutations/get-or-create-user.test.ts @@ -0,0 +1,43 @@ +import createJWKSMock from 'mock-jwks'; +import { drop } from '@mswjs/data'; +import { env } from '../../env'; +import { createMockGQLContext } from '../../test-utils'; +import { server } from '../../mocks/node'; +import { db } from '../../mocks/db'; +import { getOrCreateUser } from './get-or-create-user'; + +const jwks = createJWKSMock(`https://${env.AUTH0_DOMAIN}/`); + +test('it returns an existing user', async () => { + db.user.create({ + id: 'test_id', + auth0ID: 'auth0|test_id', + email: 'user@test.com', + emailVerified: true, + name: 'Test User', + firstName: 'Test', + }); + + server.use(jwks.handler); + + const accessToken = jwks.token({ + sub: 'test_id', + aud: env.API_IDENTIFIER, + iss: `https://${env.AUTH0_DOMAIN}/`, + }); + + const ctx = createMockGQLContext({ accessToken }); + const args = { input: { email: 'user@test.com' } }; + const result = await getOrCreateUser({}, args, ctx); + + expect(result).toMatchObject({ + id: 'test_id', + auth0ID: 'auth0|test_id', + email: 'user@test.com', + emailVerified: true, + name: 'Test User', + firstName: 'Test', + }); + + drop(db); +}); diff --git a/projects/service-api/src/schema/mutations/get-or-create-user.ts b/projects/service-api/src/schema/mutations/get-or-create-user.ts new file mode 100644 index 0000000..2c8fd58 --- /dev/null +++ b/projects/service-api/src/schema/mutations/get-or-create-user.ts @@ -0,0 +1,55 @@ +import { Context, StandardMutationPayload } from '../../types'; +import { getTokenFromContext } from '../../utils/get-token-from-context'; +import { builder } from '../builder'; +import { MutationErrorPayload } from '../types/mutation-error-payload'; +import { User } from '../types/user'; +import { createUnauthorizedError } from '../utils/create-unauthorized-error'; +import { createPayloadResolver } from '../utils/create-payload-resolver'; + +type Args = { + input: typeof GetOrCreateUserInput.$inferInput; +}; + +export async function getOrCreateUser( + _: object, + args: Args, + ctx: Context, +): Promise> { + const accessToken = getTokenFromContext(ctx); + + if (!accessToken) { + return { error: createUnauthorizedError() }; + } + + // eslint-disable-next-line no-useless-catch + try { + const user = await ctx.services.users.getOrCreateUser({ + email: args.input.email, + }); + + return user; + } catch (error: unknown) { + // TODO(#16): capture via Sentry + throw error; + } +} +const GetOrCreateUserInput = builder.inputType('GetOrCreateUserInput', { + fields: (t) => ({ + email: t.string({ required: true }), + }), +}); + +const GetOrCreateUserPayload = builder.unionType('GetOrCreateUserPayload', { + types: [User, MutationErrorPayload], + resolveType: createPayloadResolver(User), +}); + +builder.mutationField('getOrCreateUser', (t) => + t.field({ + type: GetOrCreateUserPayload, + args: { + input: t.arg({ type: GetOrCreateUserInput, required: true }), + }, + resolve: getOrCreateUser, + }), +); diff --git a/projects/service-api/src/schema/queries/get-current-user.test.ts b/projects/service-api/src/schema/queries/get-current-user.test.ts new file mode 100755 index 0000000..2774e37 --- /dev/null +++ b/projects/service-api/src/schema/queries/get-current-user.test.ts @@ -0,0 +1,42 @@ +import createJWKSMock from 'mock-jwks'; +import { env } from '../../env'; +import { createMockGQLContext } from '../../test-utils'; +import { getCurrentUser } from './get-current-user'; +import { server } from '../../mocks/node'; +import { db } from '../../mocks/db'; +import { drop } from '@mswjs/data'; + +const jwks = createJWKSMock(`https://${env.AUTH0_DOMAIN}/`); + +test('it returns the current user', async () => { + db.user.create({ + id: 'test_id', + auth0ID: 'auth0|test_id', + email: 'user@test.com', + emailVerified: true, + name: 'Test User', + firstName: 'Test', + }); + + server.use(jwks.handler); + + const accessToken = jwks.token({ + sub: 'test_id', + aud: env.API_IDENTIFIER, + iss: `https://${env.AUTH0_DOMAIN}/`, + }); + + const ctx = createMockGQLContext({ accessToken }); + const result = await getCurrentUser({}, {}, ctx); + + expect(result).toMatchObject({ + id: 'test_id', + auth0ID: 'auth0|test_id', + email: 'user@test.com', + emailVerified: true, + name: 'Test User', + firstName: 'Test', + }); + + drop(db); +}); diff --git a/projects/service-api/src/schema/queries/get-current-user.ts b/projects/service-api/src/schema/queries/get-current-user.ts new file mode 100755 index 0000000..e2cacbb --- /dev/null +++ b/projects/service-api/src/schema/queries/get-current-user.ts @@ -0,0 +1,36 @@ +import { Context } from '../../types'; +import { isAuthed } from '../../utils'; +import { builder } from '../builder'; +import { User } from '../types'; + +builder.queryField('getCurrentUser', (t) => + t.field({ + type: User, + resolve: getCurrentUser, + }), +); + +type Args = { + name?: string | null; +}; + +export async function getCurrentUser( + _: object, + args: Args, + ctx: Context, +): Promise { + if (!isAuthed(ctx)) { + // TODO(#16): capture via sentry + throw new Error('Unauthorized'); + } + + // eslint-disable-next-line no-useless-catch + try { + const user = await ctx.services.users.getCurrentUser({}); + + return user; + } catch (error: unknown) { + // TODO(#16): capture via Sentry + throw error; + } +} diff --git a/projects/service-api/src/schema/queries/hello.test.ts b/projects/service-api/src/schema/queries/hello.test.ts deleted file mode 100755 index f5b847f..0000000 --- a/projects/service-api/src/schema/queries/hello.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { resolve } from './hello'; - -test('it returns a greeting', () => { - const result = resolve({}, {}); - - expect(result).toBe('hello, world'); -}); - -test('it returns a specific greeting when provided a name', () => { - const result = resolve({}, { name: 'user' }); - - expect(result).toBe('hello, user'); -}); diff --git a/projects/service-api/src/schema/queries/hello.ts b/projects/service-api/src/schema/queries/hello.ts deleted file mode 100755 index 5b9d172..0000000 --- a/projects/service-api/src/schema/queries/hello.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { builder } from '../builder'; - -builder.queryFields((t) => ({ - hello: t.string({ - args: { - name: t.arg.string(), - }, - resolve, - }), -})); - -type Args = { - name?: string | null; -}; - -export function resolve(_: object, args: Args) { - return `hello, ${args.name || 'world'}`; -} diff --git a/projects/service-api/src/schema/types/index.ts b/projects/service-api/src/schema/types/index.ts new file mode 100644 index 0000000..47289c0 --- /dev/null +++ b/projects/service-api/src/schema/types/index.ts @@ -0,0 +1,3 @@ +export { MutationError } from './mutation-error'; +export { MutationErrorPayload } from './mutation-error-payload'; +export { User } from './user'; diff --git a/projects/service-api/src/schema/types/mutation-error-payload.ts b/projects/service-api/src/schema/types/mutation-error-payload.ts new file mode 100644 index 0000000..d44cec7 --- /dev/null +++ b/projects/service-api/src/schema/types/mutation-error-payload.ts @@ -0,0 +1,19 @@ +import { builder } from '../builder'; +import { MutationError } from './mutation-error'; + +export type MutationErrorPayloadData = { + error: typeof MutationError.$inferType; +}; + +export const MutationErrorPayload = builder.objectRef( + 'MutationErrorPayload', +); + +MutationErrorPayload.implement({ + fields: (t) => ({ + error: t.field({ + type: MutationError, + resolve: (source) => source.error, + }), + }), +}); diff --git a/projects/service-api/src/schema/types/mutation-error.ts b/projects/service-api/src/schema/types/mutation-error.ts new file mode 100644 index 0000000..38cc337 --- /dev/null +++ b/projects/service-api/src/schema/types/mutation-error.ts @@ -0,0 +1,16 @@ +import { builder } from '../builder'; + +type MutationErrorData = { + title: string; + message: string; +}; + +export const MutationError = + builder.objectRef('MutationError'); + +MutationError.implement({ + fields: (t) => ({ + title: t.exposeString('title'), + message: t.exposeString('message'), + }), +}); diff --git a/projects/service-api/src/schema/types/user.ts b/projects/service-api/src/schema/types/user.ts new file mode 100644 index 0000000..8266f1f --- /dev/null +++ b/projects/service-api/src/schema/types/user.ts @@ -0,0 +1,15 @@ +import { users } from '@campaign/postgres-schema'; +import { builder } from '../builder'; + +export const User = builder.objectRef('User'); + +User.implement({ + fields: (t) => ({ + id: t.exposeID('id'), + email: t.exposeString('email'), + emailVerified: t.exposeBoolean('emailVerified'), + name: t.exposeString('name'), + firstName: t.exposeString('firstName', { nullable: true }), + createdAt: t.expose('createdAt', { type: 'DateTime' }), + }), +}); diff --git a/projects/service-api/src/schema/utils/create-payload-resolver.ts b/projects/service-api/src/schema/utils/create-payload-resolver.ts new file mode 100644 index 0000000..5db3464 --- /dev/null +++ b/projects/service-api/src/schema/utils/create-payload-resolver.ts @@ -0,0 +1,13 @@ +import { MutationErrorPayload } from '../types/mutation-error-payload'; + +export function createPayloadResolver( + type: T, +): (value: object) => T | typeof MutationErrorPayload { + return (value) => { + if ('error' in value) { + return MutationErrorPayload; + } + + return type; + }; +} diff --git a/projects/service-api/src/schema/utils/create-unauthorized-error.ts b/projects/service-api/src/schema/utils/create-unauthorized-error.ts new file mode 100644 index 0000000..8175483 --- /dev/null +++ b/projects/service-api/src/schema/utils/create-unauthorized-error.ts @@ -0,0 +1,8 @@ +import { MutationError } from '../types/mutation-error'; + +export function createUnauthorizedError(): typeof MutationError.$inferType { + return { + title: 'Unauthorized', + message: 'You must be logged in to perform this action', + }; +} diff --git a/projects/service-api/src/services/index.ts b/projects/service-api/src/services/index.ts new file mode 100644 index 0000000..adb8056 --- /dev/null +++ b/projects/service-api/src/services/index.ts @@ -0,0 +1 @@ +export { createUserService } from './user-service/create-user-service'; diff --git a/projects/service-api/src/services/user-service/create-user-service.ts b/projects/service-api/src/services/user-service/create-user-service.ts new file mode 100644 index 0000000..526c8c8 --- /dev/null +++ b/projects/service-api/src/services/user-service/create-user-service.ts @@ -0,0 +1,18 @@ +import { createServiceContext } from '../utils/create-service-context'; +import { CreateServiceContextConfig } from '../utils/types'; +import { getCurrentUser } from './get-current-user'; +import { getOrCreateUser } from './get-or-create-user'; +import { GetCurrentUserArgs, GetOrCreateUserArgs, UserService } from './types'; + +type UserServiceConfig = CreateServiceContextConfig; + +export function createUserService(config: UserServiceConfig): UserService { + const ctx = createServiceContext(config); + + return { + getCurrentUser: async (args: GetCurrentUserArgs) => + getCurrentUser(args, ctx), + getOrCreateUser: async (args: GetOrCreateUserArgs) => + getOrCreateUser(args, ctx), + }; +} diff --git a/projects/service-api/src/services/user-service/get-current-user.test.ts b/projects/service-api/src/services/user-service/get-current-user.test.ts new file mode 100644 index 0000000..394c9e7 --- /dev/null +++ b/projects/service-api/src/services/user-service/get-current-user.test.ts @@ -0,0 +1,43 @@ +import createJWKSMock from 'mock-jwks'; +import { drop } from '@mswjs/data'; +import { env } from '../../env'; +import { server } from '../../mocks/node'; +import { db } from '../../mocks/db'; +import { createServiceContext } from '../utils/create-service-context'; +import { getCurrentUser } from './get-current-user'; + +const jwks = createJWKSMock(`https://${env.AUTH0_DOMAIN}/`); + +test('it returns the current user', async () => { + db.user.create({ + id: 'test_id', + auth0ID: 'auth0|test_id', + email: 'user@test.com', + emailVerified: true, + name: 'Test User', + firstName: 'Test', + }); + + server.use(jwks.handler); + + const accessToken = jwks.token({ + sub: 'test_id', + aud: env.API_IDENTIFIER, + iss: `https://${env.AUTH0_DOMAIN}/`, + }); + + const ctx = createServiceContext({ apiURL: env.USERS_API_URL, accessToken }); + const args = { email: 'user@test.com' }; + const result = await getCurrentUser(args, ctx); + + expect(result).toMatchObject({ + id: 'test_id', + auth0ID: 'auth0|test_id', + email: 'user@test.com', + emailVerified: true, + name: 'Test User', + firstName: 'Test', + }); + + drop(db); +}); diff --git a/projects/service-api/src/services/user-service/get-current-user.ts b/projects/service-api/src/services/user-service/get-current-user.ts new file mode 100644 index 0000000..4736dd2 --- /dev/null +++ b/projects/service-api/src/services/user-service/get-current-user.ts @@ -0,0 +1,27 @@ +import { users } from '@campaign/postgres-schema'; +import { + GetCurrentUserArgs, + RawUserData, + ServiceResponse, + userServiceContext, +} from './types'; +import { marshal } from './marshal'; + +type GetCurrentUserResponse = ServiceResponse; + +export async function getCurrentUser( + args: GetCurrentUserArgs, + ctx: userServiceContext, +): Promise { + const response = await ctx.client.get( + 'get-current-user', + { resolveBodyOnly: true }, + ); + + if (!response.success) { + // TODO(#16): capture via Sentry + throw new Error('An unknown error occurred'); + } + + return marshal(response.data); +} diff --git a/projects/service-api/src/services/user-service/get-or-create-user.test.ts b/projects/service-api/src/services/user-service/get-or-create-user.test.ts new file mode 100644 index 0000000..4dcaf1b --- /dev/null +++ b/projects/service-api/src/services/user-service/get-or-create-user.test.ts @@ -0,0 +1,43 @@ +import createJWKSMock from 'mock-jwks'; +import { drop } from '@mswjs/data'; +import { env } from '../../env'; +import { server } from '../../mocks/node'; +import { db } from '../../mocks/db'; +import { getOrCreateUser } from './get-or-create-user'; +import { createServiceContext } from '../utils/create-service-context'; + +const jwks = createJWKSMock(`https://${env.AUTH0_DOMAIN}/`); + +test('it returns an existing user', async () => { + db.user.create({ + id: 'test_id', + auth0ID: 'auth0|test_id', + email: 'user@test.com', + emailVerified: true, + name: 'Test User', + firstName: 'Test', + }); + + server.use(jwks.handler); + + const accessToken = jwks.token({ + sub: 'test_id', + aud: env.API_IDENTIFIER, + iss: `https://${env.AUTH0_DOMAIN}/`, + }); + + const ctx = createServiceContext({ apiURL: env.USERS_API_URL, accessToken }); + const args = { email: 'user@test.com' }; + const result = await getOrCreateUser(args, ctx); + + expect(result).toMatchObject({ + id: 'test_id', + auth0ID: 'auth0|test_id', + email: 'user@test.com', + emailVerified: true, + name: 'Test User', + firstName: 'Test', + }); + + drop(db); +}); diff --git a/projects/service-api/src/services/user-service/get-or-create-user.ts b/projects/service-api/src/services/user-service/get-or-create-user.ts new file mode 100644 index 0000000..dff76f3 --- /dev/null +++ b/projects/service-api/src/services/user-service/get-or-create-user.ts @@ -0,0 +1,27 @@ +import { users } from '@campaign/postgres-schema'; +import { + GetOrCreateUserArgs, + RawUserData, + ServiceResponse, + userServiceContext, +} from './types'; +import { marshal } from './marshal'; + +type GetOrCreateUserResponse = ServiceResponse; + +export async function getOrCreateUser( + args: GetOrCreateUserArgs, + ctx: userServiceContext, +): Promise { + const response = await ctx.client.post( + 'get-or-create-user', + { body: JSON.stringify(args), resolveBodyOnly: true }, + ); + + if (!response.success) { + // TODO(#16): capture via Sentry + throw new Error('An unknown error occurred'); + } + + return marshal(response.data); +} diff --git a/projects/service-api/src/services/user-service/marshal.ts b/projects/service-api/src/services/user-service/marshal.ts new file mode 100644 index 0000000..50b45bc --- /dev/null +++ b/projects/service-api/src/services/user-service/marshal.ts @@ -0,0 +1,12 @@ +import { users } from '@campaign/postgres-schema'; +import { RawUserData } from './types'; + +type UserData = typeof users.$inferSelect; + +export function marshal(rawUser: RawUserData): UserData { + return { + ...rawUser, + firstName: rawUser.firstName ?? null, + createdAt: new Date(rawUser.createdAt), + }; +} diff --git a/projects/service-api/src/services/user-service/types.ts b/projects/service-api/src/services/user-service/types.ts new file mode 100644 index 0000000..5bcb355 --- /dev/null +++ b/projects/service-api/src/services/user-service/types.ts @@ -0,0 +1,46 @@ +import { users } from '@campaign/postgres-schema'; +import { ServiceContext } from '../utils/types'; + +export type ServiceResponse = + | ServiceSuccessResponse + | ServiceErrorResponse; + +export type ServiceSuccessResponse = { + success: true; + data: T; +}; + +export type ServiceErrorResponse = { + success: false; + reason: string; +}; + +export type RawUserData = { + id: string; + auth0ID: string; + email: string; + emailVerified: boolean; + name: string; + firstName?: string; + createdAt: string; +}; + +export type userServiceContext = ServiceContext; + +export type UserService = { + getCurrentUser: ( + args: GetCurrentUserArgs, + ) => Promise; + + getOrCreateUser: ( + args: GetOrCreateUserArgs, + ) => Promise; +}; + +export type GetCurrentUserArgs = { + // +}; + +export type GetOrCreateUserArgs = { + email: string; +}; diff --git a/projects/service-api/src/services/utils/create-service-context.ts b/projects/service-api/src/services/utils/create-service-context.ts new file mode 100644 index 0000000..4aeba8d --- /dev/null +++ b/projects/service-api/src/services/utils/create-service-context.ts @@ -0,0 +1,20 @@ +import got from 'got'; +import { CreateServiceContextConfig, ServiceContext } from './types'; + +export function createServiceContext( + config: CreateServiceContextConfig, +): ServiceContext { + const client = got.extend({ + prefixUrl: config.apiURL, + responseType: 'json', + headers: { + ...(config.accessToken + ? { Authorization: `Bearer ${config.accessToken}` } + : {}), + }, + }); + + return { + client, + }; +} diff --git a/projects/service-api/src/services/utils/index.ts b/projects/service-api/src/services/utils/index.ts new file mode 100644 index 0000000..a66c1d8 --- /dev/null +++ b/projects/service-api/src/services/utils/index.ts @@ -0,0 +1 @@ +export { createServiceContext } from './create-service-context'; diff --git a/projects/service-api/src/services/utils/types.ts b/projects/service-api/src/services/utils/types.ts new file mode 100644 index 0000000..f631853 --- /dev/null +++ b/projects/service-api/src/services/utils/types.ts @@ -0,0 +1,10 @@ +import { Got } from 'got'; + +export type ServiceContext = { + client: Got; +}; + +export type CreateServiceContextConfig = { + apiURL: string; + accessToken: string | null; +}; diff --git a/projects/service-api/src/test-utils/create-mock-gql-context.ts b/projects/service-api/src/test-utils/create-mock-gql-context.ts new file mode 100644 index 0000000..8142602 --- /dev/null +++ b/projects/service-api/src/test-utils/create-mock-gql-context.ts @@ -0,0 +1,23 @@ +import { Context } from '../types'; +import { createUserService } from '../services'; +import { env } from '../env'; + +type MockContextConfig = { + accessToken: string; +}; + +export function createMockGQLContext(config: MockContextConfig): Context { + const request = new Request('https://test.com/'); + + request.headers.set('authorization', `Bearer ${config.accessToken}`); + + return { + request, + services: { + users: createUserService({ + apiURL: env.USERS_API_URL, + accessToken: config.accessToken, + }), + }, + }; +} diff --git a/projects/service-api/src/test-utils/create-mock-services.ts b/projects/service-api/src/test-utils/create-mock-services.ts new file mode 100644 index 0000000..42da95a --- /dev/null +++ b/projects/service-api/src/test-utils/create-mock-services.ts @@ -0,0 +1,10 @@ +import { Services } from '../types'; + +export function createMockServices(): Services { + return { + users: { + getCurrentUser: vi.fn(), + getOrCreateUser: vi.fn(), + }, + }; +} diff --git a/projects/service-api/src/test-utils/index.ts b/projects/service-api/src/test-utils/index.ts new file mode 100644 index 0000000..993f51f --- /dev/null +++ b/projects/service-api/src/test-utils/index.ts @@ -0,0 +1,2 @@ +export { createMockGQLContext } from './create-mock-gql-context'; +export { createMockServices } from './create-mock-services'; diff --git a/projects/service-api/src/types.ts b/projects/service-api/src/types.ts index 3e536d8..2d9464d 100755 --- a/projects/service-api/src/types.ts +++ b/projects/service-api/src/types.ts @@ -1,7 +1,31 @@ +import { Get } from 'type-fest'; +import { MutationErrorPayload } from './schema/types/mutation-error-payload'; +import { UserService } from './services/user-service/types'; + export type Env = { - POSTGRES_URL: string; LOGGING: 'debug' | 'info' | 'warn' | 'error'; NODE_ENV: 'development' | 'test' | 'production'; + + API_IDENTIFIER: string; + AUTH0_DOMAIN: string; + + // service urls + USERS_API_URL: string; + + // utils isProduction: boolean; isDevelopment: boolean; }; + +export type Context = { + request: Request; + services: Services; +}; + +export type Services = { + users: UserService; +}; + +export type StandardMutationPayload = + | Get + | typeof MutationErrorPayload.$inferType; diff --git a/projects/service-api/src/utils/get-token-from-context.test.ts b/projects/service-api/src/utils/get-token-from-context.test.ts new file mode 100644 index 0000000..e53dff1 --- /dev/null +++ b/projects/service-api/src/utils/get-token-from-context.test.ts @@ -0,0 +1,24 @@ +import { createMockServices } from '../test-utils/create-mock-services'; +import { getTokenFromContext } from './get-token-from-context'; + +const services = createMockServices(); + +test('it extracts the token from the context', () => { + const request = new Request('https://test.com/', { + headers: { + authorization: 'Bearer token', + }, + }); + + const token = getTokenFromContext({ request, services }); + + expect(token).toEqual('token'); +}); + +test('it returns null if the token is not present', () => { + const request = new Request('https://test.com/', {}); + + const token = getTokenFromContext({ request, services }); + + expect(token).toEqual(null); +}); diff --git a/projects/service-api/src/utils/get-token-from-context.ts b/projects/service-api/src/utils/get-token-from-context.ts new file mode 100644 index 0000000..f92be1b --- /dev/null +++ b/projects/service-api/src/utils/get-token-from-context.ts @@ -0,0 +1,14 @@ +import { getTokenFromHeader } from '@campaign/service-utils'; +import { Context } from '../types'; + +export function getTokenFromContext(ctx: Context): string | null { + const header = ctx.request.headers.get('authorization'); + + if (!header) { + return null; + } + + const token = getTokenFromHeader(header); + + return token; +} diff --git a/projects/service-api/src/utils/index.ts b/projects/service-api/src/utils/index.ts new file mode 100644 index 0000000..0e646cd --- /dev/null +++ b/projects/service-api/src/utils/index.ts @@ -0,0 +1,2 @@ +export { getTokenFromContext } from './get-token-from-context'; +export { isAuthed } from './is-authed'; diff --git a/projects/service-api/src/utils/is-authed.test.ts b/projects/service-api/src/utils/is-authed.test.ts new file mode 100644 index 0000000..bb3fe4a --- /dev/null +++ b/projects/service-api/src/utils/is-authed.test.ts @@ -0,0 +1,24 @@ +import { createMockServices } from '../test-utils/create-mock-services'; +import { isAuthed } from './is-authed'; + +const services = createMockServices(); + +test('it returns true if an access token is found', () => { + const request = new Request('https://test.com/', { + headers: { + authorization: 'Bearer token', + }, + }); + + const authed = isAuthed({ request, services }); + + expect(authed).toBeTrue(); +}); + +test('it returns false if an access token isnt found', () => { + const request = new Request('https://test.com/', {}); + + const authed = isAuthed({ request, services }); + + expect(authed).toBeFalse(); +}); diff --git a/projects/service-api/src/utils/is-authed.ts b/projects/service-api/src/utils/is-authed.ts new file mode 100644 index 0000000..582426a --- /dev/null +++ b/projects/service-api/src/utils/is-authed.ts @@ -0,0 +1,6 @@ +import { Context } from '../types'; +import { getTokenFromContext } from './get-token-from-context'; + +export function isAuthed(ctx: Context): boolean { + return Boolean(getTokenFromContext(ctx)); +} diff --git a/projects/service-api/tsconfig.app.json b/projects/service-api/tsconfig.app.json index 85be90f..28a0c11 100644 --- a/projects/service-api/tsconfig.app.json +++ b/projects/service-api/tsconfig.app.json @@ -4,6 +4,6 @@ "module": "ESNext", "types": ["node"] }, - "exclude": ["src/**/*.test.ts"], + "exclude": ["src/test-utils/**/*.ts", "src/**/*.test.ts"], "include": ["src/**/*.ts"] } diff --git a/projects/service-api/tsconfig.json b/projects/service-api/tsconfig.json index 573aaf9..e068a1c 100644 --- a/projects/service-api/tsconfig.json +++ b/projects/service-api/tsconfig.json @@ -2,6 +2,9 @@ "extends": "../../tsconfig.base.json", "files": [], "include": [], + "compilerOptions": { + "esModuleInterop": true + }, "references": [ { "path": "./tsconfig.app.json" @@ -9,8 +12,5 @@ { "path": "./tsconfig.test.json" } - ], - "compilerOptions": { - "esModuleInterop": true - } + ] } diff --git a/projects/service-api/tsconfig.test.json b/projects/service-api/tsconfig.test.json index 74adafa..9a79bab 100644 --- a/projects/service-api/tsconfig.test.json +++ b/projects/service-api/tsconfig.test.json @@ -5,6 +5,7 @@ "types": ["node", "vitest/globals"] }, "include": [ + "src/test-utils/**/*.ts", "src/**/*.test.ts", "src/**/*.d.ts", "vite.config.ts", diff --git a/projects/service-api/vitest.config.ts b/projects/service-api/vitest.config.ts index 4ce42e4..ab76497 100755 --- a/projects/service-api/vitest.config.ts +++ b/projects/service-api/vitest.config.ts @@ -1,7 +1,9 @@ import { loadEnv } from 'vite'; import { defineConfig } from 'vitest/config'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; export default defineConfig({ + plugins: [nxViteTsPaths()], test: { globals: true, environment: 'node', diff --git a/projects/service-api/vitest.setup.ts b/projects/service-api/vitest.setup.ts index 107b565..0802c3c 100644 --- a/projects/service-api/vitest.setup.ts +++ b/projects/service-api/vitest.setup.ts @@ -1,3 +1,14 @@ import * as matchers from 'jest-extended'; +import { server } from './src/mocks/node'; expect.extend(matchers); + +beforeAll(() => server.listen()); + +afterEach(() => server.resetHandlers()); + +afterAll(() => server.close()); + +server.events.on('request:start', ({ request }) => { + console.log('Outgoing:', request.method, request.url); +}); diff --git a/projects/service-user/.env.development b/projects/service-user/.env.development index 3e163ec..8a87476 100644 --- a/projects/service-user/.env.development +++ b/projects/service-user/.env.development @@ -1,4 +1,4 @@ NODE_ENV=development -POSTGRES_URL="postgresql://admin:password@localhost:5432/campaign" -AUTH0_DOMAIN="" -API_IDENTIFIER="" \ No newline at end of file +POSTGRES_URL="postgresql://admin:password@localhost:5433/campaign" +AUTH0_DOMAIN="chrononomicon.us.auth0.com" +API_IDENTIFIER="http://localhost:3000/" \ No newline at end of file diff --git a/projects/service-user/src/handlers/get-current-user.test.ts b/projects/service-user/src/handlers/get-current-user.test.ts new file mode 100644 index 0000000..9e99bed --- /dev/null +++ b/projects/service-user/src/handlers/get-current-user.test.ts @@ -0,0 +1,85 @@ +import { Hono } from 'hono'; +import createJWKSMock from 'mock-jwks'; +import * as schema from '@campaign/postgres-schema'; +import { createAuthMiddleware } from '@campaign/service-utils'; +import { PostgresTestUtils } from '@campaign/service-test-utils'; +import { env } from '../env'; +import { getCurrentUser } from './get-current-user'; + +// setup jwks mock +const jwks = createJWKSMock(`https://${env.AUTH0_DOMAIN}/`); + +const TEST_TOKEN_PAYLOAD = { + sub: 'auth0|test_id', + iss: `https://${env.AUTH0_DOMAIN}/`, + name: 'Test User', + email: 'user@test.com', + email_verified: 'true', +}; + +const authMiddleware = createAuthMiddleware({ + tokenVerifierConfig: { + audience: env.API_IDENTIFIER, + issuer: `https://${env.AUTH0_DOMAIN}/`, + }, +}); + +async function setupTest() { + const { db, teardown } = await PostgresTestUtils.createTestDB(); + const app = new Hono(); + + jwks.start(); + + app.get('/get-current-user', authMiddleware, async (ctx) => + getCurrentUser(ctx, db), + ); + + const token = jwks.token(TEST_TOKEN_PAYLOAD); + + return { app, db, token, teardown }; +} + +afterEach(() => { + jwks.stop(); + vi.restoreAllMocks(); +}); + +test('it returns the current user', async () => { + const { app, db, token, teardown } = await setupTest(); + + const createdAt = new Date(); + + await db.insert(schema.users).values({ + id: 'test_id', + auth0ID: 'auth0|test_id', + email: 'user@test.com', + emailVerified: true, + name: 'Test User', + firstName: 'Test', + createdAt, + }); + + const req = new Request('http://localhost/get-current-user', { + headers: { + authorization: `Bearer ${token}`, + }, + }); + + const res = await app.request(req); + + expect(res.status).toBe(200); + expect(await res.json()).toMatchObject({ + success: true, + data: { + id: 'test_id', + auth0ID: 'auth0|test_id', + email: 'user@test.com', + emailVerified: true, + name: 'Test User', + firstName: 'Test', + createdAt: createdAt.toISOString(), + }, + }); + + await teardown(); +}); diff --git a/projects/service-user/src/handlers/get-current-user.ts b/projects/service-user/src/handlers/get-current-user.ts new file mode 100644 index 0000000..180ea64 --- /dev/null +++ b/projects/service-user/src/handlers/get-current-user.ts @@ -0,0 +1,27 @@ +import { eq } from 'drizzle-orm'; +import { Context } from 'hono'; +import * as schema from '@campaign/postgres-schema'; +import { getUserIDFromContext } from '@campaign/service-utils'; +import { PostgresJsDatabase } from 'drizzle-orm/postgres-js'; + +export async function getCurrentUser( + ctx: Context, + db: PostgresJsDatabase, +) { + try { + const userID = getUserIDFromContext(ctx); + + const user = await db.query.users.findFirst({ + where: eq(schema.users.auth0ID, userID), + }); + + return ctx.json({ success: true, data: user }); + } catch (error: unknown) { + // TODO(#16): capture via Sentry + if (error instanceof Error) { + return ctx.json({ success: false, error: 'An unknown error occurred' }); + } + + throw error; + } +} diff --git a/projects/service-user/src/handlers/get-or-create-user.test.ts b/projects/service-user/src/handlers/get-or-create-user.test.ts index d7a5871..c52845e 100644 --- a/projects/service-user/src/handlers/get-or-create-user.test.ts +++ b/projects/service-user/src/handlers/get-or-create-user.test.ts @@ -1,10 +1,10 @@ import { Hono } from 'hono'; import createJWKSMock from 'mock-jwks'; import * as schema from '@campaign/postgres-schema'; -import { env } from '../env'; import { createAuthMiddleware } from '@campaign/service-utils'; +import { PostgresTestUtils } from '@campaign/service-test-utils'; +import { env } from '../env'; import { getOrCreateUser } from './get-or-create-user'; -import { PostgresTestUtils } from '../../../lib-service-test-utils/src'; // mock auth0 user info client const { getUserInfoMock } = vi.hoisted(() => ({ getUserInfoMock: vi.fn() })); @@ -45,7 +45,9 @@ async function setupTest() { const app = new Hono(); jwks.start(); - app.get('/test', authMiddleware, async (ctx) => getOrCreateUser(ctx, db)); + app.post('/get-or-create-user', authMiddleware, async (ctx) => + getOrCreateUser(ctx, db), + ); const token = jwks.token(TEST_TOKEN_PAYLOAD); @@ -62,15 +64,21 @@ test('it creates and returns a user', async () => { getUserInfoMock.mockImplementation(() => ({ data: { + sub: 'auth0|test_id', email: 'user@test.com', email_verified: true, name: 'Test User', + given_name: 'Test', }, })); - const req = new Request('http://localhost/test'); - - req.headers.set('Authorization', `Bearer ${token}`); + const req = new Request('http://localhost/get-or-create-user', { + method: 'POST', + body: JSON.stringify({ email: 'user@test.com' }), + headers: { + authorization: `Bearer ${token}`, + }, + }); const res = await app.request(req); @@ -78,10 +86,13 @@ test('it creates and returns a user', async () => { expect(await res.json()).toMatchObject({ success: true, data: { - id: 'test_id', + id: expect.any(String), + auth0ID: 'auth0|test_id', name: 'Test User', + firstName: 'Test', email: 'user@test.com', emailVerified: true, + createdAt: expect.any(String), }, }); @@ -93,14 +104,20 @@ test('it returns an existing user', async () => { await db.insert(schema.users).values({ id: 'test_id', + auth0ID: 'auth0|test_id', name: 'Test User', + firstName: 'Test', email: 'user@test.com', emailVerified: true, }); - const req = new Request('http://localhost/test'); - - req.headers.set('Authorization', `Bearer ${token}`); + const req = new Request('http://localhost/get-or-create-user', { + method: 'POST', + body: JSON.stringify({ email: 'user@test.com' }), + headers: { + authorization: `Bearer ${token}`, + }, + }); const res = await app.request(req); @@ -109,9 +126,12 @@ test('it returns an existing user', async () => { success: true, data: { id: 'test_id', + auth0ID: 'auth0|test_id', name: 'Test User', + firstName: 'Test', email: 'user@test.com', emailVerified: true, + createdAt: expect.any(String), }, }); diff --git a/projects/service-user/src/handlers/get-or-create-user.ts b/projects/service-user/src/handlers/get-or-create-user.ts index e21c032..f89e5a9 100644 --- a/projects/service-user/src/handlers/get-or-create-user.ts +++ b/projects/service-user/src/handlers/get-or-create-user.ts @@ -1,39 +1,53 @@ import { eq } from 'drizzle-orm'; import { Context } from 'hono'; +import { createId } from '@paralleldrive/cuid2'; import * as schema from '@campaign/postgres-schema'; -import { - getTokenFromContext, - getUserFromContext, -} from '@campaign/service-utils'; +import { getTokenFromContext } from '@campaign/service-utils'; import { PostgresJsDatabase } from 'drizzle-orm/postgres-js'; import * as auth0 from '../auth0'; +type RequestBody = { + email: string; +}; + export async function getOrCreateUser( ctx: Context, db: PostgresJsDatabase, ) { - const user = getUserFromContext(ctx); + try { + const { email } = await ctx.req.json(); - const existingUser = await db.query.users.findFirst({ - where: eq(schema.users.id, user.id), - }); + const existingUser = await db.query.users.findFirst({ + where: eq(schema.users.email, email), + }); - if (existingUser) { - return ctx.json({ success: true, data: existingUser }); - } + if (existingUser) { + return ctx.json({ success: true, data: existingUser }); + } - const accessToken = getTokenFromContext(ctx); - const auth0UserInfo = await auth0.userInfoClient.getUserInfo(accessToken); + const accessToken = getTokenFromContext(ctx); + const auth0UserInfo = await auth0.userInfoClient.getUserInfo(accessToken); - const newUser = { - id: user.id, - email: auth0UserInfo.data.email, - emailVerified: auth0UserInfo.data.email_verified, - name: auth0UserInfo.data.name, - createdAt: new Date(), - }; + const newUser = { + id: createId(), + auth0ID: auth0UserInfo.data.sub, + email: auth0UserInfo.data.email, + emailVerified: auth0UserInfo.data.email_verified, + name: auth0UserInfo.data.name, + firstName: auth0UserInfo.data.given_name, + createdAt: new Date(), + }; - await db.insert(schema.users).values(newUser); + await db.insert(schema.users).values(newUser); - return ctx.json({ success: true, data: newUser }); + return ctx.json({ success: true, data: newUser }); + } catch (error: unknown) { + console.log(error); + // TODO(#16): capture via Sentry + if (error instanceof Error) { + return ctx.json({ success: false, error: 'An unknown error occurred' }); + } + + throw error; + } } diff --git a/projects/service-user/src/handlers/index.ts b/projects/service-user/src/handlers/index.ts index b8950d5..913ac6f 100644 --- a/projects/service-user/src/handlers/index.ts +++ b/projects/service-user/src/handlers/index.ts @@ -1 +1,2 @@ +export { getCurrentUser } from './get-current-user'; export { getOrCreateUser } from './get-or-create-user'; diff --git a/projects/service-user/src/main.ts b/projects/service-user/src/main.ts index d596460..494603e 100644 --- a/projects/service-user/src/main.ts +++ b/projects/service-user/src/main.ts @@ -1,6 +1,7 @@ import { serve } from '@hono/node-server'; import { app } from './app'; +import './routes'; -serve(app); +serve({ fetch: app.fetch, port: 3001 }); -console.log('⚡️ Serving User API @ http://localhost:3000'); +console.log('⚡️ Serving User API @ http://localhost:3001'); diff --git a/projects/service-user/src/routes.ts b/projects/service-user/src/routes.ts index e4c2906..2157884 100644 --- a/projects/service-user/src/routes.ts +++ b/projects/service-user/src/routes.ts @@ -1,8 +1,12 @@ import { app } from './app'; -import { getOrCreateUser } from './handlers'; +import { getCurrentUser, getOrCreateUser } from './handlers'; import { db } from './db'; import { authMiddleware } from './middleware'; -app.get('/get-or-create-user', authMiddleware, async (ctx) => +app.post('/get-current-user', authMiddleware, async (ctx) => + getCurrentUser(ctx, db), +); + +app.post('/get-or-create-user', authMiddleware, async (ctx) => getOrCreateUser(ctx, db), ); diff --git a/projects/service-user/src/type-defs/hono-context.d.ts b/projects/service-user/src/type-defs/hono-context.d.ts index 876b9a6..a6a93a3 100644 --- a/projects/service-user/src/type-defs/hono-context.d.ts +++ b/projects/service-user/src/type-defs/hono-context.d.ts @@ -3,9 +3,6 @@ import 'hono'; // TODO: clean up this type type JWTPayload = { sub: string; - email: string; - email_verified: string; - name: string; }; declare module 'hono' { diff --git a/schema.graphql b/schema.graphql index 11fede5..e807ef7 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1,3 +1,41 @@ +""" +A date string, such as 2007-12-03, compliant with the `full-date` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. +""" +scalar Date + +""" +A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. +""" +scalar DateTime + +input GetOrCreateUserInput { + email: String! +} + +union GetOrCreateUserPayload = MutationErrorPayload | User + +type Mutation { + getOrCreateUser(input: GetOrCreateUserInput!): GetOrCreateUserPayload! +} + +type MutationError { + message: String! + title: String! +} + +type MutationErrorPayload { + error: MutationError! +} + type Query { - hello(name: String): String! + getCurrentUser: User! +} + +type User { + createdAt: DateTime! + email: String! + emailVerified: Boolean! + firstName: String + id: ID! + name: String! } diff --git a/tsconfig.base.json b/tsconfig.base.json index 7179aff..6f25a70 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -4,7 +4,7 @@ "rootDir": ".", "sourceMap": true, "declaration": false, - "moduleResolution": "Node", + "moduleResolution": "Bundler", "emitDecoratorMetadata": true, "experimentalDecorators": true, "importHelpers": true, diff --git a/yarn.lock b/yarn.lock index a7fcc6a..c9ca7a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -742,7 +742,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.20.0, @babel/plugin-syntax-typescript@npm:^7.24.1, @babel/plugin-syntax-typescript@npm:^7.3.3, @babel/plugin-syntax-typescript@npm:^7.7.2": +"@babel/plugin-syntax-typescript@npm:^7.20.0, @babel/plugin-syntax-typescript@npm:^7.23.3, @babel/plugin-syntax-typescript@npm:^7.24.1, @babel/plugin-syntax-typescript@npm:^7.3.3, @babel/plugin-syntax-typescript@npm:^7.7.2": version: 7.24.1 resolution: "@babel/plugin-syntax-typescript@npm:7.24.1" dependencies: @@ -1610,7 +1610,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.2": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.2": version: 7.24.4 resolution: "@babel/runtime@npm:7.24.4" dependencies: @@ -1705,6 +1705,7 @@ __metadata: "@graphql-tools/executor-http": "npm:1.0.9" "@graphql-typed-document-node/core": "npm:3.2.0" "@hono/node-server": "npm:1.10.0" + "@mswjs/data": "npm:0.16.1" "@nx/devkit": "npm:18.3.3" "@nx/esbuild": "npm:18.3.3" "@nx/eslint": "npm:18.3.3" @@ -1715,6 +1716,7 @@ __metadata: "@nx/vite": "npm:18.3.3" "@nx/web": "npm:18.3.3" "@nx/workspace": "npm:18.3.3" + "@paralleldrive/cuid2": "npm:2.2.2" "@parcel/watcher": "npm:2.4.1" "@playwright/test": "npm:1.43.0" "@pothos/core": "npm:3.41.1" @@ -1722,28 +1724,33 @@ __metadata: "@remix-run/node": "npm:2.9.1" "@remix-run/react": "npm:2.9.1" "@remix-run/serve": "npm:2.9.1" + "@remix-run/server-runtime": "npm:2.9.1" "@remix-run/testing": "npm:2.9.1" "@swc-node/register": "npm:1.9.0" "@swc/cli": "npm:0.3.12" "@swc/core": "npm:1.4.13" "@swc/helpers": "npm:0.5.8" "@testcontainers/postgresql": "npm:10.9.0" + "@testing-library/dom": "npm:10.0.0" "@testing-library/jest-dom": "npm:6.4.2" "@testing-library/react": "npm:14.3.0" + "@testing-library/user-event": "npm:14.5.2" "@types/jsonwebtoken": "npm:9.0.6" "@types/node": "npm:20.12.7" "@types/react": "npm:18.2.75" "@types/react-dom": "npm:18.2.24" "@types/react-is": "npm:18.2.4" - "@types/styled-components": "npm:5.1.34" "@typescript-eslint/eslint-plugin": "npm:7.6.0" "@typescript-eslint/parser": "npm:7.6.0" "@typescript-eslint/utils": "npm:7.7.1" + "@vanilla-extract/css": "npm:1.14.2" + "@vanilla-extract/sprinkles": "npm:1.6.1" + "@vanilla-extract/vite-plugin": "npm:4.0.7" "@vitejs/plugin-react": "npm:4.2.1" - "@vitest/coverage-v8": "npm:1.5.1" - "@vitest/ui": "npm:1.5.1" + "@vitest/coverage-v8": "npm:1.5.2" + "@vitest/expect": "npm:1.5.2" + "@vitest/ui": "npm:1.5.2" auth0: "npm:4.3.1" - cuid: "npm:3.0.0" drizzle-kit: "npm:0.20.17" drizzle-orm: "npm:0.30.9" envalid: "npm:8.0.0" @@ -1756,8 +1763,11 @@ __metadata: eslint-plugin-react: "npm:7.34.1" eslint-plugin-react-hooks: "npm:4.6.0" eslint-plugin-unicorn: "npm:52.0.0" + got: "npm:14.2.1" graphql: "npm:16.8.1" graphql-request: "npm:6.1.0" + graphql-scalars: "npm:1.23.0" + graphql-transform-scalars: "npm:1.2.1" graphql-yoga: "npm:5.3.0" happy-dom: "npm:14.7.1" hono: "npm:4.2.4" @@ -1766,9 +1776,11 @@ __metadata: jest-extended: "npm:4.0.2" jsonwebtoken: "npm:9.0.2" jwks-rsa: "npm:3.1.0" + jwt-decode: "npm:4.0.0" lint-staged: "npm:15.2.2" - mock-jwks: "npm:3.1.0" + mock-jwks: "patch:mock-jwks@npm%3A3.1.0#~/.yarn/patches/mock-jwks-npm-3.1.0-131e3bbc29.patch" msw: "npm:2.2.14" + node-mocks-http: "npm:1.14.1" nx: "npm:18.3.3" playwright: "npm:1.43.0" postgres: "npm:3.4.4" @@ -1777,15 +1789,21 @@ __metadata: react-dom: "npm:18.2.0" react-is: "npm:18.2.0" react-router-dom: "npm:6.22.3" + remix-auth: "npm:3.6.0" + remix-auth-auth0: "npm:1.10.0" + remix-auth-oauth2: "npm:1.11.2" + remix-flat-routes: "npm:0.6.4" remix-hono: "npm:0.0.16" - styled-components: "npm:6.1.8" tiny-invariant: "npm:1.3.3" + tsconfig-paths: "npm:4.2.0" tslib: "npm:2.6.2" tsx: "npm:4.7.3" + type-fest: "npm:4.17.0" typescript: "npm:5.4.5" typescript-eslint: "npm:7.6.0" + uuid: "npm:9.0.1" vite: "npm:5.2.10" - vitest: "npm:1.5.1" + vitest: "npm:1.5.2" languageName: unknown linkType: soft @@ -2035,29 +2053,6 @@ __metadata: languageName: node linkType: hard -"@emotion/is-prop-valid@npm:1.2.1": - version: 1.2.1 - resolution: "@emotion/is-prop-valid@npm:1.2.1" - dependencies: - "@emotion/memoize": "npm:^0.8.1" - checksum: 10c0/7c2aabdf0ca9986ca25abc9dae711348308cf18d418d64ffa4c8ffd2114806c47f2e06ba8ee769f38ec67d65bd59ec73f34d94023e81baa1c43510ac86ccd5e6 - languageName: node - linkType: hard - -"@emotion/memoize@npm:^0.8.1": - version: 0.8.1 - resolution: "@emotion/memoize@npm:0.8.1" - checksum: 10c0/dffed372fc3b9fa2ba411e76af22b6bb686fb0cb07694fdfaa6dd2baeb0d5e4968c1a7caa472bfcf06a5997d5e7c7d16b90e993f9a6ffae79a2c3dbdc76dfe78 - languageName: node - linkType: hard - -"@emotion/unitless@npm:0.8.0": - version: 0.8.0 - resolution: "@emotion/unitless@npm:0.8.0" - checksum: 10c0/1f2cfb7c0ccb83c20b1c6d8d92a74a93da4b2a440f9a0d49ded08647faf299065a2ffde17e1335920fa10397b85f8635bbfe14f3cd29222a59ea81d978478072 - languageName: node - linkType: hard - "@envelop/core@npm:^5.0.0": version: 5.0.0 resolution: "@envelop/core@npm:5.0.0" @@ -3916,16 +3911,6 @@ __metadata: languageName: node linkType: hard -"@mswjs/cookies@npm:^0.2.2": - version: 0.2.2 - resolution: "@mswjs/cookies@npm:0.2.2" - dependencies: - "@types/set-cookie-parser": "npm:^2.4.0" - set-cookie-parser: "npm:^2.4.6" - checksum: 10c0/f950062538d431674d581309cf19884fc4d3f57e2a276164cac0c9a3250071d42464ba7825d13be14c703ca5a912d62a62626f4a068d8f36d1629dbb63bde740 - languageName: node - linkType: hard - "@mswjs/cookies@npm:^1.1.0": version: 1.1.0 resolution: "@mswjs/cookies@npm:1.1.0" @@ -3933,19 +3918,28 @@ __metadata: languageName: node linkType: hard -"@mswjs/interceptors@npm:^0.17.10": - version: 0.17.10 - resolution: "@mswjs/interceptors@npm:0.17.10" +"@mswjs/data@npm:0.16.1": + version: 0.16.1 + resolution: "@mswjs/data@npm:0.16.1" dependencies: - "@open-draft/until": "npm:^1.0.3" - "@types/debug": "npm:^4.1.7" - "@xmldom/xmldom": "npm:^0.8.3" - debug: "npm:^4.3.3" - headers-polyfill: "npm:3.2.5" + "@types/lodash": "npm:^4.14.172" + "@types/md5": "npm:^2.3.0" + "@types/pluralize": "npm:^0.0.29" + "@types/uuid": "npm:^8.3.0" + date-fns: "npm:^2.21.1" + debug: "npm:^4.3.1" + graphql: "npm:^16.8.1" + lodash: "npm:^4.17.21" + md5: "npm:^2.3.0" + msw: "npm:^2.0.8" outvariant: "npm:^1.2.1" - strict-event-emitter: "npm:^0.2.4" - web-encoding: "npm:^1.1.5" - checksum: 10c0/0343a93711b60c321c40733d6bf2720a736d8e0730f5d0d9916ee4a24abfcfca4a83d1e4b2e21c3affef4fc61f04588104be002fbc8258dc4b0d202c384ade33 + pluralize: "npm:^8.0.0" + strict-event-emitter: "npm:^0.5.0" + uuid: "npm:^8.3.1" + dependenciesMeta: + msw: + optional: true + checksum: 10c0/9518f5e918b9bbf6fe87aa57950091282d5fb3a0b9d6ed5ab7746fe46ed326d958607932cb441e6f77378e2a957a01857e15d870f2697128a1f3c7237ffb02b0 languageName: node linkType: hard @@ -3963,6 +3957,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:^1.1.5": + version: 1.4.0 + resolution: "@noble/hashes@npm:1.4.0" + checksum: 10c0/8c3f005ee72e7b8f9cff756dfae1241485187254e3f743873e22073d63906863df5d4f13d441b7530ea614b7a093f0d889309f28b59850f33b66cb26a779a4a5 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -4465,13 +4466,6 @@ __metadata: languageName: node linkType: hard -"@open-draft/until@npm:^1.0.3": - version: 1.0.3 - resolution: "@open-draft/until@npm:1.0.3" - checksum: 10c0/f88bcd774b55359d14a4fa80f7bfe7d9d6d26a5995e94e823e43b211656daae3663e983f0a996937da286d22f6f5da2087b661845302f236ba27f8529dcd14fb - languageName: node - linkType: hard - "@open-draft/until@npm:^2.0.0, @open-draft/until@npm:^2.1.0": version: 2.1.0 resolution: "@open-draft/until@npm:2.1.0" @@ -4479,6 +4473,15 @@ __metadata: languageName: node linkType: hard +"@paralleldrive/cuid2@npm:2.2.2": + version: 2.2.2 + resolution: "@paralleldrive/cuid2@npm:2.2.2" + dependencies: + "@noble/hashes": "npm:^1.1.5" + checksum: 10c0/af5826df93de437121308f4f4ce0b2eeb89b60bb57a1a6592fb89c0d40d311ad1d9f3f6a4db2cce6f2bcf572de1aa3f85704254e89b18ce61c41ebb06564c4ee + languageName: node + linkType: hard + "@parcel/watcher-android-arm64@npm:2.4.1": version: 2.4.1 resolution: "@parcel/watcher-android-arm64@npm:2.4.1" @@ -4913,6 +4916,17 @@ __metadata: languageName: node linkType: hard +"@remix-run/v1-route-convention@npm:^0.1.3": + version: 0.1.4 + resolution: "@remix-run/v1-route-convention@npm:0.1.4" + dependencies: + minimatch: "npm:^7.4.3" + peerDependencies: + "@remix-run/dev": ^1.15.0 || ^2.0.0 + checksum: 10c0/f9984d9212d6b5c910d2d3a84a37e13cdb0b078c6832bb8b8dc5b1242a0c9ddadf77eebfc3dbdfcc524364e999272ba6d85b998f19c02d5b94db12cff5e54d15 + languageName: node + linkType: hard + "@remix-run/web-blob@npm:^3.1.0": version: 3.1.0 resolution: "@remix-run/web-blob@npm:3.1.0" @@ -5092,6 +5106,13 @@ __metadata: languageName: node linkType: hard +"@sindresorhus/is@npm:^6.1.0": + version: 6.3.0 + resolution: "@sindresorhus/is@npm:6.3.0" + checksum: 10c0/40d201fc1abcab01f946f020c3f33dbaba9532af58eda6bd8f55f6cb77ddb093ac4b1016f53b4b3699f1c8ec653a52978ad0e86aae56c834e6968e6af08a68ac + languageName: node + linkType: hard + "@sinonjs/commons@npm:^3.0.0": version: 3.0.1 resolution: "@sinonjs/commons@npm:3.0.1" @@ -5480,6 +5501,15 @@ __metadata: languageName: node linkType: hard +"@szmarczak/http-timer@npm:^5.0.1": + version: 5.0.1 + resolution: "@szmarczak/http-timer@npm:5.0.1" + dependencies: + defer-to-connect: "npm:^2.0.1" + checksum: 10c0/4629d2fbb2ea67c2e9dc03af235c0991c79ebdddcbc19aed5d5732fb29ce01c13331e9b1a491584b9069bd6ecde6581dcbf871f11b7eefdebbab34de6cf2197e + languageName: node + linkType: hard + "@testcontainers/postgresql@npm:10.9.0": version: 10.9.0 resolution: "@testcontainers/postgresql@npm:10.9.0" @@ -5489,6 +5519,22 @@ __metadata: languageName: node linkType: hard +"@testing-library/dom@npm:10.0.0": + version: 10.0.0 + resolution: "@testing-library/dom@npm:10.0.0" + dependencies: + "@babel/code-frame": "npm:^7.10.4" + "@babel/runtime": "npm:^7.12.5" + "@types/aria-query": "npm:^5.0.1" + aria-query: "npm:5.3.0" + chalk: "npm:^4.1.0" + dom-accessibility-api: "npm:^0.5.9" + lz-string: "npm:^1.5.0" + pretty-format: "npm:^27.0.2" + checksum: 10c0/2d12d2a6018a6f1d15e91834180bc068932c699ff1fcbfb80aa21aba519a4f5329c861dfa852e06ee5615bcb92ef2a0f0e755e32684ea3dada63bc34248382ab + languageName: node + linkType: hard + "@testing-library/dom@npm:^9.0.0": version: 9.3.4 resolution: "@testing-library/dom@npm:9.3.4" @@ -5552,6 +5598,15 @@ __metadata: languageName: node linkType: hard +"@testing-library/user-event@npm:14.5.2": + version: 14.5.2 + resolution: "@testing-library/user-event@npm:14.5.2" + peerDependencies: + "@testing-library/dom": ">=7.21.4" + checksum: 10c0/68a0c2aa28a3c8e6eb05cafee29705438d7d8a9427423ce5064d44f19c29e89b5636de46dd2f28620fb10abba75c67130185bbc3aa23ac1163a227a5f36641e1 + languageName: node + linkType: hard + "@tokenizer/token@npm:^0.3.0": version: 0.3.0 resolution: "@tokenizer/token@npm:0.3.0" @@ -5691,13 +5746,6 @@ __metadata: languageName: node linkType: hard -"@types/cookie@npm:^0.4.1": - version: 0.4.1 - resolution: "@types/cookie@npm:0.4.1" - checksum: 10c0/f96afe12bd51be1ec61410b0641243d93fa3a494702407c787a4c872b5c8bcd39b224471452055e44a9ce42af1a636e87d161994226eaf4c2be9c30f60418409 - languageName: node - linkType: hard - "@types/cookie@npm:^0.6.0": version: 0.6.0 resolution: "@types/cookie@npm:0.6.0" @@ -5705,7 +5753,7 @@ __metadata: languageName: node linkType: hard -"@types/debug@npm:^4.0.0, @types/debug@npm:^4.1.7": +"@types/debug@npm:^4.0.0": version: 4.1.12 resolution: "@types/debug@npm:4.1.12" dependencies: @@ -5763,7 +5811,7 @@ __metadata: languageName: node linkType: hard -"@types/express@npm:^4.17.17": +"@types/express@npm:^4.17.17, @types/express@npm:^4.17.21": version: 4.17.21 resolution: "@types/express@npm:4.17.21" dependencies: @@ -5793,17 +5841,7 @@ __metadata: languageName: node linkType: hard -"@types/hoist-non-react-statics@npm:*": - version: 3.3.5 - resolution: "@types/hoist-non-react-statics@npm:3.3.5" - dependencies: - "@types/react": "npm:*" - hoist-non-react-statics: "npm:^3.3.0" - checksum: 10c0/2a3b64bf3d9817d7830afa60ee314493c475fb09570a64e7737084cd482d2177ebdddf888ce837350bac51741278b077683facc9541f052d4bbe8487b4e3e618 - languageName: node - linkType: hard - -"@types/http-cache-semantics@npm:*": +"@types/http-cache-semantics@npm:*, @types/http-cache-semantics@npm:^4.0.2": version: 4.0.4 resolution: "@types/http-cache-semantics@npm:4.0.4" checksum: 10c0/51b72568b4b2863e0fe8d6ce8aad72a784b7510d72dc866215642da51d84945a9459fa89f49ec48f1e9a1752e6a78e85a4cda0ded06b1c73e727610c925f9ce6 @@ -5842,13 +5880,6 @@ __metadata: languageName: node linkType: hard -"@types/js-levenshtein@npm:^1.1.1": - version: 1.1.3 - resolution: "@types/js-levenshtein@npm:1.1.3" - checksum: 10c0/025f2bd8d865cfa7a996799a1a2f2a77fa2fc74a28971aa035a103de35d7c1e3d949721a88f57fdb532815bbcb2bf7019196a608ed0a8bbd1023d64c52bb251b - languageName: node - linkType: hard - "@types/js-yaml@npm:^4.0.0": version: 4.0.9 resolution: "@types/js-yaml@npm:4.0.9" @@ -5888,6 +5919,20 @@ __metadata: languageName: node linkType: hard +"@types/lodash@npm:^4.14.172": + version: 4.17.0 + resolution: "@types/lodash@npm:4.17.0" + checksum: 10c0/4c5b41c9a6c41e2c05d08499e96f7940bcf194dcfa84356235b630da920c2a5e05f193618cea76006719bec61c76617dff02defa9d29934f9f6a76a49291bd8f + languageName: node + linkType: hard + +"@types/md5@npm:^2.3.0": + version: 2.3.5 + resolution: "@types/md5@npm:2.3.5" + checksum: 10c0/aef9c40ab0ec61f1ae2acb04ee04e55b99eeec64af58176ef36d4feaf6aac335f32caca07eca0e3a1813fc362bf0b8663423250e24b39ebcfdc24c6ca4abe1cf + languageName: node + linkType: hard + "@types/mdast@npm:^3.0.0": version: 3.0.15 resolution: "@types/mdast@npm:3.0.15" @@ -5927,7 +5972,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:20.12.7, @types/node@npm:^20.10.7, @types/node@npm:^20.12.7": +"@types/node@npm:*, @types/node@npm:20.12.7, @types/node@npm:^20.10.6, @types/node@npm:^20.10.7, @types/node@npm:^20.12.7": version: 20.12.7 resolution: "@types/node@npm:20.12.7" dependencies: @@ -5959,6 +6004,13 @@ __metadata: languageName: node linkType: hard +"@types/pluralize@npm:^0.0.29": + version: 0.0.29 + resolution: "@types/pluralize@npm:0.0.29" + checksum: 10c0/840796fa1db158eb4d9787758d134736e29d9a8035f5b0cbad06e3801fc64b79112ba944c83f9a1a5b94da08703f505b8315b7e0f28bfc0f8e9e1ccfead7b083 + languageName: node + linkType: hard + "@types/prop-types@npm:*": version: 15.7.12 resolution: "@types/prop-types@npm:15.7.12" @@ -6045,15 +6097,6 @@ __metadata: languageName: node linkType: hard -"@types/set-cookie-parser@npm:^2.4.0": - version: 2.4.7 - resolution: "@types/set-cookie-parser@npm:2.4.7" - dependencies: - "@types/node": "npm:*" - checksum: 10c0/3c4b5168fe2e8f1f70e39de718fab79bf5386dcb3217b16936d732b985af2372eb0670190c0c5c9c3e68ace34dd6e52e9664439cec06354c278601f659c396ff - languageName: node - linkType: hard - "@types/ssh2-streams@npm:*": version: 0.1.12 resolution: "@types/ssh2-streams@npm:0.1.12" @@ -6096,24 +6139,6 @@ __metadata: languageName: node linkType: hard -"@types/styled-components@npm:5.1.34": - version: 5.1.34 - resolution: "@types/styled-components@npm:5.1.34" - dependencies: - "@types/hoist-non-react-statics": "npm:*" - "@types/react": "npm:*" - csstype: "npm:^3.0.2" - checksum: 10c0/5bce93ea2c6161fc45daaf863eefdc20672e839ae486597c40b95e7978e249c160c1bc9706f56cb5152a7ef63cf485d15a9502889169ef945281f511e4b2d5a0 - languageName: node - linkType: hard - -"@types/stylis@npm:4.2.0": - version: 4.2.0 - resolution: "@types/stylis@npm:4.2.0" - checksum: 10c0/c76c13e76ca485f598a13984cfb5e07bb88a851da5bee213587424a5f101f182c74f4f92d633cebf9abcec40ccebb645d600d184b7e4b42793e3eeca8729b110 - languageName: node - linkType: hard - "@types/triple-beam@npm:^1.3.2": version: 1.3.5 resolution: "@types/triple-beam@npm:1.3.5" @@ -6128,6 +6153,13 @@ __metadata: languageName: node linkType: hard +"@types/uuid@npm:^8.3.0": + version: 8.3.4 + resolution: "@types/uuid@npm:8.3.4" + checksum: 10c0/b9ac98f82fcf35962317ef7dc44d9ac9e0f6fdb68121d384c88fe12ea318487d5585d3480fa003cf28be86a3bbe213ca688ba786601dce4a97724765eb5b1cf2 + languageName: node + linkType: hard + "@types/wrap-ansi@npm:^3.0.0": version: 3.0.0 resolution: "@types/wrap-ansi@npm:3.0.0" @@ -6353,7 +6385,7 @@ __metadata: languageName: node linkType: hard -"@vanilla-extract/babel-plugin-debug-ids@npm:^1.0.4": +"@vanilla-extract/babel-plugin-debug-ids@npm:^1.0.4, @vanilla-extract/babel-plugin-debug-ids@npm:^1.0.5": version: 1.0.5 resolution: "@vanilla-extract/babel-plugin-debug-ids@npm:1.0.5" dependencies: @@ -6362,7 +6394,7 @@ __metadata: languageName: node linkType: hard -"@vanilla-extract/css@npm:^1.14.0": +"@vanilla-extract/css@npm:1.14.2, @vanilla-extract/css@npm:^1.14.0, @vanilla-extract/css@npm:^1.14.2": version: 1.14.2 resolution: "@vanilla-extract/css@npm:1.14.2" dependencies: @@ -6402,6 +6434,27 @@ __metadata: languageName: node linkType: hard +"@vanilla-extract/integration@npm:^7.1.2": + version: 7.1.2 + resolution: "@vanilla-extract/integration@npm:7.1.2" + dependencies: + "@babel/core": "npm:^7.23.9" + "@babel/plugin-syntax-typescript": "npm:^7.23.3" + "@vanilla-extract/babel-plugin-debug-ids": "npm:^1.0.5" + "@vanilla-extract/css": "npm:^1.14.2" + esbuild: "npm:esbuild@~0.17.6 || ~0.18.0 || ~0.19.0" + eval: "npm:0.1.8" + find-up: "npm:^5.0.0" + javascript-stringify: "npm:^2.0.1" + lodash: "npm:^4.17.21" + mlly: "npm:^1.4.2" + outdent: "npm:^0.8.0" + vite: "npm:^5.0.11" + vite-node: "npm:^1.2.0" + checksum: 10c0/c4bb99d3ca820bafbc8c68b8d0075c7b64b6fbcc3c137095ec258b0227a6b38d2dbadf96b5fd21d34413a91bfe820e480e34cfffda410ef85a8ef25b1dc25b9c + languageName: node + linkType: hard + "@vanilla-extract/private@npm:^1.0.4": version: 1.0.4 resolution: "@vanilla-extract/private@npm:1.0.4" @@ -6409,6 +6462,26 @@ __metadata: languageName: node linkType: hard +"@vanilla-extract/sprinkles@npm:1.6.1": + version: 1.6.1 + resolution: "@vanilla-extract/sprinkles@npm:1.6.1" + peerDependencies: + "@vanilla-extract/css": ^1.0.0 + checksum: 10c0/7ddd2ab7c88b5740260e09aba5399d938d9a46142a0652842e8cd3fe34cd2fd2fbeb75060718bb44cb1a81dce280bb9955ae35defd89f7045e3a6822baf2b5ae + languageName: node + linkType: hard + +"@vanilla-extract/vite-plugin@npm:4.0.7": + version: 4.0.7 + resolution: "@vanilla-extract/vite-plugin@npm:4.0.7" + dependencies: + "@vanilla-extract/integration": "npm:^7.1.2" + peerDependencies: + vite: ^4.0.3 || ^5.0.0 + checksum: 10c0/1d9dd8bdd7767301755ad6f9a4bbecada2437becdb9c28f900d0881bd8206a26762c1d45e24acae673fd68b31debf083deabf76c49a695adf6566176e6932ee2 + languageName: node + linkType: hard + "@vitejs/plugin-react@npm:4.2.1": version: 4.2.1 resolution: "@vitejs/plugin-react@npm:4.2.1" @@ -6424,9 +6497,9 @@ __metadata: languageName: node linkType: hard -"@vitest/coverage-v8@npm:1.5.1": - version: 1.5.1 - resolution: "@vitest/coverage-v8@npm:1.5.1" +"@vitest/coverage-v8@npm:1.5.2": + version: 1.5.2 + resolution: "@vitest/coverage-v8@npm:1.5.2" dependencies: "@ampproject/remapping": "npm:^2.2.1" "@bcoe/v8-coverage": "npm:^0.2.3" @@ -6442,58 +6515,58 @@ __metadata: strip-literal: "npm:^2.0.0" test-exclude: "npm:^6.0.0" peerDependencies: - vitest: 1.5.1 - checksum: 10c0/614b0a7ca024af243808e14deab98abad5a11b63102a9d2abe6f7647cefa11b5e4553e818344a75b7ecd9e9cd16a1872dbcd97e37b8ce7ba2af5ae5bd0438a48 + vitest: 1.5.2 + checksum: 10c0/cc982753969ca31033072324121288fc1945bc7ad09cc00ade9e2d29852acbfb97b177e7bfd0ab6c4cacab1e6600da1e287ed11e340745ffbe55d19212c25cc7 languageName: node linkType: hard -"@vitest/expect@npm:1.5.1": - version: 1.5.1 - resolution: "@vitest/expect@npm:1.5.1" +"@vitest/expect@npm:1.5.2": + version: 1.5.2 + resolution: "@vitest/expect@npm:1.5.2" dependencies: - "@vitest/spy": "npm:1.5.1" - "@vitest/utils": "npm:1.5.1" + "@vitest/spy": "npm:1.5.2" + "@vitest/utils": "npm:1.5.2" chai: "npm:^4.3.10" - checksum: 10c0/4743ca8de3ce269dca4aaf441a2a4d07510d341aeee7be59d17277c9a26b48c00541dd0570eb3d465f62290947135c8ef9978bc2697eadfbbd01cc7f0cdfdc37 + checksum: 10c0/4e8400a55f9e2d4a5a5e2be8c5679fb0a3bfa7550085597b4022320bd9d8f70663707bb4ea02a5403b5327f405d7bc3de5dd21bbf43a8aabc6ceecfc83760ba8 languageName: node linkType: hard -"@vitest/runner@npm:1.5.1": - version: 1.5.1 - resolution: "@vitest/runner@npm:1.5.1" +"@vitest/runner@npm:1.5.2": + version: 1.5.2 + resolution: "@vitest/runner@npm:1.5.2" dependencies: - "@vitest/utils": "npm:1.5.1" + "@vitest/utils": "npm:1.5.2" p-limit: "npm:^5.0.0" pathe: "npm:^1.1.1" - checksum: 10c0/a079c111c9082360b471dbc1f46a82dc3521a768f2bba7a2036f24a7d0b27161ce8f922a553ac03c9e35b77a33d37b1bbbf9ff67eb4bd111c3a130028b513793 + checksum: 10c0/9fc3e668817ceb49785a366959281eee31739b393b7629d19534a0f3044558663130275cf0631c1821cdf916b491bc3e8b57da1cfaeefa66a99473c08c4e7621 languageName: node linkType: hard -"@vitest/snapshot@npm:1.5.1": - version: 1.5.1 - resolution: "@vitest/snapshot@npm:1.5.1" +"@vitest/snapshot@npm:1.5.2": + version: 1.5.2 + resolution: "@vitest/snapshot@npm:1.5.2" dependencies: magic-string: "npm:^0.30.5" pathe: "npm:^1.1.1" pretty-format: "npm:^29.7.0" - checksum: 10c0/d3d769873b16297f6e9bc64c8394110ef981dc8f271f608270ee89d1a92e5515e56d9c2bede21fd3881baf919882652f9c912a435a6092147aafbc21d10f828d + checksum: 10c0/67ae235e59f1adec1e6a44e2a8ea1d2ee98f2416d3ccf566798474ee98943b87b3f20c2098e193866b01780ae4c767239e4f94dbbb3daf0f0978b8106e8e86b1 languageName: node linkType: hard -"@vitest/spy@npm:1.5.1": - version: 1.5.1 - resolution: "@vitest/spy@npm:1.5.1" +"@vitest/spy@npm:1.5.2": + version: 1.5.2 + resolution: "@vitest/spy@npm:1.5.2" dependencies: tinyspy: "npm:^2.2.0" - checksum: 10c0/865b94bc99a865c8adc813f25cc797b2f7ffdc7807ed54ce64f86125a8227ac80078b29c86d3463bb71febdddc582bd9f8d74f14c6089f088c1cd8af57691283 + checksum: 10c0/d66de2873f762ba9a45ca03fe9d11db0c1910635e02289a5b54746c41bd68366b9d198b265e13a8608cc21774f4f197afb25acbba5c0769e651598df0eaab5b3 languageName: node linkType: hard -"@vitest/ui@npm:1.5.1": - version: 1.5.1 - resolution: "@vitest/ui@npm:1.5.1" +"@vitest/ui@npm:1.5.2": + version: 1.5.2 + resolution: "@vitest/ui@npm:1.5.2" dependencies: - "@vitest/utils": "npm:1.5.1" + "@vitest/utils": "npm:1.5.2" fast-glob: "npm:^3.3.2" fflate: "npm:^0.8.1" flatted: "npm:^3.2.9" @@ -6501,20 +6574,20 @@ __metadata: picocolors: "npm:^1.0.0" sirv: "npm:^2.0.4" peerDependencies: - vitest: 1.5.1 - checksum: 10c0/efba22a08b639ea0a0c31c189585c392018209bc38783378c46f1f522c736f835c36aadb5318ae92b58f33513ef9fc91b72d7bef2ebdef4bab4a27c558355e49 + vitest: 1.5.2 + checksum: 10c0/85fc78e0b30dee903683023c0db0c8e72956c26307d05868c2e462187ff0dc5e6f65ccef97c0f089cb3034f87101e25faa271fd1f2befb9dc1d6dd65378c9e54 languageName: node linkType: hard -"@vitest/utils@npm:1.5.1": - version: 1.5.1 - resolution: "@vitest/utils@npm:1.5.1" +"@vitest/utils@npm:1.5.2": + version: 1.5.2 + resolution: "@vitest/utils@npm:1.5.2" dependencies: diff-sequences: "npm:^29.6.3" estree-walker: "npm:^3.0.3" loupe: "npm:^2.3.7" pretty-format: "npm:^29.7.0" - checksum: 10c0/45bef3c3c5505943f099937dadd28f8468a86220527f46de8b69c7cd581e7703f2b82831c331ea1dbd5bdf72b24d9ed4bb262343189352642d187b6f75e4e249 + checksum: 10c0/019eeac016deb5d2434db4990b2ba1ebf37434a020c3d6bcf163c77af80e01dd9add7b3d379bdacd91497847026a5bd2aafe393035c48f5296ce5275bad00126 languageName: node linkType: hard @@ -6598,13 +6671,6 @@ __metadata: languageName: node linkType: hard -"@xmldom/xmldom@npm:^0.8.3": - version: 0.8.10 - resolution: "@xmldom/xmldom@npm:0.8.10" - checksum: 10c0/c7647c442502720182b0d65b17d45d2d95317c1c8c497626fe524bda79b4fb768a9aa4fae2da919f308e7abcff7d67c058b102a9d641097e9a57f0b80187851f - languageName: node - linkType: hard - "@yarnpkg/lockfile@npm:^1.1.0": version: 1.1.0 resolution: "@yarnpkg/lockfile@npm:1.1.0" @@ -6668,7 +6734,7 @@ __metadata: languageName: node linkType: hard -"accepts@npm:~1.3.5, accepts@npm:~1.3.8": +"accepts@npm:^1.3.7, accepts@npm:~1.3.5, accepts@npm:~1.3.8": version: 1.3.8 resolution: "accepts@npm:1.3.8" dependencies: @@ -6861,17 +6927,26 @@ __metadata: dependencies: "@graphql-typed-document-node/core": "npm:3.2.0" "@hono/node-server": "npm:1.11.0" + "@mswjs/data": "npm:0.16.1" "@nx/vite": "npm:18.3.3" + "@paralleldrive/cuid2": "npm:2.2.2" "@remix-run/dev": "npm:2.9.1" "@remix-run/node": "npm:2.9.1" "@remix-run/react": "npm:2.9.1" + "@remix-run/server-runtime": "npm:2.9.1" "@remix-run/testing": "npm:2.9.1" + "@testing-library/dom": "npm:10.0.0" "@testing-library/jest-dom": "npm:6.4.2" "@testing-library/react": "npm:14.3.0" + "@testing-library/user-event": "npm:14.5.2" "@types/node": "npm:20.12.7" "@types/react": "npm:18.2.75" "@types/react-dom": "npm:18.2.24" + "@vanilla-extract/css": "npm:1.14.2" + "@vanilla-extract/sprinkles": "npm:1.6.1" + "@vanilla-extract/vite-plugin": "npm:4.0.7" "@vitejs/plugin-react": "npm:4.2.1" + "@vitest/expect": "npm:1.5.2" eslint-plugin-jsx-a11y: "npm:6.8.0" eslint-plugin-react: "npm:7.34.1" eslint-plugin-react-hooks: "npm:4.6.0" @@ -6880,14 +6955,21 @@ __metadata: hono: "npm:4.2.4" isbot: "npm:4" jest-extended: "npm:4.0.2" + jwt-decode: "npm:4.0.0" msw: "npm:2.2.14" react: "npm:18.2.0" react-dom: "npm:18.2.0" + remix-auth: "npm:3.6.0" + remix-auth-auth0: "npm:1.10.0" + remix-auth-oauth2: "npm:1.11.2" + remix-flat-routes: "npm:0.6.4" remix-hono: "npm:0.0.16" + tiny-invariant: "npm:1.3.3" tslib: "npm:2.6.2" typescript: "npm:5.4.5" + uuid: "npm:9.0.1" vite: "npm:5.2.10" - vitest: "npm:1.5.1" + vitest: "npm:1.5.2" languageName: unknown linkType: soft @@ -6988,7 +7070,7 @@ __metadata: languageName: node linkType: hard -"aria-query@npm:^5.0.0, aria-query@npm:^5.3.0": +"aria-query@npm:5.3.0, aria-query@npm:^5.0.0, aria-query@npm:^5.3.0": version: 5.3.0 resolution: "aria-query@npm:5.3.0" dependencies: @@ -7834,6 +7916,28 @@ __metadata: languageName: node linkType: hard +"cacheable-lookup@npm:^7.0.0": + version: 7.0.0 + resolution: "cacheable-lookup@npm:7.0.0" + checksum: 10c0/63a9c144c5b45cb5549251e3ea774c04d63063b29e469f7584171d059d3a88f650f47869a974e2d07de62116463d742c287a81a625e791539d987115cb081635 + languageName: node + linkType: hard + +"cacheable-request@npm:^10.2.14": + version: 10.2.14 + resolution: "cacheable-request@npm:10.2.14" + dependencies: + "@types/http-cache-semantics": "npm:^4.0.2" + get-stream: "npm:^6.0.1" + http-cache-semantics: "npm:^4.1.1" + keyv: "npm:^4.5.3" + mimic-response: "npm:^4.0.0" + normalize-url: "npm:^8.0.0" + responselike: "npm:^3.0.0" + checksum: 10c0/41b6658db369f20c03128227ecd219ca7ac52a9d24fc0f499cc9aa5d40c097b48b73553504cebd137024d957c0ddb5b67cf3ac1439b136667f3586257763f88d + languageName: node + linkType: hard + "cacheable-request@npm:^7.0.2": version: 7.0.4 resolution: "cacheable-request@npm:7.0.4" @@ -7900,13 +8004,6 @@ __metadata: languageName: node linkType: hard -"camelize@npm:^1.0.0": - version: 1.0.1 - resolution: "camelize@npm:1.0.1" - checksum: 10c0/4c9ac55efd356d37ac483bad3093758236ab686192751d1c9daa43188cc5a07b09bd431eb7458a4efd9ca22424bba23253e7b353feb35d7c749ba040de2385fb - languageName: node - linkType: hard - "caniuse-lite@npm:^1.0.30001587": version: 1.0.30001608 resolution: "caniuse-lite@npm:1.0.30001608" @@ -8065,6 +8162,13 @@ __metadata: languageName: node linkType: hard +"charenc@npm:0.0.2": + version: 0.0.2 + resolution: "charenc@npm:0.0.2" + checksum: 10c0/a45ec39363a16799d0f9365c8dd0c78e711415113c6f14787a22462ef451f5013efae8a28f1c058f81fc01f2a6a16955f7a5fd0cd56247ce94a45349c89877d8 + languageName: node + linkType: hard + "check-error@npm:^1.0.3": version: 1.0.3 resolution: "check-error@npm:1.0.3" @@ -8074,7 +8178,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.4.2, chokidar@npm:^3.5.1, chokidar@npm:^3.5.3": +"chokidar@npm:^3.5.1, chokidar@npm:^3.5.3": version: 3.6.0 resolution: "chokidar@npm:3.6.0" dependencies: @@ -8487,7 +8591,7 @@ __metadata: languageName: node linkType: hard -"content-disposition@npm:0.5.4, content-disposition@npm:^0.5.4": +"content-disposition@npm:0.5.4, content-disposition@npm:^0.5.3, content-disposition@npm:^0.5.4": version: 0.5.4 resolution: "content-disposition@npm:0.5.4" dependencies: @@ -8554,13 +8658,6 @@ __metadata: languageName: node linkType: hard -"cookie@npm:^0.4.2": - version: 0.4.2 - resolution: "cookie@npm:0.4.2" - checksum: 10c0/beab41fbd7c20175e3a2799ba948c1dcc71ef69f23fe14eeeff59fc09f50c517b0f77098db87dbb4c55da802f9d86ee86cdc1cd3efd87760341551838d53fca2 - languageName: node - linkType: hard - "cookie@npm:^0.5.0": version: 0.5.0 resolution: "cookie@npm:0.5.0" @@ -8737,10 +8834,10 @@ __metadata: languageName: node linkType: hard -"css-color-keywords@npm:^1.0.0": - version: 1.0.0 - resolution: "css-color-keywords@npm:1.0.0" - checksum: 10c0/af205a86c68e0051846ed91eb3e30b4517e1904aac040013ff1d742019b3f9369ba5658ba40901dbbc121186fc4bf0e75a814321cc3e3182fbb2feb81c6d9cb7 +"crypt@npm:0.0.2": + version: 0.0.2 + resolution: "crypt@npm:0.0.2" + checksum: 10c0/adbf263441dd801665d5425f044647533f39f4612544071b1471962209d235042fb703c27eea2795c7c53e1dfc242405173003f83cf4f4761a633d11f9653f18 languageName: node linkType: hard @@ -8757,17 +8854,6 @@ __metadata: languageName: node linkType: hard -"css-to-react-native@npm:3.2.0": - version: 3.2.0 - resolution: "css-to-react-native@npm:3.2.0" - dependencies: - camelize: "npm:^1.0.0" - css-color-keywords: "npm:^1.0.0" - postcss-value-parser: "npm:^4.0.2" - checksum: 10c0/fde850a511d5d3d7c55a1e9b8ed26b69a8ad4868b3487e36ebfbfc0b96fc34bc977d9cd1d61a289d0c74d3f9a662d8cee297da53d4433bf2e27d6acdff8e1003 - languageName: node - linkType: hard - "css-tree@npm:^2.3.1": version: 2.3.1 resolution: "css-tree@npm:2.3.1" @@ -8820,13 +8906,6 @@ __metadata: languageName: node linkType: hard -"csstype@npm:3.1.2": - version: 3.1.2 - resolution: "csstype@npm:3.1.2" - checksum: 10c0/32c038af259897c807ac738d9eab16b3d86747c72b09d5c740978e06f067f9b7b1737e1b75e407c7ab1fe1543dc95f20e202b4786aeb1b8d3bdf5d5ce655e6c6 - languageName: node - linkType: hard - "csstype@npm:^3.0.2, csstype@npm:^3.0.7": version: 3.1.3 resolution: "csstype@npm:3.1.3" @@ -8834,13 +8913,6 @@ __metadata: languageName: node linkType: hard -"cuid@npm:3.0.0": - version: 3.0.0 - resolution: "cuid@npm:3.0.0" - checksum: 10c0/e1cac04b8df3222fa612ac23f5ad1839f31ec58778a1cfcb23231224f3fe63cc0bb1747188f349bc93f87a74f574ace31ddcb3e60f5eb4543ff5c9e9458a0168 - languageName: node - linkType: hard - "cuint@npm:^0.2.2": version: 0.2.2 resolution: "cuint@npm:0.2.2" @@ -8919,6 +8991,15 @@ __metadata: languageName: node linkType: hard +"date-fns@npm:^2.21.1": + version: 2.30.0 + resolution: "date-fns@npm:2.30.0" + dependencies: + "@babel/runtime": "npm:^7.21.0" + checksum: 10c0/e4b521fbf22bc8c3db332bbfb7b094fd3e7627de0259a9d17c7551e2d2702608a7307a449206065916538e384f37b181565447ce2637ae09828427aed9cb5581 + languageName: node + linkType: hard + "debounce-fn@npm:^4.0.0": version: 4.0.0 resolution: "debounce-fn@npm:4.0.0" @@ -8944,7 +9025,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -9067,7 +9148,7 @@ __metadata: languageName: node linkType: hard -"defer-to-connect@npm:^2.0.0": +"defer-to-connect@npm:^2.0.0, defer-to-connect@npm:^2.0.1": version: 2.0.1 resolution: "defer-to-connect@npm:2.0.1" checksum: 10c0/625ce28e1b5ad10cf77057b9a6a727bf84780c17660f6644dab61dd34c23de3001f03cedc401f7d30a4ed9965c2e8a7336e220a329146f2cf85d4eddea429782 @@ -9117,6 +9198,13 @@ __metadata: languageName: node linkType: hard +"depd@npm:^1.1.0": + version: 1.1.2 + resolution: "depd@npm:1.1.2" + checksum: 10c0/acb24aaf936ef9a227b6be6d495f0d2eb20108a9a6ad40585c5bda1a897031512fef6484e4fdbb80bd249fdaa82841fa1039f416ece03188e677ba11bcfda249 + languageName: node + linkType: hard + "dependency-graph@npm:^0.11.0": version: 0.11.0 resolution: "dependency-graph@npm:0.11.0" @@ -10710,13 +10798,6 @@ __metadata: languageName: node linkType: hard -"events@npm:^3.3.0": - version: 3.3.0 - resolution: "events@npm:3.3.0" - checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 - languageName: node - linkType: hard - "execa@npm:5.1.1, execa@npm:^5.0.0, execa@npm:^5.1.1": version: 5.1.1 resolution: "execa@npm:5.1.1" @@ -11266,6 +11347,13 @@ __metadata: languageName: node linkType: hard +"form-data-encoder@npm:^4.0.2": + version: 4.0.2 + resolution: "form-data-encoder@npm:4.0.2" + checksum: 10c0/559d3130e265316452434eaf68d68560fb36392ff4d04614683419de4fb43c3dbe152dc303599fae382ce24d3451a6d3d289d3bcc182ae3d8ad32e7ce8e35e53 + languageName: node + linkType: hard + "form-data@npm:^4.0.0": version: 4.0.0 resolution: "form-data@npm:4.0.0" @@ -11291,7 +11379,7 @@ __metadata: languageName: node linkType: hard -"fresh@npm:0.5.2": +"fresh@npm:0.5.2, fresh@npm:^0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" checksum: 10c0/c6d27f3ed86cc5b601404822f31c900dd165ba63fff8152a3ef714e2012e7535027063bc67ded4cb5b3a49fa596495d46cacd9f47d6328459cf570f08b7d9e5a @@ -11316,7 +11404,7 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^11.1.0": +"fs-extra@npm:^11.1.0, fs-extra@npm:^11.1.1": version: 11.2.0 resolution: "fs-extra@npm:11.2.0" dependencies: @@ -11496,7 +11584,7 @@ __metadata: languageName: node linkType: hard -"get-stream@npm:^6.0.0": +"get-stream@npm:^6.0.0, get-stream@npm:^6.0.1": version: 6.0.1 resolution: "get-stream@npm:6.0.1" checksum: 10c0/49825d57d3fd6964228e6200a58169464b8e8970489b3acdc24906c782fb7f01f9f56f8e6653c4a50713771d6658f7cfe051e5eb8c12e334138c9c918b296341 @@ -11667,6 +11755,25 @@ __metadata: languageName: node linkType: hard +"got@npm:14.2.1": + version: 14.2.1 + resolution: "got@npm:14.2.1" + dependencies: + "@sindresorhus/is": "npm:^6.1.0" + "@szmarczak/http-timer": "npm:^5.0.1" + cacheable-lookup: "npm:^7.0.0" + cacheable-request: "npm:^10.2.14" + decompress-response: "npm:^6.0.0" + form-data-encoder: "npm:^4.0.2" + get-stream: "npm:^8.0.1" + http2-wrapper: "npm:^2.2.1" + lowercase-keys: "npm:^3.0.0" + p-cancelable: "npm:^4.0.1" + responselike: "npm:^3.0.0" + checksum: 10c0/6592f70d570d988ace9f3c7ecd4e01d34c96ff5fc2896abce1b820b1e48c6661690c5a692495ad1334054e6051efcfa056165bc863b1d90dd3659bdf0ec9421f + languageName: node + linkType: hard + "got@npm:^11.8.5": version: 11.8.6 resolution: "got@npm:11.8.6" @@ -11737,6 +11844,17 @@ __metadata: languageName: node linkType: hard +"graphql-scalars@npm:1.23.0": + version: 1.23.0 + resolution: "graphql-scalars@npm:1.23.0" + dependencies: + tslib: "npm:^2.5.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: 10c0/7666c305b8367528c4fbb583a2731d93d52f36043d71f4957ecc1d2db71d710d268e25535243beb1b2497db921daa94d3cfa83daaf4a3101a667f358ddbf3436 + languageName: node + linkType: hard + "graphql-tag@npm:^2.11.0": version: 2.12.6 resolution: "graphql-tag@npm:2.12.6" @@ -11748,6 +11866,15 @@ __metadata: languageName: node linkType: hard +"graphql-transform-scalars@npm:1.2.1": + version: 1.2.1 + resolution: "graphql-transform-scalars@npm:1.2.1" + peerDependencies: + graphql: ">=15" + checksum: 10c0/d170e808a2f09fba140808d5bf2c77f887d1dc8d19fc200c1d9de157b2b37a448983181488a9a6370a10e867de4fa5a2da60bd9460598a373f54f278b553e9a1 + languageName: node + linkType: hard + "graphql-ws@npm:^5.14.0": version: 5.16.0 resolution: "graphql-ws@npm:5.16.0" @@ -11940,13 +12067,6 @@ __metadata: languageName: node linkType: hard -"headers-polyfill@npm:3.2.5": - version: 3.2.5 - resolution: "headers-polyfill@npm:3.2.5" - checksum: 10c0/10202f4ebfaecd6aa31305f29664f876ac01d9174a3fb8fcc5a0df3eaf9c1767fb0d6cf6f961484f2bfd2101b6768090976f146bd88aeedd07af4e741cb2dcb7 - languageName: node - linkType: hard - "headers-polyfill@npm:^4.0.2": version: 4.0.3 resolution: "headers-polyfill@npm:4.0.3" @@ -11961,15 +12081,6 @@ __metadata: languageName: node linkType: hard -"hoist-non-react-statics@npm:^3.3.0": - version: 3.3.2 - resolution: "hoist-non-react-statics@npm:3.3.2" - dependencies: - react-is: "npm:^16.7.0" - checksum: 10c0/fe0889169e845d738b59b64badf5e55fa3cf20454f9203d1eb088df322d49d4318df774828e789898dcb280e8a5521bb59b3203385662ca5e9218a6ca5820e74 - languageName: node - linkType: hard - "hono@npm:4.2.4": version: 4.2.4 resolution: "hono@npm:4.2.4" @@ -12106,6 +12217,16 @@ __metadata: languageName: node linkType: hard +"http2-wrapper@npm:^2.2.1": + version: 2.2.1 + resolution: "http2-wrapper@npm:2.2.1" + dependencies: + quick-lru: "npm:^5.1.1" + resolve-alpn: "npm:^1.2.0" + checksum: 10c0/7207201d3c6e53e72e510c9b8912e4f3e468d3ecc0cf3bf52682f2aac9cd99358b896d1da4467380adc151cf97c412bedc59dc13dae90c523f42053a7449eedb + languageName: node + linkType: hard + "https-proxy-agent@npm:^7.0.0, https-proxy-agent@npm:^7.0.1": version: 7.0.4 resolution: "https-proxy-agent@npm:7.0.4" @@ -12265,7 +12386,7 @@ __metadata: languageName: node linkType: hard -"inquirer@npm:^8.0.0, inquirer@npm:^8.2.0": +"inquirer@npm:^8.0.0": version: 8.2.6 resolution: "inquirer@npm:8.2.6" dependencies: @@ -12430,6 +12551,13 @@ __metadata: languageName: node linkType: hard +"is-buffer@npm:~1.1.6": + version: 1.1.6 + resolution: "is-buffer@npm:1.1.6" + checksum: 10c0/ae18aa0b6e113d6c490ad1db5e8df9bdb57758382b313f5a22c9c61084875c6396d50bbf49315f5b1926d142d74dfb8d31b40d993a383e0a158b15fea7a82234 + languageName: node + linkType: hard + "is-builtin-module@npm:^3.2.1": version: 3.2.1 resolution: "is-builtin-module@npm:3.2.1" @@ -13429,13 +13557,6 @@ __metadata: languageName: node linkType: hard -"js-levenshtein@npm:^1.1.6": - version: 1.1.6 - resolution: "js-levenshtein@npm:1.1.6" - checksum: 10c0/14045735325ea1fd87f434a74b11d8a14380f090f154747e613529c7cff68b5ee607f5230fa40665d5fb6125a3791f4c223f73b9feca754f989b059f5c05864f - languageName: node - linkType: hard - "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -13706,6 +13827,13 @@ __metadata: languageName: node linkType: hard +"jwt-decode@npm:4.0.0": + version: 4.0.0 + resolution: "jwt-decode@npm:4.0.0" + checksum: 10c0/de75bbf89220746c388cf6a7b71e56080437b77d2edb29bae1c2155048b02c6b8c59a3e5e8d6ccdfd54f0b8bda25226e491a4f1b55ac5f8da04cfbadec4e546c + languageName: node + linkType: hard + "keyv@npm:^4.0.0, keyv@npm:^4.5.3, keyv@npm:^4.5.4": version: 4.5.4 resolution: "keyv@npm:4.5.4" @@ -14195,6 +14323,13 @@ __metadata: languageName: node linkType: hard +"lowercase-keys@npm:^3.0.0": + version: 3.0.0 + resolution: "lowercase-keys@npm:3.0.0" + checksum: 10c0/ef62b9fa5690ab0a6e4ef40c94efce68e3ed124f583cc3be38b26ff871da0178a28b9a84ce0c209653bb25ca135520ab87fea7cd411a54ac4899cb2f30501430 + languageName: node + linkType: hard + "lru-cache@npm:^10.0.0, lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": version: 10.2.0 resolution: "lru-cache@npm:10.2.0" @@ -14353,6 +14488,17 @@ __metadata: languageName: node linkType: hard +"md5@npm:^2.3.0": + version: 2.3.0 + resolution: "md5@npm:2.3.0" + dependencies: + charenc: "npm:0.0.2" + crypt: "npm:0.0.2" + is-buffer: "npm:~1.1.6" + checksum: 10c0/14a21d597d92e5b738255fbe7fe379905b8cb97e0a49d44a20b58526a646ec5518c337b817ce0094ca94d3e81a3313879c4c7b510d250c282d53afbbdede9110 + languageName: node + linkType: hard + "mdast-util-definitions@npm:^5.0.0": version: 5.1.2 resolution: "mdast-util-definitions@npm:5.1.2" @@ -14565,6 +14711,13 @@ __metadata: languageName: node linkType: hard +"merge-descriptors@npm:^1.0.1": + version: 1.0.3 + resolution: "merge-descriptors@npm:1.0.3" + checksum: 10c0/866b7094afd9293b5ea5dcd82d71f80e51514bed33b4c4e9f516795dc366612a4cbb4dc94356e943a8a6914889a914530badff27f397191b9b75cda20b6bae93 + languageName: node + linkType: hard + "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -14591,7 +14744,7 @@ __metadata: languageName: node linkType: hard -"methods@npm:~1.1.2": +"methods@npm:^1.1.2, methods@npm:~1.1.2": version: 1.1.2 resolution: "methods@npm:1.1.2" checksum: 10c0/bdf7cc72ff0a33e3eede03708c08983c4d7a173f91348b4b1e4f47d4cdbf734433ad971e7d1e8c77247d9e5cd8adb81ea4c67b0a2db526b758b2233d7814b8b2 @@ -14980,7 +15133,7 @@ __metadata: languageName: node linkType: hard -"mime@npm:1.6.0, mime@npm:^1.6.0": +"mime@npm:1.6.0, mime@npm:^1.3.4, mime@npm:^1.6.0": version: 1.6.0 resolution: "mime@npm:1.6.0" bin: @@ -15024,6 +15177,13 @@ __metadata: languageName: node linkType: hard +"mimic-response@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-response@npm:4.0.0" + checksum: 10c0/761d788d2668ae9292c489605ffd4fad220f442fbae6832adce5ebad086d691e906a6d5240c290293c7a11e99fbdbbef04abbbed498bf8699a4ee0f31315e3fb + languageName: node + linkType: hard + "min-indent@npm:^1.0.0": version: 1.0.1 resolution: "min-indent@npm:1.0.1" @@ -15237,6 +15397,19 @@ __metadata: languageName: node linkType: hard +"mock-jwks@patch:mock-jwks@npm%3A3.1.0#~/.yarn/patches/mock-jwks-npm-3.1.0-131e3bbc29.patch": + version: 3.1.0 + resolution: "mock-jwks@patch:mock-jwks@npm%3A3.1.0#~/.yarn/patches/mock-jwks-npm-3.1.0-131e3bbc29.patch::version=3.1.0&hash=3d08e1" + dependencies: + base64-url: "npm:^2.3.3" + jsonwebtoken: "npm:^9.0.0" + msw: "npm:^1.2.2" + node-forge: "npm:^1.3.1" + node-rsa: "npm:^1.1.1" + checksum: 10c0/678cdce347ae03d4cd96b46052ab759fe85d4ceadabf3105bf6c27cbd12f536033509d64070a0c7dc7a9cd96d83f70de07665f067df8547c36b9b3514db253b7 + languageName: node + linkType: hard + "modern-ahocorasick@npm:^1.0.0": version: 1.0.1 resolution: "modern-ahocorasick@npm:1.0.1" @@ -15299,7 +15472,7 @@ __metadata: languageName: node linkType: hard -"msw@npm:2.2.14": +"msw@npm:2.2.14, msw@npm:^2.0.8": version: 2.2.14 resolution: "msw@npm:2.2.14" dependencies: @@ -15331,40 +15504,6 @@ __metadata: languageName: node linkType: hard -"msw@npm:^1.2.2": - version: 1.3.3 - resolution: "msw@npm:1.3.3" - dependencies: - "@mswjs/cookies": "npm:^0.2.2" - "@mswjs/interceptors": "npm:^0.17.10" - "@open-draft/until": "npm:^1.0.3" - "@types/cookie": "npm:^0.4.1" - "@types/js-levenshtein": "npm:^1.1.1" - chalk: "npm:^4.1.1" - chokidar: "npm:^3.4.2" - cookie: "npm:^0.4.2" - graphql: "npm:^16.8.1" - headers-polyfill: "npm:3.2.5" - inquirer: "npm:^8.2.0" - is-node-process: "npm:^1.2.0" - js-levenshtein: "npm:^1.1.6" - node-fetch: "npm:^2.6.7" - outvariant: "npm:^1.4.0" - path-to-regexp: "npm:^6.2.0" - strict-event-emitter: "npm:^0.4.3" - type-fest: "npm:^2.19.0" - yargs: "npm:^17.3.1" - peerDependencies: - typescript: ">= 4.4.x" - peerDependenciesMeta: - typescript: - optional: true - bin: - msw: cli/index.js - checksum: 10c0/0c63b282a53a1a69194729bf9cb77005a682dfbbb1dac6b1a33c9bfecde7f6df1dfaabdff9336b97ed6c29ebd52d6debdae7e506d7baa8eb8fd1e05683dbc398 - languageName: node - linkType: hard - "mute-stream@npm:0.0.8": version: 0.0.8 resolution: "mute-stream@npm:0.0.8" @@ -15388,7 +15527,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.6, nanoid@npm:^3.3.7": +"nanoid@npm:^3.3.7": version: 3.3.7 resolution: "nanoid@npm:3.3.7" bin: @@ -15457,7 +15596,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.0.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.12, node-fetch@npm:^2.6.7, node-fetch@npm:^2.7.0": +"node-fetch@npm:^2.0.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.12, node-fetch@npm:^2.7.0": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -15523,6 +15662,26 @@ __metadata: languageName: node linkType: hard +"node-mocks-http@npm:1.14.1": + version: 1.14.1 + resolution: "node-mocks-http@npm:1.14.1" + dependencies: + "@types/express": "npm:^4.17.21" + "@types/node": "npm:^20.10.6" + accepts: "npm:^1.3.7" + content-disposition: "npm:^0.5.3" + depd: "npm:^1.1.0" + fresh: "npm:^0.5.2" + merge-descriptors: "npm:^1.0.1" + methods: "npm:^1.1.2" + mime: "npm:^1.3.4" + parseurl: "npm:^1.3.3" + range-parser: "npm:^1.2.0" + type-is: "npm:^1.6.18" + checksum: 10c0/bd091ea1de3e00453cd85b114503558c25ab8df195ade3f37d34bb4d1c1096ccc818f51010ae8eaa5ca2fea919cfc624b647c621a4558a6dee710a30038ff64d + languageName: node + linkType: hard + "node-releases@npm:^2.0.14": version: 2.0.14 resolution: "node-releases@npm:2.0.14" @@ -15597,6 +15756,13 @@ __metadata: languageName: node linkType: hard +"normalize-url@npm:^8.0.0": + version: 8.0.1 + resolution: "normalize-url@npm:8.0.1" + checksum: 10c0/eb439231c4b84430f187530e6fdac605c5048ef4ec556447a10c00a91fc69b52d8d8298d9d608e68d3e0f7dc2d812d3455edf425e0f215993667c3183bcab1ef + languageName: node + linkType: hard + "npm-install-checks@npm:^6.0.0": version: 6.3.0 resolution: "npm-install-checks@npm:6.3.0" @@ -16036,6 +16202,13 @@ __metadata: languageName: node linkType: hard +"p-cancelable@npm:^4.0.1": + version: 4.0.1 + resolution: "p-cancelable@npm:4.0.1" + checksum: 10c0/12636623f46784ba962b6fe7a1f34d021f1d9a2cc12c43e270baa715ea872d5c8c7d9f086ed420b8b9817e91d9bbe92c14c90e5dddd4a9968c81a2a7aef7089d + languageName: node + linkType: hard + "p-finally@npm:^1.0.0": version: 1.0.0 resolution: "p-finally@npm:1.0.0" @@ -16203,7 +16376,7 @@ __metadata: languageName: node linkType: hard -"parseurl@npm:~1.3.3": +"parseurl@npm:^1.3.3, parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" checksum: 10c0/90dd4760d6f6174adb9f20cf0965ae12e23879b5f5464f38e92fce8073354341e4b3b76fa3d878351efe7d01e617121955284cfd002ab087fba1a0726ec0b4f5 @@ -16593,24 +16766,13 @@ __metadata: languageName: node linkType: hard -"postcss-value-parser@npm:^4.0.2, postcss-value-parser@npm:^4.1.0": +"postcss-value-parser@npm:^4.1.0": version: 4.2.0 resolution: "postcss-value-parser@npm:4.2.0" checksum: 10c0/f4142a4f56565f77c1831168e04e3effd9ffcc5aebaf0f538eee4b2d465adfd4b85a44257bb48418202a63806a7da7fe9f56c330aebb3cac898e46b4cbf49161 languageName: node linkType: hard -"postcss@npm:8.4.31": - version: 8.4.31 - resolution: "postcss@npm:8.4.31" - dependencies: - nanoid: "npm:^3.3.6" - picocolors: "npm:^1.0.0" - source-map-js: "npm:^1.0.2" - checksum: 10c0/748b82e6e5fc34034dcf2ae88ea3d11fd09f69b6c50ecdd3b4a875cfc7cdca435c958b211e2cb52355422ab6fccb7d8f2f2923161d7a1b281029e4a913d59acf - languageName: node - linkType: hard - "postcss@npm:^8.4.19, postcss@npm:^8.4.38": version: 8.4.38 resolution: "postcss@npm:8.4.38" @@ -16903,7 +17065,7 @@ __metadata: languageName: node linkType: hard -"range-parser@npm:~1.2.1": +"range-parser@npm:^1.2.0, range-parser@npm:~1.2.1": version: 1.2.1 resolution: "range-parser@npm:1.2.1" checksum: 10c0/96c032ac2475c8027b7a4e9fe22dc0dfe0f6d90b85e496e0f016fbdb99d6d066de0112e680805075bd989905e2123b3b3d002765149294dce0c1f7f01fcc2ea0 @@ -16941,7 +17103,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.13.1, react-is@npm:^16.7.0": +"react-is@npm:^16.13.1": version: 16.13.1 resolution: "react-is@npm:16.13.1" checksum: 10c0/33977da7a5f1a287936a0c85639fec6ca74f4f15ef1e59a6bc20338fc73dc69555381e211f7a3529b8150a1f71e4225525b41b60b52965bda53ce7d47377ada1 @@ -17284,6 +17446,70 @@ __metadata: languageName: node linkType: hard +"remix-auth-auth0@npm:1.10.0": + version: 1.10.0 + resolution: "remix-auth-auth0@npm:1.10.0" + dependencies: + remix-auth-oauth2: "npm:1.10.0" + peerDependencies: + "@remix-run/server-runtime": 1.x || 2.x + remix-auth: 3.x + checksum: 10c0/86d0170c80cd9f7c3e99a3342bedf3642e2e806c9a953c543dde2bb1da348ae1c238d8ecda11794b3539508863ccb1243b8f82e706c7fe8461680a94145a8208 + languageName: node + linkType: hard + +"remix-auth-oauth2@npm:1.10.0": + version: 1.10.0 + resolution: "remix-auth-oauth2@npm:1.10.0" + dependencies: + debug: "npm:^4.3.4" + peerDependencies: + "@remix-run/server-runtime": ^1.0.0 || ^2.0.0 + remix-auth: ^3.6.0 + checksum: 10c0/88d7f0da6052f484e21892355ac3cf7f58b6c53f25f5da74f18390556b4acec86bf3e349442c3e705150ff2655ee43e46b6da1730ef1bb1ec3f04349b73e2e06 + languageName: node + linkType: hard + +"remix-auth-oauth2@npm:1.11.2": + version: 1.11.2 + resolution: "remix-auth-oauth2@npm:1.11.2" + dependencies: + debug: "npm:^4.3.4" + uuid: "npm:^9.0.1" + peerDependencies: + "@remix-run/server-runtime": ^1.0.0 || ^2.0.0 + remix-auth: ^3.6.0 + checksum: 10c0/382cfcc05d4261d98f34b4d1af79f4b526718b2ff4713c374f4a811f08340b52903458b06d98266de40ab5b786326004417d48a05f38f8a10058ee5f0c2066f5 + languageName: node + linkType: hard + +"remix-auth@npm:3.6.0": + version: 3.6.0 + resolution: "remix-auth@npm:3.6.0" + dependencies: + uuid: "npm:^8.3.2" + peerDependencies: + "@remix-run/react": ^1.0.0 || ^2.0.0 + "@remix-run/server-runtime": ^1.0.0 || ^2.0.0 + checksum: 10c0/2b9d9f5ad02e7addbf2082d0968b8a23cb7569d68c322b713b35864e21028ceca9d554c36e33f42e7ece04c826a08411e120fdc827595cee3932facd5071fcf5 + languageName: node + linkType: hard + +"remix-flat-routes@npm:0.6.4": + version: 0.6.4 + resolution: "remix-flat-routes@npm:0.6.4" + dependencies: + "@remix-run/v1-route-convention": "npm:^0.1.3" + fs-extra: "npm:^11.1.1" + minimatch: "npm:^5.1.0" + peerDependencies: + "@remix-run/dev": ^1.15.0 || ^2 + bin: + migrate-flat-routes: dist/cli.js + checksum: 10c0/84a2c19be980e63eaabdbe8684d24be39bb5d02cb80c9fd23a1c5676784350cb21a35a935de8952eb12dfb64856a17f8238cfb679ca5d8b7cc6e5cd8268389f8 + languageName: node + linkType: hard + "remix-hono@npm:0.0.16": version: 0.0.16 resolution: "remix-hono@npm:0.0.16" @@ -17358,7 +17584,7 @@ __metadata: languageName: node linkType: hard -"resolve-alpn@npm:^1.0.0": +"resolve-alpn@npm:^1.0.0, resolve-alpn@npm:^1.2.0": version: 1.2.1 resolution: "resolve-alpn@npm:1.2.1" checksum: 10c0/b70b29c1843bc39781ef946c8cd4482e6d425976599c0f9c138cec8209e4e0736161bf39319b01676a847000085dfdaf63583c6fb4427bf751a10635bd2aa0c4 @@ -17461,6 +17687,15 @@ __metadata: languageName: node linkType: hard +"responselike@npm:^3.0.0": + version: 3.0.0 + resolution: "responselike@npm:3.0.0" + dependencies: + lowercase-keys: "npm:^3.0.0" + checksum: 10c0/8af27153f7e47aa2c07a5f2d538cb1e5872995f0e9ff77def858ecce5c3fe677d42b824a62cde502e56d275ab832b0a8bd350d5cd6b467ac0425214ac12ae658 + languageName: node + linkType: hard + "restore-cursor@npm:^3.1.0": version: 3.1.0 resolution: "restore-cursor@npm:3.1.0" @@ -17795,7 +18030,7 @@ __metadata: languageName: node linkType: hard -"set-cookie-parser@npm:^2.4.6, set-cookie-parser@npm:^2.4.8, set-cookie-parser@npm:^2.6.0": +"set-cookie-parser@npm:^2.4.8, set-cookie-parser@npm:^2.6.0": version: 2.6.0 resolution: "set-cookie-parser@npm:2.6.0" checksum: 10c0/739da029f0e56806a103fcd5501d9c475e19e77bd8274192d7ae5c374ae714a82bba9a7ac00b0330a18227c5644b08df9e442240527be578f5a6030f9bb2bb80 @@ -17842,13 +18077,6 @@ __metadata: languageName: node linkType: hard -"shallowequal@npm:1.1.0": - version: 1.1.0 - resolution: "shallowequal@npm:1.1.0" - checksum: 10c0/b926efb51cd0f47aa9bc061add788a4a650550bbe50647962113a4579b60af2abe7b62f9b02314acc6f97151d4cf87033a2b15fc20852fae306d1a095215396c - languageName: node - linkType: hard - "shebang-command@npm:^1.2.0": version: 1.2.0 resolution: "shebang-command@npm:1.2.0" @@ -18306,23 +18534,7 @@ __metadata: languageName: node linkType: hard -"strict-event-emitter@npm:^0.2.4": - version: 0.2.8 - resolution: "strict-event-emitter@npm:0.2.8" - dependencies: - events: "npm:^3.3.0" - checksum: 10c0/6891e19fea4f0289e4da2fe7050d85906eaca7f774aa38fe674f0e58fdece1b63b868614fa23974c4cb862aa99358caa987523b705fdfff4639231c62e384394 - languageName: node - linkType: hard - -"strict-event-emitter@npm:^0.4.3": - version: 0.4.6 - resolution: "strict-event-emitter@npm:0.4.6" - checksum: 10c0/d0231ef081cb1937b1445da59a1ec202d1c097d825c504f398600532490a4104e200b0dce4137467a8eaac5f8f9718d01c99869687afad78cad3b14c4b2e6a39 - languageName: node - linkType: hard - -"strict-event-emitter@npm:^0.5.1": +"strict-event-emitter@npm:^0.5.0, strict-event-emitter@npm:^0.5.1": version: 0.5.1 resolution: "strict-event-emitter@npm:0.5.1" checksum: 10c0/f5228a6e6b6393c57f52f62e673cfe3be3294b35d6f7842fc24b172ae0a6e6c209fa83241d0e433fc267c503bc2f4ffdbe41a9990ff8ffd5ac425ec0489417f7 @@ -18592,33 +18804,6 @@ __metadata: languageName: node linkType: hard -"styled-components@npm:6.1.8": - version: 6.1.8 - resolution: "styled-components@npm:6.1.8" - dependencies: - "@emotion/is-prop-valid": "npm:1.2.1" - "@emotion/unitless": "npm:0.8.0" - "@types/stylis": "npm:4.2.0" - css-to-react-native: "npm:3.2.0" - csstype: "npm:3.1.2" - postcss: "npm:8.4.31" - shallowequal: "npm:1.1.0" - stylis: "npm:4.3.1" - tslib: "npm:2.5.0" - peerDependencies: - react: ">= 16.8.0" - react-dom: ">= 16.8.0" - checksum: 10c0/fafe4b9198d5d7980c2358821d1a89f86200d55c8eec03670cf12cf43b8a05a77eafaf0872cd85821f68238308e0f5c9d9aa43a62e6987c65b70baa2c3277ab8 - languageName: node - linkType: hard - -"stylis@npm:4.3.1": - version: 4.3.1 - resolution: "stylis@npm:4.3.1" - checksum: 10c0/33e8ebd2bfa5f0bd0215f718dc2d3be896e1d00c5bcaeb9a4ae03cf239db6867af9eee230f57229bf1c29499357073ba3e6b547484ba1db2f5de1e8be7d4eee9 - languageName: node - linkType: hard - "superjson@npm:^2.2.1": version: 2.2.1 resolution: "superjson@npm:2.2.1" @@ -19061,7 +19246,7 @@ __metadata: languageName: node linkType: hard -"tsconfig-paths@npm:^4.0.0, tsconfig-paths@npm:^4.1.2": +"tsconfig-paths@npm:4.2.0, tsconfig-paths@npm:^4.0.0, tsconfig-paths@npm:^4.1.2": version: 4.2.0 resolution: "tsconfig-paths@npm:4.2.0" dependencies: @@ -19072,13 +19257,6 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.5.0": - version: 2.5.0 - resolution: "tslib@npm:2.5.0" - checksum: 10c0/e32fc99cc730dd514e53c44e668d76016e738f0bcc726aad5dbd2d335cf19b87a95a9b1e4f0a9993e370f1d702b5e471cdd4acabcac428a3099d496b9af2021e - languageName: node - linkType: hard - "tslib@npm:2.6.2, tslib@npm:^2.0.0, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.5.2, tslib@npm:^2.6.1, tslib@npm:^2.6.2, tslib@npm:~2.6.0": version: 2.6.2 resolution: "tslib@npm:2.6.2" @@ -19132,6 +19310,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:4.17.0": + version: 4.17.0 + resolution: "type-fest@npm:4.17.0" + checksum: 10c0/7c474dca230b351f184fed07c037a9440d10c10f2570b1f591bded4760361d89efbeec0185038dde6557b3ea6622dba3579d8b36d5415b89ec9efbc8781a6f22 + languageName: node + linkType: hard + "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -19160,13 +19345,6 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^2.19.0": - version: 2.19.0 - resolution: "type-fest@npm:2.19.0" - checksum: 10c0/a5a7ecf2e654251613218c215c7493574594951c08e52ab9881c9df6a6da0aeca7528c213c622bc374b4e0cb5c443aa3ab758da4e3c959783ce884c3194e12cb - languageName: node - linkType: hard - "type-fest@npm:^4.9.0": version: 4.15.0 resolution: "type-fest@npm:4.15.0" @@ -19174,7 +19352,7 @@ __metadata: languageName: node linkType: hard -"type-is@npm:~1.6.18": +"type-is@npm:^1.6.18, type-is@npm:~1.6.18": version: 1.6.18 resolution: "type-is@npm:1.6.18" dependencies: @@ -19621,7 +19799,7 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^9.0.0": +"uuid@npm:9.0.1, uuid@npm:^9.0.0, uuid@npm:^9.0.1": version: 9.0.1 resolution: "uuid@npm:9.0.1" bin: @@ -19630,6 +19808,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^8.3.1, uuid@npm:^8.3.2": + version: 8.3.2 + resolution: "uuid@npm:8.3.2" + bin: + uuid: dist/bin/uuid + checksum: 10c0/bcbb807a917d374a49f475fae2e87fdca7da5e5530820ef53f65ba1d12131bd81a92ecf259cc7ce317cbe0f289e7d79fdfebcef9bfa3087c8c8a2fa304c9be54 + languageName: node + linkType: hard + "uvu@npm:^0.5.0": version: 0.5.6 resolution: "uvu@npm:0.5.6" @@ -19717,9 +19904,9 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:1.5.1": - version: 1.5.1 - resolution: "vite-node@npm:1.5.1" +"vite-node@npm:1.5.2": + version: 1.5.2 + resolution: "vite-node@npm:1.5.2" dependencies: cac: "npm:^6.7.14" debug: "npm:^4.3.4" @@ -19728,7 +19915,7 @@ __metadata: vite: "npm:^5.0.0" bin: vite-node: vite-node.mjs - checksum: 10c0/d3591d9c30fd949ec590183ff234c114b9a676349cc54a83c2ee9eec449ab77aa45302aa9465d5a849d83d4d76721755634e030582289033f2ef5a74b4890929 + checksum: 10c0/a5e90ae2b3ec912fbdf22ecf10f1b0d769e2fd1f24c5e4090488be03068b994dbcf9bea492d5c5fbde77f45a0e328e90a48a9ecdcb5eab30709e6d221aa0c7bd languageName: node linkType: hard @@ -19827,15 +20014,15 @@ __metadata: languageName: node linkType: hard -"vitest@npm:1.5.1": - version: 1.5.1 - resolution: "vitest@npm:1.5.1" +"vitest@npm:1.5.2": + version: 1.5.2 + resolution: "vitest@npm:1.5.2" dependencies: - "@vitest/expect": "npm:1.5.1" - "@vitest/runner": "npm:1.5.1" - "@vitest/snapshot": "npm:1.5.1" - "@vitest/spy": "npm:1.5.1" - "@vitest/utils": "npm:1.5.1" + "@vitest/expect": "npm:1.5.2" + "@vitest/runner": "npm:1.5.2" + "@vitest/snapshot": "npm:1.5.2" + "@vitest/spy": "npm:1.5.2" + "@vitest/utils": "npm:1.5.2" acorn-walk: "npm:^8.3.2" chai: "npm:^4.3.10" debug: "npm:^4.3.4" @@ -19849,13 +20036,13 @@ __metadata: tinybench: "npm:^2.5.1" tinypool: "npm:^0.8.3" vite: "npm:^5.0.0" - vite-node: "npm:1.5.1" + vite-node: "npm:1.5.2" why-is-node-running: "npm:^2.2.2" peerDependencies: "@edge-runtime/vm": "*" "@types/node": ^18.0.0 || >=20.0.0 - "@vitest/browser": 1.5.1 - "@vitest/ui": 1.5.1 + "@vitest/browser": 1.5.2 + "@vitest/ui": 1.5.2 happy-dom: "*" jsdom: "*" peerDependenciesMeta: @@ -19873,7 +20060,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 10c0/85f6b9250ca370b4ddc3daef5431b82d8d8cb4f64f04b7d8b53f9fad9bd93d2771ddf561d5e0b3a078b666e7d9dbdc9826e43968d58fc14c894ce7c6de2d665f + checksum: 10c0/1ad3a33d3ab5faeb4baa9c9ba62b34e94c00a6e140ba2a8589224d6b9db89e3a3d6753d1d1ecb85cbcb0f9023b22d8066dfde7f31e1733484f2ea5cf640f4969 languageName: node linkType: hard @@ -19895,7 +20082,7 @@ __metadata: languageName: node linkType: hard -"web-encoding@npm:1.1.5, web-encoding@npm:^1.1.5": +"web-encoding@npm:1.1.5": version: 1.1.5 resolution: "web-encoding@npm:1.1.5" dependencies: @@ -20334,7 +20521,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^17.0.0, yargs@npm:^17.3.1, yargs@npm:^17.6.2, yargs@npm:^17.7.2": +"yargs@npm:^17.0.0, yargs@npm:^17.6.2, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: