refactor: migrate betterauth to local install

also added a login page

Co-authored-by: Ona <no-reply@ona.com>
This commit is contained in:
2025-10-05 23:25:20 +00:00
parent f7bc5fd958
commit bf2087cded
23 changed files with 1951 additions and 2376 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
const authConfig = {
export default {
providers: [
{
domain: process.env.CONVEX_SITE_URL,
@@ -6,5 +6,3 @@ const authConfig = {
},
],
}
export default authConfig

View File

@@ -3,26 +3,33 @@ import { convex, crossDomain } from "@convex-dev/better-auth/plugins"
import { betterAuth } from "better-auth"
import { components } from "./_generated/api"
import type { DataModel } from "./_generated/dataModel"
import authSchema from "./betterauth/schema"
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<DataModel>(components.betterAuth, {
triggers: {
user: {
onCreate: async (ctx, user) => {
const now = Date.now()
await ctx.db.insert("directories", {
name: "",
userId: user._id,
createdAt: now,
updatedAt: now,
})
export const authComponent = createClient<DataModel, typeof authSchema>(
components.betterAuth,
{
local: {
schema: authSchema,
},
triggers: {
user: {
onCreate: async (ctx, user) => {
const now = Date.now()
await ctx.db.insert("directories", {
name: "",
userId: user._id,
createdAt: now,
updatedAt: now,
})
},
},
},
},
})
)
export const createAuth = (
ctx: GenericCtx<DataModel>,

View File

@@ -0,0 +1,971 @@
/* eslint-disable */
/**
* Generated `api` utility.
*
* THIS CODE IS AUTOMATICALLY GENERATED.
*
* To regenerate, run `npx convex dev`.
* @module
*/
import type * as adapter from "../adapter.js";
import type * as auth from "../auth.js";
import type {
ApiFromModules,
FilterApi,
FunctionReference,
} from "convex/server";
/**
* A utility for referencing Convex functions in your app's API.
*
* Usage:
* ```js
* const myFunctionReference = api.myModule.myFunction;
* ```
*/
declare const fullApi: ApiFromModules<{
adapter: typeof adapter;
auth: typeof auth;
}>;
export type Mounts = {
adapter: {
create: FunctionReference<
"mutation",
"public",
{
input:
| {
data: {
createdAt: number;
email: string;
emailVerified: boolean;
image?: null | string;
name: string;
updatedAt: number;
userId?: null | string;
};
model: "user";
}
| {
data: {
createdAt: number;
expiresAt: number;
ipAddress?: null | string;
token: string;
updatedAt: number;
userAgent?: null | string;
userId: string;
};
model: "session";
}
| {
data: {
accessToken?: null | string;
accessTokenExpiresAt?: null | number;
accountId: string;
createdAt: number;
idToken?: null | string;
password?: null | string;
providerId: string;
refreshToken?: null | string;
refreshTokenExpiresAt?: null | number;
scope?: null | string;
updatedAt: number;
userId: string;
};
model: "account";
}
| {
data: {
createdAt: number;
expiresAt: number;
identifier: string;
updatedAt: number;
value: string;
};
model: "verification";
}
| {
data: {
createdAt: number;
privateKey: string;
publicKey: string;
};
model: "jwks";
};
onCreateHandle?: string;
select?: Array<string>;
},
any
>;
deleteMany: FunctionReference<
"mutation",
"public",
{
input:
| {
model: "user";
where?: Array<{
connector?: "AND" | "OR";
field:
| "name"
| "email"
| "emailVerified"
| "image"
| "createdAt"
| "updatedAt"
| "userId"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "session";
where?: Array<{
connector?: "AND" | "OR";
field:
| "expiresAt"
| "token"
| "createdAt"
| "updatedAt"
| "ipAddress"
| "userAgent"
| "userId"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "account";
where?: Array<{
connector?: "AND" | "OR";
field:
| "accountId"
| "providerId"
| "userId"
| "accessToken"
| "refreshToken"
| "idToken"
| "accessTokenExpiresAt"
| "refreshTokenExpiresAt"
| "scope"
| "password"
| "createdAt"
| "updatedAt"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "verification";
where?: Array<{
connector?: "AND" | "OR";
field:
| "identifier"
| "value"
| "expiresAt"
| "createdAt"
| "updatedAt"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "jwks";
where?: Array<{
connector?: "AND" | "OR";
field: "publicKey" | "privateKey" | "createdAt" | "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
};
onDeleteHandle?: string;
paginationOpts: {
cursor: string | null;
endCursor?: string | null;
id?: number;
maximumBytesRead?: number;
maximumRowsRead?: number;
numItems: number;
};
},
any
>;
deleteOne: FunctionReference<
"mutation",
"public",
{
input:
| {
model: "user";
where?: Array<{
connector?: "AND" | "OR";
field:
| "name"
| "email"
| "emailVerified"
| "image"
| "createdAt"
| "updatedAt"
| "userId"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "session";
where?: Array<{
connector?: "AND" | "OR";
field:
| "expiresAt"
| "token"
| "createdAt"
| "updatedAt"
| "ipAddress"
| "userAgent"
| "userId"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "account";
where?: Array<{
connector?: "AND" | "OR";
field:
| "accountId"
| "providerId"
| "userId"
| "accessToken"
| "refreshToken"
| "idToken"
| "accessTokenExpiresAt"
| "refreshTokenExpiresAt"
| "scope"
| "password"
| "createdAt"
| "updatedAt"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "verification";
where?: Array<{
connector?: "AND" | "OR";
field:
| "identifier"
| "value"
| "expiresAt"
| "createdAt"
| "updatedAt"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "jwks";
where?: Array<{
connector?: "AND" | "OR";
field: "publicKey" | "privateKey" | "createdAt" | "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
};
onDeleteHandle?: string;
},
any
>;
findMany: FunctionReference<
"query",
"public",
{
limit?: number;
model: "user" | "session" | "account" | "verification" | "jwks";
offset?: number;
paginationOpts: {
cursor: string | null;
endCursor?: string | null;
id?: number;
maximumBytesRead?: number;
maximumRowsRead?: number;
numItems: number;
};
sortBy?: { direction: "asc" | "desc"; field: string };
where?: Array<{
connector?: "AND" | "OR";
field: string;
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
},
any
>;
findOne: FunctionReference<
"query",
"public",
{
model: "user" | "session" | "account" | "verification" | "jwks";
select?: Array<string>;
where?: Array<{
connector?: "AND" | "OR";
field: string;
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
},
any
>;
updateMany: FunctionReference<
"mutation",
"public",
{
input:
| {
model: "user";
update: {
createdAt?: number;
email?: string;
emailVerified?: boolean;
image?: null | string;
name?: string;
updatedAt?: number;
userId?: null | string;
};
where?: Array<{
connector?: "AND" | "OR";
field:
| "name"
| "email"
| "emailVerified"
| "image"
| "createdAt"
| "updatedAt"
| "userId"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "session";
update: {
createdAt?: number;
expiresAt?: number;
ipAddress?: null | string;
token?: string;
updatedAt?: number;
userAgent?: null | string;
userId?: string;
};
where?: Array<{
connector?: "AND" | "OR";
field:
| "expiresAt"
| "token"
| "createdAt"
| "updatedAt"
| "ipAddress"
| "userAgent"
| "userId"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "account";
update: {
accessToken?: null | string;
accessTokenExpiresAt?: null | number;
accountId?: string;
createdAt?: number;
idToken?: null | string;
password?: null | string;
providerId?: string;
refreshToken?: null | string;
refreshTokenExpiresAt?: null | number;
scope?: null | string;
updatedAt?: number;
userId?: string;
};
where?: Array<{
connector?: "AND" | "OR";
field:
| "accountId"
| "providerId"
| "userId"
| "accessToken"
| "refreshToken"
| "idToken"
| "accessTokenExpiresAt"
| "refreshTokenExpiresAt"
| "scope"
| "password"
| "createdAt"
| "updatedAt"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "verification";
update: {
createdAt?: number;
expiresAt?: number;
identifier?: string;
updatedAt?: number;
value?: string;
};
where?: Array<{
connector?: "AND" | "OR";
field:
| "identifier"
| "value"
| "expiresAt"
| "createdAt"
| "updatedAt"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "jwks";
update: {
createdAt?: number;
privateKey?: string;
publicKey?: string;
};
where?: Array<{
connector?: "AND" | "OR";
field: "publicKey" | "privateKey" | "createdAt" | "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
};
onUpdateHandle?: string;
paginationOpts: {
cursor: string | null;
endCursor?: string | null;
id?: number;
maximumBytesRead?: number;
maximumRowsRead?: number;
numItems: number;
};
},
any
>;
updateOne: FunctionReference<
"mutation",
"public",
{
input:
| {
model: "user";
update: {
createdAt?: number;
email?: string;
emailVerified?: boolean;
image?: null | string;
name?: string;
updatedAt?: number;
userId?: null | string;
};
where?: Array<{
connector?: "AND" | "OR";
field:
| "name"
| "email"
| "emailVerified"
| "image"
| "createdAt"
| "updatedAt"
| "userId"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "session";
update: {
createdAt?: number;
expiresAt?: number;
ipAddress?: null | string;
token?: string;
updatedAt?: number;
userAgent?: null | string;
userId?: string;
};
where?: Array<{
connector?: "AND" | "OR";
field:
| "expiresAt"
| "token"
| "createdAt"
| "updatedAt"
| "ipAddress"
| "userAgent"
| "userId"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "account";
update: {
accessToken?: null | string;
accessTokenExpiresAt?: null | number;
accountId?: string;
createdAt?: number;
idToken?: null | string;
password?: null | string;
providerId?: string;
refreshToken?: null | string;
refreshTokenExpiresAt?: null | number;
scope?: null | string;
updatedAt?: number;
userId?: string;
};
where?: Array<{
connector?: "AND" | "OR";
field:
| "accountId"
| "providerId"
| "userId"
| "accessToken"
| "refreshToken"
| "idToken"
| "accessTokenExpiresAt"
| "refreshTokenExpiresAt"
| "scope"
| "password"
| "createdAt"
| "updatedAt"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "verification";
update: {
createdAt?: number;
expiresAt?: number;
identifier?: string;
updatedAt?: number;
value?: string;
};
where?: Array<{
connector?: "AND" | "OR";
field:
| "identifier"
| "value"
| "expiresAt"
| "createdAt"
| "updatedAt"
| "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
}
| {
model: "jwks";
update: {
createdAt?: number;
privateKey?: string;
publicKey?: string;
};
where?: Array<{
connector?: "AND" | "OR";
field: "publicKey" | "privateKey" | "createdAt" | "id";
operator?:
| "lt"
| "lte"
| "gt"
| "gte"
| "eq"
| "in"
| "ne"
| "contains"
| "starts_with"
| "ends_with";
value:
| string
| number
| boolean
| Array<string>
| Array<number>
| null;
}>;
};
onUpdateHandle?: string;
},
any
>;
};
};
// For now fullApiWithMounts is only fullApi which provides
// jump-to-definition in component client code.
// Use Mounts for the same type without the inference.
declare const fullApiWithMounts: typeof fullApi;
export declare const api: FilterApi<
typeof fullApiWithMounts,
FunctionReference<any, "public">
>;
export declare const internal: FilterApi<
typeof fullApiWithMounts,
FunctionReference<any, "internal">
>;
export declare const components: {};

View File

@@ -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();

View File

@@ -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<DataModel>;
/**
* The type of a document stored in Convex.
*
* @typeParam TableName - A string literal type of the table name (like "users").
*/
export type Doc<TableName extends TableNames> = 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(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<TableName extends TableNames | SystemTableNames> =
GenericId<TableName>;
/**
* 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<typeof schema>;

View File

@@ -0,0 +1,149 @@
/* 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,
AnyComponents,
HttpActionBuilder,
MutationBuilder,
QueryBuilder,
GenericActionCtx,
GenericMutationCtx,
GenericQueryCtx,
GenericDatabaseReader,
GenericDatabaseWriter,
FunctionReference,
} from "convex/server";
import type { DataModel } from "./dataModel.js";
type GenericCtx =
| GenericActionCtx<DataModel>
| GenericMutationCtx<DataModel>
| GenericQueryCtx<DataModel>;
/**
* 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<DataModel, "public">;
/**
* 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<DataModel, "internal">;
/**
* 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<DataModel, "public">;
/**
* 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<DataModel, "internal">;
/**
* 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<DataModel, "public">;
/**
* 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<DataModel, "internal">;
/**
* Define an HTTP action.
*
* This 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 action in `convex/http.js`.
*
* @param func - The function. It receives an {@link ActionCtx} as its first argument.
* @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<DataModel>;
/**
* 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<DataModel>;
/**
* 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<DataModel>;
/**
* 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<DataModel>;
/**
* 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<DataModel>;

View File

@@ -0,0 +1,90 @@
/* 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,
componentsGeneric,
} 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 a Convex HTTP action.
*
* @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object
* as its second.
* @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`.
*/
export const httpAction = httpActionGeneric;

View File

@@ -0,0 +1,13 @@
import { createApi } from "@convex-dev/better-auth";
import schema from "./schema";
import { createAuth } from "../auth";
export const {
create,
findOne,
findMany,
updateOne,
updateMany,
deleteOne,
deleteMany,
} = createApi(schema, createAuth);

View File

@@ -0,0 +1,5 @@
import { createAuth } from '../auth'
import { getStaticAuth } from '@convex-dev/better-auth'
// Export a static instance for Better Auth schema generation
export const auth = getStaticAuth(createAuth)

View File

@@ -0,0 +1,5 @@
import { defineComponent } from "convex/server";
const component = defineComponent("betterAuth");
export default component;

View File

@@ -0,0 +1,70 @@
// This file is auto-generated. Do not edit this file manually.
// To regenerate the schema, run:
// `npx @better-auth/cli generate --output undefined -y`
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
export const tables = {
user: defineTable({
name: v.string(),
email: v.string(),
emailVerified: v.boolean(),
image: v.optional(v.union(v.null(), v.string())),
createdAt: v.number(),
updatedAt: v.number(),
userId: v.optional(v.union(v.null(), v.string())),
})
.index("email_name", ["email","name"])
.index("name", ["name"])
.index("userId", ["userId"]),
session: defineTable({
expiresAt: v.number(),
token: v.string(),
createdAt: v.number(),
updatedAt: v.number(),
ipAddress: v.optional(v.union(v.null(), v.string())),
userAgent: v.optional(v.union(v.null(), v.string())),
userId: v.string(),
})
.index("expiresAt", ["expiresAt"])
.index("expiresAt_userId", ["expiresAt","userId"])
.index("token", ["token"])
.index("userId", ["userId"]),
account: defineTable({
accountId: v.string(),
providerId: v.string(),
userId: v.string(),
accessToken: v.optional(v.union(v.null(), v.string())),
refreshToken: v.optional(v.union(v.null(), v.string())),
idToken: v.optional(v.union(v.null(), v.string())),
accessTokenExpiresAt: v.optional(v.union(v.null(), v.number())),
refreshTokenExpiresAt: v.optional(v.union(v.null(), v.number())),
scope: v.optional(v.union(v.null(), v.string())),
password: v.optional(v.union(v.null(), v.string())),
createdAt: v.number(),
updatedAt: v.number(),
})
.index("accountId", ["accountId"])
.index("accountId_providerId", ["accountId","providerId"])
.index("providerId_userId", ["providerId","userId"])
.index("userId", ["userId"]),
verification: defineTable({
identifier: v.string(),
value: v.string(),
expiresAt: v.number(),
createdAt: v.number(),
updatedAt: v.number(),
})
.index("expiresAt", ["expiresAt"])
.index("identifier", ["identifier"]),
jwks: defineTable({
publicKey: v.string(),
privateKey: v.string(),
createdAt: v.number(),
}),
};
const schema = defineSchema(tables);
export default schema;

View File

@@ -1,5 +1,5 @@
import betterAuth from "@convex-dev/better-auth/convex.config"
import { defineApp } from "convex/server"
import betterAuth from "./betterauth/convex.config"
const app = defineApp()
app.use(betterAuth)

View File

@@ -0,0 +1,33 @@
/* eslint-disable */
/**
* Generated `api` utility.
*
* THIS CODE IS AUTOMATICALLY GENERATED.
*
* To regenerate, run `npx convex dev`.
* @module
*/
import type {
ApiFromModules,
FilterApi,
FunctionReference,
} from "convex/server";
/**
* A utility for referencing Convex functions in your app's API.
*
* Usage:
* ```js
* const myFunctionReference = api.myModule.myFunction;
* ```
*/
declare const fullApi: ApiFromModules<{}>;
export declare const api: FilterApi<
typeof fullApi,
FunctionReference<any, "public">
>;
export declare const internal: FilterApi<
typeof fullApi,
FunctionReference<any, "internal">
>;

View File

@@ -0,0 +1,22 @@
/* eslint-disable */
/**
* Generated `api` utility.
*
* THIS CODE IS AUTOMATICALLY GENERATED.
*
* To regenerate, run `npx convex dev`.
* @module
*/
import { anyApi } 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;

View File

@@ -0,0 +1,58 @@
/* eslint-disable */
/**
* Generated data model types.
*
* THIS CODE IS AUTOMATICALLY GENERATED.
*
* To regenerate, run `npx convex dev`.
* @module
*/
import { AnyDataModel } from "convex/server";
import type { GenericId } from "convex/values";
/**
* No `schema.ts` file found!
*
* This generated code has permissive types like `Doc = any` because
* Convex doesn't know your schema. If you'd like more type safety, see
* https://docs.convex.dev/using/schemas for instructions on how to add a
* schema file.
*
* After you change a schema, rerun codegen with `npx convex dev`.
*/
/**
* The names of all of your Convex tables.
*/
export type TableNames = string;
/**
* The type of a document stored in Convex.
*/
export type Doc = any;
/**
* 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(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.
*/
export type Id<TableName extends TableNames = TableNames> =
GenericId<TableName>;
/**
* 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 = AnyDataModel;

View File

@@ -0,0 +1,142 @@
/* 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<DataModel, "public">;
/**
* 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<DataModel, "internal">;
/**
* 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<DataModel, "public">;
/**
* 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<DataModel, "internal">;
/**
* 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<DataModel, "public">;
/**
* 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<DataModel, "internal">;
/**
* Define an HTTP action.
*
* This 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 action in `convex/http.js`.
*
* @param func - The function. It receives an {@link ActionCtx} as its first argument.
* @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<DataModel>;
/**
* 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<DataModel>;
/**
* 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<DataModel>;
/**
* 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<DataModel>;
/**
* 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<DataModel>;

View File

@@ -0,0 +1,89 @@
/* 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 a Convex HTTP action.
*
* @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object
* as its second.
* @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`.
*/
export const httpAction = httpActionGeneric;