From 2c5545f11d6b755861da0984803364f97068effe Mon Sep 17 00:00:00 2001 From: Nicu Chiciuc Date: Fri, 30 Oct 2026 14:56:42 +0200 Subject: [PATCH 1/2] A console on the base: sign-in, stacks, and the hub A TanStack Start site on convex-hosting, served by the base deployment next to the hub. Accounts are Convex Auth password accounts with no sign-up: an internal function creates them. The pages read the Alchemy state through the redacted reader, with the stack as the center and no GitHub call. The broker moves to convex/broker.ts, so that the admin functions do not import the build of the site. Co-Authored-By: Claude Opus 5.5 --- .gitignore | 2 + AGENTS.md | 13 +- alchemy.run.ts | 2 +- convex/_generated/api.d.ts | 11 + convex/_generated/dataModel.d.ts | 34 +- convex/_generated/server.d.ts | 2 + convex/auth.config.ts | 17 +- convex/auth.ts | 99 ++ convex/authAdmin.ts | 32 + convex/broker.ts | 13 + convex/console.ts | 79 ++ convex/convex.config.ts | 14 + convex/http.ts | 28 +- convex/identityBroker.ts | 2 +- convex/schema.ts | 7 + package.json | 26 +- pnpm-lock.yaml | 2209 +++++++++++++++++++++++++++++- pnpm-workspace.yaml | 8 + scripts/ensure-convex-auth.ts | 64 + src/format.ts | 4 + src/routeTree.gen.ts | 152 ++ src/router.tsx | 37 + src/routes/__root.tsx | 39 + src/routes/_authed.tsx | 34 + src/routes/_authed/hub.tsx | 51 + src/routes/_authed/index.tsx | 60 + src/routes/_authed/stacks.$.tsx | 105 ++ src/routes/signin.tsx | 82 ++ src/server.ts | 51 + src/style.css | 5 + tsconfig.app.json | 22 + tsconfig.json | 6 +- vite.config.ts | 11 +- 33 files changed, 3228 insertions(+), 93 deletions(-) create mode 100644 convex/auth.ts create mode 100644 convex/authAdmin.ts create mode 100644 convex/broker.ts create mode 100644 convex/console.ts create mode 100644 convex/schema.ts create mode 100644 scripts/ensure-convex-auth.ts create mode 100644 src/format.ts create mode 100644 src/routeTree.gen.ts create mode 100644 src/router.tsx create mode 100644 src/routes/__root.tsx create mode 100644 src/routes/_authed.tsx create mode 100644 src/routes/_authed/hub.tsx create mode 100644 src/routes/_authed/index.tsx create mode 100644 src/routes/_authed/stacks.$.tsx create mode 100644 src/routes/signin.tsx create mode 100644 src/server.ts create mode 100644 src/style.css create mode 100644 tsconfig.app.json diff --git a/.gitignore b/.gitignore index 43166a5..ded1ef2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ node_modules .env .alchemy/ +dist +.tanstack diff --git a/AGENTS.md b/AGENTS.md index 70d37fa..1f9f6d6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,14 +6,23 @@ in its repository. - `convex/connectors.ts` lists the providers the hub offers. A provider that needs credentials also gets its variables declared in `convex/convex.config.ts`. -- `convex/http.ts` mounts the broker; `convex/identityBroker.ts` exports the admin functions for - `npx convex run`; `convex/crons.ts` runs the cleanup. +- `convex/broker.ts` defines the broker, `convex/http.ts` mounts it, `convex/identityBroker.ts` + exports the admin functions for `npx convex run`, and `convex/crons.ts` runs the cleanup. - `convex/state.ts`, `convex/reader.ts`, and `convex/auth.config.ts` serve the Alchemy state store, from the exports of `@samebase/alchemy-convex`. A push replaces every function, so a function that leaves these files leaves every stack of the team without its state. - `alchemy.run.ts` is the stack `samebase/team-base` (adopted project, adopted production deployment, push); `scripts/check-keys.ts` checks the key set inside the `deploy` script the push runs and never creates it; `scripts/init-keys.ts` creates it once, by hand. +- `src/` is the console of the base, a TanStack Start site that `convex/http.ts` serves through + convex-hosting. `convex/console.ts` holds its reads: each one needs a session, and the state comes + through the redacted `reader.repository`, so a secret never reaches the browser. A page cannot use + the paths of the hub or of Convex Auth: `/authorize`, `/continue`, `/token`, `/userinfo`, + `/connectors/*`, `/.well-known/*`, `/auth/*`. +- The console has no sign-up. Run `authAdmin:createOrUpdatePasswordAccount` from the Functions page + of the Convex dashboard, with the email and password you choose, not in a terminal. +- `pnpm run deploy:dev` builds, uploads, and pushes to the development deployment. It must run once + before `pnpm run dev`: `convex/http.ts` imports the build. - Never use `npx convex import --replace-all` on this deployment, also not with `--component`: it deletes the rows of the other components. - Never use the U+2014 em dash character. No `any`, no type assertions except `as const`. diff --git a/alchemy.run.ts b/alchemy.run.ts index d02a401..913cf4a 100644 --- a/alchemy.run.ts +++ b/alchemy.run.ts @@ -51,7 +51,7 @@ export default Alchemy.Stack( path: "./convex", command: ["node", "--run", "deploy"], // The push inputs besides the functions, package.json, and the lockfile. - include: ["scripts/**", "tsconfig*.json"], + include: ["scripts/**", "tsconfig*.json", "src/**", "vite.config.ts"], } satisfies Convex.Source; // The variables of the deployment. The secret is a prop, so the state store holds it next to // the deployment it serves. diff --git a/convex/_generated/api.d.ts b/convex/_generated/api.d.ts index 172e990..9fc4c87 100644 --- a/convex/_generated/api.d.ts +++ b/convex/_generated/api.d.ts @@ -8,7 +8,11 @@ * @module */ +import type * as auth from "../auth.js"; +import type * as authAdmin from "../authAdmin.js"; +import type * as broker from "../broker.js"; import type * as connectors from "../connectors.js"; +import type * as console from "../console.js"; import type * as crons from "../crons.js"; import type * as http from "../http.js"; import type * as identityBroker from "../identityBroker.js"; @@ -22,7 +26,11 @@ import type { } from "convex/server"; declare const fullApi: ApiFromModules<{ + auth: typeof auth; + authAdmin: typeof authAdmin; + broker: typeof broker; connectors: typeof connectors; + console: typeof console; crons: typeof crons; http: typeof http; identityBroker: typeof identityBroker; @@ -59,4 +67,7 @@ export declare const internal: FilterApi< export declare const components: { identityBroker: import("@samebase/identity-broker/_generated/component.js").ComponentApi<"identityBroker">; alchemyState: import("@samebase/alchemy-convex/state/_generated/component.js").ComponentApi<"alchemyState">; + auth: import("@convex-dev/auth/_generated/component.js").ComponentApi<"auth">; + authPassword: import("@convex-dev/auth/components/password/_generated/component.js").ComponentApi<"authPassword">; + hosting: import("@samebase/convex-hosting/_generated/component.js").ComponentApi<"hosting">; }; diff --git a/convex/_generated/dataModel.d.ts b/convex/_generated/dataModel.d.ts index a850cc1..f97fd19 100644 --- a/convex/_generated/dataModel.d.ts +++ b/convex/_generated/dataModel.d.ts @@ -8,29 +8,29 @@ * @module */ -import { AnyDataModel } from "convex/server"; +import type { + DataModelFromSchemaDefinition, + DocumentByName, + TableNamesInDataModel, + SystemTableNames, +} from "convex/server"; import type { GenericId } from "convex/values"; - -/** - * No `schema.ts` file found! - * - * This generated code has permissive types like `Doc = any` because - * Convex doesn't know your schema. If you'd like more type safety, see - * https://docs.convex.dev/using/schemas for instructions on how to add a - * schema file. - * - * After you change a schema, rerun codegen with `npx convex dev`. - */ +import schema from "../schema.js"; /** * The names of all of your Convex tables. */ -export type TableNames = string; +export type TableNames = TableNamesInDataModel; /** * The type of a document stored in Convex. + * + * @typeParam TableName - A string literal type of the table name (like "users"). */ -export type Doc = any; +export type Doc = DocumentByName< + DataModel, + TableName +>; /** * An identifier for a document in Convex. @@ -42,8 +42,10 @@ export type Doc = any; * * IDs are just strings at runtime, but this type can be used to distinguish them from other * strings when type checking. + * + * @typeParam TableName - A string literal type of the table name (like "users"). */ -export type Id = +export type Id = GenericId; /** @@ -55,4 +57,4 @@ export type Id = * This type is used to parameterize methods like `queryGeneric` and * `mutationGeneric` to make them type-safe. */ -export type DataModel = AnyDataModel; +export type DataModel = DataModelFromSchemaDefinition; diff --git a/convex/_generated/server.d.ts b/convex/_generated/server.d.ts index 2b5f025..aa3cc55 100644 --- a/convex/_generated/server.d.ts +++ b/convex/_generated/server.d.ts @@ -32,6 +32,8 @@ type Env = { readonly CONVEX_SITE_URL: string; readonly AUTH_GITHUB_CLIENT_ID: string; readonly AUTH_GITHUB_CLIENT_SECRET: string; + readonly AUTH_JWKS: string; + readonly AUTH_PRIVATE_KEY: string; readonly GOOGLE_CLIENT_ID: string; readonly GOOGLE_CLIENT_SECRET: string; readonly IDENTITY_BROKER_KEYS: string; diff --git a/convex/auth.config.ts b/convex/auth.config.ts index 3d666f3..b9142f4 100644 --- a/convex/auth.config.ts +++ b/convex/auth.config.ts @@ -1,5 +1,18 @@ import { authConfig } from "@samebase/alchemy-convex/state/auth.config"; import { env } from "./_generated/server"; -// Verifies the read tokens of `reader:authorize`. -export default authConfig(env.CONVEX_CLOUD_URL); +// Two issuers. The deployment's own key signs the read tokens of `reader:authorize`, and the auth +// component signs the sessions of the console for CONVEX_SITE_URL. convex/console.ts accepts only +// the second, and `reader:repository` accepts only the first. +export default { + providers: [ + ...authConfig(env.CONVEX_CLOUD_URL).providers, + { + type: "customJwt" as const, + applicationID: "convex", + issuer: env.CONVEX_SITE_URL, + jwks: `${env.CONVEX_SITE_URL}/auth/.well-known/jwks.json`, + algorithm: "RS256" as const, + }, + ], +}; diff --git a/convex/auth.ts b/convex/auth.ts new file mode 100644 index 0000000..e038c8d --- /dev/null +++ b/convex/auth.ts @@ -0,0 +1,99 @@ +import { setupConvexAuth } from "@convex-dev/auth/server"; +import { createFunctionHandle } from "convex/server"; +import { type Infer, v } from "convex/values"; +import { components, internal } from "./_generated/api"; +import { env, internalMutation, mutation } from "./_generated/server"; + +const { literal, number, object, string, union } = v; + +const auth = setupConvexAuth({ component: components.auth }); +export const { signOut, refreshSession } = auth; + +const PROVIDER = "password"; + +const vTokens = object({ + accessToken: string(), + accessTokenExpiresAt: number(), + refreshToken: string(), + refreshTokenExpiresAt: number(), + userId: string(), +}); + +/** The form of an email in the table `users`. */ +export const normalizeEmail = (email: string) => email.trim().toLowerCase(); + +/** +The core calls this the first time a user signs in. The password check has already found the user, +so this links the core account to it and creates nothing. +*/ +export const linkExistingUser = internalMutation({ + args: { + provider: object({ + name: literal(PROVIDER), + accountId: string(), + profile: object({ userId: v.id("users") }), + }), + }, + returns: v.id("users"), + handler: async (_ctx, args) => args.provider.profile.userId, +}); + +/** +Signs in to an existing account. There is no sign-up: `authAdmin` creates accounts. A wrong password +returns an error result instead of throwing, so the password component keeps the attempt in its +per-user rate limit. +*/ +export const signInWithPassword = mutation({ + args: { email: string(), password: string() }, + returns: union( + object({ status: literal("complete"), tokens: vTokens }), + object({ + status: literal("error"), + userError: object({ error: union(literal("INVALID_CREDENTIALS"), literal("RATE_LIMITED")) }), + }), + ), + handler: async (ctx, args) => { + const user = await ctx.db + .query("users") + .withIndex("email", (q) => q.eq("email", normalizeEmail(args.email))) + .unique(); + if (user === null) { + return { status: "error" as const, userError: { error: "INVALID_CREDENTIALS" as const } }; + } + const verification = await ctx.runMutation(components.authPassword.public.verifyPassword, { + userId: user._id, + password: args.password, + }); + if (!verification.success) { + return { + status: "error" as const, + userError: { + error: + verification.userError.error === "RATE_LIMITED" + ? ("RATE_LIMITED" as const) + : ("INVALID_CREDENTIALS" as const), + }, + }; + } + const claims = { + providerName: PROVIDER, + providerAccountId: user._id, + profile: { userId: user._id }, + }; + const issuer = env.CONVEX_SITE_URL; + const linkedUserId = await ctx.runQuery(components.auth.public.getUserIdByAccount, { + provider: PROVIDER, + providerAccountId: user._id, + }); + // Annotated: the type of `internal` contains this module, so TypeScript cannot infer it. + const tokens: Infer = + linkedUserId === null + ? await ctx.runMutation(components.auth.public.signUp, { + claims, + createUserHandle: await createFunctionHandle(internal.auth.linkExistingUser), + issuer, + }) + : await ctx.runMutation(components.auth.public.signIn, { claims, issuer }); + return { status: "complete" as const, tokens }; + }, +}); diff --git a/convex/authAdmin.ts b/convex/authAdmin.ts new file mode 100644 index 0000000..a8efc5b --- /dev/null +++ b/convex/authAdmin.ts @@ -0,0 +1,32 @@ +import { ConvexError, v } from "convex/values"; +import { components } from "./_generated/api"; +import { internalMutation } from "./_generated/server"; +import { normalizeEmail } from "./auth"; + +/** +Creates an account of the console, or sets the password of one. The function is internal, because +the console has no sign-up: only a member of the Convex team can run it, from the Functions page of +the dashboard. Run it there and not in a terminal, so that the password stays out of the shell's +history. +*/ +export const createOrUpdatePasswordAccount = internalMutation({ + args: { email: v.string(), password: v.string() }, + returns: v.object({ created: v.boolean(), email: v.string() }), + handler: async (ctx, args) => { + const email = normalizeEmail(args.email); + const existing = await ctx.db + .query("users") + .withIndex("email", (q) => q.eq("email", email)) + .unique(); + const userId = existing?._id ?? (await ctx.db.insert("users", { email })); + const result = await ctx.runMutation(components.authPassword.public.setPassword, { + userId, + password: args.password, + }); + if (!result.success) { + // A throw also takes back the new row. The code names the rule, such as PASSWORD_TOO_SHORT. + throw new ConvexError(result.userError.error); + } + return { created: existing === null, email }; + }, +}); diff --git a/convex/broker.ts b/convex/broker.ts new file mode 100644 index 0000000..2a24559 --- /dev/null +++ b/convex/broker.ts @@ -0,0 +1,13 @@ +import { defineIdentityBroker } from "@samebase/identity-broker"; +import { components } from "./_generated/api"; +import { env } from "./_generated/server"; +import { connectors } from "./connectors"; + +export const broker = defineIdentityBroker({ + component: components.identityBroker, + // Host-only by default: the deployment's own convex.site URL. A custom domain changes the issuer + // that every consuming app names, so ISSUER is set before the first app registers. + issuer: env.ISSUER ?? env.CONVEX_SITE_URL, + keys: () => env.IDENTITY_BROKER_KEYS, + connectors, +}); diff --git a/convex/console.ts b/convex/console.ts new file mode 100644 index 0000000..11fa5f1 --- /dev/null +++ b/convex/console.ts @@ -0,0 +1,79 @@ +import { ConvexError, v } from "convex/values"; +import { components } from "./_generated/api"; +import { env, query, type QueryCtx } from "./_generated/server"; + +/** +Every read of the console needs a session. A read token of `reader:authorize` is an identity too, for +one repository, so the issuer decides: a session has the issuer of the auth component. +*/ +async function requireSession(ctx: QueryCtx) { + const identity = await ctx.auth.getUserIdentity(); + if (identity === null || identity.issuer !== env.CONVEX_SITE_URL) { + throw new ConvexError("A session is required."); + } +} + +/** The repository of a stack: `owner/name`, also for a stack in a folder of it. */ +const repositoryOf = (stack: string) => stack.split("/").slice(0, 2).join("/"); + +/** +The stacks of one repository, redacted. `reader.repository` is the read that Samebase serves: secrets +are removed before the reply leaves the component. +*/ +const readRepository = (ctx: QueryCtx, repository: string) => + ctx.runQuery(components.alchemyState.reader.repository, { repository }); + +/** Every stack of the team with a summary of its stages. A stack with no run record has no stages. */ +export const stacks = query({ + args: {}, + handler: async (ctx) => { + await requireSession(ctx); + const names = await ctx.runQuery(components.alchemyState.state.stacks, {}); + const replies = await Promise.all( + [...new Set(names.map(repositoryOf))].map((repository) => readRepository(ctx, repository)), + ); + const found = new Map(replies.flatMap((reply) => reply.stacks).map((s) => [s.name, s])); + return names.map((name) => ({ + name, + repository: repositoryOf(name), + stages: (found.get(name)?.stages ?? []).map((stage) => ({ + name: stage.name, + record: stage.record, + resources: stage.resources.length, + })), + })); + }, +}); + +/** One stack with its stages, resources, and outputs. Null for a stack with no run record. */ +export const stack = query({ + args: { name: v.string() }, + handler: async (ctx, args) => { + await requireSession(ctx); + const reply = await readRepository(ctx, repositoryOf(args.name)); + return reply.stacks.find((stack) => stack.name === args.name) ?? null; + }, +}); + +/** The apps of the hub with their clients. The hash of a client secret stays on the server. */ +export const hub = query({ + args: {}, + handler: async (ctx) => { + await requireSession(ctx); + const apps = await ctx.runQuery(components.identityBroker.apps.list, {}); + return await Promise.all( + apps.map(async (app) => ({ + ...app, + clients: ( + await ctx.runQuery(components.identityBroker.clients.listByApp, { appId: app.appId }) + ).map(({ clientId, clientName, deploymentType, redirectUri, lastSignInAt }) => ({ + clientId, + clientName, + deploymentType, + redirectUri, + lastSignInAt, + })), + })), + ); + }, +}); diff --git a/convex/convex.config.ts b/convex/convex.config.ts index 3bf80a4..4cd9df3 100644 --- a/convex/convex.config.ts +++ b/convex/convex.config.ts @@ -1,4 +1,7 @@ +import auth from "@convex-dev/auth/convex.config"; +import password from "@convex-dev/auth/components/password/convex.config"; import alchemyState from "@samebase/alchemy-convex/state/convex.config"; +import hosting from "@samebase/convex-hosting/convex.config"; import identityBroker from "@samebase/identity-broker/convex.config"; import { defineApp } from "convex/server"; import { v } from "convex/values"; @@ -10,6 +13,9 @@ const app = defineApp({ env: { /** The key set and the pairwise salt: `npx identity-broker keys`. */ IDENTITY_BROKER_KEYS: v.string(), + /** The session keys of the console: scripts/ensure-convex-auth.ts creates them once. */ + AUTH_PRIVATE_KEY: v.string(), + AUTH_JWKS: v.string(), /** The issuer URL, which the stack sets. Without it, the deployment's own convex.site URL. */ ISSUER: v.optional(v.string()), /** @@ -31,5 +37,13 @@ const app = defineApp({ app.use(identityBroker); // Without a name, so that this base serves the rows that the seed of the store wrote. app.use(alchemyState); +// The console of this base: its accounts, and the site that convex/http.ts serves. The core serves +// its key set under /auth, apart from the key set of the hub. +app.use(auth, { + httpPrefix: "/auth", + env: { AUTH_PRIVATE_KEY: app.env.AUTH_PRIVATE_KEY, AUTH_JWKS: app.env.AUTH_JWKS }, +}); +app.use(password); +app.use(hosting); export default app; diff --git a/convex/http.ts b/convex/http.ts index 92c86c2..be37e08 100644 --- a/convex/http.ts +++ b/convex/http.ts @@ -1,19 +1,23 @@ -import { defineIdentityBroker } from "@samebase/identity-broker"; +import { routeAll } from "@samebase/convex-hosting"; +// Type only, nothing is bundled: the server build imported below. +import type {} from "@samebase/convex-hosting-tanstack-start/server-build"; import { httpRouter } from "convex/server"; +import { versionId } from "../.convex-hosting/version.js"; +import server from "../dist/server/server.js"; import { components } from "./_generated/api"; -import { env } from "./_generated/server"; -import { connectors } from "./connectors"; - -export const broker = defineIdentityBroker({ - component: components.identityBroker, - // Host-only by default: the deployment's own convex.site URL. A custom domain changes the issuer - // that every consuming app names, so ISSUER is set before the first app registers. - issuer: env.ISSUER ?? env.CONVEX_SITE_URL, - keys: () => env.IDENTITY_BROKER_KEYS, - connectors, -}); +import { broker } from "./broker"; const http = httpRouter(); broker.addHttpRoutes(http); +// Every other path, as a Cloudflare Worker with static assets: a file of the build, else the page +// that src/server.ts renders. Convex picks an exact path, then the longest prefix, so the routes of +// the hub above and the /auth prefix of the Convex Auth component win over "/". A page of the site +// cannot use those paths. `pnpm run deploy` writes the build and .convex-hosting/version.js. +const site = routeAll(http, components.hosting, versionId, server); +// Exact routes for the three session routes of src/server.ts: the /auth prefix would take them. +for (const path of ["/auth/signin", "/auth/refresh", "/auth/signout"]) { + http.route({ path, method: "POST", handler: site }); +} + export default http; diff --git a/convex/identityBroker.ts b/convex/identityBroker.ts index ee16359..f97f1ce 100644 --- a/convex/identityBroker.ts +++ b/convex/identityBroker.ts @@ -1,4 +1,4 @@ -import { broker } from "./http"; +import { broker } from "./broker"; // Administration for `npx convex run identityBroker:`: // createApp '{"name":"Bristol","firstParty":false}', for an app that is not the team's own diff --git a/convex/schema.ts b/convex/schema.ts new file mode 100644 index 0000000..90b9e6f --- /dev/null +++ b/convex/schema.ts @@ -0,0 +1,7 @@ +import { defineSchema, defineTable } from "convex/server"; +import { v } from "convex/values"; + +export default defineSchema({ + /** The accounts of the console. Only `authAdmin:createOrUpdatePasswordAccount` writes them. */ + users: defineTable({ email: v.string() }).index("email", ["email"]), +}); diff --git a/package.json b/package.json index f6f5faf..68d6da6 100644 --- a/package.json +++ b/package.json @@ -3,22 +3,40 @@ "private": true, "type": "module", "scripts": { - "dev": "convex dev", - "deploy": "node ./scripts/check-keys.ts && convex deploy --yes", + "dev": "convex dev --start \"vp dev\"", + "deploy": "node ./scripts/check-keys.ts && convex-hosting deploy --build \"node ./scripts/ensure-convex-auth.ts && vp build\" --dist dist/client --html-handling drop-trailing-slash", + "deploy:dev": "convex-hosting deploy --dev --build \"node ./scripts/ensure-convex-auth.ts && vp build\" --dist dist/client --html-handling drop-trailing-slash", "keys:init": "node ./scripts/init-keys.ts", "check": "vp fmt --check && vp lint && pnpm run typecheck", - "typecheck": "tsc --project convex/tsconfig.json && tsc --project tsconfig.node.json", + "typecheck": "tsc --project convex/tsconfig.json && tsc --project tsconfig.node.json && tsc --project tsconfig.app.json", "format": "vp fmt", "lint": "vp lint" }, "dependencies": { + "@convex-dev/auth": "2.0.0-beta.0", + "@convex-dev/react-query": "^0.1.0", "@samebase/alchemy-convex": "0.15.0", + "@samebase/convex-auth-tanstack-start": "^0.1.1", + "@samebase/convex-hosting": "^0.14.0", + "@samebase/convex-hosting-tanstack-start": "^0.11.0", "@samebase/identity-broker": "0.8.0", - "convex": "1.48.0" + "@tailwindcss/vite": "^4.3.3", + "@tanstack/react-query": "^5.104.5", + "@tanstack/react-router": "^1.170.45", + "@tanstack/react-router-ssr-query": "^1.167.3", + "@tanstack/react-start": "^1.169.3", + "convex": "1.48.0", + "react": "^19.3.1", + "react-dom": "^19.3.1", + "tailwindcss": "^4.3.3" }, "devDependencies": { "@effect/platform-node": "4.0.5", + "@tanstack/router-plugin": "^1.168.47", "@types/node": "24.19.2", + "@types/react": "^19.3.0", + "@types/react-dom": "^19.3.0", + "@vitejs/plugin-react": "^6.1.2", "alchemy": "2.0.0-beta.84", "effect": "4.0.5", "typescript": "7.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a8e8625..04b3530 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -187,29 +187,83 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + vite: npm:@voidzero-dev/vite-plus-core@1.3.0 + importers: .: dependencies: + '@convex-dev/auth': + specifier: 2.0.0-beta.0 + version: 2.0.0-beta.0(convex@1.48.0(react@19.3.1))(react@19.3.1)(typescript@7.0.2)(zod@4.6.7) + '@convex-dev/react-query': + specifier: ^0.1.0 + version: 0.1.0(@tanstack/react-query@5.104.5(@types/react@19.3.0)(react@19.3.1))(convex@1.48.0(react@19.3.1)) '@samebase/alchemy-convex': specifier: 0.15.0 - version: 0.15.0(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(alchemy@2.0.0-beta.84(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))(effect@4.0.5)(ws@8.22.0))(convex@1.48.0)(effect@4.0.5) + version: 0.15.0(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(alchemy@2.0.0-beta.84(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(@types/node@24.19.2)(@types/react@19.3.0)(effect@4.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(ws@8.22.0))(convex@1.48.0(react@19.3.1))(effect@4.0.5) + '@samebase/convex-auth-tanstack-start': + specifier: ^0.1.1 + version: 0.1.1(@convex-dev/auth@2.0.0-beta.0(convex@1.48.0(react@19.3.1))(react@19.3.1)(typescript@7.0.2)(zod@4.6.7))(@convex-dev/react-query@0.1.0(@tanstack/react-query@5.104.5(@types/react@19.3.0)(react@19.3.1))(convex@1.48.0(react@19.3.1)))(@tanstack/react-router@1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@tanstack/react-start@1.169.4(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1))(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(convex@1.48.0(react@19.3.1))(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@samebase/convex-hosting': + specifier: ^0.14.0 + version: 0.14.0(convex@1.48.0(react@19.3.1)) + '@samebase/convex-hosting-tanstack-start': + specifier: ^0.11.0 + version: 0.11.0(@samebase/convex-hosting@0.14.0(convex@1.48.0(react@19.3.1)))(@tanstack/react-start@1.169.4(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1))(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(react-dom@19.3.1(react@19.3.1))(react@19.3.1) '@samebase/identity-broker': specifier: 0.8.0 - version: 0.8.0(convex@1.48.0) + version: 0.8.0(convex@1.48.0(react@19.3.1)) + '@tailwindcss/vite': + specifier: ^4.3.3 + version: 4.3.3(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)) + '@tanstack/react-query': + specifier: ^5.104.5 + version: 5.104.5(@types/react@19.3.0)(react@19.3.1) + '@tanstack/react-router': + specifier: ^1.170.45 + version: 1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/react-router-ssr-query': + specifier: ^1.167.3 + version: 1.167.3(@tanstack/query-core@5.104.5)(@tanstack/react-query@5.104.5(@types/react@19.3.0)(react@19.3.1))(@tanstack/react-router@1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@tanstack/router-core@1.171.39)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/react-start': + specifier: ^1.169.3 + version: 1.169.4(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1) convex: specifier: 1.48.0 - version: 1.48.0 + version: 1.48.0(react@19.3.1) + react: + specifier: ^19.3.1 + version: 19.3.1 + react-dom: + specifier: ^19.3.1 + version: 19.3.1(react@19.3.1) + tailwindcss: + specifier: ^4.3.3 + version: 4.3.3 devDependencies: '@effect/platform-node': specifier: 4.0.5 version: 4.0.5(effect@4.0.5)(redis@6.3.0) + '@tanstack/router-plugin': + specifier: ^1.168.47 + version: 1.168.48(@tanstack/react-router@1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1) '@types/node': specifier: 24.19.2 version: 24.19.2 + '@types/react': + specifier: ^19.3.0 + version: 19.3.0 + '@types/react-dom': + specifier: ^19.3.0 + version: 19.3.0(@types/react@19.3.0) + '@vitejs/plugin-react': + specifier: ^6.1.2 + version: 6.1.2(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)) alchemy: specifier: 2.0.0-beta.84 - version: 2.0.0-beta.84(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))(effect@4.0.5)(ws@8.22.0) + version: 2.0.0-beta.84(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(@types/node@24.19.2)(@types/react@19.3.0)(effect@4.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(ws@8.22.0) effect: specifier: 4.0.5 version: 4.0.5 @@ -218,7 +272,7 @@ importers: version: 7.0.2 vite-plus: specifier: 1.3.0 - version: 1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1) + version: 1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1) packages: @@ -241,20 +295,115 @@ packages: resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.29.7': resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.10': + resolution: {integrity: sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.9': + resolution: {integrity: sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/runtime@7.29.10': resolution: {integrity: sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==} engines: {node: '>=6.9.0'} + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.10': + resolution: {integrity: sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + '@blazediff/core@1.10.0': resolution: {integrity: sha512-AOQff0zgR7cGsZL+4E7hVkmujoPUpm0J9xzWGWZj5wCjd3gmxESXAPfKyuzs93VdpQNFhHlBhfOjrcZ+XTERtQ==} + '@convex-dev/auth@2.0.0-beta.0': + resolution: {integrity: sha512-GNIYITbRvLg8Ev5YW3j/rJ71Dft/fGYO5kkTJigVwuYCcn3WOeVY9+1IpKDntzMOZou1uDZwlPnR0BcWZWGaKg==} + hasBin: true + peerDependencies: + '@convex-dev/resend': ^0.2.8 + convex: ^1.46.0 + next: ^16.0.0 + react: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@convex-dev/resend': + optional: true + next: + optional: true + react: + optional: true + + '@convex-dev/batch-worker@0.3.6': + resolution: {integrity: sha512-tR+9DaHR3jG3oqkIFX0ok/6944h7UHEQgT6HTmiuxU+lERYuYMsxA2IWwFD5yTFbCpO3YJhqXU4QdGY90sgUqQ==} + peerDependencies: + convex: ^1.43.0 + '@convex-dev/platform@0.1.11': resolution: {integrity: sha512-qdX+tYjNhNpEeLIiUhKDQQwdvUJDB529TrfJ9dAIclzLOW7DW1ozgIcyB2nl/MhlhBOUlHLY3wZ1xkjafrJO+Q==} + '@convex-dev/rate-limiter@0.3.2': + resolution: {integrity: sha512-+oBPsBfFbzdxiF/9XaaTQmVnvDlvEfg/c69/v8LxTbw4VLuiflIKlfnPQL8OS0azXQQ11hcPWHmU8ytFmHKDXA==} + peerDependencies: + convex: ^1.24.8 + react: ^18.2.0 || ^19.0.0 + peerDependenciesMeta: + react: + optional: true + + '@convex-dev/react-query@0.1.0': + resolution: {integrity: sha512-ULmBZCtAQDUePdBhUv7hj1Yy4QiCelhi6uEIOtMpjW8db6W9CFKvQwLt9heLngccFyMFfAZdOfSrT+cP4AH0Jw==} + peerDependencies: + '@tanstack/react-query': ^5.0.0 + convex: ^1.29.3 + '@effect/platform-node-shared@4.0.5': resolution: {integrity: sha512-a8rCdEkfZBGe9C6bsIjxVZuRp73svIyK5IHwHdDAVsvZXjrbkxusfI+rZ8WlX31RP1mKizwI/E72GQTNfdMWHw==} engines: {node: '>=18.0.0'} @@ -424,6 +573,15 @@ packages: cpu: [x64] os: [win32] + '@hexagon/base64@1.1.28': + resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -434,6 +592,25 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@levischuck/tiny-cbor@0.2.11': + resolution: {integrity: sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==} + + '@oozcitak/dom@2.0.2': + resolution: {integrity: sha512-GjpKhkSYC3Mj4+lfwEyI1dqnsKTgwGy48ytZEhm4A/xnH/8z9M3ZVXKr/YGQi3uCLs1AEBS+x5T2JPiueEDW8w==} + engines: {node: '>=20.0'} + + '@oozcitak/infra@2.0.2': + resolution: {integrity: sha512-2g+E7hoE2dgCz/APPOEK5s3rMhJvNxSMBrP+U+j1OWsIbtSpWxxlUjq1lU8RIsFJNYv7NMlnVsCuHcUzJW+8vA==} + engines: {node: '>=20.0'} + + '@oozcitak/url@3.0.0': + resolution: {integrity: sha512-ZKfET8Ak1wsLAiLWNfFkZc/BraDccuTJKR6svTYc7sVjbR+Iu0vtXdiDMY4o6jaFl5TW2TlS7jbLl4VovtAJWQ==} + engines: {node: '>=20.0'} + + '@oozcitak/util@10.0.0': + resolution: {integrity: sha512-hAX0pT/73190NLqBPPWSdBVGtbY6VOhWYK3qqHqtXQ1gK7kS2yz4+ivsN07hpJ6I3aeMtKP6J6npsEKOAzuTLA==} + engines: {node: '>=20.0'} + '@oxc-project/runtime@0.154.0': resolution: {integrity: sha512-cBQNGoh659BNgvA8OC/e4BNDtFkv03dJaYdkp2adgOQNtISNAPQ+nB4S8XvWtNk7Xl+0g+7aa+iRGR25Xycd1Q==} engines: {node: ^20.19.0 || >=22.12.0} @@ -722,6 +899,65 @@ packages: resolution: {integrity: sha512-G2xbfWTrbqYRhR/vfeKNMQf/sS3/ti0iKJAAkRxHuXWZH/hne/dyIb9QKk5LuR6cJLARxsL6FMoAYmfspd74MQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@peculiar/asn1-android@2.11.0': + resolution: {integrity: sha512-llW/qjavL+tOxt5i9whUv4wsbsLpUwI6k/DrvKsdA/H7A/TB/6CosMFgvei28fcJ8ncD0c5lig1oBBlo4KGMCw==} + engines: {node: '>=14'} + + '@peculiar/asn1-asym-key@2.11.0': + resolution: {integrity: sha512-r2957WdSZle/Zt4t9og7OMQYXNJ9/3ANXVtFwLCDJuHORlBZ4AFmDt1Qee0CzyTbHQg4ZZApBGEz5/6cFsyCRg==} + engines: {node: '>=14'} + + '@peculiar/asn1-cms@2.11.0': + resolution: {integrity: sha512-SlAiDoT/Cd8qaNmbTt78gqyaEvu2fQd6ML6KWJkdjXGrgDKnHHrusVkfQUelkfinL2p665IIADb0JBixtT8W1g==} + engines: {node: '>=14'} + + '@peculiar/asn1-csr@2.11.0': + resolution: {integrity: sha512-M/ED0yJ05qMK+UADPKnIa8vhAeewOJALSxTAZB7RQ/batRHhIJZkwznCcWAbFO5saHJ1yEQ+m4lncEcG9RnQSg==} + engines: {node: '>=14'} + + '@peculiar/asn1-ecc@2.11.0': + resolution: {integrity: sha512-jj1alGEKev7/un+cI+exyVK9m31lmP7cCBMCZuCb0wkFQH2zmKmJzNiG4wqXFNzlcP8timHLnzf3lV3OxBpb/Q==} + engines: {node: '>=14'} + + '@peculiar/asn1-pfx@2.11.0': + resolution: {integrity: sha512-ykSAWRu8KkmzU8LRpk9ZQC3zuLmBEtoSMjIv9XHVamD5W7amqreV5wttKqnvtjWOzzSJQxA/HVT8/tHwpEEGSQ==} + engines: {node: '>=14'} + + '@peculiar/asn1-pkcs8@2.11.0': + resolution: {integrity: sha512-lragjkjQGnQ5luxC+sxoAfAO/jBiQ7hOEGlDKJUk7MC5zY3AzjB2DU0GyPUH1Sswdv10t7DurY0zylOYMLb88w==} + engines: {node: '>=14'} + + '@peculiar/asn1-pkcs9@2.11.0': + resolution: {integrity: sha512-gDdFjpqV0weJjgNUvueUVf4D8uVbpq+VbG0TsxLAY2QGljAkJyL9qwQ7avol9j0jaYSJ7Ey7v7RZp0M3GTcQSA==} + engines: {node: '>=14'} + + '@peculiar/asn1-rsa@2.11.0': + resolution: {integrity: sha512-S2sBJmbfI09Kzdt9cEhE6pDNjHpVTkURs+811+PxS8AvsTLxC4woMNRhxHYaIbClkkNfAVt0tZxJdINVfUmzuA==} + engines: {node: '>=14'} + + '@peculiar/asn1-schema@2.11.0': + resolution: {integrity: sha512-8xh4avo53/vXO6UEv9yaoJ83hY581geaLTygf61NPIXP5AeIZCPjJhpTaYU23IZkG+NpLN/C9FYzWp7hphIT9A==} + engines: {node: '>=14'} + + '@peculiar/asn1-x509-attr@2.11.0': + resolution: {integrity: sha512-Fgvnd9REmLxEj/4cbDP54dNUNUXkzUksXLqEHqs1mHBuSRjSTCUSPM/WQIZYSvrdG7ND9CX1AQtPoIBekhgQSA==} + engines: {node: '>=14'} + + '@peculiar/asn1-x509-post-quantum@2.11.0': + resolution: {integrity: sha512-K6EnquTX3xJ2G+uLPFH0jVkh7W8y6eTzoCxvSoXAj0sWS5uvVB2PEvpBPdzY4+ytaedUM3x9ZVgX0AZKb316ew==} + engines: {node: '>=14'} + + '@peculiar/asn1-x509@2.11.0': + resolution: {integrity: sha512-J1sHAwGNlk+8J+FeR1eLVc6Gq0T9f9ITc3HWyPYgJraoW6U8AJuQiWVJ3SCEpltfTdpOY7fHdHT5oKAsbK/jww==} + engines: {node: '>=14'} + + '@peculiar/utils@2.0.3': + resolution: {integrity: sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==} + + '@peculiar/x509@2.2.0': + resolution: {integrity: sha512-adpW58ySPQMOUPv8pTKT3RIyCFqfUFt8X05ukPdtkQToXDVr8dMtxuenik1yx8tNFTbpApWsM/Hi5SzlIx48+Q==} + engines: {node: '>=20.0.0'} + '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} @@ -870,12 +1106,302 @@ packages: convex: ^1.48.0 effect: ^4.0.5 + '@samebase/convex-auth-tanstack-start@0.1.1': + resolution: {integrity: sha512-99ANO+Gkj9tYECMI8BP3jMlhvggJ9Q483BiE2Jt6xGxa5h+T0CS/tIKN8RgKaz6j+zAyByomUSfJ5t/Rcu2dLw==} + engines: {node: '>=22'} + peerDependencies: + '@convex-dev/auth': 2.0.0-beta.0 + '@convex-dev/react-query': ^0.1.0 + '@tanstack/react-router': ^1.170.38 + '@tanstack/react-start': ^1.168.60 + convex: ^1.46.0 + react: ^19.2.0 + react-dom: ^19.2.0 + vite: '*' + peerDependenciesMeta: + '@convex-dev/react-query': + optional: true + + '@samebase/convex-hosting-tanstack-start@0.11.0': + resolution: {integrity: sha512-wYoFoTelwAOCFTgoSrmih6d6h4AOUQa8ZozAtbxc6aszijhue/Xhmhgov6BWCr7YJ7m/7pUVB5ogQSsqRNo2XQ==} + engines: {node: '>=22'} + peerDependencies: + '@samebase/convex-hosting': '>=0.13.0' + '@tanstack/react-start': ^1.168.60 + react: ^19.2.0 + react-dom: ^19.2.0 + vite: '*' + peerDependenciesMeta: + '@samebase/convex-hosting': + optional: true + + '@samebase/convex-hosting@0.14.0': + resolution: {integrity: sha512-1tD9684ieAC8wAMrW4pZz5JGJ+PtY+/plYEIsraAX1CR1PAUqA7H94iC+YVKjCdHBLk+h4bjCWDXqwO7MPuvHQ==} + engines: {node: '>=22'} + hasBin: true + peerDependencies: + convex: ^1.46.0 + '@samebase/identity-broker@0.8.0': resolution: {integrity: sha512-prYpngzUhXrfowJfRYX16TQWo1J+NZlhMXHRXkj9ardBFbkcAyAFhNLBn+ZTCqP7ycyRRx2Lmwmy6L/rDleCHA==} hasBin: true peerDependencies: convex: ^1.47.0 + '@simplewebauthn/browser@14.0.0': + resolution: {integrity: sha512-1odWVqeEBTl7lJ9zMKLEsmTlnyrDO5iRcTvfMKKk1WThUnp/i8JJdffdj2icP+tty159s4PgwE3BiMoEW9NFow==} + + '@simplewebauthn/server@14.0.3': + resolution: {integrity: sha512-D39/0fiDiYmGV+nraY9s63D1Ho2AX/waMLy22/9gUadTUuvbAnstfb4bpbHYbwZuV5ZLDYN1SmzDKuiHzKAA4Q==} + engines: {node: '>=20.0.0'} + + '@tailwindcss/node@4.3.3': + resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} + + '@tailwindcss/oxide-android-arm64@4.3.3': + resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.3.3': + resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.3.3': + resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} + engines: {node: '>= 20'} + + '@tailwindcss/vite@4.3.3': + resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + + '@tanstack/history@1.162.5': + resolution: {integrity: sha512-w1+YvwmTkwt5n8yUqEH3IWZ9DsmorCZW/EQ3KYHnqEgIkOZpH54NvW6/Epq3Dzb8H0ifIeYX8PExvrNLIH5FIA==} + engines: {node: '>=20.19'} + + '@tanstack/query-core@5.104.5': + resolution: {integrity: sha512-Q94gI8Opd+CbdVNOdj8ZCyV8WqLYitrDq1t96Xc8WZT6lY0r5iRnJLXYDxMex7EEf2v+mXvn4FcjaBKSxXZQ9A==} + + '@tanstack/react-query@5.104.5': + resolution: {integrity: sha512-RORgFe052U+93weaNuqg7qHq7vNVNzXN/VrXqD4bbAuQCWUqOl2lV5Ui9flWk5CVvMyL/Bh27QWhzwH0aaOx9g==} + peerDependencies: + '@types/react': ^18 || ^19 + react: ^18 || ^19 + peerDependenciesMeta: + '@types/react': + optional: true + + '@tanstack/react-router-ssr-query@1.167.3': + resolution: {integrity: sha512-HA0pxuPuhU+rwoe+z1Xcbytuoo6ZbcROpgNgNSm38s3/hGLmgzOBLzDg+Vyx6ex26QilnPbZ+5Ypet5mImm9bQ==} + engines: {node: '>=20.19'} + peerDependencies: + '@tanstack/query-core': '>=5.102.0' + '@tanstack/react-query': '>=5.102.0' + '@tanstack/react-router': '>=1.170.33' + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-router@1.170.46': + resolution: {integrity: sha512-ez1iNIhsPjGlaDHg3BXWs67EWVIYzB2tbopEHYDESdkO7owgkGb5de52+5Kv2v1fxdkggcNzo35bdk4arTVGQw==} + engines: {node: '>=20.19'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-start-client@1.168.44': + resolution: {integrity: sha512-WvrYhQ0EgwYpxnP9mFCCo+jctqXV3qq8GfIyiSGLiZzz4GDyw+GuQ2lyA3BTN64wbNNNVeMll+9PV5OlGYi2/w==} + engines: {node: '>=22.12.0'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-start-rsc@0.1.65': + resolution: {integrity: sha512-5MmzmQoADjMA/d2XawkwKAkgBaQFrfifw/wn8qwCaLIntGYd2jkrCga/KdQW2xdjBu9IoP98WFhZilm7DfI/4g==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@rspack/core': '>=2.0.0-0' + '@vitejs/plugin-rsc': '>=0.5.30' + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + react-server-dom-rspack: '>=0.0.2' + peerDependenciesMeta: + '@rspack/core': + optional: true + '@vitejs/plugin-rsc': + optional: true + react-server-dom-rspack: + optional: true + + '@tanstack/react-start-server@1.167.52': + resolution: {integrity: sha512-131olF9oWx1CqZg8JYmIJbLNKqS/vN3UbYuc9a++pRtvfY67tpPmPzuYj4OXSxRAYalGW3f1yYlFozxqE1LE7w==} + engines: {node: '>=22.12.0'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-start@1.169.4': + resolution: {integrity: sha512-+DmlNPeQ1rsvo025I79GrlNgDm+zVCVAGg9gMIGmAevK2TJRMpKahgEKZZ1j4VSxDxjfTpkfLyuXiUxxjMJCaw==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@rsbuild/core': ^2.0.0 + '@vitejs/plugin-rsc': '*' + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + '@vitejs/plugin-rsc': + optional: true + + '@tanstack/react-store@0.11.2': + resolution: {integrity: sha512-oj5O5DmiMWE+ih+SioX2ayC1kbK7d3fpLx0B75fPJr9nY3zU+hoW010yr64qXsY/9fyiLVE2bn5mGNV3owm8RQ==} + 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.171.39': + resolution: {integrity: sha512-qUhoJ0meuSUqGYQbHbcJYdASr06YtK+bulbj6vtrhKYFkLgkSsZ6tXmMyym7sFxiSJSPYgasgozrL01LyyR/6A==} + engines: {node: '>=20.19'} + + '@tanstack/router-generator@1.167.46': + resolution: {integrity: sha512-JSailAThcqPvqBzE3+MhNh6zQyZM2IdmIsHOxZgAc061Lh++SZqamNm/Whe7QNXWK5sLP4E0J1F8AI0hP8wTSw==} + engines: {node: '>=20.19'} + + '@tanstack/router-plugin@1.168.48': + resolution: {integrity: sha512-oLDEZO/vhvF5JLrQ6qMNYcCjMMhlHA0Byx6ZXl9AHJ6qVLRxUeCU41vlZQ4buisONY2p0Zl9O09/qwLiVrIBCQ==} + engines: {node: '>=20.19'} + peerDependencies: + '@rsbuild/core': '>=1.0.2 || ^2.0.0' + '@tanstack/react-router': ^1.170.46 + vite-plugin-solid: ^2.11.10 || ^3.0.0-0 + webpack: '>=5.92.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + '@tanstack/react-router': + optional: true + vite-plugin-solid: + optional: true + webpack: + optional: true + + '@tanstack/router-ssr-query-core@1.169.3': + resolution: {integrity: sha512-0EE3mFa753mExMJEfWhZMi+EKViSLmZHoiYADZJzr5+2S/T4T12soHg8fMn67jCvDwL2dpd1mE7aL/XXzDPfhA==} + engines: {node: '>=20.19'} + peerDependencies: + '@tanstack/query-core': '>=5.102.0' + '@tanstack/router-core': '>=1.171.28' + + '@tanstack/router-utils@1.162.4': + resolution: {integrity: sha512-3TSH3rwAQTqQOtTBF8IXMFXmGNJWnjwIm+l87uguyC/of0pSRKcU9GJrozaf0fY9it8dLQvUZJA2MOlfqbW1sA==} + engines: {node: '>=20.19'} + + '@tanstack/start-client-core@1.170.39': + resolution: {integrity: sha512-G0VJbZFf9/dYomQjZkWapaTjkjEI4vbk1jnxhhVtQ3nTRb3sIRc196j+S+qZcySfEV5W9TJHu4KatjSzjZZQwQ==} + engines: {node: '>=22.12.0'} + + '@tanstack/start-fn-stubs@1.162.0': + resolution: {integrity: sha512-QWfUZ3Yo923tdQn38LyKMU8rcTw69zc+T4dAvgTWV4O56SqFRsGfS0lSWIMhJRwXIx/bvdi7nTUBDdZtTHtpTQ==} + engines: {node: '>=22.12.0'} + + '@tanstack/start-plugin-core@1.171.55': + resolution: {integrity: sha512-8FjTuuxIE8MNJoveXahZPBCfEpm8p9tMFyWTvbllfqlysdhry34rw/nCwULfcVwTG39ezXEu/RYE83NSV+miog==} + engines: {node: '>=22.12.0'} + peerDependencies: + '@rsbuild/core': ^2.0.0 + peerDependenciesMeta: + '@rsbuild/core': + optional: true + + '@tanstack/start-server-core@1.169.45': + resolution: {integrity: sha512-fKySLUGIy7aVYR6ZRgjC19TQdsZ+q/54M9hVfHrJQQVpM/T5qq5djZ3gsqhugmrWP+gyd9qpa9D6cxRtR6CJvg==} + engines: {node: '>=22.12.0'} + + '@tanstack/start-storage-context@1.167.41': + resolution: {integrity: sha512-MY+Z4cZBPbH7hjORcROMX7K3kV1X25ArFKmRbks+EukPP9UVwCXbZFVzYkTt1u0AHthvQTcpa4J9B9i0o6fEnA==} + engines: {node: '>=22.12.0'} + + '@tanstack/store@0.11.2': + resolution: {integrity: sha512-sJ4mjol8uQsHV0gOJzzjwXfh2Fwm+Sz0+8deqiTm4jGbMdjzNSW+xZCFm0kUa870uhd8yi+DpKnZb5Kc4apa0Q==} + + '@tanstack/virtual-file-routes@1.162.0': + resolution: {integrity: sha512-uhOeFyxLcU41HzvrxsGpiWdcMbScY1EDgbZ5K7DVRMYInbLYWAC0EA/kx9wXAoSM8q82bUG2hRl8+EAjE6XAbA==} + engines: {node: '>=20.19'} + '@testing-library/dom@10.4.2': resolution: {integrity: sha512-yzr2S9HyAIdhz2/6qHgbs665Q7PKVcDF05vsOlHPxG1mo36gKVesdYVeDLnXgfjJ03CrKRk08knc6+E/9m8v2Q==} engines: {node: '>=18'} @@ -901,6 +1427,14 @@ packages: '@types/node@24.19.2': resolution: {integrity: sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==} + '@types/react-dom@19.3.0': + resolution: {integrity: sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==} + peerDependencies: + '@types/react': ^19.3.0 + + '@types/react@19.3.0': + resolution: {integrity: sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==} + '@types/ws@8.18.2': resolution: {integrity: sha512-67MQl+fpWKVTT1NYdnmo3U4sc/xPo/zQBncVnI74qmQa0z/b+1g6iYqNmGCPbxO+zz2aklb08a0oHfegiVd0/w==} @@ -1024,6 +1558,22 @@ packages: cpu: [x64] os: [win32] + '@vitejs/plugin-react@6.1.2': + resolution: {integrity: sha512-fhJNGUdscQa4HkI0xFxwonWyhnVReCPDbXI7FH7jmzpnVCrFQI7PRrhWecO263610vOrs9tr2Y4xcf8uAdFxbw==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + oxc-transform-react: ^0.152.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + oxc-transform-react: + optional: true + '@vitest/browser-preview@5.0.5': resolution: {integrity: sha512-ViNg4UlomGSJHtnnr7Txm+55P7/aAMMoS+1WYnWjp5w5tzf7YEUAICcs2sb1uMovEnC8el/8zUfkWZ8+7fPCKA==} peerDependencies: @@ -1038,12 +1588,9 @@ packages: resolution: {integrity: sha512-xLL3lkDegJZw+MGoGaCCsFayDZthGgpAtr3Vziyfc4p7xH89K7KRPcRBBh/kEYm0Aqkt5DtTmkYpBtRV/FrHZg==} peerDependencies: msw: ^2.4.9 || ^3.0.0 - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: optional: true - vite: - optional: true '@vitest/pretty-format@5.0.5': resolution: {integrity: sha512-24sSdIlMA9DVPXnYiB9siwU0bTd887Y9jX3+vabztCSsvHwo7ipvJ/a2L3Rljw8+2rK1f5fCj3h5U9I/Jsqgbw==} @@ -1261,7 +1808,6 @@ packages: '@effect/platform-node': ^4.0.5 '@effect/vitest': ^4.0.5 effect: ^4.0.5 - vite: ^8.0.7 ws: ^8.21.0 peerDependenciesMeta: '@alchemy.run/frontend-frameworks': @@ -1272,8 +1818,6 @@ packages: optional: true '@effect/vitest': optional: true - vite: - optional: true ws: optional: true @@ -1281,17 +1825,51 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + ansi-regex@6.4.0: + resolution: {integrity: sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==} + engines: {node: '>=12'} + ansi-styles@5.2.0: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} + ansis@4.4.0: + resolution: {integrity: sha512-9k3v7xcHwgdO/DruxGIg4HtjvlAZlcnsX/mzqUb1t3NkYnl9kK2UJ+Gq0io+vQf7iT//BD/HB/NBkUR1LWxoeA==} + engines: {node: '>=14'} + + argon2id-wasm@0.0.0-alpha.2: + resolution: {integrity: sha512-Bxa3aVWUbpg/hKTyHdjeLT68mJXNLftm1W3tXVXu/X83vmpTJ3zzgOhNMzu33Th2iNDxMU1kU4/MEGgW5udMgQ==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + asn1js@3.1.0: + resolution: {integrity: sha512-HWYi1THkOqguCiO+vwj09ZkQFD2kKEsejYHAYCtX0D80WVdoDnvRc9IukXX/jeb0T9NRWJnRtqwdbHltnFjwXA==} + engines: {node: '>=12.0.0'} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + babel-dead-code-elimination@1.0.12: + resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==} + + baseline-browser-mapping@2.11.31: + resolution: {integrity: sha512-b0k7wXlWjpuL/Uxb/pYlpjY0ej5BjAmurtPUk3eRGuloI4yjK32m8TiKUQ81l1ptcLjKS/KH2+uqIolZti1x4Q==} + engines: {node: '>=6.0.0'} + hasBin: true + + browserslist@4.29.4: + resolution: {integrity: sha512-2TcbbiwXEq+N0kD36tykpCfyyQigUXmuwNQbnPp4Xk4PX9JOqVIKjJlIDjpH7uY6tmRGoAd+apeT1p60T8wsdA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + caniuse-lite@1.0.30001819: + resolution: {integrity: sha512-LFUqIIAwpzsIuevnKnsR9qnStBcgzPShTX61lBwN9uFkkf8o8zLiebEjbW8AYtZiF+1YKDWfdt/pWDtMuG8Xwg==} + capnweb@0.12.0: resolution: {integrity: sha512-jgZ/LMtMVTi+RVlooIslH78Gg23XbDTdvcLghWx3oz17D6u5GuJARt+uhZk/wcTo+f81eeabfnow4d3zLBj+JQ==} @@ -1299,13 +1877,51 @@ packages: resolution: {integrity: sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==} engines: {node: '>=18'} + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chokidar@5.0.0: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-spinners@3.4.0: + resolution: {integrity: sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==} + engines: {node: '>=18.20'} + + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} + engines: {node: '>=20'} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + convex-helpers@0.1.129: + resolution: {integrity: sha512-8QJLbym0fKsf3tYcF2ZTX37NeYt/BkOFBjBwB2LR1fXUAajeYaTLV11gi/0IVOU/jCdH2j/VseHhHid1qQcqFw==} + hasBin: true + peerDependencies: + '@standard-schema/spec': ^1.0.0 + convex: ^1.46.0 + hono: ^4.0.5 + react: ^17.0.2 || ^18.0.0 || ^19.0.0 + typescript: ^5.5 || ^6.0.0 || ^7.0.0 + zod: ^3.25.0 || ^4.0.0 + peerDependenciesMeta: + '@standard-schema/spec': + optional: true + hono: + optional: true + react: + optional: true + typescript: + optional: true + zod: + optional: true + convex@1.48.0: resolution: {integrity: sha512-M9jEgTvCN8ziP/VgQQUH+j0ijM7g+NmQd8tFlvETK8/HMC/aaqHZwcu4hBO30X5DV2VIyYK4mOoLQGIb1766ew==} engines: {node: '>=20.0.0', npm: '>=7.0.0'} @@ -1325,6 +1941,25 @@ packages: react: optional: true + cookie-es@3.1.1: + resolution: {integrity: sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==} + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -1333,12 +1968,23 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + diff@9.0.0: + resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==} + engines: {node: '>=0.3.1'} + dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} effect@4.0.5: resolution: {integrity: sha512-BY4/28NlpOd99yzmV741xbVGmp+1U7tks4oB7F/Png64bTa5tm5eCA6W0RiXsnuLDDoJpjfVSo4Dnq4BZb/89Q==} + electron-to-chromium@1.5.463: + resolution: {integrity: sha512-nVWNU6ltFjopvOdD44J4zoBkgO0M+WZiFKKFV7EjebOH9z0KNphk6bCEjplXtJofL21ARIuuwWOCsFkBVklm6w==} + + enhanced-resolve@5.26.0: + resolution: {integrity: sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==} + engines: {node: '>=10.13.0'} + es-module-lexer@2.3.2: resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} @@ -1347,6 +1993,10 @@ packages: engines: {node: '>=18'} hasBin: true + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -1354,6 +2004,9 @@ packages: resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} engines: {node: '>=12.0.0'} + exsolve@1.1.3: + resolution: {integrity: sha512-kuzL9zherLQoqDeQaS55AiiIg1kb4KYXaSusTtgZTPlvKP2gGCI82LNmBNh5RjDVUXIcmgx+/Mx7vPwRzBbhJA==} + fdir@6.5.0: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} @@ -1363,6 +2016,9 @@ packages: picomatch: optional: true + fetchdts@0.2.0: + resolution: {integrity: sha512-PJb4ZTGT2/wK78RmVrxZITStWabhZlKBsL52VOgq+c7clEkdHdEB+0rtzrXCbZJqeYJj+IwNWYqB5/G6vouA6A==} + fflate@0.8.3: resolution: {integrity: sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==} @@ -1374,42 +2030,127 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - jose@6.2.13: + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-east-asian-width@1.7.0: + resolution: {integrity: sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==} + engines: {node: '>=18'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + ignore@7.0.12: + resolution: {integrity: sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==} + engines: {node: '>= 4'} + + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + isbot@5.2.2: + resolution: {integrity: sha512-iQcBXcd+Rv/pkubRyGh2utW2j1oPG5hZY6TUhVPpqK4G+o3IbxpJNx04hgksjc/N7GK5pEorUxDeg31cFgEk/w==} + engines: {node: '>=18'} + + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + jose@5.10.0: + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} + + jose@6.2.13: resolution: {integrity: sha512-7TIg10ZE1x82YediN+lcrPNvGMKge9yFHQD+Qho/b8y2adfugU3AsvvHfxV0fzyFllT6l9xCjf4RWY9g/Z9PJQ==} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + lightningcss-android-arm64@1.33.0: resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + lightningcss-darwin-arm64@1.33.0: resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + lightningcss-darwin-x64@1.33.0: resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + lightningcss-freebsd-x64@1.33.0: resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + lightningcss-linux-arm-gnueabihf@1.33.0: resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + lightningcss-linux-arm64-gnu@1.33.0: resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} engines: {node: '>= 12.0.0'} @@ -1417,6 +2158,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + lightningcss-linux-arm64-musl@1.33.0: resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} engines: {node: '>= 12.0.0'} @@ -1424,6 +2172,13 @@ packages: os: [linux] libc: [musl] + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + lightningcss-linux-x64-gnu@1.33.0: resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} engines: {node: '>= 12.0.0'} @@ -1431,6 +2186,13 @@ packages: os: [linux] libc: [glibc] + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + lightningcss-linux-x64-musl@1.33.0: resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} engines: {node: '>= 12.0.0'} @@ -1438,38 +2200,80 @@ packages: os: [linux] libc: [musl] + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + lightningcss-win32-arm64-msvc@1.33.0: resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + lightningcss-win32-x64-msvc@1.33.0: resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + lightningcss@1.33.0: resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} engines: {node: '>= 12.0.0'} + log-symbols@7.0.1: + resolution: {integrity: sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==} + engines: {node: '>=18'} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magic-string@1.4.3: resolution: {integrity: sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==} + mime@4.1.1: + resolution: {integrity: sha512-YAApRsTpM2+gnUFHhRNGfkX8NK0V5xj1nyQLufGlwEI+eX4xRsTcel2IXDuMEGSGjBvzykNW4VuoEACgwYe7BQ==} + engines: {node: '>=16'} + hasBin: true + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nanoid@3.3.20: resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + node-releases@2.0.60: + resolution: {integrity: sha512-OmO8+GM1JUZqXET720VrJCwkjUCXmCMQm0Z3UDDRbfNLHS4NEAvY60j5jiFv0tkKw2PNNlqOLhahVmwJIOLDIQ==} + engines: {node: '>=18'} + oauth4webapi@3.8.8: resolution: {integrity: sha512-8N28E+a/oxfXWBgOMt+ZP/JUf/XR+IFbvkAEPP3gznXOMv9BpAAwiIj0TFNz3tGTPc0ZQ8zmWBNgN1nAys0gng==} @@ -1477,12 +2281,20 @@ packages: resolution: {integrity: sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==} engines: {node: '>=12.20.0'} + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + openapi-fetch@0.17.0: resolution: {integrity: sha512-PsbZR1wAPcG91eEthKhN+Zn92FMHxv+/faECIwjXdxfTODGSGegYv0sc1Olz+HYPvKOuoXfp+0pA2XVt2cI0Ig==} openapi-typescript-helpers@0.1.0: resolution: {integrity: sha512-OKTGPthhivLw/fHz6c3OPtg72vi86qaMlqbJuVJ23qOvQ+53uw1n7HdmkJFibloF7QEjDrDkzJiOJuockM/ljw==} + ora@9.4.1: + resolution: {integrity: sha512-6VlU9MLXbjVQD04AZCMX28hVtA5bUoadvUqO76MUCVA0ilwJbMiHsITRPfyVm6p/BC0Av/BXMujx39WCe1LEqw==} + engines: {node: '>=20'} + oxfmt@0.73.0: resolution: {integrity: sha512-Ke4xbpuzqIBP4bkd48q815RhqWNJqOBzxVA9199M4qcF0y0LtpUv7UTg1dJ5ea6jw0RBUDZvX3qOUMNmmxfxbw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1543,9 +2355,25 @@ packages: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pvtsutils@1.3.6: + resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} + + pvutils@1.2.0: + resolution: {integrity: sha512-BbubeCEyTuQjVMakvJQ/Sxbc93F2pwmbsxONT/ZRrwU7Ua38d8unYTwXpTVLAKJ4BDuH9IGztCjQcd/N/39Dvg==} + engines: {node: '>=16.0.0'} + + react-dom@19.3.1: + resolution: {integrity: sha512-Y0bARz53lhEC1NMCASs0/j+faB/zqt3R8hpvg1e8+61ZVJ4UL0UdC4cBbXfZMcIuhrfgeILTLe+ZeBCavQPtKQ==} + peerDependencies: + react: ^19.3.1 + react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react@19.3.1: + resolution: {integrity: sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==} + engines: {node: '>=0.10.0'} + readdirp@5.1.1: resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==} engines: {node: '>= 20.19.0'} @@ -1554,11 +2382,39 @@ packages: resolution: {integrity: sha512-XFQbPie1lGpKeUZ8ySYY43yLnQy/iIQtHNvIr/1XdaABpb96rUSdm3Mfl+98FEVbv9ZJIzINMno5s0Nh8E5LEw==} engines: {node: '>= 20.0.0'} + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + rolldown@1.2.13: resolution: {integrity: sha512-/5apOkwWxtACcQtZ5WlrAsKS4JwXVThQPJZ3RqIruRY9UG9M8e0VlXN068xum/JRKA4aIUoJ13ghe/kGCvidiQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + scheduler@0.28.0: + resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + seroval-plugins@1.7.1: + resolution: {integrity: sha512-5EiMqQiw2/KqzTCyJNdpMvBFbKlidtcinyRwZg77pW5Z+QllOp2JUkEpTdThkdsEFXsPGf8ofTpu5yC1kXwv0g==} + engines: {node: '>=20'} + peerDependencies: + seroval: ^1.0 + + seroval@1.7.1: + resolution: {integrity: sha512-tSRMcPkD/bu1rmY0/XfFP2zLPD8jXVuzHli6Y2UFi9AiG/d0kOd8LAc/G6NolpW8MA1PtgDUhywKCmerS4E3tg==} + engines: {node: '>=20'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + sirv@3.0.2: resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} engines: {node: '>=18'} @@ -1567,9 +2423,37 @@ packages: resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} engines: {node: '>=0.10.0'} + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + + srvx@1.0.6: + resolution: {integrity: sha512-QeTKgAhk8OSsfeq60bl3wuVs9PmBftzmk7owBInA/F1YQne+TRw0UcPymNpURldAmx8hfmM2PNNGH/zgo3GpLA==} + engines: {node: '>=20.16.0'} + hasBin: true + std-env@4.3.0: resolution: {integrity: sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==} + stdin-discarder@0.3.2: + resolution: {integrity: sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A==} + engines: {node: '>=18'} + + string-width@8.3.0: + resolution: {integrity: sha512-ZbmZM0JCihQN91dWnxoipT2KOEyHqEyfRXUyjuRhW8b/xnqPDoq4gWEVApTVa9db2wN8mmoikgFBbjh71+cGeQ==} + engines: {node: '>=20'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + tailwindcss@4.3.3: + resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + tinybench@6.2.2: resolution: {integrity: sha512-nIZ2N2dFpjBsg2hgitKu7mA+FvsIJuGJOwysRngmVRRmWgR/UyPjwJj8c/fT/dhm8EkHnF5EOogRf+0Z2qrimA==} engines: {node: '>=20.0.0'} @@ -1594,11 +2478,24 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsyringe@4.10.0: + resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==} + engines: {node: '>= 6.0.0'} + typescript@7.0.2: resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} engines: {node: '>=16.20.0'} hasBin: true + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + undici-types@7.24.6: resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} @@ -1606,6 +2503,50 @@ packages: resolution: {integrity: sha512-+fdndUTwBP86cVjihTp21hZHo7d6oj1c/47XPA3lL8mM0XHs+C4EkcjmgRsFnFk2f/UONGDy9ItBItmXsLOQHw==} engines: {node: '>=22.19.0'} + unplugin@3.4.0: + resolution: {integrity: sha512-9skdIFlCsPdFV7wUfZxNsFInlW+7nJmGu2gkTu0OUhF56aXGsHab9x52/QhdJ4lC7ZDPWTxbiC4ANqVlsuaW3w==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@farmfe/core': '*' + '@rsbuild/core': '*' + '@rspack/core': '*' + bun-types-no-globals: '*' + esbuild: '*' + rolldown: '*' + rollup: '*' + unloader: '*' + webpack: '*' + peerDependenciesMeta: + '@farmfe/core': + optional: true + '@rsbuild/core': + optional: true + '@rspack/core': + optional: true + bun-types-no-globals: + optional: true + esbuild: + optional: true + rolldown: + optional: true + rollup: + optional: true + unloader: + optional: true + webpack: + optional: true + + update-browserslist-db@1.3.4: + resolution: {integrity: sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + use-sync-external-store@1.7.0: + resolution: {integrity: sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + vite-plus@1.3.0: resolution: {integrity: sha512-wZGsDeYfPcrCegqgY68pJJHGTpEZdsZvIMH2/mWXkGkBD72UY3M7z24Sv3ZeOL/FrqbbtyqBOfkKO6BvoQ8wMw==} engines: {node: ^22.18.0 || ^24.11.0 || >=26.0.0} @@ -1622,6 +2563,14 @@ packages: playwright: optional: true + vitefu@1.1.3: + resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + vite: + optional: true + vitest@5.0.5: resolution: {integrity: sha512-cPODOMF8YnkiiYtDdHo6n4wWmBrOBBbOIYH2d33M4l3CdNn72h+qMmO6uXffUN6A5AZFXNND/d+krS9mgkXRfg==} engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0} @@ -1663,6 +2612,9 @@ packages: jsdom: optional: true + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + why-is-node-running@3.2.1: resolution: {integrity: sha512-Tb2FUhB4vUsGQlfSquQLYkApkuPAFQXGFzxWKHHumVz2dK+X1RUm/HnID4+TfIGYJ1kTcwOaCk/buYCEJr6YjQ==} engines: {node: '>=20.11'} @@ -1692,11 +2644,22 @@ packages: utf-8-validate: optional: true + xmlbuilder2@4.0.3: + resolution: {integrity: sha512-bx8Q1STctnNaaDymWnkfQLKofs0mGNN7rLLapJlGuV3VlvegD7Ls4ggMjE3aUSWItCCzU0PEv45lI87iSigiCA==} + engines: {node: '>=20.0'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yaml@2.9.1: resolution: {integrity: sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==} engines: {node: '>= 14.6'} hasBin: true + yoctocolors@2.2.0: + resolution: {integrity: sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg==} + engines: {node: '>=18'} + yuku-core@0.19.0: resolution: {integrity: sha512-kYK9e1XdfirNhkipzW0wmMcSWcVF/CWnuugodfVYRCUwvoBefweL9HzB96OiKEhsx78V5WbUxbJqlizMX869Qg==} engines: {node: '>=14.18.0'} @@ -1705,6 +2668,12 @@ packages: resolution: {integrity: sha512-XrBh9ZiQK5mJVRxZBAvD6LwRyAYrK3MFtH3+onyuxFL5hFD44EC3QOmIC1FjTj6H2MMwq46/NAI+NZxLZPZgxg==} engines: {node: '>=14.18.0'} + zod@4.6.6: + resolution: {integrity: sha512-4UmzQUF5fxvfcYHlbjBmejU+w+hbDnWFx4aS8kBx7nPBHcO2SqPbpAG8snbdg+Xse4pRefR98hgjFgIMCI/UhA==} + + zod@4.6.7: + resolution: {integrity: sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==} + snapshots: '@alchemy.run/node-utils@2.0.0-beta.84': @@ -1712,7 +2681,9 @@ snapshots: chokidar: 5.0.0 rolldown: 1.2.13 - '@alchemy.run/sigil@0.1.0-alpha.1': {} + '@alchemy.run/sigil@0.1.0-alpha.1(@types/react@19.3.0)': + optionalDependencies: + '@types/react': 19.3.0 '@babel/code-frame@7.29.7': dependencies: @@ -1720,16 +2691,152 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.10 + '@babel/parser': 7.29.9 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.8': + dependencies: + '@babel/parser': 7.29.9 + '@babel/types': 7.29.8 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.29.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.29.7': {} + '@babel/helper-validator-identifier@7.29.7': {} + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helpers@7.29.10': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + + '@babel/parser@7.29.9': + dependencies: + '@babel/types': 7.29.8 + '@babel/runtime@7.29.10': {} + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.9 + '@babel/types': 7.29.8 + + '@babel/traverse@7.29.10': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.9 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@blazediff/core@1.10.0': {} + '@convex-dev/auth@2.0.0-beta.0(convex@1.48.0(react@19.3.1))(react@19.3.1)(typescript@7.0.2)(zod@4.6.7)': + dependencies: + '@babel/code-frame': 7.29.7 + '@convex-dev/batch-worker': 0.3.6(convex@1.48.0(react@19.3.1))(react@19.3.1)(typescript@7.0.2)(zod@4.6.7) + '@convex-dev/rate-limiter': 0.3.2(convex@1.48.0(react@19.3.1))(react@19.3.1) + '@simplewebauthn/browser': 14.0.0 + '@simplewebauthn/server': 14.0.3 + argon2id-wasm: 0.0.0-alpha.2 + chalk: 5.6.2 + commander: 14.0.3 + convex: 1.48.0(react@19.3.1) + cookie: 1.1.1 + jose: 5.10.0 + ora: 9.4.1 + optionalDependencies: + react: 19.3.1 + transitivePeerDependencies: + - '@standard-schema/spec' + - hono + - typescript + - zod + + '@convex-dev/batch-worker@0.3.6(convex@1.48.0(react@19.3.1))(react@19.3.1)(typescript@7.0.2)(zod@4.6.7)': + dependencies: + convex: 1.48.0(react@19.3.1) + convex-helpers: 0.1.129(convex@1.48.0(react@19.3.1))(react@19.3.1)(typescript@7.0.2)(zod@4.6.7) + transitivePeerDependencies: + - '@standard-schema/spec' + - hono + - react + - typescript + - zod + '@convex-dev/platform@0.1.11': dependencies: openapi-fetch: 0.17.0 + '@convex-dev/rate-limiter@0.3.2(convex@1.48.0(react@19.3.1))(react@19.3.1)': + dependencies: + convex: 1.48.0(react@19.3.1) + optionalDependencies: + react: 19.3.1 + + '@convex-dev/react-query@0.1.0(@tanstack/react-query@5.104.5(@types/react@19.3.0)(react@19.3.1))(convex@1.48.0(react@19.3.1))': + dependencies: + '@tanstack/react-query': 5.104.5(@types/react@19.3.0)(react@19.3.1) + convex: 1.48.0(react@19.3.1) + '@effect/platform-node-shared@4.0.5(effect@4.0.5)': dependencies: '@types/ws': 8.18.2 @@ -1827,6 +2934,18 @@ snapshots: '@esbuild/win32-x64@0.27.0': optional: true + '@hexagon/base64@1.1.28': {} + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.6.0': {} @@ -1836,6 +2955,25 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.6.0 + '@levischuck/tiny-cbor@0.2.11': {} + + '@oozcitak/dom@2.0.2': + dependencies: + '@oozcitak/infra': 2.0.2 + '@oozcitak/url': 3.0.0 + '@oozcitak/util': 10.0.0 + + '@oozcitak/infra@2.0.2': + dependencies: + '@oozcitak/util': 10.0.0 + + '@oozcitak/url@3.0.0': + dependencies: + '@oozcitak/infra': 2.0.2 + '@oozcitak/util': 10.0.0 + + '@oozcitak/util@10.0.0': {} + '@oxc-project/runtime@0.154.0': {} '@oxc-project/types@0.153.0': {} @@ -1976,6 +3114,122 @@ snapshots: '@oxlint/plugins@1.88.0': {} + '@peculiar/asn1-android@2.11.0': + dependencies: + '@peculiar/asn1-schema': 2.11.0 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-asym-key@2.11.0': + dependencies: + '@peculiar/asn1-pkcs8': 2.11.0 + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/asn1-x509': 2.11.0 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-cms@2.11.0': + dependencies: + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/asn1-x509': 2.11.0 + '@peculiar/asn1-x509-attr': 2.11.0 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-csr@2.11.0': + dependencies: + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/asn1-x509': 2.11.0 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-ecc@2.11.0': + dependencies: + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/asn1-x509': 2.11.0 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-pfx@2.11.0': + dependencies: + '@peculiar/asn1-cms': 2.11.0 + '@peculiar/asn1-pkcs8': 2.11.0 + '@peculiar/asn1-rsa': 2.11.0 + '@peculiar/asn1-schema': 2.11.0 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-pkcs8@2.11.0': + dependencies: + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/asn1-x509': 2.11.0 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-pkcs9@2.11.0': + dependencies: + '@peculiar/asn1-cms': 2.11.0 + '@peculiar/asn1-pfx': 2.11.0 + '@peculiar/asn1-pkcs8': 2.11.0 + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/asn1-x509': 2.11.0 + '@peculiar/asn1-x509-attr': 2.11.0 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-rsa@2.11.0': + dependencies: + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/asn1-x509': 2.11.0 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-schema@2.11.0': + dependencies: + '@peculiar/utils': 2.0.3 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-x509-attr@2.11.0': + dependencies: + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/asn1-x509': 2.11.0 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-x509-post-quantum@2.11.0': + dependencies: + '@peculiar/asn1-asym-key': 2.11.0 + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/asn1-x509': 2.11.0 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/asn1-x509@2.11.0': + dependencies: + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/utils': 2.0.3 + asn1js: 3.1.0 + tslib: 2.8.1 + + '@peculiar/utils@2.0.3': + dependencies: + tslib: 2.8.1 + + '@peculiar/x509@2.2.0': + dependencies: + '@peculiar/asn1-cms': 2.11.0 + '@peculiar/asn1-csr': 2.11.0 + '@peculiar/asn1-ecc': 2.11.0 + '@peculiar/asn1-pkcs9': 2.11.0 + '@peculiar/asn1-rsa': 2.11.0 + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/asn1-x509': 2.11.0 + '@peculiar/asn1-x509-post-quantum': 2.11.0 + pvtsutils: 1.3.6 + tslib: 2.8.1 + tsyringe: 4.10.0 + '@polka/url@1.0.0-next.29': {} '@redis/bloom@6.3.0(@redis/client@6.3.0)': @@ -2043,21 +3297,443 @@ snapshots: '@rolldown/pluginutils@1.0.1': {} - '@samebase/alchemy-convex@0.15.0(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(alchemy@2.0.0-beta.84(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))(effect@4.0.5)(ws@8.22.0))(convex@1.48.0)(effect@4.0.5)': + '@samebase/alchemy-convex@0.15.0(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(alchemy@2.0.0-beta.84(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(@types/node@24.19.2)(@types/react@19.3.0)(effect@4.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(ws@8.22.0))(convex@1.48.0(react@19.3.1))(effect@4.0.5)': dependencies: '@convex-dev/platform': 0.1.11 '@effect/platform-node': 4.0.5(effect@4.0.5)(redis@6.3.0) - alchemy: 2.0.0-beta.84(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))(effect@4.0.5)(ws@8.22.0) - convex: 1.48.0 + alchemy: 2.0.0-beta.84(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(@types/node@24.19.2)(@types/react@19.3.0)(effect@4.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(ws@8.22.0) + convex: 1.48.0(react@19.3.1) effect: 4.0.5 - '@samebase/identity-broker@0.8.0(convex@1.48.0)': + '@samebase/convex-auth-tanstack-start@0.1.1(@convex-dev/auth@2.0.0-beta.0(convex@1.48.0(react@19.3.1))(react@19.3.1)(typescript@7.0.2)(zod@4.6.7))(@convex-dev/react-query@0.1.0(@tanstack/react-query@5.104.5(@types/react@19.3.0)(react@19.3.1))(convex@1.48.0(react@19.3.1)))(@tanstack/react-router@1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@tanstack/react-start@1.169.4(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1))(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(convex@1.48.0(react@19.3.1))(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@convex-dev/auth': 2.0.0-beta.0(convex@1.48.0(react@19.3.1))(react@19.3.1)(typescript@7.0.2)(zod@4.6.7) + '@tanstack/react-router': 1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/react-start': 1.169.4(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1) + convex: 1.48.0(react@19.3.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' + optionalDependencies: + '@convex-dev/react-query': 0.1.0(@tanstack/react-query@5.104.5(@types/react@19.3.0)(react@19.3.1))(convex@1.48.0(react@19.3.1)) + + '@samebase/convex-hosting-tanstack-start@0.11.0(@samebase/convex-hosting@0.14.0(convex@1.48.0(react@19.3.1)))(@tanstack/react-start@1.169.4(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1))(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@tanstack/react-start': 1.169.4(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' + optionalDependencies: + '@samebase/convex-hosting': 0.14.0(convex@1.48.0(react@19.3.1)) + + '@samebase/convex-hosting@0.14.0(convex@1.48.0(react@19.3.1))': dependencies: - convex: 1.48.0 + convex: 1.48.0(react@19.3.1) + ignore: 7.0.12 + mime: 4.1.1 + zod: 4.6.6 + + '@samebase/identity-broker@0.8.0(convex@1.48.0(react@19.3.1))': + dependencies: + convex: 1.48.0(react@19.3.1) jose: 6.2.13 oauth4webapi: 3.8.8 - '@testing-library/dom@10.4.2': + '@simplewebauthn/browser@14.0.0': {} + + '@simplewebauthn/server@14.0.3': + dependencies: + '@hexagon/base64': 1.1.28 + '@levischuck/tiny-cbor': 0.2.11 + '@peculiar/asn1-android': 2.11.0 + '@peculiar/asn1-ecc': 2.11.0 + '@peculiar/asn1-rsa': 2.11.0 + '@peculiar/asn1-schema': 2.11.0 + '@peculiar/asn1-x509': 2.11.0 + '@peculiar/asn1-x509-post-quantum': 2.11.0 + '@peculiar/x509': 2.2.0 + reflect-metadata: 0.2.2 + + '@tailwindcss/node@4.3.3': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.26.0 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.2 + tailwindcss: 4.3.3 + + '@tailwindcss/oxide-android-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide@4.3.3': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-x64': 4.3.3 + '@tailwindcss/oxide-freebsd-x64': 4.3.3 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-x64-musl': 4.3.3 + '@tailwindcss/oxide-wasm32-wasi': 4.3.3 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 + + '@tailwindcss/vite@4.3.3(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))': + dependencies: + '@tailwindcss/node': 4.3.3 + '@tailwindcss/oxide': 4.3.3 + tailwindcss: 4.3.3 + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' + + '@tanstack/history@1.162.5': {} + + '@tanstack/query-core@5.104.5': {} + + '@tanstack/react-query@5.104.5(@types/react@19.3.0)(react@19.3.1)': + dependencies: + '@tanstack/query-core': 5.104.5 + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + '@tanstack/react-router-ssr-query@1.167.3(@tanstack/query-core@5.104.5)(@tanstack/react-query@5.104.5(@types/react@19.3.0)(react@19.3.1))(@tanstack/react-router@1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@tanstack/router-core@1.171.39)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@tanstack/query-core': 5.104.5 + '@tanstack/react-query': 5.104.5(@types/react@19.3.0)(react@19.3.1) + '@tanstack/react-router': 1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/router-ssr-query-core': 1.169.3(@tanstack/query-core@5.104.5)(@tanstack/router-core@1.171.39) + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + transitivePeerDependencies: + - '@tanstack/router-core' + + '@tanstack/react-router@1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@tanstack/history': 1.162.5 + '@tanstack/react-store': 0.11.2(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/router-core': 1.171.39 + isbot: 5.2.2 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + + '@tanstack/react-start-client@1.168.44(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@tanstack/react-router': 1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/router-core': 1.171.39 + '@tanstack/start-client-core': 1.170.39 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + + '@tanstack/react-start-rsc@0.1.65(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1)': + dependencies: + '@tanstack/react-router': 1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/router-core': 1.171.39 + '@tanstack/router-utils': 1.162.4 + '@tanstack/start-client-core': 1.170.39 + '@tanstack/start-fn-stubs': 1.162.0 + '@tanstack/start-plugin-core': 1.171.55(@tanstack/react-router@1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1) + '@tanstack/start-storage-context': 1.167.41 + pathe: 2.0.3 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@farmfe/core' + - '@rsbuild/core' + - '@types/node' + - '@typescript/native-preview' + - '@vitejs/devtools' + - '@volar/typescript' + - '@vue/language-core' + - bun-types-no-globals + - esbuild + - jiti + - less + - publint + - rolldown + - rollup + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - unloader + - unplugin-unused + - unrun + - vite-plugin-solid + - vue-tsc + - webpack + - yaml + + '@tanstack/react-start-server@1.167.52(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@tanstack/react-router': 1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/router-core': 1.171.39 + '@tanstack/start-server-core': 1.169.45 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + + '@tanstack/react-start@1.169.4(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1)': + dependencies: + '@tanstack/react-router': 1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/react-start-client': 1.168.44(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/react-start-rsc': 0.1.65(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1) + '@tanstack/react-start-server': 1.167.52(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + '@tanstack/router-utils': 1.162.4 + '@tanstack/start-client-core': 1.170.39 + '@tanstack/start-plugin-core': 1.171.55(@tanstack/react-router@1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1) + '@tanstack/start-server-core': 1.169.45 + pathe: 2.0.3 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@farmfe/core' + - '@rspack/core' + - '@types/node' + - '@typescript/native-preview' + - '@vitejs/devtools' + - '@volar/typescript' + - '@vue/language-core' + - bun-types-no-globals + - esbuild + - jiti + - less + - publint + - react-server-dom-rspack + - rolldown + - rollup + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - unloader + - unplugin-unused + - unrun + - vite-plugin-solid + - vue-tsc + - webpack + - yaml + + '@tanstack/react-store@0.11.2(react-dom@19.3.1(react@19.3.1))(react@19.3.1)': + dependencies: + '@tanstack/store': 0.11.2 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + use-sync-external-store: 1.7.0(react@19.3.1) + + '@tanstack/router-core@1.171.39': + dependencies: + '@tanstack/history': 1.162.5 + cookie-es: 3.1.1 + seroval: 1.7.1 + seroval-plugins: 1.7.1(seroval@1.7.1) + + '@tanstack/router-generator@1.167.46': + dependencies: + '@babel/types': 7.29.8 + '@tanstack/router-core': 1.171.39 + '@tanstack/router-utils': 1.162.4 + '@tanstack/virtual-file-routes': 1.162.0 + jiti: 2.7.0 + magic-string: 0.30.21 + prettier: 3.9.10 + zod: 4.6.7 + transitivePeerDependencies: + - supports-color + + '@tanstack/router-plugin@1.168.48(@tanstack/react-router@1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1)': + dependencies: + '@babel/core': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + '@tanstack/router-core': 1.171.39 + '@tanstack/router-generator': 1.167.46 + '@tanstack/router-utils': 1.162.4 + chokidar: 5.0.0 + unplugin: 3.4.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1) + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' + zod: 4.6.7 + optionalDependencies: + '@tanstack/react-router': 1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@farmfe/core' + - '@rspack/core' + - '@types/node' + - '@typescript/native-preview' + - '@vitejs/devtools' + - '@volar/typescript' + - '@vue/language-core' + - bun-types-no-globals + - esbuild + - jiti + - less + - publint + - rolldown + - rollup + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - unloader + - unplugin-unused + - unrun + - vue-tsc + - yaml + + '@tanstack/router-ssr-query-core@1.169.3(@tanstack/query-core@5.104.5)(@tanstack/router-core@1.171.39)': + dependencies: + '@tanstack/query-core': 5.104.5 + '@tanstack/router-core': 1.171.39 + + '@tanstack/router-utils@1.162.4': + dependencies: + '@babel/generator': 7.29.8 + '@babel/parser': 7.29.9 + '@babel/types': 7.29.8 + ansis: 4.4.0 + babel-dead-code-elimination: 1.0.12 + diff: 9.0.0 + pathe: 2.0.3 + tinyglobby: 0.2.17 + transitivePeerDependencies: + - supports-color + + '@tanstack/start-client-core@1.170.39': + dependencies: + '@tanstack/router-core': 1.171.39 + '@tanstack/start-fn-stubs': 1.162.0 + '@tanstack/start-storage-context': 1.167.41 + seroval: 1.7.1 + + '@tanstack/start-fn-stubs@1.162.0': {} + + '@tanstack/start-plugin-core@1.171.55(@tanstack/react-router@1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/core': 7.29.7 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + '@tanstack/router-core': 1.171.39 + '@tanstack/router-generator': 1.167.46 + '@tanstack/router-plugin': 1.168.48(@tanstack/react-router@1.170.46(react-dom@19.3.1(react@19.3.1))(react@19.3.1))(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1) + '@tanstack/router-utils': 1.162.4 + '@tanstack/start-server-core': 1.169.45 + exsolve: 1.1.3 + lightningcss: 1.33.0 + pathe: 2.0.3 + picomatch: 4.0.7 + seroval: 1.7.1 + source-map: 0.7.6 + srvx: 1.0.6 + tinyglobby: 0.2.17 + ufo: 1.6.4 + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' + vitefu: 1.1.3(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)) + xmlbuilder2: 4.0.3 + zod: 4.6.7 + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@farmfe/core' + - '@rspack/core' + - '@tanstack/react-router' + - '@types/node' + - '@typescript/native-preview' + - '@vitejs/devtools' + - '@volar/typescript' + - '@vue/language-core' + - bun-types-no-globals + - esbuild + - jiti + - less + - publint + - rolldown + - rollup + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - unloader + - unplugin-unused + - unrun + - vite-plugin-solid + - vue-tsc + - webpack + - yaml + + '@tanstack/start-server-core@1.169.45': + dependencies: + '@tanstack/history': 1.162.5 + '@tanstack/router-core': 1.171.39 + '@tanstack/start-client-core': 1.170.39 + '@tanstack/start-storage-context': 1.167.41 + cookie-es: 3.1.1 + fetchdts: 0.2.0 + seroval: 1.7.1 + + '@tanstack/start-storage-context@1.167.41': + dependencies: + '@tanstack/router-core': 1.171.39 + + '@tanstack/store@0.11.2': {} + + '@tanstack/virtual-file-routes@1.162.0': {} + + '@testing-library/dom@10.4.2': dependencies: '@babel/code-frame': 7.29.7 '@babel/runtime': 7.29.10 @@ -2087,6 +3763,14 @@ snapshots: dependencies: undici-types: 7.24.6 + '@types/react-dom@19.3.0(@types/react@19.3.0)': + dependencies: + '@types/react': 19.3.0 + + '@types/react@19.3.0': + dependencies: + csstype: 3.2.3 + '@types/ws@8.18.2': dependencies: '@types/node': 24.19.2 @@ -2151,44 +3835,110 @@ snapshots: '@typescript/typescript-win32-x64@7.0.2': optional: true - '@vitest/browser-preview@5.0.5(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))(vitest@5.0.5)': + '@vitejs/plugin-react@6.1.2(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))': + dependencies: + '@rolldown/pluginutils': 1.0.1 + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' + + '@vitest/browser-preview@5.0.5(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(vitest@5.0.5)(yaml@2.9.1)': dependencies: '@testing-library/dom': 10.4.2 '@testing-library/user-event': 14.6.8(@testing-library/dom@10.4.2) - '@vitest/browser': 5.0.5(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))(vitest@5.0.5) - vitest: 5.0.5(@types/node@24.19.2)(@vitest/browser-preview@5.0.5)(@vitest/ui@5.0.5)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)) + '@vitest/browser': 5.0.5(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(vitest@5.0.5)(yaml@2.9.1) + vitest: 5.0.5(@types/node@24.19.2)(@vitest/browser-preview@5.0.5)(@vitest/ui@5.0.5)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1) transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@types/node' + - '@typescript/native-preview' + - '@vitejs/devtools' + - '@volar/typescript' + - '@vue/language-core' - bufferutil + - esbuild + - jiti + - less - msw + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - unrun - utf-8-validate - - vite + - vue-tsc + - yaml - '@vitest/browser@5.0.5(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))(vitest@5.0.5)': + '@vitest/browser@5.0.5(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(vitest@5.0.5)(yaml@2.9.1)': dependencies: '@blazediff/core': 1.10.0 - '@vitest/mocker': 5.0.5(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)) + '@vitest/mocker': 5.0.5(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1) '@vitest/ui': 5.0.5(vitest@5.0.5) '@vitest/utils': 5.0.5 magic-string: 1.4.3 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.2.0 - vitest: 5.0.5(@types/node@24.19.2)(@vitest/browser-preview@5.0.5)(@vitest/ui@5.0.5)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)) + vitest: 5.0.5(@types/node@24.19.2)(@vitest/browser-preview@5.0.5)(@vitest/ui@5.0.5)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1) ws: 8.22.0 transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@types/node' + - '@typescript/native-preview' + - '@vitejs/devtools' + - '@volar/typescript' + - '@vue/language-core' - bufferutil + - esbuild + - jiti + - less - msw + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - unrun - utf-8-validate - - vite + - vue-tsc + - yaml - '@vitest/mocker@5.0.5(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))': + '@vitest/mocker@5.0.5(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)': dependencies: '@jridgewell/trace-mapping': 0.3.31 '@vitest/spy': 5.0.5 estree-walker: 3.0.3 magic-string: 1.4.3 - optionalDependencies: - vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)' + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@types/node' + - '@typescript/native-preview' + - '@vitejs/devtools' + - '@volar/typescript' + - '@vue/language-core' + - esbuild + - jiti + - less + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - vue-tsc + - yaml '@vitest/pretty-format@5.0.5': dependencies: @@ -2211,7 +3961,7 @@ snapshots: pathe: 2.0.3 sirv: 3.0.2 tinyrainbow: 3.2.0 - vitest: 5.0.5(@types/node@24.19.2)(@vitest/browser-preview@5.0.5)(@vitest/ui@5.0.5)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)) + vitest: 5.0.5(@types/node@24.19.2)(@vitest/browser-preview@5.0.5)(@vitest/ui@5.0.5)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1) '@vitest/utils@5.0.5': dependencies: @@ -2219,7 +3969,7 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.2.0 - '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)': + '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)': dependencies: '@oxc-project/runtime': 0.154.0 '@oxc-project/types': 0.154.0 @@ -2238,6 +3988,7 @@ snapshots: '@voidzero-dev/vite-plus-win32-x64-msvc': 1.3.0 esbuild: 0.27.0 fsevents: 2.3.3 + jiti: 2.7.0 typescript: 7.0.2 yaml: 2.9.1 @@ -2303,10 +4054,10 @@ snapshots: '@yuku-toolchain/types@0.19.0': {} - alchemy@2.0.0-beta.84(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))(effect@4.0.5)(ws@8.22.0): + alchemy@2.0.0-beta.84(@effect/platform-node@4.0.5(effect@4.0.5)(redis@6.3.0))(@types/node@24.19.2)(@types/react@19.3.0)(effect@4.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(ws@8.22.0): dependencies: '@alchemy.run/node-utils': 2.0.0-beta.84 - '@alchemy.run/sigil': 0.1.0-alpha.1 + '@alchemy.run/sigil': 0.1.0-alpha.1(@types/react@19.3.0) capnweb: 0.12.0 effect: 4.0.5 fflate: 0.8.3 @@ -2314,52 +4065,146 @@ snapshots: picomatch: 4.0.7 rolldown: 1.2.13 tinyglobby: 0.2.17 + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' yaml: 2.9.1 optionalDependencies: '@effect/platform-node': 4.0.5(effect@4.0.5)(redis@6.3.0) - vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)' ws: 8.22.0 transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@types/node' - '@types/react' + - '@typescript/native-preview' + - '@vitejs/devtools' + - '@volar/typescript' + - '@vue/language-core' + - esbuild + - jiti + - less + - publint - react-devtools-core + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - vue-tsc ansi-regex@5.0.1: {} + ansi-regex@6.4.0: {} + ansi-styles@5.2.0: {} + ansis@4.4.0: {} + + argon2id-wasm@0.0.0-alpha.2: {} + + argparse@2.0.1: {} + aria-query@5.3.0: dependencies: dequal: 2.0.3 + asn1js@3.1.0: + dependencies: + pvtsutils: 1.3.6 + pvutils: 1.2.0 + tslib: 2.8.1 + assertion-error@2.0.1: {} + babel-dead-code-elimination@1.0.12: + dependencies: + '@babel/core': 7.29.7 + '@babel/parser': 7.29.9 + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + baseline-browser-mapping@2.11.31: {} + + browserslist@4.29.4: + dependencies: + baseline-browser-mapping: 2.11.31 + caniuse-lite: 1.0.30001819 + electron-to-chromium: 1.5.463 + node-releases: 2.0.60 + update-browserslist-db: 1.3.4(browserslist@4.29.4) + + caniuse-lite@1.0.30001819: {} + capnweb@0.12.0: {} chai@6.3.0: {} + chalk@5.6.2: {} + chokidar@5.0.0: dependencies: readdirp: 5.1.1 + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@3.4.0: {} + + commander@14.0.3: {} + convert-source-map@2.0.0: {} - convex@1.48.0: + convex-helpers@0.1.129(convex@1.48.0(react@19.3.1))(react@19.3.1)(typescript@7.0.2)(zod@4.6.7): + dependencies: + convex: 1.48.0(react@19.3.1) + optionalDependencies: + react: 19.3.1 + typescript: 7.0.2 + zod: 4.6.7 + + convex@1.48.0(react@19.3.1): dependencies: esbuild: 0.27.0 prettier: 3.9.10 ws: 8.21.0 + optionalDependencies: + react: 19.3.1 transitivePeerDependencies: - bufferutil - utf-8-validate + cookie-es@3.1.1: {} + + cookie@1.1.1: {} + + csstype@3.2.3: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + dequal@2.0.3: {} detect-libc@2.1.2: {} + diff@9.0.0: {} + dom-accessibility-api@0.5.16: {} effect@4.0.5: {} + electron-to-chromium@1.5.463: {} + + enhanced-resolve@5.26.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + es-module-lexer@2.3.2: {} esbuild@0.27.0: @@ -2391,16 +4236,22 @@ snapshots: '@esbuild/win32-ia32': 0.27.0 '@esbuild/win32-x64': 0.27.0 + escalade@3.2.0: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 expect-type@1.4.0: {} + exsolve@1.1.3: {} + fdir@6.5.0(picomatch@4.0.7): optionalDependencies: picomatch: 4.0.7 + fetchdts@0.2.0: {} + fflate@0.8.3: {} flatted@3.4.4: {} @@ -2408,43 +4259,118 @@ snapshots: fsevents@2.3.3: optional: true + gensync@1.0.0-beta.2: {} + + get-east-asian-width@1.7.0: {} + + graceful-fs@4.2.11: {} + + ignore@7.0.12: {} + + is-interactive@2.0.0: {} + + is-unicode-supported@2.1.0: {} + + isbot@5.2.2: {} + + jiti@2.7.0: {} + + jose@5.10.0: {} + jose@6.2.13: {} js-tokens@4.0.0: {} + js-yaml@4.3.2: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json5@2.2.3: {} + + lightningcss-android-arm64@1.32.0: + optional: true + lightningcss-android-arm64@1.33.0: optional: true + lightningcss-darwin-arm64@1.32.0: + optional: true + lightningcss-darwin-arm64@1.33.0: optional: true + lightningcss-darwin-x64@1.32.0: + optional: true + lightningcss-darwin-x64@1.33.0: optional: true + lightningcss-freebsd-x64@1.32.0: + optional: true + lightningcss-freebsd-x64@1.33.0: optional: true + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + lightningcss-linux-arm-gnueabihf@1.33.0: optional: true + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + lightningcss-linux-arm64-gnu@1.33.0: optional: true + lightningcss-linux-arm64-musl@1.32.0: + optional: true + lightningcss-linux-arm64-musl@1.33.0: optional: true + lightningcss-linux-x64-gnu@1.32.0: + optional: true + lightningcss-linux-x64-gnu@1.33.0: optional: true + lightningcss-linux-x64-musl@1.32.0: + optional: true + lightningcss-linux-x64-musl@1.33.0: optional: true + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + lightningcss-win32-arm64-msvc@1.33.0: optional: true + lightningcss-win32-x64-msvc@1.32.0: + optional: true + lightningcss-win32-x64-msvc@1.33.0: optional: true + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + lightningcss@1.33.0: dependencies: detect-libc: 2.1.2 @@ -2461,27 +4387,63 @@ snapshots: lightningcss-win32-arm64-msvc: 1.33.0 lightningcss-win32-x64-msvc: 1.33.0 + log-symbols@7.0.1: + dependencies: + is-unicode-supported: 2.1.0 + yoctocolors: 2.2.0 + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + lz-string@1.5.0: {} + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + magic-string@1.4.3: dependencies: '@jridgewell/sourcemap-codec': 1.6.0 + mime@4.1.1: {} + + mimic-function@5.0.1: {} + mrmime@2.0.1: {} + ms@2.1.3: {} + nanoid@3.3.20: {} + node-releases@2.0.60: {} + oauth4webapi@3.8.8: {} obug@3.0.0: {} + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + openapi-fetch@0.17.0: dependencies: openapi-typescript-helpers: 0.1.0 openapi-typescript-helpers@0.1.0: {} - oxfmt@0.73.0(vite-plus@1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)): + ora@9.4.1: + dependencies: + chalk: 5.6.2 + cli-cursor: 5.0.0 + cli-spinners: 3.4.0 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 7.0.1 + stdin-discarder: 0.3.2 + string-width: 8.3.0 + + oxfmt@0.73.0(vite-plus@1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)): dependencies: tinypool: 2.2.0 optionalDependencies: @@ -2504,7 +4466,7 @@ snapshots: '@oxfmt/binding-win32-arm64-msvc': 0.73.0 '@oxfmt/binding-win32-ia32-msvc': 0.73.0 '@oxfmt/binding-win32-x64-msvc': 0.73.0 - vite-plus: 1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1) + vite-plus: 1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1) oxlint-tsgolint@7.0.2004: optionalDependencies: @@ -2515,7 +4477,7 @@ snapshots: '@oxlint-tsgolint/win32-arm64': 7.0.2004 '@oxlint-tsgolint/win32-x64': 7.0.2004 - oxlint@1.88.0(oxlint-tsgolint@7.0.2004)(vite-plus@1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)): + oxlint@1.88.0(oxlint-tsgolint@7.0.2004)(vite-plus@1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)): optionalDependencies: '@oxlint/binding-android-arm-eabi': 1.88.0 '@oxlint/binding-android-arm64': 1.88.0 @@ -2537,7 +4499,7 @@ snapshots: '@oxlint/binding-win32-ia32-msvc': 1.88.0 '@oxlint/binding-win32-x64-msvc': 1.88.0 oxlint-tsgolint: 7.0.2004 - vite-plus: 1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1) + vite-plus: 1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1) pathe@2.0.3: {} @@ -2561,8 +4523,21 @@ snapshots: ansi-styles: 5.2.0 react-is: 17.0.2 + pvtsutils@1.3.6: + dependencies: + tslib: 2.8.1 + + pvutils@1.2.0: {} + + react-dom@19.3.1(react@19.3.1): + dependencies: + react: 19.3.1 + scheduler: 0.28.0 + react-is@17.0.2: {} + react@19.3.1: {} + readdirp@5.1.1: {} redis@6.3.0: @@ -2576,6 +4551,13 @@ snapshots: - '@node-rs/xxhash' - '@opentelemetry/api' + reflect-metadata@0.2.2: {} + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + rolldown@1.2.13: dependencies: '@oxc-project/types': 0.153.0 @@ -2597,6 +4579,18 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.2.13 '@rolldown/binding-win32-x64-msvc': 1.2.13 + scheduler@0.28.0: {} + + semver@6.3.1: {} + + seroval-plugins@1.7.1(seroval@1.7.1): + dependencies: + seroval: 1.7.1 + + seroval@1.7.1: {} + + signal-exit@4.1.0: {} + sirv@3.0.2: dependencies: '@polka/url': 1.0.0-next.29 @@ -2605,8 +4599,27 @@ snapshots: source-map-js@1.2.2: {} + source-map@0.7.6: {} + + srvx@1.0.6: {} + std-env@4.3.0: {} + stdin-discarder@0.3.2: {} + + string-width@8.3.0: + dependencies: + get-east-asian-width: 1.7.0 + strip-ansi: 7.2.0 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.4.0 + + tailwindcss@4.3.3: {} + + tapable@2.3.3: {} + tinybench@6.2.2: {} tinyexec@1.3.1: {} @@ -2622,6 +4635,14 @@ snapshots: totalist@3.0.1: {} + tslib@1.14.1: {} + + tslib@2.8.1: {} + + tsyringe@4.10.0: + dependencies: + tslib: 1.14.1 + typescript@7.0.2: optionalDependencies: '@typescript/typescript-aix-ppc64': 7.0.2 @@ -2645,26 +4666,69 @@ snapshots: '@typescript/typescript-win32-arm64': 7.0.2 '@typescript/typescript-win32-x64': 7.0.2 + ufo@1.6.4: {} + undici-types@7.24.6: {} undici@8.12.3: {} - vite-plus@1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1): + unplugin@3.4.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(rolldown@1.2.13)(typescript@7.0.2)(yaml@2.9.1): + dependencies: + '@jridgewell/remapping': 2.3.5 + picomatch: 4.0.7 + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' + webpack-virtual-modules: 0.6.2 + optionalDependencies: + esbuild: 0.27.0 + rolldown: 1.2.13 + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@types/node' + - '@typescript/native-preview' + - '@vitejs/devtools' + - '@volar/typescript' + - '@vue/language-core' + - jiti + - less + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - vue-tsc + - yaml + + update-browserslist-db@1.3.4(browserslist@4.29.4): + dependencies: + browserslist: 4.29.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + use-sync-external-store@1.7.0(react@19.3.1): + dependencies: + react: 19.3.1 + + vite-plus@1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1): dependencies: '@oxc-project/types': 0.154.0 '@oxlint/plugins': 1.88.0 - '@vitest/browser': 5.0.5(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))(vitest@5.0.5) - '@vitest/browser-preview': 5.0.5(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))(vitest@5.0.5) - '@vitest/mocker': 5.0.5(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)) + '@vitest/browser': 5.0.5(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(vitest@5.0.5)(yaml@2.9.1) + '@vitest/browser-preview': 5.0.5(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(vitest@5.0.5)(yaml@2.9.1) + '@vitest/mocker': 5.0.5(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1) '@vitest/pretty-format': 5.0.5 '@vitest/snapshot': 5.0.5 '@vitest/spy': 5.0.5 '@vitest/utils': 5.0.5 - oxfmt: 0.73.0(vite-plus@1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)) - oxlint: 1.88.0(oxlint-tsgolint@7.0.2004)(vite-plus@1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)) + oxfmt: 0.73.0(vite-plus@1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)) + oxlint: 1.88.0(oxlint-tsgolint@7.0.2004)(vite-plus@1.3.0(@types/node@24.19.2)(@vitest/ui@5.0.5)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)) oxlint-tsgolint: 7.0.2004 - vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)' - vitest: 5.0.5(@types/node@24.19.2)(@vitest/browser-preview@5.0.5)(@vitest/ui@5.0.5)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)) + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' + vitest: 5.0.5(@types/node@24.19.2)(@vitest/browser-preview@5.0.5)(@vitest/ui@5.0.5)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1) optionalDependencies: '@voidzero-dev/vite-plus-darwin-arm64': 1.3.0 '@voidzero-dev/vite-plus-darwin-x64': 1.3.0 @@ -2709,10 +4773,14 @@ snapshots: - vue-tsc - yaml - vitest@5.0.5(@types/node@24.19.2)(@vitest/browser-preview@5.0.5)(@vitest/ui@5.0.5)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)): + vitefu@1.1.3(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)): + optionalDependencies: + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' + + vitest@5.0.5(@types/node@24.19.2)(@vitest/browser-preview@5.0.5)(@vitest/ui@5.0.5)(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1))(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1): dependencies: '@types/chai': 5.2.3 - '@vitest/mocker': 5.0.5(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)) + '@vitest/mocker': 5.0.5(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1) chai: 6.3.0 es-module-lexer: 2.3.2 expect-type: 1.4.0 @@ -2723,14 +4791,36 @@ snapshots: tinybench: 6.2.2 tinyexec: 1.3.1 tinyglobby: 0.2.17 - vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1)' + vite: '@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(yaml@2.9.1)' why-is-node-running: 3.2.1 optionalDependencies: '@types/node': 24.19.2 - '@vitest/browser-preview': 5.0.5(@voidzero-dev/vite-plus-core@1.3.0(@types/node@24.19.2)(esbuild@0.27.0)(typescript@7.0.2)(yaml@2.9.1))(vitest@5.0.5) + '@vitest/browser-preview': 5.0.5(@types/node@24.19.2)(esbuild@0.27.0)(jiti@2.7.0)(typescript@7.0.2)(vitest@5.0.5)(yaml@2.9.1) '@vitest/ui': 5.0.5(vitest@5.0.5) transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@typescript/native-preview' + - '@vitejs/devtools' + - '@volar/typescript' + - '@vue/language-core' + - esbuild + - jiti + - less - msw + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - unrun + - vue-tsc + - yaml + + webpack-virtual-modules@0.6.2: {} why-is-node-running@3.2.1: {} @@ -2738,8 +4828,19 @@ snapshots: ws@8.22.0: {} + xmlbuilder2@4.0.3: + dependencies: + '@oozcitak/dom': 2.0.2 + '@oozcitak/infra': 2.0.2 + '@oozcitak/util': 10.0.0 + js-yaml: 4.3.2 + + yallist@3.1.1: {} + yaml@2.9.1: {} + yoctocolors@2.2.0: {} + yuku-core@0.19.0: dependencies: '@yuku-toolchain/types': 0.19.0 @@ -2761,3 +4862,7 @@ snapshots: dependencies: '@yuku-toolchain/types': 0.19.0 yuku-core: 0.19.0 + + zod@4.6.6: {} + + zod@4.6.7: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 5759941..bd190fd 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,11 @@ +# Vite+ ships Vite. Every package that asks for it gets the Vite+ build. +overrides: + vite: npm:@voidzero-dev/vite-plus-core@1.3.0 + +peerDependencyRules: + allowAny: + - vite + # Wait 7 days before resolving newly published package versions, so the ecosystem has time to # detect and yank compromised releases before CI installs them. minimumReleaseAge: 10080 diff --git a/scripts/ensure-convex-auth.ts b/scripts/ensure-convex-auth.ts new file mode 100644 index 0000000..9635bd8 --- /dev/null +++ b/scripts/ensure-convex-auth.ts @@ -0,0 +1,64 @@ +/// +import { execFileSync } from "node:child_process"; +import { generateKeyPairSync, randomUUID } from "node:crypto"; +import { fileURLToPath } from "node:url"; + +// Creates the Convex Auth signing keys of the selected deployment once, before its push: +// `pnpm run deploy` and `pnpm run deploy:dev` run this in their build, and `pnpm run dev` runs it +// before `convex dev`. Alchemy's CONVEX_DEPLOY_KEY selects the production or preview deployment; +// without one, CONVEX_DEPLOYMENT in .env.local selects the development deployment. +// +// An existing pair stays, so the deployment's sessions stay valid; one value without the other is +// an error. The keys of Convex Auth 0.0.x, JWT_PRIVATE_KEY and JWKS, are not touched. +const convex = fileURLToPath(new URL("../node_modules/convex/bin/main.js", import.meta.url)); + +function readVariable(name: string) { + return execFileSync(process.execPath, [convex, "env", "get", name], { + encoding: "utf8", + stdio: ["ignore", "pipe", "ignore"], + }).trim(); +} + +// Inside `convex deploy --cmd`, VITE_CONVEX_URL names the deployment of the push. A run that the +// CLI would point at another deployment, such as a production deploy without a deploy key, stops +// before it reads or writes anything. +const target = process.env["VITE_CONVEX_URL"]; +if (target !== undefined) { + const selected: unknown = JSON.parse( + execFileSync( + process.execPath, + [convex, "run", "--inline-query", "process.env.CONVEX_CLOUD_URL"], + { + encoding: "utf8", + }, + ), + ); + if (selected !== target) + throw new Error( + `The Convex CLI selects ${String(selected)}, but the deploy pushes to ${target}. Deploy production through the Alchemy workflow.`, + ); +} + +const privateKey = readVariable("AUTH_PRIVATE_KEY"); +const jwks = readVariable("AUTH_JWKS"); +if (privateKey && jwks) { + console.log("Convex Auth keys already configured."); +} else if (privateKey || jwks) { + throw new Error("AUTH_PRIVATE_KEY and AUTH_JWKS must be configured together."); +} else { + // The format of `npx @convex-dev/auth`: the core decodes the base64 PKCS#8 key and signs with the + // `kid` of the first key in the set. + const pair = generateKeyPairSync("rsa", { modulusLength: 2048, publicExponent: 0x10001 }); + const pem = pair.privateKey.export({ format: "pem", type: "pkcs8" }).toString(); + const publicJwk = pair.publicKey.export({ format: "jwk" }); + const keySet = JSON.stringify({ + keys: [{ ...publicJwk, kid: randomUUID(), alg: "RS256", use: "sig" }], + }); + // One request with both values, from standard input, so the private key stays out of the + // process arguments. The CLI refuses the write if either value exists by then. + execFileSync(process.execPath, [convex, "env", "set"], { + input: `AUTH_PRIVATE_KEY='${Buffer.from(pem).toString("base64")}'\nAUTH_JWKS='${keySet}'\n`, + stdio: ["pipe", "ignore", "inherit"], + }); + console.log("Convex Auth keys configured."); +} diff --git a/src/format.ts b/src/format.ts new file mode 100644 index 0000000..5e59e88 --- /dev/null +++ b/src/format.ts @@ -0,0 +1,4 @@ +/** The minute of an ISO time, in UTC, so that the server and the browser render the same text. */ +export const formatTime = (iso: string) => `${iso.slice(0, 16).replace("T", " ")} UTC`; + +export const shortCommit = (commit: string) => commit.slice(0, 7); diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts new file mode 100644 index 0000000..ac220eb --- /dev/null +++ b/src/routeTree.gen.ts @@ -0,0 +1,152 @@ +/* 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 AuthedRouteImport } from './routes/_authed' +import { Route as SigninRouteImport } from './routes/signin' +import { Route as AuthedIndexRouteImport } from './routes/_authed/index' +import { Route as AuthedHubRouteImport } from './routes/_authed/hub' +import { Route as AuthedStacksSplatRouteImport } from './routes/_authed/stacks.$' + +const AuthedRoute = AuthedRouteImport.update({ + id: '/_authed', + getParentRoute: () => rootRouteImport, +} as any) +const SigninRoute = SigninRouteImport.update({ + id: '/signin', + path: '/signin', + getParentRoute: () => rootRouteImport, +} as any) +const AuthedIndexRoute = AuthedIndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => AuthedRoute, +} as any) +const AuthedHubRoute = AuthedHubRouteImport.update({ + id: '/hub', + path: '/hub', + getParentRoute: () => AuthedRoute, +} as any) +const AuthedStacksSplatRoute = AuthedStacksSplatRouteImport.update({ + id: '/stacks/$', + path: '/stacks/$', + getParentRoute: () => AuthedRoute, +} as any) + +export interface FileRoutesByFullPath { + '/': typeof AuthedIndexRoute + '/signin': typeof SigninRoute + '/hub': typeof AuthedHubRoute + '/stacks/$': typeof AuthedStacksSplatRoute +} +export interface FileRoutesByTo { + '/signin': typeof SigninRoute + '/hub': typeof AuthedHubRoute + '/': typeof AuthedIndexRoute + '/stacks/$': typeof AuthedStacksSplatRoute +} +export interface FileRoutesById { + __root__: typeof rootRouteImport + '/_authed': typeof AuthedRouteWithChildren + '/signin': typeof SigninRoute + '/_authed/hub': typeof AuthedHubRoute + '/_authed/': typeof AuthedIndexRoute + '/_authed/stacks/$': typeof AuthedStacksSplatRoute +} +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: '/' | '/signin' | '/hub' | '/stacks/$' + fileRoutesByTo: FileRoutesByTo + to: '/signin' | '/hub' | '/' | '/stacks/$' + id: + | '__root__' + | '/_authed' + | '/signin' + | '/_authed/hub' + | '/_authed/' + | '/_authed/stacks/$' + fileRoutesById: FileRoutesById +} +export interface RootRouteChildren { + AuthedRoute: typeof AuthedRouteWithChildren + SigninRoute: typeof SigninRoute +} + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/_authed': { + id: '/_authed' + path: '' + fullPath: '/' + preLoaderRoute: typeof AuthedRouteImport + parentRoute: typeof rootRouteImport + } + '/signin': { + id: '/signin' + path: '/signin' + fullPath: '/signin' + preLoaderRoute: typeof SigninRouteImport + parentRoute: typeof rootRouteImport + } + '/_authed/': { + id: '/_authed/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof AuthedIndexRouteImport + parentRoute: typeof AuthedRoute + } + '/_authed/hub': { + id: '/_authed/hub' + path: '/hub' + fullPath: '/hub' + preLoaderRoute: typeof AuthedHubRouteImport + parentRoute: typeof AuthedRoute + } + '/_authed/stacks/$': { + id: '/_authed/stacks/$' + path: '/stacks/$' + fullPath: '/stacks/$' + preLoaderRoute: typeof AuthedStacksSplatRouteImport + parentRoute: typeof AuthedRoute + } + } +} + +interface AuthedRouteChildren { + AuthedHubRoute: typeof AuthedHubRoute + AuthedIndexRoute: typeof AuthedIndexRoute + AuthedStacksSplatRoute: typeof AuthedStacksSplatRoute +} + +const AuthedRouteChildren: AuthedRouteChildren = { + AuthedHubRoute: AuthedHubRoute, + AuthedIndexRoute: AuthedIndexRoute, + AuthedStacksSplatRoute: AuthedStacksSplatRoute, +} + +const AuthedRouteWithChildren = + AuthedRoute._addFileChildren(AuthedRouteChildren) + +const rootRouteChildren: RootRouteChildren = { + AuthedRoute: AuthedRouteWithChildren, + SigninRoute: SigninRoute, +} +export const routeTree = rootRouteImport + ._addFileChildren(rootRouteChildren) + ._addFileTypes() + +import type { getRouter } from './router.tsx' +import type { createStart } from '@tanstack/react-start' +declare module '@tanstack/react-start' { + interface Register { + ssr: true + router: Awaited> + } +} diff --git a/src/router.tsx b/src/router.tsx new file mode 100644 index 0000000..e42021d --- /dev/null +++ b/src/router.tsx @@ -0,0 +1,37 @@ +import { ConvexQueryClient } from "@convex-dev/react-query"; +import { QueryClient } from "@tanstack/react-query"; +import { createRouter as createTanStackRouter } from "@tanstack/react-router"; +import { setupRouterSsrQueryIntegration } from "@tanstack/react-router-ssr-query"; +import { routeTree } from "./routeTree.gen"; + +export function getRouter() { + // The server calls this for each request, so requests never share a client. + const convexQueryClient = new ConvexQueryClient(import.meta.env["VITE_CONVEX_URL"], { + // Holds queries until the session is known; `SessionProvider` releases it without one. + expectAuth: true, + }); + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + queryKeyHashFn: convexQueryClient.hashFn(), + queryFn: convexQueryClient.queryFn(), + }, + }, + }); + convexQueryClient.connect(queryClient); + + const router = createTanStackRouter({ + routeTree, + context: { queryClient, convexQueryClient }, + defaultPreload: "intent", + scrollRestoration: true, + }); + setupRouterSsrQueryIntegration({ router, queryClient }); + return router; +} + +declare module "@tanstack/react-router" { + interface Register { + router: ReturnType; + } +} diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx new file mode 100644 index 0000000..0e13bbe --- /dev/null +++ b/src/routes/__root.tsx @@ -0,0 +1,39 @@ +import type { ConvexQueryClient } from "@convex-dev/react-query"; +import { SessionProvider, sessionBeforeLoad } from "@samebase/convex-auth-tanstack-start"; +import type { QueryClient } from "@tanstack/react-query"; +import { createRootRouteWithContext, HeadContent, Outlet, Scripts } from "@tanstack/react-router"; +import appCss from "../style.css?url"; + +export const Route = createRootRouteWithContext<{ + queryClient: QueryClient; + convexQueryClient: ConvexQueryClient; +}>()({ + beforeLoad: sessionBeforeLoad, + head: () => ({ + meta: [ + { charSet: "utf-8" }, + { name: "viewport", content: "width=device-width, initial-scale=1" }, + { title: "Base" }, + ], + links: [{ rel: "stylesheet", href: appCss }], + }), + component: RootComponent, + notFoundComponent: () =>

Not found

, +}); + +function RootComponent() { + const { convexQueryClient, token } = Route.useRouteContext(); + return ( + + + + + + + + + + + + ); +} diff --git a/src/routes/_authed.tsx b/src/routes/_authed.tsx new file mode 100644 index 0000000..f7a23d7 --- /dev/null +++ b/src/routes/_authed.tsx @@ -0,0 +1,34 @@ +import { + RedirectWithoutSession, + redirectWithoutSession, + useSignOutSession, +} from "@samebase/convex-auth-tanstack-start"; +import { createFileRoute, Link, Outlet } from "@tanstack/react-router"; + +/** The pages under `_authed/` need a session: without one, they redirect to /signin. */ +export const Route = createFileRoute("/_authed")({ + beforeLoad: ({ serverContext }) => redirectWithoutSession(serverContext, { to: "/signin" }), + component: AuthedLayout, +}); + +function AuthedLayout() { + const signOut = useSignOutSession("/auth/signout", "/signin"); + return ( + +
+ + +
+
+ ); +} diff --git a/src/routes/_authed/hub.tsx b/src/routes/_authed/hub.tsx new file mode 100644 index 0000000..b3ee0c6 --- /dev/null +++ b/src/routes/_authed/hub.tsx @@ -0,0 +1,51 @@ +import { convexQuery } from "@convex-dev/react-query"; +import { useSuspenseQuery } from "@tanstack/react-query"; +import { createFileRoute } from "@tanstack/react-router"; +import { api } from "../../../convex/_generated/api"; + +const hubQuery = convexQuery(api.console.hub, {}); + +export const Route = createFileRoute("/_authed/hub")({ + loader: async ({ context }) => { + // @ts-expect-error convexQuery always sets queryFn, but its type allows undefined there, which `query` rejects under exactOptionalPropertyTypes. + await context.queryClient.query(hubQuery); + }, + component: HubPage, +}); + +function HubPage() { + const { data: apps } = useSuspenseQuery(hubQuery); + return ( +
+

Hub

+ {apps.map((app) => ( +
+

+ {app.name} {app.appId} +

+ + + + + + + + + + {app.clients.map((client) => ( + + + + + + ))} + +
ClientTypeCallback
{client.clientName}{client.deploymentType}{client.redirectUri}
+
+ ))} +
+ ); +} diff --git a/src/routes/_authed/index.tsx b/src/routes/_authed/index.tsx new file mode 100644 index 0000000..1973154 --- /dev/null +++ b/src/routes/_authed/index.tsx @@ -0,0 +1,60 @@ +import { convexQuery } from "@convex-dev/react-query"; +import { useSuspenseQuery } from "@tanstack/react-query"; +import { createFileRoute, Link } from "@tanstack/react-router"; +import { api } from "../../../convex/_generated/api"; +import { formatTime, shortCommit } from "../../format"; + +const stacksQuery = convexQuery(api.console.stacks, {}); + +export const Route = createFileRoute("/_authed/")({ + // On the server, the query runs with the token of the session cookie. + loader: async ({ context }) => { + // @ts-expect-error convexQuery always sets queryFn, but its type allows undefined there, which `query` rejects under exactOptionalPropertyTypes. + await context.queryClient.query(stacksQuery); + }, + component: StacksPage, +}); + +function StacksPage() { + const { data: stacks } = useSuspenseQuery(stacksQuery); + return ( +
+

Stacks

+ + + + + + + + + + {stacks.map((stack) => { + const last = stack.stages + .map((stage) => stage.record) + .reduce<(typeof stack.stages)[number]["record"] | null>( + (latest, record) => + latest === null || record.recordedAt > latest.recordedAt ? record : latest, + null, + ); + return ( + + + + + + ); + })} + +
StackStagesLast deploy
+ + {stack.name} + + {stack.stages.length} + {last === null + ? "No run record" + : `${formatTime(last.recordedAt)}, ${last.branch} ${shortCommit(last.headCommit)}`} +
+
+ ); +} diff --git a/src/routes/_authed/stacks.$.tsx b/src/routes/_authed/stacks.$.tsx new file mode 100644 index 0000000..a256639 --- /dev/null +++ b/src/routes/_authed/stacks.$.tsx @@ -0,0 +1,105 @@ +import { convexQuery } from "@convex-dev/react-query"; +import { useSuspenseQuery } from "@tanstack/react-query"; +import { createFileRoute, Link } from "@tanstack/react-router"; +import { api } from "../../../convex/_generated/api"; +import { formatTime, shortCommit } from "../../format"; + +export const Route = createFileRoute("/_authed/stacks/$")({ + validateSearch: (search: Record): { stage?: string } => + typeof search["stage"] === "string" ? { stage: search["stage"] } : {}, + loader: async ({ context, params }) => { + // @ts-expect-error convexQuery always sets queryFn, but its type allows undefined there, which `query` rejects under exactOptionalPropertyTypes. + await context.queryClient.query(convexQuery(api.console.stack, { name: params._splat ?? "" })); + }, + component: StackPage, +}); + +const parse = (json: string): Record => { + const value: unknown = JSON.parse(json); + return typeof value === "object" && value !== null + ? Object.fromEntries(Object.entries(value)) + : {}; +}; + +function StackPage() { + const { _splat: name = "" } = Route.useParams(); + const search = Route.useSearch(); + const { data: stack } = useSuspenseQuery(convexQuery(api.console.stack, { name })); + if (stack === null) { + return

{name} has no run record.

; + } + // `prod` first, then the previews. + const stages = [...stack.stages].sort( + (a, b) => Number(b.name === "prod") - Number(a.name === "prod"), + ); + const stage = stages.find(({ name }) => name === search.stage) ?? stages[0]; + if (stage === undefined) { + return

{name} has no stages.

; + } + const { record } = stage; + const repositoryUrl = `https://github.com/${record.repository}`; + return ( +
+

{stack.name}

+ + + +
+

Last run

+

+ {formatTime(record.recordedAt)} from {record.source}, branch {record.branch}, commit{" "} + + {shortCommit(record.headCommit)} + +

+

+ {record.pullRequest === null ? null : ( + + Pull request {record.pullRequest} + + )} + {record.runUrl === null ? null : ( + + Workflow run + + )} +

+
+ +
+

Output

+
{JSON.stringify(JSON.parse(stage.output), null, 2)}
+
+ +
+

Resources

+ {stage.resources.map(({ fqn, value }) => { + const resource = parse(value); + return ( +
+ + {fqn}{" "} + + {String(resource["resourceType"])}, {String(resource["status"])} + + +
{JSON.stringify(resource, null, 2)}
+
+ ); + })} +
+
+ ); +} diff --git a/src/routes/signin.tsx b/src/routes/signin.tsx new file mode 100644 index 0000000..1f45376 --- /dev/null +++ b/src/routes/signin.tsx @@ -0,0 +1,82 @@ +import { useAuthActions } from "@convex-dev/auth/react"; +import { createFileRoute } from "@tanstack/react-router"; +import { ConvexHttpClient } from "convex/browser"; +import { type SyntheticEvent, useState } from "react"; +import { api } from "../../convex/_generated/api"; + +export const Route = createFileRoute("/signin")({ component: SignInPage }); + +function SignInPage() { + const { setSession } = useAuthActions(); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [error, setError] = useState(""); + const [isPending, setIsPending] = useState(false); + + const signIn = async (event: SyntheticEvent) => { + event.preventDefault(); + setError(""); + setIsPending(true); + try { + // The route mints the session, keeps the refresh token in its httpOnly cookie, and returns + // the access token. The trailing `?path=` puts the endpoint of the client into the query. + const client = new ConvexHttpClient("/auth/signin?path=", { + skipConvexDeploymentUrlCheck: true, + }); + const result = await client.mutation(api.auth.signInWithPassword, { email, password }); + if (result.status === "error") { + setError( + result.userError.error === "RATE_LIMITED" + ? "Too many attempts. Try again later." + : "Incorrect email or password.", + ); + return; + } + await setSession(result.tokens); + // A document load, so that the server renders the first page from the new cookie. + location.assign("/"); + } catch { + setError("Sign-in failed. Try again."); + } finally { + setIsPending(false); + } + }; + + return ( +
+

Base

+
void signIn(event)}> + setEmail(event.target.value)} + type="email" + autoComplete="username" + placeholder="Email" + required + /> + setPassword(event.target.value)} + type="password" + autoComplete="current-password" + placeholder="Password" + required + /> + +
+ {error ? ( +

+ {error} +

+ ) : null} +
+ ); +} diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..8a62f55 --- /dev/null +++ b/src/server.ts @@ -0,0 +1,51 @@ +import { httpCookies, ServerAuthSession, setupConvexAuthServer } from "@convex-dev/auth/ssr"; +import handler from "@samebase/convex-hosting-tanstack-start/server"; +import { ConvexHttpClient } from "convex/browser"; +import { api } from "../convex/_generated/api"; + +const convexUrl: string = import.meta.env["VITE_CONVEX_URL"]; +const convex = new ConvexHttpClient(convexUrl); + +// Answers every request that no file and no other route of convex/http.ts answers: on Convex, +// convex/http.ts calls it; in development, Vite does. +const server = { + async fetch(request: Request) { + const url = new URL(request.url); + // `Secure` when the browser reached the site over HTTPS. A local backend and Vite's dev server + // serve plain HTTP, so the request decides, not the build or the backend URL. + const cookieOptions = { secure: url.protocol === "https:" }; + if (request.method === "POST") { + // The browser signs in, refreshes, and signs out through these routes, and the refresh token + // stays in an httpOnly cookie on this origin. The route answers 403 for a function that is + // not listed in `signIn`. + const auth = setupConvexAuthServer({ + convexUrl, + refreshSession: api.auth.refreshSession, + signOut: api.auth.signOut, + signIn: [api.auth.signInWithPassword], + cookieOptions, + }); + switch (url.pathname) { + case "/auth/signin": + return auth.convexProxyHandler(request); + case "/auth/refresh": + return auth.refreshHandler(request); + case "/auth/signout": + return auth.signOutHandler(request); + } + } + const cookies = httpCookies(request); + const session = new ServerAuthSession({ + refreshSession: (refreshToken) => convex.mutation(api.auth.refreshSession, { refreshToken }), + cookies, + cookieOptions, + }); + const token = await session.getToken(); + const page = await handler.fetch(request, { context: { token } }); + const headers = new Headers(page.headers); + cookies.applyTo(headers); + return new Response(page.body, { status: page.status, headers }); + }, +}; + +export default server; diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..be701b0 --- /dev/null +++ b/src/style.css @@ -0,0 +1,5 @@ +@import "tailwindcss"; + +:root { + color-scheme: light dark; +} diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..d3e1bc2 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "es2023", + "module": "esnext", + "jsx": "react-jsx", + "lib": ["ES2023", "DOM", "DOM.Iterable"], + "types": ["vite-plus/client", "node"], + "skipLibCheck": true, + "strict": true, + "exactOptionalPropertyTypes": true, + "noPropertyAccessFromIndexSignature": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src"] +} diff --git a/tsconfig.json b/tsconfig.json index 874c444..79283f7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,8 @@ { "files": [], - "references": [{ "path": "./convex/tsconfig.json" }, { "path": "./tsconfig.node.json" }] + "references": [ + { "path": "./convex/tsconfig.json" }, + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] } diff --git a/vite.config.ts b/vite.config.ts index 4db06fe..3109040 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,8 +1,13 @@ +import { convexAuth } from "@samebase/convex-auth-tanstack-start/vite"; +import { convexSsr } from "@samebase/convex-hosting-tanstack-start/vite"; +import tailwindcss from "@tailwindcss/vite"; +import { tanstackStart } from "@tanstack/react-start/plugin/vite"; +import react from "@vitejs/plugin-react"; import { defineConfig } from "vite-plus"; export default defineConfig({ fmt: { - ignorePatterns: ["**/_generated/**"], + ignorePatterns: ["**/_generated/**", "src/routeTree.gen.ts"], printWidth: 100, proseWrap: "always", }, @@ -10,10 +15,12 @@ export default defineConfig({ options: { typeAware: true }, plugins: ["eslint", "typescript"], env: { builtin: true }, - ignorePatterns: ["**/_generated"], + ignorePatterns: ["**/_generated", "src/routeTree.gen.ts"], rules: { "typescript/no-floating-promises": "error", "typescript/no-deprecated": "error", }, }, + // Every page needs a session, so nothing prerenders. + plugins: [convexSsr(), convexAuth(), tailwindcss(), tanstackStart(), react()], }); From 658637762fb38e079f89394a9770d1d2dc562049 Mon Sep 17 00:00:00 2001 From: Nicu Chiciuc Date: Fri, 30 Oct 2026 15:10:54 +0200 Subject: [PATCH 2/2] Keep an unauthenticated caller away from the console's work This deployment is also the sign-in hub of the team. From one Codex pass and a measured login flood: - The sign-in page is a file of the build. A request without a session cookie gets that file or a redirect, and it never reaches a refresh or a render. - Other methods answer 405 before the session code. - Every failed sign-in gets the same answer. The rate limit told a caller that an email has an account. - A read checks that the account still exists, so deleting a row of users ends its sessions at once. - Pages and files refuse framing. Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 3 ++- alchemy.run.ts | 2 +- convex/auth.ts | 23 +++++++++-------------- convex/console.ts | 7 +++++-- public/_headers | 2 ++ scripts/ensure-convex-auth.ts | 3 +-- src/routes/signin.tsx | 6 +----- src/server.ts | 23 ++++++++++++++++++++++- vite.config.ts | 19 +++++++++++++++++-- 9 files changed, 60 insertions(+), 28 deletions(-) create mode 100644 public/_headers diff --git a/AGENTS.md b/AGENTS.md index 1f9f6d6..f6600c2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,7 +20,8 @@ in its repository. the paths of the hub or of Convex Auth: `/authorize`, `/continue`, `/token`, `/userinfo`, `/connectors/*`, `/.well-known/*`, `/auth/*`. - The console has no sign-up. Run `authAdmin:createOrUpdatePasswordAccount` from the Functions page - of the Convex dashboard, with the email and password you choose, not in a terminal. + of the Convex dashboard, with the email and password you choose, not in a terminal. To end an + account's access at once, delete its row in `users`. A new password does not end its sessions. - `pnpm run deploy:dev` builds, uploads, and pushes to the development deployment. It must run once before `pnpm run dev`: `convex/http.ts` imports the build. - Never use `npx convex import --replace-all` on this deployment, also not with `--component`: it diff --git a/alchemy.run.ts b/alchemy.run.ts index 913cf4a..c80d165 100644 --- a/alchemy.run.ts +++ b/alchemy.run.ts @@ -51,7 +51,7 @@ export default Alchemy.Stack( path: "./convex", command: ["node", "--run", "deploy"], // The push inputs besides the functions, package.json, and the lockfile. - include: ["scripts/**", "tsconfig*.json", "src/**", "vite.config.ts"], + include: ["scripts/**", "tsconfig*.json", "src/**", "public/**", "vite.config.ts"], } satisfies Convex.Source; // The variables of the deployment. The secret is a prop, so the state store holds it next to // the deployment it serves. diff --git a/convex/auth.ts b/convex/auth.ts index e038c8d..1a88411 100644 --- a/convex/auth.ts +++ b/convex/auth.ts @@ -10,6 +10,7 @@ const auth = setupConvexAuth({ component: components.auth }); export const { signOut, refreshSession } = auth; const PROVIDER = "password"; +const FAILED = { status: "error", userError: { error: "INVALID_CREDENTIALS" } } as const; const vTokens = object({ accessToken: string(), @@ -39,9 +40,11 @@ export const linkExistingUser = internalMutation({ }); /** -Signs in to an existing account. There is no sign-up: `authAdmin` creates accounts. A wrong password -returns an error result instead of throwing, so the password component keeps the attempt in its -per-user rate limit. +Signs in to an existing account. There is no sign-up: `authAdmin` creates accounts. A failure +returns a result instead of throwing, so the password component keeps the attempt in its limit of +five attempts, then one per minute, for each account. Every failure gets the same answer, also the +rate limit, which only an account that exists can reach: it would tell a caller that the email has +an account. */ export const signInWithPassword = mutation({ args: { email: string(), password: string() }, @@ -49,7 +52,7 @@ export const signInWithPassword = mutation({ object({ status: literal("complete"), tokens: vTokens }), object({ status: literal("error"), - userError: object({ error: union(literal("INVALID_CREDENTIALS"), literal("RATE_LIMITED")) }), + userError: object({ error: literal("INVALID_CREDENTIALS") }), }), ), handler: async (ctx, args) => { @@ -58,22 +61,14 @@ export const signInWithPassword = mutation({ .withIndex("email", (q) => q.eq("email", normalizeEmail(args.email))) .unique(); if (user === null) { - return { status: "error" as const, userError: { error: "INVALID_CREDENTIALS" as const } }; + return FAILED; } const verification = await ctx.runMutation(components.authPassword.public.verifyPassword, { userId: user._id, password: args.password, }); if (!verification.success) { - return { - status: "error" as const, - userError: { - error: - verification.userError.error === "RATE_LIMITED" - ? ("RATE_LIMITED" as const) - : ("INVALID_CREDENTIALS" as const), - }, - }; + return FAILED; } const claims = { providerName: PROVIDER, diff --git a/convex/console.ts b/convex/console.ts index 11fa5f1..dd32c79 100644 --- a/convex/console.ts +++ b/convex/console.ts @@ -4,11 +4,14 @@ import { env, query, type QueryCtx } from "./_generated/server"; /** Every read of the console needs a session. A read token of `reader:authorize` is an identity too, for -one repository, so the issuer decides: a session has the issuer of the auth component. +one repository, so the issuer decides: a session has the issuer of the auth component. The account +must still exist: deleting a row of `users` ends the access of its sessions at once. */ async function requireSession(ctx: QueryCtx) { const identity = await ctx.auth.getUserIdentity(); - if (identity === null || identity.issuer !== env.CONVEX_SITE_URL) { + const userId = + identity?.issuer === env.CONVEX_SITE_URL ? ctx.db.normalizeId("users", identity.subject) : null; + if (userId === null || (await ctx.db.get("users", userId)) === null) { throw new ConvexError("A session is required."); } } diff --git a/public/_headers b/public/_headers new file mode 100644 index 0000000..d6e4706 --- /dev/null +++ b/public/_headers @@ -0,0 +1,2 @@ +/* + Content-Security-Policy: frame-ancestors 'none' diff --git a/scripts/ensure-convex-auth.ts b/scripts/ensure-convex-auth.ts index 9635bd8..e529063 100644 --- a/scripts/ensure-convex-auth.ts +++ b/scripts/ensure-convex-auth.ts @@ -4,8 +4,7 @@ import { generateKeyPairSync, randomUUID } from "node:crypto"; import { fileURLToPath } from "node:url"; // Creates the Convex Auth signing keys of the selected deployment once, before its push: -// `pnpm run deploy` and `pnpm run deploy:dev` run this in their build, and `pnpm run dev` runs it -// before `convex dev`. Alchemy's CONVEX_DEPLOY_KEY selects the production or preview deployment; +// `pnpm run deploy` and `pnpm run deploy:dev` run this in their build. Alchemy's CONVEX_DEPLOY_KEY selects the production or preview deployment; // without one, CONVEX_DEPLOYMENT in .env.local selects the development deployment. // // An existing pair stays, so the deployment's sessions stay valid; one value without the other is diff --git a/src/routes/signin.tsx b/src/routes/signin.tsx index 1f45376..b652b77 100644 --- a/src/routes/signin.tsx +++ b/src/routes/signin.tsx @@ -25,11 +25,7 @@ function SignInPage() { }); const result = await client.mutation(api.auth.signInWithPassword, { email, password }); if (result.status === "error") { - setError( - result.userError.error === "RATE_LIMITED" - ? "Too many attempts. Try again later." - : "Incorrect email or password.", - ); + setError("Incorrect email or password, or too many attempts."); return; } await setSession(result.tokens); diff --git a/src/server.ts b/src/server.ts index 8a62f55..8a03954 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,4 +1,10 @@ -import { httpCookies, ServerAuthSession, setupConvexAuthServer } from "@convex-dev/auth/ssr"; +import { + AUTH_JWT_COOKIE, + AUTH_REFRESH_COOKIE, + httpCookies, + ServerAuthSession, + setupConvexAuthServer, +} from "@convex-dev/auth/ssr"; import handler from "@samebase/convex-hosting-tanstack-start/server"; import { ConvexHttpClient } from "convex/browser"; import { api } from "../convex/_generated/api"; @@ -6,6 +12,9 @@ import { api } from "../convex/_generated/api"; const convexUrl: string = import.meta.env["VITE_CONVEX_URL"]; const convex = new ConvexHttpClient(convexUrl); +/** The page without a session. In the build it is a file, so it reaches this code only in development. */ +const SIGN_IN_PATH = "/signin"; + // Answers every request that no file and no other route of convex/http.ts answers: on Convex, // convex/http.ts calls it; in development, Vite does. const server = { @@ -34,7 +43,17 @@ const server = { return auth.signOutHandler(request); } } + // This deployment is also the sign-in hub of the team, so a request without a session does no + // work here: no refresh, no render. Only a browser with a session cookie reaches the pages. + if (request.method !== "GET" && request.method !== "HEAD") { + return new Response(null, { status: 405, headers: { Allow: "GET, HEAD" } }); + } const cookies = httpCookies(request); + const sessionCookie = + (await cookies.get(AUTH_JWT_COOKIE)) ?? (await cookies.get(AUTH_REFRESH_COOKIE)); + if (sessionCookie === undefined && url.pathname !== SIGN_IN_PATH) { + return new Response(null, { status: 307, headers: { Location: SIGN_IN_PATH } }); + } const session = new ServerAuthSession({ refreshSession: (refreshToken) => convex.mutation(api.auth.refreshSession, { refreshToken }), cookies, @@ -43,6 +62,8 @@ const server = { const token = await session.getToken(); const page = await handler.fetch(request, { context: { token } }); const headers = new Headers(page.headers); + // public/_headers sets the same value on the files of the build. + headers.set("Content-Security-Policy", "frame-ancestors 'none'"); cookies.applyTo(headers); return new Response(page.body, { status: page.status, headers }); }, diff --git a/vite.config.ts b/vite.config.ts index 3109040..6cb002d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -21,6 +21,21 @@ export default defineConfig({ "typescript/no-deprecated": "error", }, }, - // Every page needs a session, so nothing prerenders. - plugins: [convexSsr(), convexAuth(), tailwindcss(), tanstackStart(), react()], + plugins: [ + convexSsr(), + convexAuth(), + tailwindcss(), + // The sign-in page is the one page without a session: a file of the build, so that a visitor + // without a session never reaches the renderer (src/server.ts). + tanstackStart({ + prerender: { + enabled: true, + autoStaticPathsDiscovery: false, + crawlLinks: false, + failOnError: true, + }, + pages: [{ path: "/signin", prerender: { outputPath: "/signin/index.html" } }], + }), + react(), + ], });