From 500efc8d04ec9580f0346ef3327699955b2d93fb Mon Sep 17 00:00:00 2001 From: Jonas Daniels Date: Thu, 30 Jan 2025 15:50:12 -0800 Subject: [PATCH] tw:login --- apps/login/.gitignore | 41 ++ apps/login/README.md | 36 ++ apps/login/eslint.config.mjs | 16 + apps/login/next.config.ts | 28 ++ apps/login/package.json | 33 ++ apps/login/postcss.config.mjs | 8 + apps/login/public/tw-login.js | 144 +++++++ apps/login/src/app/api/request/route.salty | 36 ++ apps/login/src/app/favicon.ico | Bin 0 -> 15406 bytes apps/login/src/app/globals.css | 163 ++++++++ apps/login/src/app/layout.tsx | 37 ++ apps/login/src/app/page.tsx | 115 ++++++ apps/login/src/app/providers.tsx | 11 + apps/login/tailwind.config.ts | 18 + apps/login/tsconfig.json | 27 ++ package.json | 4 +- pnpm-lock.yaml | 426 ++++++++++++++++++++- turbo.json | 4 + 18 files changed, 1133 insertions(+), 14 deletions(-) create mode 100644 apps/login/.gitignore create mode 100644 apps/login/README.md create mode 100644 apps/login/eslint.config.mjs create mode 100644 apps/login/next.config.ts create mode 100644 apps/login/package.json create mode 100644 apps/login/postcss.config.mjs create mode 100644 apps/login/public/tw-login.js create mode 100644 apps/login/src/app/api/request/route.salty create mode 100644 apps/login/src/app/favicon.ico create mode 100644 apps/login/src/app/globals.css create mode 100644 apps/login/src/app/layout.tsx create mode 100644 apps/login/src/app/page.tsx create mode 100644 apps/login/src/app/providers.tsx create mode 100644 apps/login/tailwind.config.ts create mode 100644 apps/login/tsconfig.json diff --git a/apps/login/.gitignore b/apps/login/.gitignore new file mode 100644 index 00000000000..5ef6a520780 --- /dev/null +++ b/apps/login/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/apps/login/README.md b/apps/login/README.md new file mode 100644 index 00000000000..e215bc4ccf1 --- /dev/null +++ b/apps/login/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/apps/login/eslint.config.mjs b/apps/login/eslint.config.mjs new file mode 100644 index 00000000000..f5b76f3927b --- /dev/null +++ b/apps/login/eslint.config.mjs @@ -0,0 +1,16 @@ +import { dirname } from "node:path"; +import { fileURLToPath } from "node:url"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const compat = new FlatCompat({ + baseDirectory: __dirname, +}); + +const eslintConfig = [ + ...compat.extends("next/core-web-vitals", "next/typescript"), +]; + +export default eslintConfig; diff --git a/apps/login/next.config.ts b/apps/login/next.config.ts new file mode 100644 index 00000000000..5739e8a7b4a --- /dev/null +++ b/apps/login/next.config.ts @@ -0,0 +1,28 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + /* config options here */ + async headers() { + return [ + { + source: "/api/request", + headers: [ + { + key: "Access-Control-Allow-Origin", + value: "*", // Set your origin + }, + { + key: "Access-Control-Allow-Methods", + value: "GET, POST, PUT, DELETE, OPTIONS", + }, + { + key: "Access-Control-Allow-Headers", + value: "Content-Type, Authorization", + }, + ], + }, + ]; + }, +}; + +export default nextConfig; diff --git a/apps/login/package.json b/apps/login/package.json new file mode 100644 index 00000000000..c27c22b56d7 --- /dev/null +++ b/apps/login/package.json @@ -0,0 +1,33 @@ +{ + "name": "thirdweb-login", + "version": "0.1.0", + "private": true, + "scripts": { + "preinstall": "npx only-allow pnpm", + "dev": "next dev --turbopack", + "build": "next build", + "start": "next start", + "format": "biome format ./src --write", + "lint": "biome check ./src && knip && eslint ./src", + "fix": "biome check ./src --fix && eslint ./src --fix", + "typecheck": "tsc --noEmit", + "knip": "knip" + }, + "dependencies": { + "next": "15.1.6", + "react": "19.0.0", + "react-dom": "19.0.0", + "thirdweb": "workspace:*" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@types/node": "22.10.10", + "@types/react": "19.0.8", + "@types/react-dom": "19.0.3", + "eslint": "^9", + "eslint-config-next": "15.1.6", + "postcss": "8.5.1", + "tailwindcss": "3.4.17", + "typescript": "5.7.3" + } +} diff --git a/apps/login/postcss.config.mjs b/apps/login/postcss.config.mjs new file mode 100644 index 00000000000..1a69fd2a450 --- /dev/null +++ b/apps/login/postcss.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + tailwindcss: {}, + }, +}; + +export default config; diff --git a/apps/login/public/tw-login.js b/apps/login/public/tw-login.js new file mode 100644 index 00000000000..6905b177f87 --- /dev/null +++ b/apps/login/public/tw-login.js @@ -0,0 +1,144 @@ +(() => { + const { targetId, clientId, baseUrl } = getSetup(); + + // the code to verify login was not tampered with + let code = ""; + + const USER_ADDRESS_KEY = "tw.login:userAddress"; + const SESSION_KEY_ADDRESS_KEY = "tw.login:sessionKeyAddress"; + + function main() { + // check if redirected first, this sets up the logged in state if it was from redirect + const params = parseURLHash(new URL(window.location)); + console.log(params); + // TECHNICALLY this should verify the code... but can't do that without backend of some sort + if (params) { + // reset the code + code = ""; + // write the userAddress to local storage + localStorage.setItem(USER_ADDRESS_KEY, params.userAddress); + // write the sessionKeyAddress to local storage + localStorage.setItem(SESSION_KEY_ADDRESS_KEY, params.sessionKeyAddress); + // reset the URL hash + window.location.hash = ""; + } + + const userAddress = localStorage.getItem(USER_ADDRESS_KEY); + const sessionKeyAddress = localStorage.getItem(SESSION_KEY_ADDRESS_KEY); + + if (userAddress && sessionKeyAddress) { + // handle logged in state + handleIsLoggedIn(); + } else { + // handle not logged in state + handleNotLoggedIn(); + } + } + + function handleIsLoggedIn() { + console.log("handleIsLoggedIn"); + + window.thirdweb = { + isLoggedIn: true, + getAddress: () => getAddress(), + logout: () => { + window.localStorage.removeItem(USER_ADDRESS_KEY); + window.localStorage.removeItem(SESSION_KEY_ADDRESS_KEY); + window.location.reload(); + }, + makeRequest: async () => { + const res = await fetch(`${baseUrl}/api/request`, { + method: "POST", + body: JSON.stringify({ + userAddress: getAddress(), + sessionKeyAddress: getSessionKeyAddress(), + }), + }); + const data = await res.json(); + console.log(data); + }, + }; + } + + function handleNotLoggedIn() { + window.thirdweb = { login: onLogin, isLoggedIn: false }; + } + + function onLogin() { + code = window.crypto.getRandomValues(new Uint8Array(4)).join(""); + // redirect to the login page + const redirect = new URL(baseUrl); + redirect.searchParams.set("code", code); + redirect.searchParams.set("clientId", clientId); + redirect.searchParams.set("redirect", window.location.href); + window.location.href = redirect.href; + } + + function getAddress() { + return localStorage.getItem(USER_ADDRESS_KEY); + } + + function getSessionKeyAddress() { + return localStorage.getItem(SESSION_KEY_ADDRESS_KEY); + } + + // utils + + function getSetup() { + const el = document.currentScript; + if (!el) { + throw new Error("Could not find script element"); + } + const baseUrl = new URL(el.src).origin; + const dataset = el.dataset; + const targetId = dataset.target || "tw-login"; + const clientId = dataset.clientId; + if (!clientId) { + throw new Error("Missing client-id"); + } + return { targetId, clientId, baseUrl }; + } + + /** + * @param {URL} url + * @returns null | { [key: string]: string } + */ + function parseURLHash(url) { + if (!url.hash) { + return null; + } + try { + return decodeHash(url.hash); + } catch { + // if this fails, invalid data -> return null + return null; + } + } + + /** + * Decodes a URL hash string to extract the three keys. + * + * @param {string} hash - A string like "#eyJrZXkxIjoiVmFsdWU..." + * @returns {{ userAddress: string, sessionKeyAddress: string, code: string }} An object with the three keys + */ + function decodeHash(hash) { + // Remove the "#" prefix, if present. + const base64Data = hash.startsWith("#") ? hash.slice(1) : hash; + + // Decode the Base64 string, then parse the JSON. + const jsonString = atob(base64Data); + const data = JSON.parse(jsonString); + + // data should have the shape { userAddress, sessionKeyAddress, code }. + if ( + "userAddress" in data && + "sessionKeyAddress" in data && + "code" in data + ) { + return data; + } + return null; + } + + main(); +})(); diff --git a/apps/login/src/app/api/request/route.salty b/apps/login/src/app/api/request/route.salty new file mode 100644 index 00000000000..b3bbb679d10 --- /dev/null +++ b/apps/login/src/app/api/request/route.salty @@ -0,0 +1,36 @@ +import { type NextRequest, NextResponse } from "next/server"; + +export const POST = async (req: NextRequest) => { + const body = await req.json(); + const userAddress = body.userAddress; + const sessionKeyAddress = body.sessionKeyAddress; + if (!userAddress || !sessionKeyAddress) { + return NextResponse.json( + { + message: "Missing userAddress or sessionKeyAddress", + }, + { status: 400 }, + ); + } + const url = `${ENGINE_URL}/contract/84532/0x638263e3eAa3917a53630e61B1fBa685308024fa/erc1155/claim-to`; + + console.log("url", url); + + const res = await fetch(url, { + method: "POST", + headers: { + authorization: `Bearer ${ACCESS_TOKEN}`, + "x-account-address": userAddress, + "x-backend-wallet-address": sessionKeyAddress, + "content-type": "application/json", + }, + body: JSON.stringify({ + receiver: userAddress, + tokenId: "0", + quantity: "1", + }), + }); + const data = await res.json(); + + return NextResponse.json(data, { status: res.status }); +}; diff --git a/apps/login/src/app/favicon.ico b/apps/login/src/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..55c8bb8b3da7cf10e2b883b9a092afec3c95740e GIT binary patch literal 15406 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 literal 0 HcmV?d00001 diff --git a/apps/login/src/app/globals.css b/apps/login/src/app/globals.css new file mode 100644 index 00000000000..d94e43201c0 --- /dev/null +++ b/apps/login/src/app/globals.css @@ -0,0 +1,163 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +html { + /* scroll-behavior: smooth; */ + font-feature-settings: "cv02", "cv03", "cv04", "cv11"; + font-feature-settings: "rlig" 1, "calt" 0; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + font-variation-settings: normal; + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: transparent; +} + +@layer base { + :root { + --radius: 0.5rem; + --sticky-top-height: 70px; + } + + :root, + [data-theme="dark"] { + /* bg - neutral */ + --background: 0 0% 0%; + --card: 0 0% 3.92%; + --popover: 0 0% 0%; + --secondary: 0 0% 11%; + --muted: 0 0% 11%; + --accent: 0 0% 11%; + --inverted: 0 0% 100%; + + /* bg - colorful */ + --primary: 221 83% 54%; + --destructive: 360 72% 51%; + + /* Text */ + --foreground: 0 0% 98%; + --card-foreground: 0 0% 98%; + --popover-foreground: 0 0% 98%; + --primary-foreground: 0 0% 100%; + --secondary-foreground: 0 0% 98%; + --muted-foreground: 0 0% 63%; + --accent-foreground: 0 0% 98%; + --destructive-foreground: 0 0% 100%; + --link-foreground: 215.88 100% 65%; + --warning-text: 38 92% 50%; + --destructive-text: 360 72% 55%; + --success-text: 142 75% 50%; + --inverted-foreground: 0 0% 0%; + + /* Borders */ + --border: 0 0% 15%; + --active-border: 0 0% 22%; + --ring: 0 0% 30%; + --input: 0 0% 15%; + } + + [data-theme="light"] { + /* bg - neutral */ + --background: 0 0% 98%; + --popover: 0 0% 100%; + --card: 0 0% 100%; + --secondary: 0 0% 90%; + --muted: 0 0% 93%; + --accent: 0 0% 93%; + --inverted: 0 0 0%; + + /* bg - colorful */ + --primary: 221 83% 54%; + --destructive: 360 72% 51%; + + /* Text */ + --foreground: 0 0% 4%; + --card-foreground: 0 0% 4%; + --popover-foreground: 240 10% 4%; + --primary-foreground: 0 0% 100%; + --secondary-foreground: 0 0% 4%; + --muted-foreground: 0 0% 40%; + --accent-foreground: 0 0% 9%; + --destructive-foreground: 0 0% 100%; + --inverted-foreground: 0 0% 100%; + --link-foreground: 221.21deg 83.19% 53.33%; + --success-text: 142.09 70.56% 35.29%; + --warning-text: 38 92% 40%; + --destructive-text: 357.15deg 100% 68.72%; + + /* Borders */ + --border: 0 0% 85%; + --active-border: 0 0% 70%; + --input: 0 0% 85%; + --ring: 0 0% 80%; + } +} + +/* If no data-theme is added in body, its in dark theme */ +body:not([data-theme="light"]) .light-only { + display: none; +} + +[data-theme="light"] .dark-only { + display: none; +} + +code span { + color: var(--code-dark-color); +} + +body[data-theme="light"] code span { + color: var(--code-light-color); +} + +/* @layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} */ + +.styled-scrollbar::-webkit-scrollbar { + width: 0.5rem; + height: 0.5rem; +} + +@media (max-width: 640px) { + .styled-scrollbar::-webkit-scrollbar { + width: 0; + height: 0; + } +} + +.styled-scrollbar::-webkit-scrollbar-thumb { + border-radius: 0.5rem; + transition: color 200ms ease; + background: var(--border); +} + +.styled-scrollbar::-webkit-scrollbar-thumb:hover { + background: hsl(var(--foreground)); +} + +.styled-scrollbar::-webkit-scrollbar-track { + background-color: transparent; +} + +button { + -webkit-tap-highlight-color: transparent; +} + +::selection { + background: hsl(var(--foreground)); + color: hsl(var(--background)); +} + +.hide-scrollbar { + scrollbar-width: none; /* Firefox */ +} + +.hide-scrollbar::-webkit-scrollbar { + display: none; /* Safari and Chrome */ +} diff --git a/apps/login/src/app/layout.tsx b/apps/login/src/app/layout.tsx new file mode 100644 index 00000000000..3f33940031e --- /dev/null +++ b/apps/login/src/app/layout.tsx @@ -0,0 +1,37 @@ +import type { Metadata } from "next"; +import { Fira_Code, Inter } from "next/font/google"; + +import "./globals.css"; +import { Providers } from "./providers"; + +const sansFont = Inter({ + subsets: ["latin"], + variable: "--font-sans", + weight: "variable", +}); + +const monoFont = Fira_Code({ + subsets: ["latin"], + variable: "--font-mono", + weight: "variable", +}); + +export const metadata: Metadata = { + title: "login with thirdweb", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + {children} + + + ); +} diff --git a/apps/login/src/app/page.tsx b/apps/login/src/app/page.tsx new file mode 100644 index 00000000000..ced5878657a --- /dev/null +++ b/apps/login/src/app/page.tsx @@ -0,0 +1,115 @@ +"use client"; + +import { useSearchParams } from "next/navigation"; +import { createThirdwebClient, getContract, sendTransaction } from "thirdweb"; +import { baseSepolia } from "thirdweb/chains"; +import { addSessionKey, isActiveSigner } from "thirdweb/extensions/erc4337"; +import { ConnectEmbed, useActiveAccount } from "thirdweb/react"; +import { isContractDeployed } from "thirdweb/utils"; + +const sesionKeySignerAddress = "0x6f700ba0258886411D2536399624EAa7158d1742"; + +const client = createThirdwebClient({ + clientId: "e9ba48c289e0cc3d06a23bfd370cc111", +}); + +export default function Page() { + const account = useActiveAccount(); + + const onAccept = async () => { + if (!account) { + throw new Error("No account found"); + } + const accountContract = getContract({ + address: account.address, + // hard coded for now + chain: baseSepolia, + client, + }); + let hasSesionKey = false; + // check if already added + const accountDeployed = await isContractDeployed(accountContract); + if (accountDeployed) { + hasSesionKey = await isActiveSigner({ + contract: accountContract, + signer: sesionKeySignerAddress, + }); + } + // if not added, send tx to add the session key + if (!hasSesionKey) { + const transaction = addSessionKey({ + account, + contract: accountContract, + sessionKeyAddress: sesionKeySignerAddress, + // hard coded for now + permissions: { approvedTargets: "*" }, + }); + await sendTransaction({ + account, + transaction, + }); + } + }; + + const searchParams = useSearchParams(); + const code = searchParams.get("code"); + const clientId = searchParams.get("clientId"); + const redirect = searchParams.get("redirect"); + + console.log({ code, clientId, redirect }); + + return ( +
+ {account ? ( +
+

Permissions Screen

+
    +
  • perm 1
  • +
  • perm 2
  • +
  • perm 3
  • +
+ +
+ ) : ( + + )} +
+ ); +} + +function encodeHash( + userAddress: string, + sessionKeyAddress: string, + code: string, +) { + // Create an object with the three keys. + const data = { userAddress, sessionKeyAddress, code }; + + // Convert to JSON and then Base64-encode the result. + const jsonString = JSON.stringify(data); + const base64Data = btoa(jsonString); + + // Return as a hash string (with the "#" prefix). + return `#${base64Data}`; +} diff --git a/apps/login/src/app/providers.tsx b/apps/login/src/app/providers.tsx new file mode 100644 index 00000000000..5b30433c549 --- /dev/null +++ b/apps/login/src/app/providers.tsx @@ -0,0 +1,11 @@ +"use client"; + +import { ThirdwebProvider } from "thirdweb/react"; + +export const Providers = ({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) => { + return {children}; +}; diff --git a/apps/login/tailwind.config.ts b/apps/login/tailwind.config.ts new file mode 100644 index 00000000000..109807be0f7 --- /dev/null +++ b/apps/login/tailwind.config.ts @@ -0,0 +1,18 @@ +import type { Config } from "tailwindcss"; + +export default { + content: [ + "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", + "./src/components/**/*.{js,ts,jsx,tsx,mdx}", + "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: { + colors: { + background: "var(--background)", + foreground: "var(--foreground)", + }, + }, + }, + plugins: [], +} satisfies Config; diff --git a/apps/login/tsconfig.json b/apps/login/tsconfig.json new file mode 100644 index 00000000000..c1334095f87 --- /dev/null +++ b/apps/login/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/package.json b/package.json index 2c5cd977ba0..85e1b910b5d 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ }, "scripts": { "preinstall": "npx only-allow pnpm", - "lint": "pnpm dlx sherif@latest -i remark-gfm && turbo run lint", + "lint": "pnpm dlx sherif@latest -i remark-gfm -i eslint && turbo run lint", "storybook:react": "turbo run storybook --filter=./packages/*", - "prefix": "pnpm dlx sherif@latest -i remark-gfm --fix", + "prefix": "pnpm dlx sherif@latest -i remark-gfm -i eslint --fix", "fix": "turbo run fix", "wallet-ui": "turbo run dev --filter=./apps/wallet-ui --filter=./packages/thirdweb", "wallet-ui:build": "turbo run build --filter=./apps/wallet-ui --filter=./packages/thirdweb", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6b75293f39a..67e4cf276d1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -411,6 +411,49 @@ importers: specifier: 5.7.3 version: 5.7.3 + apps/login: + dependencies: + next: + specifier: 15.1.6 + version: 15.1.6(@babel/core@7.26.7)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: + specifier: 19.0.0 + version: 19.0.0 + react-dom: + specifier: 19.0.0 + version: 19.0.0(react@19.0.0) + thirdweb: + specifier: workspace:* + version: link:../../packages/thirdweb + devDependencies: + '@eslint/eslintrc': + specifier: ^3 + version: 3.2.0 + '@types/node': + specifier: 22.10.10 + version: 22.10.10 + '@types/react': + specifier: 19.0.8 + version: 19.0.8 + '@types/react-dom': + specifier: 19.0.3 + version: 19.0.3(@types/react@19.0.8) + eslint: + specifier: ^9 + version: 9.19.0(jiti@2.4.2) + eslint-config-next: + specifier: 15.1.6 + version: 15.1.6(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) + postcss: + specifier: 8.5.1 + version: 8.5.1 + tailwindcss: + specifier: 3.4.17 + version: 3.4.17(ts-node@10.9.2(@swc/core@1.10.11(@swc/helpers@0.5.15))(@types/node@22.10.10)(typescript@5.7.3)) + typescript: + specifier: 5.7.3 + version: 5.7.3 + apps/playground-web: dependencies: '@abstract-foundation/agw-client': @@ -2922,14 +2965,38 @@ packages: resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint/config-array@0.19.1': + resolution: {integrity: sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.10.0': + resolution: {integrity: sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/eslintrc@2.1.4': resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/eslintrc@3.2.0': + resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@8.57.0': resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/js@9.19.0': + resolution: {integrity: sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.5': + resolution: {integrity: sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.5': + resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ethereumjs/common@3.2.0': resolution: {integrity: sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA==} @@ -3174,6 +3241,14 @@ packages: peerDependencies: react-hook-form: ^7.0.0 + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -3187,6 +3262,14 @@ packages: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.1': + resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} + engines: {node: '>=18.18'} + '@img/sharp-darwin-arm64@0.33.5': resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -4221,7 +4304,7 @@ packages: '@radix-ui/react-context@1.1.1': resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==} peerDependencies: - '@types/react': '*' + '@types/react': npm:types-react@19.0.0-rc.1 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': @@ -4278,7 +4361,7 @@ packages: '@radix-ui/react-focus-guards@1.1.1': resolution: {integrity: sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==} peerDependencies: - '@types/react': '*' + '@types/react': npm:types-react@19.0.0-rc.1 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': @@ -4553,7 +4636,7 @@ packages: '@radix-ui/react-use-controllable-state@1.1.0': resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} peerDependencies: - '@types/react': '*' + '@types/react': npm:types-react@19.0.0-rc.1 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': @@ -4598,7 +4681,7 @@ packages: '@radix-ui/react-use-size@1.1.0': resolution: {integrity: sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==} peerDependencies: - '@types/react': '*' + '@types/react': npm:types-react@19.0.0-rc.1 react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': @@ -8629,6 +8712,10 @@ packages: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@8.2.0: + resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -8643,6 +8730,20 @@ packages: deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true + eslint@9.19.0: + resolution: {integrity: sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -9006,6 +9107,10 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + file-selector@2.1.2: resolution: {integrity: sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==} engines: {node: '>= 12'} @@ -9075,6 +9180,10 @@ packages: resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} engines: {node: ^10.12.0 || >=12.0.0} + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + flat@6.0.1: resolution: {integrity: sha512-/3FfIa8mbrg3xE7+wAhWeV+bd7L2Mof+xtZb5dRDKZ+wDvYJK4WDYeIOuOhre5Yv5aQObZrlbRmk3RTSiuQBtw==} engines: {node: '>=18'} @@ -9344,6 +9453,10 @@ packages: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -17611,8 +17724,25 @@ snapshots: eslint: 8.57.0 eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.4.1(eslint@9.19.0(jiti@2.4.2))': + dependencies: + eslint: 9.19.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.12.1': {} + '@eslint/config-array@0.19.1': + dependencies: + '@eslint/object-schema': 2.1.5 + debug: 4.4.0(supports-color@8.1.1) + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/core@0.10.0': + dependencies: + '@types/json-schema': 7.0.15 + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 @@ -17627,8 +17757,31 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/eslintrc@3.2.0': + dependencies: + ajv: 6.12.6 + debug: 4.4.0(supports-color@8.1.1) + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + '@eslint/js@8.57.0': {} + '@eslint/js@9.19.0': {} + + '@eslint/object-schema@2.1.5': {} + + '@eslint/plugin-kit@0.2.5': + dependencies: + '@eslint/core': 0.10.0 + levn: 0.4.1 + '@ethereumjs/common@3.2.0': dependencies: '@ethereumjs/util': 9.1.0 @@ -18301,6 +18454,13 @@ snapshots: dependencies: react-hook-form: 7.54.2(react@19.0.0) + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 @@ -18313,6 +18473,10 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.1': {} + '@img/sharp-darwin-arm64@0.33.5': optionalDependencies: '@img/sharp-libvips-darwin-arm64': 1.0.4 @@ -23040,6 +23204,24 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/eslint-plugin@7.14.1(@typescript-eslint/parser@7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/scope-manager': 7.14.1 + '@typescript-eslint/type-utils': 7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 7.14.1 + eslint: 9.19.0(jiti@2.4.2) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 1.4.3(typescript@5.7.3) + optionalDependencies: + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3)': dependencies: '@typescript-eslint/scope-manager': 7.14.1 @@ -23053,6 +23235,19 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/scope-manager': 7.14.1 + '@typescript-eslint/types': 7.14.1 + '@typescript-eslint/typescript-estree': 7.14.1(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 7.14.1 + debug: 4.4.0(supports-color@8.1.1) + eslint: 9.19.0(jiti@2.4.2) + optionalDependencies: + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@7.14.1': dependencies: '@typescript-eslint/types': 7.14.1 @@ -23075,6 +23270,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@typescript-eslint/typescript-estree': 7.14.1(typescript@5.7.3) + '@typescript-eslint/utils': 7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) + debug: 4.4.0(supports-color@8.1.1) + eslint: 9.19.0(jiti@2.4.2) + ts-api-utils: 1.4.3(typescript@5.7.3) + optionalDependencies: + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/types@6.19.0': {} '@typescript-eslint/types@7.14.1': {} @@ -23136,6 +23343,17 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 7.14.1 + '@typescript-eslint/types': 7.14.1 + '@typescript-eslint/typescript-estree': 7.14.1(typescript@5.7.3) + eslint: 9.19.0(jiti@2.4.2) + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/utils@8.22.0(eslint@8.57.0)(typescript@5.7.3)': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.0) @@ -26100,8 +26318,8 @@ snapshots: '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.7.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.0) eslint-plugin-react: 7.37.4(eslint@8.57.0) eslint-plugin-react-hooks: 5.1.0(eslint@8.57.0) @@ -26112,6 +26330,26 @@ snapshots: - eslint-plugin-import-x - supports-color + eslint-config-next@15.1.6(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3): + dependencies: + '@next/eslint-plugin-next': 15.1.6 + '@rushstack/eslint-patch': 1.10.5 + '@typescript-eslint/eslint-plugin': 7.14.1(@typescript-eslint/parser@7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) + eslint: 9.19.0(jiti@2.4.2) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@9.19.0(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.19.0(jiti@2.4.2)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.19.0(jiti@2.4.2)) + eslint-plugin-react: 7.37.4(eslint@9.19.0(jiti@2.4.2)) + eslint-plugin-react-hooks: 5.1.0(eslint@9.19.0(jiti@2.4.2)) + optionalDependencies: + typescript: 5.7.3 + transitivePeerDependencies: + - eslint-import-resolver-webpack + - eslint-plugin-import-x + - supports-color + eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 @@ -26120,7 +26358,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint@8.57.0))(eslint@8.57.0): + eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.0): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.0(supports-color@8.1.1) @@ -26132,7 +26370,23 @@ snapshots: is-glob: 4.0.3 stable-hash: 0.0.4 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.0) + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@9.19.0(jiti@2.4.2)): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.4.0(supports-color@8.1.1) + enhanced-resolve: 5.18.0 + eslint: 9.19.0(jiti@2.4.2) + fast-glob: 3.3.3 + get-tsconfig: 4.10.0 + is-bun-module: 1.3.0 + is-glob: 4.0.3 + stable-hash: 0.0.4 + optionalDependencies: + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.19.0(jiti@2.4.2)) transitivePeerDependencies: - supports-color @@ -26157,18 +26411,29 @@ snapshots: - bluebird - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.7.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.0) + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.12.0(@typescript-eslint/parser@7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@9.19.0(jiti@2.4.2)))(eslint@9.19.0(jiti@2.4.2)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) + eslint: 9.19.0(jiti@2.4.2) + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@9.19.0(jiti@2.4.2)) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -26179,7 +26444,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -26197,6 +26462,35 @@ snapshots: - eslint-import-resolver-webpack - supports-color + eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@9.19.0(jiti@2.4.2)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.19.0(jiti@2.4.2) + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@9.19.0(jiti@2.4.2)))(eslint@9.19.0(jiti@2.4.2)) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 7.7.0 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 7.14.1(eslint@9.19.0(jiti@2.4.2))(typescript@5.7.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.0): dependencies: aria-query: 5.3.2 @@ -26216,6 +26510,25 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 + eslint-plugin-jsx-a11y@6.10.2(eslint@9.19.0(jiti@2.4.2)): + dependencies: + aria-query: 5.3.2 + array-includes: 3.1.8 + array.prototype.flatmap: 1.3.3 + ast-types-flow: 0.0.8 + axe-core: 4.10.2 + axobject-query: 4.1.0 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + eslint: 9.19.0(jiti@2.4.2) + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + safe-regex-test: 1.1.0 + string.prototype.includes: 2.0.1 + eslint-plugin-markdown@3.0.1(eslint@8.57.0): dependencies: eslint: 8.57.0 @@ -26254,6 +26567,10 @@ snapshots: dependencies: eslint: 8.57.0 + eslint-plugin-react-hooks@5.1.0(eslint@9.19.0(jiti@2.4.2)): + dependencies: + eslint: 9.19.0(jiti@2.4.2) + eslint-plugin-react@7.37.4(eslint@8.57.0): dependencies: array-includes: 3.1.8 @@ -26276,6 +26593,28 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-plugin-react@7.37.4(eslint@9.19.0(jiti@2.4.2)): + dependencies: + array-includes: 3.1.8 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.1 + eslint: 9.19.0(jiti@2.4.2) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 7.7.0 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + eslint-plugin-storybook@0.11.2(eslint@8.57.0)(typescript@5.7.3): dependencies: '@storybook/csf': 0.1.13 @@ -26304,6 +26643,11 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 + eslint-scope@8.2.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + eslint-visitor-keys@3.4.3: {} eslint-visitor-keys@4.2.0: {} @@ -26351,6 +26695,53 @@ snapshots: transitivePeerDependencies: - supports-color + eslint@9.19.0(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.19.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.19.1 + '@eslint/core': 0.10.0 + '@eslint/eslintrc': 3.2.0 + '@eslint/js': 9.19.0 + '@eslint/plugin-kit': 0.2.5 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.1 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.0(supports-color@8.1.1) + escape-string-regexp: 4.0.0 + eslint-scope: 8.2.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + + espree@10.3.0: + dependencies: + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 + espree@9.6.1: dependencies: acorn: 8.14.0 @@ -26911,6 +27302,10 @@ snapshots: dependencies: flat-cache: 3.2.0 + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + file-selector@2.1.2: dependencies: tslib: 2.8.1 @@ -26993,6 +27388,11 @@ snapshots: keyv: 4.5.4 rimraf: 3.0.2 + flat-cache@4.0.1: + dependencies: + flatted: 3.3.2 + keyv: 4.5.4 + flat@6.0.1: {} flatted@3.3.2: {} @@ -27275,6 +27675,8 @@ snapshots: dependencies: type-fest: 0.20.2 + globals@14.0.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 diff --git a/turbo.json b/turbo.json index a3f1de415ef..5dc43c5de05 100644 --- a/turbo.json +++ b/turbo.json @@ -14,6 +14,10 @@ "outputs": ["typedoc/**"], "dependsOn": ["^build"] }, + "thirdweb-login#build": { + "outputs": [".next/**", "!.next/cache/**"], + "dependsOn": ["^build"] + }, "thirdweb-dashboard#build": { "env": [ "SENTRY_AUTH_TOKEN",