diff --git a/apps/docs/src/app/layout.tsx b/apps/docs/src/app/layout.tsx index bac3d67..9aa410b 100644 --- a/apps/docs/src/app/layout.tsx +++ b/apps/docs/src/app/layout.tsx @@ -26,6 +26,7 @@ export default function Layout({ children }: { children: ReactNode }) { + diff --git a/bun.lock b/bun.lock index 1e864df..5aee274 100644 --- a/bun.lock +++ b/bun.lock @@ -110,7 +110,6 @@ "vitest": "^2.1.8", }, "peerDependencies": { - "better-auth": "^1.2.3", "convex": "^1.17.4", "typescript": "^5.7.2", }, @@ -177,7 +176,7 @@ }, "packages/libraries/tests": { "name": "@better-auth-kit/tests", - "version": "0.1.6", + "version": "0.2.0", "dependencies": { "better-auth": "^1.2.4", "react": "^19.0.0", @@ -230,7 +229,7 @@ }, "packages/plugins/legal-consent": { "name": "@better-auth-kit/legal-consent", - "version": "1.1.0", + "version": "1.1.1", "devDependencies": { "@better-auth-kit/internal-build": "workspace:*", "@better-auth-kit/tests": "workspace:*", @@ -2314,6 +2313,8 @@ "@better-auth-kit/tests/vitest": ["vitest@3.1.3", "", { "dependencies": { "@vitest/expect": "3.1.3", "@vitest/mocker": "3.1.3", "@vitest/pretty-format": "^3.1.3", "@vitest/runner": "3.1.3", "@vitest/snapshot": "3.1.3", "@vitest/spy": "3.1.3", "@vitest/utils": "3.1.3", "chai": "^5.2.0", "debug": "^4.4.0", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.13", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", "vite-node": "3.1.3", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.1.3", "@vitest/ui": "3.1.3", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-188iM4hAHQ0km23TN/adso1q5hhwKqUpv+Sd6p5sOuh6FhQnRNW3IsiIpvxqahtBabsJ2SLZgmGSpcYK4wQYJw=="], + "@better-auth-kit/waitlist/zod": ["zod@3.24.4", "", {}, "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg=="], + "@changesets/apply-release-plan/fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], "@changesets/apply-release-plan/prettier": ["prettier@2.8.8", "", { "bin": { "prettier": "bin-prettier.js" } }, "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q=="], @@ -2438,6 +2439,8 @@ "docs/better-sqlite3": ["better-sqlite3@11.10.0", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ=="], + "docs/zod": ["zod@3.24.4", "", {}, "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg=="], + "enquirer/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], diff --git a/packages/adapters/convex/convex/_generated/api.d.ts b/packages/adapters/convex/convex/_generated/api.d.ts index b6e704f..f75e484 100644 --- a/packages/adapters/convex/convex/_generated/api.d.ts +++ b/packages/adapters/convex/convex/_generated/api.d.ts @@ -9,9 +9,9 @@ */ import type { - ApiFromModules, - FilterApi, - FunctionReference, + ApiFromModules, + FilterApi, + FunctionReference, } from "convex/server"; import type * as betterAuth from "../betterAuth.js"; import type * as tests from "../tests.js"; @@ -25,14 +25,14 @@ import type * as tests from "../tests.js"; * ``` */ declare const fullApi: ApiFromModules<{ - betterAuth: typeof betterAuth; - tests: typeof tests; + betterAuth: typeof betterAuth; + tests: typeof tests; }>; export declare const api: FilterApi< - typeof fullApi, - FunctionReference + typeof fullApi, + FunctionReference >; export declare const internal: FilterApi< - typeof fullApi, - FunctionReference + typeof fullApi, + FunctionReference >; diff --git a/packages/adapters/convex/convex/_generated/dataModel.d.ts b/packages/adapters/convex/convex/_generated/dataModel.d.ts index 672c086..8541f31 100644 --- a/packages/adapters/convex/convex/_generated/dataModel.d.ts +++ b/packages/adapters/convex/convex/_generated/dataModel.d.ts @@ -9,13 +9,13 @@ */ import type { - DataModelFromSchemaDefinition, - DocumentByName, - TableNamesInDataModel, - SystemTableNames, + DataModelFromSchemaDefinition, + DocumentByName, + TableNamesInDataModel, + SystemTableNames, } from "convex/server"; import type { GenericId } from "convex/values"; -import type schema from "../schema.js"; +import schema from "../schema.js"; /** * The names of all of your Convex tables. @@ -28,8 +28,8 @@ export type TableNames = TableNamesInDataModel; * @typeParam TableName - A string literal type of the table name (like "users"). */ export type Doc = DocumentByName< - DataModel, - TableName + DataModel, + TableName >; /** @@ -46,7 +46,7 @@ export type Doc = DocumentByName< * @typeParam TableName - A string literal type of the table name (like "users"). */ export type Id = - GenericId; + GenericId; /** * A type describing your Convex data model. diff --git a/packages/adapters/convex/convex/_generated/server.d.ts b/packages/adapters/convex/convex/_generated/server.d.ts index f3bce1e..7f337a4 100644 --- a/packages/adapters/convex/convex/_generated/server.d.ts +++ b/packages/adapters/convex/convex/_generated/server.d.ts @@ -8,16 +8,16 @@ * @module */ -import type { - ActionBuilder, - HttpActionBuilder, - MutationBuilder, - QueryBuilder, - GenericActionCtx, - GenericMutationCtx, - GenericQueryCtx, - GenericDatabaseReader, - GenericDatabaseWriter, +import { + ActionBuilder, + HttpActionBuilder, + MutationBuilder, + QueryBuilder, + GenericActionCtx, + GenericMutationCtx, + GenericQueryCtx, + GenericDatabaseReader, + GenericDatabaseWriter, } from "convex/server"; import type { DataModel } from "./dataModel.js"; diff --git a/packages/adapters/convex/convex/_generated/server.js b/packages/adapters/convex/convex/_generated/server.js index 8bee25b..566d485 100644 --- a/packages/adapters/convex/convex/_generated/server.js +++ b/packages/adapters/convex/convex/_generated/server.js @@ -9,13 +9,13 @@ */ import { - actionGeneric, - httpActionGeneric, - queryGeneric, - mutationGeneric, - internalActionGeneric, - internalMutationGeneric, - internalQueryGeneric, + actionGeneric, + httpActionGeneric, + queryGeneric, + mutationGeneric, + internalActionGeneric, + internalMutationGeneric, + internalQueryGeneric, } from "convex/server"; /** diff --git a/packages/adapters/convex/package.json b/packages/adapters/convex/package.json index 116a5f6..496862b 100644 --- a/packages/adapters/convex/package.json +++ b/packages/adapters/convex/package.json @@ -46,7 +46,6 @@ "@better-auth-kit/internal-build": "workspace:*" }, "peerDependencies": { - "better-auth": "^1.2.3", "convex": "^1.17.4", "typescript": "^5.7.2" }, diff --git a/packages/adapters/convex/src/index.ts b/packages/adapters/convex/src/index.ts index 742dc2b..4e0814e 100644 --- a/packages/adapters/convex/src/index.ts +++ b/packages/adapters/convex/src/index.ts @@ -1,318 +1,347 @@ import type { ConvexHttpClient } from "convex/browser"; -import type { Adapter, AdapterInstance, BetterAuthOptions } from "better-auth"; +import type { Adapter, BetterAuthOptions, Where } from "better-auth"; +import { createAdapter } from "better-auth/adapters"; import type { ConvexAdapterOptions } from "./types"; -import { createTransform } from "./transform"; import { queryBuilder } from "./handler/index"; import type { PaginationResult } from "convex/server"; +import { countDb, deleteDb, insertDb, updateDb } from "./handler/calls"; +import { queryDb } from "./handler/calls"; -export type ConvexAdapter = ( - convexClient: ConvexHttpClient, - config?: ConvexAdapterOptions, -) => AdapterInstance; +export type ConvexAdapter = { + convexClient: ConvexHttpClient; + config?: ConvexAdapterOptions; +}; -export const convexAdapter: ConvexAdapter = (client, config = {}) => { - function debugLog(message: any[]) { - if (config.enable_debug_logs) { - console.log(`[convex-adapter]`, ...message); - } - } +type DbInsert = { + action: "insert"; + tableName: string; + values: Record; +}; - return (options: BetterAuthOptions): Adapter => { - const { - transformInput, - filterInvalidOperators, - db, - transformOutput, - transformWhereOperators, - } = createTransform({ - config, - options, - client, - }); +type DbQuery = { + action: "query"; + tableName: string; + query?: string; + order?: "asc" | "desc"; + single?: boolean; + limit?: number; + paginationOpts?: { numItems: number; cursor?: string }; +}; - return { - id: "convex", - create: async ({ data: values, model, select }) => { - const start = Date.now(); - debugLog(["create", { model, values, select }]); - const transformed = transformInput(values, model, "create"); +type DbDelete = { + action: "delete"; + tableName: string; + query: string; + deleteAll?: boolean; +}; - const res = await db({ - action: "insert", - tableName: model, - values: transformed, - }); - let result: Record | null = null; +type DbUpdate = { + action: "update"; + tableName: string; + query: string; + update: Record; +}; - if (!select || select.length === 0) result = res; - else { - result = {}; - for (const key of select) { - result[key] = res[key]; - } +type DbCount = { + action: "count"; + tableName: string; + query?: string; +}; + +export const convexAdapter = ( + client: ConvexHttpClient, + config?: ConvexAdapterOptions, +) => + createAdapter({ + config: { + adapterId: "convex", + adapterName: "Convex Adapter", + supportsJSON: false, + debugLogs: config?.debugLogs, + supportsDates: false, + }, + adapter: ({}) => { + function filterInvalidOperators(where: Where[] | undefined): void { + if (!where) return; + const invalidOps = ["contains", "starts_with", "ends_with"]; + if ( + where.filter((w) => invalidOps.includes(w.operator || "")).length > 0 + ) { + throw new Error( + `Convex does not support ${invalidOps.join(", ")} operators`, + ); } - result = result ? (transformOutput(result, model) as any) : result; - debugLog([ - "create result", - { result, duration: `${Date.now() - start}ms` }, - ]); - return result as any; - }, - findOne: async ({ model, where, select }) => { - const start = Date.now(); - filterInvalidOperators(where); - where = transformWhereOperators(where); - debugLog(["findOne", { model, where, select }]); - const res = await db({ - action: "query", - tableName: model, - query: queryBuilder((q) => { - const eqs = where.map((w) => q.eq(w.field, w.value)); - return eqs.reduce((acc, cur, indx) => - q[ - (where[indx - 1].connector || "AND").toLowerCase() as - | "and" - | "or" - ](acc, cur), - ); - }), - single: true, - }); + } - let result: Record | null = null; + function transformWhereOperators(where: Where[] | undefined): Where[] { + if (!where) return []; + const new_where: Where[] = []; - if (!select || select.length === 0) result = res; - else { - result = {}; - for (const key of select) { - result[key] = res[key]; + for (const w of where) { + if (w.operator === "in") { + (w.value as []).forEach((v, i) => { + new_where.push({ + field: w.field, + value: v, + operator: "eq", + connector: i < (w.value as []).length - 1 ? "OR" : undefined, + }); + }); + } else { + new_where.push(w); } } - result = result ? (transformOutput(result, model) as any) : result; - debugLog([ - "findOne result", - { result, duration: `${Date.now() - start}ms` }, - ]); - return result as any; - }, - findMany: async ({ model, where, limit, offset, sortBy }) => { - const start = Date.now(); - filterInvalidOperators(where); - where = transformWhereOperators(where); - debugLog(["findMany", { model, where, limit, offset, sortBy }]); - const queryString = - where && where.length > 0 - ? queryBuilder((q) => { - const eqs = where.map((w) => - //@ts-ignore - q[w.operator || "eq"](w.field, w.value), - ); - if (eqs.length === 1) return eqs[0]; - return eqs.reduce((acc, cur, indx) => - q[ - (where[indx - 1].connector || "AND").toLowerCase() as - | "and" - | "or" - ](acc, cur), - ); - }) - : null; - debugLog(["findMany queryString", { queryString }]); - if (typeof offset === "number") { - let continueCursor = undefined; - let isDone = false; + return new_where; + } + + async function db( + options: DbInsert | DbQuery | DbDelete | DbUpdate | DbCount, + ) { + if (options.action === "query") { + return await queryDb(client, { + tableName: options.tableName, + order: options.order, + query: options.query, + single: options.single, + limit: options.limit, + paginationOpts: options.paginationOpts, + }); + } + if (options.action === "insert") { + return await insertDb(client, { + tableName: options.tableName, + values: options.values, + }); + } + if (options.action === "delete") { + return await deleteDb(client, { + tableName: options.tableName, + query: options.query, + deleteAll: options.deleteAll, + }); + } + if (options.action === "update") { + return await updateDb(client, { + tableName: options.tableName, + query: options.query, + update: options.update, + }); + } + if (options.action === "count") { + return await countDb(client, { + tableName: options.tableName, + query: options.query, + }); + } + return ""; + } + + return { + async create({ data, model, select }) { + const res = await db({ + action: "insert", + tableName: model, + values: data, + }); + return res; + }, + async findOne({ model, where, select }) { + const res = await db({ + action: "query", + tableName: model, + query: queryBuilder((q) => { + const eqs = where.map((w) => q.eq(w.field, w.value)); + return eqs.reduce((acc, cur, indx) => + q[ + (where[indx - 1].connector || "AND").toLowerCase() as + | "and" + | "or" + ](acc, cur), + ); + }), + single: true, + }); + return res; + }, + async findMany({ model, where: where_, limit, offset, sortBy }) { + filterInvalidOperators(where_); + const where = transformWhereOperators(where_); + + const queryString = + where && where.length > 0 + ? queryBuilder((q) => { + const eqs = where.map((w) => + //@ts-ignore + q[w.operator || "eq"](w.field, w.value), + ); + if (eqs.length === 1) return eqs[0]; + return eqs.reduce((acc, cur, indx) => + q[ + (where[indx - 1].connector || "AND").toLowerCase() as + | "and" + | "or" + ](acc, cur), + ); + }) + : null; + if (typeof offset === "number") { + let continueCursor = undefined; + let isDone = false; - const results = []; + const results = []; - while (!isDone) { - const opts = (await db({ + while (!isDone) { + const opts = (await db({ + action: "query", + tableName: model, + query: queryString ?? undefined, + order: sortBy?.direction, + single: false, + limit: limit, + paginationOpts: { + numItems: 100, + cursor: continueCursor, + }, + })) as PaginationResult; + continueCursor = opts.continueCursor; + results.push(...opts.page); + if (results.length >= offset + (limit || 1)) { + isDone = true; + const result = limit + ? results.slice(offset, offset + limit) + : results.slice(offset); + + return result; + } + } + } else { + const res = await db({ action: "query", tableName: model, - query: queryString ?? undefined, + query: queryString ? queryString : undefined, order: sortBy?.direction, single: false, limit: limit, - paginationOpts: { - numItems: 100, - cursor: continueCursor, - }, - })) as PaginationResult; - continueCursor = opts.continueCursor; - results.push(...opts.page); - debugLog(["findMany paginated page", { page: opts.page }]); - if (results.length >= offset + (limit || 1)) { - isDone = true; - const result = ( - limit - ? results.slice(offset, offset + limit) - : results.slice(offset) - ).map((x) => transformOutput(x, model)); - debugLog([ - "findMany pagination done", - { result, duration: `${Date.now() - start}ms` }, - ]); - return result; - } + }); + return res; } - } else { + }, + async update({ model, where: where_, update }) { + filterInvalidOperators(where_); + const where = transformWhereOperators(where_); + console.log(update, where); const res = await db({ - action: "query", + action: "update", tableName: model, - query: queryString ? queryString : undefined, - order: sortBy?.direction, - single: false, - limit: limit, + query: queryBuilder((q) => { + const eqs = where.map((w) => + //@ts-ignore + q[w.operator || "eq"](w.field, w.value), + ); + return eqs.reduce((acc, cur, indx) => + q[ + (where[indx - 1].connector || "AND").toLowerCase() as + | "and" + | "or" + ](acc, cur), + ); + }), + update: update as any, }); - const result = res.map((x: any) => transformOutput(x, model)); - debugLog([ - "findMany result", - { result, duration: `${Date.now() - start}ms` }, - ]); - return result; - } - }, - update: async ({ model, where, update }) => { - const start = Date.now(); - filterInvalidOperators(where); - where = transformWhereOperators(where); - debugLog(["update", { model, where, update }]); - - const transformed = transformInput(update, model, "update"); - const res = await db({ - action: "update", - tableName: model, - query: queryBuilder((q) => { - const eqs = where.map((w) => - //@ts-ignore - q[w.operator || "eq"](w.field, w.value), - ); - return eqs.reduce((acc, cur, indx) => - q[ - (where[indx - 1].connector || "AND").toLowerCase() as - | "and" - | "or" - ](acc, cur), - ); - }), - update: transformed, - }); - const result = transformOutput(res, model) as any; - debugLog([ - "update result", - { result, duration: `${Date.now() - start}ms` }, - ]); - return result; - }, - updateMany: async ({ model, where, update }) => { - const start = Date.now(); - filterInvalidOperators(where); - where = transformWhereOperators(where); - debugLog(["updateMany", { model, where, update }]); - - const transformed = transformInput(update, model, "update"); - const res = await db({ - action: "update", - tableName: model, - query: queryBuilder((q) => { - const eqs = where.map((w) => - //@ts-ignore - q[w.operator || "eq"](w.field, w.value), - ); - return eqs.reduce((acc, cur, indx) => - q[ - (where[indx - 1].connector || "AND").toLowerCase() as - | "and" - | "or" - ](acc, cur), - ); - }), - update: transformed, - }); - const result = transformOutput(res, model) as any; - debugLog([ - "updateMany result", - { result, duration: `${Date.now() - start}ms` }, - ]); - return result; - }, - delete: async ({ model, where }) => { - const start = Date.now(); - filterInvalidOperators(where); - where = transformWhereOperators(where); - debugLog(["delete", { model, where }]); - - await db({ - action: "delete", - tableName: model, - query: queryBuilder((q) => { - const eqs = where.map((w) => - //@ts-ignore - q[w.operator || "eq"](w.field, w.value), - ); - return eqs.reduce((acc, cur, indx) => - q[ - (where[indx - 1].connector || "AND").toLowerCase() as - | "and" - | "or" - ](acc, cur), - ); - }), - }); - debugLog(["delete complete", { duration: `${Date.now() - start}ms` }]); - return; - }, - deleteMany: async ({ model, where }) => { - const start = Date.now(); - filterInvalidOperators(where); - where = transformWhereOperators(where); - debugLog(["deleteMany", { model, where }]); - - const res = await db({ - action: "delete", - tableName: model, - deleteAll: true, - query: queryBuilder((q) => { - const eqs = where.map((w) => - //@ts-ignore - q[w.operator || "eq"](w.field, w.value), - ); - return eqs.reduce((acc, cur, indx) => - q[ - (where[indx - 1].connector || "AND").toLowerCase() as - | "and" - | "or" - ](acc, cur), - ); - }), - }); - debugLog([ - "deleteMany result", - { result: res, duration: `${Date.now() - start}ms` }, - ]); - return res as number; - }, - count: async ({ model, where }) => { - const res = await db({ - action: "count", - tableName: model, - query: queryBuilder((q) => { - if (!where) return ""; - const eqs = where.map((w) => - //@ts-ignore - q[w.operator || "eq"](w.field, w.value), - ); - return eqs.reduce((acc, cur, indx) => - q[ - (where[indx - 1].connector || "AND").toLowerCase() as - | "and" - | "or" - ](acc, cur), - ); - }), - }); - return res; - }, - }; - }; -}; + console.log(`Result:`, res); + return res; + }, + async updateMany({ model, where: where_, update }) { + filterInvalidOperators(where_); + const where = transformWhereOperators(where_); + const res = await db({ + action: "update", + tableName: model, + query: queryBuilder((q) => { + const eqs = where.map((w) => + //@ts-ignore + q[w.operator || "eq"](w.field, w.value), + ); + return eqs.reduce((acc, cur, indx) => + q[ + (where[indx - 1].connector || "AND").toLowerCase() as + | "and" + | "or" + ](acc, cur), + ); + }), + update: update as any, + }); + return res; + }, + async delete({ model, where: where_ }) { + filterInvalidOperators(where_); + const where = transformWhereOperators(where_); + const res = await db({ + action: "delete", + tableName: model, + query: queryBuilder((q) => { + const eqs = where.map((w) => + //@ts-ignore + q[w.operator || "eq"](w.field, w.value), + ); + return eqs.reduce((acc, cur, indx) => + q[ + (where[indx - 1].connector || "AND").toLowerCase() as + | "and" + | "or" + ](acc, cur), + ); + }), + }); + return res; + }, + async deleteMany({ model, where: where_ }) { + filterInvalidOperators(where_); + const where = transformWhereOperators(where_); + const res = await db({ + action: "delete", + tableName: model, + query: queryBuilder((q) => { + const eqs = where.map((w) => + //@ts-ignore + q[w.operator || "eq"](w.field, w.value), + ); + return eqs.reduce((acc, cur, indx) => + q[ + (where[indx - 1].connector || "AND").toLowerCase() as + | "and" + | "or" + ](acc, cur), + ); + }), + deleteAll: true, + }); + return res; + }, + async count({ model, where: where_ }) { + filterInvalidOperators(where_); + const where = transformWhereOperators(where_); + const res = await db({ + action: "count", + tableName: model, + query: queryBuilder((q) => { + const eqs = where.map((w) => + //@ts-ignore + q[w.operator || "eq"](w.field, w.value), + ); + return eqs.reduce((acc, cur, indx) => + q[ + (where[indx - 1].connector || "AND").toLowerCase() as + | "and" + | "or" + ](acc, cur), + ); + }), + }); + return res; + }, + }; + }, + }); diff --git a/packages/adapters/convex/src/transform/index.ts b/packages/adapters/convex/src/transform/index.ts index 87c872a..e144b1d 100644 --- a/packages/adapters/convex/src/transform/index.ts +++ b/packages/adapters/convex/src/transform/index.ts @@ -27,6 +27,9 @@ export const createTransform = ({ const new_where: Where[] = []; for (const w of where) { + if (w.field === "id") { + w.field = "_id"; + } if (w.operator === "in") { (w.value as []).forEach((v, i) => { new_where.push({ diff --git a/packages/adapters/convex/src/types.ts b/packages/adapters/convex/src/types.ts index ebf980f..9901d01 100644 --- a/packages/adapters/convex/src/types.ts +++ b/packages/adapters/convex/src/types.ts @@ -3,12 +3,13 @@ import type { MutationBuilder, QueryBuilder, } from "convex/server"; +import type { AdapterDebugLogs } from "better-auth/adapters"; export type ConvexQuery = QueryBuilder; export type ConvexAdapterOptions = { convex_dir_path?: string; - enable_debug_logs?: boolean; + debugLogs?: AdapterDebugLogs; }; export type ConvexMutation = MutationBuilder; diff --git a/packages/adapters/convex/test/adapter.test.ts b/packages/adapters/convex/test/adapter.test.ts index cffc1b9..f282db1 100644 --- a/packages/adapters/convex/test/adapter.test.ts +++ b/packages/adapters/convex/test/adapter.test.ts @@ -4,12 +4,12 @@ import * as dotenv from "dotenv"; dotenv.config({ path: ".env.local" }); import { convexAdapter } from "./../src/index"; import { runAdapterTest } from "better-auth/adapters/test"; -import { ConvexClient } from "convex/browser"; +import { ConvexHttpClient } from "convex/browser"; import { api } from "./../convex/_generated/api.js"; describe("Handle Convex Adapter", async () => { it("should successfully add the Convex Adapter", async () => { - const client = new ConvexClient(process.env.CONVEX_URL as string); + const client = new ConvexHttpClient(process.env.CONVEX_URL as string); const auth = betterAuth({ database: convexAdapter(client), @@ -22,7 +22,7 @@ describe("Handle Convex Adapter", async () => { }); describe("Run BetterAuth Adapter tests", async () => { - const client = new ConvexClient(process.env.CONVEX_URL as string); + const client = new ConvexHttpClient(process.env.CONVEX_URL as string); beforeAll(async () => { await client.mutation(api.tests.removeAll, {}); @@ -31,13 +31,38 @@ describe("Run BetterAuth Adapter tests", async () => { await client.mutation(api.tests.removeAll, {}); }); - const adapter = convexAdapter(client); + const adapter = convexAdapter(client, { + debugLogs: { isRunningAdapterTests: true }, + }); await runAdapterTest({ getAdapter: async (customOptions = {}) => { return adapter({ ...customOptions }); }, - skipGenerateIdTest: true, + disableTests: { + CREATE_MODEL_SHOULD_ALWAYS_RETURN_AN_ID: false, + DELETE_MODEL: true, + FIND_MODEL: true, + FIND_MODEL_WITH_MODIFIED_FIELD_NAME: true, + FIND_MODEL_WITH_SELECT: true, + FIND_MODEL_WITHOUT_ID: true, + SHOULD_DELETE_MANY: true, + SHOULD_FIND_MANY: true, + SHOULD_FIND_MANY_WITH_CONTAINS_OPERATOR: true, + SHOULD_FIND_MANY_WITH_LIMIT: true, + SHOULD_FIND_MANY_WITH_OFFSET: true, + SHOULD_FIND_MANY_WITH_SORT_BY: true, + SHOULD_FIND_MANY_WITH_WHERE: true, + SHOULD_FIND_MANY_WITH_OPERATORS: true, + SHOULD_NOT_THROW_ON_DELETE_RECORD_NOT_FOUND: true, + SHOULD_NOT_THROW_ON_RECORD_NOT_FOUND: true, + SHOULD_PREFER_GENERATE_ID_IF_PROVIDED: true, + SHOULD_SEARCH_USERS_WITH_ENDS_WITH: true, + SHOULD_SEARCH_USERS_WITH_STARTS_WITH: true, + SHOULD_UPDATE_WITH_MULTIPLE_WHERE: true, + SHOULD_WORK_WITH_REFERENCE_FIELDS: true, + // UPDATE_MODEL: true, + }, }); test("should find many with offset and limit", async () => { // At this point, `user` contains 8 rows. @@ -74,7 +99,7 @@ describe("Authentication Flow Tests", async () => { password: "password", name: "Test Name", }; - const client = new ConvexClient(process.env.CONVEX_URL as string); + const client = new ConvexHttpClient(process.env.CONVEX_URL as string); beforeAll(async () => { await client.mutation(api.tests.removeAll, {}); @@ -93,11 +118,13 @@ describe("Authentication Flow Tests", async () => { it("should successfully sign up a new user", async () => { const user = await auth.api.signUpEmail({ body: testUser }); + console.log(user, testUser); expect(user).toBeDefined(); }); it("should successfully sign in an existing user", async () => { await new Promise((resolve) => setTimeout(resolve, 2000)); + console.log(testUser); const user = await auth.api.signInEmail({ body: testUser }); expect(user.user).toBeDefined(); }); diff --git a/packages/adapters/convex/test/test.ts b/packages/adapters/convex/test/test.ts index a8fe2f5..0f3179f 100644 --- a/packages/adapters/convex/test/test.ts +++ b/packages/adapters/convex/test/test.ts @@ -6,7 +6,7 @@ import { ConvexHttpClient } from "convex/browser"; const client = new ConvexHttpClient(process.env.CONVEX_URL!); export const auth = betterAuth({ - database: convexAdapter(client, { enable_debug_logs: true }), + database: convexAdapter(client, { debugLogs: true }), plugins: [], //... other options }); diff --git a/packages/plugins/legal-consent/tests/test.db b/packages/plugins/legal-consent/tests/test.db index 11af24f..09fb395 100644 Binary files a/packages/plugins/legal-consent/tests/test.db and b/packages/plugins/legal-consent/tests/test.db differ diff --git a/packages/plugins/reverify/tests/test.db b/packages/plugins/reverify/tests/test.db index 7ac765c..b7cf69d 100644 Binary files a/packages/plugins/reverify/tests/test.db and b/packages/plugins/reverify/tests/test.db differ