From f403c6043257a4093f6314dce3152d3acfaedc38 Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Thu, 30 Oct 2025 13:53:06 +0000 Subject: [PATCH 1/4] migration begins --- apps/ensadmin/.cta.json | 14 + apps/ensadmin/.env.local.example | 14 - apps/ensadmin/.gitignore | 50 +- apps/ensadmin/READMETSR.md | 301 +++++ apps/ensadmin/biome.json | 53 + apps/ensadmin/biome.jsonc | 17 - apps/ensadmin/components.json | 9 +- apps/ensadmin/index.html | 20 + apps/ensadmin/next.config.ts | 10 - apps/ensadmin/package.json | 66 +- apps/ensadmin/postcss.config.mjs | 8 - .../app/api/_ai/ens-subgraph-gql-schema.ts | 453 -------- apps/ensadmin/src/app/api/_ai/route.ts | 205 ---- .../ensadmin/src/app/api/subgraph/loading.tsx | 9 - apps/ensadmin/src/app/connection/page.tsx | 5 - apps/ensadmin/src/app/globals.css | 171 --- .../src/app/inspect/visualizer/page.tsx | 11 - .../name/_components/AdditionalRecords.tsx | 1 - .../src/app/name/_components/Addresses.tsx | 1 - .../_components/NameDetailPageContent.tsx | 1 - .../_components/NameDetailPageSkeleton.tsx | 1 - .../app/name/_components/ProfileHeader.tsx | 1 - .../name/_components/ProfileInformation.tsx | 1 - .../src/app/name/_components/SocialLinks.tsx | 1 - apps/ensadmin/src/app/status/error.tsx | 17 - .../src/components/connection/index.tsx | 2 - .../components/graphiql-editor/components.tsx | 34 +- .../indexing-status-loading.tsx | 2 - .../indexing-status/indexing-status.tsx | 2 - .../src/components/layout-wrapper.tsx | 15 +- apps/ensadmin/src/components/link.tsx | 29 +- apps/ensadmin/src/components/nav-main.tsx | 39 +- .../recent-registrations/components.tsx | 52 +- apps/ensadmin/src/components/ui/sonner.tsx | 10 +- .../src/hooks/use-connection-url-param.tsx | 29 +- .../src/hooks/use-connections-library.tsx | 58 +- apps/ensadmin/src/lib/env.ts | 37 +- apps/ensadmin/src/main.tsx | 42 + apps/ensadmin/src/reportWebVitals.ts | 13 + apps/ensadmin/src/routeTree.gen.ts | 252 ++++ apps/ensadmin/src/routes/__root.tsx | 41 + .../page.tsx => routes/api/subgraph.tsx} | 9 +- apps/ensadmin/src/routes/connection.tsx | 11 + .../src/{app/page.tsx => routes/index.tsx} | 27 +- .../inspect/primary-name.tsx} | 31 +- .../inspect/primary-names.tsx} | 27 +- .../page.tsx => routes/inspect/records.tsx} | 27 +- .../src/routes/inspect/visualizer.tsx | 15 + .../{app/name/page.tsx => routes/name.tsx} | 29 +- .../page.tsx => routes/registration.tsx} | 8 +- .../status/page.tsx => routes/status.tsx} | 17 +- apps/ensadmin/src/styles.css | 147 +++ apps/ensadmin/tailwind.config.ts | 69 -- apps/ensadmin/tsconfig.json | 46 +- apps/ensadmin/vite.config.ts | 23 + pnpm-lock.yaml | 1025 +++++++++++++---- 56 files changed, 2142 insertions(+), 1466 deletions(-) create mode 100644 apps/ensadmin/.cta.json delete mode 100644 apps/ensadmin/.env.local.example create mode 100644 apps/ensadmin/READMETSR.md create mode 100644 apps/ensadmin/biome.json delete mode 100644 apps/ensadmin/biome.jsonc create mode 100644 apps/ensadmin/index.html delete mode 100644 apps/ensadmin/next.config.ts delete mode 100644 apps/ensadmin/postcss.config.mjs delete mode 100644 apps/ensadmin/src/app/api/_ai/ens-subgraph-gql-schema.ts delete mode 100644 apps/ensadmin/src/app/api/_ai/route.ts delete mode 100644 apps/ensadmin/src/app/api/subgraph/loading.tsx delete mode 100644 apps/ensadmin/src/app/connection/page.tsx delete mode 100644 apps/ensadmin/src/app/globals.css delete mode 100644 apps/ensadmin/src/app/inspect/visualizer/page.tsx delete mode 100644 apps/ensadmin/src/app/status/error.tsx create mode 100644 apps/ensadmin/src/main.tsx create mode 100644 apps/ensadmin/src/reportWebVitals.ts create mode 100644 apps/ensadmin/src/routeTree.gen.ts create mode 100644 apps/ensadmin/src/routes/__root.tsx rename apps/ensadmin/src/{app/api/subgraph/page.tsx => routes/api/subgraph.tsx} (86%) create mode 100644 apps/ensadmin/src/routes/connection.tsx rename apps/ensadmin/src/{app/page.tsx => routes/index.tsx} (58%) rename apps/ensadmin/src/{app/inspect/primary-name/page.tsx => routes/inspect/primary-name.tsx} (87%) rename apps/ensadmin/src/{app/inspect/primary-names/page.tsx => routes/inspect/primary-names.tsx} (84%) rename apps/ensadmin/src/{app/inspect/records/page.tsx => routes/inspect/records.tsx} (85%) create mode 100644 apps/ensadmin/src/routes/inspect/visualizer.tsx rename apps/ensadmin/src/{app/name/page.tsx => routes/name.tsx} (84%) rename apps/ensadmin/src/{app/registration/page.tsx => routes/registration.tsx} (50%) rename apps/ensadmin/src/{app/status/page.tsx => routes/status.tsx} (50%) create mode 100644 apps/ensadmin/src/styles.css delete mode 100644 apps/ensadmin/tailwind.config.ts create mode 100644 apps/ensadmin/vite.config.ts diff --git a/apps/ensadmin/.cta.json b/apps/ensadmin/.cta.json new file mode 100644 index 000000000..df994696d --- /dev/null +++ b/apps/ensadmin/.cta.json @@ -0,0 +1,14 @@ +{ + "projectName": "ensadmin-vite", + "mode": "file-router", + "typescript": true, + "tailwind": true, + "packageManager": "pnpm", + "addOnOptions": {}, + "git": true, + "version": 1, + "framework": "react-cra", + "chosenAddOns": [ + "biome" + ] +} \ No newline at end of file diff --git a/apps/ensadmin/.env.local.example b/apps/ensadmin/.env.local.example deleted file mode 100644 index 04584a75a..000000000 --- a/apps/ensadmin/.env.local.example +++ /dev/null @@ -1,14 +0,0 @@ -# The ENSAdmin public service URL -# Optional. The ENSAdmin web application needs this value to reference static assets. -# Note: it's recommended to explicitly set it. If not explicitly set, -# the application will try guess this value. For example, if hosting in Vercel, -# the Vercel env and Vercel URLs will be used. If not provided, -# the default public URL will be based on localhost and PORT. -ENSADMIN_PUBLIC_URL=http://localhost:4173 - -# Server's library of ENSNode URLs offered as connection options in the connection picker. -# Optional. If not set, defaults to `DEFAULT_SERVER_CONNECTION_LIBRARY` (https://api.alpha.ensnode.io,https://api.alpha-sepolia.ensnode.io,https://api.mainnet.ensnode.io,https://api.sepolia.ensnode.io,https://api.holesky.ensnode.io). -# Note: it must be a comma-separated list of URLs that are accessible from a web browser -# (i.e. it cannot be a hostname in a docker network) -# Note: if a user doesn't explicitly select an ENSNode connection then, by default, ENSAdmin will automatically select the first URL in this list as the ENSNode instance to connect the user to. -NEXT_PUBLIC_SERVER_CONNECTION_LIBRARY=https://api.alpha.ensnode.io,https://api.alpha-sepolia.ensnode.io,https://api.mainnet.ensnode.io,https://api.sepolia.ensnode.io,https://api.holesky.ensnode.io diff --git a/apps/ensadmin/.gitignore b/apps/ensadmin/.gitignore index 3639bc528..58b859832 100644 --- a/apps/ensadmin/.gitignore +++ b/apps/ensadmin/.gitignore @@ -1,42 +1,10 @@ -# 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 +node_modules .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* -!.env*.example - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts +dist +dist-ssr +*.local +count.txt +.env +.nitro +.tanstack +.wrangler diff --git a/apps/ensadmin/READMETSR.md b/apps/ensadmin/READMETSR.md new file mode 100644 index 000000000..641f154c1 --- /dev/null +++ b/apps/ensadmin/READMETSR.md @@ -0,0 +1,301 @@ +Welcome to your new TanStack app! + +# Getting Started + +To run this application: + +```bash +pnpm install +pnpm start +``` + +# Building For Production + +To build this application for production: + +```bash +pnpm build +``` + +## Testing + +This project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with: + +```bash +pnpm test +``` + +## Styling + +This project uses [Tailwind CSS](https://tailwindcss.com/) for styling. + + +## Linting & Formatting + +This project uses [Biome](https://biomejs.dev/) for linting and formatting. The following scripts are available: + + +```bash +pnpm lint +pnpm format +pnpm check +``` + + + +## Routing +This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`. + +### Adding A Route + +To add a new route to your application just add another a new file in the `./src/routes` directory. + +TanStack will automatically generate the content of the route file for you. + +Now that you have two routes you can use a `Link` component to navigate between them. + +### Adding Links + +To use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`. + +```tsx +import { Link } from "@tanstack/react-router"; +``` + +Then anywhere in your JSX you can use it like so: + +```tsx +About +``` + +This will create a link that will navigate to the `/about` route. + +More information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent). + +### Using A Layout + +In the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `` component. + +Here is an example layout that includes a header: + +```tsx +import { Outlet, createRootRoute } from '@tanstack/react-router' +import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' + +import { Link } from "@tanstack/react-router"; + +export const Route = createRootRoute({ + component: () => ( + <> +
+ +
+ + + + ), +}) +``` + +The `` component is not required so you can remove it if you don't want it in your layout. + +More information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts). + + +## Data Fetching + +There are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered. + +For example: + +```tsx +const peopleRoute = createRoute({ + getParentRoute: () => rootRoute, + path: "/people", + loader: async () => { + const response = await fetch("https://swapi.dev/api/people"); + return response.json() as Promise<{ + results: { + name: string; + }[]; + }>; + }, + component: () => { + const data = peopleRoute.useLoaderData(); + return ( +
    + {data.results.map((person) => ( +
  • {person.name}
  • + ))} +
+ ); + }, +}); +``` + +Loaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters). + +### React-Query + +React-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze. + +First add your dependencies: + +```bash +pnpm add @tanstack/react-query @tanstack/react-query-devtools +``` + +Next we'll need to create a query client and provider. We recommend putting those in `main.tsx`. + +```tsx +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +// ... + +const queryClient = new QueryClient(); + +// ... + +if (!rootElement.innerHTML) { + const root = ReactDOM.createRoot(rootElement); + + root.render( + + + + ); +} +``` + +You can also add TanStack Query Devtools to the root route (optional). + +```tsx +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; + +const rootRoute = createRootRoute({ + component: () => ( + <> + + + + + ), +}); +``` + +Now you can use `useQuery` to fetch your data. + +```tsx +import { useQuery } from "@tanstack/react-query"; + +import "./App.css"; + +function App() { + const { data } = useQuery({ + queryKey: ["people"], + queryFn: () => + fetch("https://swapi.dev/api/people") + .then((res) => res.json()) + .then((data) => data.results as { name: string }[]), + initialData: [], + }); + + return ( +
+
    + {data.map((person) => ( +
  • {person.name}
  • + ))} +
+
+ ); +} + +export default App; +``` + +You can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview). + +## State Management + +Another common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project. + +First you need to add TanStack Store as a dependency: + +```bash +pnpm add @tanstack/store +``` + +Now let's create a simple counter in the `src/App.tsx` file as a demonstration. + +```tsx +import { useStore } from "@tanstack/react-store"; +import { Store } from "@tanstack/store"; +import "./App.css"; + +const countStore = new Store(0); + +function App() { + const count = useStore(countStore); + return ( +
+ +
+ ); +} + +export default App; +``` + +One of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates. + +Let's check this out by doubling the count using derived state. + +```tsx +import { useStore } from "@tanstack/react-store"; +import { Store, Derived } from "@tanstack/store"; +import "./App.css"; + +const countStore = new Store(0); + +const doubledStore = new Derived({ + fn: () => countStore.state * 2, + deps: [countStore], +}); +doubledStore.mount(); + +function App() { + const count = useStore(countStore); + const doubledCount = useStore(doubledStore); + + return ( +
+ +
Doubled - {doubledCount}
+
+ ); +} + +export default App; +``` + +We use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating. + +Once we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook. + +You can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest). + +# Demo files + +Files prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed. + +# Learn More + +You can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com). diff --git a/apps/ensadmin/biome.json b/apps/ensadmin/biome.json new file mode 100644 index 000000000..f5f4ace61 --- /dev/null +++ b/apps/ensadmin/biome.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.3.1/schema.json", + "extends": "//", + "css": { + "parser": { + "tailwindDirectives": true + } + }, + "linter": { + "rules": { + "recommended": false, + "style": { + "noNonNullAssertion": "on" + } + } + } +} + +// { +// "$schema": "https://biomejs.dev/schemas/2.2.4/schema.json", +// "vcs": { +// "enabled": false, +// "clientKind": "git", +// "useIgnoreFile": false +// }, +// "files": { +// "ignoreUnknown": false, +// "includes": [ +// "**/src/**/*", +// "**/.vscode/**/*", +// "**/index.html", +// "**/vite.config.js", +// "!**/src/routeTree.gen.ts", +// "!**/src/styles.css" +// ] +// }, +// "formatter": { +// "enabled": true, +// "indentStyle": "tab" +// }, +// "assist": { "actions": { "source": { "organizeImports": "on" } } }, +// "linter": { +// "enabled": true, +// "rules": { +// "recommended": true +// } +// }, +// "javascript": { +// "formatter": { +// "quoteStyle": "double" +// } +// } +// } diff --git a/apps/ensadmin/biome.jsonc b/apps/ensadmin/biome.jsonc deleted file mode 100644 index 9a2ce4db6..000000000 --- a/apps/ensadmin/biome.jsonc +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "https://biomejs.dev/schemas/2.3.1/schema.json", - "extends": "//", - "css": { - "parser": { - "tailwindDirectives": true - } - }, - "linter": { - "rules": { - "recommended": false, - "style": { - "noNonNullAssertion": "on" - } - } - } -} diff --git a/apps/ensadmin/components.json b/apps/ensadmin/components.json index 4e3cb4705..67b287a0d 100644 --- a/apps/ensadmin/components.json +++ b/apps/ensadmin/components.json @@ -1,15 +1,16 @@ { "$schema": "https://ui.shadcn.com/schema.json", "style": "new-york", - "rsc": true, + "rsc": false, "tsx": true, "tailwind": { - "config": "tailwind.config.ts", - "css": "src/app/globals.css", + "config": "", + "css": "src/styles.css", "baseColor": "slate", "cssVariables": true, "prefix": "" }, + "iconLibrary": "lucide", "aliases": { "components": "@/components", "utils": "@/lib/utils", @@ -17,5 +18,5 @@ "lib": "@/lib", "hooks": "@/hooks" }, - "iconLibrary": "lucide" + "registries": {} } diff --git a/apps/ensadmin/index.html b/apps/ensadmin/index.html new file mode 100644 index 000000000..e4cf0f5a2 --- /dev/null +++ b/apps/ensadmin/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + + Create TanStack App - ensadmin-vite + + +
+ + + diff --git a/apps/ensadmin/next.config.ts b/apps/ensadmin/next.config.ts deleted file mode 100644 index 1fe68bf39..000000000 --- a/apps/ensadmin/next.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { NextConfig } from "next"; - -const nextConfig: NextConfig = { - // Use Single Page App mode only for ENSAdmin - output: "export", - // Enable source maps in production - productionBrowserSourceMaps: true, -}; - -export default nextConfig; diff --git a/apps/ensadmin/package.json b/apps/ensadmin/package.json index 411b09282..d55cfa5a9 100644 --- a/apps/ensadmin/package.json +++ b/apps/ensadmin/package.json @@ -1,25 +1,15 @@ { - "name": "ensadmin", - "version": "0.36.0", + "name": "ensadmin-vite", "private": true, "type": "module", - "description": "Explore the ENS Protocol like never before", - "license": "MIT", - "packageManager": "pnpm@10.20.0", - "repository": { - "type": "git", - "url": "git+https://github.com/namehash/ensnode.git", - "directory": "apps/ensadmin" - }, - "homepage": "https://github.com/namehash/ensnode/tree/main/apps/ensadmin", "scripts": { - "dev": "next dev -p 4173", - "build": "next build", - "start": "serve out -l 4173", - "lint": "biome check --write .", - "lint:ci": "biome ci", - "typecheck": "tsc --noEmit", - "test": "vitest" + "dev": "vite --port 3000", + "build": "vite build && tsc", + "serve": "vite preview", + "test": "vitest run", + "format": "biome format", + "lint": "biome lint", + "check": "biome check" }, "dependencies": { "@ensnode/datasources": "workspace:*", @@ -45,34 +35,46 @@ "@radix-ui/react-slot": "^1.1.2", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-tooltip": "^1.1.8", - "@tanstack/react-query": "^5.66.9", + "@radix-ui/react-slot": "^1.2.3", "@xyflow/react": "^12.4.4", "boring-avatars": "^1.11.2", + "@tailwindcss/vite": "^4.1.16", + "@tanstack/react-devtools": "^0.7.0", + "@tanstack/react-query": "^5.90.5", + "@tanstack/react-query-devtools": "^5.90.2", + "@tanstack/react-router": "^1.132.0", + "@tanstack/react-router-devtools": "^1.132.0", + "@tanstack/router-plugin": "^1.132.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "constate": "^3.3.3", "date-fns": "catalog:", "graphiql": "5.2.0", "graphql": "^16.10.0", - "lucide-react": "^0.548.0", - "next": "16.0.1", - "next-themes": "^0.4.6", - "react": "^19", - "react-dom": "^19", + "lucide-react": "^0.545.0", + "react": "^19.2.0", + "react-dom": "^19.2.0", "rooks": "^8.4.0", "serve": "^14.2.5", "sonner": "^2.0.3", - "tailwind-merge": "^3.0.2", + "tailwind-merge": "^3.3.1", + "tailwindcss": "^4.1.5", "tailwindcss-animate": "^1.0.7", "viem": "catalog:" }, "devDependencies": { - "@types/node": "^22", - "@types/react": "^19", - "@types/react-dom": "^19", - "postcss": "^8", - "tailwindcss": "^3.4.17", - "typescript": "^5", - "vitest": "catalog:" + "@biomejs/biome": "2.2.4", + "@testing-library/dom": "^10.4.0", + "@testing-library/react": "^16.2.0", + "@types/node": "^22.18.13", + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.0", + "@vitejs/plugin-react": "^5.0.4", + "jsdom": "^27.0.0", + "tw-animate-css": "^1.4.0", + "typescript": "^5.7.2", + "vite": "^7.1.7", + "vitest": "catalog:", + "web-vitals": "^5.1.0" } } diff --git a/apps/ensadmin/postcss.config.mjs b/apps/ensadmin/postcss.config.mjs deleted file mode 100644 index 1a69fd2a4..000000000 --- a/apps/ensadmin/postcss.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -/** @type {import('postcss-load-config').Config} */ -const config = { - plugins: { - tailwindcss: {}, - }, -}; - -export default config; diff --git a/apps/ensadmin/src/app/api/_ai/ens-subgraph-gql-schema.ts b/apps/ensadmin/src/app/api/_ai/ens-subgraph-gql-schema.ts deleted file mode 100644 index b6e02af78..000000000 --- a/apps/ensadmin/src/app/api/_ai/ens-subgraph-gql-schema.ts +++ /dev/null @@ -1,453 +0,0 @@ -// export const ensSubgraphSchemaGql = ` -// type Domain @entity { -// "The namehash of the name" -// id: ID! -// "The human readable name, if known. Unknown portions replaced with hash in square brackets (eg, foo.[1234].eth)" -// name: String -// "The human readable label name (imported from CSV), if known" -// labelName: String -// "keccak256(labelName)" -// labelhash: Bytes -// "The namehash (id) of the parent name" -// parent: Domain -// "Can count domains from length of array" -// subdomains: [Domain!]! @derivedFrom(field: "parent") -// "The number of subdomains" -// subdomainCount: Int! -// "Address logged from current resolver, if any" -// resolvedAddress: Account - -// "The resolver that controls the domain's settings" -// resolver: Resolver -// "The time-to-live (TTL) value of the domain's records" -// ttl: BigInt - -// "Indicates whether the domain has been migrated to a new registrar" -// isMigrated: Boolean! -// "The time when the domain was created" -// createdAt: BigInt! - -// "The account that owns the domain" -// owner: Account! -// "The account that owns the ERC721 NFT for the domain" -// registrant: Account -// "The account that owns the wrapped domain" -// wrappedOwner: Account - -// "The expiry date for the domain, from either the registration, or the wrapped domain if PCC is burned" -// expiryDate: BigInt - -// "The registration associated with the domain" -// registration: Registration @derivedFrom(field: "domain") -// "The wrapped domain associated with the domain" -// wrappedDomain: WrappedDomain @derivedFrom(field: "domain") - -// "The events associated with the domain" -// events: [DomainEvent!]! @derivedFrom(field: "domain") -// } - -// interface DomainEvent { -// "The unique identifier of the event" -// id: ID! -// "The domain name associated with the event" -// domain: Domain! -// "The block number at which the event occurred" -// blockNumber: Int! -// "The transaction hash of the transaction that triggered the event" -// transactionID: Bytes! -// } - -// type Transfer implements DomainEvent @entity { -// "The unique identifier of the event" -// id: ID! -// "The domain name associated with the event" -// domain: Domain! -// "The block number at which the event occurred" -// blockNumber: Int! -// "The transaction hash of the transaction that triggered the event" -// transactionID: Bytes! -// "The account that owns the domain after the transfer" -// owner: Account! -// } - -// type NewOwner implements DomainEvent @entity { -// "The unique identifier of the event" -// id: ID! -// "The parent domain of the domain name associated with the event" -// parentDomain: Domain! -// "The domain name associated with the event" -// domain: Domain! -// "The block number at which the event occurred" -// blockNumber: Int! -// "The transaction hash of the transaction that triggered the event" -// transactionID: Bytes! -// "The new account that owns the domain" -// owner: Account! -// } - -// type NewResolver implements DomainEvent @entity { -// "The unique identifier of the event" -// id: ID! -// "The domain name associated with the event" -// domain: Domain! -// "The block number at which the event occurred" -// blockNumber: Int! -// "The transaction hash of the transaction that triggered the event" -// transactionID: Bytes! -// "The new resolver contract address associated with the domain" -// resolver: Resolver! -// } - -// type NewTTL implements DomainEvent @entity { -// "The unique identifier of the event" -// id: ID! -// "The domain name associated with the event" -// domain: Domain! -// "The block number at which the event occurred" -// blockNumber: Int! -// "The transaction hash of the transaction that triggered the event" -// transactionID: Bytes! -// "The new TTL value (in seconds) associated with the domain" -// ttl: BigInt! -// } - -// type WrappedTransfer implements DomainEvent @entity { -// "The unique identifier of the event" -// id: ID! -// "The domain name associated with the event" -// domain: Domain! -// "The block number at which the event occurred" -// blockNumber: Int! -// "The transaction hash of the transaction that triggered the event" -// transactionID: Bytes! -// "The account that owns the wrapped domain after the transfer" -// owner: Account! -// } - -// type NameWrapped implements DomainEvent @entity { -// "The unique identifier of the wrapped domain" -// id: ID! -// "The domain name associated with the wrapped domain" -// domain: Domain! -// "The block number at which the wrapped domain was wrapped" -// blockNumber: Int! -// "The transaction hash of the transaction that wrapped the domain" -// transactionID: Bytes! -// "The human-readable name of the wrapped domain" -// name: String -// "The number of fuses associated with the wrapped domain" -// fuses: Int! -// "The account that owns the wrapped domain" -// owner: Account! -// "The expiry date of the wrapped domain registration" -// expiryDate: BigInt! -// } - -// type NameUnwrapped implements DomainEvent @entity { -// "The unique identifier of the event" -// id: ID! -// "The domain name associated with the event" -// domain: Domain! -// "The block number at which the event occurred" -// blockNumber: Int! -// "The transaction hash of the transaction that triggered the event" -// transactionID: Bytes! -// "The account that owns the domain after it was unwrapped" -// owner: Account! -// } - -// type FusesSet implements DomainEvent @entity { -// "The unique identifier of the event" -// id: ID! -// "The domain name associated with the event" -// domain: Domain! -// "The block number at which the event occurred" -// blockNumber: Int! -// "The transaction hash of the transaction that triggered the event" -// transactionID: Bytes! -// "The number of fuses associated with the domain after the set event" -// fuses: Int! -// } - -// type ExpiryExtended implements DomainEvent @entity { -// "The unique identifier of the event" -// id: ID! -// "The domain name associated with the event" -// domain: Domain! -// "The block number at which the event occurred" -// blockNumber: Int! -// "The transaction hash of the transaction that triggered the event" -// transactionID: Bytes! -// "The new expiry date associated with the domain after the extension event" -// expiryDate: BigInt! -// } - -// type Registration @entity { -// "The unique identifier of the registration" -// id: ID! -// "The domain name associated with the registration" -// domain: Domain! -// "The registration date of the domain" -// registrationDate: BigInt! -// "The expiry date of the domain" -// expiryDate: BigInt! -// "The cost associated with the domain registration" -// cost: BigInt -// "The account that registered the domain" -// registrant: Account! -// "The human-readable label name associated with the domain registration" -// labelName: String -// "The events associated with the domain registration" -// events: [RegistrationEvent!]! @derivedFrom(field: "registration") -// } - -// interface RegistrationEvent { -// "The unique identifier of the registration event" -// id: ID! -// "The registration associated with the event" -// registration: Registration! -// "The block number of the event" -// blockNumber: Int! -// "The transaction ID associated with the event" -// transactionID: Bytes! -// } - -// type NameRegistered implements RegistrationEvent @entity { -// "The unique identifier of the NameRegistered event" -// id: ID! -// "The registration associated with the event" -// registration: Registration! -// "The block number of the event" -// blockNumber: Int! -// "The transaction ID associated with the event" -// transactionID: Bytes! -// "The account that registered the name" -// registrant: Account! -// "The expiry date of the registration" -// expiryDate: BigInt! -// } - -// type NameRenewed implements RegistrationEvent @entity { -// "The unique identifier of the NameRenewed event" -// id: ID! -// "The registration associated with the event" -// registration: Registration! -// "The block number of the event" -// blockNumber: Int! -// "The transaction ID associated with the event" -// transactionID: Bytes! -// "The new expiry date of the registration" -// expiryDate: BigInt! -// } - -// type NameTransferred implements RegistrationEvent @entity { -// "The ID of the event" -// id: ID! -// "The registration associated with the event" -// registration: Registration! -// "The block number of the event" -// blockNumber: Int! -// "The transaction ID of the event" -// transactionID: Bytes! -// "The new owner of the domain" -// newOwner: Account! -// } - -// type WrappedDomain @entity { -// "unique identifier for each instance of the WrappedDomain entity" -// id: ID! -// "The domain that is wrapped by this WrappedDomain" -// domain: Domain! -// "The expiry date of the wrapped domain" -// expiryDate: BigInt! -// "The number of fuses remaining on the wrapped domain" -// fuses: Int! -// "The account that owns this WrappedDomain" -// owner: Account! -// "The name of the wrapped domain" -// name: String -// } - -// type Account @entity { -// "The unique identifier for the account" -// id: ID! -// "The domains owned by the account" -// domains: [Domain!]! @derivedFrom(field: "owner") -// "The WrappedDomains owned by the account" -// wrappedDomains: [WrappedDomain!] @derivedFrom(field: "owner") -// "The Registrations made by the account" -// registrations: [Registration!] @derivedFrom(field: "registrant") -// } - -// type Resolver @entity { -// "The unique identifier for this resolver, which is a concatenation of the resolver address and the domain namehash" -// id: ID! -// "The domain that this resolver is associated with" -// domain: Domain -// "The address of the resolver contract" -// address: Bytes! -// "The current value of the 'addr' record for this resolver, as determined by the associated events" -// addr: Account -// "The content hash for this resolver, in binary format" -// contentHash: Bytes -// "The set of observed text record keys for this resolver" -// texts: [String!] -// "The set of observed SLIP-44 coin types for this resolver" -// coinTypes: [BigInt!] -// "The events associated with this resolver" -// events: [ResolverEvent!]! @derivedFrom(field: "resolver") -// } - -// interface ResolverEvent { -// "Concatenation of block number and log ID" -// id: ID! -// "Used to derive relationships to Resolvers" -// resolver: Resolver! -// "The block number that the event occurred on" -// blockNumber: Int! -// "The transaction hash of the event" -// transactionID: Bytes! -// } - -// type AddrChanged implements ResolverEvent @entity { -// "Unique identifier for this event" -// id: ID! -// "The resolver associated with this event" -// resolver: Resolver! -// "The block number at which this event occurred" -// blockNumber: Int! -// "The transaction ID for the transaction in which this event occurred" -// transactionID: Bytes! -// "The new address associated with the resolver" -// addr: Account! -// } - -// type MulticoinAddrChanged implements ResolverEvent @entity { -// "Unique identifier for the event" -// id: ID! -// "Resolver associated with this event" -// resolver: Resolver! -// "Block number in which this event was emitted" -// blockNumber: Int! -// "Transaction ID in which this event was emitted" -// transactionID: Bytes! -// "The coin type of the changed address" -// coinType: BigInt! -// "The new address value for the given coin type" -// addr: Bytes! -// } - -// type NameChanged implements ResolverEvent @entity { -// "Concatenation of block number and log ID" -// id: ID! -// "Used to derive relationships to Resolvers" -// resolver: Resolver! -// "Block number where event occurred" -// blockNumber: Int! -// "Unique transaction ID where event occurred" -// transactionID: Bytes! -// "New ENS name value" -// name: String! -// } - -// type AbiChanged implements ResolverEvent @entity { -// "Concatenation of block number and log ID" -// id: ID! -// "Used to derive relationships to Resolvers" -// resolver: Resolver! -// "The block number at which the event was emitted" -// blockNumber: Int! -// "The transaction hash of the transaction in which the event was emitted" -// transactionID: Bytes! -// "The content type of the ABI change" -// contentType: BigInt! -// } - -// type PubkeyChanged implements ResolverEvent @entity { -// "Concatenation of block number and log ID" -// id: ID! -// "Used to derive relationships to Resolvers" -// resolver: Resolver! -// "Block number of the Ethereum block where the event occurred" -// blockNumber: Int! -// "Transaction hash of the Ethereum transaction where the event occurred" -// transactionID: Bytes! -// "The x-coordinate of the new public key" -// x: Bytes! -// "The y-coordinate of the new public key" -// y: Bytes! -// } - -// type TextChanged implements ResolverEvent @entity { -// "Concatenation of block number and log ID" -// id: ID! -// "Used to derive relationships to Resolvers" -// resolver: Resolver! -// "Block number of the Ethereum block in which the event occurred" -// blockNumber: Int! -// "Hash of the Ethereum transaction in which the event occurred" -// transactionID: Bytes! -// "The key of the text record that was changed" -// key: String! -// "The new value of the text record that was changed" -// value: String -// } - -// type ContenthashChanged implements ResolverEvent @entity { -// "Concatenation of block number and log ID" -// id: ID! -// "Used to derive relationships to Resolvers" -// resolver: Resolver! -// "The block number where the event occurred" -// blockNumber: Int! -// "The ID of the transaction where the event occurred" -// transactionID: Bytes! -// "The new content hash for the domain" -// hash: Bytes! -// } - -// type InterfaceChanged implements ResolverEvent @entity { -// "Concatenation of block number and log ID" -// id: ID! -// "Used to derive relationships to Resolvers" -// resolver: Resolver! -// "The block number in which the event occurred" -// blockNumber: Int! -// "The transaction ID for the transaction in which the event occurred" -// transactionID: Bytes! -// "The ID of the EIP-1820 interface that was changed" -// interfaceID: Bytes! -// "The address of the contract that implements the interface" -// implementer: Bytes! -// } - -// type AuthorisationChanged implements ResolverEvent @entity { -// "Unique identifier for this event" -// id: ID! -// "The resolver associated with this event" -// resolver: Resolver! -// "The block number at which the event occurred" -// blockNumber: Int! -// "The transaction hash associated with the event" -// transactionID: Bytes! -// "The owner of the authorisation" -// owner: Bytes! -// "The target of the authorisation" -// target: Bytes! -// "Whether the authorisation was added or removed" -// isAuthorized: Boolean! -// } - -// type VersionChanged implements ResolverEvent @entity { -// "Unique identifier for this event" -// id: ID! -// "The resolver associated with this event" -// resolver: Resolver! -// "The block number at which the event occurred" -// blockNumber: Int! -// "The transaction hash associated with the event" -// transactionID: Bytes! -// "The new version number of the resolver" -// version: BigInt! -// } -// `; diff --git a/apps/ensadmin/src/app/api/_ai/route.ts b/apps/ensadmin/src/app/api/_ai/route.ts deleted file mode 100644 index 07f5bfb6e..000000000 --- a/apps/ensadmin/src/app/api/_ai/route.ts +++ /dev/null @@ -1,205 +0,0 @@ -// import { AdapterAnthropic } from "@gqlpt/adapter-anthropic"; -// import { GQLPTClient } from "gqlpt"; -// import { type NextRequest } from "next/server"; -// import { ensSubgraphSchemaGql } from "./ens-subgraph-gql-schema"; - -// export async function GET(request: NextRequest) { -// const requestUrl = new URL(request.url); -// const maybePrompt = requestUrl.searchParams.get("prompt"); -// const maybeGqlApiUrl = requestUrl.searchParams.get("gqlApiUrl"); - -// let generateQueryDto: GenerateQueryDto; - -// // try to parse the request into a DTO -// try { -// generateQueryDto = getQueryGeneratorClient.parseRequest({ -// maybePrompt, -// maybeGqlApiUrl, -// }); -// } catch (error) { -// const errorMessage = error instanceof Error ? error.message : "Unknown error"; -// return Response.json({ error: `Parsing request error: ${errorMessage}` }, { status: 400 }); -// } - -// let queryGeneratorClient: QueryGeneratorClient; - -// // try to get the query generator client -// try { -// // get the optional LLM API key from the environment variable -// const llmApiKey = process.env.ANTHROPIC_API_KEY; - -// if (!llmApiKey) { -// throw new Error("ANTHROPIC_API_KEY environment variable is required but has not been set."); -// } - -// // get the query generator client for the given GQL API URL -// queryGeneratorClient = await getQueryGeneratorClient({ -// ...generateQueryDto, -// llmApiKey, -// }); -// } catch (error) { -// const errorMessage = error instanceof Error ? error.message : "Unknown error"; - -// console.error(`Query generator client error: ${errorMessage}`); -// return Response.json({ error: `Query generator client error` }, { status: 500 }); -// } - -// // try to generate the query and variables -// try { -// const generatedQueryAndVariables = await queryGeneratorClient.generateQueryAndVariables( -// generateQueryDto.prompt, -// ); -// return Response.json(generatedQueryAndVariables); -// } catch (error) { -// const errorMessage = error instanceof Error ? error.message : "Unknown error"; -// console.error(`Query generation error: ${errorMessage}`); -// return Response.json({ error: errorMessage }, { status: 500 }); -// } -// } - -// /** The max tokens to use per message */ -// const MAX_TOKENS_PER_MESSAGE = 1024; - -// /** The LLM temperature */ -// const TEMPERATURE = 0; - -// /** The system prompt to use for the LLM */ -// const SYSTEM_PROMPT = ` -// You are a helpful assistant that generates GraphQL queries and variables. - -// You will be given a prompt and a GraphQL schema. - -// You will generate a GraphQL query and variables that will be used to test the GraphQL API. - -// Always respond with the GraphQL query and variables in JSON format. - -// Always include an operation name for each generated GraphQL query. Do not forget about it under any circumstances. - -// Include useful comments in the generated GraphQL query to make it easier to understand. - -// Values such as 'vitalik.eth' or 'abc.123.com' should be interpreted as domain names. - -// Hex values with 40 hex digits (20 bytes) such as '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' should be interpreted as addresses or account id values. All addresses and account id values in your output should be formatted completely in lowercase. - -// Hex values with 64 hex digits (32 bytes) such as '0x412329d38ad88cb88b1bb6d4005cd6aa010b7bdeb55fd28f980943d423725fb1' should be interpreted as either a labelhash, or the id of a domain. All labelhash and domain id values in your output should be formatted completely in lowercase. - -// If requested to generate a query that finds domains by name, unless specifically requested to use a particular strategy such as "names ending with", default to finding name values that are an exact match. -// `; - -// /** -// * Map of GQL API URLs to query generator clients. -// */ -// const clients = new Map(); - -// interface QueryGeneratorClient extends Pick {} - -// interface GetQueryGeneratorClientOptions { -// /** The URL of the GQL API used for GQL schema introspection */ -// gqlApiUrl: URL; - -// /** The API key for the LLM */ -// llmApiKey?: string; -// } - -// /** -// * Get a query generator client for the given GQL API URL. -// * -// * @param gqlApiUrl The URL of the GQL API -// * @param llmApiKey The API key for the LLM -// * @returns query generator client -// */ -// async function getQueryGeneratorClient( -// options: GetQueryGeneratorClientOptions, -// ): Promise { -// let client = clients.get(options.gqlApiUrl.toString()); - -// if (!client) { -// // create the client if it doesn't exist yet -// client = new GQLPTClient({ -// url: options.gqlApiUrl.toString(), -// adapter: new AdapterAnthropic({ -// apiKey: options.llmApiKey, -// model: Model.Claude35Sonnet, -// systemPrompt: `${SYSTEM_PROMPT}\n\n${ensSubgraphSchemaGql}`, -// maxTokensPerMessage: MAX_TOKENS_PER_MESSAGE, -// temperature: TEMPERATURE, -// cacheControl: { -// type: "ephemeral", -// }, -// }), -// }); - -// try { -// // ensure the client is connected -// await client.connect(); -// } catch (error) { -// const errorMessage = error instanceof Error ? error.message : "Unknown error"; -// throw new Error(`Failed to connect to the LLM: ${errorMessage}`); -// } - -// // store the client in the map for future use -// clients.set(options.gqlApiUrl.toString(), client); -// } - -// return client; -// } - -// interface ParseRequestOptions { -// maybeGqlApiUrl: string | null; -// maybePrompt: string | null; -// } - -// /** -// * Parse the request URL to get the prompt and GQL API URL. -// * -// * @param requestUrl The request URL -// * @returns The prompt and GQL API URL -// * @throws {Error} If the prompt or GQL API URL was not provided -// */ -// getQueryGeneratorClient.parseRequest = function parseQueryGeneratorClientRequest( -// options: ParseRequestOptions, -// ): GenerateQueryDto { -// return GenerateQueryDto.tryParse(options.maybePrompt, options.maybeGqlApiUrl); -// }; - -// /** -// * DTO for the generateQueryAndVariables request. -// */ -// class GenerateQueryDto { -// private constructor( -// public readonly prompt: string, -// public readonly gqlApiUrl: URL, -// ) {} - -// static tryParse(maybePrompt: string | null, maybeGqlApiUrl: string | null) { -// const prompt = GenerateQueryDto.parsePrompt(maybePrompt); -// const gqlApiUrl = GenerateQueryDto.parseGqlApiUrl(maybeGqlApiUrl); - -// return new GenerateQueryDto(prompt, gqlApiUrl); -// } - -// static parsePrompt(maybePrompt: string | null) { -// if (!maybePrompt) { -// throw new Error("Prompt is required"); -// } - -// return maybePrompt; -// } - -// static parseGqlApiUrl(maybeGqlApiUrl: string | null) { -// if (!maybeGqlApiUrl) { -// throw new Error("URL is required"); -// } - -// try { -// return new URL(maybeGqlApiUrl); -// } catch (error) { -// throw new Error("Invalid URL"); -// } -// } -// } - -// enum Model { -// Claude35Sonnet = "claude-3-5-sonnet-20241022", -// Claude37Sonnet = "claude-3-7-sonnet-20250219", -// } diff --git a/apps/ensadmin/src/app/api/subgraph/loading.tsx b/apps/ensadmin/src/app/api/subgraph/loading.tsx deleted file mode 100644 index 5f38c7498..000000000 --- a/apps/ensadmin/src/app/api/subgraph/loading.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { LoadingSpinner } from "@/components/loading-spinner"; - -export default function Loading() { - return ( -
- -
- ); -} diff --git a/apps/ensadmin/src/app/connection/page.tsx b/apps/ensadmin/src/app/connection/page.tsx deleted file mode 100644 index 49bfe6874..000000000 --- a/apps/ensadmin/src/app/connection/page.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import ConnectionInfo from "@/components/connection"; - -export default function ConnectionPage() { - return ; -} diff --git a/apps/ensadmin/src/app/globals.css b/apps/ensadmin/src/app/globals.css deleted file mode 100644 index b264f211a..000000000 --- a/apps/ensadmin/src/app/globals.css +++ /dev/null @@ -1,171 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -@layer base { - :root { - --background: 0 0% 100%; - - --foreground: 222.2 84% 4.9%; - - --card: 0 0% 100%; - - --card-foreground: 222.2 84% 4.9%; - - --popover: 0 0% 100%; - - --popover-foreground: 222.2 84% 4.9%; - - --primary: 222.2 47.4% 11.2%; - - --primary-foreground: 210 40% 98%; - - --secondary: 210 40% 96.1%; - - --secondary-foreground: 222.2 47.4% 11.2%; - - --muted: 210 40% 96.1%; - - --muted-foreground: 215.4 16.3% 46.9%; - - --accent: 210 40% 96.1%; - - --accent-foreground: 222.2 47.4% 11.2%; - - --destructive: 0 84.2% 60.2%; - - --destructive-foreground: 210 40% 98%; - - --border: 214.3 31.8% 91.4%; - - --input: 214.3 31.8% 91.4%; - - --ring: 222.2 84% 4.9%; - - --chart-1: 12 76% 61%; - - --chart-2: 173 58% 39%; - - --chart-3: 197 37% 24%; - - --chart-4: 43 74% 66%; - - --chart-5: 27 87% 67%; - - --radius: 0.5rem; - - --sidebar-background: 0 0% 98%; - - --sidebar-foreground: 240 5.3% 26.1%; - - --sidebar-primary: 240 5.9% 10%; - - --sidebar-primary-foreground: 0 0% 98%; - - --sidebar-accent: 240 4.8% 95.9%; - - --sidebar-accent-foreground: 240 5.9% 10%; - - --sidebar-border: 220 13% 91%; - - --sidebar-ring: 217.2 91.2% 59.8%; - } - - .dark { - --background: 222.2 84% 4.9%; - - --foreground: 210 40% 98%; - - --card: 222.2 84% 4.9%; - - --card-foreground: 210 40% 98%; - - --popover: 222.2 84% 4.9%; - - --popover-foreground: 210 40% 98%; - - --primary: 210 40% 98%; - - --primary-foreground: 222.2 47.4% 11.2%; - - --secondary: 217.2 32.6% 17.5%; - - --secondary-foreground: 210 40% 98%; - - --muted: 217.2 32.6% 17.5%; - - --muted-foreground: 215 20.2% 65.1%; - - --accent: 217.2 32.6% 17.5%; - - --accent-foreground: 210 40% 98%; - - --destructive: 0 62.8% 30.6%; - - --destructive-foreground: 210 40% 98%; - - --border: 217.2 32.6% 17.5%; - - --input: 217.2 32.6% 17.5%; - - --ring: 212.7 26.8% 83.9%; - - --chart-1: 220 70% 50%; - - --chart-2: 160 60% 45%; - - --chart-3: 30 80% 55%; - - --chart-4: 280 65% 60%; - - --chart-5: 340 75% 55%; - - --sidebar-background: 240 5.9% 10%; - - --sidebar-foreground: 240 4.8% 95.9%; - - --sidebar-primary: 224.3 76.3% 48%; - - --sidebar-primary-foreground: 0 0% 100%; - - --sidebar-accent: 240 3.7% 15.9%; - - --sidebar-accent-foreground: 240 4.8% 95.9%; - - --sidebar-border: 240 3.7% 15.9%; - - --sidebar-ring: 217.2 91.2% 59.8%; - } -} - -@layer base { - * { - @apply border-border outline-ring/50; - } - - body { - @apply bg-background text-foreground; - } -} - -@layer base { - * { - @apply border-border; - } - body { - @apply bg-background text-foreground; - } -} - -@layer utilities { - /* Hide scrollbar for Chrome, Safari, and Opera */ - .no-scrollbar::-webkit-scrollbar { - display: none; - } - - /* Hide scrollbar for IE, Edge, and Firefox */ - .no-scrollbar { - -ms-overflow-style: none; /* IE and Edge */ - scrollbar-width: none; /* Firefox */ - } -} diff --git a/apps/ensadmin/src/app/inspect/visualizer/page.tsx b/apps/ensadmin/src/app/inspect/visualizer/page.tsx deleted file mode 100644 index 2a8050fe7..000000000 --- a/apps/ensadmin/src/app/inspect/visualizer/page.tsx +++ /dev/null @@ -1,11 +0,0 @@ -"use client"; - -import VisualizerClient from "@/components/visualizer/client"; - -export default function InspectorPage() { - return ( -
- -
- ); -} diff --git a/apps/ensadmin/src/app/name/_components/AdditionalRecords.tsx b/apps/ensadmin/src/app/name/_components/AdditionalRecords.tsx index 41c7a0abf..ab950e4a0 100644 --- a/apps/ensadmin/src/app/name/_components/AdditionalRecords.tsx +++ b/apps/ensadmin/src/app/name/_components/AdditionalRecords.tsx @@ -1,4 +1,3 @@ -"use client"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; diff --git a/apps/ensadmin/src/app/name/_components/Addresses.tsx b/apps/ensadmin/src/app/name/_components/Addresses.tsx index 5a5c13b5f..6e86150f6 100644 --- a/apps/ensadmin/src/app/name/_components/Addresses.tsx +++ b/apps/ensadmin/src/app/name/_components/Addresses.tsx @@ -1,4 +1,3 @@ -"use client"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; diff --git a/apps/ensadmin/src/app/name/_components/NameDetailPageContent.tsx b/apps/ensadmin/src/app/name/_components/NameDetailPageContent.tsx index b0b1340ab..0f47f53d9 100644 --- a/apps/ensadmin/src/app/name/_components/NameDetailPageContent.tsx +++ b/apps/ensadmin/src/app/name/_components/NameDetailPageContent.tsx @@ -1,4 +1,3 @@ -"use client"; import { ASSUME_IMMUTABLE_QUERY, useRecords } from "@ensnode/ensnode-react"; import { type Name, type ResolverRecordsSelection } from "@ensnode/ensnode-sdk"; diff --git a/apps/ensadmin/src/app/name/_components/NameDetailPageSkeleton.tsx b/apps/ensadmin/src/app/name/_components/NameDetailPageSkeleton.tsx index e514b5530..425c05e4a 100644 --- a/apps/ensadmin/src/app/name/_components/NameDetailPageSkeleton.tsx +++ b/apps/ensadmin/src/app/name/_components/NameDetailPageSkeleton.tsx @@ -1,4 +1,3 @@ -"use client"; import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Skeleton } from "@/components/ui/skeleton"; diff --git a/apps/ensadmin/src/app/name/_components/ProfileHeader.tsx b/apps/ensadmin/src/app/name/_components/ProfileHeader.tsx index dbe613799..c6ce48dbb 100644 --- a/apps/ensadmin/src/app/name/_components/ProfileHeader.tsx +++ b/apps/ensadmin/src/app/name/_components/ProfileHeader.tsx @@ -1,4 +1,3 @@ -"use client"; import type { ENSNamespaceId, Name } from "@ensnode/ensnode-sdk"; diff --git a/apps/ensadmin/src/app/name/_components/ProfileInformation.tsx b/apps/ensadmin/src/app/name/_components/ProfileInformation.tsx index f27a46e3b..e101f3e1b 100644 --- a/apps/ensadmin/src/app/name/_components/ProfileInformation.tsx +++ b/apps/ensadmin/src/app/name/_components/ProfileInformation.tsx @@ -1,4 +1,3 @@ -"use client"; import { Mail } from "lucide-react"; diff --git a/apps/ensadmin/src/app/name/_components/SocialLinks.tsx b/apps/ensadmin/src/app/name/_components/SocialLinks.tsx index 220289558..12b73fae5 100644 --- a/apps/ensadmin/src/app/name/_components/SocialLinks.tsx +++ b/apps/ensadmin/src/app/name/_components/SocialLinks.tsx @@ -1,4 +1,3 @@ -"use client"; import { SiFarcaster, SiGithub, SiReddit, SiTelegram, SiX } from "@icons-pack/react-simple-icons"; import { useMemo } from "react"; diff --git a/apps/ensadmin/src/app/status/error.tsx b/apps/ensadmin/src/app/status/error.tsx deleted file mode 100644 index 92718bf4f..000000000 --- a/apps/ensadmin/src/app/status/error.tsx +++ /dev/null @@ -1,17 +0,0 @@ -"use client"; - -import { useEffect } from "react"; - -export default function StatusError({ error }: { error: Error; reset: () => void }) { - useEffect(() => { - // log the error to the console for operators - console.error(error); - }, [error]); - - return ( -
-

An error occurred

-

{error.message}

-
- ); -} diff --git a/apps/ensadmin/src/components/connection/index.tsx b/apps/ensadmin/src/components/connection/index.tsx index c71a88f17..c2d512083 100644 --- a/apps/ensadmin/src/components/connection/index.tsx +++ b/apps/ensadmin/src/components/connection/index.tsx @@ -1,5 +1,3 @@ -"use client"; - import packageJson from "@/../package.json" with { type: "json" }; import { PlugZap } from "lucide-react"; diff --git a/apps/ensadmin/src/components/graphiql-editor/components.tsx b/apps/ensadmin/src/components/graphiql-editor/components.tsx index f3fde4301..a577f1d9d 100644 --- a/apps/ensadmin/src/components/graphiql-editor/components.tsx +++ b/apps/ensadmin/src/components/graphiql-editor/components.tsx @@ -1,5 +1,3 @@ -"use client"; - import "graphiql/setup-workers/webpack"; import "graphiql/style.css"; import "@graphiql/plugin-explorer/style.css"; @@ -7,8 +5,8 @@ import "@graphiql/plugin-explorer/style.css"; // import { AiQueryGeneratorForm } from "@/components/ai-query-generator"; import { explorerPlugin } from "@graphiql/plugin-explorer"; import { createGraphiQLFetcher } from "@graphiql/toolkit"; +import { useSearch } from "@tanstack/react-router"; import { GraphiQL, type GraphiQLProps, HISTORY_PLUGIN } from "graphiql"; -import { useSearchParams } from "next/navigation"; const defaultQuery = `# # Welcome to this interactive playground for @@ -27,14 +25,21 @@ const defaultQuery = `# * A GraphiQL editor for Ponder API page. */ export function PonderGraphiQLEditor(props: GraphiQLPropsWithUrl) { - const searchParams = useSearchParams(); + const search = useSearch({ strict: false }) as Record< + string, + string | undefined + >; - const initialQuery = searchParams.get("query") || defaultQuery; - const initialVariables = searchParams.get("variables") || ""; + const initialQuery = search.query || defaultQuery; + const initialVariables = search.variables || ""; return (
- +
); } @@ -43,10 +48,13 @@ export function PonderGraphiQLEditor(props: GraphiQLPropsWithUrl) { * A GraphiQL editor for Subgraph API page. */ export function SubgraphGraphiQLEditor(props: GraphiQLPropsWithUrl) { - const searchParams = useSearchParams(); + const search = useSearch({ strict: false }) as Record< + string, + string | undefined + >; - const initialQuery = searchParams.get("query") || defaultQuery; - const initialVariables = searchParams.get("variables") || ""; + const initialQuery = search.query || defaultQuery; + const initialVariables = search.variables || ""; return (
@@ -58,7 +66,11 @@ export function SubgraphGraphiQLEditor(props: GraphiQLPropsWithUrl) { url={props.url} />*/} - +
); } diff --git a/apps/ensadmin/src/components/indexing-status/indexing-status-loading.tsx b/apps/ensadmin/src/components/indexing-status/indexing-status-loading.tsx index acac68671..b556b1bbe 100644 --- a/apps/ensadmin/src/components/indexing-status/indexing-status-loading.tsx +++ b/apps/ensadmin/src/components/indexing-status/indexing-status-loading.tsx @@ -1,5 +1,3 @@ -"use client"; - import { Card, CardContent, CardHeader } from "@/components/ui/card"; /** diff --git a/apps/ensadmin/src/components/indexing-status/indexing-status.tsx b/apps/ensadmin/src/components/indexing-status/indexing-status.tsx index 3139256be..f53ae15e8 100644 --- a/apps/ensadmin/src/components/indexing-status/indexing-status.tsx +++ b/apps/ensadmin/src/components/indexing-status/indexing-status.tsx @@ -2,8 +2,6 @@ * This is the main file composing all other ideas into a single UI component * that describes overall indexing status across all indexed chains. */ -"use client"; - import { useIndexingStatus } from "@ensnode/ensnode-react"; import { IndexingStats } from "./indexing-stats"; diff --git a/apps/ensadmin/src/components/layout-wrapper.tsx b/apps/ensadmin/src/components/layout-wrapper.tsx index d9c910753..b7feaabaf 100644 --- a/apps/ensadmin/src/components/layout-wrapper.tsx +++ b/apps/ensadmin/src/components/layout-wrapper.tsx @@ -1,12 +1,15 @@ -"use client"; - -import { usePathname } from "next/navigation"; +import { useLocation } from "@tanstack/react-router"; import { Suspense } from "react"; import { AppSidebar } from "@/components/app-sidebar"; import { RequireActiveConnection } from "@/components/connections/require-active-connection"; import { RequireSelectedConnection } from "@/components/connections/require-selected-connection"; -import { Header, HeaderActions, HeaderBreadcrumbs, HeaderNav } from "@/components/header"; +import { + Header, + HeaderActions, + HeaderBreadcrumbs, + HeaderNav, +} from "@/components/header"; import { SelectedENSNodeProvider } from "@/components/providers/selected-ensnode-provider"; import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"; import { Skeleton } from "@/components/ui/skeleton"; @@ -20,7 +23,9 @@ export function LayoutWrapper({ breadcrumbs: React.ReactNode; actions: React.ReactNode; }) { - const pathname = usePathname(); + const pathname = useLocation({ + select: (location) => location.pathname, + }); if (pathname === "/") { return children; diff --git a/apps/ensadmin/src/components/link.tsx b/apps/ensadmin/src/components/link.tsx index 92e49252a..eec4db8ef 100644 --- a/apps/ensadmin/src/components/link.tsx +++ b/apps/ensadmin/src/components/link.tsx @@ -1,5 +1,5 @@ +import { Link } from "@tanstack/react-router"; import { ExternalLink as ExternalLinkIcon } from "lucide-react"; -import Link from "next/link"; import type { PropsWithChildren } from "react"; interface LinkProps { @@ -10,9 +10,16 @@ interface LinkProps { /** * Renders an internal link. */ -export function InternalLink({ href, className, children }: PropsWithChildren) { +export function InternalLink({ + href, + className, + children, +}: PropsWithChildren) { return ( - + {children} ); @@ -21,13 +28,19 @@ export function InternalLink({ href, className, children }: PropsWithChildren
  • ) { +export function ExternalLink({ + href, + className, + children, +}: PropsWithChildren) { return ( {children} @@ -37,7 +50,11 @@ export function ExternalLink({ href, className, children }: PropsWithChildren
  • ) { +export function ExternalLinkWithIcon({ + href, + className, + children, +}: PropsWithChildren) { return ( {children} diff --git a/apps/ensadmin/src/components/nav-main.tsx b/apps/ensadmin/src/components/nav-main.tsx index 8f22695c5..52b7525cd 100644 --- a/apps/ensadmin/src/components/nav-main.tsx +++ b/apps/ensadmin/src/components/nav-main.tsx @@ -1,12 +1,13 @@ -"use client"; - +import { Link, useLocation } from "@tanstack/react-router"; import { ChevronRight, type LucideIcon } from "lucide-react"; -import Link from "next/link"; -import { usePathname, useSearchParams } from "next/navigation"; import type { UrlString } from "@ensnode/ensnode-sdk"; -import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "@/components/ui/collapsible"; import { SidebarGroup, SidebarGroupLabel, @@ -32,8 +33,9 @@ export function NavMain({ }[]; }[]; }) { - const searchParams = useSearchParams(); - const pathname = usePathname(); + const location = useLocation(); + const pathname = location.pathname; + const searchParams = new URLSearchParams(location.search); const appendQueryParams = (url: UrlString) => { if (pathname.startsWith("/inspector") && !url.startsWith("/inspector")) { @@ -75,8 +77,12 @@ export function NavMain({ if (!hasItems) return ( - - + + {item.icon && } {item.title} @@ -85,7 +91,8 @@ export function NavMain({ ); const anySubItemActive = - item.items?.some((subItem) => isActive(subItem.url)) || isItemActive; + item.items?.some((subItem) => isActive(subItem.url)) || + isItemActive; return ( - + {item.icon && } {item.title} @@ -110,8 +120,11 @@ export function NavMain({ return ( - - + + {subItem.title} diff --git a/apps/ensadmin/src/components/recent-registrations/components.tsx b/apps/ensadmin/src/components/recent-registrations/components.tsx index dd8a9c607..b3d3cf815 100644 --- a/apps/ensadmin/src/components/recent-registrations/components.tsx +++ b/apps/ensadmin/src/components/recent-registrations/components.tsx @@ -1,7 +1,5 @@ -"use client"; - +import { Link } from "@tanstack/react-router"; import { useAutoAnimate } from "@formkit/auto-animate/react"; -import Link from "next/link"; import { Fragment } from "react"; import { @@ -66,7 +64,9 @@ export interface RecentRegistrationsErrorProps { * Error - * error: {@link ErrorInfoProps} */ -export type RecentRegistrationsProps = RecentRegistrationsOkProps | RecentRegistrationsErrorProps; +export type RecentRegistrationsProps = + | RecentRegistrationsOkProps + | RecentRegistrationsErrorProps; /** * Displays a panel containing the list of the most recently indexed * registrations and the date of the most recently indexed block. @@ -87,7 +87,11 @@ export function RecentRegistrations(props: RecentRegistrationsProps) { const { omnichainSnapshot } = realtimeProjection.snapshot; - if (!SUPPORTED_OMNICHAIN_INDEXING_STATUSES.includes(omnichainSnapshot.omnichainStatus)) { + if ( + !SUPPORTED_OMNICHAIN_INDEXING_STATUSES.includes( + omnichainSnapshot.omnichainStatus + ) + ) { return ( @@ -196,29 +201,36 @@ function UnsupportedOmnichainIndexingStatusMessage({ {formatOmnichainIndexingStatus(omnichainIndexingStatus)}
    - The latest indexed registrations will be available once the omnichain indexing status is{" "} - {supportedOmnichainIndexingStatuses.map((supportedOmnichainIndexingStatus, idx) => ( - - - {formatOmnichainIndexingStatus(supportedOmnichainIndexingStatus)} - - {idx < supportedOmnichainIndexingStatuses.length - 1 && " or "} - - ))} + The latest indexed registrations will be available once the omnichain + indexing status is{" "} + {supportedOmnichainIndexingStatuses.map( + (supportedOmnichainIndexingStatus, idx) => ( + + + {formatOmnichainIndexingStatus( + supportedOmnichainIndexingStatus + )} + + {idx < supportedOmnichainIndexingStatuses.length - 1 && " or "} + + ) + )} .
    diff --git a/apps/ensadmin/src/components/ui/sonner.tsx b/apps/ensadmin/src/components/ui/sonner.tsx index 8d084f8ff..0921376cc 100644 --- a/apps/ensadmin/src/components/ui/sonner.tsx +++ b/apps/ensadmin/src/components/ui/sonner.tsx @@ -1,24 +1,22 @@ "use client"; -import { useTheme } from "next-themes"; import { Toaster as Sonner } from "sonner"; type ToasterProps = React.ComponentProps; const Toaster = ({ ...props }: ToasterProps) => { - const { theme = "system" } = useTheme(); - return ( )[RAW_CONNECTION_PARAM_KEY] ?? null; // Build callback for setting the raw connection URL param const setRawConnectionUrlParam = useCallback( (rawUrl: string | null) => { - const params = new URLSearchParams(searchParams.toString()); + const newSearch = { ...search } as Record; + if (rawUrl === null) { - params.delete(RAW_CONNECTION_PARAM_KEY); + delete newSearch[RAW_CONNECTION_PARAM_KEY]; } else { - params.set(RAW_CONNECTION_PARAM_KEY, rawUrl); + newSearch[RAW_CONNECTION_PARAM_KEY] = rawUrl; } - const paramString = params.toString(); - router.replace(paramString ? `?${paramString}` : ""); + + navigate({ + search: newSearch, + replace: true, + }); }, - [router, searchParams], + [navigate, search] ); // Build callback for attaching the current raw connection URL param @@ -99,7 +102,7 @@ export function useRawConnectionUrlParam(): UseRawConnectionUrlParamResult { return pathWithRetainedConnection; }, - [rawConnectionUrlParam], + [rawConnectionUrlParam] ); return { diff --git a/apps/ensadmin/src/hooks/use-connections-library.tsx b/apps/ensadmin/src/hooks/use-connections-library.tsx index d7fd99f6a..feac4b731 100644 --- a/apps/ensadmin/src/hooks/use-connections-library.tsx +++ b/apps/ensadmin/src/hooks/use-connections-library.tsx @@ -1,5 +1,3 @@ -"use client"; - import constate from "constate"; import { Suspense, useCallback, useEffect, useMemo, useState } from "react"; import { useLocalstorageState } from "rooks"; @@ -11,10 +9,10 @@ import { useRawConnectionUrlParam } from "@/hooks/use-connection-url-param"; import { useHydrated } from "@/hooks/use-hydrated"; import { getServerConnectionLibrary } from "@/lib/env"; import { - BuildHttpHostnameResult, + type BuildHttpHostnameResult, buildHttpHostname, buildHttpHostnames, - HttpHostname, + type HttpHostname, } from "@/lib/url-utils"; const CUSTOM_CONNECTIONS_LOCAL_STORAGE_KEY = "ensadmin:custom-connections:urls"; @@ -50,15 +48,16 @@ const defaultSelectedConnection = serverConnectionLibrary[0]; function _useConnectionsLibrary() { const hydrated = useHydrated(); - const { rawConnectionUrlParam, setRawConnectionUrlParam } = useRawConnectionUrlParam(); + const { rawConnectionUrlParam, setRawConnectionUrlParam } = + useRawConnectionUrlParam(); // get raw custom connection library URLs from localStorage - const [rawCustomConnectionUrls, storeRawCustomConnectionUrls] = useLocalstorageState( - CUSTOM_CONNECTIONS_LOCAL_STORAGE_KEY, - [], - ); + const [rawCustomConnectionUrls, storeRawCustomConnectionUrls] = + useLocalstorageState(CUSTOM_CONNECTIONS_LOCAL_STORAGE_KEY, []); - const [rawExistingConnectionUrl, setRawExistingConnectionUrl] = useState(null); + const [rawExistingConnectionUrl, setRawExistingConnectionUrl] = useState< + string | null + >(null); /** * Invariants: @@ -76,10 +75,19 @@ function _useConnectionsLibrary() { // clean up custom connection library URLs in localStorage if validation changed anything useEffect(() => { - if (JSON.stringify(customConnectionLibrary) !== JSON.stringify(rawCustomConnectionUrls)) { - storeRawCustomConnectionUrls(customConnectionLibrary.map((url) => url.toString())); + if ( + JSON.stringify(customConnectionLibrary) !== + JSON.stringify(rawCustomConnectionUrls) + ) { + storeRawCustomConnectionUrls( + customConnectionLibrary.map((url) => url.toString()) + ); } - }, [customConnectionLibrary, rawCustomConnectionUrls, storeRawCustomConnectionUrls]); + }, [ + customConnectionLibrary, + rawCustomConnectionUrls, + storeRawCustomConnectionUrls, + ]); /** * Invariants: @@ -104,7 +112,7 @@ function _useConnectionsLibrary() { .filter((url) => !serverConnectionLibrary.includes(url)) .map((url) => ({ url, type: "custom" as const })), ], - [customConnectionLibrary], + [customConnectionLibrary] ); const addCustomConnection = useCallback( @@ -116,18 +124,18 @@ function _useConnectionsLibrary() { return url; }, - [storeRawCustomConnectionUrls], + [storeRawCustomConnectionUrls] ); const removeCustomConnection = useCallback( (url: HttpHostname) => { storeRawCustomConnectionUrls((customConnections) => - customConnections.filter((rawUrl) => rawUrl !== url.toString()), + customConnections.filter((rawUrl) => rawUrl !== url.toString()) ); return url; }, - [storeRawCustomConnectionUrls], + [storeRawCustomConnectionUrls] ); const selectedConnection = useMemo(() => { @@ -165,7 +173,7 @@ function _useConnectionsLibrary() { (url: HttpHostname) => { setRawConnectionUrlParam(url.toString()); }, - [setRawConnectionUrlParam], + [setRawConnectionUrlParam] ); return { @@ -177,7 +185,9 @@ function _useConnectionsLibrary() { }; } -const [ConnectionsLibraryProviderInner, useConnectionsLibrary] = constate(_useConnectionsLibrary); +const [ConnectionsLibraryProviderInner, useConnectionsLibrary] = constate( + _useConnectionsLibrary +); export { useConnectionsLibrary }; @@ -196,10 +206,16 @@ export { useConnectionsLibrary }; * - removeCustomConnection: Callback for removing a custom connection * - selectConnection: Callback for selecting a connection */ -export function ConnectionsLibraryProvider({ children }: { children: React.ReactNode }) { +export function ConnectionsLibraryProvider({ + children, +}: { + children: React.ReactNode; +}) { return ( - {children} + + {children} + ); } diff --git a/apps/ensadmin/src/lib/env.ts b/apps/ensadmin/src/lib/env.ts index 6f9a8b7f3..853fb3127 100644 --- a/apps/ensadmin/src/lib/env.ts +++ b/apps/ensadmin/src/lib/env.ts @@ -1,6 +1,10 @@ import { uniq } from "@ensnode/ensnode-sdk"; -import { buildHttpHostname, buildHttpHostnames, type HttpHostname } from "./url-utils"; +import { + buildHttpHostname, + buildHttpHostnames, + type HttpHostname, +} from "./url-utils"; const DEFAULT_ENSADMIN_PORT = 4173; const DEFAULT_SERVER_CONNECTION_LIBRARY = [ @@ -14,7 +18,9 @@ const DEFAULT_SERVER_CONNECTION_LIBRARY = [ /** * Determines whether `variables` is a non-null object and a valid Record. */ -const isValidRuntimeEnvVariables = (value: unknown): value is Record => +const isValidRuntimeEnvVariables = ( + value: unknown +): value is Record => typeof value === "object" && value !== null; /** @@ -26,7 +32,8 @@ const isValidRuntimeEnvVariables = (value: unknown): value is Record { if (typeof window == "undefined") return undefined; - const variables = (window as any).__ENSADMIN_RUNTIME_ENVIRONMENT_VARIABLES as unknown; + const variables = (window as any) + .__ENSADMIN_RUNTIME_ENVIRONMENT_VARIABLES as unknown; if (!isValidRuntimeEnvVariables(variables)) return undefined; const value = variables[key]; @@ -39,7 +46,7 @@ const getRuntimeEnvVariable = (key: string): string | undefined => { }; function localhostEnsAdminPublicUrl(): string { - const port = process.env.PORT || DEFAULT_ENSADMIN_PORT.toString(); + const port = import.meta.env.PORT || DEFAULT_ENSADMIN_PORT.toString(); return `http://localhost:${port}`; } @@ -47,7 +54,7 @@ function localhostEnsAdminPublicUrl(): string { * Tells if the application runs on Vercel. */ function isAppOnVercelPlatform(): boolean { - return process.env.VERCEL === "1"; + return import.meta.env.VERCEL === "1"; } /** @@ -59,12 +66,12 @@ function isAppOnVercelPlatform(): boolean { function getVercelAppPublicUrl(): string | undefined { if (!isAppOnVercelPlatform()) return undefined; - switch (process.env.VERCEL_ENV) { + switch (import.meta.env.VERCEL_ENV) { case "production": - return process.env.VERCEL_PROJECT_PRODUCTION_URL; + return import.meta.env.VERCEL_PROJECT_PRODUCTION_URL; case "development": case "preview": - return process.env.VERCEL_BRANCH_URL || process.env.VERCEL_URL; + return import.meta.env.VERCEL_BRANCH_URL || import.meta.env.VERCEL_URL; } } @@ -79,12 +86,14 @@ function getVercelAppPublicUrl(): string | undefined { */ export function ensAdminPublicUrl(): HttpHostname { const envVarValue = - process.env.ENSADMIN_PUBLIC_URL || getVercelAppPublicUrl() || localhostEnsAdminPublicUrl(); + import.meta.env.ENSADMIN_PUBLIC_URL || + getVercelAppPublicUrl() || + localhostEnsAdminPublicUrl(); const result = buildHttpHostname(envVarValue); if (!result.isValid) { throw new Error( - `Invalid ENSADMIN_PUBLIC_URL value "${envVarValue}": Cannot build ENSAdmin public HttpHostname: ${result.error}`, + `Invalid ENSADMIN_PUBLIC_URL value "${envVarValue}": Cannot build ENSAdmin public HttpHostname: ${result.error}` ); } return result.url; @@ -97,17 +106,17 @@ export function ensAdminPublicUrl(): HttpHostname { * @throws when no `HttpHostname` could be returned. */ export function getServerConnectionLibrary(): HttpHostname[] { - const envVarName = "NEXT_PUBLIC_SERVER_CONNECTION_LIBRARY"; + const envVarName = "VITE_SERVER_CONNECTION_LIBRARY"; const envVarValue = - getRuntimeEnvVariable("NEXT_PUBLIC_SERVER_CONNECTION_LIBRARY") || - process.env.NEXT_PUBLIC_SERVER_CONNECTION_LIBRARY || // NOTE: must specify full key for nextjs to replace + getRuntimeEnvVariable("VITE_SERVER_CONNECTION_LIBRARY") || + import.meta.env.VITE_SERVER_CONNECTION_LIBRARY || DEFAULT_SERVER_CONNECTION_LIBRARY; const connections = buildHttpHostnames(envVarValue.split(",")); if (connections.length === 0) { throw new Error( - `Invalid ${envVarName} value: "${envVarValue}" must contain at least one valid ENSNode connection URL`, + `Invalid ${envVarName} value: "${envVarValue}" must contain at least one valid ENSNode connection URL` ); } diff --git a/apps/ensadmin/src/main.tsx b/apps/ensadmin/src/main.tsx new file mode 100644 index 000000000..1b093697f --- /dev/null +++ b/apps/ensadmin/src/main.tsx @@ -0,0 +1,42 @@ +import { StrictMode } from 'react' +import ReactDOM from 'react-dom/client' +import { RouterProvider, createRouter } from '@tanstack/react-router' + +// Import the generated route tree +import { routeTree } from './routeTree.gen' + +import './styles.css' +import reportWebVitals from './reportWebVitals.ts' + +// Create a new router instance +const router = createRouter({ + routeTree, + context: {}, + defaultPreload: 'intent', + scrollRestoration: true, + defaultStructuralSharing: true, + defaultPreloadStaleTime: 0, +}) + +// Register the router instance for type safety +declare module '@tanstack/react-router' { + interface Register { + router: typeof router + } +} + +// Render the app +const rootElement = document.getElementById('app') +if (rootElement && !rootElement.innerHTML) { + const root = ReactDOM.createRoot(rootElement) + root.render( + + + , + ) +} + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals() diff --git a/apps/ensadmin/src/reportWebVitals.ts b/apps/ensadmin/src/reportWebVitals.ts new file mode 100644 index 000000000..16b66b5f6 --- /dev/null +++ b/apps/ensadmin/src/reportWebVitals.ts @@ -0,0 +1,13 @@ +const reportWebVitals = (onPerfEntry?: () => void) => { + if (onPerfEntry && onPerfEntry instanceof Function) { + import('web-vitals').then(({ onCLS, onINP, onFCP, onLCP, onTTFB }) => { + onCLS(onPerfEntry) + onINP(onPerfEntry) + onFCP(onPerfEntry) + onLCP(onPerfEntry) + onTTFB(onPerfEntry) + }) + } +} + +export default reportWebVitals diff --git a/apps/ensadmin/src/routeTree.gen.ts b/apps/ensadmin/src/routeTree.gen.ts new file mode 100644 index 000000000..295a629b0 --- /dev/null +++ b/apps/ensadmin/src/routeTree.gen.ts @@ -0,0 +1,252 @@ +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. + +import { Route as rootRouteImport } from './routes/__root' +import { Route as StatusRouteImport } from './routes/status' +import { Route as RegistrationRouteImport } from './routes/registration' +import { Route as NameRouteImport } from './routes/name' +import { Route as ConnectionRouteImport } from './routes/connection' +import { Route as IndexRouteImport } from './routes/index' +import { Route as InspectVisualizerRouteImport } from './routes/inspect/visualizer' +import { Route as InspectRecordsRouteImport } from './routes/inspect/records' +import { Route as InspectPrimaryNamesRouteImport } from './routes/inspect/primary-names' +import { Route as InspectPrimaryNameRouteImport } from './routes/inspect/primary-name' +import { Route as ApiSubgraphRouteImport } from './routes/api/subgraph' + +const StatusRoute = StatusRouteImport.update({ + id: '/status', + path: '/status', + getParentRoute: () => rootRouteImport, +} as any) +const RegistrationRoute = RegistrationRouteImport.update({ + id: '/registration', + path: '/registration', + getParentRoute: () => rootRouteImport, +} as any) +const NameRoute = NameRouteImport.update({ + id: '/name', + path: '/name', + getParentRoute: () => rootRouteImport, +} as any) +const ConnectionRoute = ConnectionRouteImport.update({ + id: '/connection', + path: '/connection', + getParentRoute: () => rootRouteImport, +} as any) +const IndexRoute = IndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRouteImport, +} as any) +const InspectVisualizerRoute = InspectVisualizerRouteImport.update({ + id: '/inspect/visualizer', + path: '/inspect/visualizer', + getParentRoute: () => rootRouteImport, +} as any) +const InspectRecordsRoute = InspectRecordsRouteImport.update({ + id: '/inspect/records', + path: '/inspect/records', + getParentRoute: () => rootRouteImport, +} as any) +const InspectPrimaryNamesRoute = InspectPrimaryNamesRouteImport.update({ + id: '/inspect/primary-names', + path: '/inspect/primary-names', + getParentRoute: () => rootRouteImport, +} as any) +const InspectPrimaryNameRoute = InspectPrimaryNameRouteImport.update({ + id: '/inspect/primary-name', + path: '/inspect/primary-name', + getParentRoute: () => rootRouteImport, +} as any) +const ApiSubgraphRoute = ApiSubgraphRouteImport.update({ + id: '/api/subgraph', + path: '/api/subgraph', + getParentRoute: () => rootRouteImport, +} as any) + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute + '/connection': typeof ConnectionRoute + '/name': typeof NameRoute + '/registration': typeof RegistrationRoute + '/status': typeof StatusRoute + '/api/subgraph': typeof ApiSubgraphRoute + '/inspect/primary-name': typeof InspectPrimaryNameRoute + '/inspect/primary-names': typeof InspectPrimaryNamesRoute + '/inspect/records': typeof InspectRecordsRoute + '/inspect/visualizer': typeof InspectVisualizerRoute +} +export interface FileRoutesByTo { + '/': typeof IndexRoute + '/connection': typeof ConnectionRoute + '/name': typeof NameRoute + '/registration': typeof RegistrationRoute + '/status': typeof StatusRoute + '/api/subgraph': typeof ApiSubgraphRoute + '/inspect/primary-name': typeof InspectPrimaryNameRoute + '/inspect/primary-names': typeof InspectPrimaryNamesRoute + '/inspect/records': typeof InspectRecordsRoute + '/inspect/visualizer': typeof InspectVisualizerRoute +} +export interface FileRoutesById { + __root__: typeof rootRouteImport + '/': typeof IndexRoute + '/connection': typeof ConnectionRoute + '/name': typeof NameRoute + '/registration': typeof RegistrationRoute + '/status': typeof StatusRoute + '/api/subgraph': typeof ApiSubgraphRoute + '/inspect/primary-name': typeof InspectPrimaryNameRoute + '/inspect/primary-names': typeof InspectPrimaryNamesRoute + '/inspect/records': typeof InspectRecordsRoute + '/inspect/visualizer': typeof InspectVisualizerRoute +} +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: + | '/' + | '/connection' + | '/name' + | '/registration' + | '/status' + | '/api/subgraph' + | '/inspect/primary-name' + | '/inspect/primary-names' + | '/inspect/records' + | '/inspect/visualizer' + fileRoutesByTo: FileRoutesByTo + to: + | '/' + | '/connection' + | '/name' + | '/registration' + | '/status' + | '/api/subgraph' + | '/inspect/primary-name' + | '/inspect/primary-names' + | '/inspect/records' + | '/inspect/visualizer' + id: + | '__root__' + | '/' + | '/connection' + | '/name' + | '/registration' + | '/status' + | '/api/subgraph' + | '/inspect/primary-name' + | '/inspect/primary-names' + | '/inspect/records' + | '/inspect/visualizer' + fileRoutesById: FileRoutesById +} +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute + ConnectionRoute: typeof ConnectionRoute + NameRoute: typeof NameRoute + RegistrationRoute: typeof RegistrationRoute + StatusRoute: typeof StatusRoute + ApiSubgraphRoute: typeof ApiSubgraphRoute + InspectPrimaryNameRoute: typeof InspectPrimaryNameRoute + InspectPrimaryNamesRoute: typeof InspectPrimaryNamesRoute + InspectRecordsRoute: typeof InspectRecordsRoute + InspectVisualizerRoute: typeof InspectVisualizerRoute +} + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/status': { + id: '/status' + path: '/status' + fullPath: '/status' + preLoaderRoute: typeof StatusRouteImport + parentRoute: typeof rootRouteImport + } + '/registration': { + id: '/registration' + path: '/registration' + fullPath: '/registration' + preLoaderRoute: typeof RegistrationRouteImport + parentRoute: typeof rootRouteImport + } + '/name': { + id: '/name' + path: '/name' + fullPath: '/name' + preLoaderRoute: typeof NameRouteImport + parentRoute: typeof rootRouteImport + } + '/connection': { + id: '/connection' + path: '/connection' + fullPath: '/connection' + preLoaderRoute: typeof ConnectionRouteImport + parentRoute: typeof rootRouteImport + } + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexRouteImport + parentRoute: typeof rootRouteImport + } + '/inspect/visualizer': { + id: '/inspect/visualizer' + path: '/inspect/visualizer' + fullPath: '/inspect/visualizer' + preLoaderRoute: typeof InspectVisualizerRouteImport + parentRoute: typeof rootRouteImport + } + '/inspect/records': { + id: '/inspect/records' + path: '/inspect/records' + fullPath: '/inspect/records' + preLoaderRoute: typeof InspectRecordsRouteImport + parentRoute: typeof rootRouteImport + } + '/inspect/primary-names': { + id: '/inspect/primary-names' + path: '/inspect/primary-names' + fullPath: '/inspect/primary-names' + preLoaderRoute: typeof InspectPrimaryNamesRouteImport + parentRoute: typeof rootRouteImport + } + '/inspect/primary-name': { + id: '/inspect/primary-name' + path: '/inspect/primary-name' + fullPath: '/inspect/primary-name' + preLoaderRoute: typeof InspectPrimaryNameRouteImport + parentRoute: typeof rootRouteImport + } + '/api/subgraph': { + id: '/api/subgraph' + path: '/api/subgraph' + fullPath: '/api/subgraph' + preLoaderRoute: typeof ApiSubgraphRouteImport + parentRoute: typeof rootRouteImport + } + } +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, + ConnectionRoute: ConnectionRoute, + NameRoute: NameRoute, + RegistrationRoute: RegistrationRoute, + StatusRoute: StatusRoute, + ApiSubgraphRoute: ApiSubgraphRoute, + InspectPrimaryNameRoute: InspectPrimaryNameRoute, + InspectPrimaryNamesRoute: InspectPrimaryNamesRoute, + InspectRecordsRoute: InspectRecordsRoute, + InspectVisualizerRoute: InspectVisualizerRoute, +} +export const routeTree = rootRouteImport + ._addFileChildren(rootRouteChildren) + ._addFileTypes() diff --git a/apps/ensadmin/src/routes/__root.tsx b/apps/ensadmin/src/routes/__root.tsx new file mode 100644 index 000000000..53424435e --- /dev/null +++ b/apps/ensadmin/src/routes/__root.tsx @@ -0,0 +1,41 @@ +import { Outlet, createRootRoute } from "@tanstack/react-router"; +import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"; +import { TanStackDevtools } from "@tanstack/react-devtools"; +import { Suspense } from "react"; + +import { QueryClientProvider } from "@/components/query-client/components"; +import { ConnectionsLibraryProvider } from "@/hooks/use-connections-library"; +import { LayoutWrapper } from "@/components/layout-wrapper"; +import { Toaster } from "@/components/ui/sonner"; + +export const Route = createRootRoute({ + component: RootLayout, +}); + +function RootLayout() { + return ( + <> + + + + + + + + + + + , + }, + ]} + /> + + ); +} diff --git a/apps/ensadmin/src/app/api/subgraph/page.tsx b/apps/ensadmin/src/routes/api/subgraph.tsx similarity index 86% rename from apps/ensadmin/src/app/api/subgraph/page.tsx rename to apps/ensadmin/src/routes/api/subgraph.tsx index 5e6e62ffd..983c2e76c 100644 --- a/apps/ensadmin/src/app/api/subgraph/page.tsx +++ b/apps/ensadmin/src/routes/api/subgraph.tsx @@ -1,11 +1,14 @@ -"use client"; - +import { createFileRoute } from "@tanstack/react-router"; import { Suspense } from "react"; import { SubgraphGraphiQLEditor } from "@/components/graphiql-editor"; import { LoadingSpinner } from "@/components/loading-spinner"; import { useSelectedConnection } from "@/hooks/active/use-selected-connection"; +export const Route = createFileRoute("/api/subgraph")({ + component: SubgraphGraphQLPage, +}); + function SubgraphGraphQLContent() { const { validatedSelectedConnection } = useSelectedConnection(); @@ -26,7 +29,7 @@ function SubgraphGraphQLContent() { return ; } -export default function SubgraphGraphQLPage() { +function SubgraphGraphQLPage() { return ( ; +} diff --git a/apps/ensadmin/src/app/page.tsx b/apps/ensadmin/src/routes/index.tsx similarity index 58% rename from apps/ensadmin/src/app/page.tsx rename to apps/ensadmin/src/routes/index.tsx index 5b00c78a9..e8ba0a305 100644 --- a/apps/ensadmin/src/app/page.tsx +++ b/apps/ensadmin/src/routes/index.tsx @@ -1,19 +1,34 @@ -import Link from "next/link"; +import { createFileRoute, Link } from "@tanstack/react-router"; import { Button } from "@/components/ui/button"; -export default function SplashPage() { +export const Route = createFileRoute("/")({ + component: SplashPage, +}); + +function SplashPage() { return (
    - ENSAdmin + ENSAdmin
    - ENSAdmin Logo -

    ENSAdmin

    + ENSAdmin Logo +

    + ENSAdmin +

    @@ -21,7 +36,7 @@ export default function SplashPage() {

    diff --git a/apps/ensadmin/src/app/inspect/primary-name/page.tsx b/apps/ensadmin/src/routes/inspect/primary-name.tsx similarity index 87% rename from apps/ensadmin/src/app/inspect/primary-name/page.tsx rename to apps/ensadmin/src/routes/inspect/primary-name.tsx index b1bf71655..f68d4fa1d 100644 --- a/apps/ensadmin/src/app/inspect/primary-name/page.tsx +++ b/apps/ensadmin/src/routes/inspect/primary-name.tsx @@ -1,6 +1,4 @@ -"use client"; - -import { useSearchParams } from "next/navigation"; +import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { useState } from "react"; import { useDebouncedValue } from "rooks"; import { type Address, isAddress } from "viem"; @@ -28,6 +26,21 @@ import { } from "@/components/ui/select"; import { getChainName } from "@/lib/namespace-utils"; +type PrimaryNameSearchParams = { + address?: string; + chainId?: string; +}; + +export const Route = createFileRoute("/inspect/primary-name")({ + component: ResolvePrimaryNameInspector, + validateSearch: (search: Record): PrimaryNameSearchParams => { + return { + address: (search.address as string) || undefined, + chainId: (search.chainId as string) || undefined, + }; + }, +}); + const EXAMPLE_INPUT = [ { address: "0x179A862703a4adfb29896552DF9e307980D19285", chainId: "1" }, // greg mainnet { address: "0x179A862703a4adfb29896552DF9e307980D19285", chainId: "8453" }, // greg base @@ -45,14 +58,11 @@ const getENSIP19SupportedChainIds = (namespace: ENSNamespaceId) => .filter((ds) => ds !== undefined) .map((ds) => ds.chain.id); -// TODO: showcase current ENSNode configuration and viable acceleration pathways? -// TODO: use shadcn/form, react-hook-form, and zod to make all of this nicer aross the board -// TODO: sync form state to query params, current just defaulting is supported -export default function ResolvePrimaryNameInspector() { - const searchParams = useSearchParams(); +function ResolvePrimaryNameInspector() { + const searchParams = Route.useSearch(); - const [address, setAddress] = useState(searchParams.get("address") || EXAMPLE_INPUT[0].address); - const [chainId, setChainId] = useState(searchParams.get("chainId") || EXAMPLE_INPUT[0].chainId); + const [address, setAddress] = useState(searchParams.address || EXAMPLE_INPUT[0].address); + const [chainId, setChainId] = useState(searchParams.chainId || EXAMPLE_INPUT[0].chainId); const [debouncedAddress] = useDebouncedValue(address, 150); const additionalChainIds = getENSIP19SupportedChainIds(ENSNamespaceIds.Mainnet); @@ -136,7 +146,6 @@ export default function ResolvePrimaryNameInspector() {
    Examples: - {/* -mx-6 px-6 insets the scroll container against card for prettier scrolling */}
    {EXAMPLE_INPUT.map(({ address, chainId }) => ( ): PrimaryNamesSearchParams => { + return { + address: (search.address as string) || undefined, + }; + }, +}); + const EXAMPLE_INPUT = [ "0x179A862703a4adfb29896552DF9e307980D19285", // greg "0xe7a863d7cdC48Cc0CcB135c9c0B4c1fafA3a2e69", // katzman @@ -21,13 +32,10 @@ const EXAMPLE_INPUT = [ "0x2211d1D0020DAEA8039E46Cf1367962070d77DA9", // jesse ]; -// TODO: showcase current ENSNode configuration and viable acceleration pathways? -// TODO: use shadcn/form, react-hook-form, and zod to make all of this nicer aross the board -// TODO: sync form state to query params, current just defaulting is supported -export default function ResolvePrimaryNameInspector() { - const searchParams = useSearchParams(); +function ResolvePrimaryNamesInspector() { + const searchParams = Route.useSearch(); - const [address, setAddress] = useState(searchParams.get("address") || EXAMPLE_INPUT[0]); + const [address, setAddress] = useState(searchParams.address || EXAMPLE_INPUT[0]); const [debouncedAddress] = useDebouncedValue(address, 150); const canQuery = @@ -91,7 +99,6 @@ export default function ResolvePrimaryNameInspector() {
    Examples: - {/* -mx-6 px-6 insets the scroll container against card for prettier scrolling */}
    {EXAMPLE_INPUT.map((address) => ( setAddress(address)} className="font-mono"> diff --git a/apps/ensadmin/src/app/inspect/records/page.tsx b/apps/ensadmin/src/routes/inspect/records.tsx similarity index 85% rename from apps/ensadmin/src/app/inspect/records/page.tsx rename to apps/ensadmin/src/routes/inspect/records.tsx index caec8c8e3..a9144fafc 100644 --- a/apps/ensadmin/src/app/inspect/records/page.tsx +++ b/apps/ensadmin/src/routes/inspect/records.tsx @@ -1,6 +1,4 @@ -"use client"; - -import { useSearchParams } from "next/navigation"; +import { createFileRoute } from "@tanstack/react-router"; import { useState } from "react"; import { useDebouncedValue } from "rooks"; @@ -15,6 +13,19 @@ import { Label } from "@/components/ui/label"; import { useActiveNamespace } from "@/hooks/active/use-active-namespace"; import { DefaultRecordsSelection } from "@/lib/default-records-selection"; +type RecordsSearchParams = { + name?: string; +}; + +export const Route = createFileRoute("/inspect/records")({ + component: ResolveRecordsInspector, + validateSearch: (search: Record): RecordsSearchParams => { + return { + name: (search.name as string) || undefined, + }; + }, +}); + const EXAMPLE_INPUT = [ "vitalik.eth", "gregskril.eth", @@ -29,14 +40,11 @@ const EXAMPLE_INPUT = [ "🔥🔥🔥🔥🔥.eth", ]; -// TODO: showcase current ENSNode configuration and viable acceleration pathways? -// TODO: use shadcn/form, react-hook-form, and zod to make all of this nicer aross the board -// TODO: sync form state to query params, currently just defaulting is supported -export default function ResolveRecordsInspector() { +function ResolveRecordsInspector() { const namespace = useActiveNamespace(); - const searchParams = useSearchParams(); + const searchParams = Route.useSearch(); - const [name, setName] = useState(searchParams.get("name") || EXAMPLE_INPUT[0]); + const [name, setName] = useState(searchParams.name || EXAMPLE_INPUT[0]); const [debouncedName] = useDebouncedValue(name, 150); const canQuery = !!debouncedName && debouncedName.length > 0; @@ -107,7 +115,6 @@ export default function ResolveRecordsInspector() {
    Examples: - {/* -mx-6 px-6 insets the scroll container against card for prettier scrolling */}
    {EXAMPLE_INPUT.map((name) => ( setName(name)} className="font-mono"> diff --git a/apps/ensadmin/src/routes/inspect/visualizer.tsx b/apps/ensadmin/src/routes/inspect/visualizer.tsx new file mode 100644 index 000000000..fed1b0e91 --- /dev/null +++ b/apps/ensadmin/src/routes/inspect/visualizer.tsx @@ -0,0 +1,15 @@ +import { createFileRoute } from "@tanstack/react-router"; + +import VisualizerClient from "@/components/visualizer/client"; + +export const Route = createFileRoute("/inspect/visualizer")({ + component: InspectorPage, +}); + +function InspectorPage() { + return ( +
    + +
    + ); +} diff --git a/apps/ensadmin/src/app/name/page.tsx b/apps/ensadmin/src/routes/name.tsx similarity index 84% rename from apps/ensadmin/src/app/name/page.tsx rename to apps/ensadmin/src/routes/name.tsx index 4b8abb2b2..9472738f2 100644 --- a/apps/ensadmin/src/app/name/page.tsx +++ b/apps/ensadmin/src/routes/name.tsx @@ -1,6 +1,4 @@ -"use client"; - -import { useRouter, useSearchParams } from "next/navigation"; +import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { type ChangeEvent, useState } from "react"; import type { Name } from "@ensnode/ensnode-sdk"; @@ -11,7 +9,21 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { useRawConnectionUrlParam } from "@/hooks/use-connection-url-param"; -import { NameDetailPageContent } from "./_components/NameDetailPageContent"; +import { NameDetailPageContent } from "../app/name/_components/NameDetailPageContent"; + +// Define search params schema +type NameSearchParams = { + name?: string; +}; + +export const Route = createFileRoute("/name")({ + component: ExploreNamesPage, + validateSearch: (search: Record): NameSearchParams => { + return { + name: (search.name as string) || undefined, + }; + }, +}); const EXAMPLE_NAMES = [ "vitalik.eth", @@ -28,10 +40,9 @@ const EXAMPLE_NAMES = [ "lightwalker.eth", ]; -export default function ExploreNamesPage() { - const router = useRouter(); - const searchParams = useSearchParams(); - const nameFromQuery = searchParams.get("name"); +function ExploreNamesPage() { + const navigate = useNavigate(); + const { name: nameFromQuery } = Route.useSearch(); const [rawInputName, setRawInputName] = useState(""); const { retainCurrentRawConnectionUrlParam } = useRawConnectionUrlParam(); @@ -44,7 +55,7 @@ export default function ExploreNamesPage() { const href = retainCurrentRawConnectionUrlParam(getNameDetailsRelativePath(rawInputName)); - router.push(href); + navigate({ to: href as any }); }; const handleRawInputNameChange = (e: ChangeEvent) => { diff --git a/apps/ensadmin/src/app/registration/page.tsx b/apps/ensadmin/src/routes/registration.tsx similarity index 50% rename from apps/ensadmin/src/app/registration/page.tsx rename to apps/ensadmin/src/routes/registration.tsx index dbf3cf047..931e9930b 100644 --- a/apps/ensadmin/src/app/registration/page.tsx +++ b/apps/ensadmin/src/routes/registration.tsx @@ -1,8 +1,12 @@ -"use client"; +import { createFileRoute } from "@tanstack/react-router"; import { Registrations } from "@/components/recent-registrations/registrations"; -export default function ExploreRegistrations() { +export const Route = createFileRoute("/registration")({ + component: ExploreRegistrations, +}); + +function ExploreRegistrations() { return (
    diff --git a/apps/ensadmin/src/app/status/page.tsx b/apps/ensadmin/src/routes/status.tsx similarity index 50% rename from apps/ensadmin/src/app/status/page.tsx rename to apps/ensadmin/src/routes/status.tsx index bfb6b7b71..a14718b03 100644 --- a/apps/ensadmin/src/app/status/page.tsx +++ b/apps/ensadmin/src/routes/status.tsx @@ -1,9 +1,15 @@ +import { createFileRoute } from "@tanstack/react-router"; import { Suspense } from "react"; import { IndexingStatus } from "@/components/indexing-status"; import { LoadingSpinner } from "@/components/loading-spinner"; -export default function Status() { +export const Route = createFileRoute("/status")({ + component: StatusPage, + errorComponent: StatusError, +}); + +function StatusPage() { return ( }> @@ -18,3 +24,12 @@ function Loading() {
    ); } + +function StatusError({ error }: { error: Error }) { + return ( +
    +

    An error occurred

    +

    {error.message}

    +
    + ); +} diff --git a/apps/ensadmin/src/styles.css b/apps/ensadmin/src/styles.css new file mode 100644 index 000000000..226b8f724 --- /dev/null +++ b/apps/ensadmin/src/styles.css @@ -0,0 +1,147 @@ +@import "tailwindcss"; +@import "tw-animate-css"; + +@custom-variant dark (&:is(.dark *)); + +body { + @apply m-0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", + monospace; +} + +@theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} + +:root { + --radius: 0.625rem; + --background: oklch(1 0 0); + --foreground: oklch(0.129 0.042 264.695); + --card: oklch(1 0 0); + --card-foreground: oklch(0.129 0.042 264.695); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.129 0.042 264.695); + --primary: oklch(0.208 0.042 265.755); + --primary-foreground: oklch(0.984 0.003 247.858); + --secondary: oklch(0.968 0.007 247.896); + --secondary-foreground: oklch(0.208 0.042 265.755); + --muted: oklch(0.968 0.007 247.896); + --muted-foreground: oklch(0.554 0.046 257.417); + --accent: oklch(0.968 0.007 247.896); + --accent-foreground: oklch(0.208 0.042 265.755); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.929 0.013 255.508); + --input: oklch(0.929 0.013 255.508); + --ring: oklch(0.704 0.04 256.788); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.984 0.003 247.858); + --sidebar-foreground: oklch(0.129 0.042 264.695); + --sidebar-primary: oklch(0.208 0.042 265.755); + --sidebar-primary-foreground: oklch(0.984 0.003 247.858); + --sidebar-accent: oklch(0.968 0.007 247.896); + --sidebar-accent-foreground: oklch(0.208 0.042 265.755); + --sidebar-border: oklch(0.929 0.013 255.508); + --sidebar-ring: oklch(0.704 0.04 256.788); +} + +.dark { + --background: oklch(0.129 0.042 264.695); + --foreground: oklch(0.984 0.003 247.858); + --card: oklch(0.208 0.042 265.755); + --card-foreground: oklch(0.984 0.003 247.858); + --popover: oklch(0.208 0.042 265.755); + --popover-foreground: oklch(0.984 0.003 247.858); + --primary: oklch(0.929 0.013 255.508); + --primary-foreground: oklch(0.208 0.042 265.755); + --secondary: oklch(0.279 0.041 260.031); + --secondary-foreground: oklch(0.984 0.003 247.858); + --muted: oklch(0.279 0.041 260.031); + --muted-foreground: oklch(0.704 0.04 256.788); + --accent: oklch(0.279 0.041 260.031); + --accent-foreground: oklch(0.984 0.003 247.858); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.551 0.027 264.364); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.208 0.042 265.755); + --sidebar-foreground: oklch(0.984 0.003 247.858); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.984 0.003 247.858); + --sidebar-accent: oklch(0.279 0.041 260.031); + --sidebar-accent-foreground: oklch(0.984 0.003 247.858); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.551 0.027 264.364); +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} + +@layer utilities { + /* Hide scrollbar for Chrome, Safari, and Opera */ + .no-scrollbar::-webkit-scrollbar { + display: none; + } + + /* Hide scrollbar for IE, Edge, and Firefox */ + .no-scrollbar { + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + } +} diff --git a/apps/ensadmin/tailwind.config.ts b/apps/ensadmin/tailwind.config.ts deleted file mode 100644 index 0ca46fb0d..000000000 --- a/apps/ensadmin/tailwind.config.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { Config } from "tailwindcss"; -import tailwindAnimatePlugin from "tailwindcss-animate"; - -export default { - darkMode: ["class"], - content: ["./src/components/**/*.{js,ts,jsx,tsx,mdx}", "./src/app/**/*.{js,ts,jsx,tsx,mdx}"], - theme: { - extend: { - colors: { - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", - card: { - DEFAULT: "hsl(var(--card))", - foreground: "hsl(var(--card-foreground))", - }, - popover: { - DEFAULT: "hsl(var(--popover))", - foreground: "hsl(var(--popover-foreground))", - }, - primary: { - DEFAULT: "hsl(var(--primary))", - foreground: "hsl(var(--primary-foreground))", - }, - secondary: { - DEFAULT: "hsl(var(--secondary))", - foreground: "hsl(var(--secondary-foreground))", - }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, - accent: { - DEFAULT: "hsl(var(--accent))", - foreground: "hsl(var(--accent-foreground))", - }, - destructive: { - DEFAULT: "hsl(var(--destructive))", - foreground: "hsl(var(--destructive-foreground))", - }, - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - chart: { - "1": "hsl(var(--chart-1))", - "2": "hsl(var(--chart-2))", - "3": "hsl(var(--chart-3))", - "4": "hsl(var(--chart-4))", - "5": "hsl(var(--chart-5))", - }, - sidebar: { - DEFAULT: "hsl(var(--sidebar-background))", - foreground: "hsl(var(--sidebar-foreground))", - primary: "hsl(var(--sidebar-primary))", - "primary-foreground": "hsl(var(--sidebar-primary-foreground))", - accent: "hsl(var(--sidebar-accent))", - "accent-foreground": "hsl(var(--sidebar-accent-foreground))", - border: "hsl(var(--sidebar-border))", - ring: "hsl(var(--sidebar-ring))", - }, - }, - borderRadius: { - lg: "var(--radius)", - md: "calc(var(--radius) - 2px)", - sm: "calc(var(--radius) - 4px)", - }, - }, - }, - plugins: [tailwindAnimatePlugin], -} satisfies Config; diff --git a/apps/ensadmin/tsconfig.json b/apps/ensadmin/tsconfig.json index fc3094790..7920df93f 100644 --- a/apps/ensadmin/tsconfig.json +++ b/apps/ensadmin/tsconfig.json @@ -1,34 +1,28 @@ { + "include": ["**/*.ts", "**/*.tsx"], "compilerOptions": { - "target": "ES2020", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, + "target": "ES2022", + "jsx": "react-jsx", + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "types": ["vite/client"], + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + /* Linting */ "skipLibCheck": true, "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "react-jsx", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true, + "baseUrl": ".", "paths": { "@/*": ["./src/*"], - "react": ["./node_modules/@types/react"] } - }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts", - ".next/dev/types/**/*.ts" - ], - "exclude": ["node_modules"] + } } diff --git a/apps/ensadmin/vite.config.ts b/apps/ensadmin/vite.config.ts new file mode 100644 index 000000000..82addebd8 --- /dev/null +++ b/apps/ensadmin/vite.config.ts @@ -0,0 +1,23 @@ +import { defineConfig } from 'vite' +import viteReact from '@vitejs/plugin-react' +import tailwindcss from '@tailwindcss/vite' + +import { tanstackRouter } from '@tanstack/router-plugin/vite' +import { fileURLToPath, URL } from 'node:url' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + tanstackRouter({ + target: 'react', + autoCodeSplitting: true, + }), + viteReact(), + tailwindcss(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + }, + }, +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3c804a931..1cb2dbb32 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -167,7 +167,7 @@ importers: specifier: ^1.1.2 version: 1.1.7(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@radix-ui/react-slot': - specifier: ^1.1.2 + specifier: ^1.2.3 version: 1.2.3(@types/react@19.2.2)(react@19.2.0) '@radix-ui/react-tabs': specifier: ^1.1.13 @@ -175,9 +175,27 @@ importers: '@radix-ui/react-tooltip': specifier: ^1.1.8 version: 1.2.8(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@tailwindcss/vite': + specifier: ^4.1.16 + version: 4.1.16(vite@7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1)) + '@tanstack/react-devtools': + specifier: ^0.7.0 + version: 0.7.11(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(csstype@3.1.3)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(solid-js@1.9.10) '@tanstack/react-query': - specifier: ^5.66.9 + specifier: ^5.90.5 version: 5.90.5(react@19.2.0) + '@tanstack/react-query-devtools': + specifier: ^5.90.2 + version: 5.90.2(@tanstack/react-query@5.90.5(react@19.2.0))(react@19.2.0) + '@tanstack/react-router': + specifier: ^1.132.0 + version: 1.133.36(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@tanstack/react-router-devtools': + specifier: ^1.132.0 + version: 1.133.36(@tanstack/react-router@1.133.36(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.133.36)(@types/node@22.18.13)(csstype@3.1.3)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(solid-js@1.9.10)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1) + '@tanstack/router-plugin': + specifier: ^1.132.0 + version: 1.133.36(@tanstack/react-router@1.133.36(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1)) '@xyflow/react': specifier: ^12.4.4 version: 12.9.1(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -203,19 +221,13 @@ importers: specifier: ^16.10.0 version: 16.11.0 lucide-react: - specifier: ^0.548.0 - version: 0.548.0(react@19.2.0) - next: - specifier: 16.0.1 - version: 16.0.1(@opentelemetry/api@1.9.0(patch_hash=4b2adeefaf7c22f9987d0a125d69cab900719bec7ed7636648bea6947107033a))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - next-themes: - specifier: ^0.4.6 - version: 0.4.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + specifier: ^0.545.0 + version: 0.545.0(react@19.2.0) react: - specifier: ^19 + specifier: ^19.2.0 version: 19.2.0 react-dom: - specifier: ^19 + specifier: ^19.2.0 version: 19.2.0(react@19.2.0) rooks: specifier: ^8.4.0 @@ -227,36 +239,57 @@ importers: specifier: ^2.0.3 version: 2.0.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0) tailwind-merge: - specifier: ^3.0.2 + specifier: ^3.3.1 version: 3.3.1 + tailwindcss: + specifier: ^4.1.5 + version: 4.1.5 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@3.4.17) + version: 1.0.7(tailwindcss@4.1.5) viem: specifier: 'catalog:' version: 2.38.5(typescript@5.9.3)(zod@3.25.76) devDependencies: + '@biomejs/biome': + specifier: 2.2.4 + version: 2.2.4 + '@testing-library/dom': + specifier: ^10.4.0 + version: 10.4.1 + '@testing-library/react': + specifier: ^16.2.0 + version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@types/node': - specifier: ^22 + specifier: ^22.18.13 version: 22.18.13 '@types/react': - specifier: ^19 + specifier: ^19.2.0 version: 19.2.2 '@types/react-dom': - specifier: ^19 + specifier: ^19.2.0 version: 19.2.2(@types/react@19.2.2) - postcss: - specifier: ^8 - version: 8.5.6 - tailwindcss: - specifier: ^3.4.17 - version: 3.4.17 + '@vitejs/plugin-react': + specifier: ^5.0.4 + version: 5.1.0(vite@7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1)) + jsdom: + specifier: ^27.0.0 + version: 27.0.1(postcss@8.5.6) + tw-animate-css: + specifier: ^1.4.0 + version: 1.4.0 typescript: - specifier: ^5 + specifier: ^5.7.2 version: 5.9.3 + vite: + specifier: ^7.1.7 + version: 7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) vitest: specifier: 'catalog:' version: 4.0.5(@types/debug@4.1.12)(@types/node@22.18.13)(jiti@2.6.1)(jsdom@27.0.1(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + web-vitals: + specifier: ^5.1.0 + version: 5.1.0 apps/ensapi: dependencies: @@ -977,14 +1010,28 @@ packages: resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.27.2': resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} + '@babel/helper-create-class-features-plugin@7.28.5': + resolution: {integrity: sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/helper-globals@7.28.0': resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} + '@babel/helper-member-expression-to-functions@7.28.5': + resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.27.1': resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} @@ -995,10 +1042,24 @@ packages: peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + '@babel/helper-plugin-utils@7.27.1': resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} + '@babel/helper-replace-supers@7.27.1': + resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -1020,6 +1081,24 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/plugin-syntax-jsx@7.27.1': + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.27.1': + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.27.1': + resolution: {integrity: sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-react-jsx-self@7.27.1': resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} engines: {node: '>=6.9.0'} @@ -1032,6 +1111,18 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-typescript@7.28.5': + resolution: {integrity: sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.28.5': + resolution: {integrity: sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/runtime@7.28.4': resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} @@ -1048,53 +1139,106 @@ packages: resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} + '@biomejs/biome@2.2.4': + resolution: {integrity: sha512-TBHU5bUy/Ok6m8c0y3pZiuO/BZoY/OcGxoLlrfQof5s8ISVwbVBdFINPQZyFfKwil8XibYWb7JMwnT8wT4WVPg==} + engines: {node: '>=14.21.3'} + hasBin: true + '@biomejs/biome@2.3.2': resolution: {integrity: sha512-8e9tzamuDycx7fdrcJ/F/GDZ8SYukc5ud6tDicjjFqURKYFSWMl0H0iXNXZEGmcmNUmABgGuHThPykcM41INgg==} engines: {node: '>=14.21.3'} hasBin: true + '@biomejs/cli-darwin-arm64@2.2.4': + resolution: {integrity: sha512-RJe2uiyaloN4hne4d2+qVj3d3gFJFbmrr5PYtkkjei1O9c+BjGXgpUPVbi8Pl8syumhzJjFsSIYkcLt2VlVLMA==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [darwin] + '@biomejs/cli-darwin-arm64@2.3.2': resolution: {integrity: sha512-4LECm4kc3If0JISai4c3KWQzukoUdpxy4fRzlrPcrdMSRFksR9ZoXK7JBcPuLBmd2SoT4/d7CQS33VnZpgBjew==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] + '@biomejs/cli-darwin-x64@2.2.4': + resolution: {integrity: sha512-cFsdB4ePanVWfTnPVaUX+yr8qV8ifxjBKMkZwN7gKb20qXPxd/PmwqUH8mY5wnM9+U0QwM76CxFyBRJhC9tQwg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [darwin] + '@biomejs/cli-darwin-x64@2.3.2': resolution: {integrity: sha512-jNMnfwHT4N3wi+ypRfMTjLGnDmKYGzxVr1EYAPBcauRcDnICFXN81wD6wxJcSUrLynoyyYCdfW6vJHS/IAoTDA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] + '@biomejs/cli-linux-arm64-musl@2.2.4': + resolution: {integrity: sha512-7TNPkMQEWfjvJDaZRSkDCPT/2r5ESFPKx+TEev+I2BXDGIjfCZk2+b88FOhnJNHtksbOZv8ZWnxrA5gyTYhSsQ==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + '@biomejs/cli-linux-arm64-musl@2.3.2': resolution: {integrity: sha512-2Zz4usDG1GTTPQnliIeNx6eVGGP2ry5vE/v39nT73a3cKN6t5H5XxjcEoZZh62uVZvED7hXXikclvI64vZkYqw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + '@biomejs/cli-linux-arm64@2.2.4': + resolution: {integrity: sha512-M/Iz48p4NAzMXOuH+tsn5BvG/Jb07KOMTdSVwJpicmhN309BeEyRyQX+n1XDF0JVSlu28+hiTQ2L4rZPvu7nMw==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + '@biomejs/cli-linux-arm64@2.3.2': resolution: {integrity: sha512-amnqvk+gWybbQleRRq8TMe0rIv7GHss8mFJEaGuEZYWg1Tw14YKOkeo8h6pf1c+d3qR+JU4iT9KXnBKGON4klw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] + '@biomejs/cli-linux-x64-musl@2.2.4': + resolution: {integrity: sha512-m41nFDS0ksXK2gwXL6W6yZTYPMH0LughqbsxInSKetoH6morVj43szqKx79Iudkp8WRT5SxSh7qVb8KCUiewGg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + '@biomejs/cli-linux-x64-musl@2.3.2': resolution: {integrity: sha512-gzB19MpRdTuOuLtPpFBGrV3Lq424gHyq2lFj8wfX9tvLMLdmA/R9C7k/mqBp/spcbWuHeIEKgEs3RviOPcWGBA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + '@biomejs/cli-linux-x64@2.2.4': + resolution: {integrity: sha512-orr3nnf2Dpb2ssl6aihQtvcKtLySLta4E2UcXdp7+RTa7mfJjBgIsbS0B9GC8gVu0hjOu021aU8b3/I1tn+pVQ==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + '@biomejs/cli-linux-x64@2.3.2': resolution: {integrity: sha512-8BG/vRAhFz1pmuyd24FQPhNeueLqPtwvZk6yblABY2gzL2H8fLQAF/Z2OPIc+BPIVPld+8cSiKY/KFh6k81xfA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] + '@biomejs/cli-win32-arm64@2.2.4': + resolution: {integrity: sha512-NXnfTeKHDFUWfxAefa57DiGmu9VyKi0cDqFpdI+1hJWQjGJhJutHPX0b5m+eXvTKOaf+brU+P0JrQAZMb5yYaQ==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [win32] + '@biomejs/cli-win32-arm64@2.3.2': resolution: {integrity: sha512-lCruqQlfWjhMlOdyf5pDHOxoNm4WoyY2vZ4YN33/nuZBRstVDuqPPjS0yBkbUlLEte11FbpW+wWSlfnZfSIZvg==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] + '@biomejs/cli-win32-x64@2.2.4': + resolution: {integrity: sha512-3Y4V4zVRarVh/B/eSHczR4LYoSVyv3Dfuvm3cWs5w/HScccS0+Wt/lHOcDTRYeHjQmMYVC3rIRWqyN2EI52+zg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [win32] + '@biomejs/cli-win32-x64@2.3.2': resolution: {integrity: sha512-6Ee9P26DTb4D8sN9nXxgbi9Dw5vSOfH98M7UlmkjKB2vtUbrRqCbZiNfryGiwnPIpd6YUoTl7rLVD2/x1CyEHQ==} engines: {node: '>=14.21.3'} @@ -1978,57 +2122,6 @@ packages: react: ^18 react-dom: ^18 - '@next/env@16.0.1': - resolution: {integrity: sha512-LFvlK0TG2L3fEOX77OC35KowL8D7DlFF45C0OvKMC4hy8c/md1RC4UMNDlUGJqfCoCS2VWrZ4dSE6OjaX5+8mw==} - - '@next/swc-darwin-arm64@16.0.1': - resolution: {integrity: sha512-R0YxRp6/4W7yG1nKbfu41bp3d96a0EalonQXiMe+1H9GTHfKxGNCGFNWUho18avRBPsO8T3RmdWuzmfurlQPbg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@next/swc-darwin-x64@16.0.1': - resolution: {integrity: sha512-kETZBocRux3xITiZtOtVoVvXyQLB7VBxN7L6EPqgI5paZiUlnsgYv4q8diTNYeHmF9EiehydOBo20lTttCbHAg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@next/swc-linux-arm64-gnu@16.0.1': - resolution: {integrity: sha512-hWg3BtsxQuSKhfe0LunJoqxjO4NEpBmKkE+P2Sroos7yB//OOX3jD5ISP2wv8QdUwtRehMdwYz6VB50mY6hqAg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-arm64-musl@16.0.1': - resolution: {integrity: sha512-UPnOvYg+fjAhP3b1iQStcYPWeBFRLrugEyK/lDKGk7kLNua8t5/DvDbAEFotfV1YfcOY6bru76qN9qnjLoyHCQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-x64-gnu@16.0.1': - resolution: {integrity: sha512-Et81SdWkcRqAJziIgFtsFyJizHoWne4fzJkvjd6V4wEkWTB4MX6J0uByUb0peiJQ4WeAt6GGmMszE5KrXK6WKg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-linux-x64-musl@16.0.1': - resolution: {integrity: sha512-qBbgYEBRrC1egcG03FZaVfVxrJm8wBl7vr8UFKplnxNRprctdP26xEv9nJ07Ggq4y1adwa0nz2mz83CELY7N6Q==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-win32-arm64-msvc@16.0.1': - resolution: {integrity: sha512-cPuBjYP6I699/RdbHJonb3BiRNEDm5CKEBuJ6SD8k3oLam2fDRMKAvmrli4QMDgT2ixyRJ0+DTkiODbIQhRkeQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@next/swc-win32-x64-msvc@16.0.1': - resolution: {integrity: sha512-XeEUJsE4JYtfrXe/LaJn3z1pD19fK0Q6Er8Qoufi+HqvdO4LEPyCxLUt4rxA+4RfYo6S9gMlmzCMU2F+AatFqQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - '@noble/ciphers@1.3.0': resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==} engines: {node: ^14.21.3 || >=16} @@ -2873,6 +2966,9 @@ packages: '@rolldown/pluginutils@1.0.0-beta.27': resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} + '@rolldown/pluginutils@1.0.0-beta.43': + resolution: {integrity: sha512-5Uxg7fQUCmfhax7FJke2+8B6cqgeUJUD9o2uXIKXhD+mG0mL6NObmVoi9wXEU1tY89mZKgAYA6fTbftx3q2ZPQ==} + '@rollup/pluginutils@5.3.0': resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} engines: {node: '>=14.0.0'} @@ -3031,12 +3127,39 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + '@solid-primitives/event-listener@2.4.3': + resolution: {integrity: sha512-h4VqkYFv6Gf+L7SQj+Y6puigL/5DIi7x5q07VZET7AWcS+9/G3WfIE9WheniHWJs51OEkRB43w6lDys5YeFceg==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/keyboard@1.3.3': + resolution: {integrity: sha512-9dQHTTgLBqyAI7aavtO+HnpTVJgWQA1ghBSrmLtMu1SMxLPDuLfuNr+Tk5udb4AL4Ojg7h9JrKOGEEDqsJXWJA==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/resize-observer@2.1.3': + resolution: {integrity: sha512-zBLje5E06TgOg93S7rGPldmhDnouNGhvfZVKOp+oG2XU8snA+GoCSSCz1M+jpNAg5Ek2EakU5UVQqL152WmdXQ==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/rootless@1.5.2': + resolution: {integrity: sha512-9HULb0QAzL2r47CCad0M+NKFtQ+LrGGNHZfteX/ThdGvKIg2o2GYhBooZubTCd/RTu2l2+Nw4s+dEfiDGvdrrQ==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/static-store@0.1.2': + resolution: {integrity: sha512-ReK+5O38lJ7fT+L6mUFvUr6igFwHBESZF+2Ug842s7fvlVeBdIVEdTCErygff6w7uR6+jrr7J8jQo+cYrEq4Iw==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/utils@6.3.2': + resolution: {integrity: sha512-hZ/M/qr25QOCcwDPOHtGjxTD8w2mNyVAYvcfgwzBHq2RwNqHNdDNsMZYap20+ruRwW4A3Cdkczyoz0TSxLCAPQ==} + peerDependencies: + solid-js: ^1.6.12 + '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} - '@swc/helpers@0.5.15': - resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} @@ -3130,23 +3253,142 @@ packages: peerDependencies: vite: 7.1.11 + '@tanstack/devtools-client@0.0.3': + resolution: {integrity: sha512-kl0r6N5iIL3t9gGDRAv55VRM3UIyMKVH83esRGq7xBjYsRLe/BeCIN2HqrlJkObUXQMKhy7i8ejuGOn+bDqDBw==} + engines: {node: '>=18'} + + '@tanstack/devtools-event-bus@0.3.3': + resolution: {integrity: sha512-lWl88uLAz7ZhwNdLH6A3tBOSEuBCrvnY9Fzr5JPdzJRFdM5ZFdyNWz1Bf5l/F3GU57VodrN0KCFi9OA26H5Kpg==} + engines: {node: '>=18'} + + '@tanstack/devtools-event-client@0.3.4': + resolution: {integrity: sha512-eq+PpuutUyubXu+ycC1GIiVwBs86NF/8yYJJAKSpPcJLWl6R/761F1H4F/9ziX6zKezltFUH1ah3Cz8Ah+KJrw==} + engines: {node: '>=18'} + + '@tanstack/devtools-ui@0.4.4': + resolution: {integrity: sha512-5xHXFyX3nom0UaNfiOM92o6ziaHjGo3mcSGe2HD5Xs8dWRZNpdZ0Smd0B9ddEhy0oB+gXyMzZgUJb9DmrZV0Mg==} + engines: {node: '>=18'} + peerDependencies: + solid-js: '>=1.9.7' + + '@tanstack/devtools@0.7.0': + resolution: {integrity: sha512-AlAoCqJhWLg9GBEaoV1g/j+X/WA1aJSWOsekxeuZpYeS2hdVuKAjj04KQLUMJhtLfNl2s2E+TCj7ZRtWyY3U4w==} + engines: {node: '>=18'} + peerDependencies: + solid-js: '>=1.9.7' + + '@tanstack/history@1.133.28': + resolution: {integrity: sha512-B7+x7eP2FFvi3fgd3rNH9o/Eixt+pp0zCIdGhnQbAJjFrlwIKGjGnwyJjhWJ5fMQlGks/E2LdDTqEV4W9Plx7g==} + engines: {node: '>=12'} + '@tanstack/query-core@5.90.5': resolution: {integrity: sha512-wLamYp7FaDq6ZnNehypKI5fNvxHPfTYylE0m/ZpuuzJfJqhR5Pxg9gvGBHZx4n7J+V5Rg5mZxHHTlv25Zt5u+w==} + '@tanstack/query-devtools@5.90.1': + resolution: {integrity: sha512-GtINOPjPUH0OegJExZ70UahT9ykmAhmtNVcmtdnOZbxLwT7R5OmRztR5Ahe3/Cu7LArEmR6/588tAycuaWb1xQ==} + + '@tanstack/react-devtools@0.7.11': + resolution: {integrity: sha512-a2Lmz8x+JoDrsU6f7uKRcyyY+k8mA/n5mb9h7XJ3Fz/y3+sPV9t7vAW1s5lyNkQyyDt6V1Oim99faLthoJSxMw==} + engines: {node: '>=18'} + peerDependencies: + '@types/react': '>=16.8' + '@types/react-dom': '>=16.8' + react: '>=16.8' + react-dom: '>=16.8' + + '@tanstack/react-query-devtools@5.90.2': + resolution: {integrity: sha512-vAXJzZuBXtCQtrY3F/yUNJCV4obT/A/n81kb3+YqLbro5Z2+phdAbceO+deU3ywPw8B42oyJlp4FhO0SoivDFQ==} + peerDependencies: + '@tanstack/react-query': ^5.90.2 + react: ^18 || ^19 + '@tanstack/react-query@5.90.5': resolution: {integrity: sha512-pN+8UWpxZkEJ/Rnnj2v2Sxpx1WFlaa9L6a4UO89p6tTQbeo+m0MS8oYDjbggrR8QcTyjKoYWKS3xJQGr3ExT8Q==} peerDependencies: react: ^18 || ^19 + '@tanstack/react-router-devtools@1.133.36': + resolution: {integrity: sha512-il+DNzc8Ia54N+HOmIlY10NBk7rp0N7Nyysk8eeC1ZSIXImC3MPchdAspwioE6DI7WfK+MfpTav2m9zoOL8wSQ==} + engines: {node: '>=12'} + peerDependencies: + '@tanstack/react-router': ^1.133.36 + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-router@1.133.36': + resolution: {integrity: sha512-pT4d2uEucDQ3SAIQ0pLUw6RUKwkB5pHzpBB6otaoKpO0cAwHkRPi+p59DivuzSANJLHLVEiXyJCCk72EeHMRxA==} + engines: {node: '>=12'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-store@0.8.0': + resolution: {integrity: sha512-1vG9beLIuB7q69skxK9r5xiLN3ztzIPfSQSs0GfeqWGO2tGIyInZx0x1COhpx97RKaONSoAb8C3dxacWksm1ow==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + '@tanstack/react-virtual@3.13.12': resolution: {integrity: sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + '@tanstack/router-core@1.133.36': + resolution: {integrity: sha512-VJ9kFduePsxgjhDW+uKxL6ol9ZpJlaUO2EI9Zmq8AA6uhW/LRg+0/365OZOZaVqNqvx2eKt3MZKHLN+29jd5Uw==} + engines: {node: '>=12'} + + '@tanstack/router-devtools-core@1.133.36': + resolution: {integrity: sha512-jgXSCfWPLukcjXDf4thpk/0QgLXv61mrvmfh9xc8+xeC5TMeLyz2xBaTghniD2PtdF6eII3vMaTWOpMHj4+cVQ==} + engines: {node: '>=12'} + peerDependencies: + '@tanstack/router-core': ^1.133.36 + csstype: ^3.0.10 + solid-js: '>=1.9.5' + tiny-invariant: ^1.3.3 + peerDependenciesMeta: + csstype: + optional: true + + '@tanstack/router-generator@1.133.36': + resolution: {integrity: sha512-3+pJBqkm95/zV7INyhbr688lp1PklZT3wtNNwW9oIxmsBiUJg5hqHWh7z4JgP9E+0D0KAwT535wncWUFfMMZwA==} + engines: {node: '>=12'} + + '@tanstack/router-plugin@1.133.36': + resolution: {integrity: sha512-y0vttpDRFbniPk2EOS93wxfNA0SqvD/anj6kXTIl/3caW0rvOC4MzMXV09atJ+3jMSOgHFniljKQj/66AY5dZg==} + engines: {node: '>=12'} + peerDependencies: + '@rsbuild/core': '>=1.0.2' + '@tanstack/react-router': ^1.133.36 + vite: '>=5.0.0 || >=6.0.0 || >=7.0.0' + vite-plugin-solid: ^2.11.10 + webpack: '>=5.92.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + '@tanstack/react-router': + optional: true + vite: + optional: true + vite-plugin-solid: + optional: true + webpack: + optional: true + + '@tanstack/router-utils@1.133.19': + resolution: {integrity: sha512-WEp5D2gPxvlLDRXwD/fV7RXjYtqaqJNXKB/L6OyZEbT+9BG/Ib2d7oG9GSUZNNMGPGYAlhBUOi3xutySsk6rxA==} + engines: {node: '>=12'} + + '@tanstack/store@0.8.0': + resolution: {integrity: sha512-Om+BO0YfMZe//X2z0uLF2j+75nQga6TpTJgLJQBiq85aOyZNIhkCgleNcud2KQg4k4v9Y9l+Uhru3qWMPGTOzQ==} + '@tanstack/virtual-core@3.13.12': resolution: {integrity: sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==} + '@tanstack/virtual-file-routes@1.133.19': + resolution: {integrity: sha512-IKwZENsK7owmW1Lm5FhuHegY/SyQ8KqtL/7mTSnzoKJgfzhrrf9qwKB1rmkKkt+svUuy/Zw3uVEpZtUzQruWtA==} + engines: {node: '>=12'} + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -3403,6 +3645,12 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@vitejs/plugin-react@5.1.0': + resolution: {integrity: sha512-4LuWrg7EKWgQaMJfnN+wcmbAW+VSsCmqGohftWjuct47bv8uE4n/nPpq4XjJPsxgq00GGG5J8dvBczp8uxScew==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@vitest/expect@4.0.5': resolution: {integrity: sha512-DJctLVlKoddvP/G389oGmKWNG6GD9frm2FPXARziU80Rjo7SIYxQzb2YFzmQ4fVD3Q5utUYY8nUmWrqsuIlIXQ==} @@ -3610,6 +3858,10 @@ packages: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} + ansis@4.2.0: + resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} + engines: {node: '>=14'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -3651,6 +3903,10 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + astring@1.9.0: resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} hasBin: true @@ -3712,6 +3968,9 @@ packages: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} + babel-dead-code-elimination@1.0.10: + resolution: {integrity: sha512-DV5bdJZTzZ0zn0DC24v3jD7Mnidh6xhKa4GfKCbq3sfW8kaWhDdZjP3i81geA8T33tdYqWKw4D3fVv0CwEgKVA==} + bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} @@ -4032,6 +4291,9 @@ packages: cookie-es@1.2.2: resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} + cookie-es@2.0.0: + resolution: {integrity: sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg==} + cookie@1.0.2: resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} engines: {node: '>=18'} @@ -4382,6 +4644,10 @@ packages: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} + diff@8.0.2: + resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} + engines: {node: '>=0.3.1'} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -4865,6 +5131,11 @@ packages: globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + goober@2.1.18: + resolution: {integrity: sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==} + peerDependencies: + csstype: ^3.0.10 + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -5193,6 +5464,10 @@ packages: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} engines: {node: '>=16'} + isbot@5.1.31: + resolution: {integrity: sha512-DPgQshehErHAqSCKDb3rNW03pa2wS/v5evvUqtxt6TTnHRqAG8FdzcSSJs9656pK6Y+NT7K9R4acEYXLHYfpUQ==} + engines: {node: '>=18'} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -5448,8 +5723,8 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - lucide-react@0.548.0: - resolution: {integrity: sha512-63b16z63jM9yc1MwxajHeuu0FRZFsDtljtDjYm26Kd86UQ5HQzu9ksEtoUUw4RBuewodw/tGFmvipePvRsKeDA==} + lucide-react@0.545.0: + resolution: {integrity: sha512-7r1/yUuflQDSt4f1bpn5ZAocyIxcTyVyBBChSVtBKn5M+392cPmI5YJMWOJKk/HUWGm5wg83chlAZtCcGbEZtw==} peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -5813,33 +6088,6 @@ packages: resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} engines: {node: '>= 10'} - next-themes@0.4.6: - resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} - peerDependencies: - react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - - next@16.0.1: - resolution: {integrity: sha512-e9RLSssZwd35p7/vOa+hoDFggUZIUbZhIUSLZuETCwrCVvxOs87NamoUzT+vbcNAL8Ld9GobBnWOA6SbV/arOw==} - engines: {node: '>=20.9.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.51.1 - babel-plugin-react-compiler: '*' - react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - babel-plugin-react-compiler: - optional: true - sass: - optional: true - nlcst-to-string@4.0.0: resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==} @@ -6248,10 +6496,6 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -6386,6 +6630,10 @@ packages: resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} + react-refresh@0.18.0: + resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} + engines: {node: '>=0.10.0'} + react-remove-scroll-bar@2.3.8: resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} engines: {node: '>=10'} @@ -6452,6 +6700,10 @@ packages: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + engines: {node: '>= 4'} + recma-build-jsx@1.0.0: resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} @@ -6653,6 +6905,16 @@ packages: engines: {node: '>=10'} hasBin: true + seroval-plugins@1.3.3: + resolution: {integrity: sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + + seroval@1.3.2: + resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==} + engines: {node: '>=10'} + serve-handler@6.1.6: resolution: {integrity: sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==} @@ -6716,6 +6978,9 @@ packages: resolution: {integrity: sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g==} engines: {node: '>= 18'} + solid-js@1.9.10: + resolution: {integrity: sha512-Coz956cos/EPDlhs6+jsdTxKuJDPT7B5SVIWgABwROyxjY7Xbr8wkzD68Et+NxnV7DLJ3nJdAC2r9InuV/4Jew==} + sonic-boom@3.8.1: resolution: {integrity: sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==} @@ -6736,6 +7001,10 @@ packages: resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} engines: {node: '>=0.10.0'} + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + source-map@0.7.6: resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} engines: {node: '>= 12'} @@ -6857,19 +7126,6 @@ packages: style-to-object@1.0.11: resolution: {integrity: sha512-5A560JmXr7wDyGLK12Nq/EYS38VkGlglVzkis1JEdbGWSnbQIEhZzTJhzURXN5/8WwwFCs/f/VVcmkTppbXLow==} - styled-jsx@5.1.6: - resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - stylis@4.3.6: resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} @@ -6955,6 +7211,12 @@ packages: tiny-inflate@1.0.3: resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -7057,6 +7319,9 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + tw-animate-css@1.4.0: + resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} + type-fest@0.7.1: resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} engines: {node: '>=8'} @@ -7162,6 +7427,10 @@ packages: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} + unplugin@2.3.10: + resolution: {integrity: sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==} + engines: {node: '>=18.12.0'} + unstorage@1.17.1: resolution: {integrity: sha512-KKGwRTT0iVBCErKemkJCLs7JdxNVfqTPc/85ae1XES0+bsHbc/sFBfVi5kJp156cc51BHinIH2l3k0EZ24vOBQ==} peerDependencies: @@ -7582,6 +7851,9 @@ packages: web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + web-vitals@5.1.0: + resolution: {integrity: sha512-ArI3kx5jI0atlTtmV0fWU3fjpLmq/nD3Zr1iFFlJLaqa5wLBkUSzINwBPySCX/8jRyjlmy1Volw1kz1g9XE4Jg==} + webauthn-p256@0.0.5: resolution: {integrity: sha512-drMGNWKdaixZNobeORVIqq7k5DsRC9FnG201K2QjeOoQLmtSDaSsVZdkg6n5jUALJKcAG++zBPJXmv6hy0nWFg==} @@ -7595,6 +7867,9 @@ packages: resolution: {integrity: sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==} engines: {node: '>=20'} + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} @@ -8051,6 +8326,10 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.28.5 + '@babel/helper-compilation-targets@7.27.2': dependencies: '@babel/compat-data': 7.28.5 @@ -8059,12 +8338,32 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-globals@7.28.0': {} - - '@babel/helper-module-imports@7.27.1': + '@babel/helper-create-class-features-plugin@7.28.5(@babel/core@7.28.5)': dependencies: + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.5) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.28.5': + dependencies: + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color @@ -8077,8 +8376,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.28.5 + '@babel/helper-plugin-utils@7.27.1': {} + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + transitivePeerDependencies: + - supports-color + '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.28.5': {} @@ -8094,6 +8413,24 @@ snapshots: dependencies: '@babel/types': 7.28.5 + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)': dependencies: '@babel/core': 7.28.5 @@ -8104,6 +8441,28 @@ snapshots: '@babel/core': 7.28.5 '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-typescript@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) + transitivePeerDependencies: + - supports-color + + '@babel/preset-typescript@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-typescript': 7.28.5(@babel/core@7.28.5) + transitivePeerDependencies: + - supports-color + '@babel/runtime@7.28.4': {} '@babel/template@7.27.2': @@ -8129,6 +8488,17 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@biomejs/biome@2.2.4': + optionalDependencies: + '@biomejs/cli-darwin-arm64': 2.2.4 + '@biomejs/cli-darwin-x64': 2.2.4 + '@biomejs/cli-linux-arm64': 2.2.4 + '@biomejs/cli-linux-arm64-musl': 2.2.4 + '@biomejs/cli-linux-x64': 2.2.4 + '@biomejs/cli-linux-x64-musl': 2.2.4 + '@biomejs/cli-win32-arm64': 2.2.4 + '@biomejs/cli-win32-x64': 2.2.4 + '@biomejs/biome@2.3.2': optionalDependencies: '@biomejs/cli-darwin-arm64': 2.3.2 @@ -8140,27 +8510,51 @@ snapshots: '@biomejs/cli-win32-arm64': 2.3.2 '@biomejs/cli-win32-x64': 2.3.2 + '@biomejs/cli-darwin-arm64@2.2.4': + optional: true + '@biomejs/cli-darwin-arm64@2.3.2': optional: true + '@biomejs/cli-darwin-x64@2.2.4': + optional: true + '@biomejs/cli-darwin-x64@2.3.2': optional: true + '@biomejs/cli-linux-arm64-musl@2.2.4': + optional: true + '@biomejs/cli-linux-arm64-musl@2.3.2': optional: true + '@biomejs/cli-linux-arm64@2.2.4': + optional: true + '@biomejs/cli-linux-arm64@2.3.2': optional: true + '@biomejs/cli-linux-x64-musl@2.2.4': + optional: true + '@biomejs/cli-linux-x64-musl@2.3.2': optional: true + '@biomejs/cli-linux-x64@2.2.4': + optional: true + '@biomejs/cli-linux-x64@2.3.2': optional: true + '@biomejs/cli-win32-arm64@2.2.4': + optional: true + '@biomejs/cli-win32-arm64@2.3.2': optional: true + '@biomejs/cli-win32-x64@2.2.4': + optional: true + '@biomejs/cli-win32-x64@2.3.2': optional: true @@ -9220,32 +9614,6 @@ snapshots: - utf-8-validate - zod - '@next/env@16.0.1': {} - - '@next/swc-darwin-arm64@16.0.1': - optional: true - - '@next/swc-darwin-x64@16.0.1': - optional: true - - '@next/swc-linux-arm64-gnu@16.0.1': - optional: true - - '@next/swc-linux-arm64-musl@16.0.1': - optional: true - - '@next/swc-linux-x64-gnu@16.0.1': - optional: true - - '@next/swc-linux-x64-musl@16.0.1': - optional: true - - '@next/swc-win32-arm64-msvc@16.0.1': - optional: true - - '@next/swc-win32-x64-msvc@16.0.1': - optional: true - '@noble/ciphers@1.3.0': {} '@noble/curves@1.4.0': @@ -10188,6 +10556,8 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.27': {} + '@rolldown/pluginutils@1.0.0-beta.43': {} + '@rollup/pluginutils@5.3.0(rollup@4.52.5)': dependencies: '@types/estree': 1.0.8 @@ -10321,11 +10691,41 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} - '@standard-schema/spec@1.0.0': {} + '@solid-primitives/event-listener@2.4.3(solid-js@1.9.10)': + dependencies: + '@solid-primitives/utils': 6.3.2(solid-js@1.9.10) + solid-js: 1.9.10 - '@swc/helpers@0.5.15': + '@solid-primitives/keyboard@1.3.3(solid-js@1.9.10)': dependencies: - tslib: 2.8.1 + '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.10) + '@solid-primitives/rootless': 1.5.2(solid-js@1.9.10) + '@solid-primitives/utils': 6.3.2(solid-js@1.9.10) + solid-js: 1.9.10 + + '@solid-primitives/resize-observer@2.1.3(solid-js@1.9.10)': + dependencies: + '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.10) + '@solid-primitives/rootless': 1.5.2(solid-js@1.9.10) + '@solid-primitives/static-store': 0.1.2(solid-js@1.9.10) + '@solid-primitives/utils': 6.3.2(solid-js@1.9.10) + solid-js: 1.9.10 + + '@solid-primitives/rootless@1.5.2(solid-js@1.9.10)': + dependencies: + '@solid-primitives/utils': 6.3.2(solid-js@1.9.10) + solid-js: 1.9.10 + + '@solid-primitives/static-store@0.1.2(solid-js@1.9.10)': + dependencies: + '@solid-primitives/utils': 6.3.2(solid-js@1.9.10) + solid-js: 1.9.10 + + '@solid-primitives/utils@6.3.2(solid-js@1.9.10)': + dependencies: + solid-js: 1.9.10 + + '@standard-schema/spec@1.0.0': {} '@swc/helpers@0.5.17': dependencies: @@ -10399,13 +10799,115 @@ snapshots: tailwindcss: 4.1.16 vite: 7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + '@tanstack/devtools-client@0.0.3': + dependencies: + '@tanstack/devtools-event-client': 0.3.4 + + '@tanstack/devtools-event-bus@0.3.3': + dependencies: + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@tanstack/devtools-event-client@0.3.4': {} + + '@tanstack/devtools-ui@0.4.4(csstype@3.1.3)(solid-js@1.9.10)': + dependencies: + clsx: 2.1.1 + goober: 2.1.18(csstype@3.1.3) + solid-js: 1.9.10 + transitivePeerDependencies: + - csstype + + '@tanstack/devtools@0.7.0(csstype@3.1.3)(solid-js@1.9.10)': + dependencies: + '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.10) + '@solid-primitives/keyboard': 1.3.3(solid-js@1.9.10) + '@solid-primitives/resize-observer': 2.1.3(solid-js@1.9.10) + '@tanstack/devtools-client': 0.0.3 + '@tanstack/devtools-event-bus': 0.3.3 + '@tanstack/devtools-ui': 0.4.4(csstype@3.1.3)(solid-js@1.9.10) + clsx: 2.1.1 + goober: 2.1.18(csstype@3.1.3) + solid-js: 1.9.10 + transitivePeerDependencies: + - bufferutil + - csstype + - utf-8-validate + + '@tanstack/history@1.133.28': {} + '@tanstack/query-core@5.90.5': {} + '@tanstack/query-devtools@5.90.1': {} + + '@tanstack/react-devtools@0.7.11(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(csstype@3.1.3)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(solid-js@1.9.10)': + dependencies: + '@tanstack/devtools': 0.7.0(csstype@3.1.3)(solid-js@1.9.10) + '@types/react': 19.2.2 + '@types/react-dom': 19.2.2(@types/react@19.2.2) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + transitivePeerDependencies: + - bufferutil + - csstype + - solid-js + - utf-8-validate + + '@tanstack/react-query-devtools@5.90.2(@tanstack/react-query@5.90.5(react@19.2.0))(react@19.2.0)': + dependencies: + '@tanstack/query-devtools': 5.90.1 + '@tanstack/react-query': 5.90.5(react@19.2.0) + react: 19.2.0 + '@tanstack/react-query@5.90.5(react@19.2.0)': dependencies: '@tanstack/query-core': 5.90.5 react: 19.2.0 + '@tanstack/react-router-devtools@1.133.36(@tanstack/react-router@1.133.36(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(@tanstack/router-core@1.133.36)(@types/node@22.18.13)(csstype@3.1.3)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(solid-js@1.9.10)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1)': + dependencies: + '@tanstack/react-router': 1.133.36(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@tanstack/router-devtools-core': 1.133.36(@tanstack/router-core@1.133.36)(@types/node@22.18.13)(csstype@3.1.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + vite: 7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + transitivePeerDependencies: + - '@tanstack/router-core' + - '@types/node' + - csstype + - jiti + - less + - lightningcss + - sass + - sass-embedded + - solid-js + - stylus + - sugarss + - terser + - tiny-invariant + - tsx + - yaml + + '@tanstack/react-router@1.133.36(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@tanstack/history': 1.133.28 + '@tanstack/react-store': 0.8.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@tanstack/router-core': 1.133.36 + isbot: 5.1.31 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + '@tanstack/react-store@0.8.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@tanstack/store': 0.8.0 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + use-sync-external-store: 1.6.0(react@19.2.0) + '@tanstack/react-virtual@3.13.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@tanstack/virtual-core': 3.13.12 @@ -10418,8 +10920,93 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) + '@tanstack/router-core@1.133.36': + dependencies: + '@tanstack/history': 1.133.28 + '@tanstack/store': 0.8.0 + cookie-es: 2.0.0 + seroval: 1.3.2 + seroval-plugins: 1.3.3(seroval@1.3.2) + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + '@tanstack/router-devtools-core@1.133.36(@tanstack/router-core@1.133.36)(@types/node@22.18.13)(csstype@3.1.3)(jiti@2.6.1)(lightningcss@1.30.2)(solid-js@1.9.10)(tiny-invariant@1.3.3)(tsx@4.20.6)(yaml@2.8.1)': + dependencies: + '@tanstack/router-core': 1.133.36 + clsx: 2.1.1 + goober: 2.1.18(csstype@3.1.3) + solid-js: 1.9.10 + tiny-invariant: 1.3.3 + vite: 7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + optionalDependencies: + csstype: 3.1.3 + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + + '@tanstack/router-generator@1.133.36': + dependencies: + '@tanstack/router-core': 1.133.36 + '@tanstack/router-utils': 1.133.19 + '@tanstack/virtual-file-routes': 1.133.19 + prettier: 3.6.2 + recast: 0.23.11 + source-map: 0.7.6 + tsx: 4.20.6 + zod: 3.25.76 + transitivePeerDependencies: + - supports-color + + '@tanstack/router-plugin@1.133.36(@tanstack/react-router@1.133.36(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite@7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1))': + dependencies: + '@babel/core': 7.28.5 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@tanstack/router-core': 1.133.36 + '@tanstack/router-generator': 1.133.36 + '@tanstack/router-utils': 1.133.19 + '@tanstack/virtual-file-routes': 1.133.19 + babel-dead-code-elimination: 1.0.10 + chokidar: 3.6.0 + unplugin: 2.3.10 + zod: 3.25.76 + optionalDependencies: + '@tanstack/react-router': 1.133.36(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + vite: 7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + transitivePeerDependencies: + - supports-color + + '@tanstack/router-utils@1.133.19': + dependencies: + '@babel/core': 7.28.5 + '@babel/generator': 7.28.5 + '@babel/parser': 7.28.5 + '@babel/preset-typescript': 7.28.5(@babel/core@7.28.5) + ansis: 4.2.0 + diff: 8.0.2 + pathe: 2.0.3 + tinyglobby: 0.2.15 + transitivePeerDependencies: + - supports-color + + '@tanstack/store@0.8.0': {} + '@tanstack/virtual-core@3.13.12': {} + '@tanstack/virtual-file-routes@1.133.19': {} + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.27.1 @@ -10723,6 +11310,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitejs/plugin-react@5.1.0(vite@7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1))': + dependencies: + '@babel/core': 7.28.5 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5) + '@rolldown/pluginutils': 1.0.0-beta.43 + '@types/babel__core': 7.20.5 + react-refresh: 0.18.0 + vite: 7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + transitivePeerDependencies: + - supports-color + '@vitest/expect@4.0.5': dependencies: '@standard-schema/spec': 1.0.0 @@ -10956,6 +11555,8 @@ snapshots: ansi-styles@6.2.3: {} + ansis@4.2.0: {} + any-promise@1.3.0: {} anymatch@3.1.3: @@ -10989,6 +11590,10 @@ snapshots: assertion-error@2.0.1: {} + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + astring@1.9.0: {} astro-expressive-code@0.41.3(astro@5.15.2(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.52.5)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1)): @@ -11155,6 +11760,15 @@ snapshots: axobject-query@4.1.0: {} + babel-dead-code-elimination@1.0.10: + dependencies: + '@babel/core': 7.28.5 + '@babel/parser': 7.28.5 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + transitivePeerDependencies: + - supports-color + bail@2.0.2: {} balanced-match@1.0.2: {} @@ -11479,6 +12093,8 @@ snapshots: cookie-es@1.2.2: {} + cookie-es@2.0.0: {} + cookie@1.0.2: {} copy-anything@4.0.5: @@ -11833,6 +12449,8 @@ snapshots: diff@5.2.0: {} + diff@8.0.2: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -12271,6 +12889,10 @@ snapshots: globrex@0.1.2: {} + goober@2.1.18(csstype@3.1.3): + dependencies: + csstype: 3.1.3 + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -12728,6 +13350,8 @@ snapshots: dependencies: is-inside-container: 1.0.0 + isbot@5.1.31: {} + isexe@2.0.0: {} isobject@3.0.1: {} @@ -12944,7 +13568,7 @@ snapshots: dependencies: yallist: 3.1.1 - lucide-react@0.548.0(react@19.2.0): + lucide-react@0.545.0(react@19.2.0): dependencies: react: 19.2.0 @@ -13580,35 +14204,6 @@ snapshots: neotraverse@0.6.18: {} - next-themes@0.4.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0): - dependencies: - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - - next@16.0.1(@opentelemetry/api@1.9.0(patch_hash=4b2adeefaf7c22f9987d0a125d69cab900719bec7ed7636648bea6947107033a))(react-dom@19.2.0(react@19.2.0))(react@19.2.0): - dependencies: - '@next/env': 16.0.1 - '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001751 - postcss: 8.4.31 - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - styled-jsx: 5.1.6(react@19.2.0) - optionalDependencies: - '@next/swc-darwin-arm64': 16.0.1 - '@next/swc-darwin-x64': 16.0.1 - '@next/swc-linux-arm64-gnu': 16.0.1 - '@next/swc-linux-arm64-musl': 16.0.1 - '@next/swc-linux-x64-gnu': 16.0.1 - '@next/swc-linux-x64-musl': 16.0.1 - '@next/swc-win32-arm64-msvc': 16.0.1 - '@next/swc-win32-x64-msvc': 16.0.1 - '@opentelemetry/api': 1.9.0(patch_hash=4b2adeefaf7c22f9987d0a125d69cab900719bec7ed7636648bea6947107033a) - sharp: 0.34.4 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - nlcst-to-string@4.0.0: dependencies: '@types/nlcst': 2.0.3 @@ -14089,12 +14684,6 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.4.31: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -14214,6 +14803,8 @@ snapshots: react-refresh@0.17.0: {} + react-refresh@0.18.0: {} + react-remove-scroll-bar@2.3.8(@types/react@19.2.2)(react@19.2.0): dependencies: react: 19.2.0 @@ -14278,6 +14869,14 @@ snapshots: real-require@0.2.0: {} + recast@0.23.11: + dependencies: + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tiny-invariant: 1.3.3 + tslib: 2.8.1 + recma-build-jsx@1.0.0: dependencies: '@types/estree': 1.0.8 @@ -14584,6 +15183,12 @@ snapshots: semver@7.7.3: {} + seroval-plugins@1.3.3(seroval@1.3.2): + dependencies: + seroval: 1.3.2 + + seroval@1.3.2: {} + serve-handler@6.1.6: dependencies: bytes: 3.0.0 @@ -14713,6 +15318,12 @@ snapshots: smol-toml@1.4.2: {} + solid-js@1.9.10: + dependencies: + csstype: 3.1.3 + seroval: 1.3.2 + seroval-plugins: 1.3.3(seroval@1.3.2) + sonic-boom@3.8.1: dependencies: atomic-sleep: 1.0.0 @@ -14730,6 +15341,8 @@ snapshots: source-map@0.5.6: {} + source-map@0.6.1: {} + source-map@0.7.6: {} source-map@0.8.0-beta.0: @@ -14860,11 +15473,6 @@ snapshots: dependencies: inline-style-parser: 0.2.4 - styled-jsx@5.1.6(react@19.2.0): - dependencies: - client-only: 0.0.1 - react: 19.2.0 - stylis@4.3.6: {} sucrase@3.35.0: @@ -14903,9 +15511,9 @@ snapshots: tailwind-merge@3.3.1: {} - tailwindcss-animate@1.0.7(tailwindcss@3.4.17): + tailwindcss-animate@1.0.7(tailwindcss@4.1.5): dependencies: - tailwindcss: 3.4.17 + tailwindcss: 4.1.5 tailwindcss@3.4.17: dependencies: @@ -14975,6 +15583,10 @@ snapshots: tiny-inflate@1.0.3: {} + tiny-invariant@1.3.3: {} + + tiny-warning@1.0.3: {} + tinybench@2.9.0: {} tinyexec@0.3.2: {} @@ -15067,6 +15679,8 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + tw-animate-css@1.4.0: {} + type-fest@0.7.1: {} type-fest@2.19.0: {} @@ -15183,6 +15797,13 @@ snapshots: universalify@0.1.2: {} + unplugin@2.3.10: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.15.0 + picomatch: 4.0.3 + webpack-virtual-modules: 0.6.2 + unstorage@1.17.1: dependencies: anymatch: 3.1.3 @@ -15579,6 +16200,8 @@ snapshots: web-namespaces@2.0.1: {} + web-vitals@5.1.0: {} + webauthn-p256@0.0.5: dependencies: '@noble/curves': 1.9.7 @@ -15590,6 +16213,8 @@ snapshots: webidl-conversions@8.0.0: {} + webpack-virtual-modules@0.6.2: {} + whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 From a2d279dc5b29e100fd2f16598d251c191795b4db Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Thu, 30 Oct 2025 16:52:58 +0000 Subject: [PATCH 2/4] lint --- apps/ensadmin/.cta.json | 6 +- apps/ensadmin/.env.local.example | 14 + apps/ensadmin/{biome.json => biome.jsonc} | 2 +- apps/ensadmin/package.json | 34 +- .../name/_components/AdditionalRecords.tsx | 1 - .../src/app/name/_components/Addresses.tsx | 1 - .../_components/NameDetailPageContent.tsx | 1 - .../_components/NameDetailPageSkeleton.tsx | 1 - .../app/name/_components/ProfileHeader.tsx | 1 - .../name/_components/ProfileInformation.tsx | 1 - .../src/app/name/_components/SocialLinks.tsx | 1 - .../components/graphiql-editor/components.tsx | 23 +- .../src/components/layout-wrapper.tsx | 7 +- apps/ensadmin/src/components/link.tsx | 27 +- apps/ensadmin/src/components/nav-main.tsx | 25 +- .../recent-registrations/components.tsx | 50 +-- apps/ensadmin/src/components/ui/sonner.tsx | 6 +- .../src/hooks/use-connection-url-param.tsx | 4 +- .../src/hooks/use-connections-library.tsx | 52 +-- apps/ensadmin/src/lib/env.ts | 21 +- apps/ensadmin/src/main.tsx | 29 +- apps/ensadmin/src/reportWebVitals.ts | 18 +- apps/ensadmin/src/routeTree.gen.ts | 378 +++++++++--------- apps/ensadmin/src/routes/__root.tsx | 8 +- apps/ensadmin/src/routes/index.tsx | 17 +- apps/ensadmin/src/styles.css | 9 +- apps/ensadmin/tsconfig.json | 2 +- apps/ensadmin/vite.config.ts | 28 +- biome.jsonc | 2 +- docs/ensnode.io/biome.jsonc | 2 +- docs/ensrainbow.io/biome.jsonc | 2 +- packages/ensnode-sdk/src/client.test.ts | 55 ++- pnpm-lock.yaml | 22 +- 33 files changed, 410 insertions(+), 440 deletions(-) create mode 100644 apps/ensadmin/.env.local.example rename apps/ensadmin/{biome.json => biome.jsonc} (93%) diff --git a/apps/ensadmin/.cta.json b/apps/ensadmin/.cta.json index df994696d..35699ff2b 100644 --- a/apps/ensadmin/.cta.json +++ b/apps/ensadmin/.cta.json @@ -8,7 +8,5 @@ "git": true, "version": 1, "framework": "react-cra", - "chosenAddOns": [ - "biome" - ] -} \ No newline at end of file + "chosenAddOns": ["biome"] +} diff --git a/apps/ensadmin/.env.local.example b/apps/ensadmin/.env.local.example new file mode 100644 index 000000000..04584a75a --- /dev/null +++ b/apps/ensadmin/.env.local.example @@ -0,0 +1,14 @@ +# The ENSAdmin public service URL +# Optional. The ENSAdmin web application needs this value to reference static assets. +# Note: it's recommended to explicitly set it. If not explicitly set, +# the application will try guess this value. For example, if hosting in Vercel, +# the Vercel env and Vercel URLs will be used. If not provided, +# the default public URL will be based on localhost and PORT. +ENSADMIN_PUBLIC_URL=http://localhost:4173 + +# Server's library of ENSNode URLs offered as connection options in the connection picker. +# Optional. If not set, defaults to `DEFAULT_SERVER_CONNECTION_LIBRARY` (https://api.alpha.ensnode.io,https://api.alpha-sepolia.ensnode.io,https://api.mainnet.ensnode.io,https://api.sepolia.ensnode.io,https://api.holesky.ensnode.io). +# Note: it must be a comma-separated list of URLs that are accessible from a web browser +# (i.e. it cannot be a hostname in a docker network) +# Note: if a user doesn't explicitly select an ENSNode connection then, by default, ENSAdmin will automatically select the first URL in this list as the ENSNode instance to connect the user to. +NEXT_PUBLIC_SERVER_CONNECTION_LIBRARY=https://api.alpha.ensnode.io,https://api.alpha-sepolia.ensnode.io,https://api.mainnet.ensnode.io,https://api.sepolia.ensnode.io,https://api.holesky.ensnode.io diff --git a/apps/ensadmin/biome.json b/apps/ensadmin/biome.jsonc similarity index 93% rename from apps/ensadmin/biome.json rename to apps/ensadmin/biome.jsonc index f5f4ace61..542522eb8 100644 --- a/apps/ensadmin/biome.json +++ b/apps/ensadmin/biome.jsonc @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.3.1/schema.json", + "$schema": "https://biomejs.dev/schemas/2.3.2/schema.json", "extends": "//", "css": { "parser": { diff --git a/apps/ensadmin/package.json b/apps/ensadmin/package.json index d55cfa5a9..b1c3fd207 100644 --- a/apps/ensadmin/package.json +++ b/apps/ensadmin/package.json @@ -1,15 +1,25 @@ { - "name": "ensadmin-vite", + "name": "ensadmin", + "version": "0.36.0", "private": true, "type": "module", + "description": "Explore the ENS Protocol like never before", + "license": "MIT", + "packageManager": "pnpm@10.20.0", + "repository": { + "type": "git", + "url": "git+https://github.com/namehash/ensnode.git", + "directory": "apps/ensadmin" + }, + "homepage": "https://github.com/namehash/ensnode/tree/main/apps/ensadmin", "scripts": { - "dev": "vite --port 3000", + "dev": "vite --port 4173", "build": "vite build && tsc", - "serve": "vite preview", - "test": "vitest run", - "format": "biome format", - "lint": "biome lint", - "check": "biome check" + "start": "serve out -l 4173", + "lint": "biome check --write .", + "lint:ci": "biome ci", + "typecheck": "tsc --noEmit", + "test": "vitest" }, "dependencies": { "@ensnode/datasources": "workspace:*", @@ -32,12 +42,9 @@ "@radix-ui/react-label": "^2.1.2", "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.2", - "@radix-ui/react-slot": "^1.1.2", + "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-tooltip": "^1.1.8", - "@radix-ui/react-slot": "^1.2.3", - "@xyflow/react": "^12.4.4", - "boring-avatars": "^1.11.2", "@tailwindcss/vite": "^4.1.16", "@tanstack/react-devtools": "^0.7.0", "@tanstack/react-query": "^5.90.5", @@ -45,6 +52,8 @@ "@tanstack/react-router": "^1.132.0", "@tanstack/react-router-devtools": "^1.132.0", "@tanstack/router-plugin": "^1.132.0", + "@xyflow/react": "^12.4.4", + "boring-avatars": "^1.11.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "constate": "^3.3.3", @@ -60,7 +69,8 @@ "tailwind-merge": "^3.3.1", "tailwindcss": "^4.1.5", "tailwindcss-animate": "^1.0.7", - "viem": "catalog:" + "viem": "catalog:", + "vite-plugin-monaco-editor": "^1.1.0" }, "devDependencies": { "@biomejs/biome": "2.2.4", diff --git a/apps/ensadmin/src/app/name/_components/AdditionalRecords.tsx b/apps/ensadmin/src/app/name/_components/AdditionalRecords.tsx index ab950e4a0..c6ff90ba1 100644 --- a/apps/ensadmin/src/app/name/_components/AdditionalRecords.tsx +++ b/apps/ensadmin/src/app/name/_components/AdditionalRecords.tsx @@ -1,4 +1,3 @@ - import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; interface AdditionalRecordsProps { diff --git a/apps/ensadmin/src/app/name/_components/Addresses.tsx b/apps/ensadmin/src/app/name/_components/Addresses.tsx index 6e86150f6..14c29bbf0 100644 --- a/apps/ensadmin/src/app/name/_components/Addresses.tsx +++ b/apps/ensadmin/src/app/name/_components/Addresses.tsx @@ -1,4 +1,3 @@ - import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; interface AddressesProps { diff --git a/apps/ensadmin/src/app/name/_components/NameDetailPageContent.tsx b/apps/ensadmin/src/app/name/_components/NameDetailPageContent.tsx index 0f47f53d9..9674f8388 100644 --- a/apps/ensadmin/src/app/name/_components/NameDetailPageContent.tsx +++ b/apps/ensadmin/src/app/name/_components/NameDetailPageContent.tsx @@ -1,4 +1,3 @@ - import { ASSUME_IMMUTABLE_QUERY, useRecords } from "@ensnode/ensnode-react"; import { type Name, type ResolverRecordsSelection } from "@ensnode/ensnode-sdk"; diff --git a/apps/ensadmin/src/app/name/_components/NameDetailPageSkeleton.tsx b/apps/ensadmin/src/app/name/_components/NameDetailPageSkeleton.tsx index 425c05e4a..b43a57bb7 100644 --- a/apps/ensadmin/src/app/name/_components/NameDetailPageSkeleton.tsx +++ b/apps/ensadmin/src/app/name/_components/NameDetailPageSkeleton.tsx @@ -1,4 +1,3 @@ - import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Skeleton } from "@/components/ui/skeleton"; diff --git a/apps/ensadmin/src/app/name/_components/ProfileHeader.tsx b/apps/ensadmin/src/app/name/_components/ProfileHeader.tsx index c6ce48dbb..06f90a68e 100644 --- a/apps/ensadmin/src/app/name/_components/ProfileHeader.tsx +++ b/apps/ensadmin/src/app/name/_components/ProfileHeader.tsx @@ -1,4 +1,3 @@ - import type { ENSNamespaceId, Name } from "@ensnode/ensnode-sdk"; import { EnsAvatar } from "@/components/ens-avatar"; diff --git a/apps/ensadmin/src/app/name/_components/ProfileInformation.tsx b/apps/ensadmin/src/app/name/_components/ProfileInformation.tsx index e101f3e1b..80f123429 100644 --- a/apps/ensadmin/src/app/name/_components/ProfileInformation.tsx +++ b/apps/ensadmin/src/app/name/_components/ProfileInformation.tsx @@ -1,4 +1,3 @@ - import { Mail } from "lucide-react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; diff --git a/apps/ensadmin/src/app/name/_components/SocialLinks.tsx b/apps/ensadmin/src/app/name/_components/SocialLinks.tsx index 12b73fae5..55570c7b4 100644 --- a/apps/ensadmin/src/app/name/_components/SocialLinks.tsx +++ b/apps/ensadmin/src/app/name/_components/SocialLinks.tsx @@ -1,4 +1,3 @@ - import { SiFarcaster, SiGithub, SiReddit, SiTelegram, SiX } from "@icons-pack/react-simple-icons"; import { useMemo } from "react"; diff --git a/apps/ensadmin/src/components/graphiql-editor/components.tsx b/apps/ensadmin/src/components/graphiql-editor/components.tsx index a577f1d9d..86c4e351e 100644 --- a/apps/ensadmin/src/components/graphiql-editor/components.tsx +++ b/apps/ensadmin/src/components/graphiql-editor/components.tsx @@ -1,4 +1,3 @@ -import "graphiql/setup-workers/webpack"; import "graphiql/style.css"; import "@graphiql/plugin-explorer/style.css"; @@ -25,21 +24,14 @@ const defaultQuery = `# * A GraphiQL editor for Ponder API page. */ export function PonderGraphiQLEditor(props: GraphiQLPropsWithUrl) { - const search = useSearch({ strict: false }) as Record< - string, - string | undefined - >; + const search = useSearch({ strict: false }) as Record; const initialQuery = search.query || defaultQuery; const initialVariables = search.variables || ""; return (
    - +
    ); } @@ -48,10 +40,7 @@ export function PonderGraphiQLEditor(props: GraphiQLPropsWithUrl) { * A GraphiQL editor for Subgraph API page. */ export function SubgraphGraphiQLEditor(props: GraphiQLPropsWithUrl) { - const search = useSearch({ strict: false }) as Record< - string, - string | undefined - >; + const search = useSearch({ strict: false }) as Record; const initialQuery = search.query || defaultQuery; const initialVariables = search.variables || ""; @@ -66,11 +55,7 @@ export function SubgraphGraphiQLEditor(props: GraphiQLPropsWithUrl) { url={props.url} />*/} - + ); } diff --git a/apps/ensadmin/src/components/layout-wrapper.tsx b/apps/ensadmin/src/components/layout-wrapper.tsx index b7feaabaf..7f22f793f 100644 --- a/apps/ensadmin/src/components/layout-wrapper.tsx +++ b/apps/ensadmin/src/components/layout-wrapper.tsx @@ -4,12 +4,7 @@ import { Suspense } from "react"; import { AppSidebar } from "@/components/app-sidebar"; import { RequireActiveConnection } from "@/components/connections/require-active-connection"; import { RequireSelectedConnection } from "@/components/connections/require-selected-connection"; -import { - Header, - HeaderActions, - HeaderBreadcrumbs, - HeaderNav, -} from "@/components/header"; +import { Header, HeaderActions, HeaderBreadcrumbs, HeaderNav } from "@/components/header"; import { SelectedENSNodeProvider } from "@/components/providers/selected-ensnode-provider"; import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"; import { Skeleton } from "@/components/ui/skeleton"; diff --git a/apps/ensadmin/src/components/link.tsx b/apps/ensadmin/src/components/link.tsx index eec4db8ef..34717a5c0 100644 --- a/apps/ensadmin/src/components/link.tsx +++ b/apps/ensadmin/src/components/link.tsx @@ -10,16 +10,9 @@ interface LinkProps { /** * Renders an internal link. */ -export function InternalLink({ - href, - className, - children, -}: PropsWithChildren) { +export function InternalLink({ href, className, children }: PropsWithChildren) { return ( - + {children} ); @@ -28,19 +21,13 @@ export function InternalLink({ /** * Renders an external link that opens in a new tab. */ -export function ExternalLink({ - href, - className, - children, -}: PropsWithChildren) { +export function ExternalLink({ href, className, children }: PropsWithChildren) { return ( {children} @@ -50,11 +37,7 @@ export function ExternalLink({ /** * Renders an external link with an external link icon. */ -export function ExternalLinkWithIcon({ - href, - className, - children, -}: PropsWithChildren) { +export function ExternalLinkWithIcon({ href, className, children }: PropsWithChildren) { return ( {children} diff --git a/apps/ensadmin/src/components/nav-main.tsx b/apps/ensadmin/src/components/nav-main.tsx index 52b7525cd..dae8ebce2 100644 --- a/apps/ensadmin/src/components/nav-main.tsx +++ b/apps/ensadmin/src/components/nav-main.tsx @@ -3,11 +3,7 @@ import { ChevronRight, type LucideIcon } from "lucide-react"; import type { UrlString } from "@ensnode/ensnode-sdk"; -import { - Collapsible, - CollapsibleContent, - CollapsibleTrigger, -} from "@/components/ui/collapsible"; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { SidebarGroup, SidebarGroupLabel, @@ -77,11 +73,7 @@ export function NavMain({ if (!hasItems) return ( - + {item.icon && } {item.title} @@ -91,8 +83,7 @@ export function NavMain({ ); const anySubItemActive = - item.items?.some((subItem) => isActive(subItem.url)) || - isItemActive; + item.items?.some((subItem) => isActive(subItem.url)) || isItemActive; return ( - + {item.icon && } {item.title} @@ -120,10 +108,7 @@ export function NavMain({ return ( - + {subItem.title} diff --git a/apps/ensadmin/src/components/recent-registrations/components.tsx b/apps/ensadmin/src/components/recent-registrations/components.tsx index b3d3cf815..4119dfdf0 100644 --- a/apps/ensadmin/src/components/recent-registrations/components.tsx +++ b/apps/ensadmin/src/components/recent-registrations/components.tsx @@ -1,5 +1,5 @@ -import { Link } from "@tanstack/react-router"; import { useAutoAnimate } from "@formkit/auto-animate/react"; +import { Link } from "@tanstack/react-router"; import { Fragment } from "react"; import { @@ -64,9 +64,7 @@ export interface RecentRegistrationsErrorProps { * Error - * error: {@link ErrorInfoProps} */ -export type RecentRegistrationsProps = - | RecentRegistrationsOkProps - | RecentRegistrationsErrorProps; +export type RecentRegistrationsProps = RecentRegistrationsOkProps | RecentRegistrationsErrorProps; /** * Displays a panel containing the list of the most recently indexed * registrations and the date of the most recently indexed block. @@ -87,11 +85,7 @@ export function RecentRegistrations(props: RecentRegistrationsProps) { const { omnichainSnapshot } = realtimeProjection.snapshot; - if ( - !SUPPORTED_OMNICHAIN_INDEXING_STATUSES.includes( - omnichainSnapshot.omnichainStatus - ) - ) { + if (!SUPPORTED_OMNICHAIN_INDEXING_STATUSES.includes(omnichainSnapshot.omnichainStatus)) { return ( @@ -201,36 +194,29 @@ function UnsupportedOmnichainIndexingStatusMessage({ {formatOmnichainIndexingStatus(omnichainIndexingStatus)}
    - The latest indexed registrations will be available once the omnichain - indexing status is{" "} - {supportedOmnichainIndexingStatuses.map( - (supportedOmnichainIndexingStatus, idx) => ( - - - {formatOmnichainIndexingStatus( - supportedOmnichainIndexingStatus - )} - - {idx < supportedOmnichainIndexingStatuses.length - 1 && " or "} - - ) - )} + The latest indexed registrations will be available once the omnichain indexing status is{" "} + {supportedOmnichainIndexingStatuses.map((supportedOmnichainIndexingStatus, idx) => ( + + + {formatOmnichainIndexingStatus(supportedOmnichainIndexingStatus)} + + {idx < supportedOmnichainIndexingStatuses.length - 1 && " or "} + + ))} .
    diff --git a/apps/ensadmin/src/components/ui/sonner.tsx b/apps/ensadmin/src/components/ui/sonner.tsx index 0921376cc..1399b7435 100644 --- a/apps/ensadmin/src/components/ui/sonner.tsx +++ b/apps/ensadmin/src/components/ui/sonner.tsx @@ -13,10 +13,8 @@ const Toaster = ({ ...props }: ToasterProps) => { toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg", description: "group-[.toast]:text-muted-foreground", - actionButton: - "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground", - cancelButton: - "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground", + actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground", + cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground", }, }} {...props} diff --git a/apps/ensadmin/src/hooks/use-connection-url-param.tsx b/apps/ensadmin/src/hooks/use-connection-url-param.tsx index f6f421066..8d71074e9 100644 --- a/apps/ensadmin/src/hooks/use-connection-url-param.tsx +++ b/apps/ensadmin/src/hooks/use-connection-url-param.tsx @@ -76,7 +76,7 @@ export function useRawConnectionUrlParam(): UseRawConnectionUrlParamResult { replace: true, }); }, - [navigate, search] + [navigate, search], ); // Build callback for attaching the current raw connection URL param @@ -102,7 +102,7 @@ export function useRawConnectionUrlParam(): UseRawConnectionUrlParamResult { return pathWithRetainedConnection; }, - [rawConnectionUrlParam] + [rawConnectionUrlParam], ); return { diff --git a/apps/ensadmin/src/hooks/use-connections-library.tsx b/apps/ensadmin/src/hooks/use-connections-library.tsx index feac4b731..44935c0bf 100644 --- a/apps/ensadmin/src/hooks/use-connections-library.tsx +++ b/apps/ensadmin/src/hooks/use-connections-library.tsx @@ -48,16 +48,15 @@ const defaultSelectedConnection = serverConnectionLibrary[0]; function _useConnectionsLibrary() { const hydrated = useHydrated(); - const { rawConnectionUrlParam, setRawConnectionUrlParam } = - useRawConnectionUrlParam(); + const { rawConnectionUrlParam, setRawConnectionUrlParam } = useRawConnectionUrlParam(); // get raw custom connection library URLs from localStorage - const [rawCustomConnectionUrls, storeRawCustomConnectionUrls] = - useLocalstorageState(CUSTOM_CONNECTIONS_LOCAL_STORAGE_KEY, []); + const [rawCustomConnectionUrls, storeRawCustomConnectionUrls] = useLocalstorageState( + CUSTOM_CONNECTIONS_LOCAL_STORAGE_KEY, + [], + ); - const [rawExistingConnectionUrl, setRawExistingConnectionUrl] = useState< - string | null - >(null); + const [rawExistingConnectionUrl, setRawExistingConnectionUrl] = useState(null); /** * Invariants: @@ -75,19 +74,10 @@ function _useConnectionsLibrary() { // clean up custom connection library URLs in localStorage if validation changed anything useEffect(() => { - if ( - JSON.stringify(customConnectionLibrary) !== - JSON.stringify(rawCustomConnectionUrls) - ) { - storeRawCustomConnectionUrls( - customConnectionLibrary.map((url) => url.toString()) - ); + if (JSON.stringify(customConnectionLibrary) !== JSON.stringify(rawCustomConnectionUrls)) { + storeRawCustomConnectionUrls(customConnectionLibrary.map((url) => url.toString())); } - }, [ - customConnectionLibrary, - rawCustomConnectionUrls, - storeRawCustomConnectionUrls, - ]); + }, [customConnectionLibrary, rawCustomConnectionUrls, storeRawCustomConnectionUrls]); /** * Invariants: @@ -112,7 +102,7 @@ function _useConnectionsLibrary() { .filter((url) => !serverConnectionLibrary.includes(url)) .map((url) => ({ url, type: "custom" as const })), ], - [customConnectionLibrary] + [customConnectionLibrary], ); const addCustomConnection = useCallback( @@ -124,18 +114,18 @@ function _useConnectionsLibrary() { return url; }, - [storeRawCustomConnectionUrls] + [storeRawCustomConnectionUrls], ); const removeCustomConnection = useCallback( (url: HttpHostname) => { storeRawCustomConnectionUrls((customConnections) => - customConnections.filter((rawUrl) => rawUrl !== url.toString()) + customConnections.filter((rawUrl) => rawUrl !== url.toString()), ); return url; }, - [storeRawCustomConnectionUrls] + [storeRawCustomConnectionUrls], ); const selectedConnection = useMemo(() => { @@ -173,7 +163,7 @@ function _useConnectionsLibrary() { (url: HttpHostname) => { setRawConnectionUrlParam(url.toString()); }, - [setRawConnectionUrlParam] + [setRawConnectionUrlParam], ); return { @@ -185,9 +175,7 @@ function _useConnectionsLibrary() { }; } -const [ConnectionsLibraryProviderInner, useConnectionsLibrary] = constate( - _useConnectionsLibrary -); +const [ConnectionsLibraryProviderInner, useConnectionsLibrary] = constate(_useConnectionsLibrary); export { useConnectionsLibrary }; @@ -206,16 +194,10 @@ export { useConnectionsLibrary }; * - removeCustomConnection: Callback for removing a custom connection * - selectConnection: Callback for selecting a connection */ -export function ConnectionsLibraryProvider({ - children, -}: { - children: React.ReactNode; -}) { +export function ConnectionsLibraryProvider({ children }: { children: React.ReactNode }) { return ( - - {children} - + {children} ); } diff --git a/apps/ensadmin/src/lib/env.ts b/apps/ensadmin/src/lib/env.ts index 853fb3127..a3601932d 100644 --- a/apps/ensadmin/src/lib/env.ts +++ b/apps/ensadmin/src/lib/env.ts @@ -1,10 +1,6 @@ import { uniq } from "@ensnode/ensnode-sdk"; -import { - buildHttpHostname, - buildHttpHostnames, - type HttpHostname, -} from "./url-utils"; +import { buildHttpHostname, buildHttpHostnames, type HttpHostname } from "./url-utils"; const DEFAULT_ENSADMIN_PORT = 4173; const DEFAULT_SERVER_CONNECTION_LIBRARY = [ @@ -18,9 +14,7 @@ const DEFAULT_SERVER_CONNECTION_LIBRARY = [ /** * Determines whether `variables` is a non-null object and a valid Record. */ -const isValidRuntimeEnvVariables = ( - value: unknown -): value is Record => +const isValidRuntimeEnvVariables = (value: unknown): value is Record => typeof value === "object" && value !== null; /** @@ -32,8 +26,7 @@ const isValidRuntimeEnvVariables = ( const getRuntimeEnvVariable = (key: string): string | undefined => { if (typeof window == "undefined") return undefined; - const variables = (window as any) - .__ENSADMIN_RUNTIME_ENVIRONMENT_VARIABLES as unknown; + const variables = (window as any).__ENSADMIN_RUNTIME_ENVIRONMENT_VARIABLES as unknown; if (!isValidRuntimeEnvVariables(variables)) return undefined; const value = variables[key]; @@ -86,14 +79,12 @@ function getVercelAppPublicUrl(): string | undefined { */ export function ensAdminPublicUrl(): HttpHostname { const envVarValue = - import.meta.env.ENSADMIN_PUBLIC_URL || - getVercelAppPublicUrl() || - localhostEnsAdminPublicUrl(); + import.meta.env.ENSADMIN_PUBLIC_URL || getVercelAppPublicUrl() || localhostEnsAdminPublicUrl(); const result = buildHttpHostname(envVarValue); if (!result.isValid) { throw new Error( - `Invalid ENSADMIN_PUBLIC_URL value "${envVarValue}": Cannot build ENSAdmin public HttpHostname: ${result.error}` + `Invalid ENSADMIN_PUBLIC_URL value "${envVarValue}": Cannot build ENSAdmin public HttpHostname: ${result.error}`, ); } return result.url; @@ -116,7 +107,7 @@ export function getServerConnectionLibrary(): HttpHostname[] { if (connections.length === 0) { throw new Error( - `Invalid ${envVarName} value: "${envVarValue}" must contain at least one valid ENSNode connection URL` + `Invalid ${envVarName} value: "${envVarValue}" must contain at least one valid ENSNode connection URL`, ); } diff --git a/apps/ensadmin/src/main.tsx b/apps/ensadmin/src/main.tsx index 1b093697f..9cf315e68 100644 --- a/apps/ensadmin/src/main.tsx +++ b/apps/ensadmin/src/main.tsx @@ -1,42 +1,43 @@ -import { StrictMode } from 'react' -import ReactDOM from 'react-dom/client' -import { RouterProvider, createRouter } from '@tanstack/react-router' +import { createRouter, RouterProvider } from "@tanstack/react-router"; +import { StrictMode } from "react"; +import ReactDOM from "react-dom/client"; // Import the generated route tree -import { routeTree } from './routeTree.gen' +import { routeTree } from "./routeTree.gen"; -import './styles.css' -import reportWebVitals from './reportWebVitals.ts' +import "./styles.css"; + +import reportWebVitals from "./reportWebVitals.ts"; // Create a new router instance const router = createRouter({ routeTree, context: {}, - defaultPreload: 'intent', + defaultPreload: "intent", scrollRestoration: true, defaultStructuralSharing: true, defaultPreloadStaleTime: 0, -}) +}); // Register the router instance for type safety -declare module '@tanstack/react-router' { +declare module "@tanstack/react-router" { interface Register { - router: typeof router + router: typeof router; } } // Render the app -const rootElement = document.getElementById('app') +const rootElement = document.getElementById("app"); if (rootElement && !rootElement.innerHTML) { - const root = ReactDOM.createRoot(rootElement) + const root = ReactDOM.createRoot(rootElement); root.render( , - ) + ); } // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals() +reportWebVitals(); diff --git a/apps/ensadmin/src/reportWebVitals.ts b/apps/ensadmin/src/reportWebVitals.ts index 16b66b5f6..d0b60372c 100644 --- a/apps/ensadmin/src/reportWebVitals.ts +++ b/apps/ensadmin/src/reportWebVitals.ts @@ -1,13 +1,13 @@ const reportWebVitals = (onPerfEntry?: () => void) => { if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ onCLS, onINP, onFCP, onLCP, onTTFB }) => { - onCLS(onPerfEntry) - onINP(onPerfEntry) - onFCP(onPerfEntry) - onLCP(onPerfEntry) - onTTFB(onPerfEntry) - }) + import("web-vitals").then(({ onCLS, onINP, onFCP, onLCP, onTTFB }) => { + onCLS(onPerfEntry); + onINP(onPerfEntry); + onFCP(onPerfEntry); + onLCP(onPerfEntry); + onTTFB(onPerfEntry); + }); } -} +}; -export default reportWebVitals +export default reportWebVitals; diff --git a/apps/ensadmin/src/routeTree.gen.ts b/apps/ensadmin/src/routeTree.gen.ts index 295a629b0..13fc48abf 100644 --- a/apps/ensadmin/src/routeTree.gen.ts +++ b/apps/ensadmin/src/routeTree.gen.ts @@ -8,230 +8,230 @@ // You should NOT make any changes in this file as it will be overwritten. // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. -import { Route as rootRouteImport } from './routes/__root' -import { Route as StatusRouteImport } from './routes/status' -import { Route as RegistrationRouteImport } from './routes/registration' -import { Route as NameRouteImport } from './routes/name' -import { Route as ConnectionRouteImport } from './routes/connection' -import { Route as IndexRouteImport } from './routes/index' -import { Route as InspectVisualizerRouteImport } from './routes/inspect/visualizer' -import { Route as InspectRecordsRouteImport } from './routes/inspect/records' -import { Route as InspectPrimaryNamesRouteImport } from './routes/inspect/primary-names' -import { Route as InspectPrimaryNameRouteImport } from './routes/inspect/primary-name' -import { Route as ApiSubgraphRouteImport } from './routes/api/subgraph' +import { Route as rootRouteImport } from "./routes/__root"; +import { Route as ApiSubgraphRouteImport } from "./routes/api/subgraph"; +import { Route as ConnectionRouteImport } from "./routes/connection"; +import { Route as IndexRouteImport } from "./routes/index"; +import { Route as InspectPrimaryNameRouteImport } from "./routes/inspect/primary-name"; +import { Route as InspectPrimaryNamesRouteImport } from "./routes/inspect/primary-names"; +import { Route as InspectRecordsRouteImport } from "./routes/inspect/records"; +import { Route as InspectVisualizerRouteImport } from "./routes/inspect/visualizer"; +import { Route as NameRouteImport } from "./routes/name"; +import { Route as RegistrationRouteImport } from "./routes/registration"; +import { Route as StatusRouteImport } from "./routes/status"; const StatusRoute = StatusRouteImport.update({ - id: '/status', - path: '/status', + id: "/status", + path: "/status", getParentRoute: () => rootRouteImport, -} as any) +} as any); const RegistrationRoute = RegistrationRouteImport.update({ - id: '/registration', - path: '/registration', + id: "/registration", + path: "/registration", getParentRoute: () => rootRouteImport, -} as any) +} as any); const NameRoute = NameRouteImport.update({ - id: '/name', - path: '/name', + id: "/name", + path: "/name", getParentRoute: () => rootRouteImport, -} as any) +} as any); const ConnectionRoute = ConnectionRouteImport.update({ - id: '/connection', - path: '/connection', + id: "/connection", + path: "/connection", getParentRoute: () => rootRouteImport, -} as any) +} as any); const IndexRoute = IndexRouteImport.update({ - id: '/', - path: '/', + id: "/", + path: "/", getParentRoute: () => rootRouteImport, -} as any) +} as any); const InspectVisualizerRoute = InspectVisualizerRouteImport.update({ - id: '/inspect/visualizer', - path: '/inspect/visualizer', + id: "/inspect/visualizer", + path: "/inspect/visualizer", getParentRoute: () => rootRouteImport, -} as any) +} as any); const InspectRecordsRoute = InspectRecordsRouteImport.update({ - id: '/inspect/records', - path: '/inspect/records', + id: "/inspect/records", + path: "/inspect/records", getParentRoute: () => rootRouteImport, -} as any) +} as any); const InspectPrimaryNamesRoute = InspectPrimaryNamesRouteImport.update({ - id: '/inspect/primary-names', - path: '/inspect/primary-names', + id: "/inspect/primary-names", + path: "/inspect/primary-names", getParentRoute: () => rootRouteImport, -} as any) +} as any); const InspectPrimaryNameRoute = InspectPrimaryNameRouteImport.update({ - id: '/inspect/primary-name', - path: '/inspect/primary-name', + id: "/inspect/primary-name", + path: "/inspect/primary-name", getParentRoute: () => rootRouteImport, -} as any) +} as any); const ApiSubgraphRoute = ApiSubgraphRouteImport.update({ - id: '/api/subgraph', - path: '/api/subgraph', + id: "/api/subgraph", + path: "/api/subgraph", getParentRoute: () => rootRouteImport, -} as any) +} as any); export interface FileRoutesByFullPath { - '/': typeof IndexRoute - '/connection': typeof ConnectionRoute - '/name': typeof NameRoute - '/registration': typeof RegistrationRoute - '/status': typeof StatusRoute - '/api/subgraph': typeof ApiSubgraphRoute - '/inspect/primary-name': typeof InspectPrimaryNameRoute - '/inspect/primary-names': typeof InspectPrimaryNamesRoute - '/inspect/records': typeof InspectRecordsRoute - '/inspect/visualizer': typeof InspectVisualizerRoute + "/": typeof IndexRoute; + "/connection": typeof ConnectionRoute; + "/name": typeof NameRoute; + "/registration": typeof RegistrationRoute; + "/status": typeof StatusRoute; + "/api/subgraph": typeof ApiSubgraphRoute; + "/inspect/primary-name": typeof InspectPrimaryNameRoute; + "/inspect/primary-names": typeof InspectPrimaryNamesRoute; + "/inspect/records": typeof InspectRecordsRoute; + "/inspect/visualizer": typeof InspectVisualizerRoute; } export interface FileRoutesByTo { - '/': typeof IndexRoute - '/connection': typeof ConnectionRoute - '/name': typeof NameRoute - '/registration': typeof RegistrationRoute - '/status': typeof StatusRoute - '/api/subgraph': typeof ApiSubgraphRoute - '/inspect/primary-name': typeof InspectPrimaryNameRoute - '/inspect/primary-names': typeof InspectPrimaryNamesRoute - '/inspect/records': typeof InspectRecordsRoute - '/inspect/visualizer': typeof InspectVisualizerRoute + "/": typeof IndexRoute; + "/connection": typeof ConnectionRoute; + "/name": typeof NameRoute; + "/registration": typeof RegistrationRoute; + "/status": typeof StatusRoute; + "/api/subgraph": typeof ApiSubgraphRoute; + "/inspect/primary-name": typeof InspectPrimaryNameRoute; + "/inspect/primary-names": typeof InspectPrimaryNamesRoute; + "/inspect/records": typeof InspectRecordsRoute; + "/inspect/visualizer": typeof InspectVisualizerRoute; } export interface FileRoutesById { - __root__: typeof rootRouteImport - '/': typeof IndexRoute - '/connection': typeof ConnectionRoute - '/name': typeof NameRoute - '/registration': typeof RegistrationRoute - '/status': typeof StatusRoute - '/api/subgraph': typeof ApiSubgraphRoute - '/inspect/primary-name': typeof InspectPrimaryNameRoute - '/inspect/primary-names': typeof InspectPrimaryNamesRoute - '/inspect/records': typeof InspectRecordsRoute - '/inspect/visualizer': typeof InspectVisualizerRoute + __root__: typeof rootRouteImport; + "/": typeof IndexRoute; + "/connection": typeof ConnectionRoute; + "/name": typeof NameRoute; + "/registration": typeof RegistrationRoute; + "/status": typeof StatusRoute; + "/api/subgraph": typeof ApiSubgraphRoute; + "/inspect/primary-name": typeof InspectPrimaryNameRoute; + "/inspect/primary-names": typeof InspectPrimaryNamesRoute; + "/inspect/records": typeof InspectRecordsRoute; + "/inspect/visualizer": typeof InspectVisualizerRoute; } export interface FileRouteTypes { - fileRoutesByFullPath: FileRoutesByFullPath + fileRoutesByFullPath: FileRoutesByFullPath; fullPaths: - | '/' - | '/connection' - | '/name' - | '/registration' - | '/status' - | '/api/subgraph' - | '/inspect/primary-name' - | '/inspect/primary-names' - | '/inspect/records' - | '/inspect/visualizer' - fileRoutesByTo: FileRoutesByTo + | "/" + | "/connection" + | "/name" + | "/registration" + | "/status" + | "/api/subgraph" + | "/inspect/primary-name" + | "/inspect/primary-names" + | "/inspect/records" + | "/inspect/visualizer"; + fileRoutesByTo: FileRoutesByTo; to: - | '/' - | '/connection' - | '/name' - | '/registration' - | '/status' - | '/api/subgraph' - | '/inspect/primary-name' - | '/inspect/primary-names' - | '/inspect/records' - | '/inspect/visualizer' + | "/" + | "/connection" + | "/name" + | "/registration" + | "/status" + | "/api/subgraph" + | "/inspect/primary-name" + | "/inspect/primary-names" + | "/inspect/records" + | "/inspect/visualizer"; id: - | '__root__' - | '/' - | '/connection' - | '/name' - | '/registration' - | '/status' - | '/api/subgraph' - | '/inspect/primary-name' - | '/inspect/primary-names' - | '/inspect/records' - | '/inspect/visualizer' - fileRoutesById: FileRoutesById + | "__root__" + | "/" + | "/connection" + | "/name" + | "/registration" + | "/status" + | "/api/subgraph" + | "/inspect/primary-name" + | "/inspect/primary-names" + | "/inspect/records" + | "/inspect/visualizer"; + fileRoutesById: FileRoutesById; } export interface RootRouteChildren { - IndexRoute: typeof IndexRoute - ConnectionRoute: typeof ConnectionRoute - NameRoute: typeof NameRoute - RegistrationRoute: typeof RegistrationRoute - StatusRoute: typeof StatusRoute - ApiSubgraphRoute: typeof ApiSubgraphRoute - InspectPrimaryNameRoute: typeof InspectPrimaryNameRoute - InspectPrimaryNamesRoute: typeof InspectPrimaryNamesRoute - InspectRecordsRoute: typeof InspectRecordsRoute - InspectVisualizerRoute: typeof InspectVisualizerRoute + IndexRoute: typeof IndexRoute; + ConnectionRoute: typeof ConnectionRoute; + NameRoute: typeof NameRoute; + RegistrationRoute: typeof RegistrationRoute; + StatusRoute: typeof StatusRoute; + ApiSubgraphRoute: typeof ApiSubgraphRoute; + InspectPrimaryNameRoute: typeof InspectPrimaryNameRoute; + InspectPrimaryNamesRoute: typeof InspectPrimaryNamesRoute; + InspectRecordsRoute: typeof InspectRecordsRoute; + InspectVisualizerRoute: typeof InspectVisualizerRoute; } -declare module '@tanstack/react-router' { +declare module "@tanstack/react-router" { interface FileRoutesByPath { - '/status': { - id: '/status' - path: '/status' - fullPath: '/status' - preLoaderRoute: typeof StatusRouteImport - parentRoute: typeof rootRouteImport - } - '/registration': { - id: '/registration' - path: '/registration' - fullPath: '/registration' - preLoaderRoute: typeof RegistrationRouteImport - parentRoute: typeof rootRouteImport - } - '/name': { - id: '/name' - path: '/name' - fullPath: '/name' - preLoaderRoute: typeof NameRouteImport - parentRoute: typeof rootRouteImport - } - '/connection': { - id: '/connection' - path: '/connection' - fullPath: '/connection' - preLoaderRoute: typeof ConnectionRouteImport - parentRoute: typeof rootRouteImport - } - '/': { - id: '/' - path: '/' - fullPath: '/' - preLoaderRoute: typeof IndexRouteImport - parentRoute: typeof rootRouteImport - } - '/inspect/visualizer': { - id: '/inspect/visualizer' - path: '/inspect/visualizer' - fullPath: '/inspect/visualizer' - preLoaderRoute: typeof InspectVisualizerRouteImport - parentRoute: typeof rootRouteImport - } - '/inspect/records': { - id: '/inspect/records' - path: '/inspect/records' - fullPath: '/inspect/records' - preLoaderRoute: typeof InspectRecordsRouteImport - parentRoute: typeof rootRouteImport - } - '/inspect/primary-names': { - id: '/inspect/primary-names' - path: '/inspect/primary-names' - fullPath: '/inspect/primary-names' - preLoaderRoute: typeof InspectPrimaryNamesRouteImport - parentRoute: typeof rootRouteImport - } - '/inspect/primary-name': { - id: '/inspect/primary-name' - path: '/inspect/primary-name' - fullPath: '/inspect/primary-name' - preLoaderRoute: typeof InspectPrimaryNameRouteImport - parentRoute: typeof rootRouteImport - } - '/api/subgraph': { - id: '/api/subgraph' - path: '/api/subgraph' - fullPath: '/api/subgraph' - preLoaderRoute: typeof ApiSubgraphRouteImport - parentRoute: typeof rootRouteImport - } + "/status": { + id: "/status"; + path: "/status"; + fullPath: "/status"; + preLoaderRoute: typeof StatusRouteImport; + parentRoute: typeof rootRouteImport; + }; + "/registration": { + id: "/registration"; + path: "/registration"; + fullPath: "/registration"; + preLoaderRoute: typeof RegistrationRouteImport; + parentRoute: typeof rootRouteImport; + }; + "/name": { + id: "/name"; + path: "/name"; + fullPath: "/name"; + preLoaderRoute: typeof NameRouteImport; + parentRoute: typeof rootRouteImport; + }; + "/connection": { + id: "/connection"; + path: "/connection"; + fullPath: "/connection"; + preLoaderRoute: typeof ConnectionRouteImport; + parentRoute: typeof rootRouteImport; + }; + "/": { + id: "/"; + path: "/"; + fullPath: "/"; + preLoaderRoute: typeof IndexRouteImport; + parentRoute: typeof rootRouteImport; + }; + "/inspect/visualizer": { + id: "/inspect/visualizer"; + path: "/inspect/visualizer"; + fullPath: "/inspect/visualizer"; + preLoaderRoute: typeof InspectVisualizerRouteImport; + parentRoute: typeof rootRouteImport; + }; + "/inspect/records": { + id: "/inspect/records"; + path: "/inspect/records"; + fullPath: "/inspect/records"; + preLoaderRoute: typeof InspectRecordsRouteImport; + parentRoute: typeof rootRouteImport; + }; + "/inspect/primary-names": { + id: "/inspect/primary-names"; + path: "/inspect/primary-names"; + fullPath: "/inspect/primary-names"; + preLoaderRoute: typeof InspectPrimaryNamesRouteImport; + parentRoute: typeof rootRouteImport; + }; + "/inspect/primary-name": { + id: "/inspect/primary-name"; + path: "/inspect/primary-name"; + fullPath: "/inspect/primary-name"; + preLoaderRoute: typeof InspectPrimaryNameRouteImport; + parentRoute: typeof rootRouteImport; + }; + "/api/subgraph": { + id: "/api/subgraph"; + path: "/api/subgraph"; + fullPath: "/api/subgraph"; + preLoaderRoute: typeof ApiSubgraphRouteImport; + parentRoute: typeof rootRouteImport; + }; } } @@ -246,7 +246,7 @@ const rootRouteChildren: RootRouteChildren = { InspectPrimaryNamesRoute: InspectPrimaryNamesRoute, InspectRecordsRoute: InspectRecordsRoute, InspectVisualizerRoute: InspectVisualizerRoute, -} +}; export const routeTree = rootRouteImport ._addFileChildren(rootRouteChildren) - ._addFileTypes() + ._addFileTypes(); diff --git a/apps/ensadmin/src/routes/__root.tsx b/apps/ensadmin/src/routes/__root.tsx index 53424435e..603a7e564 100644 --- a/apps/ensadmin/src/routes/__root.tsx +++ b/apps/ensadmin/src/routes/__root.tsx @@ -1,12 +1,12 @@ -import { Outlet, createRootRoute } from "@tanstack/react-router"; -import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"; import { TanStackDevtools } from "@tanstack/react-devtools"; +import { createRootRoute, Outlet } from "@tanstack/react-router"; +import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"; import { Suspense } from "react"; -import { QueryClientProvider } from "@/components/query-client/components"; -import { ConnectionsLibraryProvider } from "@/hooks/use-connections-library"; import { LayoutWrapper } from "@/components/layout-wrapper"; +import { QueryClientProvider } from "@/components/query-client/components"; import { Toaster } from "@/components/ui/sonner"; +import { ConnectionsLibraryProvider } from "@/hooks/use-connections-library"; export const Route = createRootRoute({ component: RootLayout, diff --git a/apps/ensadmin/src/routes/index.tsx b/apps/ensadmin/src/routes/index.tsx index e8ba0a305..ba9490d91 100644 --- a/apps/ensadmin/src/routes/index.tsx +++ b/apps/ensadmin/src/routes/index.tsx @@ -11,24 +11,13 @@ function SplashPage() {
    - ENSAdmin + ENSAdmin
    - ENSAdmin Logo -

    - ENSAdmin -

    + ENSAdmin Logo +

    ENSAdmin

    diff --git a/apps/ensadmin/src/styles.css b/apps/ensadmin/src/styles.css index 226b8f724..e8bc49f93 100644 --- a/apps/ensadmin/src/styles.css +++ b/apps/ensadmin/src/styles.css @@ -5,16 +5,15 @@ body { @apply m-0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", + "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } @theme inline { diff --git a/apps/ensadmin/tsconfig.json b/apps/ensadmin/tsconfig.json index 7920df93f..fbb99a246 100644 --- a/apps/ensadmin/tsconfig.json +++ b/apps/ensadmin/tsconfig.json @@ -22,7 +22,7 @@ "noUncheckedSideEffectImports": true, "baseUrl": ".", "paths": { - "@/*": ["./src/*"], + "@/*": ["./src/*"] } } } diff --git a/apps/ensadmin/vite.config.ts b/apps/ensadmin/vite.config.ts index 82addebd8..4fef005ab 100644 --- a/apps/ensadmin/vite.config.ts +++ b/apps/ensadmin/vite.config.ts @@ -1,23 +1,35 @@ -import { defineConfig } from 'vite' -import viteReact from '@vitejs/plugin-react' -import tailwindcss from '@tailwindcss/vite' +import { fileURLToPath, URL } from "node:url"; -import { tanstackRouter } from '@tanstack/router-plugin/vite' -import { fileURLToPath, URL } from 'node:url' +import tailwindcss from "@tailwindcss/vite"; +import { tanstackRouter } from "@tanstack/router-plugin/vite"; +import viteReact from "@vitejs/plugin-react"; +import { defineConfig } from "vite"; +import $monacoEditorPlugin from "vite-plugin-monaco-editor"; + +const monacoEditorPlugin = $monacoEditorPlugin.default ?? $monacoEditorPlugin; // https://vitejs.dev/config/ export default defineConfig({ plugins: [ tanstackRouter({ - target: 'react', + target: "react", autoCodeSplitting: true, }), viteReact(), tailwindcss(), + monacoEditorPlugin({ + languageWorkers: ["editorWorkerService", "json"], + customWorkers: [ + { + label: "graphql", + entry: "monaco-graphql/esm/graphql.worker.js", + }, + ], + }), ], resolve: { alias: { - '@': fileURLToPath(new URL('./src', import.meta.url)), + "@": fileURLToPath(new URL("./src", import.meta.url)), }, }, -}) +}); diff --git a/biome.jsonc b/biome.jsonc index 68e2cf067..32b9d5e8d 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.3.1/schema.json", + "$schema": "https://biomejs.dev/schemas/2.3.2/schema.json", "vcs": { "enabled": true, "clientKind": "git", diff --git a/docs/ensnode.io/biome.jsonc b/docs/ensnode.io/biome.jsonc index 30c5f014c..c964cdef8 100644 --- a/docs/ensnode.io/biome.jsonc +++ b/docs/ensnode.io/biome.jsonc @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.3.1/schema.json", + "$schema": "https://biomejs.dev/schemas/2.3.2/schema.json", "extends": "//", "assist": { "actions": { diff --git a/docs/ensrainbow.io/biome.jsonc b/docs/ensrainbow.io/biome.jsonc index 30c5f014c..c964cdef8 100644 --- a/docs/ensrainbow.io/biome.jsonc +++ b/docs/ensrainbow.io/biome.jsonc @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/2.3.1/schema.json", + "$schema": "https://biomejs.dev/schemas/2.3.2/schema.json", "extends": "//", "assist": { "actions": { diff --git a/packages/ensnode-sdk/src/client.test.ts b/packages/ensnode-sdk/src/client.test.ts index 1840f9816..f64a63da3 100644 --- a/packages/ensnode-sdk/src/client.test.ts +++ b/packages/ensnode-sdk/src/client.test.ts @@ -19,10 +19,8 @@ import { ChainIndexingConfigTypeIds, ChainIndexingStatusIds, CrossChainIndexingStrategyIds, - deserializeENSIndexerPublicConfig, OmnichainIndexingStatusIds, PluginName, - type SerializedENSIndexerPublicConfig, type SerializedOmnichainIndexingStatusSnapshotFollowing, } from "./ensindexer"; import type { ResolverRecordsSelection } from "./resolution"; @@ -231,7 +229,10 @@ describe("ENSNodeClient", () => { // TODO: integrate with default-case expectations from resolution api and test behavior it("should handle address and text selections", async () => { const mockResponse = { records: EXAMPLE_RECORDS_RESPONSE }; - mockFetch.mockResolvedValueOnce({ ok: true, json: async () => mockResponse }); + mockFetch.mockResolvedValueOnce({ + ok: true, + json: async () => mockResponse, + }); const client = new ENSNodeClient(); const response = await client.resolveRecords(EXAMPLE_NAME, EXAMPLE_SELECTION); @@ -246,7 +247,10 @@ describe("ENSNodeClient", () => { it("should include trace if specified", async () => { const mockResponse = { records: EXAMPLE_RECORDS_RESPONSE, trace: [] }; - mockFetch.mockResolvedValueOnce({ ok: true, json: async () => mockResponse }); + mockFetch.mockResolvedValueOnce({ + ok: true, + json: async () => mockResponse, + }); const client = new ENSNodeClient(); const response = await client.resolveRecords(EXAMPLE_NAME, EXAMPLE_SELECTION, { @@ -263,7 +267,10 @@ describe("ENSNodeClient", () => { }); it("should throw error when API returns error", async () => { - mockFetch.mockResolvedValueOnce({ ok: false, json: async () => EXAMPLE_ERROR_RESPONSE }); + mockFetch.mockResolvedValueOnce({ + ok: false, + json: async () => EXAMPLE_ERROR_RESPONSE, + }); const client = new ENSNodeClient(); await expect(client.resolveRecords(EXAMPLE_NAME, EXAMPLE_SELECTION)).rejects.toThrowError( @@ -293,10 +300,15 @@ describe("ENSNodeClient", () => { it("should include trace if specified", async () => { const mockResponse = { name: EXAMPLE_NAME, trace: [] }; - mockFetch.mockResolvedValueOnce({ ok: true, json: async () => mockResponse }); + mockFetch.mockResolvedValueOnce({ + ok: true, + json: async () => mockResponse, + }); const client = new ENSNodeClient(); - const response = await client.resolvePrimaryName(EXAMPLE_ADDRESS, 1, { trace: true }); + const response = await client.resolvePrimaryName(EXAMPLE_ADDRESS, 1, { + trace: true, + }); const expectedUrl = new URL( `/api/resolve/primary-name/${EXAMPLE_ADDRESS}/1`, @@ -327,7 +339,10 @@ describe("ENSNodeClient", () => { }); it("should throw error when API returns error", async () => { - mockFetch.mockResolvedValueOnce({ ok: false, json: async () => EXAMPLE_ERROR_RESPONSE }); + mockFetch.mockResolvedValueOnce({ + ok: false, + json: async () => EXAMPLE_ERROR_RESPONSE, + }); const client = new ENSNodeClient(); await expect(client.resolvePrimaryName(EXAMPLE_ADDRESS, 1)).rejects.toThrowError(ClientError); @@ -373,10 +388,15 @@ describe("ENSNodeClient", () => { it("should include trace if specified", async () => { const mockResponse = { ...EXAMPLE_PRIMARY_NAMES_RESPONSE, trace: [] }; - mockFetch.mockResolvedValueOnce({ ok: true, json: async () => mockResponse }); + mockFetch.mockResolvedValueOnce({ + ok: true, + json: async () => mockResponse, + }); const client = new ENSNodeClient(); - const response = await client.resolvePrimaryNames(EXAMPLE_ADDRESS, { trace: true }); + const response = await client.resolvePrimaryNames(EXAMPLE_ADDRESS, { + trace: true, + }); const expectedUrl = new URL( `/api/resolve/primary-names/${EXAMPLE_ADDRESS}`, @@ -407,7 +427,10 @@ describe("ENSNodeClient", () => { }); it("should throw error when API returns error", async () => { - mockFetch.mockResolvedValueOnce({ ok: false, json: async () => EXAMPLE_ERROR_RESPONSE }); + mockFetch.mockResolvedValueOnce({ + ok: false, + json: async () => EXAMPLE_ERROR_RESPONSE, + }); const client = new ENSNodeClient(); await expect(client.resolvePrimaryNames(EXAMPLE_ADDRESS)).rejects.toThrowError(ClientError); @@ -433,7 +456,10 @@ describe("ENSNodeClient", () => { }); it("should throw error when API returns error", async () => { - mockFetch.mockResolvedValueOnce({ ok: false, json: async () => EXAMPLE_ERROR_RESPONSE }); + mockFetch.mockResolvedValueOnce({ + ok: false, + json: async () => EXAMPLE_ERROR_RESPONSE, + }); const client = new ENSNodeClient(); @@ -463,7 +489,10 @@ describe("ENSNodeClient", () => { // arrange const client = new ENSNodeClient(); - mockFetch.mockResolvedValueOnce({ ok: false, json: async () => EXAMPLE_ERROR_RESPONSE }); + mockFetch.mockResolvedValueOnce({ + ok: false, + json: async () => EXAMPLE_ERROR_RESPONSE, + }); // act & assert await expect(client.indexingStatus()).rejects.toThrow( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1cb2dbb32..c42ed6623 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -250,6 +250,9 @@ importers: viem: specifier: 'catalog:' version: 2.38.5(typescript@5.9.3)(zod@3.25.76) + vite-plugin-monaco-editor: + specifier: ^1.1.0 + version: 1.1.0(monaco-editor@0.52.2) devDependencies: '@biomejs/biome': specifier: 2.2.4 @@ -7574,6 +7577,11 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true + vite-plugin-monaco-editor@1.1.0: + resolution: {integrity: sha512-IvtUqZotrRoVqwT0PBBDIZPNraya3BxN/bfcNfnxZ5rkJiGcNtO5eAOWWSgT7zullIAEqQwxMU83yL9J5k7gww==} + peerDependencies: + monaco-editor: '>=0.33.0' + vite-tsconfig-paths@4.3.1: resolution: {integrity: sha512-cfgJwcGOsIxXOLU/nELPny2/LUD/lcf1IbfyeKTv2bsupVbTH/xpFtdQlBmIP1GEK2CjjLxYhFfB+QODFAx5aw==} peerDependencies: @@ -11331,6 +11339,14 @@ snapshots: chai: 6.2.0 tinyrainbow: 3.0.3 + '@vitest/mocker@4.0.5(vite@7.1.12(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1))': + dependencies: + '@vitest/spy': 4.0.5 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.1.12(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1) + '@vitest/mocker@4.0.5(vite@7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1))': dependencies: '@vitest/spy': 4.0.5 @@ -15929,6 +15945,10 @@ snapshots: - supports-color - terser + vite-plugin-monaco-editor@1.1.0(monaco-editor@0.52.2): + dependencies: + monaco-editor: 0.52.2 + vite-tsconfig-paths@4.3.1(typescript@5.9.3)(vite@6.4.1(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1)): dependencies: debug: 4.4.3 @@ -16005,7 +16025,7 @@ snapshots: vitest@4.0.5(@types/debug@4.1.12)(@types/node@20.19.24)(jiti@2.6.1)(jsdom@27.0.1(postcss@8.5.6))(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1): dependencies: '@vitest/expect': 4.0.5 - '@vitest/mocker': 4.0.5(vite@7.1.12(@types/node@22.18.13)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1)) + '@vitest/mocker': 4.0.5(vite@7.1.12(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.20.6)(yaml@2.8.1)) '@vitest/pretty-format': 4.0.5 '@vitest/runner': 4.0.5 '@vitest/snapshot': 4.0.5 From ed1cc32009aa510b70b3b281b143c8014a7e442b Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Thu, 30 Oct 2025 16:55:29 +0000 Subject: [PATCH 3/4] dist --- apps/ensadmin/Dockerfile | 2 +- apps/ensadmin/READMETSR.md | 301 ----------------------- apps/ensadmin/nginx.conf | 13 - apps/ensadmin/package.json | 2 +- apps/ensadmin/src/routeTree.gen.ts | 378 ++++++++++++++--------------- 5 files changed, 191 insertions(+), 505 deletions(-) delete mode 100644 apps/ensadmin/READMETSR.md diff --git a/apps/ensadmin/Dockerfile b/apps/ensadmin/Dockerfile index 8b38d9678..f1a8fb1f3 100644 --- a/apps/ensadmin/Dockerfile +++ b/apps/ensadmin/Dockerfile @@ -18,7 +18,7 @@ RUN pnpm --filter ensadmin build FROM nginx:alpine AS runner # Copy the static export output -COPY --from=builder /app/apps/ensadmin/out /usr/share/nginx/html +COPY --from=builder /app/apps/ensadmin/dist /usr/share/nginx/html # Replace default nginx configuration with our own RUN rm -f /etc/nginx/conf.d/default.conf.default diff --git a/apps/ensadmin/READMETSR.md b/apps/ensadmin/READMETSR.md deleted file mode 100644 index 641f154c1..000000000 --- a/apps/ensadmin/READMETSR.md +++ /dev/null @@ -1,301 +0,0 @@ -Welcome to your new TanStack app! - -# Getting Started - -To run this application: - -```bash -pnpm install -pnpm start -``` - -# Building For Production - -To build this application for production: - -```bash -pnpm build -``` - -## Testing - -This project uses [Vitest](https://vitest.dev/) for testing. You can run the tests with: - -```bash -pnpm test -``` - -## Styling - -This project uses [Tailwind CSS](https://tailwindcss.com/) for styling. - - -## Linting & Formatting - -This project uses [Biome](https://biomejs.dev/) for linting and formatting. The following scripts are available: - - -```bash -pnpm lint -pnpm format -pnpm check -``` - - - -## Routing -This project uses [TanStack Router](https://tanstack.com/router). The initial setup is a file based router. Which means that the routes are managed as files in `src/routes`. - -### Adding A Route - -To add a new route to your application just add another a new file in the `./src/routes` directory. - -TanStack will automatically generate the content of the route file for you. - -Now that you have two routes you can use a `Link` component to navigate between them. - -### Adding Links - -To use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`. - -```tsx -import { Link } from "@tanstack/react-router"; -``` - -Then anywhere in your JSX you can use it like so: - -```tsx -About -``` - -This will create a link that will navigate to the `/about` route. - -More information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent). - -### Using A Layout - -In the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the `` component. - -Here is an example layout that includes a header: - -```tsx -import { Outlet, createRootRoute } from '@tanstack/react-router' -import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' - -import { Link } from "@tanstack/react-router"; - -export const Route = createRootRoute({ - component: () => ( - <> -

    - -
    - - - - ), -}) -``` - -The `` component is not required so you can remove it if you don't want it in your layout. - -More information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts). - - -## Data Fetching - -There are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered. - -For example: - -```tsx -const peopleRoute = createRoute({ - getParentRoute: () => rootRoute, - path: "/people", - loader: async () => { - const response = await fetch("https://swapi.dev/api/people"); - return response.json() as Promise<{ - results: { - name: string; - }[]; - }>; - }, - component: () => { - const data = peopleRoute.useLoaderData(); - return ( -
      - {data.results.map((person) => ( -
    • {person.name}
    • - ))} -
    - ); - }, -}); -``` - -Loaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters). - -### React-Query - -React-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze. - -First add your dependencies: - -```bash -pnpm add @tanstack/react-query @tanstack/react-query-devtools -``` - -Next we'll need to create a query client and provider. We recommend putting those in `main.tsx`. - -```tsx -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; - -// ... - -const queryClient = new QueryClient(); - -// ... - -if (!rootElement.innerHTML) { - const root = ReactDOM.createRoot(rootElement); - - root.render( - - - - ); -} -``` - -You can also add TanStack Query Devtools to the root route (optional). - -```tsx -import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; - -const rootRoute = createRootRoute({ - component: () => ( - <> - - - - - ), -}); -``` - -Now you can use `useQuery` to fetch your data. - -```tsx -import { useQuery } from "@tanstack/react-query"; - -import "./App.css"; - -function App() { - const { data } = useQuery({ - queryKey: ["people"], - queryFn: () => - fetch("https://swapi.dev/api/people") - .then((res) => res.json()) - .then((data) => data.results as { name: string }[]), - initialData: [], - }); - - return ( -
    -
      - {data.map((person) => ( -
    • {person.name}
    • - ))} -
    -
    - ); -} - -export default App; -``` - -You can find out everything you need to know on how to use React-Query in the [React-Query documentation](https://tanstack.com/query/latest/docs/framework/react/overview). - -## State Management - -Another common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project. - -First you need to add TanStack Store as a dependency: - -```bash -pnpm add @tanstack/store -``` - -Now let's create a simple counter in the `src/App.tsx` file as a demonstration. - -```tsx -import { useStore } from "@tanstack/react-store"; -import { Store } from "@tanstack/store"; -import "./App.css"; - -const countStore = new Store(0); - -function App() { - const count = useStore(countStore); - return ( -
    - -
    - ); -} - -export default App; -``` - -One of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates. - -Let's check this out by doubling the count using derived state. - -```tsx -import { useStore } from "@tanstack/react-store"; -import { Store, Derived } from "@tanstack/store"; -import "./App.css"; - -const countStore = new Store(0); - -const doubledStore = new Derived({ - fn: () => countStore.state * 2, - deps: [countStore], -}); -doubledStore.mount(); - -function App() { - const count = useStore(countStore); - const doubledCount = useStore(doubledStore); - - return ( -
    - -
    Doubled - {doubledCount}
    -
    - ); -} - -export default App; -``` - -We use the `Derived` class to create a new store that is derived from another store. The `Derived` class has a `mount` method that will start the derived store updating. - -Once we've created the derived store we can use it in the `App` component just like we would any other store using the `useStore` hook. - -You can find out everything you need to know on how to use TanStack Store in the [TanStack Store documentation](https://tanstack.com/store/latest). - -# Demo files - -Files prefixed with `demo` can be safely deleted. They are there to provide a starting point for you to play around with the features you've installed. - -# Learn More - -You can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com). diff --git a/apps/ensadmin/nginx.conf b/apps/ensadmin/nginx.conf index 447a4771f..94dd4c4e8 100644 --- a/apps/ensadmin/nginx.conf +++ b/apps/ensadmin/nginx.conf @@ -5,19 +5,6 @@ server { root /usr/share/nginx/html; index index.html; - # Backward compatibility redirects from ENSNode services - location = /about { - return 301 /; - } - - location = /gql/subgraph-compat { - return 301 /api/subgraph; - } - - location = /gql/ponder { - return 301 /; - } - # Try to serve the requested URI, then with .html extension, then as directory, or 404 location / { try_files $uri $uri.html $uri/ =404; diff --git a/apps/ensadmin/package.json b/apps/ensadmin/package.json index b1c3fd207..8161ff315 100644 --- a/apps/ensadmin/package.json +++ b/apps/ensadmin/package.json @@ -15,7 +15,7 @@ "scripts": { "dev": "vite --port 4173", "build": "vite build && tsc", - "start": "serve out -l 4173", + "start": "serve dist -l 4173", "lint": "biome check --write .", "lint:ci": "biome ci", "typecheck": "tsc --noEmit", diff --git a/apps/ensadmin/src/routeTree.gen.ts b/apps/ensadmin/src/routeTree.gen.ts index 13fc48abf..295a629b0 100644 --- a/apps/ensadmin/src/routeTree.gen.ts +++ b/apps/ensadmin/src/routeTree.gen.ts @@ -8,230 +8,230 @@ // You should NOT make any changes in this file as it will be overwritten. // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. -import { Route as rootRouteImport } from "./routes/__root"; -import { Route as ApiSubgraphRouteImport } from "./routes/api/subgraph"; -import { Route as ConnectionRouteImport } from "./routes/connection"; -import { Route as IndexRouteImport } from "./routes/index"; -import { Route as InspectPrimaryNameRouteImport } from "./routes/inspect/primary-name"; -import { Route as InspectPrimaryNamesRouteImport } from "./routes/inspect/primary-names"; -import { Route as InspectRecordsRouteImport } from "./routes/inspect/records"; -import { Route as InspectVisualizerRouteImport } from "./routes/inspect/visualizer"; -import { Route as NameRouteImport } from "./routes/name"; -import { Route as RegistrationRouteImport } from "./routes/registration"; -import { Route as StatusRouteImport } from "./routes/status"; +import { Route as rootRouteImport } from './routes/__root' +import { Route as StatusRouteImport } from './routes/status' +import { Route as RegistrationRouteImport } from './routes/registration' +import { Route as NameRouteImport } from './routes/name' +import { Route as ConnectionRouteImport } from './routes/connection' +import { Route as IndexRouteImport } from './routes/index' +import { Route as InspectVisualizerRouteImport } from './routes/inspect/visualizer' +import { Route as InspectRecordsRouteImport } from './routes/inspect/records' +import { Route as InspectPrimaryNamesRouteImport } from './routes/inspect/primary-names' +import { Route as InspectPrimaryNameRouteImport } from './routes/inspect/primary-name' +import { Route as ApiSubgraphRouteImport } from './routes/api/subgraph' const StatusRoute = StatusRouteImport.update({ - id: "/status", - path: "/status", + id: '/status', + path: '/status', getParentRoute: () => rootRouteImport, -} as any); +} as any) const RegistrationRoute = RegistrationRouteImport.update({ - id: "/registration", - path: "/registration", + id: '/registration', + path: '/registration', getParentRoute: () => rootRouteImport, -} as any); +} as any) const NameRoute = NameRouteImport.update({ - id: "/name", - path: "/name", + id: '/name', + path: '/name', getParentRoute: () => rootRouteImport, -} as any); +} as any) const ConnectionRoute = ConnectionRouteImport.update({ - id: "/connection", - path: "/connection", + id: '/connection', + path: '/connection', getParentRoute: () => rootRouteImport, -} as any); +} as any) const IndexRoute = IndexRouteImport.update({ - id: "/", - path: "/", + id: '/', + path: '/', getParentRoute: () => rootRouteImport, -} as any); +} as any) const InspectVisualizerRoute = InspectVisualizerRouteImport.update({ - id: "/inspect/visualizer", - path: "/inspect/visualizer", + id: '/inspect/visualizer', + path: '/inspect/visualizer', getParentRoute: () => rootRouteImport, -} as any); +} as any) const InspectRecordsRoute = InspectRecordsRouteImport.update({ - id: "/inspect/records", - path: "/inspect/records", + id: '/inspect/records', + path: '/inspect/records', getParentRoute: () => rootRouteImport, -} as any); +} as any) const InspectPrimaryNamesRoute = InspectPrimaryNamesRouteImport.update({ - id: "/inspect/primary-names", - path: "/inspect/primary-names", + id: '/inspect/primary-names', + path: '/inspect/primary-names', getParentRoute: () => rootRouteImport, -} as any); +} as any) const InspectPrimaryNameRoute = InspectPrimaryNameRouteImport.update({ - id: "/inspect/primary-name", - path: "/inspect/primary-name", + id: '/inspect/primary-name', + path: '/inspect/primary-name', getParentRoute: () => rootRouteImport, -} as any); +} as any) const ApiSubgraphRoute = ApiSubgraphRouteImport.update({ - id: "/api/subgraph", - path: "/api/subgraph", + id: '/api/subgraph', + path: '/api/subgraph', getParentRoute: () => rootRouteImport, -} as any); +} as any) export interface FileRoutesByFullPath { - "/": typeof IndexRoute; - "/connection": typeof ConnectionRoute; - "/name": typeof NameRoute; - "/registration": typeof RegistrationRoute; - "/status": typeof StatusRoute; - "/api/subgraph": typeof ApiSubgraphRoute; - "/inspect/primary-name": typeof InspectPrimaryNameRoute; - "/inspect/primary-names": typeof InspectPrimaryNamesRoute; - "/inspect/records": typeof InspectRecordsRoute; - "/inspect/visualizer": typeof InspectVisualizerRoute; + '/': typeof IndexRoute + '/connection': typeof ConnectionRoute + '/name': typeof NameRoute + '/registration': typeof RegistrationRoute + '/status': typeof StatusRoute + '/api/subgraph': typeof ApiSubgraphRoute + '/inspect/primary-name': typeof InspectPrimaryNameRoute + '/inspect/primary-names': typeof InspectPrimaryNamesRoute + '/inspect/records': typeof InspectRecordsRoute + '/inspect/visualizer': typeof InspectVisualizerRoute } export interface FileRoutesByTo { - "/": typeof IndexRoute; - "/connection": typeof ConnectionRoute; - "/name": typeof NameRoute; - "/registration": typeof RegistrationRoute; - "/status": typeof StatusRoute; - "/api/subgraph": typeof ApiSubgraphRoute; - "/inspect/primary-name": typeof InspectPrimaryNameRoute; - "/inspect/primary-names": typeof InspectPrimaryNamesRoute; - "/inspect/records": typeof InspectRecordsRoute; - "/inspect/visualizer": typeof InspectVisualizerRoute; + '/': typeof IndexRoute + '/connection': typeof ConnectionRoute + '/name': typeof NameRoute + '/registration': typeof RegistrationRoute + '/status': typeof StatusRoute + '/api/subgraph': typeof ApiSubgraphRoute + '/inspect/primary-name': typeof InspectPrimaryNameRoute + '/inspect/primary-names': typeof InspectPrimaryNamesRoute + '/inspect/records': typeof InspectRecordsRoute + '/inspect/visualizer': typeof InspectVisualizerRoute } export interface FileRoutesById { - __root__: typeof rootRouteImport; - "/": typeof IndexRoute; - "/connection": typeof ConnectionRoute; - "/name": typeof NameRoute; - "/registration": typeof RegistrationRoute; - "/status": typeof StatusRoute; - "/api/subgraph": typeof ApiSubgraphRoute; - "/inspect/primary-name": typeof InspectPrimaryNameRoute; - "/inspect/primary-names": typeof InspectPrimaryNamesRoute; - "/inspect/records": typeof InspectRecordsRoute; - "/inspect/visualizer": typeof InspectVisualizerRoute; + __root__: typeof rootRouteImport + '/': typeof IndexRoute + '/connection': typeof ConnectionRoute + '/name': typeof NameRoute + '/registration': typeof RegistrationRoute + '/status': typeof StatusRoute + '/api/subgraph': typeof ApiSubgraphRoute + '/inspect/primary-name': typeof InspectPrimaryNameRoute + '/inspect/primary-names': typeof InspectPrimaryNamesRoute + '/inspect/records': typeof InspectRecordsRoute + '/inspect/visualizer': typeof InspectVisualizerRoute } export interface FileRouteTypes { - fileRoutesByFullPath: FileRoutesByFullPath; + fileRoutesByFullPath: FileRoutesByFullPath fullPaths: - | "/" - | "/connection" - | "/name" - | "/registration" - | "/status" - | "/api/subgraph" - | "/inspect/primary-name" - | "/inspect/primary-names" - | "/inspect/records" - | "/inspect/visualizer"; - fileRoutesByTo: FileRoutesByTo; + | '/' + | '/connection' + | '/name' + | '/registration' + | '/status' + | '/api/subgraph' + | '/inspect/primary-name' + | '/inspect/primary-names' + | '/inspect/records' + | '/inspect/visualizer' + fileRoutesByTo: FileRoutesByTo to: - | "/" - | "/connection" - | "/name" - | "/registration" - | "/status" - | "/api/subgraph" - | "/inspect/primary-name" - | "/inspect/primary-names" - | "/inspect/records" - | "/inspect/visualizer"; + | '/' + | '/connection' + | '/name' + | '/registration' + | '/status' + | '/api/subgraph' + | '/inspect/primary-name' + | '/inspect/primary-names' + | '/inspect/records' + | '/inspect/visualizer' id: - | "__root__" - | "/" - | "/connection" - | "/name" - | "/registration" - | "/status" - | "/api/subgraph" - | "/inspect/primary-name" - | "/inspect/primary-names" - | "/inspect/records" - | "/inspect/visualizer"; - fileRoutesById: FileRoutesById; + | '__root__' + | '/' + | '/connection' + | '/name' + | '/registration' + | '/status' + | '/api/subgraph' + | '/inspect/primary-name' + | '/inspect/primary-names' + | '/inspect/records' + | '/inspect/visualizer' + fileRoutesById: FileRoutesById } export interface RootRouteChildren { - IndexRoute: typeof IndexRoute; - ConnectionRoute: typeof ConnectionRoute; - NameRoute: typeof NameRoute; - RegistrationRoute: typeof RegistrationRoute; - StatusRoute: typeof StatusRoute; - ApiSubgraphRoute: typeof ApiSubgraphRoute; - InspectPrimaryNameRoute: typeof InspectPrimaryNameRoute; - InspectPrimaryNamesRoute: typeof InspectPrimaryNamesRoute; - InspectRecordsRoute: typeof InspectRecordsRoute; - InspectVisualizerRoute: typeof InspectVisualizerRoute; + IndexRoute: typeof IndexRoute + ConnectionRoute: typeof ConnectionRoute + NameRoute: typeof NameRoute + RegistrationRoute: typeof RegistrationRoute + StatusRoute: typeof StatusRoute + ApiSubgraphRoute: typeof ApiSubgraphRoute + InspectPrimaryNameRoute: typeof InspectPrimaryNameRoute + InspectPrimaryNamesRoute: typeof InspectPrimaryNamesRoute + InspectRecordsRoute: typeof InspectRecordsRoute + InspectVisualizerRoute: typeof InspectVisualizerRoute } -declare module "@tanstack/react-router" { +declare module '@tanstack/react-router' { interface FileRoutesByPath { - "/status": { - id: "/status"; - path: "/status"; - fullPath: "/status"; - preLoaderRoute: typeof StatusRouteImport; - parentRoute: typeof rootRouteImport; - }; - "/registration": { - id: "/registration"; - path: "/registration"; - fullPath: "/registration"; - preLoaderRoute: typeof RegistrationRouteImport; - parentRoute: typeof rootRouteImport; - }; - "/name": { - id: "/name"; - path: "/name"; - fullPath: "/name"; - preLoaderRoute: typeof NameRouteImport; - parentRoute: typeof rootRouteImport; - }; - "/connection": { - id: "/connection"; - path: "/connection"; - fullPath: "/connection"; - preLoaderRoute: typeof ConnectionRouteImport; - parentRoute: typeof rootRouteImport; - }; - "/": { - id: "/"; - path: "/"; - fullPath: "/"; - preLoaderRoute: typeof IndexRouteImport; - parentRoute: typeof rootRouteImport; - }; - "/inspect/visualizer": { - id: "/inspect/visualizer"; - path: "/inspect/visualizer"; - fullPath: "/inspect/visualizer"; - preLoaderRoute: typeof InspectVisualizerRouteImport; - parentRoute: typeof rootRouteImport; - }; - "/inspect/records": { - id: "/inspect/records"; - path: "/inspect/records"; - fullPath: "/inspect/records"; - preLoaderRoute: typeof InspectRecordsRouteImport; - parentRoute: typeof rootRouteImport; - }; - "/inspect/primary-names": { - id: "/inspect/primary-names"; - path: "/inspect/primary-names"; - fullPath: "/inspect/primary-names"; - preLoaderRoute: typeof InspectPrimaryNamesRouteImport; - parentRoute: typeof rootRouteImport; - }; - "/inspect/primary-name": { - id: "/inspect/primary-name"; - path: "/inspect/primary-name"; - fullPath: "/inspect/primary-name"; - preLoaderRoute: typeof InspectPrimaryNameRouteImport; - parentRoute: typeof rootRouteImport; - }; - "/api/subgraph": { - id: "/api/subgraph"; - path: "/api/subgraph"; - fullPath: "/api/subgraph"; - preLoaderRoute: typeof ApiSubgraphRouteImport; - parentRoute: typeof rootRouteImport; - }; + '/status': { + id: '/status' + path: '/status' + fullPath: '/status' + preLoaderRoute: typeof StatusRouteImport + parentRoute: typeof rootRouteImport + } + '/registration': { + id: '/registration' + path: '/registration' + fullPath: '/registration' + preLoaderRoute: typeof RegistrationRouteImport + parentRoute: typeof rootRouteImport + } + '/name': { + id: '/name' + path: '/name' + fullPath: '/name' + preLoaderRoute: typeof NameRouteImport + parentRoute: typeof rootRouteImport + } + '/connection': { + id: '/connection' + path: '/connection' + fullPath: '/connection' + preLoaderRoute: typeof ConnectionRouteImport + parentRoute: typeof rootRouteImport + } + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexRouteImport + parentRoute: typeof rootRouteImport + } + '/inspect/visualizer': { + id: '/inspect/visualizer' + path: '/inspect/visualizer' + fullPath: '/inspect/visualizer' + preLoaderRoute: typeof InspectVisualizerRouteImport + parentRoute: typeof rootRouteImport + } + '/inspect/records': { + id: '/inspect/records' + path: '/inspect/records' + fullPath: '/inspect/records' + preLoaderRoute: typeof InspectRecordsRouteImport + parentRoute: typeof rootRouteImport + } + '/inspect/primary-names': { + id: '/inspect/primary-names' + path: '/inspect/primary-names' + fullPath: '/inspect/primary-names' + preLoaderRoute: typeof InspectPrimaryNamesRouteImport + parentRoute: typeof rootRouteImport + } + '/inspect/primary-name': { + id: '/inspect/primary-name' + path: '/inspect/primary-name' + fullPath: '/inspect/primary-name' + preLoaderRoute: typeof InspectPrimaryNameRouteImport + parentRoute: typeof rootRouteImport + } + '/api/subgraph': { + id: '/api/subgraph' + path: '/api/subgraph' + fullPath: '/api/subgraph' + preLoaderRoute: typeof ApiSubgraphRouteImport + parentRoute: typeof rootRouteImport + } } } @@ -246,7 +246,7 @@ const rootRouteChildren: RootRouteChildren = { InspectPrimaryNamesRoute: InspectPrimaryNamesRoute, InspectRecordsRoute: InspectRecordsRoute, InspectVisualizerRoute: InspectVisualizerRoute, -}; +} export const routeTree = rootRouteImport ._addFileChildren(rootRouteChildren) - ._addFileTypes(); + ._addFileTypes() From c0e0aabe77303316d70eacd3f60670ea6edb9898 Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Thu, 30 Oct 2025 18:37:57 +0000 Subject: [PATCH 4/4] mocks --- apps/ensadmin/index.html | 34 +- apps/ensadmin/package.json | 1 + .../src/app/@actions/api/subgraph/page.tsx | 21 - .../src/app/@actions/connection/page.tsx | 3 - apps/ensadmin/src/app/@actions/default.tsx | 3 - .../@actions/inspect/primary-name/page.tsx | 3 - .../@actions/inspect/primary-names/page.tsx | 3 - .../src/app/@actions/inspect/records/page.tsx | 3 - apps/ensadmin/src/app/@actions/layout.tsx | 3 - apps/ensadmin/src/app/@actions/loading.tsx | 3 - apps/ensadmin/src/app/@actions/name/page.tsx | 32 -- .../src/app/@actions/registration/page.tsx | 3 - .../ensadmin/src/app/@actions/status/page.tsx | 3 - .../@breadcrumbs/(apis)/api/subgraph/page.tsx | 9 - .../src/app/@breadcrumbs/(apis)/layout.tsx | 5 - .../src/app/@breadcrumbs/connection/page.tsx | 9 - .../ensadmin/src/app/@breadcrumbs/default.tsx | 3 - .../src/app/@breadcrumbs/inspect/layout.tsx | 5 - .../inspect/primary-name/page.tsx | 9 - .../inspect/primary-names/page.tsx | 9 - .../app/@breadcrumbs/inspect/records/page.tsx | 9 - .../@breadcrumbs/inspect/visualizer/page.tsx | 14 - apps/ensadmin/src/app/@breadcrumbs/layout.tsx | 9 - .../@breadcrumbs/mock/config-info/page.tsx | 26 - .../mock/display-identity/page.tsx | 26 - .../@breadcrumbs/mock/indexing-stats/page.tsx | 26 - .../src/app/@breadcrumbs/mock/layout.tsx | 9 - .../src/app/@breadcrumbs/mock/page.tsx | 9 - .../mock/recent-registrations/page.tsx | 26 - .../@breadcrumbs/mock/relative-time/page.tsx | 25 - .../src/app/@breadcrumbs/name/page.tsx | 46 -- .../app/@breadcrumbs/registration/layout.tsx | 5 - .../app/@breadcrumbs/registration/page.tsx | 9 - .../src/app/@breadcrumbs/status/page.tsx | 9 - apps/ensadmin/src/app/layout.tsx | 78 --- apps/ensadmin/src/app/mock/config-api.mock.ts | 30 -- .../src/components/layout-wrapper.tsx | 20 +- .../ensadmin/src/components/route-actions.tsx | 38 ++ .../src/components/route-breadcrumbs.tsx | 220 ++++++++ .../{app => lib}/mock/config-info/data.json | 0 .../mock/indexing-status-api.mock.ts | 0 .../{app => lib}/mock/relative-time/data.json | 0 apps/ensadmin/src/main.tsx | 1 + apps/ensadmin/src/routeTree.gen.ts | 504 +++++++++++------- apps/ensadmin/src/routes/__root.tsx | 2 +- .../page.tsx => routes/mock/config-info.tsx} | 36 +- .../mock/display-identity.tsx} | 9 +- .../mock/page.tsx => routes/mock/index.tsx} | 20 +- .../mock/indexing-stats.tsx} | 12 +- .../mock/recent-registrations.tsx} | 10 +- .../mock/relative-time.tsx} | 11 +- apps/ensadmin/src/styles.css | 22 +- pnpm-lock.yaml | 8 + 53 files changed, 691 insertions(+), 742 deletions(-) delete mode 100644 apps/ensadmin/src/app/@actions/api/subgraph/page.tsx delete mode 100644 apps/ensadmin/src/app/@actions/connection/page.tsx delete mode 100644 apps/ensadmin/src/app/@actions/default.tsx delete mode 100644 apps/ensadmin/src/app/@actions/inspect/primary-name/page.tsx delete mode 100644 apps/ensadmin/src/app/@actions/inspect/primary-names/page.tsx delete mode 100644 apps/ensadmin/src/app/@actions/inspect/records/page.tsx delete mode 100644 apps/ensadmin/src/app/@actions/layout.tsx delete mode 100644 apps/ensadmin/src/app/@actions/loading.tsx delete mode 100644 apps/ensadmin/src/app/@actions/name/page.tsx delete mode 100644 apps/ensadmin/src/app/@actions/registration/page.tsx delete mode 100644 apps/ensadmin/src/app/@actions/status/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/(apis)/api/subgraph/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/(apis)/layout.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/connection/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/default.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/inspect/layout.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/inspect/primary-name/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/inspect/primary-names/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/inspect/records/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/inspect/visualizer/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/layout.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/mock/config-info/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/mock/display-identity/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/mock/indexing-stats/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/mock/layout.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/mock/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/mock/recent-registrations/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/mock/relative-time/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/name/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/registration/layout.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/registration/page.tsx delete mode 100644 apps/ensadmin/src/app/@breadcrumbs/status/page.tsx delete mode 100644 apps/ensadmin/src/app/layout.tsx delete mode 100644 apps/ensadmin/src/app/mock/config-api.mock.ts create mode 100644 apps/ensadmin/src/components/route-actions.tsx create mode 100644 apps/ensadmin/src/components/route-breadcrumbs.tsx rename apps/ensadmin/src/{app => lib}/mock/config-info/data.json (100%) rename apps/ensadmin/src/{app => lib}/mock/indexing-status-api.mock.ts (100%) rename apps/ensadmin/src/{app => lib}/mock/relative-time/data.json (100%) rename apps/ensadmin/src/{app/mock/config-info/page.tsx => routes/mock/config-info.tsx} (67%) rename apps/ensadmin/src/{app/mock/display-identity/page.tsx => routes/mock/display-identity.tsx} (98%) rename apps/ensadmin/src/{app/mock/page.tsx => routes/mock/index.tsx} (70%) rename apps/ensadmin/src/{app/mock/indexing-stats/page.tsx => routes/mock/indexing-stats.tsx} (92%) rename apps/ensadmin/src/{app/mock/recent-registrations/page.tsx => routes/mock/recent-registrations.tsx} (92%) rename apps/ensadmin/src/{app/mock/relative-time/page.tsx => routes/mock/relative-time.tsx} (97%) diff --git a/apps/ensadmin/index.html b/apps/ensadmin/index.html index e4cf0f5a2..2f6cc28eb 100644 --- a/apps/ensadmin/index.html +++ b/apps/ensadmin/index.html @@ -5,13 +5,43 @@ + + + ENSAdmin + + + + + + + + + + + + + + + + + + + - Create TanStack App - ensadmin-vite + + +
    diff --git a/apps/ensadmin/package.json b/apps/ensadmin/package.json index 8161ff315..cb25befa6 100644 --- a/apps/ensadmin/package.json +++ b/apps/ensadmin/package.json @@ -27,6 +27,7 @@ "@ensnode/ensnode-schema": "workspace:*", "@ensnode/ensnode-sdk": "workspace:*", "@ensnode/ponder-metadata": "workspace:*", + "@fontsource-variable/inter": "^5.2.8", "@formkit/auto-animate": "^0.9.0", "@graphiql/plugin-explorer": "5.1.1", "@graphiql/react": "0.37.1", diff --git a/apps/ensadmin/src/app/@actions/api/subgraph/page.tsx b/apps/ensadmin/src/app/@actions/api/subgraph/page.tsx deleted file mode 100644 index 24bb8506c..000000000 --- a/apps/ensadmin/src/app/@actions/api/subgraph/page.tsx +++ /dev/null @@ -1,21 +0,0 @@ -"use client"; - -import { CopyButton } from "@/components/copy-button"; -import { useSelectedConnection } from "@/hooks/active/use-selected-connection"; - -export default function ActionsSubgraphCompatPage() { - const { validatedSelectedConnection } = useSelectedConnection(); - - // TODO: we need a broader refactor to recognize the difference between - // a selected connection being in a valid format or not. - if (!validatedSelectedConnection.isValid) return null; - - const url = new URL(`/subgraph`, validatedSelectedConnection.url).toString(); - - return ( -
    - {url} - -
    - ); -} diff --git a/apps/ensadmin/src/app/@actions/connection/page.tsx b/apps/ensadmin/src/app/@actions/connection/page.tsx deleted file mode 100644 index 0c2eca337..000000000 --- a/apps/ensadmin/src/app/@actions/connection/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function ConnectionActions() { - return null; -} diff --git a/apps/ensadmin/src/app/@actions/default.tsx b/apps/ensadmin/src/app/@actions/default.tsx deleted file mode 100644 index 44918316f..000000000 --- a/apps/ensadmin/src/app/@actions/default.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function ActionsDefault() { - return null; -} diff --git a/apps/ensadmin/src/app/@actions/inspect/primary-name/page.tsx b/apps/ensadmin/src/app/@actions/inspect/primary-name/page.tsx deleted file mode 100644 index 04a75648f..000000000 --- a/apps/ensadmin/src/app/@actions/inspect/primary-name/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function PrimaryNameActions() { - return null; -} diff --git a/apps/ensadmin/src/app/@actions/inspect/primary-names/page.tsx b/apps/ensadmin/src/app/@actions/inspect/primary-names/page.tsx deleted file mode 100644 index 759aaac3a..000000000 --- a/apps/ensadmin/src/app/@actions/inspect/primary-names/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function PrimaryNamesActions() { - return null; -} diff --git a/apps/ensadmin/src/app/@actions/inspect/records/page.tsx b/apps/ensadmin/src/app/@actions/inspect/records/page.tsx deleted file mode 100644 index 9a0e43395..000000000 --- a/apps/ensadmin/src/app/@actions/inspect/records/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function RecordsActions() { - return null; -} diff --git a/apps/ensadmin/src/app/@actions/layout.tsx b/apps/ensadmin/src/app/@actions/layout.tsx deleted file mode 100644 index b444b3aee..000000000 --- a/apps/ensadmin/src/app/@actions/layout.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function ActionsLayout({ children }: { children: React.ReactNode }) { - return children; -} diff --git a/apps/ensadmin/src/app/@actions/loading.tsx b/apps/ensadmin/src/app/@actions/loading.tsx deleted file mode 100644 index 8a6b0b05a..000000000 --- a/apps/ensadmin/src/app/@actions/loading.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Loading() { - return
    ; -} diff --git a/apps/ensadmin/src/app/@actions/name/page.tsx b/apps/ensadmin/src/app/@actions/name/page.tsx deleted file mode 100644 index 9b4e1e75d..000000000 --- a/apps/ensadmin/src/app/@actions/name/page.tsx +++ /dev/null @@ -1,32 +0,0 @@ -"use client"; - -import { useSearchParams } from "next/navigation"; - -import type { Name } from "@ensnode/ensnode-sdk"; - -import { ExternalLinkWithIcon } from "@/components/link"; -import { Button } from "@/components/ui/button"; -import { useNamespace } from "@/hooks/async/use-namespace"; -import { buildExternalEnsAppProfileUrl } from "@/lib/namespace-utils"; - -export default function ActionsNamePage() { - const searchParams = useSearchParams(); - const nameParam = searchParams.get("name"); - - const name = nameParam ? (decodeURIComponent(nameParam) as Name) : null; - - const { data: namespace } = useNamespace(); - - const ensAppProfileUrl = - name && namespace ? buildExternalEnsAppProfileUrl(name, namespace) : null; - - if (!ensAppProfileUrl) return null; - - return ( - - ); -} diff --git a/apps/ensadmin/src/app/@actions/registration/page.tsx b/apps/ensadmin/src/app/@actions/registration/page.tsx deleted file mode 100644 index cfa72d3e1..000000000 --- a/apps/ensadmin/src/app/@actions/registration/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function ActionsExploreRegistrationsPage() { - return null; -} diff --git a/apps/ensadmin/src/app/@actions/status/page.tsx b/apps/ensadmin/src/app/@actions/status/page.tsx deleted file mode 100644 index bc0caacdf..000000000 --- a/apps/ensadmin/src/app/@actions/status/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function StatusActions() { - return null; -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/(apis)/api/subgraph/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/(apis)/api/subgraph/page.tsx deleted file mode 100644 index b71535d4b..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/(apis)/api/subgraph/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { BreadcrumbItem, BreadcrumbPage } from "@/components/ui/breadcrumb"; - -export default function Page() { - return ( - - Subgraph (GraphQL) - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/(apis)/layout.tsx b/apps/ensadmin/src/app/@breadcrumbs/(apis)/layout.tsx deleted file mode 100644 index 6b40d4517..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/(apis)/layout.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import BreadcrumbsGroup from "@/components/breadcrumbs/group"; - -export default function BreadcrumbsAPIsLayout({ children }: { children: React.ReactNode }) { - return {children}; -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/connection/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/connection/page.tsx deleted file mode 100644 index 5ffc8aa53..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/connection/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { BreadcrumbItem, BreadcrumbPage } from "@/components/ui/breadcrumb"; - -export default function Page() { - return ( - - Connection - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/default.tsx b/apps/ensadmin/src/app/@breadcrumbs/default.tsx deleted file mode 100644 index 616118376..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/default.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function BreadcrumbsDefault() { - return null; -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/inspect/layout.tsx b/apps/ensadmin/src/app/@breadcrumbs/inspect/layout.tsx deleted file mode 100644 index 41911a2d2..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/inspect/layout.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import BreadcrumbsGroup from "@/components/breadcrumbs/group"; - -export default function Layout({ children }: { children: React.ReactNode }) { - return {children}; -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/inspect/primary-name/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/inspect/primary-name/page.tsx deleted file mode 100644 index b809ab87a..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/inspect/primary-name/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { BreadcrumbItem, BreadcrumbPage } from "@/components/ui/breadcrumb"; - -export default function Page() { - return ( - - Primary Name Resolution - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/inspect/primary-names/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/inspect/primary-names/page.tsx deleted file mode 100644 index 1d3aa361c..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/inspect/primary-names/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { BreadcrumbItem, BreadcrumbPage } from "@/components/ui/breadcrumb"; - -export default function Page() { - return ( - - Primary Names Resolution - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/inspect/records/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/inspect/records/page.tsx deleted file mode 100644 index b04d84489..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/inspect/records/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { BreadcrumbItem, BreadcrumbPage } from "@/components/ui/breadcrumb"; - -export default function Page() { - return ( - - Records Resolution - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/inspect/visualizer/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/inspect/visualizer/page.tsx deleted file mode 100644 index 40e3397a7..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/inspect/visualizer/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { BreadcrumbItem, BreadcrumbPage } from "@/components/ui/breadcrumb"; - -export default function Page() { - return ( - - - Visualization Example{" "} - - teaser - - - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/layout.tsx b/apps/ensadmin/src/app/@breadcrumbs/layout.tsx deleted file mode 100644 index c06f0f439..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/layout.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Breadcrumb, BreadcrumbList } from "@/components/ui/breadcrumb"; - -export default function BreadcrumbsLayout({ children }: { children: React.ReactNode }) { - return ( - - {children} - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/mock/config-info/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/mock/config-info/page.tsx deleted file mode 100644 index 7f508fd19..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/mock/config-info/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -"use client"; - -import { - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbPage, - BreadcrumbSeparator, -} from "@/components/ui/breadcrumb"; -import { useRawConnectionUrlParam } from "@/hooks/use-connection-url-param"; - -export default function Page() { - const { retainCurrentRawConnectionUrlParam } = useRawConnectionUrlParam(); - const uiMocksBaseHref = retainCurrentRawConnectionUrlParam("/mock"); - - return ( - <> - - UI Mocks - - - - ENSNodeConfigInfo - - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/mock/display-identity/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/mock/display-identity/page.tsx deleted file mode 100644 index 5a63e3ef4..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/mock/display-identity/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -"use client"; - -import { - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbPage, - BreadcrumbSeparator, -} from "@/components/ui/breadcrumb"; -import { useRawConnectionUrlParam } from "@/hooks/use-connection-url-param"; - -export default function Page() { - const { retainCurrentRawConnectionUrlParam } = useRawConnectionUrlParam(); - const uiMocksBaseHref = retainCurrentRawConnectionUrlParam("/mock"); - - return ( - <> - - UI Mocks - - - - DisplayIdentity - - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/mock/indexing-stats/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/mock/indexing-stats/page.tsx deleted file mode 100644 index 8f9dd043b..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/mock/indexing-stats/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -"use client"; - -import { - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbPage, - BreadcrumbSeparator, -} from "@/components/ui/breadcrumb"; -import { useRawConnectionUrlParam } from "@/hooks/use-connection-url-param"; - -export default function Page() { - const { retainCurrentRawConnectionUrlParam } = useRawConnectionUrlParam(); - const uiMocksBaseHref = retainCurrentRawConnectionUrlParam("/mock"); - - return ( - <> - - UI Mocks - - - - IndexingStats - - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/mock/layout.tsx b/apps/ensadmin/src/app/@breadcrumbs/mock/layout.tsx deleted file mode 100644 index 6351256bf..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/mock/layout.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Breadcrumb, BreadcrumbList } from "@/components/ui/breadcrumb"; - -export default function Layout({ children }: { children: React.ReactNode }) { - return ( - - {children} - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/mock/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/mock/page.tsx deleted file mode 100644 index 19f7cffee..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/mock/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { BreadcrumbItem, BreadcrumbPage } from "@/components/ui/breadcrumb"; - -export default function Page() { - return ( - - UI Mocks - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/mock/recent-registrations/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/mock/recent-registrations/page.tsx deleted file mode 100644 index bd4691347..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/mock/recent-registrations/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -"use client"; - -import { - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbPage, - BreadcrumbSeparator, -} from "@/components/ui/breadcrumb"; -import { useRawConnectionUrlParam } from "@/hooks/use-connection-url-param"; - -export default function Page() { - const { retainCurrentRawConnectionUrlParam } = useRawConnectionUrlParam(); - const uiMocksBaseHref = retainCurrentRawConnectionUrlParam("/mock"); - - return ( - <> - - UI Mocks - - - - RecentRegistrations - - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/mock/relative-time/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/mock/relative-time/page.tsx deleted file mode 100644 index 199d3a118..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/mock/relative-time/page.tsx +++ /dev/null @@ -1,25 +0,0 @@ -"use client"; - -import { - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbPage, - BreadcrumbSeparator, -} from "@/components/ui/breadcrumb"; -import { useRawConnectionUrlParam } from "@/hooks/use-connection-url-param"; - -export default function Page() { - const { retainCurrentRawConnectionUrlParam } = useRawConnectionUrlParam(); - const uiMocksBaseHref = retainCurrentRawConnectionUrlParam("/mock"); - return ( - <> - - UI Mocks - - - - RelativeTime - - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/name/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/name/page.tsx deleted file mode 100644 index d83791aba..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/name/page.tsx +++ /dev/null @@ -1,46 +0,0 @@ -"use client"; - -import { useSearchParams } from "next/navigation"; - -import type { Name } from "@ensnode/ensnode-sdk"; - -import BreadcrumbsGroup from "@/components/breadcrumbs/group"; -import { NameDisplay } from "@/components/identity/utils"; -import { - BreadcrumbItem, - BreadcrumbLink, - BreadcrumbPage, - BreadcrumbSeparator, -} from "@/components/ui/breadcrumb"; -import { useRawConnectionUrlParam } from "@/hooks/use-connection-url-param"; - -export default function Page() { - const searchParams = useSearchParams(); - const nameParam = searchParams.get("name"); - const { retainCurrentRawConnectionUrlParam } = useRawConnectionUrlParam(); - const exploreNamesBaseHref = retainCurrentRawConnectionUrlParam("/name"); - - const name = nameParam ? (decodeURIComponent(nameParam) as Name) : null; - - return ( - - {name ? ( - <> - - Names - - - - - - - - - ) : ( - - Names - - )} - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/registration/layout.tsx b/apps/ensadmin/src/app/@breadcrumbs/registration/layout.tsx deleted file mode 100644 index f642722e5..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/registration/layout.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import BreadcrumbsGroup from "@/components/breadcrumbs/group"; - -export default function BreadcrumbsNameLayout({ children }: { children: React.ReactNode }) { - return {children}; -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/registration/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/registration/page.tsx deleted file mode 100644 index b36b59bbe..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/registration/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { BreadcrumbItem, BreadcrumbPage } from "@/components/ui/breadcrumb"; - -export default function Page() { - return ( - - Registrations - - ); -} diff --git a/apps/ensadmin/src/app/@breadcrumbs/status/page.tsx b/apps/ensadmin/src/app/@breadcrumbs/status/page.tsx deleted file mode 100644 index 24a1e2bb9..000000000 --- a/apps/ensadmin/src/app/@breadcrumbs/status/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { BreadcrumbItem, BreadcrumbPage } from "@/components/ui/breadcrumb"; - -export default function Page() { - return ( - - Status - - ); -} diff --git a/apps/ensadmin/src/app/layout.tsx b/apps/ensadmin/src/app/layout.tsx deleted file mode 100644 index 244b08d13..000000000 --- a/apps/ensadmin/src/app/layout.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import type { Metadata } from "next"; -import "./globals.css"; - -import { Inter } from "next/font/google"; -import Script from "next/script"; -import { Suspense } from "react"; - -import { LayoutWrapper } from "@/components/layout-wrapper"; -import { QueryClientProvider } from "@/components/query-client/components"; -import { Toaster } from "@/components/ui/sonner"; -import { ConnectionsLibraryProvider } from "@/hooks/use-connections-library"; -import { ensAdminPublicUrl } from "@/lib/env"; - -const inter = Inter({ - variable: "--font-inter", - subsets: ["latin"], -}); - -const siteName = "ENSAdmin"; -const title = "ENSAdmin"; -const description = "Explore the ENS Protocol like never before"; - -export const metadata: Metadata = { - title: title, - description: description, - metadataBase: ensAdminPublicUrl(), - openGraph: { - title: { - template: `${siteName} - %s`, - default: title, - }, - description: description, - url: "/", - type: "website", - siteName: siteName, - images: ["/opengraph-image.png"], - }, - twitter: { - title: { - template: `${siteName} - %s`, - default: title, - }, - card: "summary_large_image", - site: "@NamehashLabs", - creator: "@NamehashLabs", - images: ["/twitter-image.png"], - }, -}; - -export default function Layout({ - children, - breadcrumbs, - actions, -}: { - children: React.ReactNode; - breadcrumbs: React.ReactNode; - actions: React.ReactNode; -}) { - return ( - - - - - - - {children} - - - - - - - {/* load the runtime-config.js script ahead of next.js */} -