diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf506ef..70697ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,3 +43,7 @@ jobs: - name: Build Project run: pnpm run build + env: + NEXT_PUBLIC_CONVEX_URL: "https://insightful-pheasant-237.convex.cloud" + NEXT_PUBLIC_CONVEX_SITE_URL: "https://insightful-pheasant-237.convex.site" + NEXT_PUBLIC_SITE_URL: "http://localhost:3000" diff --git a/app/(shared-layout)/test/page.tsx b/app/(shared-layout)/test/page.tsx new file mode 100644 index 0000000..43b9f74 --- /dev/null +++ b/app/(shared-layout)/test/page.tsx @@ -0,0 +1,15 @@ +"use client"; + +import { api } from "@/convex/_generated/api"; +import { useQuery } from "convex/react"; + +export default function Page() { + const tasks = useQuery(api.tasks.get); + return ( +
+ {tasks?.map(({ _id, text }) => ( +
{text}
+ ))} +
+ ); +} diff --git a/app/api/auth/[...all]/route.ts b/app/api/auth/[...all]/route.ts new file mode 100644 index 0000000..8d7e031 --- /dev/null +++ b/app/api/auth/[...all]/route.ts @@ -0,0 +1,3 @@ +import { handler } from "@/lib/auth-server"; + +export const { GET, POST } = handler; diff --git a/app/auth/sign-up/page.tsx b/app/auth/sign-up/page.tsx index f99cb57..97dcc0f 100644 --- a/app/auth/sign-up/page.tsx +++ b/app/auth/sign-up/page.tsx @@ -19,6 +19,7 @@ import { FieldLabel, } from "@/components/ui/field"; import { Button } from "@/components/ui/button"; +import { authClient } from "@/lib/auth-client"; export default function SignupPage() { const form = useForm>({ @@ -31,8 +32,12 @@ export default function SignupPage() { }, }); - const onSubmit = () => { - console.log("yoo"); + const onSubmit = async (data: z.infer) => { + await authClient.signUp.email({ + email: data.email, + name: data.name, + password: data.password, + }); }; return ( diff --git a/app/layout.tsx b/app/layout.tsx index bf63635..11c5617 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -3,6 +3,7 @@ import React from "react"; import { Outfit, Geist_Mono } from "next/font/google"; import "./globals.css"; import { ThemeProvider } from "@/components/ui/theme-provider"; +import { ConvexClientProvider } from "../components/web/ConvexClientProvider"; const outfit = Outfit({ variable: "--font-sans", @@ -35,7 +36,7 @@ export default function RootLayout({ disableTransitionOnChange >
- {children} + {children}
diff --git a/components/web/ConvexClientProvider.tsx b/components/web/ConvexClientProvider.tsx new file mode 100644 index 0000000..0b33aca --- /dev/null +++ b/components/web/ConvexClientProvider.tsx @@ -0,0 +1,26 @@ +"use client"; + +import { ReactNode } from "react"; +import { ConvexReactClient } from "convex/react"; +import { authClient } from "@/lib/auth-client"; +import { ConvexBetterAuthProvider } from "@convex-dev/better-auth/react"; + +const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!); + +export function ConvexClientProvider({ + children, + initialToken, +}: { + children: ReactNode; + initialToken?: string | null; +}) { + return ( + + {children} + + ); +} diff --git a/components/web/navbar.tsx b/components/web/navbar.tsx index 574ee04..a99ed3f 100644 --- a/components/web/navbar.tsx +++ b/components/web/navbar.tsx @@ -1,8 +1,13 @@ +"use client"; + import Link from "next/link"; -import { buttonVariants } from "@/components/ui/button"; +import { Button, buttonVariants } from "@/components/ui/button"; import { ThemeToggle } from "@/components/ui/theme-toggle"; +import { useConvexAuth } from "convex/react"; +import { authClient } from "@/lib/auth-client"; export default function Navbar() { + const { isAuthenticated, isLoading } = useConvexAuth(); return ( diff --git a/convex/_generated/api.d.ts b/convex/_generated/api.d.ts index 5abfa11..a2fd81c 100644 --- a/convex/_generated/api.d.ts +++ b/convex/_generated/api.d.ts @@ -8,13 +8,21 @@ * @module */ +import type * as auth from "../auth.js"; +import type * as http from "../http.js"; +import type * as tasks from "../tasks.js"; + import type { ApiFromModules, FilterApi, FunctionReference, } from "convex/server"; -declare const fullApi: ApiFromModules<{}>; +declare const fullApi: ApiFromModules<{ + auth: typeof auth; + http: typeof http; + tasks: typeof tasks; +}>; /** * A utility for referencing Convex functions in your app's public API. @@ -42,4 +50,6 @@ export declare const internal: FilterApi< FunctionReference >; -export declare const components: {}; +export declare const components: { + betterAuth: import("@convex-dev/better-auth/_generated/component.js").ComponentApi<"betterAuth">; +}; diff --git a/convex/auth.config.ts b/convex/auth.config.ts new file mode 100644 index 0000000..a2851b4 --- /dev/null +++ b/convex/auth.config.ts @@ -0,0 +1,6 @@ +import { getAuthConfigProvider } from "@convex-dev/better-auth/auth-config"; +import type { AuthConfig } from "convex/server"; + +export default { + providers: [getAuthConfigProvider()], +} satisfies AuthConfig; diff --git a/convex/auth.ts b/convex/auth.ts new file mode 100644 index 0000000..44c2f34 --- /dev/null +++ b/convex/auth.ts @@ -0,0 +1,38 @@ +import { createClient, type GenericCtx } from "@convex-dev/better-auth"; +import { convex } from "@convex-dev/better-auth/plugins"; +import { components } from "./_generated/api"; +import { DataModel } from "./_generated/dataModel"; +import { query } from "./_generated/server"; +import { betterAuth } from "better-auth/minimal"; +import authConfig from "./auth.config"; + +const siteUrl = process.env.SITE_URL!; + +// The component client has methods needed for integrating Convex with Better Auth, +// as well as helper methods for general use. +export const authComponent = createClient(components.betterAuth); + +export const createAuth = (ctx: GenericCtx) => { + return betterAuth({ + baseURL: siteUrl, + database: authComponent.adapter(ctx), + // Configure simple, non-verified email/password to get started + emailAndPassword: { + enabled: true, + requireEmailVerification: false, + }, + plugins: [ + // The Convex plugin is required for Convex compatibility + convex({ authConfig }), + ], + }); +}; + +// Example function for getting the current user +// Feel free to edit, omit, etc. +export const getCurrentUser = query({ + args: {}, + handler: async (ctx) => { + return authComponent.getAuthUser(ctx); + }, +}); diff --git a/convex/convex.config.ts b/convex/convex.config.ts new file mode 100644 index 0000000..23cabb0 --- /dev/null +++ b/convex/convex.config.ts @@ -0,0 +1,7 @@ +import { defineApp } from "convex/server"; +import betterAuth from "@convex-dev/better-auth/convex.config"; + +const app = defineApp(); +app.use(betterAuth); + +export default app; diff --git a/convex/http.ts b/convex/http.ts new file mode 100644 index 0000000..bcd0024 --- /dev/null +++ b/convex/http.ts @@ -0,0 +1,8 @@ +import { httpRouter } from "convex/server"; +import { authComponent, createAuth } from "./auth"; + +const http = httpRouter(); + +authComponent.registerRoutes(http, createAuth); + +export default http; diff --git a/convex/tasks.ts b/convex/tasks.ts new file mode 100644 index 0000000..3db81bc --- /dev/null +++ b/convex/tasks.ts @@ -0,0 +1,8 @@ +import { query } from "./_generated/server"; + +export const get = query({ + args: {}, + handler: async (ctx) => { + return await ctx.db.query("tasks").collect(); + }, +}); diff --git a/lib/auth-client.ts b/lib/auth-client.ts new file mode 100644 index 0000000..6588328 --- /dev/null +++ b/lib/auth-client.ts @@ -0,0 +1,6 @@ +import { createAuthClient } from "better-auth/react"; +import { convexClient } from "@convex-dev/better-auth/client/plugins"; + +export const authClient = createAuthClient({ + plugins: [convexClient()], +}); diff --git a/lib/auth-server.ts b/lib/auth-server.ts new file mode 100644 index 0000000..038a6fb --- /dev/null +++ b/lib/auth-server.ts @@ -0,0 +1,14 @@ +import { convexBetterAuthNextJs } from "@convex-dev/better-auth/nextjs"; + +export const { + handler, + preloadAuthQuery, + isAuthenticated, + getToken, + fetchAuthQuery, + fetchAuthMutation, + fetchAuthAction, +} = convexBetterAuthNextJs({ + convexUrl: process.env.NEXT_PUBLIC_CONVEX_URL!, + convexSiteUrl: process.env.NEXT_PUBLIC_CONVEX_SITE_URL!, +}); diff --git a/package.json b/package.json index 328c574..4e30d02 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,9 @@ "format:check": "prettier --check ." }, "dependencies": { + "@convex-dev/better-auth": "^0.11.4", "@hookform/resolvers": "^5.2.2", + "better-auth": "1.5.3", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "convex": "^1.35.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 922ac33..c606e28 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,9 +7,15 @@ settings: importers: .: dependencies: + "@convex-dev/better-auth": + specifier: ^0.11.4 + version: 0.11.4(@standard-schema/spec@1.1.0)(better-auth@1.5.3(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(convex@1.35.1(react@19.2.4))(hono@4.12.9)(react@19.2.4)(typescript@5.9.3) "@hookform/resolvers": specifier: ^5.2.2 version: 5.2.2(react-hook-form@7.72.1(react@19.2.4)) + better-auth: + specifier: 1.5.3 + version: 1.5.3(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -24,7 +30,7 @@ importers: version: 1.7.0(react@19.2.4) next: specifier: 16.2.1 - version: 16.2.1(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + version: 16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -302,6 +308,72 @@ packages: } engines: { node: ">=6.9.0" } + "@better-auth/core@1.5.3": + resolution: + { + integrity: sha512-fORsQjNZ6BQ7o96xMe7elz3Y4Y8DsqXmQrdyzt289G9rmzX4auwBCPTtE2cXTRTYGiVvH9bv0b97t1Uo/OWynQ==, + } + peerDependencies: + "@better-auth/utils": 0.3.1 + "@better-fetch/fetch": 1.1.21 + "@cloudflare/workers-types": ">=4" + better-call: 1.3.2 + jose: ^6.1.0 + kysely: ^0.28.5 + nanostores: ^1.0.1 + peerDependenciesMeta: + "@cloudflare/workers-types": + optional: true + + "@better-auth/kysely-adapter@1.5.3": + resolution: + { + integrity: sha512-eAm1KPrlPXkH/qXUXnGBcHPDgCX153b6BSlc2QJ2IeqmiWym9D/6XORqBIZOl71JiP0Cifzocr2GLpnz0gt31Q==, + } + peerDependencies: + "@better-auth/core": 1.5.3 + "@better-auth/utils": ^0.3.0 + kysely: ^0.27.0 || ^0.28.0 + + "@better-auth/memory-adapter@1.5.3": + resolution: + { + integrity: sha512-QdeTI3bvUmaPkHsjcSMfroXyuGsgnxobv7wZVl57e+ox6yQVR1j4VKbqmCILP6PL6Rr2gpcBH/liHr8v5gqY5Q==, + } + peerDependencies: + "@better-auth/core": 1.5.3 + "@better-auth/utils": ^0.3.0 + + "@better-auth/telemetry@1.5.3": + resolution: + { + integrity: sha512-ZX/r8AsWdB6BwH+Rb7H/SyJnGtPN6EDWrNxBQEDsqRrBJVcDLwAIz165P57RXci0WwtY872T0guKq+XVyy5rkA==, + } + peerDependencies: + "@better-auth/core": 1.5.3 + + "@better-auth/utils@0.3.1": + resolution: + { + integrity: sha512-+CGp4UmZSUrHHnpHhLPYu6cV+wSUSvVbZbNykxhUDocpVNTo9uFFxw/NqJlh1iC4wQ9HKKWGCKuZ5wUgS0v6Kg==, + } + + "@better-fetch/fetch@1.1.21": + resolution: + { + integrity: sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A==, + } + + "@convex-dev/better-auth@0.11.4": + resolution: + { + integrity: sha512-CsRsM7UaQgQKH1mt4z64QOZUfrhZKNsspkpWjlhqLiIz5THfnM2vaSVMQ3GOddcUvw7AgkNCNR3u8C8HjLQEMA==, + } + peerDependencies: + better-auth: ">=1.5.0 <1.6.0" + convex: ^1.25.0 + react: ^18.3.1 || ^19.0.0 + "@dotenvx/dotenvx@1.58.0": resolution: { @@ -1137,6 +1209,13 @@ packages: } engines: { node: ^14.21.3 || >=16 } + "@noble/ciphers@2.2.0": + resolution: + { + integrity: sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA==, + } + engines: { node: ">= 20.19.0" } + "@noble/curves@1.9.7": resolution: { @@ -1151,6 +1230,13 @@ packages: } engines: { node: ^14.21.3 || >=16 } + "@noble/hashes@2.2.0": + resolution: + { + integrity: sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==, + } + engines: { node: ">= 20.19.0" } + "@nodelib/fs.scandir@2.1.5": resolution: { @@ -1197,6 +1283,13 @@ packages: integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==, } + "@opentelemetry/api@1.9.1": + resolution: + { + integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==, + } + engines: { node: ">=8.0.0" } + "@radix-ui/number@1.1.1": resolution: { @@ -2086,6 +2179,12 @@ packages: } engines: { node: ">=18" } + "@standard-schema/spec@1.1.0": + resolution: + { + integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==, + } + "@standard-schema/utils@0.3.0": resolution: { @@ -2758,6 +2857,91 @@ packages: engines: { node: ">=6.0.0" } hasBin: true + better-auth@1.5.3: + resolution: + { + integrity: sha512-E+9kA9GMX1+gT3FfMCqRz0NufT4X/+tNhpOsHW1jLmyPZKinkHtfZkUffSBnG5qGkvfBaH/slT5c1fKttnmF5w==, + } + peerDependencies: + "@better-auth/drizzle-adapter": 1.5.3 + "@better-auth/mongo-adapter": 1.5.3 + "@better-auth/prisma-adapter": 1.5.3 + "@lynx-js/react": "*" + "@prisma/client": ^5.0.0 || ^6.0.0 || ^7.0.0 + "@sveltejs/kit": ^2.0.0 + "@tanstack/react-start": ^1.0.0 + "@tanstack/solid-start": ^1.0.0 + better-sqlite3: ^12.0.0 + drizzle-kit: ">=0.31.4" + drizzle-orm: ">=0.41.0" + mongodb: ^6.0.0 || ^7.0.0 + mysql2: ^3.0.0 + next: ^14.0.0 || ^15.0.0 || ^16.0.0 + pg: ^8.0.0 + prisma: ^5.0.0 || ^6.0.0 || ^7.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + solid-js: ^1.0.0 + svelte: ^4.0.0 || ^5.0.0 + vitest: ^2.0.0 || ^3.0.0 || ^4.0.0 + vue: ^3.0.0 + peerDependenciesMeta: + "@better-auth/drizzle-adapter": + optional: true + "@better-auth/mongo-adapter": + optional: true + "@better-auth/prisma-adapter": + optional: true + "@lynx-js/react": + optional: true + "@prisma/client": + optional: true + "@sveltejs/kit": + optional: true + "@tanstack/react-start": + optional: true + "@tanstack/solid-start": + optional: true + better-sqlite3: + optional: true + drizzle-kit: + optional: true + drizzle-orm: + optional: true + mongodb: + optional: true + mysql2: + optional: true + next: + optional: true + pg: + optional: true + prisma: + optional: true + react: + optional: true + react-dom: + optional: true + solid-js: + optional: true + svelte: + optional: true + vitest: + optional: true + vue: + optional: true + + better-call@1.3.2: + resolution: + { + integrity: sha512-4cZIfrerDsNTn3cm+MhLbUePN0gdwkhSXEuG7r/zuQ8c/H7iU0/jSK5TD3FW7U0MgKHce/8jGpPYNO4Ve+4NBw==, + } + peerDependencies: + zod: ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + body-parser@2.2.2: resolution: { @@ -2935,6 +3119,13 @@ packages: } engines: { node: ">=20" } + common-tags@1.8.2: + resolution: + { + integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==, + } + engines: { node: ">=4.0.0" } + concat-map@0.0.1: resolution: { @@ -2961,6 +3152,31 @@ packages: integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, } + convex-helpers@0.1.114: + resolution: + { + integrity: sha512-elEdh+gG6BDv2dWIWVvBeJPbHnDQS5+WexUuwlGVJXz1EbMkXz/UIQwFIfLMZIXUwW6ot4JYf/1JJKNStrE6lg==, + } + hasBin: true + peerDependencies: + "@standard-schema/spec": ^1.0.0 + convex: ^1.32.0 + hono: ^4.0.5 + react: ^17.0.2 || ^18.0.0 || ^19.0.0 + typescript: ^5.5 + 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.35.1: resolution: { @@ -3160,6 +3376,12 @@ packages: } engines: { node: ">= 0.4" } + defu@6.1.7: + resolution: + { + integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==, + } + depd@2.0.0: resolution: { @@ -4497,6 +4719,13 @@ packages: } engines: { node: ">=6" } + kysely@0.28.16: + resolution: + { + integrity: sha512-3i5pmOiZvMDj00qhrIVbH0AnioVTx22DMP7Vn5At4yJO46iy+FM8Y/g61ltenLVSo3fiO8h8Q3QOFgf/gQ72ww==, + } + engines: { node: ">=20.0.0" } + language-subtag-registry@0.3.23: resolution: { @@ -4802,6 +5031,13 @@ packages: engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } hasBin: true + nanostores@1.3.0: + resolution: + { + integrity: sha512-XPUa/jz+P1oJvN9VBxw4L9MtdFfaH3DAryqPssqhb2kXjmb9npz0dly6rCsgFWOPr4Yg9mTfM3MDZgZZ+7A3lA==, + } + engines: { node: ^20.0.0 || >=22.0.0 } + napi-postinstall@0.3.4: resolution: { @@ -5353,6 +5589,12 @@ packages: } engines: { node: ">= 0.4" } + remeda@2.33.7: + resolution: + { + integrity: sha512-cXlyjevWx5AcslOUEETG4o8XYi9UkoCXcJmj7XhPFVbla+ITuOBxv6ijBrmbeg+ZhzmDThkNdO+iXKUfrJep1w==, + } + require-directory@2.1.1: resolution: { @@ -5416,6 +5658,12 @@ packages: } engines: { iojs: ">=1.0.0", node: ">=0.10.0" } + rou3@0.7.12: + resolution: + { + integrity: sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg==, + } + router@2.2.0: resolution: { @@ -5498,6 +5746,12 @@ packages: } engines: { node: ">= 18" } + set-cookie-parser@3.1.0: + resolution: + { + integrity: sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==, + } + set-function-length@1.2.2: resolution: { @@ -5901,6 +6155,13 @@ packages: } engines: { node: ">= 0.8.0" } + type-fest@4.41.0: + resolution: + { + integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==, + } + engines: { node: ">=16" } + type-fest@5.5.0: resolution: { @@ -6442,6 +6703,56 @@ snapshots: "@babel/helper-string-parser": 7.27.1 "@babel/helper-validator-identifier": 7.28.5 + "@better-auth/core@1.5.3(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.16)(nanostores@1.3.0)": + dependencies: + "@better-auth/utils": 0.3.1 + "@better-fetch/fetch": 1.1.21 + "@standard-schema/spec": 1.1.0 + better-call: 1.3.2(zod@4.3.6) + jose: 6.2.2 + kysely: 0.28.16 + nanostores: 1.3.0 + zod: 4.3.6 + + "@better-auth/kysely-adapter@1.5.3(@better-auth/core@1.5.3(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.3.1)(kysely@0.28.16)": + dependencies: + "@better-auth/core": 1.5.3(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.16)(nanostores@1.3.0) + "@better-auth/utils": 0.3.1 + kysely: 0.28.16 + + "@better-auth/memory-adapter@1.5.3(@better-auth/core@1.5.3(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.3.1)": + dependencies: + "@better-auth/core": 1.5.3(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.16)(nanostores@1.3.0) + "@better-auth/utils": 0.3.1 + + "@better-auth/telemetry@1.5.3(@better-auth/core@1.5.3(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.16)(nanostores@1.3.0))": + dependencies: + "@better-auth/core": 1.5.3(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.16)(nanostores@1.3.0) + "@better-auth/utils": 0.3.1 + "@better-fetch/fetch": 1.1.21 + + "@better-auth/utils@0.3.1": {} + + "@better-fetch/fetch@1.1.21": {} + + "@convex-dev/better-auth@0.11.4(@standard-schema/spec@1.1.0)(better-auth@1.5.3(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(convex@1.35.1(react@19.2.4))(hono@4.12.9)(react@19.2.4)(typescript@5.9.3)": + dependencies: + "@better-fetch/fetch": 1.1.21 + better-auth: 1.5.3(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + common-tags: 1.8.2 + convex: 1.35.1(react@19.2.4) + convex-helpers: 0.1.114(@standard-schema/spec@1.1.0)(convex@1.35.1(react@19.2.4))(hono@4.12.9)(react@19.2.4)(typescript@5.9.3)(zod@4.3.6) + jose: 6.2.2 + react: 19.2.4 + remeda: 2.33.7 + semver: 7.7.4 + type-fest: 4.41.0 + zod: 4.3.6 + transitivePeerDependencies: + - "@standard-schema/spec" + - hono + - typescript + "@dotenvx/dotenvx@1.58.0": dependencies: commander: 11.1.0 @@ -6849,12 +7160,16 @@ snapshots: "@noble/ciphers@1.3.0": {} + "@noble/ciphers@2.2.0": {} + "@noble/curves@1.9.7": dependencies: "@noble/hashes": 1.8.0 "@noble/hashes@1.8.0": {} + "@noble/hashes@2.2.0": {} + "@nodelib/fs.scandir@2.1.5": dependencies: "@nodelib/fs.stat": 2.0.5 @@ -6878,6 +7193,9 @@ snapshots: "@open-draft/until@2.1.0": {} + "@opentelemetry/api@1.9.1": + optional: true + "@radix-ui/number@1.1.1": {} "@radix-ui/primitive@1.1.3": {} @@ -7631,6 +7949,8 @@ snapshots: "@sindresorhus/merge-streams@4.0.0": {} + "@standard-schema/spec@1.1.0": {} + "@standard-schema/utils@0.3.0": {} "@swc/helpers@0.5.15": @@ -8025,6 +8345,38 @@ snapshots: baseline-browser-mapping@2.10.11: {} + better-auth@1.5.3(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + "@better-auth/core": 1.5.3(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.16)(nanostores@1.3.0) + "@better-auth/kysely-adapter": 1.5.3(@better-auth/core@1.5.3(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.3.1)(kysely@0.28.16) + "@better-auth/memory-adapter": 1.5.3(@better-auth/core@1.5.3(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.16)(nanostores@1.3.0))(@better-auth/utils@0.3.1) + "@better-auth/telemetry": 1.5.3(@better-auth/core@1.5.3(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.2(zod@4.3.6))(jose@6.2.2)(kysely@0.28.16)(nanostores@1.3.0)) + "@better-auth/utils": 0.3.1 + "@better-fetch/fetch": 1.1.21 + "@noble/ciphers": 2.2.0 + "@noble/hashes": 2.2.0 + better-call: 1.3.2(zod@4.3.6) + defu: 6.1.7 + jose: 6.2.2 + kysely: 0.28.16 + nanostores: 1.3.0 + zod: 4.3.6 + optionalDependencies: + next: 16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + transitivePeerDependencies: + - "@cloudflare/workers-types" + + better-call@1.3.2(zod@4.3.6): + dependencies: + "@better-auth/utils": 0.3.1 + "@better-fetch/fetch": 1.1.21 + rou3: 0.7.12 + set-cookie-parser: 3.1.0 + optionalDependencies: + zod: 4.3.6 + body-parser@2.2.2: dependencies: bytes: 3.1.2 @@ -8128,6 +8480,8 @@ snapshots: commander@14.0.3: {} + common-tags@1.8.2: {} + concat-map@0.0.1: {} content-disposition@1.0.1: {} @@ -8136,6 +8490,16 @@ snapshots: convert-source-map@2.0.0: {} + convex-helpers@0.1.114(@standard-schema/spec@1.1.0)(convex@1.35.1(react@19.2.4))(hono@4.12.9)(react@19.2.4)(typescript@5.9.3)(zod@4.3.6): + dependencies: + convex: 1.35.1(react@19.2.4) + optionalDependencies: + "@standard-schema/spec": 1.1.0 + hono: 4.12.9 + react: 19.2.4 + typescript: 5.9.3 + zod: 4.3.6 + convex@1.35.1(react@19.2.4): dependencies: esbuild: 0.27.0 @@ -8234,6 +8598,8 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 + defu@6.1.7: {} + depd@2.0.0: {} detect-libc@2.1.2: {} @@ -9168,6 +9534,8 @@ snapshots: kleur@4.1.5: {} + kysely@0.28.16: {} + language-subtag-registry@0.3.23: {} language-tags@1.0.9: @@ -9323,6 +9691,8 @@ snapshots: nanoid@3.3.11: {} + nanostores@1.3.0: {} + napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} @@ -9334,7 +9704,7 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - next@16.2.1(@babel/core@7.29.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): dependencies: "@next/env": 16.2.1 "@swc/helpers": 0.5.15 @@ -9353,6 +9723,7 @@ snapshots: "@next/swc-linux-x64-musl": 16.2.1 "@next/swc-win32-arm64-msvc": 16.2.1 "@next/swc-win32-x64-msvc": 16.2.1 + "@opentelemetry/api": 1.9.1 sharp: 0.34.5 transitivePeerDependencies: - "@babel/core" @@ -9720,6 +10091,8 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 + remeda@2.33.7: {} + require-directory@2.1.1: {} require-from-string@2.0.2: {} @@ -9752,6 +10125,8 @@ snapshots: reusify@1.1.0: {} + rou3@0.7.12: {} + router@2.2.0: dependencies: debug: 4.4.3 @@ -9820,6 +10195,8 @@ snapshots: transitivePeerDependencies: - supports-color + set-cookie-parser@3.1.0: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -10134,6 +10511,8 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-fest@4.41.0: {} + type-fest@5.5.0: dependencies: tagged-tag: 1.0.0 diff --git a/sampleData.jsonl b/sampleData.jsonl new file mode 100644 index 0000000..737408e --- /dev/null +++ b/sampleData.jsonl @@ -0,0 +1,3 @@ +{"text": "Buy groceries", "isCompleted": true} +{"text": "Go for a swim", "isCompleted": true} +{"text": "Integrate Convex", "isCompleted": false} \ No newline at end of file