diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 361283f..35b3e9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -85,6 +85,8 @@ jobs: - name: Build all packages run: pnpm build + env: + NEXT_PUBLIC_CONVEX_URL: https://terrific-llama-923.convex.cloud - name: Upload build artifacts uses: actions/upload-artifact@v4 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0b20cbd..9538516 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -53,6 +53,8 @@ jobs: - name: Build run: pnpm build + env: + NEXT_PUBLIC_CONVEX_URL: https://terrific-llama-923.convex.cloud - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e7240a..bef35d9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -77,6 +77,8 @@ jobs: - name: Build run: pnpm build + env: + NEXT_PUBLIC_CONVEX_URL: https://terrific-llama-923.convex.cloud release: name: Create GitHub Release diff --git a/.prettierignore b/.prettierignore index 461b008..5539be9 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,4 +4,7 @@ node_modules/ .turbo/ coverage/ pnpm-lock.yaml -.pnpm-store/ \ No newline at end of file +.pnpm-store/ +# Convex auto-generated files +packages/backend/convex/_generated/ +packages/backend/convex/README.md \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 464c7d8..ffd0f07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,73 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- +## [0.2.0] - 2026-06-29 + +### Overview + +This release integrates **Convex** as the real-time backend for the Echo monorepo. +A new `@workspace/backend` package encapsulates all Convex schema definitions and +server-side functions, and both `apps/web` and `apps/widget` are wired to the live +Convex deployment via `ConvexProvider` and the generated TypeScript API. + +--- + +### Added + +#### `packages/backend` — New Convex workspace package + +- Scaffolded `@workspace/backend` as a dedicated Convex workspace package +- `convex/schema.ts` — database schema with a `users` table (`name: string`) defined + using Convex's `defineSchema` and `defineTable` helpers +- `convex/users.ts` — two server functions: + - `getMany` — `query` that fetches all users from the database + - `add` — `mutation` that inserts a new user record (`name: "RISHII"`) +- `convex/_generated/` — committed auto-generated TypeScript API types (`api.d.ts`, + `api.js`, `dataModel.d.ts`, `server.d.ts`, `server.js`) for full type safety across + the monorepo without requiring a running Convex dev server in CI +- `package.json` — workspace package definition (`name: @workspace/backend`, + `convex: ^1.42.0` runtime dependency, `dev` and `setup` scripts) +- `tsconfig.json` — TypeScript configuration extending `@workspace/typescript-config` +- `.gitignore` — excludes `.env.local` (contains deployment secrets) +- `convex/README.md` — Convex-generated quickstart guide (excluded from Prettier) + +#### Convex client integration in `apps/web` and `apps/widget` + +- Added `@workspace/backend: workspace:*` and `convex: ^1.42.0` to both app + `package.json` files +- Added `@workspace/backend/*` TypeScript path alias in both `tsconfig.json` files, + pointing to `packages/backend/convex/*` for generated API type imports +- `components/theme-provider.tsx` — replaced static `NextThemesProvider` wrapper with + `ConvexProvider` backed by `ConvexReactClient`, reading from `NEXT_PUBLIC_CONVEX_URL` + environment variable +- `app/page.tsx` — replaced static math function demo with live Convex hooks: + - `useQuery(api.users.getMany)` — subscribes to real-time user list + - `useMutation(api.users.add)` — triggers user insertion via a button click + +#### CI/tooling improvements + +- Added `NEXT_PUBLIC_CONVEX_URL` environment variable to the `build` step in + `ci.yml`, `release.yml`, and `codeql.yml` — required for `ConvexReactClient` + to initialise with a valid URL during `next build` in CI environments +- Added `packages/backend/convex/_generated/` and `packages/backend/convex/README.md` + to `.prettierignore` — auto-generated files should not be subject to formatting rules + +--- + +### Technical Decisions + +- **`convex/_generated/` committed to source control** — Generated API types provide + full TypeScript safety across the monorepo without requiring every developer to run + `convex dev` before getting type completions. Files are excluded from Prettier. +- **`ConvexProvider` in theme-provider** — Centralises the Convex client provider at + the layout level so all pages and components have access to real-time hooks without + additional wrapper boilerplate. +- **`NEXT_PUBLIC_CONVEX_URL` as build-time env** — Convex's React client requires a + valid URL at module initialisation; adding it to CI workflows prevents static page + prerender failures in environments where `.env.local` is not present. + +--- + ## [0.1.1] - 2026-06-28 ### Fixed @@ -182,6 +249,7 @@ Initial release of **Echo** — an enterprise-grade full-stack monorepo platform --- -[Unreleased]: https://github.com/RISHII7/echo/compare/v0.1.1...HEAD +[Unreleased]: https://github.com/RISHII7/echo/compare/v0.2.0...HEAD +[0.2.0]: https://github.com/RISHII7/echo/compare/v0.1.1...v0.2.0 [0.1.1]: https://github.com/RISHII7/echo/compare/v0.1.0...v0.1.1 [0.1.0]: https://github.com/RISHII7/echo/releases/tag/v0.1.0 diff --git a/README.md b/README.md index d4619bf..13d3642 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ [![Next.js](https://img.shields.io/badge/Next.js-16-black?logo=next.js)](https://nextjs.org) [![Turborepo](https://img.shields.io/badge/Turborepo-2-EF4444?logo=turborepo)](https://turbo.build) [![Tailwind CSS](https://img.shields.io/badge/Tailwind-4-38BDF8?logo=tailwindcss)](https://tailwindcss.com) +[![Convex](https://img.shields.io/badge/Convex-backend-EE342F?logo=convex)](https://convex.dev) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) [Report Bug](https://github.com/RISHII7/echo/issues/new?template=bug_report.yml) · [Request Feature](https://github.com/RISHII7/echo/issues/new?template=feature_request.yml) · [Documentation](https://github.com/RISHII7/echo/wiki) @@ -56,7 +57,8 @@ Echo is a production-ready, full-stack monorepo platform engineered for enterpri ## Features - **Monorepo Architecture** — Turborepo with remote caching, task pipelines, and workspace dependency graph -- **Type Safety** — End-to-end TypeScript with strict mode across all packages +- **Real-Time Backend** — Convex reactive database with live queries and server mutations +- **Type Safety** — End-to-end TypeScript with strict mode and generated API types across all packages - **Design System** — Shared UI component library built on shadcn/ui and Radix primitives - **Performance** — Next.js Turbopack, React Server Components, and Tailwind CSS v4 - **Code Quality** — ESLint 9, Prettier, and TypeScript strict checks enforced on every commit @@ -74,13 +76,14 @@ echo/ │ ├── web/ # Primary Next.js application │ └── widget/ # Embeddable widget application ├── packages/ +│ ├── backend/ # Convex real-time backend (schema + server functions) │ ├── ui/ # Shared component library │ ├── math/ # Shared utilities │ ├── eslint-config/ # Shared ESLint configuration │ └── typescript-config/ # Shared TypeScript configuration ``` -The monorepo uses a **workspace dependency graph** where apps consume packages, and packages can depend on other packages. Turborepo ensures tasks run in topological order with caching at every layer. +The monorepo uses a **workspace dependency graph** where apps consume packages, and packages can depend on other packages. Turborepo ensures tasks run in topological order with caching at every layer. The `@workspace/backend` package provides a shared Convex client that both apps import for real-time data access. --- @@ -93,6 +96,7 @@ The monorepo uses a **workspace dependency graph** where apps consume packages, | UI Library | React 19 | | Styling | Tailwind CSS 4 | | Components | shadcn/ui + Radix UI | +| Backend | Convex (real-time DB) | | Icons | Lucide React | | Monorepo | Turborepo 2 | | Package Manager | pnpm 10 | @@ -129,9 +133,19 @@ pnpm dev ### Environment Variables -| Variable | Description | Required | -| --------------------- | --------------------------------- | -------- | -| `NEXT_PUBLIC_APP_URL` | Public URL of the web application | Yes | +Create `apps/web/.env.local` and `apps/widget/.env.local` with the following: + +| Variable | Description | Required | +| ------------------------ | --------------------------------- | -------- | +| `NEXT_PUBLIC_CONVEX_URL` | Convex deployment URL | Yes | +| `NEXT_PUBLIC_APP_URL` | Public URL of the web application | No | + +To get your `NEXT_PUBLIC_CONVEX_URL`, run `pnpm --filter backend dev` and copy the deployment URL from the Convex dashboard, or from `packages/backend/.env.local` after the first `convex dev` run. + +```bash +# apps/web/.env.local +NEXT_PUBLIC_CONVEX_URL=https://.convex.cloud +``` --- @@ -140,15 +154,16 @@ pnpm dev ### Commands ```bash -pnpm dev # Start all apps in development mode -pnpm build # Build all packages and apps -pnpm lint # Run linting across all workspaces -pnpm typecheck # Run type checking across all workspaces -pnpm format # Format all files with Prettier +pnpm dev # Start all apps in development mode (Next.js + Convex) +pnpm build # Build all packages and apps +pnpm lint # Run linting across all workspaces +pnpm typecheck # Run type checking across all workspaces +pnpm format # Format all files with Prettier -# Target a specific app +# Target a specific workspace pnpm --filter web dev pnpm --filter widget dev +pnpm --filter backend dev # Start Convex dev server only ``` ### Branch Strategy @@ -202,6 +217,11 @@ echo/ │ ├── web/ # Next.js web application │ └── widget/ # Embeddable widget ├── packages/ +│ ├── backend/ # Convex real-time backend +│ │ └── convex/ +│ │ ├── _generated/ # Auto-generated TypeScript API types +│ │ ├── schema.ts # Database schema definitions +│ │ └── users.ts # User query & mutation functions │ ├── ui/ # Shared component library │ ├── math/ # Shared utilities │ ├── eslint-config/ # ESLint config presets @@ -217,6 +237,26 @@ echo/ ## Packages +### `@workspace/backend` + +Convex real-time backend package. Provides the database schema and server functions, with auto-generated TypeScript types for end-to-end type safety. + +```tsx +import { api } from "@workspace/backend/_generated/api" +import { useQuery, useMutation } from "convex/react" + +const users = useQuery(api.users.getMany) +const addUser = useMutation(api.users.add) +``` + +To start the Convex dev server: + +```bash +pnpm --filter backend dev +# or from repo root: +pnpm dev # starts all apps including Convex +``` + ### `@workspace/ui` Shared component library built on shadcn/ui and Radix UI primitives. diff --git a/apps/web/app/page.tsx b/apps/web/app/page.tsx index f9e964b..dcb5e26 100644 --- a/apps/web/app/page.tsx +++ b/apps/web/app/page.tsx @@ -1,13 +1,18 @@ +"use client" + +import { useMutation, useQuery } from "convex/react" +import { api } from "@workspace/backend/_generated/api" import { Button } from "@workspace/ui/components/button" -import { add } from "@workspace/math/add" export default function Page() { + const users = useQuery(api.users.getMany) + const addUser = useMutation(api.users.add) return ( -
-
-

Hello apps/web

- -

{add(2, 6)}

+
+

apps/web

+ +
+ {JSON.stringify(users, null, 2)}
) diff --git a/apps/web/components/theme-provider.tsx b/apps/web/components/theme-provider.tsx index 3d44f48..d37aeef 100644 --- a/apps/web/components/theme-provider.tsx +++ b/apps/web/components/theme-provider.tsx @@ -1,24 +1,16 @@ "use client" import * as React from "react" +import { ConvexProvider, ConvexReactClient } from "convex/react" import { ThemeProvider as NextThemesProvider, useTheme } from "next-themes" +const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL || "") + function ThemeProvider({ children, ...props }: React.ComponentProps) { - return ( - - - {children} - - ) + return {children} } function isTypingTarget(target: EventTarget | null) { diff --git a/apps/web/package.json b/apps/web/package.json index 88952fb..3d96e5f 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -12,8 +12,10 @@ "typecheck": "tsc --noEmit" }, "dependencies": { + "@workspace/backend": "workspace:*", "@workspace/math": "workspace:*", "@workspace/ui": "workspace:*", + "convex": "^1.42.0", "lucide-react": "^1.21.0", "next": "16.2.6", "next-themes": "^0.4.6", diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index c4301c3..b58cfa9 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -3,7 +3,8 @@ "compilerOptions": { "paths": { "@/*": ["./*"], - "@workspace/ui/*": ["../../packages/ui/src/*"] + "@workspace/ui/*": ["../../packages/ui/src/*"], + "@workspace/backend/*": ["../../packages/backend/convex/*"] }, "plugins": [ { diff --git a/apps/widget/app/page.tsx b/apps/widget/app/page.tsx index e6733ab..cc1ee97 100644 --- a/apps/widget/app/page.tsx +++ b/apps/widget/app/page.tsx @@ -1,15 +1,19 @@ -import { add } from "@workspace/math/add" +"use client" + +import { useMutation, useQuery } from "convex/react" +import { api } from "@workspace/backend/_generated/api" import { Button } from "@workspace/ui/components/button" -import { Input } from "@workspace/ui/components/input" export default function Page() { + const users = useQuery(api.users.getMany) + const addUser = useMutation(api.users.add) + return ( -
-
-

Hello apps/widget

- -

{add(10, 12)}

- +
+

apps/widget

+ +
+ {JSON.stringify(users, null, 2)}
) diff --git a/apps/widget/components/theme-provider.tsx b/apps/widget/components/theme-provider.tsx index 3d44f48..371ac85 100644 --- a/apps/widget/components/theme-provider.tsx +++ b/apps/widget/components/theme-provider.tsx @@ -2,23 +2,15 @@ import * as React from "react" import { ThemeProvider as NextThemesProvider, useTheme } from "next-themes" +import { ConvexReactClient, ConvexProvider } from "convex/react" + +const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL || "") function ThemeProvider({ children, ...props }: React.ComponentProps) { - return ( - - - {children} - - ) + return {children} } function isTypingTarget(target: EventTarget | null) { diff --git a/apps/widget/package.json b/apps/widget/package.json index aaad8ce..3d8be70 100644 --- a/apps/widget/package.json +++ b/apps/widget/package.json @@ -12,8 +12,10 @@ "typecheck": "tsc --noEmit" }, "dependencies": { + "@workspace/backend": "workspace:*", "@workspace/math": "workspace:*", "@workspace/ui": "workspace:*", + "convex": "^1.42.0", "lucide-react": "^1.21.0", "next": "16.2.6", "next-themes": "^0.4.6", diff --git a/apps/widget/tsconfig.json b/apps/widget/tsconfig.json index c4301c3..b58cfa9 100644 --- a/apps/widget/tsconfig.json +++ b/apps/widget/tsconfig.json @@ -3,7 +3,8 @@ "compilerOptions": { "paths": { "@/*": ["./*"], - "@workspace/ui/*": ["../../packages/ui/src/*"] + "@workspace/ui/*": ["../../packages/ui/src/*"], + "@workspace/backend/*": ["../../packages/backend/convex/*"] }, "plugins": [ { diff --git a/packages/backend/.gitignore b/packages/backend/.gitignore new file mode 100644 index 0000000..8c5fbb9 --- /dev/null +++ b/packages/backend/.gitignore @@ -0,0 +1,2 @@ + +.env.local diff --git a/packages/backend/convex/README.md b/packages/backend/convex/README.md new file mode 100644 index 0000000..91a9db2 --- /dev/null +++ b/packages/backend/convex/README.md @@ -0,0 +1,90 @@ +# Welcome to your Convex functions directory! + +Write your Convex functions here. +See https://docs.convex.dev/functions for more. + +A query function that takes two arguments looks like: + +```ts +// convex/myFunctions.ts +import { query } from "./_generated/server"; +import { v } from "convex/values"; + +export const myQueryFunction = query({ + // Validators for arguments. + args: { + first: v.number(), + second: v.string(), + }, + + // Function implementation. + handler: async (ctx, args) => { + // Read the database as many times as you need here. + // See https://docs.convex.dev/database/reading-data. + const documents = await ctx.db.query("tablename").collect(); + + // Arguments passed from the client are properties of the args object. + console.log(args.first, args.second); + + // Write arbitrary JavaScript here: filter, aggregate, build derived data, + // remove non-public properties, or create new objects. + return documents; + }, +}); +``` + +Using this query function in a React component looks like: + +```ts +const data = useQuery(api.myFunctions.myQueryFunction, { + first: 10, + second: "hello", +}); +``` + +A mutation function looks like: + +```ts +// convex/myFunctions.ts +import { mutation } from "./_generated/server"; +import { v } from "convex/values"; + +export const myMutationFunction = mutation({ + // Validators for arguments. + args: { + first: v.string(), + second: v.string(), + }, + + // Function implementation. + handler: async (ctx, args) => { + // Insert or modify documents in the database here. + // Mutations can also read from the database like queries. + // See https://docs.convex.dev/database/writing-data. + const message = { body: args.first, author: args.second }; + const id = await ctx.db.insert("messages", message); + + // Optionally, return a value from your mutation. + return await ctx.db.get("messages", id); + }, +}); +``` + +Using this mutation function in a React component looks like: + +```ts +const mutation = useMutation(api.myFunctions.myMutationFunction); +function handleButtonPress() { + // fire and forget, the most common way to use mutations + mutation({ first: "Hello!", second: "me" }); + // OR + // use the result once the mutation has completed + mutation({ first: "Hello!", second: "me" }).then((result) => + console.log(result), + ); +} +``` + +Use the Convex CLI to push your functions to a deployment. See everything +the Convex CLI can do by running `npx convex -h` in your project root +directory. To learn more, launch the docs with `npx convex docs`. diff --git a/packages/backend/convex/_generated/api.d.ts b/packages/backend/convex/_generated/api.d.ts new file mode 100644 index 0000000..cc9480e --- /dev/null +++ b/packages/backend/convex/_generated/api.d.ts @@ -0,0 +1,49 @@ +/* eslint-disable */ +/** + * Generated `api` utility. + * + * THIS CODE IS AUTOMATICALLY GENERATED. + * + * To regenerate, run `npx convex dev`. + * @module + */ + +import type * as users from "../users.js"; + +import type { + ApiFromModules, + FilterApi, + FunctionReference, +} from "convex/server"; + +declare const fullApi: ApiFromModules<{ + users: typeof users; +}>; + +/** + * A utility for referencing Convex functions in your app's public API. + * + * Usage: + * ```js + * const myFunctionReference = api.myModule.myFunction; + * ``` + */ +export declare const api: FilterApi< + typeof fullApi, + FunctionReference +>; + +/** + * A utility for referencing Convex functions in your app's internal API. + * + * Usage: + * ```js + * const myFunctionReference = internal.myModule.myFunction; + * ``` + */ +export declare const internal: FilterApi< + typeof fullApi, + FunctionReference +>; + +export declare const components: {}; diff --git a/packages/backend/convex/_generated/api.js b/packages/backend/convex/_generated/api.js new file mode 100644 index 0000000..44bf985 --- /dev/null +++ b/packages/backend/convex/_generated/api.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +/** + * Generated `api` utility. + * + * THIS CODE IS AUTOMATICALLY GENERATED. + * + * To regenerate, run `npx convex dev`. + * @module + */ + +import { anyApi, componentsGeneric } from "convex/server"; + +/** + * A utility for referencing Convex functions in your app's API. + * + * Usage: + * ```js + * const myFunctionReference = api.myModule.myFunction; + * ``` + */ +export const api = anyApi; +export const internal = anyApi; +export const components = componentsGeneric(); diff --git a/packages/backend/convex/_generated/dataModel.d.ts b/packages/backend/convex/_generated/dataModel.d.ts new file mode 100644 index 0000000..f97fd19 --- /dev/null +++ b/packages/backend/convex/_generated/dataModel.d.ts @@ -0,0 +1,60 @@ +/* eslint-disable */ +/** + * Generated data model types. + * + * THIS CODE IS AUTOMATICALLY GENERATED. + * + * To regenerate, run `npx convex dev`. + * @module + */ + +import type { + DataModelFromSchemaDefinition, + DocumentByName, + TableNamesInDataModel, + SystemTableNames, +} from "convex/server"; +import type { GenericId } from "convex/values"; +import schema from "../schema.js"; + +/** + * The names of all of your Convex tables. + */ +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 = DocumentByName< + DataModel, + TableName +>; + +/** + * An identifier for a document in Convex. + * + * Convex documents are uniquely identified by their `Id`, which is accessible + * on the `_id` field. To learn more, see [Document IDs](https://docs.convex.dev/using/document-ids). + * + * Documents can be loaded using `db.get(tableName, id)` in query and mutation functions. + * + * 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 = + GenericId; + +/** + * A type describing your Convex data model. + * + * This type includes information about what tables you have, the type of + * documents stored in those tables, and the indexes defined on them. + * + * This type is used to parameterize methods like `queryGeneric` and + * `mutationGeneric` to make them type-safe. + */ +export type DataModel = DataModelFromSchemaDefinition; diff --git a/packages/backend/convex/_generated/server.d.ts b/packages/backend/convex/_generated/server.d.ts new file mode 100644 index 0000000..bec05e6 --- /dev/null +++ b/packages/backend/convex/_generated/server.d.ts @@ -0,0 +1,143 @@ +/* eslint-disable */ +/** + * Generated utilities for implementing server-side Convex query and mutation functions. + * + * THIS CODE IS AUTOMATICALLY GENERATED. + * + * To regenerate, run `npx convex dev`. + * @module + */ + +import { + ActionBuilder, + HttpActionBuilder, + MutationBuilder, + QueryBuilder, + GenericActionCtx, + GenericMutationCtx, + GenericQueryCtx, + GenericDatabaseReader, + GenericDatabaseWriter, +} from "convex/server"; +import type { DataModel } from "./dataModel.js"; + +/** + * Define a query in this Convex app's public API. + * + * This function will be allowed to read your Convex database and will be accessible from the client. + * + * @param func - The query function. It receives a {@link QueryCtx} as its first argument. + * @returns The wrapped query. Include this as an `export` to name it and make it accessible. + */ +export declare const query: QueryBuilder; + +/** + * Define a query that is only accessible from other Convex functions (but not from the client). + * + * This function will be allowed to read from your Convex database. It will not be accessible from the client. + * + * @param func - The query function. It receives a {@link QueryCtx} as its first argument. + * @returns The wrapped query. Include this as an `export` to name it and make it accessible. + */ +export declare const internalQuery: QueryBuilder; + +/** + * Define a mutation in this Convex app's public API. + * + * This function will be allowed to modify your Convex database and will be accessible from the client. + * + * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. + * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. + */ +export declare const mutation: MutationBuilder; + +/** + * Define a mutation that is only accessible from other Convex functions (but not from the client). + * + * This function will be allowed to modify your Convex database. It will not be accessible from the client. + * + * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. + * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. + */ +export declare const internalMutation: MutationBuilder; + +/** + * Define an action in this Convex app's public API. + * + * An action is a function which can execute any JavaScript code, including non-deterministic + * code and code with side-effects, like calling third-party services. + * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. + * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. + * + * @param func - The action. It receives an {@link ActionCtx} as its first argument. + * @returns The wrapped action. Include this as an `export` to name it and make it accessible. + */ +export declare const action: ActionBuilder; + +/** + * Define an action that is only accessible from other Convex functions (but not from the client). + * + * @param func - The function. It receives an {@link ActionCtx} as its first argument. + * @returns The wrapped function. Include this as an `export` to name it and make it accessible. + */ +export declare const internalAction: ActionBuilder; + +/** + * Define an HTTP action. + * + * The wrapped function will be used to respond to HTTP requests received + * by a Convex deployment if the requests matches the path and method where + * this action is routed. Be sure to route your httpAction in `convex/http.js`. + * + * @param func - The function. It receives an {@link ActionCtx} as its first argument + * and a Fetch API `Request` object as its second. + * @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up. + */ +export declare const httpAction: HttpActionBuilder; + +/** + * A set of services for use within Convex query functions. + * + * The query context is passed as the first argument to any Convex query + * function run on the server. + * + * This differs from the {@link MutationCtx} because all of the services are + * read-only. + */ +export type QueryCtx = GenericQueryCtx; + +/** + * A set of services for use within Convex mutation functions. + * + * The mutation context is passed as the first argument to any Convex mutation + * function run on the server. + */ +export type MutationCtx = GenericMutationCtx; + +/** + * A set of services for use within Convex action functions. + * + * The action context is passed as the first argument to any Convex action + * function run on the server. + */ +export type ActionCtx = GenericActionCtx; + +/** + * An interface to read from the database within Convex query functions. + * + * The two entry points are {@link DatabaseReader.get}, which fetches a single + * document by its {@link Id}, or {@link DatabaseReader.query}, which starts + * building a query. + */ +export type DatabaseReader = GenericDatabaseReader; + +/** + * An interface to read from and write to the database within Convex mutation + * functions. + * + * Convex guarantees that all writes within a single mutation are + * executed atomically, so you never have to worry about partial writes leaving + * your data in an inconsistent state. See [the Convex Guide](https://docs.convex.dev/understanding/convex-fundamentals/functions#atomicity-and-optimistic-concurrency-control) + * for the guarantees Convex provides your functions. + */ +export type DatabaseWriter = GenericDatabaseWriter; diff --git a/packages/backend/convex/_generated/server.js b/packages/backend/convex/_generated/server.js new file mode 100644 index 0000000..bf3d25a --- /dev/null +++ b/packages/backend/convex/_generated/server.js @@ -0,0 +1,93 @@ +/* eslint-disable */ +/** + * Generated utilities for implementing server-side Convex query and mutation functions. + * + * THIS CODE IS AUTOMATICALLY GENERATED. + * + * To regenerate, run `npx convex dev`. + * @module + */ + +import { + actionGeneric, + httpActionGeneric, + queryGeneric, + mutationGeneric, + internalActionGeneric, + internalMutationGeneric, + internalQueryGeneric, +} from "convex/server"; + +/** + * Define a query in this Convex app's public API. + * + * This function will be allowed to read your Convex database and will be accessible from the client. + * + * @param func - The query function. It receives a {@link QueryCtx} as its first argument. + * @returns The wrapped query. Include this as an `export` to name it and make it accessible. + */ +export const query = queryGeneric; + +/** + * Define a query that is only accessible from other Convex functions (but not from the client). + * + * This function will be allowed to read from your Convex database. It will not be accessible from the client. + * + * @param func - The query function. It receives a {@link QueryCtx} as its first argument. + * @returns The wrapped query. Include this as an `export` to name it and make it accessible. + */ +export const internalQuery = internalQueryGeneric; + +/** + * Define a mutation in this Convex app's public API. + * + * This function will be allowed to modify your Convex database and will be accessible from the client. + * + * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. + * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. + */ +export const mutation = mutationGeneric; + +/** + * Define a mutation that is only accessible from other Convex functions (but not from the client). + * + * This function will be allowed to modify your Convex database. It will not be accessible from the client. + * + * @param func - The mutation function. It receives a {@link MutationCtx} as its first argument. + * @returns The wrapped mutation. Include this as an `export` to name it and make it accessible. + */ +export const internalMutation = internalMutationGeneric; + +/** + * Define an action in this Convex app's public API. + * + * An action is a function which can execute any JavaScript code, including non-deterministic + * code and code with side-effects, like calling third-party services. + * They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive. + * They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}. + * + * @param func - The action. It receives an {@link ActionCtx} as its first argument. + * @returns The wrapped action. Include this as an `export` to name it and make it accessible. + */ +export const action = actionGeneric; + +/** + * Define an action that is only accessible from other Convex functions (but not from the client). + * + * @param func - The function. It receives an {@link ActionCtx} as its first argument. + * @returns The wrapped function. Include this as an `export` to name it and make it accessible. + */ +export const internalAction = internalActionGeneric; + +/** + * Define an HTTP action. + * + * The wrapped function will be used to respond to HTTP requests received + * by a Convex deployment if the requests matches the path and method where + * this action is routed. Be sure to route your httpAction in `convex/http.js`. + * + * @param func - The function. It receives an {@link ActionCtx} as its first argument + * and a Fetch API `Request` object as its second. + * @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up. + */ +export const httpAction = httpActionGeneric; diff --git a/packages/backend/convex/schema.ts b/packages/backend/convex/schema.ts new file mode 100644 index 0000000..f721723 --- /dev/null +++ b/packages/backend/convex/schema.ts @@ -0,0 +1,8 @@ +import { defineSchema, defineTable } from "convex/server" +import { v } from "convex/values" + +export default defineSchema({ + users: defineTable({ + name: v.string(), + }), +}) diff --git a/packages/backend/convex/tsconfig.json b/packages/backend/convex/tsconfig.json new file mode 100644 index 0000000..41bfbb9 --- /dev/null +++ b/packages/backend/convex/tsconfig.json @@ -0,0 +1,25 @@ +{ + /* This TypeScript project config describes the environment that + * Convex functions run in and is used to typecheck them. + * You can modify it, but some settings are required to use Convex. + */ + "compilerOptions": { + /* These settings are not required by Convex and can be modified. */ + "allowJs": true, + "strict": true, + "moduleResolution": "Bundler", + "jsx": "react-jsx", + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + + /* These compiler options are required by Convex */ + "target": "ESNext", + "lib": ["ES2023", "dom"], + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "isolatedModules": true, + "noEmit": true + }, + "include": ["./**/*"], + "exclude": ["./_generated"] +} diff --git a/packages/backend/convex/users.ts b/packages/backend/convex/users.ts new file mode 100644 index 0000000..0111a28 --- /dev/null +++ b/packages/backend/convex/users.ts @@ -0,0 +1,21 @@ +import { query, mutation } from "./_generated/server" + +export const getMany = query({ + args: {}, + handler: async (ctx) => { + const users = await ctx.db.query("users").collect() + + return users + }, +}) + +export const add = mutation({ + args: {}, + handler: async (ctx) => { + const userId = await ctx.db.insert("users", { + name: "RISHII", + }) + + return userId + }, +}) diff --git a/packages/backend/package.json b/packages/backend/package.json new file mode 100644 index 0000000..039f871 --- /dev/null +++ b/packages/backend/package.json @@ -0,0 +1,18 @@ +{ + "name": "@workspace/backend", + "type": "module", + "scripts": { + "dev": "convex dev", + "setup": "convex dev --until-success" + }, + "exports": { + "./convex": "./convex/*.ts" + }, + "devDependencies": { + "@workspace/typescript-config": "workspace:*", + "typescript": "latest" + }, + "dependencies": { + "convex": "^1.42.0" + } +} diff --git a/packages/backend/tsconfig.json b/packages/backend/tsconfig.json new file mode 100644 index 0000000..84b35d0 --- /dev/null +++ b/packages/backend/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "@workspace/typescript-config/base.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@workspace/backend/*": ["./convex/*"] + } + }, + "include": ["."], + "exclude": ["node_modules"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 27aaef0..e4f915b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,12 +29,18 @@ importers: apps/web: dependencies: + '@workspace/backend': + specifier: workspace:* + version: link:../../packages/backend '@workspace/math': specifier: workspace:* version: link:../../packages/math '@workspace/ui': specifier: workspace:* version: link:../../packages/ui + convex: + specifier: ^1.42.0 + version: 1.42.0(react@19.2.4) lucide-react: specifier: ^1.21.0 version: 1.21.0(react@19.2.4) @@ -78,12 +84,18 @@ importers: apps/widget: dependencies: + '@workspace/backend': + specifier: workspace:* + version: link:../../packages/backend '@workspace/math': specifier: workspace:* version: link:../../packages/math '@workspace/ui': specifier: workspace:* version: link:../../packages/ui + convex: + specifier: ^1.42.0 + version: 1.42.0(react@19.2.4) lucide-react: specifier: ^1.21.0 version: 1.21.0(react@19.2.4) @@ -125,6 +137,19 @@ importers: specifier: ^5 version: 5.9.3 + packages/backend: + dependencies: + convex: + specifier: ^1.42.0 + version: 1.42.0(react@19.2.4) + devDependencies: + '@workspace/typescript-config': + specifier: workspace:* + version: link:../typescript-config + typescript: + specifier: latest + version: 6.0.3 + packages/eslint-config: devDependencies: '@eslint/js': @@ -427,156 +452,312 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.27.0': + resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.25.12': resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} engines: {node: '>=18'} cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.27.0': + resolution: {integrity: sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.25.12': resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} engines: {node: '>=18'} cpu: [arm] os: [android] + '@esbuild/android-arm@0.27.0': + resolution: {integrity: sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.25.12': resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} engines: {node: '>=18'} cpu: [x64] os: [android] + '@esbuild/android-x64@0.27.0': + resolution: {integrity: sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.25.12': resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.27.0': + resolution: {integrity: sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.25.12': resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.27.0': + resolution: {integrity: sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.25.12': resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.27.0': + resolution: {integrity: sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.12': resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.27.0': + resolution: {integrity: sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.25.12': resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} engines: {node: '>=18'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.27.0': + resolution: {integrity: sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.25.12': resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} engines: {node: '>=18'} cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.27.0': + resolution: {integrity: sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.25.12': resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.27.0': + resolution: {integrity: sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.25.12': resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} engines: {node: '>=18'} cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.27.0': + resolution: {integrity: sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.25.12': resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.27.0': + resolution: {integrity: sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.25.12': resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.27.0': + resolution: {integrity: sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.25.12': resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.27.0': + resolution: {integrity: sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.25.12': resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.27.0': + resolution: {integrity: sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.25.12': resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.27.0': + resolution: {integrity: sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.12': resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.27.0': + resolution: {integrity: sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.12': resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.27.0': + resolution: {integrity: sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.12': resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.27.0': + resolution: {integrity: sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.12': resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.27.0': + resolution: {integrity: sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openharmony-arm64@0.25.12': resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] + '@esbuild/openharmony-arm64@0.27.0': + resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.25.12': resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} engines: {node: '>=18'} cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.27.0': + resolution: {integrity: sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.25.12': resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.27.0': + resolution: {integrity: sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.25.12': resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.27.0': + resolution: {integrity: sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.25.12': resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} engines: {node: '>=18'} cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.27.0': + resolution: {integrity: sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1488,6 +1669,25 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + convex@1.42.0: + resolution: {integrity: sha512-KS1U+YkE7N7jDfucPW28iNehnb9/N5n9RJmdAFNdPIHTeNpbLKNqk1pJHp4ajHyMBAhGmri8Z4S1lc1LjliZWQ==} + engines: {node: '>=18.0.0', npm: '>=7.0.0'} + hasBin: true + peerDependencies: + '@auth0/auth0-react': ^2.0.1 + '@clerk/clerk-react': ^4.12.8 || ^5.0.0 + '@clerk/react': ^6.4.3 + react: ^18.0.0 || ^19.0.0-0 || ^19.0.0 + peerDependenciesMeta: + '@auth0/auth0-react': + optional: true + '@clerk/clerk-react': + optional: true + '@clerk/react': + optional: true + react: + optional: true + cookie-signature@1.2.2: resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} engines: {node: '>=6.6.0'} @@ -1685,6 +1885,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.27.0: + resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -3216,6 +3421,18 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + wsl-utils@0.3.1: resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} engines: {node: '>=20'} @@ -3500,81 +3717,159 @@ snapshots: '@esbuild/aix-ppc64@0.25.12': optional: true + '@esbuild/aix-ppc64@0.27.0': + optional: true + '@esbuild/android-arm64@0.25.12': optional: true + '@esbuild/android-arm64@0.27.0': + optional: true + '@esbuild/android-arm@0.25.12': optional: true + '@esbuild/android-arm@0.27.0': + optional: true + '@esbuild/android-x64@0.25.12': optional: true + '@esbuild/android-x64@0.27.0': + optional: true + '@esbuild/darwin-arm64@0.25.12': optional: true + '@esbuild/darwin-arm64@0.27.0': + optional: true + '@esbuild/darwin-x64@0.25.12': optional: true + '@esbuild/darwin-x64@0.27.0': + optional: true + '@esbuild/freebsd-arm64@0.25.12': optional: true + '@esbuild/freebsd-arm64@0.27.0': + optional: true + '@esbuild/freebsd-x64@0.25.12': optional: true + '@esbuild/freebsd-x64@0.27.0': + optional: true + '@esbuild/linux-arm64@0.25.12': optional: true + '@esbuild/linux-arm64@0.27.0': + optional: true + '@esbuild/linux-arm@0.25.12': optional: true + '@esbuild/linux-arm@0.27.0': + optional: true + '@esbuild/linux-ia32@0.25.12': optional: true + '@esbuild/linux-ia32@0.27.0': + optional: true + '@esbuild/linux-loong64@0.25.12': optional: true + '@esbuild/linux-loong64@0.27.0': + optional: true + '@esbuild/linux-mips64el@0.25.12': optional: true + '@esbuild/linux-mips64el@0.27.0': + optional: true + '@esbuild/linux-ppc64@0.25.12': optional: true + '@esbuild/linux-ppc64@0.27.0': + optional: true + '@esbuild/linux-riscv64@0.25.12': optional: true + '@esbuild/linux-riscv64@0.27.0': + optional: true + '@esbuild/linux-s390x@0.25.12': optional: true + '@esbuild/linux-s390x@0.27.0': + optional: true + '@esbuild/linux-x64@0.25.12': optional: true + '@esbuild/linux-x64@0.27.0': + optional: true + '@esbuild/netbsd-arm64@0.25.12': optional: true + '@esbuild/netbsd-arm64@0.27.0': + optional: true + '@esbuild/netbsd-x64@0.25.12': optional: true + '@esbuild/netbsd-x64@0.27.0': + optional: true + '@esbuild/openbsd-arm64@0.25.12': optional: true + '@esbuild/openbsd-arm64@0.27.0': + optional: true + '@esbuild/openbsd-x64@0.25.12': optional: true + '@esbuild/openbsd-x64@0.27.0': + optional: true + '@esbuild/openharmony-arm64@0.25.12': optional: true + '@esbuild/openharmony-arm64@0.27.0': + optional: true + '@esbuild/sunos-x64@0.25.12': optional: true + '@esbuild/sunos-x64@0.27.0': + optional: true + '@esbuild/win32-arm64@0.25.12': optional: true + '@esbuild/win32-arm64@0.27.0': + optional: true + '@esbuild/win32-ia32@0.25.12': optional: true + '@esbuild/win32-ia32@0.27.0': + optional: true + '@esbuild/win32-x64@0.25.12': optional: true + '@esbuild/win32-x64@0.27.0': + optional: true + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.7.0))': dependencies: eslint: 9.39.4(jiti@2.7.0) @@ -4422,6 +4717,17 @@ snapshots: convert-source-map@2.0.0: {} + convex@1.42.0(react@19.2.4): + dependencies: + esbuild: 0.27.0 + prettier: 3.8.3 + ws: 8.21.0 + optionalDependencies: + react: 19.2.4 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + cookie-signature@1.2.2: {} cookie@0.7.2: {} @@ -4685,6 +4991,35 @@ snapshots: '@esbuild/win32-ia32': 0.25.12 '@esbuild/win32-x64': 0.25.12 + esbuild@0.27.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.0 + '@esbuild/android-arm': 0.27.0 + '@esbuild/android-arm64': 0.27.0 + '@esbuild/android-x64': 0.27.0 + '@esbuild/darwin-arm64': 0.27.0 + '@esbuild/darwin-x64': 0.27.0 + '@esbuild/freebsd-arm64': 0.27.0 + '@esbuild/freebsd-x64': 0.27.0 + '@esbuild/linux-arm': 0.27.0 + '@esbuild/linux-arm64': 0.27.0 + '@esbuild/linux-ia32': 0.27.0 + '@esbuild/linux-loong64': 0.27.0 + '@esbuild/linux-mips64el': 0.27.0 + '@esbuild/linux-ppc64': 0.27.0 + '@esbuild/linux-riscv64': 0.27.0 + '@esbuild/linux-s390x': 0.27.0 + '@esbuild/linux-x64': 0.27.0 + '@esbuild/netbsd-arm64': 0.27.0 + '@esbuild/netbsd-x64': 0.27.0 + '@esbuild/openbsd-arm64': 0.27.0 + '@esbuild/openbsd-x64': 0.27.0 + '@esbuild/openharmony-arm64': 0.27.0 + '@esbuild/sunos-x64': 0.27.0 + '@esbuild/win32-arm64': 0.27.0 + '@esbuild/win32-ia32': 0.27.0 + '@esbuild/win32-x64': 0.27.0 + escalade@3.2.0: {} escape-html@1.0.3: {} @@ -6304,6 +6639,8 @@ snapshots: wrappy@1.0.2: {} + ws@8.21.0: {} + wsl-utils@0.3.1: dependencies: is-wsl: 3.1.1